pax_global_header00006660000000000000000000000064136447562020014523gustar00rootroot0000000000000052 comment=0657978769355f0238545c2db6f3eae5b6479dce Carla-2.1/000077500000000000000000000000001364475620200124075ustar00rootroot00000000000000Carla-2.1/.gitignore000066400000000000000000000054401364475620200144020ustar00rootroot00000000000000# Hidden files .directory .fuse-* .*.kate-swp .libmagic-tmp .libmagic-tmp.bc .kdev_include_paths .kdev4/ .DS_Store # Temp files *~ *.bak *.swp *.swo # Binary files *.7z *.bz2 *.a *.o *.dll *.dll.def *.dylib *.exe *.msi *.so *.vst *.vst3 # Binary dir bin/ansi-pedantic-test_* bin/carla bin/carla.lv2/carla-bridge-* bin/carla-database bin/carla-settings bin/jack/ bin/resources/ bin/styles/ build/ # Project files *.carxp *.carxs *.pro.user # C++ files *.moc moc_*.cpp ui_*.h resources.*.cpp qrc_resources.cpp # Python files *.pyc # Qt files *_rc.cpp *_rc.py ui_*.hpp ui_*.py # Misc files *.aria2 *.deb *.gz *.meta4 *.tar *.ttl *.xz *.zip # Binaries carla-bridge-qtcreator carla-bridge-arm32 carla-bridge-native carla-bridge-posix32 carla-bridge-posix64 carla-bridge-lv2-cocoa carla-bridge-lv2-external carla-bridge-lv2-gtk2 carla-bridge-lv2-gtk3 carla-bridge-lv2-qt4 carla-bridge-lv2-qt5 carla-bridge-lv2-x11 carla-bridge-vst2-carbon carla-bridge-vst2-cocoa carla-bridge-vst2-x11 carla-discovery-qtcreator carla-discovery-native carla-discovery-arm32 carla-discovery-posix32 carla-discovery-posix64 carla-lv2-export carla-native-plugin carla-rest-server zynaddsubfx-ui stoat-output.png source/tests/ansi-pedantic-test_* source/tests/CachedPlugins source/tests/CarlaRingBuffer source/tests/CarlaPipeUtils source/tests/CarlaString source/tests/CarlaUtils1 source/tests/CarlaUtils2 source/tests/CarlaUtils3 source/tests/CarlaUtils4 source/tests/Exceptions source/tests/Print source/tests/RDF source/tests/EngineEvents source/tests/PipeServer source/tests/RtLinkedList source/tests/RtLinkedListGnu # Docs doc/CarlaBackend/ doc/CarlaBridge/ doc/DISTRHO/ # CX-Freeze builds source/dist/ # QtCreator builds *build-*Debug/ *build-*Release/ # python files in plugin resources dir bin/resources/*.py bin/resources/patchcanvas bin/resources/widgets source/native-plugins/resources/*.py # Other source/frontend/carla_config.py source/includes/asio/ source/includes/rewire/ source/includes/vst2 source/includes/vst3 source/includes/config.h source/modules/dgl/src/Resources.cpp source/modules/dgl/src/Resources.hpp source/modules/dgl/src/resources/ source/modules/dgl/src/sofd/ source/modules/distrho/src/DistrhoPluginJack.cpp source/modules/distrho/src/DistrhoPluginLADSPA+DSSI.cpp source/modules/distrho/src/DistrhoPluginLV2.cpp source/modules/distrho/src/DistrhoPluginLV2export.cpp source/modules/distrho/src/DistrhoPluginVST.cpp source/modules/distrho/src/DistrhoUIDSSI.cpp source/modules/distrho/src/DistrhoUILV2.cpp data/linux/*.gz data/linux/*.tgz data/linux/*.xz data/linux/*.*/ data/macos/*.gz data/macos/*.tgz data/macos/*-svn/ data/macos/*.*/ data/macos/Carla/ data/windows/Carla data/windows/CarlaControl data/windows/Carla-*-win32/ data/windows/Carla-*-win64/ data/windows/Carla.lv2/ data/windows/Carla_* data/windows/python/ Carla-2.1/.gitmodules000066400000000000000000000002031364475620200145570ustar00rootroot00000000000000[submodule "source/native-plugins/external"] path = source/native-plugins/external url = https://github.com/falkTX/Carla-Plugins Carla-2.1/.travis.yml000066400000000000000000000020361364475620200145210ustar00rootroot00000000000000language: - cpp sudo: required dist: trusty matrix: include: # linux with default, builds native and bridges - os: linux compiler: gcc env: - TARGET="linux" # linux with macOS cross-compilation - os: linux compiler: gcc env: - TARGET="macos" # linux with win32 cross-compilation - os: linux compiler: gcc env: - TARGET="win32" # linux with win64 cross-compilation - os: linux compiler: gcc env: - TARGET="win64" # linux with gcc 8, strict build - os: linux compiler: gcc env: - TARGET="linux-strict" # linux with gcc 8, strict build, using juce - os: linux compiler: gcc env: - TARGET="linux-juce-strict" before_install: - sh ${TRAVIS_BUILD_DIR}/.travis/before_install.sh install: - sh ${TRAVIS_BUILD_DIR}/.travis/install.sh script: - sh ${TRAVIS_BUILD_DIR}/.travis/script-${TARGET}.sh notifications: email: false irc: "ircs://chat.freenode.net:7070/#kxstudio" Carla-2.1/.travis/000077500000000000000000000000001364475620200137755ustar00rootroot00000000000000Carla-2.1/.travis/before_install.sh000066400000000000000000000006401364475620200173210ustar00rootroot00000000000000#!/bin/bash set -e sudo add-apt-repository -y ppa:kxstudio-debian/kxstudio sudo add-apt-repository -y ppa:kxstudio-debian/mingw sudo add-apt-repository -y ppa:kxstudio-debian/toolchain if [ "${TARGET}" = "linux-strict" ] || [ "${TARGET}" = "linux-juce-strict" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test fi sudo apt-get update -qq sudo apt-get install kxstudio-repos sudo apt-get update -qq Carla-2.1/.travis/install.sh000077500000000000000000000063161364475620200160100ustar00rootroot00000000000000#!/bin/bash set -e if [ "${TARGET}" = "linux" ]; then sudo apt-get install -y \ g++-multilib \ pkg-config \ pyqt5-dev-tools \ python3-pyqt5.qtsvg \ python3-rdflib \ libgtk2.0-dev \ libgtk-3-dev \ libqt4-dev \ qtbase5-dev \ libasound2-dev \ libpulse-dev \ libmagic-dev \ libgl1-mesa-dev \ libx11-dev \ libx11-6:i386 \ liblo-static \ fluidsynth-static \ mingw32-x-gcc \ mingw32-x-pkgconfig \ mingw64-x-gcc \ mingw64-x-pkgconfig \ wine-rt-dev # Fix for 32bit bridge link sudo ln -s /usr/lib/i386-linux-gnu/libX11.so.6 /usr/lib/i386-linux-gnu/libX11.so elif [ "${TARGET}" = "linux-strict" ]; then sudo apt-get install -y \ g++-8 \ g++-8-multilib \ pkg-config \ pyqt5-dev-tools \ python3-pyqt5.qtsvg \ python3-rdflib \ libgtk2.0-dev \ libgtk-3-dev \ libqt4-dev \ qtbase5-dev \ libasound2-dev \ libpulse-dev \ libmagic-dev \ libgl1-mesa-dev \ libx11-dev \ libx11-6:i386 \ liblo-static \ fluidsynth-static # Fix for 32bit bridge link sudo ln -s /usr/lib/i386-linux-gnu/libX11.so.6 /usr/lib/i386-linux-gnu/libX11.so elif [ "${TARGET}" = "linux-juce-strict" ]; then sudo apt-get install -y \ g++-8 \ pkg-config \ pyqt5-dev-tools \ python3-pyqt5.qtsvg \ python3-rdflib \ libgtk2.0-dev \ libgtk-3-dev \ libqt4-dev \ qtbase5-dev \ libasound2-dev \ libjack-jackd2-dev \ libfreetype6-dev \ libmagic-dev \ libgl1-mesa-dev \ libx11-dev \ libxext-dev \ liblo-static \ fluidsynth-static elif [ "${TARGET}" = "macos" ]; then sudo apt-get install -y \ pkg-config \ apple-x86-setup # mkdir /tmp/osx-macports-pkgs # cd /tmp/osx-macports-pkgs # wget https://launchpad.net/~kxstudio-team/+archive/ubuntu/builds/+files/apple-macports-flac_1.2.1-1_all.deb # wget https://launchpad.net/~kxstudio-team/+archive/ubuntu/builds/+files/apple-macports-libiconv_1.14-0_all.deb # wget https://launchpad.net/~kxstudio-team/+archive/ubuntu/builds/+files/apple-macports-liblo_0.26-1_all.deb # wget https://launchpad.net/~kxstudio-team/+archive/ubuntu/builds/+files/apple-macports-libogg_1.3.0-1_all.deb # wget https://launchpad.net/~kxstudio-team/+archive/ubuntu/builds/+files/apple-macports-libsndfile_1.0.25-0_all.deb # wget https://launchpad.net/~kxstudio-team/+archive/ubuntu/builds/+files/apple-macports-libvorbis_1.3.3-0_all.deb # cd ~ # rm -r /tmp/osx-macports-pkgs elif [ "${TARGET}" = "win32" ]; then sudo apt-get install -y \ mingw32-x-gcc \ mingw32-x-pkgconfig elif [ "${TARGET}" = "win64" ]; then sudo apt-get install -y \ mingw32-x-gcc \ mingw32-x-pkgconfig \ mingw64-x-gcc \ mingw64-x-pkgconfig fi # mingw32-x-fluidsynth # mingw32-x-fftw # mingw32-x-liblo # mingw32-x-mxml # mingw32-x-zlib # mingw64-x-fluidsynth # mingw64-x-fftw # mingw64-x-liblo # mingw64-x-mxml # mingw64-x-zlib Carla-2.1/.travis/script-linux-juce-strict.sh000077500000000000000000000006211364475620200212260ustar00rootroot00000000000000#!/bin/bash set -e # Preparation export CC=gcc-8 export CXX=g++-8 export PKG_CONFIG_PATH=/opt/kxstudio/lib/pkgconfig:${PKG_CONFIG_PATH} unset CFLAGS unset CXXFLAGS unset LDFLAGS # Start clean make distclean >/dev/null # Print available features make features # Build things that we skip strict tests for make 3rd frontend USING_JUCE=true # Build native stuff make TESTBUILD=true USING_JUCE=true Carla-2.1/.travis/script-linux-strict.sh000077500000000000000000000007111364475620200203020ustar00rootroot00000000000000#!/bin/bash set -e # Preparation export CC=gcc-8 export CXX=g++-8 export PKG_CONFIG_PATH=/opt/kxstudio/lib/pkgconfig:${PKG_CONFIG_PATH} unset CFLAGS unset CXXFLAGS unset LDFLAGS # Start clean make distclean >/dev/null # Print available features make features # Build things that we skip strict tests for make 3rd frontend make -C source/modules/water posix32 # Build native stuff make TESTBUILD=true # Build 32bit bridges make TESTBUILD=true posix32 Carla-2.1/.travis/script-linux.sh000077500000000000000000000012561364475620200170010ustar00rootroot00000000000000#!/bin/bash set -e # Preparation _FLAGS="-Werror" export CFLAGS="${_FLAGS}" export CXXFLAGS="${_FLAGS}" export LDFLAGS="-L/opt/kxstudio/lib" export PATH=/opt/kxstudio/bin:${PATH} export PKG_CONFIG_PATH=/opt/kxstudio/lib/pkgconfig:${PKG_CONFIG_PATH} # Start clean make distclean >/dev/null # Print available features make features # Build native stuff make all posix32 posix64 # Build wine bridges make wine32 wine64 # Build windows binaries for bridges env PATH=/opt/mingw32/bin:${PATH} make win32 USING_JUCE=false CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ env PATH=/opt/mingw64/bin:${PATH} make win64 USING_JUCE=false CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ Carla-2.1/.travis/script-macos.sh000077500000000000000000000005731364475620200167450ustar00rootroot00000000000000#!/bin/bash set -e # Preparation _FLAGS="-Wno-attributes -Wno-deprecated-declarations -Werror -DBUILDING_FOR_CI" export CFLAGS="${_FLAGS}" export CXXFLAGS="${_FLAGS}" export MACOS_OLD=true export CROSS_COMPILING=true . /usr/bin/apple-cross-setup.env # Start clean make distclean >/dev/null # Print available features make features # Build native stuff make USING_JUCE=false Carla-2.1/.travis/script-win32.sh000077500000000000000000000011051364475620200165750ustar00rootroot00000000000000#!/bin/bash set -e # Preparation _FLAGS="-DFLUIDSYNTH_NOT_A_DLL -DPTW32_STATIC_LIB -Werror -DBUILDING_FOR_CI" _PREFIX=i686-w64-mingw32 export AR=${_PREFIX}-ar export CC=${_PREFIX}-gcc export CXX=${_PREFIX}-g++ export CFLAGS="${_FLAGS}" export CXXFLAGS="${_FLAGS}" export PATH=/opt/mingw32/${_PREFIX}/bin:/opt/mingw32/bin:${PATH} export PKG_CONFIG_PATH=/opt/mingw32/lib/pkgconfig:${PKG_CONFIG_PATH} export CROSS_COMPILING=true # Start clean make distclean >/dev/null # Print available features make features # Build native stuff make BUILDING_FOR_WINDOWS=true USING_JUCE=false Carla-2.1/.travis/script-win64.sh000077500000000000000000000011071364475620200166040ustar00rootroot00000000000000#!/bin/bash set -e # Preparation _FLAGS="-DFLUIDSYNTH_NOT_A_DLL -DPTW32_STATIC_LIB -Werror -DBUILDING_FOR_CI" _PREFIX=x86_64-w64-mingw32 export AR=${_PREFIX}-ar export CC=${_PREFIX}-gcc export CXX=${_PREFIX}-g++ export CFLAGS="${_FLAGS}" export CXXFLAGS="${_FLAGS}" export PATH=/opt/mingw64/${_PREFIX}/bin:/opt/mingw64/bin:${PATH} export PKG_CONFIG_PATH=/opt/mingw64/lib/pkgconfig:${PKG_CONFIG_PATH} export CROSS_COMPILING=true # Start clean make distclean >/dev/null # Print available features make features # Build native stuff make BUILDING_FOR_WINDOWS=true USING_JUCE=false Carla-2.1/INSTALL.md000066400000000000000000000052741364475620200140470ustar00rootroot00000000000000# INSTALL for Carla To install Carla, simply run as usual: ``` $ make $ [sudo] make install ``` You can run it without installing, by using instead: ``` $ make $ ./source/frontend/carla ``` Packagers can make use of the `PREFIX` and `DESTDIR` variable during install, like this: ``` $ make install PREFIX=/usr DESTDIR=./test-dir ``` ## BUILD DEPENDENCIES There are no required build dependencies. The default build is probably not what you want though. If you want the frontend (which is likely), you will need PyQt5 (python3 version). You likely will also want: - libmagic/file (for auto-detection of binary types, needed for plugin-bridges) - liblo (for OSC support, also a requirement for DSSI UIs) Optional for extra Linux-only engine features: - ALSA - PulseAudio - X11 (LV2/VST X11 UI support) Optional for extended LV2 UIs support: (Linux only) - Gtk2 - Gtk3 - Qt4 - Qt5 Optional for extra samplers support: - FluidSynth (SF2/3) Optional for extra LADSPA plugin information: - python3-rdflib You can use: ``` $ make features ``` To find out which dependencies are missing. Under Debian based systems, you can use this command to install everything: ``` sudo apt install python3-pyqt5.qtsvg python3-rdflib pyqt5-dev-tools \ libmagic-dev liblo-dev libasound2-dev libpulse-dev libx11-dev \ libgtk2.0-dev libgtk-3-dev libqt4-dev qtbase5-dev libfluidsynth-dev ``` Under Fedora, you can use the following command instead: ``` sudo dnf install python3-qt5-devel python3-rdflib \ file-devel liblo-devel alsa-lib-devel pulseaudio-libs-devel libX11-devel gtk2-devel gtk3-devel qt4-devel qt5-devel fluidsynth-devel libsndfile-devel ``` ## BUILD BRIDGES (Experimental) Carla can make use of plugin bridges to load additional plugin types. ### 32bit plugins on 64bit systems Simply run `make posix32` after a regular Carla build, and install or run Carla locally.
This feature requires a compiler capable of building 32bit binaries. ### JACK Applications inside Carla This is built by default on Linux systems.
Requires LD_PRELOAD support by the OS and the GCC compiler.
Does not work with clang. (if you discover why, please let me know!) ### Windows plugins (via Wine) Requires a mingw compiler, and winegcc. First, we build the Windows bridges using mingw, like this: (adjust as needed) ``` make win32 CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ make win64 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ ``` To finalize, we build the wine<->native bridges using winegcc: ``` make wine32 make wine64 ``` Then install or run Carla locally as usual.
Don't forget to enable experimental options and plugin bridges in Carla settings to actually be able to use them. Carla-2.1/Makefile000066400000000000000000000742351364475620200140620ustar00rootroot00000000000000#!/usr/bin/make -f # Makefile for Carla # # ------------------ # # Created by falkTX # CWD=source include source/Makefile.mk # --------------------------------------------------------------------------------------------------------------------- PREFIX := /usr/local BINDIR := $(PREFIX)/bin LIBDIR := $(PREFIX)/lib DATADIR := $(PREFIX)/share INCLUDEDIR := $(PREFIX)/include DESTDIR := ifeq ($(DEBUG),true) MODULEDIR := $(CURDIR)/build/modules/Debug else MODULEDIR := $(CURDIR)/build/modules/Release endif # --------------------------------------------------------------------------------------------------------------------- all: backend discovery bridges-plugin bridges-ui frontend interposer libjack plugin theme # --------------------------------------------------------------------------------------------------------------------- # Binaries (native) ALL_LIBS += $(MODULEDIR)/carla_engine.a ALL_LIBS += $(MODULEDIR)/carla_engine_plugin.a ALL_LIBS += $(MODULEDIR)/carla_plugin.a ALL_LIBS += $(MODULEDIR)/jackbridge.a ALL_LIBS += $(MODULEDIR)/native-plugins.a ALL_LIBS += $(MODULEDIR)/rtmempool.a 3RD_LIBS += $(MODULEDIR)/audio_decoder.a 3RD_LIBS += $(MODULEDIR)/lilv.a 3RD_LIBS += $(MODULEDIR)/sfzero.a 3RD_LIBS += $(MODULEDIR)/water.a ifeq ($(HAVE_DGL),true) 3RD_LIBS += $(MODULEDIR)/dgl.a endif ifeq ($(HAVE_HYLIA),true) 3RD_LIBS += $(MODULEDIR)/hylia.a endif ifeq ($(HAVE_QT4),true) 3RD_LIBS += $(MODULEDIR)/theme.qt4.a endif ifeq ($(HAVE_QT5),true) 3RD_LIBS += $(MODULEDIR)/theme.qt5.a endif ifeq ($(USING_JUCE),true) 3RD_LIBS += $(MODULEDIR)/juce_audio_basics.a 3RD_LIBS += $(MODULEDIR)/juce_audio_devices.a 3RD_LIBS += $(MODULEDIR)/juce_audio_processors.a 3RD_LIBS += $(MODULEDIR)/juce_core.a 3RD_LIBS += $(MODULEDIR)/juce_data_structures.a 3RD_LIBS += $(MODULEDIR)/juce_events.a 3RD_LIBS += $(MODULEDIR)/juce_graphics.a 3RD_LIBS += $(MODULEDIR)/juce_gui_basics.a ifeq ($(MACOS),true) 3RD_LIBS += $(MODULEDIR)/juce_gui_extra.a endif else 3RD_LIBS += $(MODULEDIR)/rtaudio.a 3RD_LIBS += $(MODULEDIR)/rtmidi.a endif ALL_LIBS += $(3RD_LIBS) 3rd: $(3RD_LIBS) @$(MAKE) -C source/theme ifeq ($(HAVE_QT4),true) @$(MAKE) -C source/bridges-ui ui_lv2-qt4 endif libs: $(ALL_LIBS) $(MODULEDIR)/carla_engine.a: .FORCE @$(MAKE) -C source/backend/engine $(MODULEDIR)/carla_engine_plugin.a: $(MODULEDIR)/carla_engine.a @$(MAKE) -C source/backend/engine $(MODULEDIR)/carla_plugin.a: .FORCE @$(MAKE) -C source/backend/plugin $(MODULEDIR)/jackbridge.a: .FORCE @$(MAKE) -C source/jackbridge $(MODULEDIR)/jackbridge.%.a: .FORCE @$(MAKE) -C source/jackbridge $* $(MODULEDIR)/native-plugins.a: .FORCE @$(MAKE) -C source/native-plugins $(MODULEDIR)/theme.qt4.a: .FORCE @$(MAKE) -C source/theme qt4 $(MODULEDIR)/theme.qt5.a: .FORCE @$(MAKE) -C source/theme qt5 $(MODULEDIR)/%.arm32.a: .FORCE ifneq ($(WIN32),true) @$(MAKE) -C source/modules/$* arm32 else $(error Trying to build ARM binaries with a Windows toolchain, this cannot work) endif $(MODULEDIR)/%.posix32.a: .FORCE ifneq ($(WIN32),true) @$(MAKE) -C source/modules/$* posix32 else $(error Trying to build POSIX binaries with a Windows toolchain, this cannot work) endif $(MODULEDIR)/%.posix64.a: .FORCE ifneq ($(WIN32),true) @$(MAKE) -C source/modules/$* posix64 else $(error Trying to build POSIX binaries with a Windows toolchain, this cannot work) endif $(MODULEDIR)/%.win32.a: .FORCE ifeq ($(WIN32),true) @$(MAKE) -C source/modules/$* win32 else $(error Trying to build Windows binaries with a regular toolchain, this cannot work) endif $(MODULEDIR)/%.win64.a: .FORCE ifeq ($(WIN32),true) @$(MAKE) -C source/modules/$* win64 else $(error Trying to build Windows binaries with a regular toolchain, this cannot work) endif $(MODULEDIR)/dgl.wine.a: .FORCE @$(MAKE) -C source/modules/dgl wine $(MODULEDIR)/water.files.a: .FORCE @$(MAKE) -C source/modules/water files $(MODULEDIR)/%.a: .FORCE @$(MAKE) -C source/modules/$* # --------------------------------------------------------------------------------------------------------------------- backend: libs @$(MAKE) -C source/backend bridges-plugin: libs @$(MAKE) -C source/bridges-plugin bridges-ui: libs @$(MAKE) -C source/bridges-ui discovery: libs @$(MAKE) -C source/discovery frontend: libs ifeq ($(HAVE_PYQT),true) @$(MAKE) -C source/frontend endif interposer: ifeq ($(LINUX),true) @$(MAKE) -C source/interposer endif libjack: libs @$(MAKE) -C source/libjack lv2-bundles-dep: $(MODULEDIR)/audio_decoder.a $(MODULEDIR)/water.a @$(MAKE) -C source/native-plugins bundles lv2-bundles: lv2-bundles-dep @$(MAKE) -C source/plugin bundles plugin: backend bridges-plugin bridges-ui discovery @$(MAKE) -C source/plugin ifeq ($(WIN32),true) plugin-wine: @$(MAKE) -C source/plugin wine else plugin-wine: $(MODULEDIR)/dgl.wine.a @$(MAKE) -C source/plugin wine endif rest: libs @$(MAKE) -C source/rest theme: libs @$(MAKE) -C source/theme # --------------------------------------------------------------------------------------------------------------------- # nuitka nuitka: bin/carla bin/carla-rack bin/carla-plugin bin/carla: python3 -m nuitka \ -j 4 \ --python-flag -O --warn-unusual-code --warn-implicit-exceptions \ --follow-imports \ -o ./$@ \ ./source/frontend/carla bin/carla-rack: python3 -m nuitka \ -j 8 \ --recurse-all \ --python-flag -O --warn-unusual-code --warn-implicit-exceptions \ --recurse-not-to=PyQt5 \ --file-reference-choice=runtime \ -o ./$@ \ ./source/frontend/carla bin/carla-plugin: python3 -m nuitka \ -j 8 \ --recurse-all \ --python-flag -O --warn-unusual-code --warn-implicit-exceptions \ --recurse-not-to=PyQt5 \ --file-reference-choice=runtime \ -o ./$@ \ ./source/native-plugins/resources/carla-plugin # --------------------------------------------------------------------------------------------------------------------- # Binaries (arm32) LIBS_ARM32 = $(MODULEDIR)/jackbridge.arm32.a LIBS_ARM32 += $(MODULEDIR)/lilv.arm32.a LIBS_ARM32 += $(MODULEDIR)/rtmempool.arm32.a LIBS_ARM32 += $(MODULEDIR)/water.arm32.a arm32: $(LIBS_ARM32) $(MAKE) -C source/bridges-plugin arm32 $(MAKE) -C source/discovery arm32 # --------------------------------------------------------------------------------------------------------------------- # Binaries (posix32) LIBS_POSIX32 = $(MODULEDIR)/jackbridge.posix32.a LIBS_POSIX32 += $(MODULEDIR)/lilv.posix32.a LIBS_POSIX32 += $(MODULEDIR)/rtmempool.posix32.a LIBS_POSIX32 += $(MODULEDIR)/water.posix32.a ifeq ($(USING_JUCE),true) LIBS_POSIX32 += $(MODULEDIR)/juce_audio_basics.posix32.a LIBS_POSIX32 += $(MODULEDIR)/juce_audio_processors.posix32.a LIBS_POSIX32 += $(MODULEDIR)/juce_data_structures.posix32.a LIBS_POSIX32 += $(MODULEDIR)/juce_core.posix32.a LIBS_POSIX32 += $(MODULEDIR)/juce_events.posix32.a ifeq ($(MACOS_OR_WIN32),true) LIBS_POSIX32 += $(MODULEDIR)/juce_graphics.posix32.a LIBS_POSIX32 += $(MODULEDIR)/juce_gui_basics.posix32.a endif ifeq ($(MACOS),true) LIBS_POSIX32 += $(MODULEDIR)/juce_gui_extra.posix32.a endif endif posix32: $(LIBS_POSIX32) $(MAKE) -C source/bridges-plugin posix32 $(MAKE) -C source/discovery posix32 # --------------------------------------------------------------------------------------------------------------------- # Binaries (posix64) LIBS_POSIX64 = $(MODULEDIR)/jackbridge.posix64.a LIBS_POSIX64 += $(MODULEDIR)/lilv.posix64.a LIBS_POSIX64 += $(MODULEDIR)/rtmempool.posix64.a LIBS_POSIX64 += $(MODULEDIR)/water.posix64.a ifeq ($(USING_JUCE),true) LIBS_POSIX64 += $(MODULEDIR)/juce_audio_basics.posix64.a LIBS_POSIX64 += $(MODULEDIR)/juce_audio_processors.posix64.a LIBS_POSIX64 += $(MODULEDIR)/juce_data_structures.posix64.a LIBS_POSIX64 += $(MODULEDIR)/juce_core.posix64.a LIBS_POSIX64 += $(MODULEDIR)/juce_events.posix64.a ifeq ($(MACOS_OR_WIN32),true) LIBS_POSIX64 += $(MODULEDIR)/juce_graphics.posix64.a LIBS_POSIX64 += $(MODULEDIR)/juce_gui_basics.posix64.a endif ifeq ($(MACOS),true) LIBS_POSIX64 += $(MODULEDIR)/juce_gui_extra.posix64.a endif endif posix64: $(LIBS_POSIX64) $(MAKE) -C source/bridges-plugin posix64 $(MAKE) -C source/discovery posix64 # --------------------------------------------------------------------------------------------------------------------- # Binaries (win32) ifeq ($(BUILDING_FOR_WINDOWS),true) LIBS_WIN32 = $(MODULEDIR)/jackbridge.win32.a else LIBS_WIN32 = $(MODULEDIR)/jackbridge.win32e.a endif LIBS_WIN32 += $(MODULEDIR)/lilv.win32.a LIBS_WIN32 += $(MODULEDIR)/rtmempool.win32.a LIBS_WIN32 += $(MODULEDIR)/water.win32.a ifeq ($(USING_JUCE),true) LIBS_WIN32 += $(MODULEDIR)/juce_audio_basics.win32.a LIBS_WIN32 += $(MODULEDIR)/juce_audio_processors.win32.a LIBS_WIN32 += $(MODULEDIR)/juce_data_structures.win32.a LIBS_WIN32 += $(MODULEDIR)/juce_core.win32.a LIBS_WIN32 += $(MODULEDIR)/juce_events.win32.a LIBS_WIN32 += $(MODULEDIR)/juce_graphics.win32.a LIBS_WIN32 += $(MODULEDIR)/juce_gui_basics.win32.a endif win32: $(LIBS_WIN32) $(MAKE) -C source/bridges-plugin win32 $(MAKE) -C source/discovery win32 # --------------------------------------------------------------------------------------------------------------------- # Binaries (win64) ifeq ($(BUILDING_FOR_WINDOWS),true) LIBS_WIN64 = $(MODULEDIR)/jackbridge.win64.a else LIBS_WIN64 = $(MODULEDIR)/jackbridge.win64e.a endif LIBS_WIN64 += $(MODULEDIR)/lilv.win64.a LIBS_WIN64 += $(MODULEDIR)/rtmempool.win64.a LIBS_WIN64 += $(MODULEDIR)/water.win64.a ifeq ($(USING_JUCE),true) LIBS_WIN64 += $(MODULEDIR)/juce_audio_basics.win64.a LIBS_WIN64 += $(MODULEDIR)/juce_audio_processors.win64.a LIBS_WIN64 += $(MODULEDIR)/juce_data_structures.win64.a LIBS_WIN64 += $(MODULEDIR)/juce_core.win64.a LIBS_WIN64 += $(MODULEDIR)/juce_events.win64.a LIBS_WIN64 += $(MODULEDIR)/juce_graphics.win64.a LIBS_WIN64 += $(MODULEDIR)/juce_gui_basics.win64.a endif win64: $(LIBS_WIN64) $(MAKE) -C source/bridges-plugin win64 $(MAKE) -C source/discovery win64 # --------------------------------------------------------------------------------------------------------------------- # Binaries (wine) wine32: $(MAKE) -C source/jackbridge wine32 cp -f $(MODULEDIR)/jackbridge-wine32.dll.so $(CURDIR)/bin/jackbridge-wine32.dll wine64: $(MAKE) -C source/jackbridge wine64 cp -f $(MODULEDIR)/jackbridge-wine64.dll.so $(CURDIR)/bin/jackbridge-wine64.dll # --------------------------------------------------------------------------------------------------------------------- clean: $(MAKE) clean -C source/backend $(MAKE) clean -C source/bridges-plugin $(MAKE) clean -C source/bridges-ui $(MAKE) clean -C source/discovery $(MAKE) clean -C source/frontend $(MAKE) clean -C source/interposer $(MAKE) clean -C source/libjack $(MAKE) clean -C source/modules $(MAKE) clean -C source/native-plugins $(MAKE) clean -C source/plugin $(MAKE) clean -C source/tests $(MAKE) clean -C source/theme rm -f *~ source/*~ distclean: clean rm -f bin/*.exe bin/*.dll bin/*.dylib bin/*.so rm -rf build build-lv2 cpp: $(MAKE) CPPMODE=true debug: $(MAKE) DEBUG=true doxygen: $(MAKE) doxygen -C source/backend tests: $(MAKE) -C source/tests stoat: stoat --recursive ./build/ --suppression ./data/stoat-supression.txt --whitelist ./data/stoat-whitelist.txt --graph-view ./data/stoat-callgraph.png # stoat --recursive ./build/ \ # --suppression ./data/stoat-supression.txt \ # --whitelist ./data/stoat-whitelist.txt \ # --graph-view ./data/stoat-callgraph.png # --------------------------------------------------------------------------------------------------------------------- install_main: # Create directories install -d $(DESTDIR)$(BINDIR) ifeq ($(LINUX),true) install -d $(DESTDIR)$(LIBDIR)/carla/jack else install -d $(DESTDIR)$(LIBDIR)/carla endif install -d $(DESTDIR)$(LIBDIR)/pkgconfig install -d $(DESTDIR)$(INCLUDEDIR)/carla/includes ifeq ($(LINUX),true) ifeq ($(HAVE_JACK),true) ifeq ($(JACKBRIDGE_DIRECT),true) install -d $(DESTDIR)$(JACK_LIBDIR) endif endif endif ifeq ($(HAVE_PYQT),true) # Create directories (gui) install -d $(DESTDIR)$(LIBDIR)/carla/styles install -d $(DESTDIR)$(DATADIR)/applications install -d $(DESTDIR)$(DATADIR)/icons/hicolor/16x16/apps install -d $(DESTDIR)$(DATADIR)/icons/hicolor/48x48/apps install -d $(DESTDIR)$(DATADIR)/icons/hicolor/128x128/apps install -d $(DESTDIR)$(DATADIR)/icons/hicolor/256x256/apps install -d $(DESTDIR)$(DATADIR)/icons/hicolor/scalable/apps install -d $(DESTDIR)$(DATADIR)/mime/packages install -d $(DESTDIR)$(DATADIR)/carla/resources install -d $(DESTDIR)$(DATADIR)/carla/modgui install -d $(DESTDIR)$(DATADIR)/carla/patchcanvas install -d $(DESTDIR)$(DATADIR)/carla/widgets endif # ------------------------------------------------------------------------------------------------------------- # Install script files (non-gui) install -m 755 \ data/carla-single \ $(DESTDIR)$(BINDIR) # Adjust PREFIX value in script files (non-gui) sed $(SED_ARGS) 's?X-PREFIX-X?$(PREFIX)?' \ $(DESTDIR)$(BINDIR)/carla-single # Install backend libs install -m 644 \ bin/libcarla_*.* \ $(DESTDIR)$(LIBDIR)/carla # Install other binaries install -m 755 \ bin/*bridge-* \ bin/carla-discovery-* \ $(DESTDIR)$(LIBDIR)/carla ifeq ($(LINUX),true) ifeq ($(HAVE_JACK),true) ifeq ($(JACKBRIDGE_DIRECT),true) # Install internal jack client ln -sf \ $(LIBDIR)/carla/libcarla_standalone2.so \ $(DESTDIR)$(JACK_LIBDIR)/carla.so endif endif ifneq ($(JACKBRIDGE_DIRECT),true) # Install custom libjack install -m 755 \ bin/jack/libjack.so.0 \ $(DESTDIR)$(LIBDIR)/carla/jack endif endif # Install pkg-config files install -m 644 \ data/*.pc \ $(DESTDIR)$(LIBDIR)/pkgconfig # Adjust PREFIX, LIBDIR and INCLUDEDIR in pkg-config files sed $(SED_ARGS) 's?X-PREFIX-X?$(PREFIX)?' \ $(DESTDIR)$(LIBDIR)/pkgconfig/carla-native-plugin.pc \ $(DESTDIR)$(LIBDIR)/pkgconfig/carla-standalone.pc \ $(DESTDIR)$(LIBDIR)/pkgconfig/carla-utils.pc sed $(SED_ARGS) 's?X-LIBDIR-X?$(LIBDIR)?' \ $(DESTDIR)$(LIBDIR)/pkgconfig/carla-native-plugin.pc \ $(DESTDIR)$(LIBDIR)/pkgconfig/carla-standalone.pc \ $(DESTDIR)$(LIBDIR)/pkgconfig/carla-utils.pc sed $(SED_ARGS) 's?X-INCLUDEDIR-X?$(INCLUDEDIR)?' \ $(DESTDIR)$(LIBDIR)/pkgconfig/carla-native-plugin.pc \ $(DESTDIR)$(LIBDIR)/pkgconfig/carla-standalone.pc \ $(DESTDIR)$(LIBDIR)/pkgconfig/carla-utils.pc # Install headers install -m 644 \ source/backend/CarlaBackend.h \ source/backend/CarlaHost.h \ source/backend/CarlaUtils.h \ source/backend/CarlaEngine.hpp \ source/backend/CarlaPlugin.hpp \ source/includes/CarlaNative.h \ $(DESTDIR)$(INCLUDEDIR)/carla install -m 644 \ source/includes/CarlaDefines.h \ source/includes/CarlaMIDI.h \ source/includes/CarlaNative.h \ source/includes/CarlaNativePlugin.h \ $(DESTDIR)$(INCLUDEDIR)/carla/includes # ------------------------------------------------------------------------------------------------------------- ifeq ($(HAVE_PYQT),true) ifneq ($(CPPMODE),true) # Install script files (gui) install -m 755 \ data/carla \ data/carla-database \ data/carla-jack-multi \ data/carla-jack-single \ data/carla-patchbay \ data/carla-rack \ data/carla-settings \ $(DESTDIR)$(BINDIR) # Adjust PREFIX value in script files (gui) sed $(SED_ARGS) 's?X-PREFIX-X?$(PREFIX)?' \ $(DESTDIR)$(BINDIR)/carla \ $(DESTDIR)$(BINDIR)/carla-database \ $(DESTDIR)$(BINDIR)/carla-jack-multi \ $(DESTDIR)$(BINDIR)/carla-jack-single \ $(DESTDIR)$(BINDIR)/carla-patchbay \ $(DESTDIR)$(BINDIR)/carla-rack \ $(DESTDIR)$(BINDIR)/carla-settings ifeq ($(HAVE_LIBLO),true) install -m 755 \ data/carla-control \ $(DESTDIR)$(BINDIR) sed $(SED_ARGS) 's?X-PREFIX-X?$(PREFIX)?' \ $(DESTDIR)$(BINDIR)/carla-control endif # Install the real modgui bridge install -m 755 \ data/carla-bridge-lv2-modgui \ $(DESTDIR)$(LIBDIR)/carla sed $(SED_ARGS) 's?X-PREFIX-X?$(PREFIX)?' \ $(DESTDIR)$(LIBDIR)/carla/carla-bridge-lv2-modgui # Install frontend install -m 644 \ source/frontend/carla \ source/frontend/carla-control \ source/frontend/carla-jack-multi \ source/frontend/carla-jack-single \ source/frontend/carla-patchbay \ source/frontend/carla-rack \ source/frontend/*.py \ $(DESTDIR)$(DATADIR)/carla/ install -m 644 \ source/frontend/modgui/*.py \ $(DESTDIR)$(DATADIR)/carla/modgui/ install -m 644 \ source/frontend/patchcanvas/*.py \ $(DESTDIR)$(DATADIR)/carla/patchcanvas/ install -m 644 \ source/frontend/widgets/*.py \ $(DESTDIR)$(DATADIR)/carla/widgets/ # Adjust LIBDIR and DATADIR value in python code sed $(SED_ARGS) 's?X_LIBDIR_X = None?X_LIBDIR_X = "$(LIBDIR)"?' \ $(DESTDIR)$(DATADIR)/carla/carla_shared.py sed $(SED_ARGS) 's?X_DATADIR_X = None?X_DATADIR_X = "$(DATADIR)"?' \ $(DESTDIR)$(DATADIR)/carla/carla_shared.py # Install resources (gui) install -m 755 \ bin/resources/carla-plugin \ bin/resources/carla-plugin-patchbay \ bin/resources/*-ui \ $(DESTDIR)$(DATADIR)/carla/resources endif # CPPMODE ifeq ($(HAVE_THEME),true) # Install theme install -m 644 \ bin/styles/* \ $(DESTDIR)$(LIBDIR)/carla/styles endif # Install desktop files install -m 644 data/carla.desktop $(DESTDIR)$(DATADIR)/applications ifeq ($(HAVE_LIBLO),true) install -m 644 data/carla-control.desktop $(DESTDIR)$(DATADIR)/applications endif # Install mime package install -m 644 data/carla.xml $(DESTDIR)$(DATADIR)/mime/packages # Install icons, 16x16 install -m 644 resources/16x16/carla.png $(DESTDIR)$(DATADIR)/icons/hicolor/16x16/apps install -m 644 resources/16x16/carla-control.png $(DESTDIR)$(DATADIR)/icons/hicolor/16x16/apps # Install icons, 48x48 install -m 644 resources/48x48/carla.png $(DESTDIR)$(DATADIR)/icons/hicolor/48x48/apps install -m 644 resources/48x48/carla-control.png $(DESTDIR)$(DATADIR)/icons/hicolor/48x48/apps # Install icons, 128x128 install -m 644 resources/128x128/carla.png $(DESTDIR)$(DATADIR)/icons/hicolor/128x128/apps install -m 644 resources/128x128/carla-control.png $(DESTDIR)$(DATADIR)/icons/hicolor/128x128/apps # Install icons, 256x256 install -m 644 resources/256x256/carla.png $(DESTDIR)$(DATADIR)/icons/hicolor/256x256/apps install -m 644 resources/256x256/carla-control.png $(DESTDIR)$(DATADIR)/icons/hicolor/256x256/apps # Install icons, scalable install -m 644 resources/scalable/carla.svg $(DESTDIR)$(DATADIR)/icons/hicolor/scalable/apps install -m 644 resources/scalable/carla-control.svg $(DESTDIR)$(DATADIR)/icons/hicolor/scalable/apps # Install resources (re-use python files) $(LINK) ../modgui $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../patchcanvas $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../widgets $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../carla_app.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../carla_backend.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../carla_backend_qt.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../carla_control.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../carla_database.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../carla_host.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../carla_settings.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../carla_skin.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../carla_shared.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../carla_utils.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../carla_widgets.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../externalui.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../resources_rc.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_about.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_about_juce.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_add_jack.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_database.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_edit.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_host.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_parameter.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_plugin_calf.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_plugin_classic.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_plugin_compact.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_plugin_default.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_plugin_presets.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_refresh.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_settings.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_carla_settings_driver.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_inputdialog_value.py $(DESTDIR)$(DATADIR)/carla/resources $(LINK) ../ui_midipattern.py $(DESTDIR)$(DATADIR)/carla/resources endif # HAVE_PYQT # ------------------------------------------------------------------------------------------------------------- # Install lv2 plugin install -d $(DESTDIR)$(LIBDIR)/lv2/carla.lv2 install -m 644 \ bin/carla.lv2/carla.* \ bin/carla.lv2/*.ttl \ $(DESTDIR)$(LIBDIR)/lv2/carla.lv2 # Link binaries for lv2 plugin @for i in `find $(DESTDIR)$(LIBDIR)/carla/ -maxdepth 1 -type f -exec basename {} ';'`; do \ $(LINK) ../../carla/$$i $(DESTDIR)$(LIBDIR)/lv2/carla.lv2/$$i; \ done rm -f $(DESTDIR)$(LIBDIR)/lv2/carla.lv2/libcarla_standalone2.* ifeq ($(LINUX),true) # Link jack app bridge rm -rf $(DESTDIR)$(LIBDIR)/lv2/carla.lv2/jack $(LINK) ../../carla/jack $(DESTDIR)$(LIBDIR)/lv2/carla.lv2/jack endif ifeq ($(HAVE_PYQT),true) # Link resources for lv2 plugin rm -rf $(DESTDIR)$(LIBDIR)/lv2/carla.lv2/resources $(LINK) ../../../share/carla/resources $(DESTDIR)$(LIBDIR)/lv2/carla.lv2/resources # Link styles for lv2 plugin rm -rf $(DESTDIR)$(LIBDIR)/lv2/carla.lv2/styles $(LINK) ../../carla/styles $(DESTDIR)$(LIBDIR)/lv2/carla.lv2/styles endif # ------------------------------------------------------------------------------------------------------------- ifneq ($(HAIKU),true) ifeq ($(HAVE_PYQT),true) # Install vst plugin install -d $(DESTDIR)$(LIBDIR)/vst/carla.vst install -m 644 \ bin/CarlaRack*.* \ bin/CarlaPatchbay*.* \ $(DESTDIR)$(LIBDIR)/vst/carla.vst # Link binaries for vst plugin @for i in `find $(DESTDIR)$(LIBDIR)/carla/ -maxdepth 1 -type f -exec basename {} ';'`; do \ $(LINK) ../../carla/$$i $(DESTDIR)$(LIBDIR)/vst/carla.vst/$$i; \ done rm -f $(DESTDIR)$(LIBDIR)/vst/carla.vst/libcarla_standalone2.* # Link jack app bridge rm -rf $(DESTDIR)$(LIBDIR)/vst/carla.vst/jack $(LINK) ../../carla/jack $(DESTDIR)$(LIBDIR)/vst/carla.vst/jack # Link resources for vst plugin rm -rf $(DESTDIR)$(LIBDIR)/vst/carla.vst/resources $(LINK) ../../../share/carla/resources $(DESTDIR)$(LIBDIR)/vst/carla.vst/resources # Link styles for vst plugin rm -rf $(DESTDIR)$(LIBDIR)/vst/carla.vst/styles $(LINK) ../../carla/styles $(DESTDIR)$(LIBDIR)/vst/carla.vst/styles endif endif # ------------------------------------------------------------------------------------------------------------- ifneq ($(HAVE_PYQT),true) # Remove gui files for non-gui build rm $(DESTDIR)$(LIBDIR)/carla/carla-bridge-lv2-modgui rm $(DESTDIR)$(LIBDIR)/lv2/carla.lv2/carla-bridge-lv2-modgui endif # --------------------------------------------------------------------------------------------------------------------- ifneq ($(EXTERNAL_PLUGINS),true) install_external_plugins: endif install: install_main install_external_plugins # --------------------------------------------------------------------------------------------------------------------- uninstall: rm -f $(DESTDIR)$(BINDIR)/carla* rm -f $(DESTDIR)$(LIBDIR)/pkgconfig/carla-native-plugin.pc rm -f $(DESTDIR)$(LIBDIR)/pkgconfig/carla-standalone.pc rm -f $(DESTDIR)$(LIBDIR)/pkgconfig/carla-utils.pc rm -f $(DESTDIR)$(DATADIR)/applications/carla.desktop rm -f $(DESTDIR)$(DATADIR)/applications/carla-control.desktop rm -f $(DESTDIR)$(DATADIR)/icons/hicolor/*/apps/carla.png rm -f $(DESTDIR)$(DATADIR)/icons/hicolor/*/apps/carla-control.png rm -f $(DESTDIR)$(DATADIR)/icons/hicolor/scalable/apps/carla.svg rm -f $(DESTDIR)$(DATADIR)/icons/hicolor/scalable/apps/carla-control.svg rm -f $(DESTDIR)$(DATADIR)/mime/packages/carla.xml rm -rf $(DESTDIR)$(LIBDIR)/carla rm -rf $(DESTDIR)$(LIBDIR)/lv2/carla.lv2 rm -rf $(DESTDIR)$(LIBDIR)/lv2/carla-native.lv2 rm -rf $(DESTDIR)$(LIBDIR)/vst/carla.vst rm -rf $(DESTDIR)$(DATADIR)/carla rm -rf $(DESTDIR)$(INCLUDEDIR)/carla # ---------------------------------------------------------------------------------------------------------------------------- ifneq ($(MAKE_TERMOUT),) ANS_NO=\033[31mNO\033[0m ANS_YES=\033[32mYES\033[0m mS=\033[33m[ mZ=\033[30;1m[ mE=]\033[0m tS=\033[36m tE=\033[0m else ANS_NO=NO ANS_YES=YES mS=[ mZ=[ mE=] endif features_print_main: @printf -- "$(tS)---> Main features $(tE)\n" ifeq ($(HAVE_PYQT),true) @printf -- "Front-End: $(ANS_YES)\n" @printf -- "LV2 plugin: $(ANS_YES)\n" ifneq ($(HAIKU),true) @printf -- "VST plugin: $(ANS_YES)\n" else @printf -- "VST plugin: $(ANS_NO) $(mZ)Not available for Haiku$(mE)\n" endif else @printf -- "Front-End: $(ANS_NO) $(mS)Missing PyQt$(mE)\n" @printf -- "LV2 plugin: $(ANS_NO) $(mS)No front-end$(mE)\n" @printf -- "VST plugin: $(ANS_NO) $(mS)No front-end$(mE)\n" endif ifeq ($(HAVE_HYLIA),true) @printf -- "Link support: $(ANS_YES)\n" else ifeq ($(MACOS_OLD),true) @printf -- "Link support: $(ANS_NO) $(mZ)MacOS >= 10.10 only$(mE)\n" else @printf -- "Link support: $(ANS_NO) $(mZ)Linux, MacOS and Windows only$(mE)\n" endif endif ifeq ($(HAVE_LIBLO),true) @printf -- "OSC support: $(ANS_YES)\n" else @printf -- "OSC support: $(ANS_NO) $(mS)Missing liblo$(mE)\n" endif ifeq ($(WIN32),true) @printf -- "Binary detect: $(ANS_YES)\n" else ifeq ($(HAVE_LIBMAGIC),true) @printf -- "Binary detect: $(ANS_YES)\n" else @printf -- "Binary detect: $(ANS_NO) $(mS)Missing libmagic/file$(mE)\n" endif endif @printf -- "\n" @printf -- "$(tS)---> Engine drivers $(tE)\n" @printf -- "JACK: $(ANS_YES)\n" ifeq ($(LINUX),true) ifeq ($(HAVE_ALSA),true) @printf -- "ALSA: $(ANS_YES)\n" else @printf -- "ALSA: $(ANS_NO) $(mS)Missing ALSA$(mE)\n" endif else @printf -- "ALSA: $(ANS_NO) $(mZ)Linux only$(mE)\n" endif ifeq ($(UNIX),true) ifneq ($(MACOS),true) ifeq ($(HAVE_PULSEAUDIO),true) @printf -- "PulseAudio: $(ANS_YES)\n" else @printf -- "PulseAudio: $(ANS_NO) $(mS)Missing PulseAudio$(mE)\n" endif else @printf -- "PulseAudio: $(ANS_NO) $(mZ)Not available for MacOS$(mE)\n" endif else @printf -- "PulseAudio: $(ANS_NO) $(mZ)Only available for Unix systems$(mE)\n" endif ifeq ($(MACOS),true) @printf -- "CoreAudio: $(ANS_YES)\n" else @printf -- "CoreAudio: $(ANS_NO) $(mZ)MacOS only$(mE)\n" endif ifeq ($(WIN32),true) @printf -- "ASIO: $(ANS_YES)\n" @printf -- "DirectSound: $(ANS_YES)\n" @printf -- "WASAPI: $(ANS_YES)\n" else @printf -- "ASIO: $(ANS_NO) $(mZ)Windows only$(mE)\n" @printf -- "DirectSound: $(ANS_NO) $(mZ)Windows only$(mE)\n" @printf -- "WASAPI: $(ANS_NO) $(mZ)Windows only$(mE)\n" endif @printf -- "\n" @printf -- "$(tS)---> Plugin formats: $(tE)\n" @printf -- "Internal: $(ANS_YES)\n" @printf -- "LADSPA: $(ANS_YES)\n" @printf -- "DSSI: $(ANS_YES)\n" @printf -- "LV2: $(ANS_YES)\n" ifeq ($(MACOS_OR_WIN32),true) @printf -- "VST: $(ANS_YES) (with UI)\n" else ifeq ($(HAIKU),true) @printf -- "VST: $(ANS_YES) (without UI)\n" else ifeq ($(HAVE_X11),true) @printf -- "VST: $(ANS_YES) (with UI)\n" else @printf -- "VST: $(ANS_YES) (without UI) $(mS)Missing X11$(mE)\n" endif endif endif @printf -- "\n" @printf -- "$(tS)---> LV2 UI toolkit support: $(tE)\n" @printf -- "External: $(ANS_YES) (direct)\n" ifneq ($(MACOS_OR_WIN32),true) ifeq ($(HAVE_GTK2),true) @printf -- "Gtk2: $(ANS_YES) (bridge)\n" else @printf -- "Gtk2: $(ANS_NO) $(mS)Gtk2 missing$(mE)\n" endif ifeq ($(HAVE_GTK3),true) @printf -- "Gtk3: $(ANS_YES) (bridge)\n" else @printf -- "Gtk3: $(ANS_NO) $(mS)Gtk3 missing$(mE)\n" endif ifeq ($(HAVE_QT4),true) @printf -- "Qt4: $(ANS_YES) (bridge)\n" else @printf -- "Qt4: $(ANS_NO) $(mS)Qt4 missing$(mE)\n" endif ifeq ($(HAVE_QT5),true) @printf -- "Qt5: $(ANS_YES) (bridge)\n" else @printf -- "Qt5: $(ANS_NO) $(mS)Qt5 missing$(mE)\n" endif ifeq ($(HAVE_X11),true) @printf -- "X11: $(ANS_YES) (direct+bridge)\n" else @printf -- "X11: $(ANS_NO) $(mS)X11 missing$(mE)\n" endif else # LINUX @printf -- "Gtk2: $(ANS_NO) $(mZ)Not available for Windows or MacOS$(mE)\n" @printf -- "Gtk3: $(ANS_NO) $(mZ)Not available for Windows or MacOS$(mE)\n" @printf -- "Qt4: $(ANS_NO) $(mZ)Not available for Windows or MacOS$(mE)\n" @printf -- "Qt5: $(ANS_NO) $(mZ)Not available for Windows or MacOS$(mE)\n" @printf -- "X11: $(ANS_NO) $(mZ)Not available for Windows or MacOS$(mE)\n" endif # LINUX ifeq ($(MACOS),true) @printf -- "Cocoa: $(ANS_YES) (direct+bridge)\n" else @printf -- "Cocoa: $(ANS_NO) $(mZ)MacOS only$(mE)\n" endif ifeq ($(WIN32),true) @printf -- "Windows: $(ANS_YES) (direct+bridge)\n" else @printf -- "Windows: $(ANS_NO) $(mZ)Windows only$(mE)\n" endif @printf -- "\n" @printf -- "$(tS)---> File formats: $(tE)\n" ifeq ($(HAVE_SNDFILE),true) @printf -- "Basic: $(ANS_YES)\n" else @printf -- "Basic: $(ANS_NO) $(mS)libsndfile missing$(mE)\n" endif ifeq ($(HAVE_FFMPEG),true) @printf -- "Extra: $(ANS_YES)\n" else @printf -- "Extra: $(ANS_NO) $(mS)FFmpeg missing or too new$(mE)\n" endif ifeq ($(HAVE_FLUIDSYNTH),true) @printf -- "SF2/3: $(ANS_YES)\n" else @printf -- "SF2/3: $(ANS_NO) $(mS)FluidSynth missing or too old$(mE)\n" endif @printf -- "SFZ: $(ANS_YES)\n" @printf -- "\n" @printf -- "$(tS)---> Internal plugins: $(tE)\n" @printf -- "Basic Plugins: $(ANS_YES)\n" @printf -- "Carla-Patchbay: $(ANS_YES)\n" @printf -- "Carla-Rack: $(ANS_YES)\n" ifeq ($(EXTERNAL_PLUGINS),true) @printf -- "External Plugins: $(ANS_YES)\n" else @printf -- "External Plugins: $(ANS_NO)\n" endif ifneq ($(EXTERNAL_PLUGINS),true) features_print_external_plugins: endif features: features_print_main features_print_external_plugins # --------------------------------------------------------------------------------------------------------------------- .FORCE: .PHONY: .FORCE # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/README.md000066400000000000000000000025101364475620200136640ustar00rootroot00000000000000# ![Carla Logo](https://raw.githubusercontent.com/falkTX/Carla/master/resources/48x48/carla.png) Carla Plugin Host [![Build Status](https://travis-ci.org/falkTX/Carla.png)](https://travis-ci.org/falkTX/Carla) What is Carla? --------------- Carla is a fully-featured audio plugin host, with support for many audio drivers and plugin formats.
It's open source and licensed under the GNU General Public License, version 2 or later. Features --------- * LADSPA, DSSI, LV2 and VST2, VST3 and AU plugin formats * SF2/3 and SFZ sound banks * Internal audio and midi file player * Automation of plugin parameters via MIDI CC * Remote control over OSC * Rack and Patchbay processing modes, plus Single and Multi-Client if using JACK * Native audio drivers (ALSA, DirectSound, CoreAudio, etc) and JACK In experimental phase / work in progress: * Export any Carla loadable plugin or sound bank as an LV2 plugin * Plugin bridge support (such as running 32bit plugins on a 64bit Carla, or Windows plugins on Linux) * Run JACK applications as audio plugins * Transport controls, sync with JACK Transport or Ableton Link Carla is also available as an LV2 plugin and VST2 plugin. Screenshot ---------- ![Screenshot](http://kxstudio.linuxaudio.org/screenshots/carla.png) See the [official webpage](http://kxstudio.linuxaudio.org/Applications:Carla) also. Carla-2.1/bin/000077500000000000000000000000001364475620200131575ustar00rootroot00000000000000Carla-2.1/bin/carla-bridge-lv2-modgui000077500000000000000000000001761364475620200174100ustar00rootroot00000000000000#!/bin/bash ASPATH=$(readlink -f $0) BINDIR=$(dirname $ASPATH) exec python3 $BINDIR/../source/frontend/carla_modgui.py "$@" Carla-2.1/bin/carla.lv2/000077500000000000000000000000001364475620200147435ustar00rootroot00000000000000Carla-2.1/bin/carla.lv2/resources000077700000000000000000000000001364475620200210432../resourcesustar00rootroot00000000000000Carla-2.1/data/000077500000000000000000000000001364475620200133205ustar00rootroot00000000000000Carla-2.1/data/about.xcf000066400000000000000000013535131364475620200151470ustar00rootroot00000000000000gimp xcf file/BB" icc-profile H HLinomntrRGB XYZ  1acspMSFTIEC sRGB-HP cprtP3desclwtptbkptrXYZgXYZ,bXYZ@dmndTpdmddvuedLview$lumimeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ QXYZ XYZ o8XYZ bXYZ $descIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view_. \XYZ L VPWmeassig CRT curv #(-27;@EJOTY^chmrw| %+28>ELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Kmgimp-image-grid(style solid) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) icc-profile-namePhotoshop ICC profile!ctTOP     gimp-text-layer(markup "Plugin developed by falkTX,\nArtwork by nieee,\nCat from oneko by Masayuki Koba.\n\nBased on Nekobee by Sean Bolton and others.\nUsing the DISTRHO Plugin Toolkit, OpenGL UI.") (font "Kozuka Gothic Pr6N") (font-size 12.000000) (font-size-unit pixels) (antialias yes) (hint-style full) (language "en-us") (base-direction ltr) (color (color-rgb 0.654902 0.654902 0.654902)) (justify center) (line-spacing 3.000000) (box-mode fixed) (box-width 399.000000) (box-height 116.000000) (box-unit pixels) (hinting yes) tt a,tDuKKKKY jIz;U;=;<===('''(((()@;U;=;<===('''(((()@;U;=;<===('''(((()@;;=;;===5( H\e't 'v?/Ȋ'* Z( (% (~)(j'R()G\ݿ|o@CUݧUإᦤU8U8)񧦥Uߧ覠UU駢U+ , - UUU㦧㢧UUUU?CUݧUإᦤU8U8)񧦥Uߧ覠UU駢U+ , - UUU㦧㢧UUUU?CUݧUإᦤU8U8)񧦥Uߧ覠UU駢U+ , - UUU㦧㢧UUUU?C&]sսq[0}ֿi¹9a¹u̔W npb_na|Lna]. ,(% (*  -T '(t|;+dxmpp~~g6\ڶd޷KзMąзM 885Ҕ )3G\XȊ' %uяX 0IfNnB]~OK1PDc*1j Ѳ.LEL+ vj({JDgs)'o46σ+ , - tXuяZ0o2uя[0¹ Uuя]~wani]~pbnax]~1* ߿* (j*Ѳ++ `+gsgs~)gsσσзMxσ?U   U٧ӤԧUUާU=&  䦧 ⧦U  UUߧ##*U 쥧⧦٤퀧䧥U!!"U   U٧ӤԧUUާU=&  䦧 ⧦U  UUߧ##*U 쥧⧦٤퀧䧥U!!"U   U٧ӤԧUUާU=&  䦧 ⧦U  UUߧ##*U 쥧⧦٤퀧䧥U!!"U %~ m яGޔ¹}ֿiIޗ PLW~rna_tYHPxR|E*(,*)eY   0\ *(+{v:sd~pa%gv!σbׄзM޷KRۂ 5d|E=Û%zUIޗ Plll xtY䱲UdUdUd *)eط  0 `+{vدa%gJeT!JeT!JeT!3xRۂ b\b\b\Q|#U#E*m2Iޗ PÐ{i$$WtYġٶ xR|qcc xR|vXE*)eгz `ܾYY;g 0;l\$N\z +{vչۺ:Q:aڿa%gvvodv\!Rۂ h35/56d|!zy!hE"!t02334330<=C(((禧ꧦ姦ꧦ\02334330<=C(((禧ꧦ姦ꧦ\02334330<=C(((禧ꧦ姦ꧦ\HLJ0'(2\334/$3>39330*:Q<U<C(Û8(zz(2QZݟ$AcG xR|*<;Yi\G@@ֺ:*MaB{vLhZT5\    h!!!UUU뙦지UUU홦   '8U8h!!!UUU뙦지UUU홦   '8U8h!!!UUU뙦지UUU홦   '8U8h!ֽ-!A!?/M¹}ֿiuя[0 Z$ na_]~pb €(,* # 7 )V(+M'R.~pgsԮ!\ݿ|GзM޷Kσ\M[0sսqȊV1¹ $ pbW nudna € .( 7 (*V'y.mp(~ ֌GڶdoзM' 885Ҕ M      맥Uҧҧ駕UUU;;;UUUUUUUAM      맥Uҧҧ駕UUU;;;UUUUUUUAM      맥Uҧҧ駕UUU;;;UUUUUUUAM  \    bm¹ UuяIޗ¹¹Iޗ P nax]~tnanatYn~(j**((*)e Ѳ  0`q `+++{v~)gsa~~a%gPзMxσRۂзMзMRۂ ;|;;Eĕ%ݓؘ/ٲ&ֶ&`HF YK ]r~~i"&~$ NՄ  /N$oXiy+j \Iwդ0׮!An  ޥșUܦߧ󤀧էާ UUߧʧUUU0U0n  ޥșUܦߧ󤀧էާ UUߧʧUUU0U0n  ޥșUܦߧ󤀧էާ UUߧʧUUU0U0nI W l$WQZظxQZUd xR|ǦAcG:P&AcG5YQ<;<;x\0:@@ @@JeT!v_IaB,IaBb\5ׄ ZT>VZT ؘ \sսq[0uяuя UȊW npb]~]~x. **j Ѳ '++ `dxmpgsgs)(36\ڶdσσxoQ 0U05Ҕ X, , UUޠ죙瀤U맙UU򤦀UUU晦롦U󦧀󝦧 ==X, , UUޠ죙瀤U맙UU򤦀UUU晦롦U󦧀󝦧 ==X, , UUޠ죙瀤U맙UU򤦀UUU晦롦U󦧀󝦧 ==X, \, ?/[0}ֿiuяȊV1¹XM Zpb_]~udna$  ,*(1€  7)(+V'Rpgs(~.\ݿ|޷KσoзMGٲ&V YK "~iGޔ¹[0v$rnapb% *( 4$ ;i*^(*\Id~¤yL׮!bׄзM wک ֌ ==@= ~@= ~@= ~@L= ~    :c11%BOTTOM     gimp-text-layerq(text "For more information see distrho.sf.net/plugins.php") (font "Kozuka Gothic Pr6N") (font-size 12.000000) (font-size-unit pixels) (antialias yes) (hint-style full) (language "en-us") (base-direction ltr) (color (color-rgb 0.654902 0.654902 0.654902)) (justify center) (box-mode fixed) (box-width 305.000000) (box-height 37.000000) (box-unit pixels) (hinting yes) _1% 1%v+-9=UU䧦䧙UUUU9=UU䧦䧙UUUU9=UU䧦䧙UUUU9=uяXZ0o2uяX¹]~wani]~naT*1 *1(++gsgs~σσзML0UUԦݦUUUL0UUԦݦUUUL0UUԦݦUUUL50e\[0tuяXZ0o2?/Ȋuя[0pb]~wani Z]~pb *1 *  +)+gs'R(gsσ\ݿ|oσ\**蠟UU罹罹泥U ꥧUU􀥦\**蠟UU罹罹泥U ꥧUU􀥦\**蠟UU罹罹泥U ꥧUU􀥦\*\*M¹¹}ֿiM¡ȊXV1uя$ nana_$ ud]~€((,€1*7 7 V(V+.~~p.(gsLGзMзM޷KGoσEۧU᧦㧥( U( EۧU᧦㧥( U( EۧU᧦㧥( U( E5e\_Mt[0¹ȊGޔsսq[$ pbna\rW np€ ( *. 72  VE* '.L~(ddxmpGзMosnbׄ6\ڶd ( ( 5Ҕ D..퀒맢 {D..퀒맢 {D..퀒맢 {D..0MGޔV1Gޔb$ rudr€**7  V**.LddGbׄbׄ {L &/aboutnoise.png     /ccc/5QFE2vKA]r-^K3@.2020..0//0/10..0.0..//23/.0020/0211/0030/100122/121121120/-20/////.-00-1/-10/-/.0-//--0.-.,--,,--..,-/-+-.---+.-,/-*-.+,,.2/1/-.-//.0/0/-./-0-..13/-00/1/./2100.//2/.0021.011011001/.-1//..//.-/0,0.,0/.-/./,./-,0.--,,-,,--..,-/-+---,,+.-,/-)-.+,,.2/1/-.-//.0/0/-./-0-..13/-00/1/./2100.//2/.0021.011011001/.-1//..//.-/0,0.,0/.-/./-./-,0.--,,-,,--..,-/-+---,,+.-,/-)-.+,,/00/1023210211.1042420102112320020301145102242124331225213  .//.0/1211/100-0/4131/0/100121//1/1/00340/11031013211/114102     .//.0/1211/100-0/4131/0/100121//1/1/00340/11031013211/114102      2344124334334211221324543243303264542243324343223242257314 123301321232231001002024320211/215343112132320120301146203123301321232231001002024320211/2153431121323201203011462034354246544243632445653455455446422332435654354414375653343532421253312252132234412432343342112113135431322/326353121332332421253312252132234412432343342112113135431322/326353121332345423425233684244643465442446424456634654554344254444247145345234353354656324456165435344554234445354335257343113131156213324313543313252133541343343222143333136/34134112242142444112335043314232343113334242214146343113131156213324313543313252133541343343222143333136/34134112242142444112335043314232343113334242214146,,++.* ,,,*. ,--++/-, ,,,,,*--*.,*.- ,* , ,-* ,-+*-,++*****++ ,+ *+-+)+++,,++.* ,,,*.,--+*/-, ,,,,+*--*.,*.-,* , , -* ,-+*-,++*****++ ,,!*+-+)+++,,++.* ,,,*. ,--+*/ -, ,, ,,+*--*.,*.- ,* , , -* ,-+*-,++ *****++ ,,!*+-+)+++    !       ! !!       !            !"   !  !  !"!  !    !  !   !   !! !! " "                !    !!     !    !! !    !   !  !     "       !  !       ! ! !       !   !            !   ! !"  !  !  ! "! !  ! !  ! !  !! " "                 !    !!      !     "     "   ! !    "                 ! ! !       !   !               !   !  !"      !  !  "! !   ! !   ! !  !!" "                !  !     !! !     !    !  !    "    !  !      "       !            ! ! !            !                               2440554422362243332443431360342341222422424441123350432131223320133/34231125112122032222025/231230011310313330/1224/32102011221/133/34231125112122032222025/231230011310313330/1224/32102011221/+*) ,+*-+(+ ,)****)),)*+*),+,+*).,+++++*),,)-+)-,+*,+,*+,**-+*+)*,++*,++*+-,*+,))**+(++,,-*,*,*(+*,,+*,*+,-,,-+*.+*+*+*-.*'++) ,+*-+(+ ,)****)),) *+*),+,+*).,+++++*),,)-+)-,+*,+,*+,**-+*+)*,++*,++*+-,*+,))**+(++,,-*,*,*(+*,,+*,*+,-,,-+*.+*+*+*-.*'++) ,+*-+(+ ,)****)),) *+*),+,+*).,+++++*),,)-+)-,+*,+,*+,**-+*+)*,++*,++*+-,*+,))**+(++,,-*,*,*(+*,,+*,*+,-,,-+*.+*+*+*-.*'  ! !                  +**(+)+,,+*++,++)*,++*,++-,*+-))++(++-,.+,*,*)+*,--+,,*-+,-!   !            +**(+)+,,+*++,++)+,++-++-,*+-))++,(+,-,.+,*,*)+*,--+,,*-+,-!   !           !      +**(+)+,,+*++,++)+,++-++-,*+-))++,(+,-,.+,*,*)+*,--+,,*-+,-   --,.,+/,+,*,+./+(,++),*,--,+,,-,,+,--,-,.,-,,/.+,.++,,-*--.-/,.   --,.,+/,+,*,+./*(,++),*,--,+,,-,,*,-,,.,-,,/-+,.++,,-*,-.-/,-   --,.,+/,+,*,+./*(,++),*,--,+,,-,,*,-,,-,.,-,,/-+,.++,,-*,-.-/,-,.,*-,.//--,.-../..0.,1.-.,.-01,*.--+.,.//.-../..,.//./.0./..1,-+*-+-..--,.,-./../-,0--,.-00,*.--+-,-..-..,-/..-/..-.0,-+*-+-..--,.,-./../-,0--,.-00,*.--+-,-..-..,-/..-/..-.012223132103035022.23120013001000/21111.04-02/01./0/1//1/111..0-.0--../,//001.0.0.,/.011//0.0/0011020/30/0.0/011120210/2/24/11-2201//03//0/00.10000.03,01./1-./.0..0/101.-/-.0,,..+./0/1./-/-,.-/00.//-0./010/1/.2/././/011120210/2/24/11-2201//03//0/00.10000.03,01./1-./.0..0/101.-/-.0,,..+./0/1./-/-,.-/00.//-0./01001/.2/././/_K/%/ Background     db/d'3?/di6d [? 6{`Cg9:;<9998888888 888 888887777777777 7777776666666666 666666555555555555589:888877777777777777777766666666666666666665555555555555555555 54489:88887 7777777777 777777766 666666666666666  66555555 5555555555555544<=>       :;<       :;<       >?@    <$=>        <%=>            @,A  ?>           ?>             .A AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AA@@.>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>555544444444444444444443333333333333333333332 2222222222222222222444444 444444444 44443333 3333333 33333333333333322222 2222222222 2222444444 444 44444444444333 3333333333333333333333 32222 222222222 22222                                          @@ @@@@@@@@@@@@@@@@@@ @@@@ ??????????????? ??????>>>>>>>>>>>>> >>>>>=> >>>>>>>>>>>> >>> >>>>>= = = ================= =====<<<<<<<<<<<<<<<<<<> >> > >>>>>>>>>>>>>>>>>==== ======= === ====== === ===<<<<<<<<<<<< << <<<2222222222111111111111111111111111111111111 1111111111111111111>12222222222222222222222222222222 222222222 2222222222222222222222>2222222222222222 2222222222222222 22222 22222222222222222222 222222>2     1 1+23      2723          2623     345    34   3 4    5567      5567    5567================ < <<<<<<<<<<<<<<<;;;;;;;;; ;;;;;;::::::::: :::::889:<<<<;;;;;;;;;;;;;;;;;;;;::::::::::::::::::9999999999 999999998778<<<<;;;;;;;;;;;;; ;;; ;;;;:::::: :::::: :: ::::9999999999999999998778_K/%Carla-2.1/data/build-haiku.sh000066400000000000000000000003771364475620200160610ustar00rootroot00000000000000#!/bin/bash export HAIKU=true export CC=gcc-x86 export CXX=g++-x86 export MOC_QT4=moc-x86 export RCC_QT4=rcc-x86 export UIC_QT4=uic-x86 export PKG_CONFIG_PATH=/boot/home/config/develop/lib/x86/pkgconfig:/boot/system/non-packaged/lib/pkgconfig exec "$@" Carla-2.1/data/carla000077500000000000000000000005271364475620200143340ustar00rootroot00000000000000#!/bin/bash PYTHON=$(which python3 2>/dev/null) if [ ! -f ${PYTHON} ]; then PYTHON=python fi if [ "$1" = "--gdb" ]; then PYTHON="gdb --args $PYTHON" fi INSTALL_PREFIX="X-PREFIX-X" export PATH="$INSTALL_PREFIX"/lib/carla:$PATH exec $PYTHON "$INSTALL_PREFIX"/share/carla/carla --with-appname="$0" --with-libprefix="$INSTALL_PREFIX" "$@" Carla-2.1/data/carla-bridge-lv2-modgui000066400000000000000000000003501364475620200175400ustar00rootroot00000000000000#!/bin/bash PYTHON=$(which python3 2>/dev/null) if [ ! -f ${PYTHON} ]; then PYTHON=python fi INSTALL_PREFIX="X-PREFIX-X" export CARLA_LIB_PREFIX="$INSTALL_PREFIX" exec $PYTHON "$INSTALL_PREFIX"/share/carla/carla_modgui.py "$@" Carla-2.1/data/carla-control000077500000000000000000000005371364475620200160130ustar00rootroot00000000000000#!/bin/bash PYTHON=$(which python3 2>/dev/null) if [ ! -f ${PYTHON} ]; then PYTHON=python fi if [ "$1" = "--gdb" ]; then PYTHON="gdb --args $PYTHON" fi INSTALL_PREFIX="X-PREFIX-X" export PATH="$INSTALL_PREFIX"/lib/carla:$PATH exec $PYTHON "$INSTALL_PREFIX"/share/carla/carla-control --with-appname="$0" --with-libprefix="$INSTALL_PREFIX" "$@" Carla-2.1/data/carla-control.desktop000066400000000000000000000005031364475620200174510ustar00rootroot00000000000000[Desktop Entry] Name=Carla Control GenericName=Carla OSC Control GenericName[fr]=Contrôle OSC pour Carla Comment=Audio Plugin Host (OSC Control) Comment[fr]=Hôte de greffon audio (contrôle OSC) Exec=carla-control %u Icon=carla-control Terminal=false Type=Application Categories=AudioVideo;X-AudioEditing;Qt; Version=1.0 Carla-2.1/data/carla-database000077500000000000000000000005171364475620200160750ustar00rootroot00000000000000#!/bin/bash PYTHON=$(which python3 2>/dev/null) if [ ! -f ${PYTHON} ]; then PYTHON=python fi if [ "$1" = "--gdb" ]; then PYTHON="gdb --args $PYTHON" fi INSTALL_PREFIX="X-PREFIX-X" export PATH="$INSTALL_PREFIX"/lib/carla:$PATH exec $PYTHON "$INSTALL_PREFIX"/share/carla/carla_database.py --with-libprefix="$INSTALL_PREFIX" "$@" Carla-2.1/data/carla-jack-multi000077500000000000000000000005421364475620200163670ustar00rootroot00000000000000#!/bin/bash PYTHON=$(which python3 2>/dev/null) if [ ! -f ${PYTHON} ]; then PYTHON=python fi if [ "$1" = "--gdb" ]; then PYTHON="gdb --args $PYTHON" fi INSTALL_PREFIX="X-PREFIX-X" export PATH="$INSTALL_PREFIX"/lib/carla:$PATH exec $PYTHON "$INSTALL_PREFIX"/share/carla/carla-jack-multi --with-appname="$0" --with-libprefix="$INSTALL_PREFIX" "$@" Carla-2.1/data/carla-jack-single000077500000000000000000000005431364475620200165170ustar00rootroot00000000000000#!/bin/bash PYTHON=$(which python3 2>/dev/null) if [ ! -f ${PYTHON} ]; then PYTHON=python fi if [ "$1" = "--gdb" ]; then PYTHON="gdb --args $PYTHON" fi INSTALL_PREFIX="X-PREFIX-X" export PATH="$INSTALL_PREFIX"/lib/carla:$PATH exec $PYTHON "$INSTALL_PREFIX"/share/carla/carla-jack-single --with-appname="$0" --with-libprefix="$INSTALL_PREFIX" "$@" Carla-2.1/data/carla-libdir000077500000000000000000000003451364475620200155750ustar00rootroot00000000000000#!/bin/bash # small script that only prints carla's libdir. # can be used to detect if carla is installed, and where to find its libcarla_standalone2.so file CARLA_LIBDIR="X-LIBDIR-X" printf -- "%s" ${CARLA_LIBDIR}/carla exit 0 Carla-2.1/data/carla-native-plugin.pc000066400000000000000000000004201364475620200175020ustar00rootroot00000000000000prefix=X-PREFIX-X libdir=X-LIBDIR-X/carla includedir=X-INCLUDEDIR-X/carla Name: carla-native-plugin Version: 2.1.0 Description: Carla Native Plugin Libs: -Wl,-rpath=${libdir} -L${libdir} -lcarla_native-plugin Cflags: -DREAL_BUILD -I${includedir} -I${includedir}/includes Carla-2.1/data/carla-patchbay000077500000000000000000000005401364475620200161200ustar00rootroot00000000000000#!/bin/bash PYTHON=$(which python3 2>/dev/null) if [ ! -f ${PYTHON} ]; then PYTHON=python fi if [ "$1" = "--gdb" ]; then PYTHON="gdb --args $PYTHON" fi INSTALL_PREFIX="X-PREFIX-X" export PATH="$INSTALL_PREFIX"/lib/carla:$PATH exec $PYTHON "$INSTALL_PREFIX"/share/carla/carla-patchbay --with-appname="$0" --with-libprefix="$INSTALL_PREFIX" "$@" Carla-2.1/data/carla-rack000077500000000000000000000005341364475620200152500ustar00rootroot00000000000000#!/bin/bash PYTHON=$(which python3 2>/dev/null) if [ ! -f ${PYTHON} ]; then PYTHON=python fi if [ "$1" = "--gdb" ]; then PYTHON="gdb --args $PYTHON" fi INSTALL_PREFIX="X-PREFIX-X" export PATH="$INSTALL_PREFIX"/lib/carla:$PATH exec $PYTHON "$INSTALL_PREFIX"/share/carla/carla-rack --with-appname="$0" --with-libprefix="$INSTALL_PREFIX" "$@" Carla-2.1/data/carla-settings000077500000000000000000000005171364475620200161710ustar00rootroot00000000000000#!/bin/bash PYTHON=$(which python3 2>/dev/null) if [ ! -f ${PYTHON} ]; then PYTHON=python fi if [ "$1" = "--gdb" ]; then PYTHON="gdb --args $PYTHON" fi INSTALL_PREFIX="X-PREFIX-X" export PATH="$INSTALL_PREFIX"/lib/carla:$PATH exec $PYTHON "$INSTALL_PREFIX"/share/carla/carla_settings.py --with-libprefix="$INSTALL_PREFIX" "$@" Carla-2.1/data/carla-single000077500000000000000000000202241364475620200156070ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Script to start carla plugin bridges # Copyright (C) 2015-2018 Filipe Coelho # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # For a full copy of the GNU General Public License see the doc/GPL.txt file. # -------------------------------------------------------------------------------------------------------- # Imports import os import sys # -------------------------------------------------------------------------------------------------------- # Setup INSTALL_PREFIX = "X-PREFIX-X" CARLA_LIBDIR = os.path.join(INSTALL_PREFIX, "lib", "carla") CARLA_RESDIR = os.path.join(INSTALL_PREFIX, "share", "carla", "resources") # -------------------------------------------------------------------------------------------------------- # Check for enough arguments usageMsg = """\ usage: %s [arch (optional)] [format] [filename/uri] [label (optional)] [uniqueId (optional)] Possible archs: - native (default) - linux32 - linux64 - win32 - win64 Possible formats: - internal - ladspa - dssi - lv2 - vst|vst2 - vst3 - sf2 - sfz Examples: $ %s internal midisplit $ %s dssi /usr/lib/dssi/whysynth.so $ %s lv2 http://calf.sourceforge.net/plugins/Compressor $ %s native vst /usr/lib/vst/TAL-NoiseMaker.so $ %s win32 vst \"~/.wine/drive_c/Program Files (x86)/VstPlugins/Kontakt 5.dll\" $ CARLA_BRIDGE_PLUGIN_BINARY_TYPE=win64 %s vst \"~/.wine/drive_c/Program Files/Common Files/VST2/Sytrus VSTi.dll\" Format can be skipped for internal and lv2 plugins (auto-detected), like this: $ %s midipattern $ %s http://synthv1.sourceforge.net/lv2""" % ((sys.argv[0],)*9) def printUsageAndQuit(): print(usageMsg) sys.exit(0) if len(sys.argv) < 2: printUsageAndQuit() # -------------------------------------------------------------------------------------------------------- # Initialize variables to null ARCH = os.getenv("CARLA_BRIDGE_PLUGIN_BINARY_TYPE", "native") FORMAT = "none" FILENAME = "" LABEL = "" UNIQUEID = 0 # -------------------------------------------------------------------------------------------------------- # Set arch arg = 1 if sys.argv[arg] in ("native", "posix32", "posix64", "linux32", "linux64", "mac32", "mac64", "win32", "win64"): ARCH = sys.argv[arg].replace("linux", "posix").replace("mac", "posix") arg += 1 if len(sys.argv) == arg: printUsageAndQuit() # -------------------------------------------------------------------------------------------------------- # Set format if sys.argv[arg] in ("internal", "ladspa", "dssi", "lv2", "vst", "vst2", "vst3", "au", "sf2", "sfz"): FORMAT = sys.argv[arg] arg += 1 if FORMAT == "vst": FORMAT = "vst2" elif len(sys.argv) == arg+1: FORMAT = "lv2" if ":" in sys.argv[arg] else "internal" else: print("Invalid format") sys.exit(1) if len(sys.argv) == arg: printUsageAndQuit() # -------------------------------------------------------------------------------------------------------- # Set filename/uri if FORMAT in ("internal", "lv2"): LABEL = sys.argv[arg] arg += 1 else: FILENAME = os.path.expanduser(sys.argv[arg]) arg += 1 # -------------------------------------------------------------------------------------------------------- # Set label (optional) if len(sys.argv) > arg: if FORMAT == "internal": print("label/uri already set, ignoring 2nd label") elif FORMAT == "lv2": newpwd = sys.argv[arg] if os.path.exists(newpwd): print("using path hack for lv2 plugin") os.chdir(newpwd) else: LABEL = sys.argv[arg] arg += 1 # -------------------------------------------------------------------------------------------------------- # Set uniqueId (optional) if len(sys.argv) > arg: if FORMAT in ("internal", "dssi", "lv2", "au", "sf2", "sfz"): print("uniqueId is not used in this format, ignored") else: try: UNIQUEID = int(sys.argv[arg]) except: print("uniqueId must be a number") sys.exit(1) arg += 1 # -------------------------------------------------------------------------------------------------------- # Others? if len(sys.argv) > arg: print("Got too many arguments, ignoring past uniqueId") # -------------------------------------------------------------------------------------------------------- # Set bridge binary BRIDGE = os.path.join(CARLA_LIBDIR, "carla-bridge-" + ARCH) if ARCH in ("win32", "win64"): BRIDGE = BRIDGE + ".exe" # -------------------------------------------------------------------------------------------------------- # Check for existing carla folder if not os.path.exists(CARLA_LIBDIR): print("Carla library folder does not exist, is Carla installed?") sys.exit(2) if not os.path.exists(CARLA_RESDIR): print("Carla resource folder does not exist, is Carla installed?") sys.exit(2) # -------------------------------------------------------------------------------------------------------- # Check for existing arch binary if not os.path.exists(BRIDGE): print("Carla plugin bridge for the requested arch (%s) does not exist" % (ARCH,)) sys.exit(2) # -------------------------------------------------------------------------------------------------------- # Final checks if ARCH not in ("native", "posix32", "posix64", "win32", "win64"): print("Invalid arch") sys.exit(1) if FORMAT not in ("internal", "ladspa", "dssi", "lv2", "vst2", "vst3", "au", "sf2", "sfz"): print("Invalid format") sys.exit(1) if FILENAME and not os.path.exists(FILENAME): print("Requested filename does not exist") sys.exit(1) # -------------------------------------------------------------------------------------------------------- # Setup environment LADSPA_PATH = os.getenv("LADSPA_PATH") DSSI_PATH = os.getenv("DSSI_PATH") LV2_PATH = os.getenv("LV2_PATH") VST2_PATH = os.getenv("VST_PATH") VST3_PATH = os.getenv("VST3_PATH") SF2_PATH = os.getenv("SF2_PATH") SFZ_PATH = os.getenv("SFZ_PATH") if LADSPA_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_LADSPA"] = LADSPA_PATH if DSSI_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_DSSI"] = DSSI_PATH if LV2_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_LV2"] = LV2_PATH if VST2_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_VST2"] = VST2_PATH if VST3_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_VST3"] = VST3_PATH if SF2_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_SF2"] = SF2_PATH if SFZ_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_SFZ"] = SFZ_PATH os.environ["ENGINE_OPTION_PATH_BINARIES"] = CARLA_LIBDIR os.environ["ENGINE_OPTION_PATH_RESOURCES"] = CARLA_RESDIR # -------------------------------------------------------------------------------------------------------- CARLA_CLIENT_NAME = os.getenv("CARLA_CLIENT_NAME") LADISH_APP_NAME = os.getenv("LADISH_APP_NAME") if CARLA_CLIENT_NAME is not None: os.environ["CARLA_CLIENT_NAME"] = CARLA_CLIENT_NAME elif LADISH_APP_NAME is not None: os.environ["CARLA_CLIENT_NAME"] = LADISH_APP_NAME else: os.environ["CARLA_CLIENT_NAME"] = "(none)" # -------------------------------------------------------------------------------------------------------- # Exec command = [] if os.getenv("CARLA_BRIDGE_PLUGIN_BINARY_TYPE") is not None: BRIDGE = os.path.join(CARLA_LIBDIR, "carla-bridge-native") elif ARCH == "win32": command.append("wine") elif ARCH == "win64": command.append("wine64") command.append(BRIDGE) command.append(FORMAT) command.append(FILENAME or "(none)") command.append(LABEL or "(none)") command.append(str(UNIQUEID)) print(command) os.execvp(command[0], command) # -------------------------------------------------------------------------------------------------------- Carla-2.1/data/carla-standalone.pc000066400000000000000000000004151364475620200170540ustar00rootroot00000000000000prefix=X-PREFIX-X libdir=X-LIBDIR-X/carla includedir=X-INCLUDEDIR-X/carla Name: carla-standalone Version: 2.1.0 Description: Carla Host Standalone Libs: -Wl,-rpath=${libdir} -L${libdir} -lcarla_standalone2 Cflags: -DREAL_BUILD -I${includedir} -I${includedir}/includes Carla-2.1/data/carla-utils.pc000066400000000000000000000004271364475620200160670ustar00rootroot00000000000000prefix=X-PREFIX-X libdir=X-LIBDIR-X/carla includedir=X-INCLUDEDIR-X/carla Name: carla-utils Version: 2.1.0 Description: Carla Host Utilities Libs: -Wl,-rpath=${libdir} -L${libdir} -lcarla_utils Cflags: -DREAL_BUILD -I${includedir} -I${includedir}/includes -I${includedir}/utils Carla-2.1/data/carla.desktop000066400000000000000000000005041364475620200157740ustar00rootroot00000000000000[Desktop Entry] Name=Carla GenericName=Carla Plugin Host GenericName[fr]=Hôte de greffon Carla Comment=Audio Plugin Host Comment[fr]=Hôte de greffon audio Exec=carla %u Icon=carla Terminal=false Type=Application Categories=AudioVideo;X-AudioEditing;Qt; MimeType=application/x-carla-project; Version=1.0 X-NSM-capable=true Carla-2.1/data/carla.xml000066400000000000000000000007451364475620200151320ustar00rootroot00000000000000 Carla project Carla plugin preset Carla-2.1/data/copy-dpf-stuff000077500000000000000000000112201364475620200161100ustar00rootroot00000000000000#!/bin/bash set -e cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DPF/dgl/*.hpp /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/dgl/ cp -r -v /home/falktx/FOSS/GIT-mine/DISTRHO/DPF/dgl/src /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/dgl/ cp -r -v /home/falktx/FOSS/GIT-mine/DISTRHO/DPF/distrho/* /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/distrho/ || true rm -r /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/dgl/src/resources rm -r /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/dgl/src/sofd rm /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/dgl/src/Resources.* rm /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/distrho/src/DistrhoPlugin{Jack,LADSPA+DSSI,LV2,LV2export,VST}.cpp rm /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/distrho/src/DistrhoUI{DSSI,LV2}.cpp # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_mini-series/plugins/3BandEQ/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/3bandeq/ # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_mini-series/plugins/3BandSplitter/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/3bandsplitter/ # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_mini-series/plugins/PingPongPan/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/pingpongpan/ # # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_nekobi/plugins/Nekobi/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/nekobi/ # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_nekobi/plugins/Nekobi/nekobee-src/{*.c,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/nekobi/nekobee-src/ # # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO_prom/plugins/ProM/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/prom/ # # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/GrooveJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/groovejuice/ # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/PowerJuice/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/powerjuice/ # # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/PowerJuiceX2/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/powerjuicex2/ # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/SegmentJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/segmentjuice/ # # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/StutterJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/stutterjuice/ # # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/TriggerJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/triggerjuice/ # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/VectorJuice/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/vectorjuice/ # cp -v /home/falktx/FOSS/GIT-mine/DISTRHO/JuicePlugins/plugins/WobbleJuice/{*.cpp,*.hpp,*.hxx,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/wobblejuice/ # # cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamComp/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zamcomp/ # cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamCompX2/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zamcompx2/ # cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamEQ2/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zameq2/ # cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamSynth/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zamsynth/ # cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZamTube/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zamtube/ # cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZaMultiComp/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zamulticomp/ # cp -v /home/falktx/FOSS/GIT-mine/zam-plugins-DPF/plugins/ZaMultiCompX2/{*.cpp,*.hpp,*.h} /home/falktx/FOSS/GIT-mine/falkTX/Carla/source/modules/native-plugins/zamulticompx2/ Carla-2.1/data/copy-zynaddsubfx000077500000000000000000000044621364475620200165650ustar00rootroot00000000000000#!/bin/bash set -e ORIG_ZYN_DIR="/home/falktx/FOSS/GIT-mine/falkTX/zynaddsubfx" CARLA_ZYN_DIR="/home/falktx/FOSS/GIT-mine/falkTX/Carla/source/native-plugins/zynaddsubfx" rm -f $CARLA_ZYN_DIR/*.cpp rm -f $CARLA_ZYN_DIR/*.h rm -f $CARLA_ZYN_DIR/Containers/* rm -f $CARLA_ZYN_DIR/DSP/* rm -f $CARLA_ZYN_DIR/Effects/* rm -f $CARLA_ZYN_DIR/Misc/* rm -f $CARLA_ZYN_DIR/Nio/* rm -f $CARLA_ZYN_DIR/Params/* rm -f $CARLA_ZYN_DIR/Synth/* rm -f $CARLA_ZYN_DIR/Tests/* rm -fr $CARLA_ZYN_DIR/UI/* rm -fr $CARLA_ZYN_DIR/rtosc/* rm -f $CARLA_ZYN_DIR/tlsf/* cp $ORIG_ZYN_DIR/src/*.cpp $CARLA_ZYN_DIR/ cp $ORIG_ZYN_DIR/src/*.h $CARLA_ZYN_DIR/ cp $ORIG_ZYN_DIR/src/Containers/* $CARLA_ZYN_DIR/Containers/ cp $ORIG_ZYN_DIR/src/DSP/* $CARLA_ZYN_DIR/DSP/ cp $ORIG_ZYN_DIR/src/Effects/* $CARLA_ZYN_DIR/Effects/ cp $ORIG_ZYN_DIR/src/Misc/* $CARLA_ZYN_DIR/Misc/ cp $ORIG_ZYN_DIR/src/Nio/* $CARLA_ZYN_DIR/Nio/ cp $ORIG_ZYN_DIR/src/Params/* $CARLA_ZYN_DIR/Params/ cp $ORIG_ZYN_DIR/src/Synth/* $CARLA_ZYN_DIR/Synth/ cp -r $ORIG_ZYN_DIR/src/UI/* $CARLA_ZYN_DIR/UI/ cp $ORIG_ZYN_DIR/rtosc/include/rtosc/* $CARLA_ZYN_DIR/rtosc/ cp -r $ORIG_ZYN_DIR/rtosc/src/* $CARLA_ZYN_DIR/rtosc/ cp $ORIG_ZYN_DIR/tlsf/*.h $CARLA_ZYN_DIR/tlsf/ cp $ORIG_ZYN_DIR/tlsf/*.c $CARLA_ZYN_DIR/tlsf/ rm $CARLA_ZYN_DIR/*/CMakeLists.txt rm $CARLA_ZYN_DIR/UI/zynaddsubfx.xpm cp $ORIG_ZYN_DIR/src/zyn-version.h.in $CARLA_ZYN_DIR/zyn-version.h sed -i 's|${VERSION_MAJOR}|3|' $CARLA_ZYN_DIR/zyn-version.h sed -i 's|${VERSION_MINOR}|0|' $CARLA_ZYN_DIR/zyn-version.h sed -i 's|${VERSION_REVISION}|2|' $CARLA_ZYN_DIR/zyn-version.h find $CARLA_ZYN_DIR -name "*.h" -type f | xargs sed -i "s|namespace zyn|namespace zyncarla|g" find $CARLA_ZYN_DIR -name "*.fl" -type f | xargs sed -i "s|namespace zyn|namespace zyncarla|g" find $CARLA_ZYN_DIR -name "*.cpp" -type f | xargs sed -i "s|namespace zyn|namespace zyncarla|g" sed -i "s|zyn::|zyncarla::|g" $CARLA_ZYN_DIR/*/*.h sed -i "s|zyn::|zyncarla::|g" $CARLA_ZYN_DIR/*/*.cpp sed -i "s|emplace_uint32(|emplace_uint32_cpp(|" $CARLA_ZYN_DIR/rtosc/cpp/subtree-serialize.cpp sed -i "s|../../include/rtosc/|../|" $CARLA_ZYN_DIR/rtosc/cpp/*.cpp sed -i "s|../../tlsf/tlsf.h|tlsf/tlsf.h|" $CARLA_ZYN_DIR/Misc/Allocator.cpp sed -i "s|../src/globals.h|globals.h|" $CARLA_ZYN_DIR/Misc/Config.cpp sed -i "s|identity|identity_ts|" $CARLA_ZYN_DIR/UI/Fl_Osc_TSlider.cpp Carla-2.1/data/linux/000077500000000000000000000000001364475620200144575ustar00rootroot00000000000000Carla-2.1/data/linux/README000066400000000000000000000020751364475620200153430ustar00rootroot00000000000000# --- README for Carla - Linux build --- What is Carla? --------------- Carla is a fully-featured audio plugin host, with support for many audio drivers and plugin formats.
It's open source and licensed under the GNU General Public License, version 2 or later. Features --------- * LADSPA, DSSI, LV2 and VST2 plugin formats * SF2/3 and SFZ sound banks * Internal audio and midi file player * Automation of plugin parameters via MIDI CC * Remote control over OSC * Rack and Patchbay processing modes, plus Single and Multi-Client if using JACK * Native audio drivers (ALSA, DirectSound, CoreAudio, etc) and JACK * Transport controls, sync with JACK Transport or Ableton Link In experimental phase / work in progress: * Export any Carla loadable plugin or sound bank as an LV2 plugin * Plugin bridge support (such as running 32bit plugins on a 64bit Carla, or Windows plugins on Linux) * Run JACK applications as audio plugins Carla is also available as an LV2 and VST2 plugin for Linux. For a complete and updated description of Carla, please check: https://kx.studio/carla Carla-2.1/data/linux/app-carla-control.py000066400000000000000000000020721364475620200203500ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------------------------------------ # Imports (cx_Freeze) from cx_Freeze import setup, Executable # ------------------------------------------------------------------------------------------------------------ # Imports (Custom Stuff) from carla_host import VERSION # ------------------------------------------------------------------------------------------------------------ options = { "zip_include_packages": ["*"], "zip_exclude_packages": ["PyQt5"], "replace_paths": [["*","./lib/"]], "build_exe": "./build-carla-control", "optimize": True, } exe_options = { "script": "./source/frontend/carla-control", "targetName": "carla-control", } setup(name = "CarlaControl", version = VERSION, description = "Carla Plugin Host", options = {"build_exe": options}, executables = [Executable(**exe_options)]) # ------------------------------------------------------------------------------------------------------------ Carla-2.1/data/linux/app-carla.py000066400000000000000000000020331364475620200166670ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------------------------------------ # Imports (cx_Freeze) from cx_Freeze import setup, Executable # ------------------------------------------------------------------------------------------------------------ # Imports (Custom Stuff) from carla_host import VERSION # ------------------------------------------------------------------------------------------------------------ options = { "zip_include_packages": ["*"], "zip_exclude_packages": ["PyQt5"], "replace_paths": [["*","./lib/"]], "build_exe": "./build-carla", "optimize": True, } exe_options = { "script": "./source/frontend/carla", "targetName": "carla", } setup(name = "Carla", version = VERSION, description = "Carla Plugin Host", options = {"build_exe": options}, executables = [Executable(**exe_options)]) # ------------------------------------------------------------------------------------------------------------ Carla-2.1/data/linux/app-plugin.py000066400000000000000000000021051364475620200171030ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------------------------------------ # Imports (cx_Freeze) from cx_Freeze import setup, Executable # ------------------------------------------------------------------------------------------------------------ # Imports (Custom Stuff) from carla_host import VERSION from os import getenv # ------------------------------------------------------------------------------------------------------------ name = getenv("TARGET_NAME") options = { "zip_include_packages": ["*"], "zip_exclude_packages": ["PyQt5"], "replace_paths": [["*","./lib/"]], "build_exe": "./build-carla", "optimize": True, } exe_options = { "script": "./bin/resources/{}".format(name), "targetName": name, } setup(name = "Carla", version = VERSION, description = name, options = {"build_exe": options}, executables = [Executable(**exe_options)]) # ------------------------------------------------------------------------------------------------------------ Carla-2.1/data/linux/build-all.sh000077500000000000000000000374171364475620200166770ustar00rootroot00000000000000#!/bin/bash # --------------------------------------------------------------------------------------------------------------------- # check dependencies if ! which debootstrap > /dev/null; then echo "debootstrap not found, please install it" exit 1 fi # --------------------------------------------------------------------------------------------------------------------- # startup as main script if [ -z "${SOURCED_BY_DOCKER}" ]; then # stop on error set -e # cd to correct path cd $(dirname $0) fi # --------------------------------------------------------------------------------------------------------------------- # set variables source common.env # where we build stuff inside the chroot CHROOT_CARLA_DIR="/tmp/carla-src" # used for downloading packages from kxstudio repos, in order to get lv2-gtk3 and windows bridges CARLA_GIT_VER="2.1~rc1+git20200331" PKGS_NUM="20200331" # --------------------------------------------------------------------------------------------------------------------- # function to remove old stuff cleanup() { if [ -d ${TARGETDIR}/chroot32 ]; then sudo umount -lf ${TARGETDIR}/chroot32/dev/pts || true sudo umount -lf ${TARGETDIR}/chroot32/sys || true sudo umount -lf ${TARGETDIR}/chroot32/proc || true fi if [ -d ${TARGETDIR}/chroot64 ]; then sudo umount -lf ${TARGETDIR}/chroot64/dev/pts || true sudo umount -lf ${TARGETDIR}/chroot64/sys || true sudo umount -lf ${TARGETDIR}/chroot64/proc || true fi if [ -d ${TARGETDIR}/chroot32 ]; then sudo mv ${TARGETDIR}/chroot32 ${TARGETDIR}/chroot32-deleteme2 sudo rm -rf ${TARGETDIR}/chroot32-deleteme || true fi if [ -d ${TARGETDIR}/chroot64 ]; then sudo mv ${TARGETDIR}/chroot64 ${TARGETDIR}/chroot64-deleteme2 sudo rm -rf ${TARGETDIR}/chroot64-deleteme || true fi } # --------------------------------------------------------------------------------------------------------------------- # create chroots prepare() { if [ ! -d ${TARGETDIR}/chroot32 ]; then sudo debootstrap --no-check-gpg --arch=i386 lucid ${TARGETDIR}/chroot32 http://old-releases.ubuntu.com/ubuntu/ fi if [ ! -d ${TARGETDIR}/chroot64 ]; then sudo debootstrap --no-check-gpg --arch=amd64 lucid ${TARGETDIR}/chroot64 http://old-releases.ubuntu.com/ubuntu/ fi } # --------------------------------------------------------------------------------------------------------------------- # setup chroots chroot_setup() { CHROOT_DIR=${TARGETDIR}/chroot${ARCH} if [ ! -f ${CHROOT_DIR}/tmp/setup-aria2 ]; then pushd ${CHROOT_DIR}/tmp if [ x"${ARCH}" = x"32" ]; then wget -c https://github.com/q3aql/aria2-static-builds/releases/download/v1.34.0/aria2-1.34.0-linux-gnu-32bit-build1.tar.bz2 else wget -c https://github.com/q3aql/aria2-static-builds/releases/download/v1.34.0/aria2-1.34.0-linux-gnu-64bit-build1.tar.bz2 fi tar xf aria2-*.tar.bz2 popd fi cat < /etc/apt/sources.list apt-get update touch /tmp/setup-repo-list fi if [ ! -f /tmp/setup-repo-upgrade ]; then dpkg-divert --local --rename --add /sbin/initctl ln -s /bin/true /sbin/initctl apt-get dist-upgrade touch /tmp/setup-repo-upgrade fi if [ ! -f /tmp/setup-repo-packages ]; then apt-get install -y build-essential autoconf libtool cmake libglib2.0-dev libgl1-mesa-dev git-core apt-get clean touch /tmp/setup-repo-packages fi if [ ! -f /tmp/setup-aria2 ]; then pushd /tmp/aria2-* make install popd rm -r /tmp/aria2-* touch /tmp/setup-aria2 fi if [ ! -d ${CHROOT_CARLA_DIR} ]; then git clone --depth=1 -b develop git://github.com/falkTX/Carla ${CHROOT_CARLA_DIR} fi if [ ! -f ${CHROOT_CARLA_DIR}/source/native-plugins/external/README.md ]; then git clone git://github.com/falkTX/Carla-Plugins ${CHROOT_CARLA_DIR}/source/native-plugins/external fi cd ${CHROOT_CARLA_DIR} git checkout . git pull git submodule init git submodule update # might be updated by git pull chmod 777 data/linux/*.sh chmod 777 data/linux/common.env sync EOF } # --------------------------------------------------------------------------------------------------------------------- # build base libs chroot_build_deps() { CHROOT_DIR=${TARGETDIR}/chroot${ARCH} cp build-deps.sh build-pyqt.sh common.env ${CHROOT_DIR}${CHROOT_CARLA_DIR}/data/linux/ sudo cp /etc/ca-certificates.conf ${CHROOT_DIR}/etc/ sudo cp -r /usr/share/ca-certificates/* ${CHROOT_DIR}/usr/share/ca-certificates/ cat < Carla chmod +x Carla rm -rf carla carla-2.1 carla.zip mv build-carla-control carla-control-2.1 zip --symlinks -r -9 carla-control.zip carla-control-2.1 cat data/windows/unzipfx-carla-control/unzipfx2cat carla-control.zip > CarlaControl chmod +x CarlaControl rm -rf carla-control carla-control-2.1 carla-control.zip rm -rf ${PKG_FOLDER}${ARCH} mkdir ${PKG_FOLDER}${ARCH} cp data/linux/README ${PKG_FOLDER}${ARCH}/ mv Carla CarlaControl build-lv2/*.lv2 build-vst/*.vst ${PKG_FOLDER}${ARCH}/ rmdir build-lv2 build-vst tar cJf ${PKG_FOLDER}${ARCH}.tar.xz ${PKG_FOLDER}${ARCH} mv ${PKG_FOLDER}${ARCH}.tar.xz /tmp/ EOF } # --------------------------------------------------------------------------------------------------------------------- # run the functions if [ -z "${SOURCED_BY_DOCKER}" ]; then # name of final dir and xz file, needed only by chroot_pack_carla export PKG_FOLDER="Carla_2.1-linux" # cleanup prepare # 32bit build export ARCH=32 chroot_setup chroot_build_deps chroot_build_carla download_carla_extras chroot_pack_carla # 64bit build export ARCH=64 chroot_setup chroot_build_deps chroot_build_carla download_carla_extras chroot_pack_carla fi # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/data/linux/build-deps.sh000077500000000000000000000300001364475620200170370ustar00rootroot00000000000000#!/bin/bash # apt-get install build-essential autoconf libtool cmake libglib2.0-dev libgl1-mesa-dev # --------------------------------------------------------------------------------------------------------------------- # stop on error set -e # --------------------------------------------------------------------------------------------------------------------- # cd to correct path cd $(dirname $0) # --------------------------------------------------------------------------------------------------------------------- # set variables source common.env # --------------------------------------------------------------------------------------------------------------------- # function to remove old stuff cleanup() { rm -rf ${TARGETDIR}/carla32/ ${TARGETDIR}/carla64/ rm -rf file-* rm -rf flac-* rm -rf fltk-* rm -rf fluidsynth-* rm -rf liblo-* rm -rf libogg-* rm -rf libsndfile-* rm -rf libvorbis-* rm -rf pkg-config-* rm -rf qtbase-* rm -rf qtsvg-* rm -rf zlib-* } # --------------------------------------------------------------------------------------------------------------------- # function to build base libs build_base() { export CC=gcc export CXX=g++ export PREFIX=${TARGETDIR}/carla${ARCH} export PATH=${PREFIX}/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin export PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig export CFLAGS="-O3 -mtune=generic -msse -msse2 -mfpmath=sse -fvisibility=hidden -fdata-sections -ffunction-sections" export CFLAGS="${CFLAGS} -fPIC -DPIC -DNDEBUG -I${PREFIX}/include -m${ARCH}" export CXXFLAGS="${CFLAGS} -fvisibility-inlines-hidden" export LDFLAGS="-fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed -Wl,--strip-all" export LDFLAGS="${LDFLAGS} -L${PREFIX}/lib -m${ARCH}" # --------------------------------------------------------------------------------------------------------------------- # pkgconfig if [ ! -d pkg-config-${PKG_CONFIG_VERSION} ]; then aria2c https://pkg-config.freedesktop.org/releases/pkg-config-${PKG_CONFIG_VERSION}.tar.gz tar -xf pkg-config-${PKG_CONFIG_VERSION}.tar.gz fi if [ ! -f pkg-config-${PKG_CONFIG_VERSION}_$ARCH/build-done ]; then cp -r pkg-config-${PKG_CONFIG_VERSION} pkg-config-${PKG_CONFIG_VERSION}_$ARCH cd pkg-config-${PKG_CONFIG_VERSION}_$ARCH ./configure --enable-indirect-deps --with-internal-glib --with-pc-path=$PKG_CONFIG_PATH --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # liblo if [ ! -d liblo-${LIBLO_VERSION} ]; then aria2c https://download.sourceforge.net/liblo/liblo-${LIBLO_VERSION}.tar.gz tar -xf liblo-${LIBLO_VERSION}.tar.gz fi if [ ! -f liblo-${LIBLO_VERSION}_$ARCH/build-done ]; then cp -r liblo-${LIBLO_VERSION} liblo-${LIBLO_VERSION}_$ARCH cd liblo-${LIBLO_VERSION}_$ARCH ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --enable-threads \ --disable-examples --disable-tools make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- if [ x"${ARCH}" = x"32" ] && [ x"${TARGET}" != x"32" ]; then return fi # --------------------------------------------------------------------------------------------------------------------- # qt if [ ! -d qtbase-opensource-src-${QT5_VERSION} ]; then aria2c http://download.qt.io/archive/qt/${QT5_MVERSION}/${QT5_VERSION}/submodules/qtbase-opensource-src-${QT5_VERSION}.tar.xz tar xf qtbase-opensource-src-${QT5_VERSION}.tar.xz fi if [ ! -f qtbase-opensource-src-${QT5_VERSION}/build-done ]; then cd qtbase-opensource-src-${QT5_VERSION} if [ ! -f configured ]; then ./configure -release -strip -silent \ -sse2 \ -no-sse3 -no-ssse3 -no-sse4.1 -no-sse4.2 \ -no-avx -no-avx2 -no-avx512 \ -prefix ${PREFIX} \ -opensource -confirm-license \ -optimize-size -optimized-qmake \ -qt-freetype \ -qt-harfbuzz \ -qt-libjpeg \ -qt-libpng \ -qt-pcre \ -qt-sqlite \ -qt-xcb \ -qt-zlib \ -opengl desktop \ -no-cups \ -no-gtk \ -no-icu \ -no-openssl \ -make libs \ -make tools \ -nomake examples \ -nomake tests touch configured fi make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # qt5-svg if [ ! -d qtsvg-opensource-src-${QT5_VERSION} ]; then aria2c http://download.qt.io/archive/qt/${QT5_MVERSION}/${QT5_VERSION}/submodules/qtsvg-opensource-src-${QT5_VERSION}.tar.xz tar xf qtsvg-opensource-src-${QT5_VERSION}.tar.xz fi if [ ! -f qtsvg-opensource-src-${QT5_VERSION}/build-done ]; then cd qtsvg-opensource-src-${QT5_VERSION} qmake make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # zlib if [ ! -d zlib-${ZLIB_VERSION} ]; then aria2c https://github.com/madler/zlib/archive/v${ZLIB_VERSION}.tar.gz tar -xf zlib-${ZLIB_VERSION}.tar.gz fi if [ ! -f zlib-${ZLIB_VERSION}/build-done ]; then cd zlib-${ZLIB_VERSION} ./configure --static --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # file/magic if [ ! -d file-${FILE_VERSION} ]; then wget ftp://ftp.astron.com/pub/file/file-${FILE_VERSION}.tar.gz tar -xf file-${FILE_VERSION}.tar.gz fi if [ ! -f file-${FILE_VERSION}/build-done ]; then cd file-${FILE_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # libogg if [ ! -d libogg-${LIBOGG_VERSION} ]; then aria2c https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-${LIBOGG_VERSION}.tar.gz tar -xf libogg-${LIBOGG_VERSION}.tar.gz fi if [ ! -f libogg-${LIBOGG_VERSION}/build-done ]; then cd libogg-${LIBOGG_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # libvorbis if [ ! -d libvorbis-${LIBVORBIS_VERSION} ]; then aria2c https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-${LIBVORBIS_VERSION}.tar.gz tar -xf libvorbis-${LIBVORBIS_VERSION}.tar.gz fi if [ ! -f libvorbis-${LIBVORBIS_VERSION}/build-done ]; then cd libvorbis-${LIBVORBIS_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # flac if [ ! -d flac-${FLAC_VERSION} ]; then aria2c https://ftp.osuosl.org/pub/xiph/releases/flac/flac-${FLAC_VERSION}.tar.xz tar -xf flac-${FLAC_VERSION}.tar.xz fi if [ ! -f flac-${FLAC_VERSION}/build-done ]; then cd flac-${FLAC_VERSION} chmod +x configure install-sh ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --disable-cpplibs make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # libsndfile if [ ! -d libsndfile-${LIBSNDFILE_VERSION} ]; then wget http://www.mega-nerd.com/libsndfile/files/libsndfile-${LIBSNDFILE_VERSION}.tar.gz tar -xf libsndfile-${LIBSNDFILE_VERSION}.tar.gz fi if [ ! -f libsndfile-${LIBSNDFILE_VERSION}/build-done ]; then cd libsndfile-${LIBSNDFILE_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --disable-full-suite --disable-alsa --disable-sqlite make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # glib if [ ! -d ${PREFIX}/include/glib-2.0 ]; then cp -r /usr/include/glib-2.0 ${PREFIX}/include/ fi if [ ! -f ${PREFIX}/lib/pkgconfig/glib-2.0.pc ]; then if [ -f /usr/lib/x86_64-linux-gnu/pkgconfig/glib-2.0.pc ]; then cp /usr/lib/x86_64-linux-gnu/pkgconfig/glib-2.0.pc ${PREFIX}/lib/pkgconfig/ cp /usr/lib/x86_64-linux-gnu/pkgconfig/gthread-2.0.pc ${PREFIX}/lib/pkgconfig/ cp /usr/lib/x86_64-linux-gnu/pkgconfig/libpcre.pc ${PREFIX}/lib/pkgconfig/ else cp /usr/lib/pkgconfig/glib-2.0.pc ${PREFIX}/lib/pkgconfig/ cp /usr/lib/pkgconfig/gthread-2.0.pc ${PREFIX}/lib/pkgconfig/ fi fi # --------------------------------------------------------------------------------------------------------------------- # fluidsynth if [ ! -d fluidsynth-${FLUIDSYNTH_VERSION} ]; then aria2c https://github.com/FluidSynth/fluidsynth/archive/v${FLUIDSYNTH_VERSION}.tar.gz tar -xf fluidsynth-${FLUIDSYNTH_VERSION}.tar.gz fi if [ ! -f fluidsynth-${FLUIDSYNTH_VERSION}/build-done ]; then cd fluidsynth-${FLUIDSYNTH_VERSION} if [ ! -f patched ]; then patch -p1 -i ../../patches/fluidsynth-skip-drivers-build.patch touch patched fi sed -i "s/3.0.2/2.8.0/" CMakeLists.txt sed -i 's/_init_lib_suffix "64"/_init_lib_suffix ""/' CMakeLists.txt cmake . -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${PREFIX} -DBUILD_SHARED_LIBS=OFF \ -Denable-debug=OFF -Denable-profiling=OFF -Denable-ladspa=OFF -Denable-fpe-check=OFF -Denable-portaudio=OFF \ -Denable-trap-on-fpe=OFF -Denable-aufile=OFF -Denable-dbus=OFF -Denable-ipv6=OFF -Denable-jack=OFF \ -Denable-midishare=OFF -Denable-oss=OFF -Denable-pulseaudio=OFF -Denable-readline=OFF -Denable-ladcca=OFF \ -Denable-lash=OFF -Denable-alsa=OFF -Denable-coreaudio=OFF -Denable-coremidi=OFF -Denable-framework=OFF \ -Denable-floats=ON make ${MAKE_ARGS} make install sed -i -e "s|-lfluidsynth|-lfluidsynth -lglib-2.0 -lgthread-2.0 -lsndfile -lFLAC -lvorbisenc -lvorbis -logg -lpthread -lm|" ${PREFIX}/lib/pkgconfig/fluidsynth.pc touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # mxml if [ ! -d mxml-${MXML_VERSION} ]; then aria2c https://github.com/michaelrsweet/mxml/releases/download/v${MXML_VERSION}/mxml-${MXML_VERSION}.tar.gz tar -xf mxml-${MXML_VERSION}.tar.gz fi if [ ! -f mxml-${MXML_VERSION}/build-done ]; then cd mxml-${MXML_VERSION} ./configure --disable-shared --prefix=$PREFIX make libmxml.a cp *.a $PREFIX/lib/ cp *.pc $PREFIX/lib/pkgconfig/ cp mxml.h $PREFIX/include/ touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # fftw3 (needs to be last as it modifies C[XX]FLAGS) if [ ! -d fftw-${FFTW3_VERSION} ]; then aria2c http://www.fftw.org/fftw-${FFTW3_VERSION}.tar.gz tar -xf fftw-${FFTW3_VERSION}.tar.gz fi if [ ! -f fftw-${FFTW3_VERSION}/build-done ]; then export CFLAGS="${CFLAGS} -ffast-math" export CXXFLAGS="${CXXFLAGS} -ffast-math" cd fftw-${FFTW3_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --enable-sse2 \ --disable-debug --disable-alloca --disable-fortran \ --with-our-malloc make make install make clean ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --enable-sse2 --enable-sse --enable-single \ --disable-debug --disable-alloca --disable-fortran \ --with-our-malloc make make install make clean touch build-done cd .. fi } # --------------------------------------------------------------------------------------------------------------------- # build base libs export ARCH=32 export TARGET="${1}" build_base if [ x"${TARGET}" != x"32" ]; then export ARCH=64 build_base fi # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/data/linux/build-pyqt.sh000077500000000000000000000105531364475620200171140ustar00rootroot00000000000000#!/bin/bash # apt-get install build-essential autoconf libtool cmake libglib2.0-dev libgl1-mesa-dev # --------------------------------------------------------------------------------------------------------------------- # stop on error set -e # --------------------------------------------------------------------------------------------------------------------- # cd to correct path cd $(dirname $0) # --------------------------------------------------------------------------------------------------------------------- # set variables source common.env # --------------------------------------------------------------------------------------------------------------------- # function to remove old stuff cleanup() { rm -rf cx_Freeze-* rm -rf Python-* rm -rf PyQt-* rm -rf PyQt5_* rm -rf pyliblo-* rm -rf sip-* } # --------------------------------------------------------------------------------------------------------------------- # function to build base libs build_pyqt() { export CC=gcc export CXX=g++ export PREFIX=${TARGETDIR}/carla${ARCH} export PATH=${PREFIX}/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin export PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig export CFLAGS="-O3 -mtune=generic -msse -msse2 -mfpmath=sse -fPIC -DPIC -DNDEBUG -m${ARCH}" export CXXFLAGS="${CFLAGS}" export LDFLAGS="-m${ARCH} -Wl,-O1" # TODO build libffi statically # --------------------------------------------------------------------------------------------------------------------- # python if [ ! -d Python-${PYTHON_VERSION} ]; then aria2c https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz tar -xf Python-${PYTHON_VERSION}.tgz fi if [ ! -f Python-${PYTHON_VERSION}/build-done ]; then cd Python-${PYTHON_VERSION} ./configure --prefix=${PREFIX} make make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # sip if [ ! -d sip-${SIP_VERSION} ]; then aria2c http://sourceforge.net/projects/pyqt/files/sip/sip-${SIP_VERSION}/sip-${SIP_VERSION}.tar.gz tar -xf sip-${SIP_VERSION}.tar.gz fi if [ ! -f sip-${SIP_VERSION}/build-done ]; then cd sip-${SIP_VERSION} python3 configure.py --sip-module PyQt5.sip make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # pyqt5 if [ ! -d PyQt5_gpl-${PYQT5_VERSION} ]; then aria2c http://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-${PYQT5_VERSION}/PyQt5_gpl-${PYQT5_VERSION}.tar.gz tar -xf PyQt5_gpl-${PYQT5_VERSION}.tar.gz fi if [ ! -f PyQt5_gpl-${PYQT5_VERSION}/build-done ]; then cd PyQt5_gpl-${PYQT5_VERSION} python3 configure.py --confirm-license -c make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # cxfreeze if [ ! -d cx_Freeze-${CXFREEZE_VERSION} ]; then aria2c https://github.com/anthony-tuininga/cx_Freeze/archive/${CXFREEZE_VERSION}.tar.gz tar -xf cx_Freeze-${CXFREEZE_VERSION}.tar.gz fi if [ ! -f cx_Freeze-${CXFREEZE_VERSION}/build-done ]; then cd cx_Freeze-${CXFREEZE_VERSION} python3 setup.py build python3 setup.py install --prefix=${PREFIX} touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # pyliblo (needs to be last as it modifies CFLAGS) if [ ! -d pyliblo-${PYLIBLO_VERSION} ]; then aria2c http://das.nasophon.de/download/pyliblo-${PYLIBLO_VERSION}.tar.gz tar -xf pyliblo-${PYLIBLO_VERSION}.tar.gz fi if [ ! -f pyliblo-${PYLIBLO_VERSION}/build-done ]; then cd pyliblo-${PYLIBLO_VERSION} if [ ! -f patched ]; then patch -p1 -i ../../patches/pyliblo-python3.7.patch touch patched fi export CFLAGS="${CFLAGS} -I${PREFIX}/include -L${PREFIX}/lib" python3 setup.py build python3 setup.py install --prefix=${PREFIX} touch build-done cd .. fi } # --------------------------------------------------------------------------------------------------------------------- # build base libs export TARGET="${1}" if [ x"${TARGET}" = x"32" ]; then export ARCH=32 else export ARCH=64 fi build_pyqt # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/data/linux/build64.sh000077500000000000000000000027371364475620200163000ustar00rootroot00000000000000#!/bin/bash # --------------------------------------------------------------------------------------------------------------------- # stop on error set -e # --------------------------------------------------------------------------------------------------------------------- # cd to correct path if [ ! -f Makefile ]; then cd $(dirname $0)/../.. fi # --------------------------------------------------------------------------------------------------------------------- # set variables source data/linux/common.env MAKE_ARGS="${MAKE_ARGS} HAVE_FFMPEG=false HAVE_PULSEAUDIO=false EXTERNAL_PLUGINS=false" export LINUX="true" export CC=gcc export CXX=g++ unset CPPFLAGS # --------------------------------------------------------------------------------------------------------------------- # Complete 64bit build export CFLAGS="-I${TARGETDIR}/carla64/include -m64" export CXXFLAGS=${CFLAGS} export LDFLAGS="-L${TARGETDIR}/carla64/lib -m64" export PKG_CONFIG_PATH=${TARGETDIR}/carla64/lib/pkgconfig make ${MAKE_ARGS} # --------------------------------------------------------------------------------------------------------------------- # Build 32bit bridges export CFLAGS="-I${TARGETDIR}/carla32/include -m32" export CXXFLAGS=${CFLAGS} export LDFLAGS="-L${TARGETDIR}/carla32/lib -m32" export PKG_CONFIG_PATH=${TARGETDIR}/carla32/lib/pkgconfig make posix32 ${MAKE_ARGS} # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/data/linux/common.env000066400000000000000000000006551364475620200164670ustar00rootroot00000000000000#!/bin/bash PKG_CONFIG_VERSION=0.28 LIBLO_VERSION=0.30 ZLIB_VERSION=1.2.11 FILE_VERSION=5.34 LIBOGG_VERSION=1.3.4 LIBVORBIS_VERSION=1.3.6 FLAC_VERSION=1.3.2 LIBSNDFILE_VERSION=1.0.28 FLUIDSYNTH_VERSION=1.1.11 MXML_VERSION=2.12 FFTW3_VERSION=3.3.8 QT5_VERSION=5.9.8 QT5_MVERSION=5.9 PYTHON_VERSION=3.7.3 SIP_VERSION=4.19.13 PYLIBLO_VERSION=0.9.2 PYQT5_VERSION=5.11.3 CXFREEZE_VERSION=6.0 MAKE_ARGS="-j 1" TARGETDIR=$HOME/builds Carla-2.1/data/lv2-bundles/000077500000000000000000000000001364475620200154555ustar00rootroot00000000000000Carla-2.1/data/lv2-bundles/audiogain/000077500000000000000000000000001364475620200174155ustar00rootroot00000000000000Carla-2.1/data/lv2-bundles/audiogain/audiogain.ttl000066400000000000000000000040341364475620200221030ustar00rootroot00000000000000@prefix doap: . @prefix foaf: . @prefix lv2: . @prefix opts: . @prefix unit: . a lv2:UtilityPlugin, lv2:Plugin ; lv2:optionalFeature ; lv2:requiredFeature , , ; lv2:extensionData ; lv2:extensionData ; opts:supportedOption , , ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 0 ; lv2:symbol "lv2_freewheel" ; lv2:name "Freewheel" ; lv2:default 0.0 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ; lv2:designation ; lv2:portProperty lv2:toggled, ; ] ; lv2:port [ a lv2:InputPort, lv2:AudioPort ; lv2:index 1 ; lv2:symbol "lv2_audio_in_1" ; lv2:name "Audio Input 1" ; ] ; lv2:port [ a lv2:OutputPort, lv2:AudioPort ; lv2:index 2 ; lv2:symbol "lv2_audio_out_1" ; lv2:name "Audio Output 1" ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 3 ; lv2:symbol "gain" ; lv2:name "Gain" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 4.000000 ; unit:unit unit:coef ; ] ; doap:name "Audio Gain (Mono)" ; doap:maintainer [ foaf:name "falkTX" ] . Carla-2.1/data/lv2-bundles/audiogain/audiogain_s.ttl000066400000000000000000000055531364475620200224340ustar00rootroot00000000000000@prefix doap: . @prefix foaf: . @prefix lv2: . @prefix opts: . @prefix unit: . a lv2:UtilityPlugin, lv2:Plugin ; lv2:optionalFeature ; lv2:requiredFeature , , ; lv2:extensionData ; lv2:extensionData ; opts:supportedOption , , ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 0 ; lv2:symbol "lv2_freewheel" ; lv2:name "Freewheel" ; lv2:default 0.0 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ; lv2:designation ; lv2:portProperty lv2:toggled, ; ] ; lv2:port [ a lv2:InputPort, lv2:AudioPort ; lv2:index 1 ; lv2:symbol "lv2_audio_in_1" ; lv2:name "Audio Input 1" ; ] , [ a lv2:InputPort, lv2:AudioPort ; lv2:index 2 ; lv2:symbol "lv2_audio_in_2" ; lv2:name "Audio Input 2" ; ] ; lv2:port [ a lv2:OutputPort, lv2:AudioPort ; lv2:index 3 ; lv2:symbol "lv2_audio_out_1" ; lv2:name "Audio Output 1" ; ] , [ a lv2:OutputPort, lv2:AudioPort ; lv2:index 4 ; lv2:symbol "lv2_audio_out_2" ; lv2:name "Audio Output 2" ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 5 ; lv2:symbol "gain" ; lv2:name "Gain" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 4.000000 ; unit:unit unit:coef ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 6 ; lv2:symbol "apply_left" ; lv2:name "Apply Left" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 7 ; lv2:symbol "apply_right" ; lv2:name "Apply Right" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; ] ; doap:name "Audio Gain (Stereo)" ; doap:maintainer [ foaf:name "falkTX" ] . Carla-2.1/data/lv2-bundles/audiogain/manifest.ttl000066400000000000000000000005641364475620200217550ustar00rootroot00000000000000@prefix lv2: . @prefix rdfs: . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . Carla-2.1/data/lv2-bundles/files/000077500000000000000000000000001364475620200165575ustar00rootroot00000000000000Carla-2.1/data/lv2-bundles/files/audiofile.ttl000066400000000000000000000054051364475620200212510ustar00rootroot00000000000000@prefix atom: . @prefix doap: . @prefix foaf: . @prefix lv2: . @prefix opts: . @prefix patch: . a lv2:UtilityPlugin, lv2:Plugin ; lv2:optionalFeature ; lv2:requiredFeature , , ; lv2:extensionData ; lv2:extensionData ; lv2:extensionData ; lv2:extensionData ; opts:supportedOption , , ; lv2:port [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:designation lv2:control ; lv2:index 0 ; lv2:symbol "lv2_events_in" ; lv2:name "Events Input" ; ] ; patch:writable ; lv2:port [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; lv2:index 1 ; lv2:symbol "lv2_events_out" ; lv2:name "Events Output" ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 2 ; lv2:symbol "lv2_freewheel" ; lv2:name "Freewheel" ; lv2:default 0.0 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ; lv2:designation ; lv2:portProperty lv2:toggled, ; ] ; lv2:port [ a lv2:OutputPort, lv2:AudioPort ; lv2:index 3 ; lv2:symbol "lv2_audio_out_1" ; lv2:name "Audio Output 1" ; ] , [ a lv2:OutputPort, lv2:AudioPort ; lv2:index 4 ; lv2:symbol "lv2_audio_out_2" ; lv2:name "Audio Output 2" ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 5 ; lv2:symbol "loop_mode" ; lv2:name "Loop Mode" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; ] ; doap:name "Audio File" ; doap:maintainer [ foaf:name "falkTX" ] . Carla-2.1/data/lv2-bundles/files/manifest.ttl000066400000000000000000000017401364475620200211140ustar00rootroot00000000000000@prefix atom: . @prefix lv2: . @prefix mod: . @prefix opts: . @prefix rdfs: . @prefix ui: . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . a lv2:Parameter ; rdfs:label "file" ; rdfs:range atom:Path . a lv2:Parameter ; mod:fileTypes "audiofiles,audioloops" ; rdfs:label "audio file" ; rdfs:range atom:Path . a lv2:Parameter ; mod:fileTypes "midi" ; rdfs:label "midi file" ; rdfs:range atom:Path . Carla-2.1/data/lv2-bundles/files/midifile.ttl000066400000000000000000000043571364475620200210770ustar00rootroot00000000000000@prefix atom: . @prefix doap: . @prefix foaf: . @prefix lv2: . @prefix opts: . @prefix patch: . a lv2:UtilityPlugin, lv2:Plugin ; lv2:optionalFeature ; lv2:requiredFeature , , ; lv2:extensionData ; lv2:extensionData ; lv2:extensionData ; lv2:extensionData ; opts:supportedOption , , ; lv2:port [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:designation lv2:control ; lv2:index 0 ; lv2:symbol "lv2_events_in" ; lv2:name "Events Input" ; ] ; patch:writable ; lv2:port [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 1 ; lv2:symbol "lv2_events_out" ; lv2:name "Events Output" ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 2 ; lv2:symbol "lv2_freewheel" ; lv2:name "Freewheel" ; lv2:default 0.0 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ; lv2:designation ; lv2:portProperty lv2:toggled, ; ] ; doap:name "MIDI File" ; doap:maintainer [ foaf:name "falkTX" ] . Carla-2.1/data/lv2-bundles/miditools/000077500000000000000000000000001364475620200174605ustar00rootroot00000000000000Carla-2.1/data/lv2-bundles/miditools/manifest.ttl000066400000000000000000000020361364475620200220140ustar00rootroot00000000000000@prefix lv2: . @prefix rdfs: . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . Carla-2.1/data/lv2-bundles/miditools/midichanab.ttl000066400000000000000000000245021364475620200222670ustar00rootroot00000000000000@prefix atom: . @prefix doap: . @prefix foaf: . @prefix lv2: . @prefix opts: . @prefix patch: . @prefix rdf: . @prefix rdfs: . @prefix ui: . @prefix unit: . a lv2:UtilityPlugin, lv2:Plugin ; lv2:optionalFeature ; lv2:requiredFeature , , ; lv2:extensionData ; lv2:extensionData ; opts:supportedOption , , ; lv2:port [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:designation lv2:control ; lv2:index 0 ; lv2:symbol "lv2_midi_in" ; lv2:name "MIDI Input" ; ] ; lv2:port [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 1 ; lv2:symbol "lv2_midi_out_1" ; lv2:name "MIDI Output #1" ; ] ; lv2:port [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 2 ; lv2:symbol "lv2_midi_out_2" ; lv2:name "MIDI Output #2" ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 3 ; lv2:symbol "lv2_freewheel" ; lv2:name "Freewheel" ; lv2:default 0.0 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ; lv2:designation ; lv2:portProperty lv2:toggled, ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 4 ; lv2:symbol "_1" ; lv2:name "1" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 5 ; lv2:symbol "_2" ; lv2:name "2" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 6 ; lv2:symbol "_3" ; lv2:name "3" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 7 ; lv2:symbol "_4" ; lv2:name "4" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 8 ; lv2:symbol "_5" ; lv2:name "5" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 9 ; lv2:symbol "_6" ; lv2:name "6" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 10 ; lv2:symbol "_7" ; lv2:name "7" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 11 ; lv2:symbol "_8" ; lv2:name "8" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 12 ; lv2:symbol "_9" ; lv2:name "9" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 13 ; lv2:symbol "_10" ; lv2:name "10" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 14 ; lv2:symbol "_11" ; lv2:name "11" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 15 ; lv2:symbol "_12" ; lv2:name "12" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 16 ; lv2:symbol "_13" ; lv2:name "13" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 17 ; lv2:symbol "_14" ; lv2:name "14" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 18 ; lv2:symbol "_15" ; lv2:name "15" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 19 ; lv2:symbol "_16" ; lv2:name "16" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Output A" ; rdf:value 0.000000 ] , [ rdfs:label "Output B" ; rdf:value 1.000000 ] ; ] ; doap:name "MIDI Channel A/B" ; doap:maintainer [ foaf:name "Milk Brewster" ] . Carla-2.1/data/lv2-bundles/miditools/midichanfilter.ttl000066400000000000000000000236001364475620200231700ustar00rootroot00000000000000@prefix atom: . @prefix doap: . @prefix foaf: . @prefix lv2: . @prefix opts: . @prefix patch: . @prefix rdf: . @prefix rdfs: . @prefix ui: . @prefix unit: . a lv2:UtilityPlugin, lv2:Plugin ; lv2:optionalFeature ; lv2:requiredFeature , , ; lv2:extensionData ; lv2:extensionData ; opts:supportedOption , , ; lv2:port [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:designation lv2:control ; lv2:index 0 ; lv2:symbol "lv2_midi_in" ; lv2:name "MIDI Input" ; ] ; lv2:port [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 1 ; lv2:symbol "lv2_midi_out" ; lv2:name "MIDI Output" ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 2 ; lv2:symbol "lv2_freewheel" ; lv2:name "Freewheel" ; lv2:default 0.0 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ; lv2:designation ; lv2:portProperty lv2:toggled, ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 3 ; lv2:symbol "_1" ; lv2:name "1" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 4 ; lv2:symbol "_2" ; lv2:name "2" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 5 ; lv2:symbol "_3" ; lv2:name "3" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 6 ; lv2:symbol "_4" ; lv2:name "4" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 7 ; lv2:symbol "_5" ; lv2:name "5" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 8 ; lv2:symbol "_6" ; lv2:name "6" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 9 ; lv2:symbol "_7" ; lv2:name "7" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 10 ; lv2:symbol "_8" ; lv2:name "8" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 11 ; lv2:symbol "_9" ; lv2:name "9" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 12 ; lv2:symbol "_10" ; lv2:name "10" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 13 ; lv2:symbol "_11" ; lv2:name "11" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 14 ; lv2:symbol "_12" ; lv2:name "12" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 15 ; lv2:symbol "_13" ; lv2:name "13" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 16 ; lv2:symbol "_14" ; lv2:name "14" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 17 ; lv2:symbol "_15" ; lv2:name "15" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 18 ; lv2:symbol "_16" ; lv2:name "16" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; lv2:portProperty lv2:enumeration ; lv2:scalePoint [ rdfs:label "Off" ; rdf:value 0.000000 ] , [ rdfs:label "On" ; rdf:value 1.000000 ] ; ] ; doap:name "MIDI Channel Filter" ; doap:maintainer [ foaf:name "falkTX" ] . Carla-2.1/data/lv2-bundles/miditools/midichannelize.ttl000066400000000000000000000050611364475620200231720ustar00rootroot00000000000000@prefix atom: . @prefix doap: . @prefix foaf: . @prefix lv2: . @prefix opts: . @prefix patch: . @prefix rdf: . @prefix rdfs: . @prefix ui: . @prefix unit: . a lv2:UtilityPlugin, lv2:Plugin ; lv2:optionalFeature ; lv2:requiredFeature , , ; lv2:extensionData ; lv2:extensionData ; opts:supportedOption , , ; lv2:port [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:designation lv2:control ; lv2:index 0 ; lv2:symbol "lv2_midi_in" ; lv2:name "MIDI Input" ; ] ; lv2:port [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 1 ; lv2:symbol "lv2_midi_out" ; lv2:name "MIDI Output" ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 2 ; lv2:symbol "lv2_freewheel" ; lv2:name "Freewheel" ; lv2:default 0.0 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ; lv2:designation ; lv2:portProperty lv2:toggled, ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 3 ; lv2:symbol "channel" ; lv2:name "Channel" ; lv2:default 1.000000 ; lv2:minimum 1.000000 ; lv2:maximum 16.000000 ; lv2:portProperty lv2:integer ; ] ; doap:name "MIDI Channelize" ; doap:maintainer [ foaf:name "falkTX" ] . Carla-2.1/data/lv2-bundles/miditools/midigain.ttl000066400000000000000000000064641364475620200220000ustar00rootroot00000000000000@prefix atom: . @prefix doap: . @prefix foaf: . @prefix lv2: . @prefix opts: . @prefix patch: . @prefix rdf: . @prefix rdfs: . @prefix ui: . @prefix unit: . a lv2:UtilityPlugin, lv2:Plugin ; lv2:optionalFeature ; lv2:requiredFeature , , ; lv2:extensionData ; lv2:extensionData ; opts:supportedOption , , ; lv2:port [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:designation lv2:control ; lv2:index 0 ; lv2:symbol "lv2_midi_in" ; lv2:name "MIDI Input" ; ] ; lv2:port [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 1 ; lv2:symbol "lv2_midi_out" ; lv2:name "MIDI Output" ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 2 ; lv2:symbol "lv2_freewheel" ; lv2:name "Freewheel" ; lv2:default 0.0 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ; lv2:designation ; lv2:portProperty lv2:toggled, ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 3 ; lv2:symbol "gain" ; lv2:name "Gain" ; lv2:default 1.000000 ; lv2:minimum 0.001000 ; lv2:maximum 4.000000 ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 4 ; lv2:symbol "apply_notes" ; lv2:name "Apply Notes" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 5 ; lv2:symbol "apply_aftertouch" ; lv2:name "Apply Aftertouch" ; lv2:default 1.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 6 ; lv2:symbol "apply_cc" ; lv2:name "Apply CC" ; lv2:default 0.000000 ; lv2:minimum 0.000000 ; lv2:maximum 1.000000 ; lv2:portProperty lv2:toggled ; ] ; doap:name "MIDI Gain" ; doap:maintainer [ foaf:name "falkTX" ] . Carla-2.1/data/lv2-bundles/miditools/midijoin.ttl000066400000000000000000000137511364475620200220160ustar00rootroot00000000000000@prefix atom: . @prefix doap: . @prefix foaf: . @prefix lv2: . @prefix opts: . @prefix patch: . @prefix rdf: . @prefix rdfs: . @prefix ui: . @prefix unit: . a lv2:UtilityPlugin, lv2:Plugin ; lv2:optionalFeature ; lv2:requiredFeature , , ; lv2:extensionData ; lv2:extensionData ; opts:supportedOption , , ; lv2:port [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:designation lv2:control ; lv2:index 0 ; lv2:symbol "lv2_midi_in_1" ; lv2:name "MIDI Input #1" ; ] ; lv2:port [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 1 ; lv2:symbol "lv2_midi_in_2" ; lv2:name "MIDI Input #2" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 2 ; lv2:symbol "lv2_midi_in_3" ; lv2:name "MIDI Input #3" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 3 ; lv2:symbol "lv2_midi_in_4" ; lv2:name "MIDI Input #4" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 4 ; lv2:symbol "lv2_midi_in_5" ; lv2:name "MIDI Input #5" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 5 ; lv2:symbol "lv2_midi_in_6" ; lv2:name "MIDI Input #6" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 6 ; lv2:symbol "lv2_midi_in_7" ; lv2:name "MIDI Input #7" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 7 ; lv2:symbol "lv2_midi_in_8" ; lv2:name "MIDI Input #8" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 8 ; lv2:symbol "lv2_midi_in_9" ; lv2:name "MIDI Input #9" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 9 ; lv2:symbol "lv2_midi_in_10" ; lv2:name "MIDI Input #10" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 10 ; lv2:symbol "lv2_midi_in_11" ; lv2:name "MIDI Input #11" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 11 ; lv2:symbol "lv2_midi_in_12" ; lv2:name "MIDI Input #12" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 12 ; lv2:symbol "lv2_midi_in_13" ; lv2:name "MIDI Input #13" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 13 ; lv2:symbol "lv2_midi_in_14" ; lv2:name "MIDI Input #14" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 14 ; lv2:symbol "lv2_midi_in_15" ; lv2:name "MIDI Input #15" ; ] , [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 15 ; lv2:symbol "lv2_midi_in_16" ; lv2:name "MIDI Input #16" ; ] ; lv2:port [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 16 ; lv2:symbol "lv2_midi_out" ; lv2:name "MIDI Output" ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 17 ; lv2:symbol "lv2_freewheel" ; lv2:name "Freewheel" ; lv2:default 0.0 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ; lv2:designation ; lv2:portProperty lv2:toggled, ; ] ; doap:name "MIDI Join" ; doap:maintainer [ foaf:name "falkTX" ] . Carla-2.1/data/lv2-bundles/miditools/midisplit.ttl000066400000000000000000000140301364475620200222010ustar00rootroot00000000000000@prefix atom: . @prefix doap: . @prefix foaf: . @prefix lv2: . @prefix opts: . @prefix patch: . @prefix rdf: . @prefix rdfs: . @prefix ui: . @prefix unit: . a lv2:UtilityPlugin, lv2:Plugin ; lv2:optionalFeature ; lv2:requiredFeature , , ; lv2:extensionData ; lv2:extensionData ; opts:supportedOption , , ; lv2:port [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:designation lv2:control ; lv2:index 0 ; lv2:symbol "lv2_midi_in" ; lv2:name "MIDI Input" ; ] ; lv2:port [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 1 ; lv2:symbol "lv2_midi_out_1" ; lv2:name "MIDI Output #1" ; ] ; lv2:port [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 2 ; lv2:symbol "lv2_midi_out_2" ; lv2:name "MIDI Output #2" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 3 ; lv2:symbol "lv2_midi_out_3" ; lv2:name "MIDI Output #3" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 4 ; lv2:symbol "lv2_midi_out_4" ; lv2:name "MIDI Output #4" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 5 ; lv2:symbol "lv2_midi_out_5" ; lv2:name "MIDI Output #5" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 6 ; lv2:symbol "lv2_midi_out_6" ; lv2:name "MIDI Output #6" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 7 ; lv2:symbol "lv2_midi_out_7" ; lv2:name "MIDI Output #7" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 8 ; lv2:symbol "lv2_midi_out_8" ; lv2:name "MIDI Output #8" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 9 ; lv2:symbol "lv2_midi_out_9" ; lv2:name "MIDI Output #9" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 10 ; lv2:symbol "lv2_midi_out_10" ; lv2:name "MIDI Output #10" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 11 ; lv2:symbol "lv2_midi_out_11" ; lv2:name "MIDI Output #11" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 12 ; lv2:symbol "lv2_midi_out_12" ; lv2:name "MIDI Output #12" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 13 ; lv2:symbol "lv2_midi_out_13" ; lv2:name "MIDI Output #13" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 14 ; lv2:symbol "lv2_midi_out_14" ; lv2:name "MIDI Output #14" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 15 ; lv2:symbol "lv2_midi_out_15" ; lv2:name "MIDI Output #15" ; ] , [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 16 ; lv2:symbol "lv2_midi_out_16" ; lv2:name "MIDI Output #16" ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 17 ; lv2:symbol "lv2_freewheel" ; lv2:name "Freewheel" ; lv2:default 0.0 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ; lv2:designation ; lv2:portProperty lv2:toggled, ; ] ; doap:name "MIDI Split" ; doap:maintainer [ foaf:name "falkTX" ] . Carla-2.1/data/lv2-bundles/miditools/miditranspose.ttl000066400000000000000000000055011364475620200230670ustar00rootroot00000000000000@prefix atom: . @prefix doap: . @prefix foaf: . @prefix lv2: . @prefix opts: . @prefix patch: . @prefix rdf: . @prefix rdfs: . @prefix ui: . @prefix unit: . a lv2:UtilityPlugin, lv2:Plugin ; lv2:optionalFeature ; lv2:requiredFeature , , ; lv2:extensionData ; lv2:extensionData ; opts:supportedOption , , ; lv2:port [ a lv2:InputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:designation lv2:control ; lv2:index 0 ; lv2:symbol "lv2_midi_in" ; lv2:name "MIDI Input" ; ] ; lv2:port [ a lv2:OutputPort, atom:AtomPort ; atom:bufferType atom:Sequence ; atom:supports ; lv2:index 1 ; lv2:symbol "lv2_midi_out" ; lv2:name "MIDI Output" ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 2 ; lv2:symbol "lv2_freewheel" ; lv2:name "Freewheel" ; lv2:default 0.0 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ; lv2:designation ; lv2:portProperty lv2:toggled, ; ] ; lv2:port [ a lv2:InputPort, lv2:ControlPort ; lv2:index 3 ; lv2:symbol "octaves" ; lv2:name "Octaves" ; lv2:default 0.000000 ; lv2:minimum -8.000000 ; lv2:maximum 8.000000 ; lv2:portProperty lv2:integer ; ] , [ a lv2:InputPort, lv2:ControlPort ; lv2:index 4 ; lv2:symbol "semitones" ; lv2:name "Semitones" ; lv2:default 0.000000 ; lv2:minimum -12.000000 ; lv2:maximum 12.000000 ; lv2:portProperty lv2:integer ; ] ; doap:name "MIDI Transpose" ; doap:maintainer [ foaf:name "falkTX" ] . Carla-2.1/data/macos/000077500000000000000000000000001364475620200144225ustar00rootroot00000000000000Carla-2.1/data/macos/README000066400000000000000000000027171364475620200153110ustar00rootroot00000000000000# --- README for Carla - macOS build --- What is Carla? --------------- Carla is a fully-featured audio plugin host, with support for many audio drivers and plugin formats.
It's open source and licensed under the GNU General Public License, version 2 or later. Features --------- * LADSPA, DSSI, LV2 and VST2, VST3 and AU plugin formats * SF2/3 and SFZ sound banks * Internal audio and midi file player * Automation of plugin parameters via MIDI CC * Remote control over OSC * Rack and Patchbay processing modes, plus Single and Multi-Client if using JACK * Native audio drivers (ALSA, DirectSound, CoreAudio, etc) and JACK * Transport controls, sync with JACK Transport or Ableton Link In experimental phase / work in progress: * Export any Carla loadable plugin or sound bank as an LV2 plugin * Plugin bridge support (such as running 32bit plugins on a 64bit Carla, or Windows plugins on Linux) Carla is also available as an LV2 and VST2 plugin for macOS. For the LV2 plugin, create the /Library/Audio/Plug-Ins/LV2 folder (if it does not exist yet), then copy carla.lv2 into it and restart your LV2 host. For the VST2 plugin, create the /Library/Audio/Plug-Ins/VST folder (if it does not exist yet), then copy carla.vst and carlafx.vst into it and restart your VST2 host. For a complete and updated description of Carla, please check: https://kx.studio/carla NOTE! Carla's LV2 and VST2 plugins are not notarized, so they will not run in macOS 10.15 (Catalina) or higher. Carla-2.1/data/macos/build-deps-new.sh000077500000000000000000000443461364475620200176130ustar00rootroot00000000000000#!/bin/bash # NOTE: You need the following packages installed via MacPorts: # automake, autoconf, cmake, libtool, p7zip, pkgconfig, aria2 # --------------------------------------------------------------------------------------------------------------------- # stop on error set -e # --------------------------------------------------------------------------------------------------------------------- # cd to correct path if [ -f Makefile ]; then cd data/macos fi # --------------------------------------------------------------------------------------------------------------------- # set variables export DEPS_NEW=1 source common.env # --------------------------------------------------------------------------------------------------------------------- # function to remove old stuff cleanup() { rm -rf $TARGETDIR/carla/ $TARGETDIR/carla32/ $TARGETDIR/carla64/ rm -rf cx_Freeze-* rm -rf Python-* rm -rf PyQt-* rm -rf PyQt5_* rm -rf file-* rm -rf flac-* rm -rf fltk-* rm -rf fluidsynth-* rm -rf fftw-* rm -rf gettext-* rm -rf glib-* rm -rf libffi-* rm -rf liblo-* rm -rf libogg-* rm -rf libsndfile-* rm -rf libvorbis-* rm -rf mxml-* rm -rf pkg-config-* rm -rf pyliblo-* rm -rf qtbase-* rm -rf qtmacextras-* rm -rf qtsvg-* rm -rf sip-* rm -rf zlib-* rm -rf PaxHeaders.* } # --------------------------------------------------------------------------------------------------------------------- # function to build base libs build_base() { export CC=clang export CXX=clang++ export PREFIX=${TARGETDIR}/carla${ARCH} export PATH=${PREFIX}/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin export PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig export CFLAGS="-O3 -mtune=generic -msse -msse2 -mfpmath=sse -fvisibility=hidden -fdata-sections -ffunction-sections" export CFLAGS="${CFLAGS} -fPIC -DPIC -DNDEBUG -I${PREFIX}/include -m${ARCH} -mmacosx-version-min=10.12" export CXXFLAGS="${CFLAGS} -fvisibility-inlines-hidden -std=gnu++11 -stdlib=libc++" export LDFLAGS="-fdata-sections -ffunction-sections -Wl,-dead_strip -Wl,-dead_strip_dylibs" export LDFLAGS="${LDFLAGS} -L${PREFIX}/lib -m${ARCH} -stdlib=libc++" # --------------------------------------------------------------------------------------------------------------------- # pkgconfig if [ ! -d pkg-config-${PKG_CONFIG_VERSION} ]; then curl -O https://pkg-config.freedesktop.org/releases/pkg-config-${PKG_CONFIG_VERSION}.tar.gz tar -xf pkg-config-${PKG_CONFIG_VERSION}.tar.gz fi if [ ! -f pkg-config-${PKG_CONFIG_VERSION}_$ARCH/build-done ]; then cp -r pkg-config-${PKG_CONFIG_VERSION} pkg-config-${PKG_CONFIG_VERSION}_$ARCH cd pkg-config-${PKG_CONFIG_VERSION}_$ARCH ./configure --enable-indirect-deps --with-internal-glib --with-pc-path=$PKG_CONFIG_PATH --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # liblo if [ ! -d liblo-${LIBLO_VERSION} ]; then curl -L http://download.sourceforge.net/liblo/liblo-${LIBLO_VERSION}.tar.gz -o liblo-${LIBLO_VERSION}.tar.gz tar -xf liblo-${LIBLO_VERSION}.tar.gz fi if [ ! -f liblo-${LIBLO_VERSION}_$ARCH/build-done ]; then cp -r liblo-${LIBLO_VERSION} liblo-${LIBLO_VERSION}_$ARCH cd liblo-${LIBLO_VERSION}_$ARCH ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --enable-threads \ --disable-examples --disable-tools make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- if [ x"${ARCH}" = x"32" ]; then return fi # --------------------------------------------------------------------------------------------------------------------- # zlib if [ ! -d zlib-${ZLIB_VERSION} ]; then /opt/local/bin/aria2c https://github.com/madler/zlib/archive/v${ZLIB_VERSION}.tar.gz tar -xf zlib-${ZLIB_VERSION}.tar.gz fi if [ ! -f zlib-${ZLIB_VERSION}/build-done ]; then cd zlib-${ZLIB_VERSION} ./configure --static --prefix=${PREFIX} make make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # file/magic if [ ! -d file-${FILE_VERSION} ]; then curl -O ftp://ftp.astron.com/pub/file/file-${FILE_VERSION}.tar.gz tar -xf file-${FILE_VERSION}.tar.gz fi if [ ! -f file-${FILE_VERSION}/build-done ]; then cd file-${FILE_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # libogg if [ ! -d libogg-${LIBOGG_VERSION} ]; then curl -O https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-${LIBOGG_VERSION}.tar.gz tar -xf libogg-${LIBOGG_VERSION}.tar.gz fi if [ ! -f libogg-${LIBOGG_VERSION}/build-done ]; then cd libogg-${LIBOGG_VERSION} sed -i -e 's/__MACH__/__MACH_SKIP__/' include/ogg/os_types.h ./configure --enable-static --disable-shared --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # libvorbis if [ ! -d libvorbis-${LIBVORBIS_VERSION} ]; then curl -O https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-${LIBVORBIS_VERSION}.tar.gz tar -xf libvorbis-${LIBVORBIS_VERSION}.tar.gz fi if [ ! -f libvorbis-${LIBVORBIS_VERSION}/build-done ]; then cd libvorbis-${LIBVORBIS_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # flac if [ ! -d flac-${FLAC_VERSION} ]; then curl -O https://ftp.osuosl.org/pub/xiph/releases/flac/flac-${FLAC_VERSION}.tar.xz /opt/local/bin/7z x flac-${FLAC_VERSION}.tar.xz /opt/local/bin/7z x flac-${FLAC_VERSION}.tar fi if [ ! -f flac-${FLAC_VERSION}/build-done ]; then cd flac-${FLAC_VERSION} chmod +x configure install-sh ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --disable-cpplibs make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # libsndfile if [ ! -d libsndfile-${LIBSNDFILE_VERSION} ]; then curl -O http://www.mega-nerd.com/libsndfile/files/libsndfile-${LIBSNDFILE_VERSION}.tar.gz tar -xf libsndfile-${LIBSNDFILE_VERSION}.tar.gz fi if [ ! -f libsndfile-${LIBSNDFILE_VERSION}/build-done ]; then cd libsndfile-${LIBSNDFILE_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --disable-full-suite --disable-alsa --disable-sqlite make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # glib if [ ! -d glib-${GLIB_VERSION} ]; then /opt/local/bin/aria2c http://caesar.ftp.acc.umu.se/pub/GNOME/sources/glib/${GLIB_MVERSION}/glib-${GLIB_VERSION}.tar.xz /opt/local/bin/7z x glib-${GLIB_VERSION}.tar.xz /opt/local/bin/7z x glib-${GLIB_VERSION}.tar fi if [ ! -f glib-${GLIB_VERSION}/build-done ]; then cd glib-${GLIB_VERSION} if [ ! -f patched ]; then patch -p1 -i ../../patches/glib_skip-gettext.patch rm m4macros/glib-gettext.m4 touch patched fi chmod +x autogen.sh configure install-sh env PATH=/opt/local/bin:$PATH ./autogen.sh env PATH=/opt/local/bin:$PATH LDFLAGS="-L${PREFIX}/lib -m${ARCH}" \ ./configure --enable-static --disable-shared --prefix=${PREFIX} env PATH=/opt/local/bin:$PATH make ${MAKE_ARGS} -k || true touch gio/gio-querymodules gio/glib-compile-resources gio/gsettings gio/gdbus gio/gresource gio/gapplication touch gobject/gobject-query tests/gobject/performance tests/gobject/performance-threaded env PATH=/opt/local/bin:$PATH make touch ${PREFIX}/bin/gtester-report env PATH=/opt/local/bin:$PATH make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # fluidsynth if [ ! -d fluidsynth-${FLUIDSYNTH_VERSION} ]; then /opt/local/bin/aria2c https://github.com/FluidSynth/fluidsynth/archive/v${FLUIDSYNTH_VERSION}.tar.gz tar -xf fluidsynth-${FLUIDSYNTH_VERSION}.tar.gz fi if [ ! -f fluidsynth-${FLUIDSYNTH_VERSION}/build-done ]; then cd fluidsynth-${FLUIDSYNTH_VERSION} if [ ! -f patched ]; then patch -p1 -i ../../patches/fluidsynth-skip-drivers-build.patch touch patched fi sed -i -e 's/_init_lib_suffix "64"/_init_lib_suffix ""/' CMakeLists.txt /opt/local/bin/cmake . -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${PREFIX} -DBUILD_SHARED_LIBS=OFF \ -Denable-debug=OFF -Denable-profiling=OFF -Denable-ladspa=OFF -Denable-fpe-check=OFF -Denable-portaudio=OFF \ -Denable-trap-on-fpe=OFF -Denable-aufile=OFF -Denable-dbus=OFF -Denable-ipv6=OFF -Denable-jack=OFF \ -Denable-midishare=OFF -Denable-oss=OFF -Denable-pulseaudio=OFF -Denable-readline=OFF -Denable-ladcca=OFF \ -Denable-lash=OFF -Denable-alsa=OFF -Denable-coreaudio=OFF -Denable-coremidi=OFF -Denable-framework=OFF \ -Denable-floats=ON make ${MAKE_ARGS} -k || true touch src/fluidsynth make make install sed -i -e "s|-lfluidsynth|-lfluidsynth -lglib-2.0 -lgthread-2.0 -lsndfile -lFLAC -lvorbisenc -lvorbis -logg -lpthread -lm -liconv|" ${PREFIX}/lib/pkgconfig/fluidsynth.pc touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # mxml if [ ! -d mxml-${MXML_VERSION} ]; then /opt/local/bin/aria2c https://github.com/michaelrsweet/mxml/releases/download/v${MXML_VERSION}/mxml-${MXML_VERSION}.tar.gz tar -xf mxml-${MXML_VERSION}.tar.gz fi if [ ! -f mxml-${MXML_VERSION}/build-done ]; then cd mxml-${MXML_VERSION} ./configure --disable-shared --prefix=${PREFIX} make libmxml.a cp *.a ${PREFIX}/lib/ cp *.pc ${PREFIX}/lib/pkgconfig/ cp mxml.h ${PREFIX}/include/ touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # fftw3 (needs to be last as it modifies C[XX]FLAGS) if [ ! -d fftw-${FFTW3_VERSION} ]; then curl -O http://www.fftw.org/fftw-${FFTW3_VERSION}.tar.gz tar -xf fftw-${FFTW3_VERSION}.tar.gz fi if [ ! -f fftw-${FFTW3_VERSION}/build-done ]; then export CFLAGS="${CFLAGS} -ffast-math" export CXXFLAGS="${CXXFLAGS} -ffast-math" cd fftw-${FFTW3_VERSION} ./configure --enable-static --enable-sse2 --disable-shared --disable-debug --prefix=${PREFIX} make make install make clean ./configure --enable-static --enable-sse --enable-sse2 --enable-single --disable-shared --disable-debug --prefix=${PREFIX} make make install make clean touch build-done cd .. fi } # --------------------------------------------------------------------------------------------------------------------- # build base libs # cleanup export ARCH=64 build_base # --------------------------------------------------------------------------------------------------------------------- # set flags for qt stuff export PREFIX=${TARGETDIR}/carla export PATH=${PREFIX}/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin export PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig export PKG_CONFIG=${TARGETDIR}/carla64/bin/pkg-config export CFLAGS="-O3 -mtune=generic -msse -msse2 -mfpmath=sse -fPIC -DPIC -DNDEBUG -I${PREFIX}/include -m64 -mmacosx-version-min=10.12" export CXXFLAGS="${CFLAGS} -std=gnu++11 -stdlib=libc++" export LDFLAGS="-L${PREFIX}/lib -m64 -stdlib=libc++" export MAKE=/usr/bin/make # --------------------------------------------------------------------------------------------------------------------- # qt5-base download if [ ! -d qtbase-everywhere-src-${QT5_VERSION} ]; then curl -L http://download.qt.io/archive/qt/${QT5_MVERSION}/${QT5_VERSION}/submodules/qtbase-everywhere-src-${QT5_VERSION}.tar.xz -o qtbase-everywhere-src-${QT5_VERSION}.tar.xz /opt/local/bin/7z x qtbase-everywhere-src-${QT5_VERSION}.tar.xz /opt/local/bin/7z x qtbase-everywhere-src-${QT5_VERSION}.tar fi # --------------------------------------------------------------------------------------------------------------------- # qt5-base (64bit, shared, framework) if [ ! -f qtbase-everywhere-src-${QT5_VERSION}/build-done ]; then cd qtbase-everywhere-src-${QT5_VERSION} if [ ! -f configured ]; then chmod +x configure ./configure -release -shared -opensource -confirm-license -platform macx-clang -framework \ -prefix ${PREFIX} -plugindir ${PREFIX}/lib/qt5/plugins -headerdir ${PREFIX}/include/qt5 \ -pkg-config -force-pkg-config -strip \ -sse2 -no-sse3 -no-ssse3 -no-sse4.1 -no-sse4.2 -no-avx -no-avx2 -no-avx512 \ -no-mips_dsp -no-mips_dspr2 \ -no-pch -pkg-config \ -make libs -make tools \ -nomake examples -nomake tests \ -no-compile-examples \ -gui -widgets \ -no-dbus \ -no-glib -qt-pcre \ -no-journald -no-syslog -no-slog2 \ -no-openssl -no-securetransport -no-sctp -no-libproxy \ -no-cups -no-fontconfig -qt-freetype -no-harfbuzz -no-gtk -opengl desktop -qpa cocoa \ -no-directfb -no-eglfs -no-xcb -no-xcb-xlib \ -no-evdev -no-libinput -no-mtdev \ -no-gif -no-ico -qt-libpng -qt-libjpeg \ -qt-sqlite touch configured fi make ${MAKE_ARGS} make install ln -s ${PREFIX}/lib/QtCore.framework/Headers ${PREFIX}/include/qt5/QtCore ln -s ${PREFIX}/lib/QtGui.framework/Headers ${PREFIX}/include/qt5/QtGui ln -s ${PREFIX}/lib/QtWidgets.framework/Headers ${PREFIX}/include/qt5/QtWidgets touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # qt5-mac-extras if [ ! -d qtmacextras-everywhere-src-${QT5_VERSION} ]; then curl -L http://download.qt.io/archive/qt/${QT5_MVERSION}/${QT5_VERSION}/submodules/qtmacextras-everywhere-src-${QT5_VERSION}.tar.xz -o qtmacextras-everywhere-src-${QT5_VERSION}.tar.xz /opt/local/bin/7z x qtmacextras-everywhere-src-${QT5_VERSION}.tar.xz /opt/local/bin/7z x qtmacextras-everywhere-src-${QT5_VERSION}.tar fi if [ ! -f qtmacextras-everywhere-src-${QT5_VERSION}/build-done ]; then cd qtmacextras-everywhere-src-${QT5_VERSION} qmake make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # qt5-svg if [ ! -d qtsvg-everywhere-src-${QT5_VERSION} ]; then curl -L http://download.qt.io/archive/qt/${QT5_MVERSION}/${QT5_VERSION}/submodules/qtsvg-everywhere-src-${QT5_VERSION}.tar.xz -o qtsvg-everywhere-src-${QT5_VERSION}.tar.xz /opt/local/bin/7z x qtsvg-everywhere-src-${QT5_VERSION}.tar.xz /opt/local/bin/7z x qtsvg-everywhere-src-${QT5_VERSION}.tar fi if [ ! -f qtsvg-everywhere-src-${QT5_VERSION}/build-done ]; then cd qtsvg-everywhere-src-${QT5_VERSION} qmake make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # python if [ ! -d Python-${PYTHON_VERSION} ]; then /opt/local/bin/aria2c https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz tar -xf Python-${PYTHON_VERSION}.tgz fi if [ ! -f Python-${PYTHON_VERSION}/build-done ]; then cd Python-${PYTHON_VERSION} sed -i -e "s/#zlib zlibmodule.c/zlib zlibmodule.c/" Modules/Setup.dist ./configure --prefix=${PREFIX} --enable-optimizations --enable-shared make make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # sip if [ ! -d sip-${SIP_VERSION} ]; then /opt/local/bin/aria2c https://www.riverbankcomputing.com/static/Downloads/sip/${SIP_VERSION}/sip-${SIP_VERSION}.tar.gz tar -xf sip-${SIP_VERSION}.tar.gz fi if [ ! -f sip-${SIP_VERSION}/build-done ]; then cd sip-${SIP_VERSION} python3 configure.py --sip-module PyQt5.sip make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # pyqt5 if [ ! -d PyQt5_gpl-${PYQT5_VERSION} ]; then /opt/local/bin/aria2c https://www.riverbankcomputing.com/static/Downloads/PyQt5/${PYQT5_VERSION}/PyQt5_gpl-${PYQT5_VERSION}.tar.gz tar -xf PyQt5_gpl-${PYQT5_VERSION}.tar.gz fi if [ ! -f PyQt5_gpl-${PYQT5_VERSION}/build-done ]; then cd PyQt5_gpl-${PYQT5_VERSION} python3 configure.py --concatenate --confirm-license -c make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # pyliblo if [ ! -d pyliblo-${PYLIBLO_VERSION} ]; then /opt/local/bin/aria2c http://das.nasophon.de/download/pyliblo-${PYLIBLO_VERSION}.tar.gz tar -xf pyliblo-${PYLIBLO_VERSION}.tar.gz fi if [ ! -f pyliblo-${PYLIBLO_VERSION}/build-done ]; then cd pyliblo-${PYLIBLO_VERSION} if [ ! -f patched ]; then patch -p1 -i ../../patches/pyliblo-python3.7.patch touch patched fi env CFLAGS="${CFLAGS} -I${TARGETDIR}/carla64/include" LDFLAGS="${LDFLAGS} -L${TARGETDIR}/carla64/lib" \ python3 setup.py build python3 setup.py install --prefix=${PREFIX} touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # cxfreeze if [ ! -d cx_Freeze-${CXFREEZE_VERSION} ]; then /opt/local/bin/aria2c https://github.com/anthony-tuininga/cx_Freeze/archive/${CXFREEZE_VERSION}.tar.gz tar -xf cx_Freeze-${CXFREEZE_VERSION}.tar.gz fi if [ ! -f cx_Freeze-${CXFREEZE_VERSION}/build-done ]; then cd cx_Freeze-${CXFREEZE_VERSION} sed -i -e 's/"python%s.%s"/"python%s.%sm"/' setup.py python3 setup.py build python3 setup.py install --prefix=${PREFIX} touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/data/macos/build-deps.sh000077500000000000000000000526021364475620200170160ustar00rootroot00000000000000#!/bin/bash # NOTE: You need the following packages installed via MacPorts: # automake, autoconf, cmake, libtool, p7zip, pkgconfig, aria2 # --------------------------------------------------------------------------------------------------------------------- # stop on error set -e # --------------------------------------------------------------------------------------------------------------------- # cd to correct path if [ -f Makefile ]; then cd data/macos fi # --------------------------------------------------------------------------------------------------------------------- # set variables source common.env # --------------------------------------------------------------------------------------------------------------------- # function to remove old stuff cleanup() { rm -rf $TARGETDIR/carla/ $TARGETDIR/carla32/ $TARGETDIR/carla64/ rm -rf cx_Freeze-* rm -rf Python-* rm -rf PyQt-* rm -rf PyQt5_* rm -rf file-* rm -rf flac-* rm -rf fltk-* rm -rf fluidsynth-* rm -rf fftw-* rm -rf gettext-* rm -rf glib-* rm -rf libffi-* rm -rf liblo-* rm -rf libogg-* rm -rf libsndfile-* rm -rf libvorbis-* rm -rf mxml-* rm -rf pkg-config-* rm -rf pyliblo-* rm -rf qtbase-* rm -rf qtmacextras-* rm -rf qtsvg-* rm -rf sip-* rm -rf zlib-* rm -rf PaxHeaders.* } # --------------------------------------------------------------------------------------------------------------------- # function to build base libs build_base() { export CC=clang export CXX=clang++ export PREFIX=${TARGETDIR}/carla${ARCH} export PATH=${PREFIX}/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin export PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig export CFLAGS="-O3 -mtune=generic -msse -msse2 -mfpmath=sse -fvisibility=hidden -fdata-sections -ffunction-sections" export CFLAGS="${CFLAGS} -fPIC -DPIC -DNDEBUG -I${PREFIX}/include -m${ARCH} -mmacosx-version-min=10.8" export CXXFLAGS="${CFLAGS} -fvisibility-inlines-hidden -stdlib=libc++" export LDFLAGS="-fdata-sections -ffunction-sections -Wl,-dead_strip -Wl,-dead_strip_dylibs" export LDFLAGS="${LDFLAGS} -L${PREFIX}/lib -m${ARCH} -stdlib=libc++" # --------------------------------------------------------------------------------------------------------------------- # pkgconfig if [ ! -d pkg-config-${PKG_CONFIG_VERSION} ]; then curl -O https://pkg-config.freedesktop.org/releases/pkg-config-${PKG_CONFIG_VERSION}.tar.gz tar -xf pkg-config-${PKG_CONFIG_VERSION}.tar.gz fi if [ ! -f pkg-config-${PKG_CONFIG_VERSION}_$ARCH/build-done ]; then cp -r pkg-config-${PKG_CONFIG_VERSION} pkg-config-${PKG_CONFIG_VERSION}_$ARCH cd pkg-config-${PKG_CONFIG_VERSION}_$ARCH ./configure --enable-indirect-deps --with-internal-glib --with-pc-path=$PKG_CONFIG_PATH --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # liblo if [ ! -d liblo-${LIBLO_VERSION} ]; then curl -L http://download.sourceforge.net/liblo/liblo-${LIBLO_VERSION}.tar.gz -o liblo-${LIBLO_VERSION}.tar.gz tar -xf liblo-${LIBLO_VERSION}.tar.gz fi if [ ! -f liblo-${LIBLO_VERSION}_$ARCH/build-done ]; then cp -r liblo-${LIBLO_VERSION} liblo-${LIBLO_VERSION}_$ARCH cd liblo-${LIBLO_VERSION}_$ARCH ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --enable-threads \ --disable-examples --disable-tools make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- if [ x"${ARCH}" = x"32" ]; then return fi # --------------------------------------------------------------------------------------------------------------------- # zlib if [ ! -d zlib-${ZLIB_VERSION} ]; then /opt/local/bin/aria2c https://github.com/madler/zlib/archive/v${ZLIB_VERSION}.tar.gz tar -xf zlib-${ZLIB_VERSION}.tar.gz fi if [ ! -f zlib-${ZLIB_VERSION}/build-done ]; then cd zlib-${ZLIB_VERSION} ./configure --static --prefix=${PREFIX} make make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # file/magic if [ ! -d file-${FILE_VERSION} ]; then curl -O ftp://ftp.astron.com/pub/file/file-${FILE_VERSION}.tar.gz tar -xf file-${FILE_VERSION}.tar.gz fi if [ ! -f file-${FILE_VERSION}/build-done ]; then cd file-${FILE_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # libogg if [ ! -d libogg-${LIBOGG_VERSION} ]; then curl -O https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-${LIBOGG_VERSION}.tar.gz tar -xf libogg-${LIBOGG_VERSION}.tar.gz fi if [ ! -f libogg-${LIBOGG_VERSION}/build-done ]; then cd libogg-${LIBOGG_VERSION} sed -i -e 's/__MACH__/__MACH_SKIP__/' include/ogg/os_types.h ./configure --enable-static --disable-shared --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # libvorbis if [ ! -d libvorbis-${LIBVORBIS_VERSION} ]; then curl -O https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-${LIBVORBIS_VERSION}.tar.gz tar -xf libvorbis-${LIBVORBIS_VERSION}.tar.gz fi if [ ! -f libvorbis-${LIBVORBIS_VERSION}/build-done ]; then cd libvorbis-${LIBVORBIS_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # flac if [ ! -d flac-${FLAC_VERSION} ]; then curl -O https://ftp.osuosl.org/pub/xiph/releases/flac/flac-${FLAC_VERSION}.tar.xz /opt/local/bin/7z x flac-${FLAC_VERSION}.tar.xz /opt/local/bin/7z x flac-${FLAC_VERSION}.tar fi if [ ! -f flac-${FLAC_VERSION}/build-done ]; then cd flac-${FLAC_VERSION} chmod +x configure install-sh ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --disable-cpplibs make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # libsndfile if [ ! -d libsndfile-${LIBSNDFILE_VERSION} ]; then curl -O http://www.mega-nerd.com/libsndfile/files/libsndfile-${LIBSNDFILE_VERSION}.tar.gz tar -xf libsndfile-${LIBSNDFILE_VERSION}.tar.gz fi if [ ! -f libsndfile-${LIBSNDFILE_VERSION}/build-done ]; then cd libsndfile-${LIBSNDFILE_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --disable-full-suite --disable-alsa --disable-sqlite make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # glib if [ ! -d glib-${GLIB_VERSION} ]; then /opt/local/bin/aria2c http://caesar.ftp.acc.umu.se/pub/GNOME/sources/glib/${GLIB_MVERSION}/glib-${GLIB_VERSION}.tar.xz /opt/local/bin/7z x glib-${GLIB_VERSION}.tar.xz /opt/local/bin/7z x glib-${GLIB_VERSION}.tar fi if [ ! -f glib-${GLIB_VERSION}/build-done ]; then cd glib-${GLIB_VERSION} if [ ! -f patched ]; then patch -p1 -i ../../patches/glib_skip-gettext.patch rm m4macros/glib-gettext.m4 touch patched fi chmod +x autogen.sh configure install-sh env PATH=/opt/local/bin:$PATH ./autogen.sh env PATH=/opt/local/bin:$PATH LDFLAGS="-L${PREFIX}/lib -m${ARCH}" \ ./configure --enable-static --disable-shared --prefix=${PREFIX} env PATH=/opt/local/bin:$PATH make ${MAKE_ARGS} -k || true touch gio/gio-querymodules gio/glib-compile-resources gio/gsettings gio/gdbus gio/gresource gio/gapplication touch gobject/gobject-query tests/gobject/performance tests/gobject/performance-threaded env PATH=/opt/local/bin:$PATH make touch ${PREFIX}/bin/gtester-report env PATH=/opt/local/bin:$PATH make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # fluidsynth if [ ! -d fluidsynth-${FLUIDSYNTH_VERSION} ]; then /opt/local/bin/aria2c https://github.com/FluidSynth/fluidsynth/archive/v${FLUIDSYNTH_VERSION}.tar.gz tar -xf fluidsynth-${FLUIDSYNTH_VERSION}.tar.gz fi if [ ! -f fluidsynth-${FLUIDSYNTH_VERSION}/build-done ]; then cd fluidsynth-${FLUIDSYNTH_VERSION} if [ ! -f patched ]; then patch -p1 -i ../../patches/fluidsynth-skip-drivers-build.patch touch patched fi sed -i -e 's/_init_lib_suffix "64"/_init_lib_suffix ""/' CMakeLists.txt /opt/local/bin/cmake . -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${PREFIX} -DBUILD_SHARED_LIBS=OFF \ -Denable-debug=OFF -Denable-profiling=OFF -Denable-ladspa=OFF -Denable-fpe-check=OFF -Denable-portaudio=OFF \ -Denable-trap-on-fpe=OFF -Denable-aufile=OFF -Denable-dbus=OFF -Denable-ipv6=OFF -Denable-jack=OFF \ -Denable-midishare=OFF -Denable-oss=OFF -Denable-pulseaudio=OFF -Denable-readline=OFF -Denable-ladcca=OFF \ -Denable-lash=OFF -Denable-alsa=OFF -Denable-coreaudio=OFF -Denable-coremidi=OFF -Denable-framework=OFF \ -Denable-floats=ON make ${MAKE_ARGS} -k || true touch src/fluidsynth make make install sed -i -e "s|-lfluidsynth|-lfluidsynth -lglib-2.0 -lgthread-2.0 -lsndfile -lFLAC -lvorbisenc -lvorbis -logg -lpthread -lm -liconv|" ${PREFIX}/lib/pkgconfig/fluidsynth.pc touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # mxml if [ ! -d mxml-${MXML_VERSION} ]; then /opt/local/bin/aria2c https://github.com/michaelrsweet/mxml/releases/download/v${MXML_VERSION}/mxml-${MXML_VERSION}.tar.gz tar -xf mxml-${MXML_VERSION}.tar.gz fi if [ ! -f mxml-${MXML_VERSION}/build-done ]; then cd mxml-${MXML_VERSION} ./configure --disable-shared --prefix=${PREFIX} make libmxml.a cp *.a ${PREFIX}/lib/ cp *.pc ${PREFIX}/lib/pkgconfig/ cp mxml.h ${PREFIX}/include/ touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # fftw3 (needs to be last as it modifies C[XX]FLAGS) if [ ! -d fftw-${FFTW3_VERSION} ]; then curl -O http://www.fftw.org/fftw-${FFTW3_VERSION}.tar.gz tar -xf fftw-${FFTW3_VERSION}.tar.gz fi if [ ! -f fftw-${FFTW3_VERSION}/build-done ]; then export CFLAGS="${CFLAGS} -ffast-math" export CXXFLAGS="${CXXFLAGS} -ffast-math" cd fftw-${FFTW3_VERSION} ./configure --enable-static --enable-sse2 --disable-shared --disable-debug --prefix=${PREFIX} make make install make clean ./configure --enable-static --enable-sse --enable-sse2 --enable-single --disable-shared --disable-debug --prefix=${PREFIX} make make install make clean touch build-done cd .. fi } # --------------------------------------------------------------------------------------------------------------------- # build base libs # cleanup export ARCH=32 build_base export ARCH=64 build_base # --------------------------------------------------------------------------------------------------------------------- # set flags for qt stuff export PREFIX=${TARGETDIR}/carla export PATH=${PREFIX}/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin export PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig export PKG_CONFIG=${TARGETDIR}/carla64/bin/pkg-config export CFLAGS="-O3 -mtune=generic -msse -msse2 -mfpmath=sse -fPIC -DPIC -DNDEBUG -I${PREFIX}/include -m64 -mmacosx-version-min=10.8" export CXXFLAGS="${CFLAGS} -std=gnu++11 -stdlib=libc++" export LDFLAGS="-L${PREFIX}/lib -m64 -stdlib=libc++" export MAKE=/usr/bin/make # --------------------------------------------------------------------------------------------------------------------- # qt5-base download if [ ! -d qtbase-opensource-src-${QT5_VERSION} ]; then curl -L http://download.qt.io/archive/qt/${QT5_MVERSION}/${QT5_VERSION}/submodules/qtbase-opensource-src-${QT5_VERSION}.tar.xz -o qtbase-opensource-src-${QT5_VERSION}.tar.xz /opt/local/bin/7z x qtbase-opensource-src-${QT5_VERSION}.tar.xz /opt/local/bin/7z x qtbase-opensource-src-${QT5_VERSION}.tar fi # --------------------------------------------------------------------------------------------------------------------- # qt5-base (64bit, shared, framework) if [ ! -f qtbase-opensource-src-${QT5_VERSION}/build-done ]; then cd qtbase-opensource-src-${QT5_VERSION} if [ ! -f configured ]; then if [ ! -f carla-patched ]; then #sed -i -e "s|PNG_WARNINGS_SUPPORTED|PNG_WARNINGS_NOT_SUPPORTED|" src/3rdparty/libpng/pnglibconf.h #sed -i -e "s|AWK=.*|AWK=/opt/local/bin/gawk|" configure #sed -i -e "s|/usr/bin/xcrun -find xcrun|true|" configure #sed -i -e "s|/usr/bin/xcrun -find xcrun|echo hello|" mkspecs/features/mac/default_pre.prf #patch -p1 -i ../../patches/qt55-newosx-fix.patch #patch -p1 -i ../../patches/qt56-cpp98-compat.patch patch -p1 -i ../../patches/qt59-osx10.8-compat.patch patch -p1 -i ../../patches/qt59-osx10.8-compat2.patch patch -p1 -i ../../patches/qt59-osx10.8-compat3.patch sed -i -e "s/10.10/10.8/" mkspecs/macx-clang/qmake.conf sed -i -e "s/ --sdk \$sdk / /" configure sed -i -e "s/ --sdk \$\$sdk / /" mkspecs/features/mac/sdk.prf touch carla-patched fi QT55_ARGS="./configure -release -shared -opensource -confirm-license -force-pkg-config -platform macx-clang -framework \ -prefix ${PREFIX} -plugindir ${PREFIX}/lib/qt5/plugins -headerdir ${PREFIX}/include/qt5 \ -qt-freetype -qt-libjpeg -qt-libpng -qt-pcre -opengl desktop -qpa cocoa \ -no-directfb -no-eglfs -no-kms -no-linuxfb -no-mtdev -no-xcb -no-xcb-xlib \ -no-sse3 -no-ssse3 -no-sse4.1 -no-sse4.2 -no-avx -no-avx2 -no-mips_dsp -no-mips_dspr2 \ -no-cups -no-dbus -no-evdev -no-fontconfig -no-harfbuzz -no-gif -no-glib -no-nis -no-openssl -no-pch -no-sql-ibase -no-sql-odbc \ -no-audio-backend -no-qml-debug -no-separate-debug-info -no-use-gold-linker \ -no-compile-examples -nomake examples -nomake tests -make libs -make tools " QT56_ARGS="./configure -prefix ${PREFIX} -plugindir ${PREFIX}/lib/qt5/plugins -headerdir ${PREFIX}/include/qt5 \ -release -optimized-tools -opensource -confirm-license -c++std c++98 -no-qml-debug -platform macx-clang \ -no-sse3 -no-ssse3 -no-sse4.1 -no-sse4.2 -no-avx -no-avx2 -no-mips_dsp -no-mips_dspr2 \ -pkg-config -force-pkg-config \ -no-mtdev -no-gif -qt-libpng -qt-libjpeg -qt-freetype \ -no-openssl -no-libproxy \ -qt-pcre -no-xcb -no-xkbcommon-x11 -no-xkbcommon-evdev -no-xinput2 -no-xcb-xlib -no-glib \ -no-pulseaudio -no-alsa -no-gtkstyle \ -make libs -make tools \ -nomake examples -nomake tests \ -no-compile-examples \ -no-cups -no-iconv -no-evdev -no-icu -no-fontconfig \ -no-dbus -no-xcb -no-eglfs -no-kms -no-gbm -no-directfb -no-linuxfb \ -qpa cocoa -opengl desktop -framework \ -no-audio-backend -no-pch " QT59_ARGS="./configure -silent -prefix ${PREFIX} -plugindir ${PREFIX}/lib/qt5/plugins -headerdir ${PREFIX}/include/qt5 \ -opensource -confirm-license -release -strip -shared -platform macx-clang \ -sse2 -no-sse3 -no-ssse3 -no-sse4.1 -no-sse4.2 -no-avx -no-avx2 -no-avx512 \ -no-mips_dsp -no-mips_dspr2 \ -no-pch -pkg-config -force-pkg-config \ -make libs -make tools \ -nomake examples -nomake tests \ -no-compile-examples \ -gui -widgets \ -no-dbus \ -no-glib -qt-pcre \ -no-journald -no-syslog -no-slog2 \ -no-openssl -no-securetransport -no-sctp -no-libproxy \ -no-cups -no-fontconfig -qt-freetype -no-harfbuzz -no-gtk -opengl desktop -qpa cocoa -no-xcb-xlib \ -no-directfb -no-eglfs -no-xcb \ -no-evdev -no-libinput -no-mtdev -no-xinput2 -no-xkbcommon-x11 -no-xkbcommon-evdev \ -no-gif -no-ico -qt-libpng -qt-libjpeg \ -qt-sqlite " chmod +x configure ${QT59_ARGS} #chmod -R 777 config.tests/unix/ touch configured fi make ${MAKE_ARGS} make install ln -s ${PREFIX}/lib/QtCore.framework/Headers ${PREFIX}/include/qt5/QtCore ln -s ${PREFIX}/lib/QtGui.framework/Headers ${PREFIX}/include/qt5/QtGui ln -s ${PREFIX}/lib/QtWidgets.framework/Headers ${PREFIX}/include/qt5/QtWidgets #sed -i -e "s/ -lqtpcre/ /" ${PREFIX}/lib/pkgconfig/Qt5Core.pc #sed -i -e "s/ '/ /" ${PREFIX}/lib/pkgconfig/Qt5Core.pc #sed -i -e "s/ '/ /" ${PREFIX}/lib/pkgconfig/Qt5Core.pc #sed -i -e "s/ '/ /" ${PREFIX}/lib/pkgconfig/Qt5Gui.pc #sed -i -e "s/ '/ /" ${PREFIX}/lib/pkgconfig/Qt5Gui.pc #sed -i -e "s/ '/ /" ${PREFIX}/lib/pkgconfig/Qt5Widgets.pc #sed -i -e "s/ '/ /" ${PREFIX}/lib/pkgconfig/Qt5Widgets.pc touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # qt5-mac-extras if [ ! -d qtmacextras-opensource-src-${QT5_VERSION} ]; then curl -L http://download.qt.io/archive/qt/${QT5_MVERSION}/${QT5_VERSION}/submodules/qtmacextras-opensource-src-${QT5_VERSION}.tar.xz -o qtmacextras-opensource-src-${QT5_VERSION}.tar.xz /opt/local/bin/7z x qtmacextras-opensource-src-${QT5_VERSION}.tar.xz /opt/local/bin/7z x qtmacextras-opensource-src-${QT5_VERSION}.tar fi if [ ! -f qtmacextras-opensource-src-${QT5_VERSION}/build-done ]; then cd qtmacextras-opensource-src-${QT5_VERSION} qmake make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # qt5-svg if [ ! -d qtsvg-opensource-src-${QT5_VERSION} ]; then curl -L http://download.qt.io/archive/qt/${QT5_MVERSION}/${QT5_VERSION}/submodules/qtsvg-opensource-src-${QT5_VERSION}.tar.xz -o qtsvg-opensource-src-${QT5_VERSION}.tar.xz /opt/local/bin/7z x qtsvg-opensource-src-${QT5_VERSION}.tar.xz /opt/local/bin/7z x qtsvg-opensource-src-${QT5_VERSION}.tar fi if [ ! -f qtsvg-opensource-src-${QT5_VERSION}/build-done ]; then cd qtsvg-opensource-src-${QT5_VERSION} qmake make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # python if [ ! -d Python-${PYTHON_VERSION} ]; then /opt/local/bin/aria2c https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz tar -xf Python-${PYTHON_VERSION}.tgz fi if [ ! -f Python-${PYTHON_VERSION}/build-done ]; then cd Python-${PYTHON_VERSION} sed -i -e "s/#zlib zlibmodule.c/zlib zlibmodule.c/" Modules/Setup.dist ./configure --prefix=${PREFIX} --enable-shared make make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # sip if [ ! -d sip-${SIP_VERSION} ]; then /opt/local/bin/aria2c http://sourceforge.net/projects/pyqt/files/sip/sip-${SIP_VERSION}/sip-${SIP_VERSION}.tar.gz tar -xf sip-${SIP_VERSION}.tar.gz fi if [ ! -f sip-${SIP_VERSION}/build-done ]; then cd sip-${SIP_VERSION} python3 configure.py # --sip-module PyQt5.sip make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # pyqt5 if [ ! -d PyQt5_gpl-${PYQT5_VERSION} ]; then /opt/local/bin/aria2c http://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-${PYQT5_VERSION}/PyQt5_gpl-${PYQT5_VERSION}.tar.gz tar -xf PyQt5_gpl-${PYQT5_VERSION}.tar.gz fi if [ ! -f PyQt5_gpl-${PYQT5_VERSION}/build-done ]; then cd PyQt5_gpl-${PYQT5_VERSION} python3 configure.py --concatenate --confirm-license -c make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # pyliblo if [ ! -d pyliblo-${PYLIBLO_VERSION} ]; then /opt/local/bin/aria2c http://das.nasophon.de/download/pyliblo-${PYLIBLO_VERSION}.tar.gz tar -xf pyliblo-${PYLIBLO_VERSION}.tar.gz fi if [ ! -f pyliblo-${PYLIBLO_VERSION}/build-done ]; then cd pyliblo-${PYLIBLO_VERSION} if [ ! -f patched ]; then patch -p1 -i ../../patches/pyliblo-python3.7.patch touch patched fi env CFLAGS="${CFLAGS} -I${TARGETDIR}/carla64/include" LDFLAGS="${LDFLAGS} -L${TARGETDIR}/carla64/lib" \ python3 setup.py build python3 setup.py install --prefix=${PREFIX} touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # cxfreeze if [ ! -d cx_Freeze-${CXFREEZE_VERSION} ]; then /opt/local/bin/aria2c https://github.com/anthony-tuininga/cx_Freeze/archive/${CXFREEZE_VERSION}.tar.gz tar -xf cx_Freeze-${CXFREEZE_VERSION}.tar.gz fi if [ ! -f cx_Freeze-${CXFREEZE_VERSION}/build-done ]; then cd cx_Freeze-${CXFREEZE_VERSION} #sed -i -e 's/"python%s.%s"/"python%s.%sm"/' setup.py python3 setup.py build python3 setup.py install --prefix=${PREFIX} touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/data/macos/build.sh000077500000000000000000000253271364475620200160710ustar00rootroot00000000000000#!/bin/bash # ------------------------------------------------------------------------------------ # stop on error set -e # ------------------------------------------------------------------------------------ # cd to correct path if [ ! -f Makefile ]; then cd ../.. fi # --------------------------------------------------------------------------------------------------------------------- # set variables PKG_FOLDER="Carla_2.1-macos" source data/macos/common.env if [ $(clang -v 2>&1 | grep version | cut -d' ' -f4 | cut -d'.' -f1) -lt 11 ]; then export MACOS_VERSION_MIN="10.8" else export MACOS_VERSION_MIN="10.12" fi export MACOS="true" export USING_JUCE="true" export CC=clang export CXX=clang++ unset CPPFLAGS ############################################################################################## # Complete 64bit build export CFLAGS="-I${TARGETDIR}/carla64/include -m64 -mmacosx-version-min=${MACOS_VERSION_MIN}" export CXXFLAGS="${CFLAGS} -stdlib=libc++" export LDFLAGS="-L${TARGETDIR}/carla64/lib -m64 -mmacosx-version-min=${MACOS_VERSION_MIN} -stdlib=libc++" export PATH=${TARGETDIR}/carla/bin:${TARGETDIR}/carla64/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin export PKG_CONFIG_PATH=${TARGETDIR}/carla/lib/pkgconfig:${TARGETDIR}/carla64/lib/pkgconfig export MOC_QT5=moc export RCC_QT5=rcc export UIC_QT5=uic make USING_JUCE=${USING_JUCE} ${MAKE_ARGS} ############################################################################################## # Build 32bit bridges if [ "${MACOS_VERSION_MIN}" != "10.12" ]; then export CFLAGS="-I${TARGETDIR}/carla32/include -m32 -mmacosx-version-min=${MACOS_VERSION_MIN}" export CXXFLAGS="${CFLAGS} -stdlib=libc++" export LDFLAGS="-L${TARGETDIR}/carla32/lib -m32 -mmacosx-version-min=${MACOS_VERSION_MIN} -stdlib=libc++" export PATH=${TARGETDIR}/carla32/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin export PKG_CONFIG_PATH=${TARGETDIR}/carla32/lib/pkgconfig make USING_JUCE=${USING_JUCE} posix32 ${MAKE_ARGS} fi ############################################################################################## # Build Mac App export PATH=${TARGETDIR}/carla/bin:${TARGETDIR}/carla64/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin export PYTHONPATH=$(pwd)/source/frontend unset CFLAGS unset CXXFLAGS unset LDLAGS unset PKG_CONFIG_PATH rm -rf ./build/Carla rm -rf ./build/CarlaControl rm -rf ./build/Carla.app rm -rf ./build/CarlaControl.app rm -rf ./build/exe.* rm -rf ./build/*.lv2 rm -rf ./build/*.vst cp ./source/frontend/carla ./source/frontend/Carla.pyw cp ./source/frontend/carla-control ./source/frontend/Carla-Control.pyw cp ./source/frontend/carla-plugin ./source/frontend/carla-plugin.pyw cp ./source/frontend/bigmeter-ui ./source/frontend/bigmeter-ui.pyw cp ./source/frontend/midipattern-ui ./source/frontend/midipattern-ui.pyw cp ./source/frontend/notes-ui ./source/frontend/notes-ui.pyw env SCRIPT_NAME=Carla python3 ./data/macos/bundle.py bdist_mac --bundle-name=Carla env SCRIPT_NAME=Carla-Control python3 ./data/macos/bundle.py bdist_mac --bundle-name=Carla-Control env SCRIPT_NAME=carla-plugin python3 ./data/macos/bundle.py bdist_mac --bundle-name=carla-plugin env SCRIPT_NAME=bigmeter-ui python3 ./data/macos/bundle.py bdist_mac --bundle-name=bigmeter-ui env SCRIPT_NAME=midipattern-ui python3 ./data/macos/bundle.py bdist_mac --bundle-name=midipattern-ui env SCRIPT_NAME=notes-ui python3 ./data/macos/bundle.py bdist_mac --bundle-name=notes-ui rm ./source/frontend/*.pyw mkdir -p build/Carla.app/Contents/MacOS/resources mkdir -p build/Carla.app/Contents/MacOS/styles mkdir -p build/Carla-Control.app/Contents/MacOS/styles cp bin/*carla*.dylib build/Carla.app/Contents/MacOS/ cp bin/carla-bridge-* build/Carla.app/Contents/MacOS/ cp bin/carla-discovery-* build/Carla.app/Contents/MacOS/ cp bin/styles/* build/Carla.app/Contents/MacOS/styles/ cp bin/*utils.dylib build/Carla-Control.app/Contents/MacOS/ cp bin/styles/* build/Carla-Control.app/Contents/MacOS/styles/ rm -f build/Carla.app/Contents/MacOS/carla-bridge-lv2-modgui rm -f build/Carla.app/Contents/MacOS/carla-bridge-lv2-qt5 find build/ -type f -name "*.py" -delete find build/ -type f -name "*.pyc" -delete find build/ -type f -name "*.pyi" -delete find build/ -type f -name "pylupdate.so" -delete find build/ -type f -name "pyrcc.so" -delete find build/ -type f -name "QtMacExtras*" -delete find build/ -type f -name "QtNetwork*" -delete find build/ -type f -name "QtSql*" -delete find build/ -type f -name "QtTest*" -delete find build/ -type f -name "QtXml*" -delete rm -rf build/Carla.app/Contents/MacOS/lib/PyQt5/uic rm -rf build/Carla.app/Contents/MacOS/resources/__pycache__ rm -rf build/Carla.app/Contents/MacOS/resources/patchcanvas rm -rf build/Carla.app/Contents/MacOS/resources/widgets rm -rf build/Carla.app/Contents/MacOS/resources/zynaddsubfx rm -rf build/Carla-Control.app/Contents/MacOS/resources/__pycache__ # missed by cx-freeze mkdir build/Carla.app/Contents/MacOS/iconengines cp ${TARGETDIR}/carla/lib/qt5/plugins/iconengines/libqsvgicon.dylib build/Carla.app/Contents/MacOS/iconengines/ # continuing... cd build/Carla.app/Contents/MacOS for f in `find . -type f | grep -e Q -e libq -e carlastyle.dylib`; do install_name_tool -change "@rpath/QtCore.framework/Versions/5/QtCore" @executable_path/QtCore $f install_name_tool -change "@rpath/QtGui.framework/Versions/5/QtGui" @executable_path/QtGui $f install_name_tool -change "@rpath/QtOpenGL.framework/Versions/5/QtOpenGL" @executable_path/QtOpenGL $f install_name_tool -change "@rpath/QtPrintSupport.framework/Versions/5/QtPrintSupport" @executable_path/QtPrintSupport $f install_name_tool -change "@rpath/QtSvg.framework/Versions/5/QtSvg" @executable_path/QtSvg $f install_name_tool -change "@rpath/QtWidgets.framework/Versions/5/QtWidgets" @executable_path/QtWidgets $f install_name_tool -change "@rpath/QtMacExtras.framework/Versions/5/QtMacExtras" @executable_path/QtMacExtras $f done cd ../../../.. cd build/Carla-Control.app/Contents/MacOS for f in `find . -type f | grep -e Q -e libq -e carlastyle.dylib`; do install_name_tool -change "@rpath/QtCore.framework/Versions/5/QtCore" @executable_path/QtCore $f install_name_tool -change "@rpath/QtGui.framework/Versions/5/QtGui" @executable_path/QtGui $f install_name_tool -change "@rpath/QtOpenGL.framework/Versions/5/QtOpenGL" @executable_path/QtOpenGL $f install_name_tool -change "@rpath/QtPrintSupport.framework/Versions/5/QtPrintSupport" @executable_path/QtPrintSupport $f install_name_tool -change "@rpath/QtSvg.framework/Versions/5/QtSvg" @executable_path/QtSvg $f install_name_tool -change "@rpath/QtWidgets.framework/Versions/5/QtWidgets" @executable_path/QtWidgets $f install_name_tool -change "@rpath/QtMacExtras.framework/Versions/5/QtMacExtras" @executable_path/QtMacExtras $f done cd ../../../.. mv build/carla-plugin.app/Contents/MacOS/carla-plugin build/Carla.app/Contents/MacOS/resources/ mv build/bigmeter-ui.app/Contents/MacOS/bigmeter-ui build/Carla.app/Contents/MacOS/resources/ mv build/midipattern-ui.app/Contents/MacOS/midipattern-ui build/Carla.app/Contents/MacOS/resources/ mv build/notes-ui.app/Contents/MacOS/notes-ui build/Carla.app/Contents/MacOS/resources/ mv build/Carla.app/Contents/MacOS/lib/library.zip build/Carla.app/Contents/MacOS/lib/library-carla1.zip mv build/carla-plugin.app/Contents/MacOS/lib/library.zip build/Carla.app/Contents/MacOS/lib/library-carla2.zip mv build/bigmeter-ui.app/Contents/MacOS/lib/library.zip build/Carla.app/Contents/MacOS/lib/library-bigmeter.zip mv build/midipattern-ui.app/Contents/MacOS/lib/library.zip build/Carla.app/Contents/MacOS/lib/library-midipattern.zip mv build/notes-ui.app/Contents/MacOS/lib/library.zip build/Carla.app/Contents/MacOS/lib/library-notes.zip mkdir build/Carla.app/Contents/MacOS/lib/_lib pushd build/Carla.app/Contents/MacOS/lib/_lib unzip -o ../library-bigmeter.zip unzip -o ../library-midipattern.zip unzip -o ../library-notes.zip unzip -o ../library-carla2.zip unzip -o ../library-carla1.zip zip -r -9 ../library.zip * popd rm -r build/Carla.app/Contents/MacOS/lib/_lib build/Carla.app/Contents/MacOS/lib/library-*.zip rm -rf build/carla-plugin.app build/bigmeter-ui.app build/midipattern-ui.app build/notes-ui.app cd build/Carla.app/Contents/MacOS/resources/ ln -sf ../Qt* ../lib ../iconengines ../imageformats ../platforms ../styles . ln -sf carla-plugin carla-plugin-patchbay cd ../../../../.. mkdir build/carla.lv2 mkdir build/carla.lv2/resources mkdir build/carla.lv2/styles cp bin/carla.lv2/*.* build/carla.lv2/ cp bin/carla-bridge-* build/carla.lv2/ cp bin/carla-discovery-* build/carla.lv2/ cp bin/libcarla_utils.dylib build/carla.lv2/ rm -f build/carla.lv2/carla-bridge-lv2-modgui rm -f build/carla.lv2/carla-bridge-lv2-qt5 cp -LR build/Carla.app/Contents/MacOS/resources/* build/carla.lv2/resources/ cp build/Carla.app/Contents/MacOS/styles/* build/carla.lv2/styles/ ./data/macos/generate-vst-bundles.sh mv bin/CarlaVstShell.vst build/carla.vst mv bin/CarlaVstFxShell.vst build/carlafx.vst rm -rf bin/*.vst mkdir build/carla.vst/Contents/MacOS/resources mkdir build/carla.vst/Contents/MacOS/styles mkdir build/carlafx.vst/Contents/MacOS/resources mkdir build/carlafx.vst/Contents/MacOS/styles cp bin/carla-bridge-* build/carla.vst/Contents/MacOS/ cp bin/carla-discovery-* build/carla.vst/Contents/MacOS/ cp bin/libcarla_utils.dylib build/carla.vst/Contents/MacOS/ rm -f build/carla.vst/carla-bridge-lv2-modgui rm -f build/carla.vst/carla-bridge-lv2-qt5 cp -LR build/Carla.app/Contents/MacOS/resources/* build/carla.vst/Contents/MacOS/resources/ cp build/Carla.app/Contents/MacOS/styles/* build/carla.vst/Contents/MacOS/styles/ cp bin/carla-bridge-* build/carlafx.vst/Contents/MacOS/ cp bin/carla-discovery-* build/carlafx.vst/Contents/MacOS/ cp bin/libcarla_utils.dylib build/carlafx.vst/Contents/MacOS/ rm -f build/carlafx.vst/carla-bridge-lv2-modgui rm -f build/carlafx.vst/carla-bridge-lv2-qt5 cp -LR build/Carla.app/Contents/MacOS/resources/* build/carlafx.vst/Contents/MacOS/resources/ cp build/Carla.app/Contents/MacOS/styles/* build/carlafx.vst/Contents/MacOS/styles/ ############################################################################################## rm -rf ${PKG_FOLDER} mkdir ${PKG_FOLDER} cp data/macos/README ${PKG_FOLDER}/ mv build/carla.lv2 ${PKG_FOLDER}/ mv build/carla.vst ${PKG_FOLDER}/ mv build/carlafx.vst ${PKG_FOLDER}/ mv build/Carla.app ${PKG_FOLDER}/ mv build/Carla-Control.app ${PKG_FOLDER}/ ############################################################################################## Carla-2.1/data/macos/bundle.py000066400000000000000000000020771364475620200162530ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------------------------------------ # Imports (cx_Freeze) from cx_Freeze import setup, Executable from os import getenv # ------------------------------------------------------------------------------------------------------------ # Imports (Custom Stuff) from carla_host import VERSION # ------------------------------------------------------------------------------------------------------------ options = { "zip_include_packages": ["*"], "zip_exclude_packages": ["PyQt5"], "replace_paths": [["*","@executable_path/"]], "optimize": True, } boptions = { "iconfile": "./resources/ico/carla.icns" } setup(name = "Carla", version = VERSION, description = "Carla Plugin Host", options = {"build_exe": options, "bdist_mac": boptions}, executables = [Executable("./source/frontend/%s.pyw" % getenv("SCRIPT_NAME"))]) # ------------------------------------------------------------------------------------------------------------ Carla-2.1/data/macos/common.env000066400000000000000000000011461364475620200164260ustar00rootroot00000000000000#!/bin/bash PKG_CONFIG_VERSION=0.28 LIBLO_VERSION=0.30 ZLIB_VERSION=1.2.11 FILE_VERSION=5.34 LIBOGG_VERSION=1.3.4 LIBVORBIS_VERSION=1.3.6 FLAC_VERSION=1.3.2 LIBSNDFILE_VERSION=1.0.28 GLIB_VERSION=2.44.1 GLIB_MVERSION=2.44 FLUIDSYNTH_VERSION=1.1.11 MXML_VERSION=2.12 FFTW3_VERSION=3.3.8 PYTHON_VERSION=3.7.4 PYLIBLO_VERSION=0.9.2 CXFREEZE_VERSION=6.1 if [ -n "$DEPS_NEW" ]; then QT5_VERSION=5.12.5 QT5_MVERSION=5.12 PYQT5_VERSION=5.13.1 SIP_VERSION=4.19.19 else QT5_VERSION=5.9.8 QT5_MVERSION=5.9 SIP_VERSION=4.19.13 PYQT5_VERSION=5.9.2 fi MAKE_ARGS="-j 2" TARGETDIR=$HOME/builds Carla-2.1/data/macos/env.sh000066400000000000000000000015451364475620200155530ustar00rootroot00000000000000#!/bin/bash ############################################################################################## # MacOS X default environment for Carla source data/macos/common.env if [ $(clang -v 2>&1 | grep version | cut -d' ' -f4 | cut -d'.' -f1) -lt 11 ]; then export MACOS_VERSION_MIN="10.8" else export MACOS_VERSION_MIN="10.12" fi export CC=clang export CXX=clang++ export CFLAGS="-I${TARGETDIR}/carla64/include -m64 -mmacosx-version-min=${MACOS_VERSION_MIN}" export CXXFLAGS="${CFLAGS} -stdlib=libc++" export LDFLAGS="-L${TARGETDIR}/carla64/lib -m64 -stdlib=libc++" unset CPPFLAGS export MACOS="true" export PATH=${TARGETDIR}/carla/bin:${TARGETDIR}/carla64/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin export PKG_CONFIG_PATH=${TARGETDIR}/carla/lib/pkgconfig:${TARGETDIR}/carla64/lib/pkgconfig export MOC_QT5=moc export RCC_QT5=rcc export UIC_QT5=uic Carla-2.1/data/macos/generate-vst-bundles.sh000077500000000000000000000007711364475620200210240ustar00rootroot00000000000000#!/bin/bash set -e if [ -d bin ]; then cd bin else echo "Please run this script from the root folder" exit fi rm -rf *.vst/ PLUGINS=$(ls | grep "Carla" | grep "dylib") for i in ${PLUGINS}; do FILE=$(echo $i | awk 'sub(".dylib","")') cp -r ../data/macos/plugin.vst ${FILE}.vst cp $i ${FILE}.vst/Contents/MacOS/${FILE} rm -f ${FILE}.vst/Contents/MacOS/deleteme sed -i -e "s/X-PROJECTNAME-X/${FILE}/" ${FILE}.vst/Contents/Info.plist rm -f ${FILE}.vst/Contents/Info.plist-e done cd .. Carla-2.1/data/macos/mac-build-test.sh000077500000000000000000000006241364475620200175750ustar00rootroot00000000000000#!/bin/bash set -e export MACOS_OLD=true export CROSS_COMPILING=true _FLAGS="-mmacosx-version-min=10.6 -Wno-attributes -Wno-deprecated-declarations -Werror" export CFLAGS="${_FLAGS} -m32" export CXXFLAGS="${_FLAGS} -m32" export LDFLAGS="-m32" apple-cross-setup make -j4 export CFLAGS="${_FLAGS} -m64" export CXXFLAGS="${_FLAGS} -m64" export LDFLAGS="-m64" # FIXME apple-cross-setup make posix64 -j4 Carla-2.1/data/macos/plugin.vst/000077500000000000000000000000001364475620200165335ustar00rootroot00000000000000Carla-2.1/data/macos/plugin.vst/Contents/000077500000000000000000000000001364475620200203305ustar00rootroot00000000000000Carla-2.1/data/macos/plugin.vst/Contents/Info.plist000066400000000000000000000015151364475620200223020ustar00rootroot00000000000000 CFBundleDevelopmentRegion English CFBundleExecutable X-PROJECTNAME-X CFBundleIconFile CFBundleIdentifier net.sf.distrho.X-PROJECTNAME-X CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleSignature ???? CFBundleVersion 1.0 CSResourcesFileMapped Carla-2.1/data/macos/plugin.vst/Contents/MacOS/000077500000000000000000000000001364475620200212725ustar00rootroot00000000000000Carla-2.1/data/macos/plugin.vst/Contents/MacOS/deleteme000066400000000000000000000000021364475620200227710ustar00rootroot00000000000000 Carla-2.1/data/macos/plugin.vst/Contents/PkgInfo000066400000000000000000000000111364475620200216000ustar00rootroot00000000000000BNDL???? Carla-2.1/data/macos/plugin.vst/Contents/Resources/000077500000000000000000000000001364475620200223025ustar00rootroot00000000000000Carla-2.1/data/macos/plugin.vst/Contents/Resources/empty.lproj000066400000000000000000000000001364475620200244760ustar00rootroot00000000000000Carla-2.1/data/patches/000077500000000000000000000000001364475620200147475ustar00rootroot00000000000000Carla-2.1/data/patches/cxfreeze-py37.patch000066400000000000000000000026331364475620200204070ustar00rootroot00000000000000From 76542754e01d2d4b21c6744c563dda8d5c72b3b2 Mon Sep 17 00:00:00 2001 From: egormartiniuc Date: Tue, 3 Jul 2018 16:38:06 +0200 Subject: [PATCH] Update freezer.py python 3.7.0 64Bit --- cx_Freeze/freezer.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cx_Freeze/freezer.py b/cx_Freeze/freezer.py index 27a78c2..cfcc3b4 100644 --- a/cx_Freeze/freezer.py +++ b/cx_Freeze/freezer.py @@ -555,10 +555,16 @@ def _WriteModules(self, fileName, finder): # the file is up to date so we can safely set this value to zero if module.code is not None: if module.file is not None and os.path.exists(module.file): - mtime = os.stat(module.file).st_mtime + stat = os.stat(module.file) + mtime = stat.st_mtime + size = stat.st_size & 0xFFFFFFFF else: mtime = time.time() - header = magic + struct.pack(" #include +#define ngettext(t1, t2, n) t1 + /** * SECTION:gunixconnection * @title: GUnixConnection diff --git a/glib/ggettext.c b/glib/ggettext.c index bf74ccb..2430a0d 100644 --- a/glib/ggettext.c +++ b/glib/ggettext.c @@ -40,7 +40,6 @@ #include #include -#include #ifdef G_OS_WIN32 diff --git a/glib/gi18n.h b/glib/gi18n.h index f765c3d..2c950cd 100644 --- a/glib/gi18n.h +++ b/glib/gi18n.h @@ -20,13 +20,13 @@ #include -#include #include -#define _(String) gettext (String) -#define Q_(String) g_dpgettext (NULL, String, 0) +#define _(String) String #define N_(String) (String) -#define C_(Context,String) g_dpgettext (NULL, Context "\004" String, strlen (Context) + 1) #define NC_(Context, String) (String) +#define textdomain(...) +#define bindtextdomain(...) + #endif /* __G_I18N_H__ */ diff --git a/m4macros/Makefile.am b/m4macros/Makefile.am index 971871c..8a4f40c 100644 --- a/m4macros/Makefile.am +++ b/m4macros/Makefile.am @@ -1,6 +1,6 @@ include $(top_srcdir)/glib.mk -installed_m4= glib-2.0.m4 glib-gettext.m4 gsettings.m4 +installed_m4= glib-2.0.m4 gsettings.m4 EXTRA_DIST+=$(installed_m4) Carla-2.1/data/patches/pyliblo-python3.7.patch000066400000000000000000000042661364475620200212210ustar00rootroot00000000000000diff --git a/src/liblo.c b/src/liblo.c index bb314a5..6535baf 100644 --- a/src/liblo.c +++ b/src/liblo.c @@ -13882,12 +13882,12 @@ static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) *value = local_value; *tb = local_tb; #if CYTHON_COMPILING_IN_CPYTHON - tmp_type = tstate->exc_type; - tmp_value = tstate->exc_value; - tmp_tb = tstate->exc_traceback; - tstate->exc_type = local_type; - tstate->exc_value = local_value; - tstate->exc_traceback = local_tb; + tmp_type = tstate->exc_state.exc_type; + tmp_value = tstate->exc_state.exc_value; + tmp_tb = tstate->exc_state.exc_traceback; + tstate->exc_state.exc_type = local_type; + tstate->exc_state.exc_value = local_value; + tstate->exc_state.exc_traceback = local_tb; /* Make sure tstate is in a consistent state when we XDECREF these objects (DECREF may run arbitrary code). */ Py_XDECREF(tmp_type); @@ -13927,9 +13927,9 @@ bad: static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) { #if CYTHON_COMPILING_IN_CPYTHON PyThreadState *tstate = PyThreadState_GET(); - *type = tstate->exc_type; - *value = tstate->exc_value; - *tb = tstate->exc_traceback; + *type = tstate->exc_state.exc_type; + *value = tstate->exc_state.exc_value; + *tb = tstate->exc_state.exc_traceback; Py_XINCREF(*type); Py_XINCREF(*value); Py_XINCREF(*tb); @@ -13941,12 +13941,12 @@ static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) #if CYTHON_COMPILING_IN_CPYTHON PyObject *tmp_type, *tmp_value, *tmp_tb; PyThreadState *tstate = PyThreadState_GET(); - tmp_type = tstate->exc_type; - tmp_value = tstate->exc_value; - tmp_tb = tstate->exc_traceback; - tstate->exc_type = type; - tstate->exc_value = value; - tstate->exc_traceback = tb; + tmp_type = tstate->exc_state.exc_type; + tmp_value = tstate->exc_state.exc_value; + tmp_tb = tstate->exc_state.exc_traceback; + tstate->exc_state.exc_type = type; + tstate->exc_state.exc_value = value; + tstate->exc_state.exc_traceback = tb; Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); Carla-2.1/data/patches/qt55-newosx-fix.patch000066400000000000000000000072741364475620200207050ustar00rootroot00000000000000From 0707260a4f8e64dfadf1df5f935e74cabb7c7d27 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Sun, 1 Oct 2017 21:48:17 -0700 Subject: [PATCH] Fix build error with macOS 10.13 SDK MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Several of these variables/macros are no longer defined. We didn't validate the preconditions on iOS, tvOS, or watchOS, so no need to bother validating them on macOS either. Nor did we check the OSStatus result on any platform anyways. Task-number: QTBUG-63401 Change-Id: Ife64dff767cf6d3f4b839fc53ec486181c176bf3 (cherry-picked from 861544583511d4e6f7745d2339b26ff1cd44132b) Reviewed-by: Timur Pocheptsov Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoahelpers.h | 2 +- src/plugins/platforms/cocoa/qcocoahelpers.mm | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index bbb3793..74371d5 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -80,7 +80,7 @@ QColor qt_mac_toQColor(CGColorRef color); // Creates a mutable shape, it's the caller's responsibility to release. HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion ®ion); -OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage); +void qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage); NSDragOperation qt_mac_mapDropAction(Qt::DropAction action); NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions); diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index cd73148..3f8429e 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -544,15 +544,8 @@ NSRect qt_mac_flipRect(const QRect &rect) return NSMakeRect(rect.x(), flippedY, rect.width(), rect.height()); } -OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage) +void qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage) { - // Verbatim copy if HIViewDrawCGImage (as shown on Carbon-Dev) - OSStatus err = noErr; - - require_action(inContext != NULL, InvalidContext, err = paramErr); - require_action(inBounds != NULL, InvalidBounds, err = paramErr); - require_action(inImage != NULL, InvalidImage, err = paramErr); - CGContextSaveGState( inContext ); CGContextTranslateCTM (inContext, 0, inBounds->origin.y + CGRectGetMaxY(*inBounds)); CGContextScaleCTM(inContext, 1, -1); @@ -560,10 +553,6 @@ OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGIm CGContextDrawImage(inContext, *inBounds, inImage); CGContextRestoreGState(inContext); -InvalidImage: -InvalidBounds: -InvalidContext: - return err; } Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) -- 2.7.4 diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 7e1dfd9..674c037 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -736,7 +736,7 @@ void QCoreTextFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, gl QFixed QCoreTextFontEngine::emSquareSize() const { - return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont))); + return QFixed(int(CTFontGetUnitsPerEm(ctfont))); } QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const Carla-2.1/data/patches/qt56-cpp98-compat.patch000066400000000000000000000020601364475620200210070ustar00rootroot00000000000000diff --git a/qcocoawindow.mm b/qcocoawindow.mm index 0e5655f..6ab3a21 100644 --- a/qcocoawindow.mm +++ b/qcocoawindow.mm @@ -272,7 +272,7 @@ static bool isMouseEvent(NSEvent *ev) + (void)applicationActivationChanged:(NSNotification*)notification { const id sender = self; - NSEnumerator *windowEnumerator = nullptr; + NSEnumerator *windowEnumerator = Q_NULLPTR; NSApplication *application = [NSApplication sharedApplication]; #if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) @@ -313,7 +313,7 @@ static bool isMouseEvent(NSEvent *ev) continue; if ([window conformsToProtocol:@protocol(QNSWindowProtocol)]) { - QCocoaWindow *cocoaWindow = static_cast>(window).helper.platformWindow; + QCocoaWindow *cocoaWindow = static_cast< id >(window).helper.platformWindow; window.level = notification.name == NSApplicationWillResignActiveNotification ? NSNormalWindowLevel : cocoaWindow->windowLevel(cocoaWindow->window()->flags()); } Carla-2.1/data/patches/qt59-osx10.8-compat.patch000066400000000000000000000444061364475620200212010ustar00rootroot00000000000000diff --git a/mkspecs/common/clang-mac.conf b/mkspecs/common/clang-mac.conf index cbae2e62..dc4694fa 100644 --- a/mkspecs/common/clang-mac.conf +++ b/mkspecs/common/clang-mac.conf @@ -10,4 +10,5 @@ QMAKE_CXXFLAGS += -stdlib=libc++ QMAKE_LFLAGS += -stdlib=libc++ QMAKE_AR_LTCG = libtool -static -o -QMAKE_CFLAGS_APPLICATION_EXTENSION = -fapplication-extension +QMAKE_CFLAGS_APPLICATION_EXTENSION = +# -fapplication-extension diff --git a/src/corelib/global/qoperatingsystemversion_darwin.mm b/src/corelib/global/qoperatingsystemversion_darwin.mm index d8b927ff..9a690adc 100644 --- a/src/corelib/global/qoperatingsystemversion_darwin.mm +++ b/src/corelib/global/qoperatingsystemversion_darwin.mm @@ -40,16 +40,37 @@ #include "qoperatingsystemversion_p.h" #import +typedef qint16 (*GestaltFunction)(quint32 selector, qint32 *response); + QT_BEGIN_NAMESPACE QOperatingSystemVersion QOperatingSystemVersion::current() { - NSOperatingSystemVersion osv = NSProcessInfo.processInfo.operatingSystemVersion; QOperatingSystemVersion v; v.m_os = currentType(); - v.m_major = osv.majorVersion; - v.m_minor = osv.minorVersion; - v.m_micro = osv.patchVersion; + v.m_major = -1; + v.m_minor = -1; + v.m_micro = -1; + static GestaltFunction pGestalt = 0; + if (!pGestalt) { + CFBundleRef b = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreServices")); + pGestalt = reinterpret_cast(CFBundleGetFunctionPointerForName(b, + CFSTR("Gestalt"))); + } + // Use temporary variables so we can return 0.0.0 (unknown version) + // in case of an error partway through determining the OS version + qint32 major = 0, minor = 0, patch = 0; + if (!pGestalt) + return v; + if (pGestalt('sys1', &major) != 0) + return v; + if (pGestalt('sys2', &minor) != 0) + return v; + if (pGestalt('sys3', &patch) != 0) + return v; + v.m_major = major; + v.m_minor = minor; + v.m_micro = patch; return v; } diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 7fed54f7..bbf5e6d6 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -126,8 +126,11 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e #ifdef Q_OS_MACOS // Find if an application other than Finder claims to know how to handle the package - QCFType application = LSCopyDefaultApplicationURLForURL(url, - kLSRolesEditor | kLSRolesViewer, nullptr); + QCFType application; + LSGetApplicationForURL(url, + kLSRolesEditor|kLSRolesViewer, + NULL, + &application); if (application) { QCFType bundle = CFBundleCreate(kCFAllocatorDefault, application); diff --git a/src/corelib/kernel/qcore_foundation.mm b/src/corelib/kernel/qcore_foundation.mm index 56eabc4b..c48a7979 100644 --- a/src/corelib/kernel/qcore_foundation.mm +++ b/src/corelib/kernel/qcore_foundation.mm @@ -46,7 +46,7 @@ #include #include -#if QT_CONFIG(timezone) && !defined(QT_NO_SYSTEMLOCALE) +#if 0 #include #include #include @@ -433,7 +433,7 @@ NSDate *QDateTime::toNSDate() const // ---------------------------------------------------------------------------- -#if QT_CONFIG(timezone) && !defined(QT_NO_SYSTEMLOCALE) +#if 0 /*! \since 5.9 diff --git a/src/corelib/tools/qtimezone.h b/src/corelib/tools/qtimezone.h index bd87139f..d154cbf9 100644 --- a/src/corelib/tools/qtimezone.h +++ b/src/corelib/tools/qtimezone.h @@ -47,7 +47,7 @@ QT_REQUIRE_CONFIG(timezone); -#if (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE) +#if 0 Q_FORWARD_DECLARE_CF_TYPE(CFTimeZone); Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone); #endif @@ -147,7 +147,7 @@ public: static QList windowsIdToIanaIds(const QByteArray &windowsId, QLocale::Country country); -#if (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE) +#if 0 static QTimeZone fromCFTimeZone(CFTimeZoneRef timeZone); CFTimeZoneRef toCFTimeZone() const Q_DECL_CF_RETURNS_RETAINED; static QTimeZone fromNSTimeZone(const NSTimeZone *timeZone); diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index f8fe160e..3c350b3c 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -456,7 +456,6 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const return QFontEngineFT::create(*fontData, fontDef.pixelSize, static_cast(fontDef.hintingPreference)); } else if (NSURL *url = descriptorAttribute(descriptor, kCTFontURLAttribute)) { - Q_ASSERT(url.fileURL); QFontEngine::FaceId faceId; faceId.filename = QString::fromNSString(url.path).toUtf8(); return QFontEngineFT::create(fontDef, faceId); diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index e41c70b8..815028b7 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -329,13 +329,6 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem * } insertNative(cocoaItem, beforeItem); - - // Empty menus on a menubar are hidden by default. If the menu gets - // added to the menubar before it contains any item, we need to sync. - if (isVisible() && attachedItem().hidden) { - if (auto *mb = qobject_cast(menuParent())) - mb->syncMenu(this); - } } void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem) diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index a4cd465d..06d63f7d 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -369,7 +369,7 @@ void QCocoaMenuBar::updateMenuBarImmediately() QCocoaMenuLoader *loader = [QCocoaMenuLoader sharedMenuLoader]; [loader ensureAppMenuInMenu:mb->nsMenu()]; - NSMutableSet *mergedItems = [[NSMutableSet setWithCapacity:mb->merged().count()] retain]; + NSMutableSet *mergedItems = [[NSMutableSet setWithCapacity:0] retain]; foreach (QCocoaMenuItem *m, mb->merged()) { [mergedItems addObject:m->nsItem()]; m->syncMerged(); diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 5504c242..fa0b7f71 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -172,12 +172,11 @@ void *QCocoaNativeInterface::NSPrintInfoForPrintEngine(QPrintEngine *printEngine QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard() { + QCFType url; const int ExpectedImageWidth = 242; const int ExpectedImageHeight = 414; - QCFType urls = LSCopyApplicationURLsForBundleIdentifier( - CFSTR("com.apple.KeyboardSetupAssistant"), nullptr); - if (urls && CFArrayGetCount(urls) > 0) { - CFURLRef url = (CFURLRef)CFArrayGetValueAtIndex(urls, 0); + if (LSFindApplicationForInfo(kLSUnknownCreator, CFSTR("com.apple.KeyboardSetupAssistant"), + 0, 0, &url) == noErr) { QCFType bundle = CFBundleCreate(kCFAllocatorDefault, url); if (bundle) { url = CFBundleCopyResourceURL(bundle, CFSTR("Background"), CFSTR("png"), 0); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index aa8fffdf..191553e6 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -316,6 +316,8 @@ public: // for QNSView bool m_viewIsEmbedded; // true if the m_view is actually embedded in a "foreign" NSView hiearchy bool m_viewIsToBeEmbedded; // true if the m_view is intended to be embedded in a "foreign" NSView hiearchy + QCocoaWindow *m_parentCocoaWindow; + Qt::WindowFlags m_windowFlags; Qt::WindowState m_lastReportedWindowState; Qt::WindowModality m_windowModality; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 86fd7b8a..c7aa5792 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -325,7 +325,7 @@ static void qt_closePopups() + (void)applicationActivationChanged:(NSNotification*)notification { const id sender = self; - NSEnumerator *windowEnumerator = nullptr; + NSEnumerator* windowEnumerator = nullptr; NSApplication *application = [NSApplication sharedApplication]; #if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) @@ -526,6 +526,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw, WId nativeHandle) , m_nsWindow(0) , m_viewIsEmbedded(false) , m_viewIsToBeEmbedded(false) + , m_parentCocoaWindow(0) , m_lastReportedWindowState(Qt::WindowNoState) , m_windowModality(Qt::NonModal) , m_windowUnderMouse(false) @@ -594,10 +595,12 @@ QCocoaWindow::~QCocoaWindow() [m_nsWindow makeFirstResponder:nil]; [m_nsWindow setContentView:nil]; [m_nsWindow.helper detachFromPlatformWindow]; - if (m_view.window.parentWindow) - [m_view.window.parentWindow removeChildWindow:m_view.window]; - else if ([m_view superview]) + if (m_view.window.parentWindow) { + if (m_parentCocoaWindow) + m_parentCocoaWindow->removeChildWindow(this); + } else if ([m_view superview]) { [m_view removeFromSuperview]; + } removeMonitor(); @@ -614,6 +617,7 @@ QCocoaWindow::~QCocoaWindow() foreachChildNSWindow(^(QCocoaWindow *childWindow) { [m_nsWindow removeChildWindow:childWindow->m_nsWindow]; + childWindow->m_parentCocoaWindow = 0; }); [m_view release]; @@ -690,7 +694,7 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) if (isChildNSWindow()) { QPlatformWindow::setGeometry(rect); - NSWindow *parentNSWindow = m_view.window.parentWindow; + NSWindow *parentNSWindow = m_parentCocoaWindow->m_nsWindow; NSRect parentWindowFrame = [parentNSWindow contentRectForFrameRect:parentNSWindow.frame]; clipWindow(parentWindowFrame); @@ -744,7 +748,7 @@ void QCocoaWindow::clipWindow(const NSRect &clipRect) m_hiddenByClipping = false; if (!m_hiddenByAncestor) { [m_nsWindow orderFront:nil]; - static_cast(QPlatformWindow::parent())->reinsertChildWindow(this); + m_parentCocoaWindow->reinsertChildWindow(this); } } } @@ -781,7 +785,7 @@ void QCocoaWindow::show(bool becauseOfAncestor) if ([m_nsWindow isVisible]) return; - if (m_view.window.parentWindow && !m_view.window.parentWindow.visible) { + if (m_parentCocoaWindow && ![m_parentCocoaWindow->m_nsWindow isVisible]) { m_hiddenByAncestor = true; // Parent still hidden, don't show now } else if ((becauseOfAncestor == m_hiddenByAncestor) // Was NEITHER explicitly hidden && !m_hiddenByClipping) { // ... NOR clipped @@ -792,7 +796,7 @@ void QCocoaWindow::show(bool becauseOfAncestor) if (!m_hiddenByClipping) { // setCocoaGeometry() can change the clipping status [m_nsWindow orderFront:nil]; if (isChildNSWindow()) - static_cast(QPlatformWindow::parent())->reinsertChildWindow(this); + m_parentCocoaWindow->reinsertChildWindow(this); foreachChildNSWindow(^(QCocoaWindow *childWindow) { childWindow->show(true); }); @@ -1190,7 +1194,7 @@ void QCocoaWindow::raise() // -[NSWindow orderFront:] doesn't work with attached windows. // The only solution is to remove and add the child window. // This will place it on top of all the other NSWindows. - NSWindow *parentNSWindow = m_view.window.parentWindow; + NSWindow *parentNSWindow = m_parentCocoaWindow->m_nsWindow; [parentNSWindow removeChildWindow:m_nsWindow]; [parentNSWindow addChildWindow:m_nsWindow ordered:NSWindowAbove]; } else { @@ -1226,7 +1230,7 @@ void QCocoaWindow::lower() // The only solution is to remove and add all the child windows except this one. // This will keep the current window at the bottom while adding the others on top of it, // hopefully in the same order (this is not documented anywhere in the Cocoa documentation). - NSWindow *parentNSWindow = m_view.window.parentWindow; + NSWindow *parentNSWindow = m_parentCocoaWindow->m_nsWindow; NSArray *children = [parentNSWindow.childWindows copy]; for (NSWindow *child in children) if (m_nsWindow != child) { @@ -1698,14 +1702,15 @@ void QCocoaWindow::recreateWindowIfNeeded() qCDebug(lcQpaCocoaWindow) << "Reconfiguring NSWindow due to" << recreateReason; - QCocoaWindow *parentCocoaWindow = static_cast(parentWindow); + // FIXME: Replace member with direct parentWindow usage (possibly cast) + m_parentCocoaWindow = static_cast(parentWindow); if (shouldBeChildNSWindow) { QWindow *parentQWindow = parentWindow->window(); // Ensure that all parents in the hierarchy are also child NSWindows if (!parentQWindow->property("_q_platform_MacUseNSWindow").toBool()) { parentQWindow->setProperty("_q_platform_MacUseNSWindow", QVariant(true)); - parentCocoaWindow->recreateWindowIfNeeded(); + m_parentCocoaWindow->recreateWindowIfNeeded(); } } @@ -1713,8 +1718,8 @@ void QCocoaWindow::recreateWindowIfNeeded() if ((isContentView() && !shouldBeContentView) || (recreateReason & PanelChanged)) { qCDebug(lcQpaCocoaWindow) << "Getting rid of existing window" << m_nsWindow; [m_nsWindow closeAndRelease]; - if (isChildNSWindow()) - [m_view.window.parentWindow removeChildWindow:m_view.window]; + if (isChildNSWindow() && oldParentCocoaWindow) + oldParentCocoaWindow->removeChildWindow(this); if (isContentView()) { // We explicitly disassociate m_view from the window's contentView, // as AppKit does not automatically do this in response to removing @@ -1730,9 +1735,9 @@ void QCocoaWindow::recreateWindowIfNeeded() if (noPreviousWindow) m_nsWindow = createNSWindow(shouldBeChildNSWindow, shouldBePanel); - if (m_view.window.parentWindow) { - if (!shouldBeChildNSWindow || (recreateReason & ParentChanged)) - [m_view.window.parentWindow removeChildWindow:m_view.window]; + if (oldParentCocoaWindow) { + if (!shouldBeChildNSWindow || oldParentCocoaWindow != m_parentCocoaWindow) + oldParentCocoaWindow->removeChildWindow(this); m_forwardWindow = oldParentCocoaWindow; } @@ -1759,8 +1764,8 @@ void QCocoaWindow::recreateWindowIfNeeded() setWindowState(window()->windowState()); } else if (shouldBeChildNSWindow) { if (!m_hiddenByClipping) { - [parentCocoaWindow->m_nsWindow addChildWindow:m_nsWindow ordered:NSWindowAbove]; - parentCocoaWindow->reinsertChildWindow(this); + [m_parentCocoaWindow->m_nsWindow addChildWindow:m_nsWindow ordered:NSWindowAbove]; + m_parentCocoaWindow->reinsertChildWindow(this); } // Set properties after the window has been made a child NSWindow @@ -1771,7 +1776,7 @@ void QCocoaWindow::recreateWindowIfNeeded() if ([m_view superview]) [m_view removeFromSuperview]; - [parentCocoaWindow->m_view addSubview:m_view]; + [m_parentCocoaWindow->m_view addSubview:m_view]; QRect rect = windowGeometry(); // Prevent setting a (0,0) window size; causes opengl context // "Invalid Drawable" warnings. @@ -1915,6 +1920,11 @@ bool QCocoaWindow::alwaysShowToolWindow() const return qt_mac_resolveOption(false, window(), "_q_macAlwaysShowToolWindow", ""); } +void QCocoaWindow::removeChildWindow(QCocoaWindow *child) +{ + [m_nsWindow removeChildWindow:child->m_nsWindow]; +} + void QCocoaWindow::removeMonitor() { if (!monitor) @@ -2046,12 +2056,14 @@ Qt::WindowState QCocoaWindow::windowState() const // FIXME: Support compound states (Qt::WindowStates) NSWindow *window = m_view.window; + /* if (window.miniaturized) return Qt::WindowMinimized; + */ if (window.qt_fullScreen) return Qt::WindowFullScreen; - if ((window.zoomed && !isTransitioningToFullScreen()) - || (m_lastReportedWindowState == Qt::WindowMaximized && isTransitioningToFullScreen())) + if (/*(window.zoomed && !isTransitioningToFullScreen()) + ||*/ (m_lastReportedWindowState == Qt::WindowMaximized && isTransitioningToFullScreen())) return Qt::WindowMaximized; // Note: We do not report Qt::WindowActive, even if isActive() @@ -2181,7 +2193,6 @@ void QCocoaWindow::applyContentBorderThickness(NSWindow *window) if (!m_drawContentBorderGradient) { [window setStyleMask:[window styleMask] & ~NSTexturedBackgroundWindowMask]; [[[window contentView] superview] setNeedsDisplay:YES]; - window.titlebarAppearsTransparent = NO; return; } @@ -2206,7 +2217,6 @@ void QCocoaWindow::applyContentBorderThickness(NSWindow *window) int effectiveBottomContentBorderThickness = m_bottomContentBorderThickness; [window setStyleMask:[window styleMask] | NSTexturedBackgroundWindowMask]; - window.titlebarAppearsTransparent = YES; [window setContentBorderThickness:effectiveTopContentBorderThickness forEdge:NSMaxYEdge]; [window setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge]; Carla-2.1/data/patches/qt59-osx10.8-compat2.patch000066400000000000000000000253551364475620200212650ustar00rootroot00000000000000diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm index aa61245..2423378 100644 --- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm @@ -78,7 +78,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); mHelper = 0; mStolenContentView = 0; mPanelButtons = nil; - mResultCode = NSModalResponseCancel; + mResultCode = NSCancelButton; mDialogIsExecuting = false; mResultSet = false; mClosingDueToKnownButton = false; @@ -166,7 +166,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); mClosingDueToKnownButton = true; [mColorPanel close]; [self updateQtColor]; - [self finishOffWithCode:NSModalResponseOK]; + [self finishOffWithCode:NSOKButton]; } - (void)onCancelClicked @@ -175,7 +175,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); mClosingDueToKnownButton = true; [mColorPanel close]; mQtColor = QColor(); - [self finishOffWithCode:NSModalResponseCancel]; + [self finishOffWithCode:NSCancelButton]; } } @@ -236,12 +236,12 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); [NSApp runModalForWindow:mColorPanel]; mDialogIsExecuting = false; - return (mResultCode == NSModalResponseOK); + return (mResultCode == NSOKButton); } - (QPlatformDialogHelper::DialogCode)dialogResultCode { - return (mResultCode == NSModalResponseOK) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected; + return (mResultCode == NSOKButton) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected; } - (BOOL)windowShouldClose:(id)window @@ -250,7 +250,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); if (!mPanelButtons) [self updateQtColor]; if (mDialogIsExecuting) { - [self finishOffWithCode:NSModalResponseCancel]; + [self finishOffWithCode:NSCancelButton]; } else { mResultSet = true; if (mHelper) @@ -276,7 +276,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); // This check will prevent any such recursion. if (!mResultSet) { mResultSet = true; - if (mResultCode == NSModalResponseCancel) { + if (mResultCode == NSCancelButton) { emit mHelper->reject(); } else { emit mHelper->accept(); diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index b22f1b1..d2dd645 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -401,7 +401,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) // [NSApp run], which is the normal code path for cocoa applications. if (NSModalSession session = d->currentModalSession()) { QBoolBlocker execGuard(d->currentExecIsNSAppRun, false); - while ([NSApp runModalSession:session] == NSModalResponseContinue && !d->interrupt) { + while ([NSApp runModalSession:session] == NSRunContinuesResponse && !d->interrupt) { qt_mac_waitForMoreEvents(NSModalPanelRunLoopMode); if (session != d->currentModalSessionCached) { // It's possible to release the current modal session @@ -445,7 +445,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) if (flags & QEventLoop::WaitForMoreEvents) qt_mac_waitForMoreEvents(NSModalPanelRunLoopMode); NSInteger status = [NSApp runModalSession:session]; - if (status != NSModalResponseContinue && session == d->currentModalSessionCached) { + if (status != NSRunContinuesResponse && session == d->currentModalSessionCached) { // INVARIANT: Someone called [NSApp stopModal:] from outside the event // dispatcher (e.g to stop a native dialog). But that call wrongly stopped // 'session' as well. As a result, we need to restart all internal sessions: diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index 9a96895..b227794 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -104,7 +104,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); mHelper = 0; mStolenContentView = 0; mPanelButtons = 0; - mResultCode = NSModalResponseCancel; + mResultCode = NSCancelButton; mDialogIsExecuting = false; mResultSet = false; @@ -169,7 +169,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); - (void)onOkClicked { [mFontPanel close]; - [self finishOffWithCode:NSModalResponseOK]; + [self finishOffWithCode:NSOKButton]; } - (void)onCancelClicked @@ -177,7 +177,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); if (mPanelButtons) { [mFontPanel close]; mQtFont = QFont(); - [self finishOffWithCode:NSModalResponseCancel]; + [self finishOffWithCode:NSCancelButton]; } } @@ -222,12 +222,12 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); [NSApp runModalForWindow:mFontPanel]; mDialogIsExecuting = false; - return (mResultCode == NSModalResponseOK); + return (mResultCode == NSOKButton); } - (QPlatformDialogHelper::DialogCode)dialogResultCode { - return (mResultCode == NSModalResponseOK) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected; + return (mResultCode == NSOKButton) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected; } - (BOOL)windowShouldClose:(id)window @@ -236,7 +236,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); if (!mPanelButtons) [self updateQtFont]; if (mDialogIsExecuting) { - [self finishOffWithCode:NSModalResponseCancel]; + [self finishOffWithCode:NSCancelButton]; } else { mResultSet = true; if (mHelper) @@ -262,7 +262,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); // This check will prevent any such recursion. if (!mResultSet) { mResultSet = true; - if (mResultCode == NSModalResponseCancel) { + if (mResultCode == NSCancelButton) { emit mHelper->reject(); } else { emit mHelper->accept(); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 191553e..e6abf49 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -217,7 +217,9 @@ public: Q_NOTIFICATION_HANDLER(NSWindowDidExitFullScreenNotification) void windowDidExitFullScreen(); Q_NOTIFICATION_HANDLER(NSWindowDidOrderOffScreenNotification) void windowDidOrderOffScreen(); Q_NOTIFICATION_HANDLER(NSWindowDidOrderOnScreenAndFinishAnimatingNotification) void windowDidOrderOnScreen(); +#if 0 Q_NOTIFICATION_HANDLER(NSWindowDidChangeOcclusionStateNotification) void windowDidChangeOcclusionState(); +#endif Q_NOTIFICATION_HANDLER(NSWindowDidChangeScreenNotification) void windowDidChangeScreen(); Q_NOTIFICATION_HANDLER(NSWindowWillCloseNotification) void windowWillClose(); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index c7aa579..56eb291 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1532,6 +1532,7 @@ void QCocoaWindow::windowDidOrderOnScreen() exposeWindow(); } +#if 0 void QCocoaWindow::windowDidChangeOcclusionState() { // Several unit tests expect paint and/or expose events for windows that are @@ -1547,6 +1548,7 @@ void QCocoaWindow::windowDidChangeOcclusionState() } } } +#endif void QCocoaWindow::windowDidChangeScreen() { diff --git a/src/printsupport/dialogs/qpagesetupdialog_mac.mm b/src/printsupport/dialogs/qpagesetupdialog_mac.mm index 1e39845..9305566 100644 --- a/src/printsupport/dialogs/qpagesetupdialog_mac.mm +++ b/src/printsupport/dialogs/qpagesetupdialog_mac.mm @@ -77,7 +77,7 @@ QT_USE_NAMESPACE QPageSetupDialog *dialog = static_cast(contextInfo); QPrinter *printer = dialog->printer(); - if (returnCode == NSModalResponseOK) { + if (returnCode == NSOKButton) { PMPageFormat format = static_cast([printInfo PMPageFormat]); PMRect paperRect; PMGetUnadjustedPaperRect(format, &paperRect); @@ -88,7 +88,7 @@ QT_USE_NAMESPACE printer->printEngine()->setProperty(QPrintEngine::PPK_Orientation, orientation == kPMLandscape ? QPrinter::Landscape : QPrinter::Portrait); } - dialog->done((returnCode == NSModalResponseOK) ? QDialog::Accepted : QDialog::Rejected); + dialog->done((returnCode == NSOKButton) ? QDialog::Accepted : QDialog::Rejected); } @end diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm index 8547799..f7bbb59 100644 --- a/src/printsupport/dialogs/qprintdialog_mac.mm +++ b/src/printsupport/dialogs/qprintdialog_mac.mm @@ -101,7 +101,7 @@ QT_USE_NAMESPACE QPrintDialog *dialog = static_cast(contextInfo); QPrinter *printer = dialog->printer(); - if (returnCode == NSModalResponseOK) { + if (returnCode == NSOKButton) { PMPrintSession session = static_cast([printInfo PMPrintSession]); PMPrintSettings settings = static_cast([printInfo PMPrintSettings]); @@ -190,7 +190,7 @@ QT_USE_NAMESPACE printer->setPageSize(pageSize); printer->setOrientation(orientation == kPMLandscape ? QPrinter::Landscape : QPrinter::Portrait); - dialog->done((returnCode == NSModalResponseOK) ? QDialog::Accepted : QDialog::Rejected); + dialog->done((returnCode == NSOKButton) ? QDialog::Accepted : QDialog::Rejected); } @end diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 4c5c9e1..5b4a95e 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -147,6 +147,7 @@ static bool debuggerPresent() return CFStringCompare(str1, str2, kCFCompareCaseInsensitive) == kCFCompareEqualTo; }; +#if 0 // Check if there is an exception handler for the process: mach_msg_type_number_t portCount = 0; exception_mask_t masks[EXC_TYPES_COUNT]; @@ -163,6 +164,7 @@ static bool debuggerPresent() } } } +#endif // Ok, no debugger attached. So, let's see if CrashReporter will throw up a dialog. If so, we // leave it to the OS to do the stack trace. Carla-2.1/data/patches/qt59-osx10.8-compat3.patch000066400000000000000000000130141364475620200212530ustar00rootroot00000000000000diff --git a/src/gui/.obj/qcoregraphics.o b/src/gui/.obj/qcoregraphics.o index 00f0647..2d1b7da 100644 Binary files a/src/gui/.obj/qcoregraphics.o and b/src/gui/.obj/qcoregraphics.o differ diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm index c4fb8af..91875cd 100644 --- a/src/gui/painting/qcoregraphics.mm +++ b/src/gui/painting/qcoregraphics.mm @@ -47,6 +47,21 @@ #include #include +@interface NSGraphicsContext (QtAdditions) + ++ (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState; + +@end + +@implementation NSGraphicsContext (QtAdditions) + ++ (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState +{ + return [self graphicsContextWithGraphicsPort:graphicsPort flipped:initialFlippedState]; +} + +@end + QT_BEGIN_NAMESPACE // ---------------------- Images ---------------------- @@ -147,7 +162,7 @@ QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size) QMacCGContext ctx(&pixmap); if (!ctx) return QPixmap(); - NSGraphicsContext *gc = [NSGraphicsContext graphicsContextWithCGContext:ctx flipped:YES]; + NSGraphicsContext *gc = [NSGraphicsContext qt_graphicsContextWithCGContext:ctx flipped:YES]; if (!gc) return QPixmap(); [NSGraphicsContext saveGraphicsState]; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index bac49cf..83b51cd 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -144,7 +144,7 @@ void QCocoaScreen::updateGeometry() // The reference screen for the geometry is always the primary screen, but since // we may be in the process of creating and registering the primary screen, we // must special-case that and assign it direcly. - QCocoaScreen *primaryScreen = (nsScreen == [[NSScreen screens] firstObject]) ? + QCocoaScreen *primaryScreen = (nsScreen == [[NSScreen screens] objectAtIndex:0]) ? this : static_cast(QGuiApplication::primaryScreen()->handle()); m_geometry = primaryScreen->mapFromNative(m_geometry).toRect(); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 56eb291..5d63dea 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -858,12 +858,7 @@ void QCocoaWindow::setVisible(bool visible) applyWindowState(window()->windowState()); if (window()->windowState() != Qt::WindowMinimized) { - if ((window()->modality() == Qt::WindowModal - || window()->type() == Qt::Sheet) - && parentCocoaWindow) { - // show the window as a sheet - [parentCocoaWindow->m_nsWindow beginSheet:m_nsWindow completionHandler:nil]; - } else if (window()->modality() != Qt::NonModal) { + if (window()->modality() != Qt::NonModal) { // show the window as application modal QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast(QGuiApplication::instance()->eventDispatcher()); Q_ASSERT(cocoaEventDispatcher != 0); @@ -923,11 +918,6 @@ void QCocoaWindow::setVisible(bool visible) if (cocoaEventDispatcherPrivate) cocoaEventDispatcherPrivate->endModalSession(window()); m_hasModalSession = false; - } else { - if ([m_nsWindow isSheet]) { - Q_ASSERT_X(parentCocoaWindow, "QCocoaWindow", "Window modal dialog has no transient parent."); - [parentCocoaWindow->m_nsWindow endSheet:m_nsWindow]; - } } hide(); diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index e6436f8..db1878a 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -137,6 +137,21 @@ #include #include +@interface NSGraphicsContext (QtAdditions) + ++ (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState; + +@end + +@implementation NSGraphicsContext (QtAdditions) + ++ (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState +{ + return [self graphicsContextWithGraphicsPort:graphicsPort flipped:initialFlippedState]; +} + +@end + QT_USE_NAMESPACE static QWindow *qt_getWindow(const QWidget *widget) @@ -1036,8 +1051,8 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h CGContextSetAlpha(ctx, 0.5); // As applied to the stroke color below [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:ctx - flipped:NO]]; + [NSGraphicsContext setCurrentContext:[NSGraphicsContext qt_graphicsContextWithCGContext:ctx + flipped:NO]]; CGRect focusRingRect = CGRectMake(hMargin, vMargin, size, size); NSBezierPath *focusRingPath; if (radius > 0) { Carla-2.1/data/png2rgba.py000077500000000000000000000107751364475620200154110ustar00rootroot00000000000000#!/usr/bin/env python import os, numpy, sys import Image # ----------------------------------------------------- def png2rgba(namespace, filenames): fdH = open("%s.hpp" % namespace, "w") fdH.write("/* (Auto-generated binary data file). */\n") fdH.write("\n") fdH.write("#ifndef BINARY_%s_HPP\n" % namespace.upper()) fdH.write("#define BINARY_%s_HPP\n" % namespace.upper()) fdH.write("\n") fdH.write("namespace %s\n" % namespace) fdH.write("{\n") fdC = open("%s.cpp" % namespace, "w") fdC.write("/* (Auto-generated binary data file). */\n") fdC.write("\n") fdC.write("#include \"%s.hpp\"\n" % namespace) fdC.write("\n") tempIndex = 1 for filename in filenames: shortFilename = filename.rsplit(os.sep, 1)[-1].split(".", 1)[0] shortFilename = shortFilename.replace("-", "_") png = Image.open(filename) pngNumpy = numpy.array(png) pngData = pngNumpy.tolist() pngData.reverse() height = len(pngData) for dataBlock in pngData: width = len(dataBlock) channels = len(dataBlock[0]) break else: print("Invalid image found, cannot continue!") quit() if channels not in (3, 4): print("Invalid image channel count, cannot continue!") quit() print("Generating data for \"%s\" using '%s' type" % (filename, "GL_BGR" if channels == 3 else "GL_BGRA")) #print(" Width: %i" % width) #print(" Height: %i" % height) #print(" DataSize: %i" % (width * height * channels)) fdH.write(" extern const char* %sData;\n" % shortFilename) fdH.write(" const unsigned int %sDataSize = %i;\n" % (shortFilename, width * height * channels)) fdH.write(" const unsigned int %sWidth = %i;\n" % (shortFilename, width)) fdH.write(" const unsigned int %sHeight = %i;\n" % (shortFilename, height)) if tempIndex != len(filenames): fdH.write("\n") fdC.write("static const unsigned char temp%i[] = {\n" % tempIndex) curColumn = 1 fdC.write(" ") for dataBlock in pngData: if curColumn == 0: fdC.write(" ") for data in dataBlock: if channels == 3: r, g, b = data fdC.write(" %3u, %3u, %3u," % (b, g, r)) else: r, g, b, a = data if filename in ("artwork/claw1.png", "artwork/claw2.png", "artwork/run1.png", "artwork/run2.png", "artwork/run3.png", "artwork/run4.png", "artwork/scratch1.png", "artwork/scratch2.png", "artwork/sit.png", "artwork/tail.png"): if r == 255: a -= 38 if a < 0: a = 0 #a = 0 #else: #r = g = b = 255 fdC.write(" %3u, %3u, %3u, %3u," % (b, g, r, a)) if curColumn > 20: fdC.write("\n ") curColumn = 1 else: curColumn += 1 fdC.write("};\n") fdC.write("const char* %s::%sData = (const char*)temp%i;\n" % (namespace, shortFilename, tempIndex)) if tempIndex != len(filenames): fdC.write("\n") tempIndex += 1 fdH.write("}\n") fdH.write("\n") fdH.write("#endif // BINARY_%s_HPP\n" % namespace.upper()) fdH.write("\n") fdH.close() fdC.write("\n") fdC.close() # ----------------------------------------------------- if __name__ == '__main__': if len(sys.argv) != 3: print("Usage: %s " % sys.argv[0]) quit() namespace = sys.argv[1] artFolder = sys.argv[2] if not os.path.exists(artFolder): print("Folder '%s' does not exist" % artFolder) quit() # find png files pngFiles = [] for root, dirs, files in os.walk(artFolder): for name in [name for name in files if name.lower().endswith(".png")]: pngFiles.append(os.path.join(root, name)) pngFiles.sort() # create code now png2rgba(namespace, pngFiles) Carla-2.1/data/presentation/000077500000000000000000000000001364475620200160335ustar00rootroot00000000000000Carla-2.1/data/presentation/lac2015-carla-workshop.pdf000066400000000000000000003240641364475620200225400ustar00rootroot00000000000000%PDF-1.4 %äüöß 2 0 obj <> stream x;k1[,w mHA*K}$_ PtfpYw^eKo3&\lH9}K4Av3y?mԺSsx_el'4/^lpv=tLGZg_#]+wD‰H6A2LP\Qm*S-x*56\ endstream endobj 3 0 obj 222 endobj 4 0 obj <> stream JFIFC     C   " eePIDνn~|bGʞGgY,wr'sNɎ UW+ BWyRӧ% 5(uKleϙgi҇PCA.:d*NrҡuY$٩v4]'[0HlY%i8;P85luq:sWĢ8d{k+,׽ӏ/G|gΊU3a^NCKxxIԮX"6˝2'DAiXs GVZ(#FUee6S!XU:yz RIڨAr5)ư:J!D0 f i/9ͬrEsrВX2+dowu"Y[V*wg/mʹ7JO^u7wsVTwhFҞ.n:qLpZVΗV:GJf2+( (""(sNr1+K(!͕NѶ34Ւ .Ӎ 3裱z6):wu]NX3>^7#4y::}G/OG2hù: ogu|{x\#YjҬ;GNW<啅ϭ:1SJC9QE Ω:OYYea;+k3txStg ,]sDxHgNyyv9qɪ~>7Wъ<\׻hu<#s\Y˟n֎vv@yJѮ.^GNW`<'7W(/ uee"U*%gI*q% i;bt) C0 GD9 LoQ(q6u.^;co4<':95gX.j>VG##c)yrN^qno+QJAstǍk>2<ӱwvʛ-x0ܻ=o33\4O7G4c\Ɏjˬ.aA8;+&7HUӞӊѱᎮID\AeYe.BDcj˝tU\A:SX'JS++VV8ɝsYVCrv18u~:9Ypgv&Ey[Ymhdltb7G0Pzrsts_K5Q: 7;:cZ[X U+.6g;V^@ym ^^aXZ8hΒK2*$W\ӤE#ie5RtEerXS);:`ڳ5xǨThdltb77O)f5N\YO.ۃy4W8c%qӭpOwk0Ѹ;ʲ.^GNyo ^NQX^Lv4gI p060FwizPWQ<jJkR9Շ XJQ<󬱳iYC5.cMgҳκz5CO73Mhߞ}yR;öַ=y󳪀  s۞Oz;;ƴD!Ѭ1B #Csʑ>L7>cN5AFc;GbN*85r=9go7rttg]W!kFrណp0Ҭ-fVԊ:km@)*.$e]eY)DqAYXҴqC.tq;DN@ӛ]P^7묞t(Ls9дԓ|0T{x T254+ާ>jN+7g^x80*N:y3daUt DSdm+jˍ7rdjN1+fVJK\sFMNN2kf|hSV7͉K#6լq"fF.F>{.ß_J~5OW;k-䁴><.\b "U::VI;diVUŊe"ڰƦ:&VT ޓƲlB+%Kγsr hzyY8xQ?z5BN]Jt4qNSwii! i[y=\z9ہ ;$dhZ})Ϝ$x_Z24i*ޗ觞g}+u8`ul.kg}jWz99FFVZ*8 :M s+9bήEeY8e]jdWJNGHΎ4&!XnN>!G5yޔ;ӟuR98XqKNtC}uTrETBFo=a$8_ 25RC7|70[!5Ɲ Zkжt99JGVZ*[tTss655aGMsIVYNImY[|xچ9Qҳ'I CŔRt5Pӟ}8G}9N8ݒtC }`rvϔD[ d9``ʒicc#t؋:O*8vfVs˟^Rw*)پvK2fC#!\a:YxUL0FbKt$p0MX6Thda2 39dDVJ[aY(dfVGYBHcnhضVU:NgId}cVA牤<굙[Nз^.xXD$nN__NvCJbᩕ0sT XEHw15dry<l֪\Ӥ 2R#(+b3ml51S@jt1H TToo 19ZJtIt/=ϫuHVU5^Y5Yk}y7*I)ӝ;/b3MŲdeA`9|5aZK,0bl44r| !V4ற5'Ga*XCaYXPmjTGMdeY *Q"U): zYXnN:|V.T5G.}9:tƓFJuruo}7/ fFHV*Cˬ2(d(Z6I"7W3͐0]YuA9dt V1lD Emf0Dtq VUSխV"UgFVsxcuu YT/zrחXۧtga^NYRXTLn_~{k?JfF*ӈ0l 0 JrOՈ+*m Z:K`aZ]Hs57G`EDeeAN  ($P GwZ61It:N%I)9xcurYS:N(Yӧ& $m,t#g}tF_;8{7 +32m0"%HGRj̭XKY' ]#+K MΉD2ZGm%Ycb(hf`jDڀed'l9ZU#h:R^tg:~N.,҆?;ւ N<,;`E 0"peGFj̦eXXYm''mMeiueLq:)-2ӎ.F:::&M](;PVQYVYqڱoiWxheQ3:q4Xg=?txb 0" ֘XV;P+:: r'm57GVT'AӢS+-0e'b mfVMV:&Ru tZ5#h9'IL:G&gU>ׇϧq8|/}ϡMvOw?v}Zη=Җu>ܱIaMQ#+-1څeZژ2ttf)II8Z\jnJ*Lmul 1ձ5a](ң1i]u'YI+9捣*>n秷oS?34m~t绚V_Đ|Hh u0"!])5j[F-8"Ή[,AOqet,G QҘ9:Rƌ:8mM (:t2:ea2AJ#lqfWr6,641%eκXEud;l8]Z6D&UgG'g<}K۝>Ww57}>?kW?I9=g_JJY YY +SmձvA,AAh$v6t) RrAB49eYҬP;fdVuwCQ XjUuβv.J//Md5o>=Fwk}J|D>ߕ>3|{=[Y׫\GYt >y_!:IɬlISYk_YCY] +V8 )!4j D F 0: l[N"B2jUgJVQ!`Gb:$lDJB*;J& J.FmK~5'Se q~ZKzse_οGY:=+_W9=:;w{7>.|:ɝ%66>oaed,XQQ3+11 XZѲKb,mIut&PYgZ&.+Z;dlg:;VV **:J&҉Dd;m;l=Ǎz>{U}޾$O'ZyN"yDkS^G'voF}n|;y29֍io5amg>oYud"cD̎B@.I )ف6ڦPYZiD U4:GATU:J&ʈ3eFϞBNpʲK\FۣNGί%^y8omg͝J@gVR4F7rk?>A+ez`VmG̎ 'bu`² VTvj*Y5BҰ5 C- <蕃.;VVTU:J&1ԉD4GmGѾ6:NeYPtqyIcX8oIYz^W{z/Ä  CXќFςq&uj;d`E8:!X :$1ڃ$ vXѢT:C gj6KF:Lӂ(tJJ F0 ˝1NVDt6!hހ"%DVT^UX6:ޗs# {{icNiXpk*S>*9nZ2퐂 R! ts$2՝PkJҭD: d05JxQdj*LAflMI6ن:8#;J&14gS 2؏Mm/YYbt$Ʋ卡|X{8agao<; 5ʲjI, 12A3B!"0#$%գQ?#/RAW7kG` S Njh\?/}W>辐DA_E_O踻_DR%NrW}B#',vڎov~qSj~ښ?a m˵9j67rNM˳ df𜍆 o,RѬ KZScڷj:y4~0ݬ;"jrln '&ق3q#qp\]R†1.v[-]N͎X[i#$a=|ibx(~ajr: etPEM0p#!stP*fvl:)bx(~5~FaXv9j67tprn](k- 6: 0spphȊJ(eOHfSeS4|NTےufFOCg#0ݬ;CNZ' f  6: 0s&#&xU=!]M,)x(~Y~fhrv-FNM˳ dd`c ; aP k5vU6v,־OYg#0ݍhr:NM˳#YnM 6: aLÑ 9IyO jfϚI۪NÁk_XfaF'&ق`a6 nphȊKE7<*TڞϚIߒueEUږ&wfbx,~ ]9w3g`u˂(dF3qAl0q naLNG+D#+NMz➳[uSj[Twg+l.dbG 6 ; +NMzmMmVh{;[1<q ?݃Ń6v ˂(#r68`#&ʗ)5U6Io`\0@Žqgl6 $dbE 68`Gi'n 'ol6 PG21#76 aLÑ ;GߩXLoaj*G.T"_G[*?8|uZj?G4ߵwhol2p"(#l9vpcD0"< ԍZaZhSM^p.pGNoQF=|0$Ri'nB{=6\cv\C'21#7(8cpsnsCUЛ0O+G?oEJBȅ_#ܩu OӥV7絟޻>٤?Ӌ;g`A.PE[ltA9v0cD5]/̭Ay>y%Q:RJ/ٴʗQeZCyp?)c_])'noȳӋ;g`A.sq&'a3G+GaUbJ>.6{SC}VWc7}v}ҪooG/$v,"ݞ{!v  .PEs#Ynn0QqMNF84CTr#Wu45*~m'Rw¼$ULn* UYe*n(9x.!kCX!Wv|GuSn(@{g`A.sq6 ð#&cK))icx\7?~7|*7g4wU6W{g`AEPG25lnx9A5@oy{&㾉jU:D*|pTUj/(^Y_LS/}jA_T=-WSʦ֋݁`Wm흂A95;25M3~oSS}*+|+g|>"z-47>mOO?ehm Y(lqgl67e ɩّ7(8cp6:ߧ|&=Oy2ߏ~yLg~)ժy4/AsH>^FFΚhm2_`A.PNMN̍eQdvV3V$~g)QjPu&|Bv/_e_UOWySi S?_?QM<3¦|=*TE@1_>ڃ.hmh68vyA95;25AFAx97E%XƩ[}s> _S/#|J'>n!U|U?srb;*Yyv Y W ݗA97.̍em|A9v0r4CTr";r_~:~/Ԯpr- }UC.#b:68f\2v\eu eQq'a3F84CE%"WPўO w:ު.O2b;'$Og8fBΣ!7e ɹvessc 1u^* \#qcQk:/CDzt/}1˵bbZ!e=G_cQk/C#!Ǫ=*\ƺ/D>e=л2qWX1hcɗ4G k!!xN1hcɗ5z{.Qk!/ -cɗ4GUvS׀|1ˑz=Q2qWX-cɗ4\=|T.զ]*C&\8BUWucZ#.eCUFU^cZ#.eC{GxLqupǃ2q1ouh늽Q y2qp.6VųQ y2qcZ:xLqDeL\=ccCǓ.GBͽգ/%1.e=c6V^bFF<#pc^Kbpǃ2qp!91.e=c|1ϑЇ7XF\1˚#Їb-1hL[Cf3. 4| 8Ţ_?Ţ&\?ўnhcɕhXC1CBᒮ?| |TfW1و_F\1Ob:[;!Oz-y6|:Ţ5'Xf1?1jc 01@AP?MVynx0zFhf,36<l=g4c[)G4cŸSeH#Zs6<lb5h/-0zpa>ѱS1akN 2 )ȏHa5V}/-,L&>Fˁe9"O8E. 7K)GUi{EŠ-Zy MU}! {Fl&>gpj83 Qm3akN>G#֞q>֜}>֞ql0ig+q >iF >i[ >i_~^Өg3US8s?!H? }4}4}4m8 0!@Pq1Q"Aa2Bbr#R`3c?k4!dЩk_m`歅%KZ18 =X)/l-jx=X)/l-jx(;նR_5l(,4*ZQŧLI|հdЩkS'G3k%VBlN33k%Wͅ%KZG3k%VBlNn-:f jQXhTۋNl-jx(Ӧm`jQXhTQŦr jQXhT_GNl-r =X(yaFaR֧Nn-:f K歅%K\n-: kQXhTۋJk5l(,4*Z(9{k5l(,4*Z(ҧFC%KZ18 =^C%KZ18 8ZTcm`BOZc,/n(ydЩkQML7l-jx(9{k7l-kbp{3caiSa{qC%K\jl-*`,(PyF-jx8νkV4*ZQҦmpo(CBOZTU[ m-jx(fҦ4*Z(:Ҧmpo(CBLNfhQMO7ЩkҔq[J QyK\Xl-*`*G7ЩkS(fҦ7ЩkQ͍LX(j?4Q qK&}R'X(3s5 YzJM^pmz8'_ޤ}~'6.N~rB{G47G/ǴV|﷦i]sx(/s],p$Ϲ7/U]ixQK~|~}8I,m,lj㞎Aқ9G~qxez{Kͩ,ryMY7ٓoh%Mͷ7&>VYZ2_QϜ|~o4ϦsrLcs}qMjo=6jGq qb^SK=hfDzѼIrf1vco}xI_^U%=(G`(F'3aNN)>`NJlzq B>d#w K/60aaޔ\̈́.&{ >GhOڥXu2k )&_iv|SLgy Yz@~.:Ҕq Y?m.ix?ѥ6'M 3å!G'#A7}Y?4Lu`(F|pHy}s^W{r&ӘF6x5u%}6iƮpF+mڲ~JGBSՉ>IT7č[ΰ{ű? ?hO[^UGw{rkKm4q.XG84%>]9xAi$8e&GM,43$&GO/{;:~$M94 pVWB77 cf6)6?L nps՗5fׇoA5=}ƞÿ3V^~3,/8wG<|ve6#Bmif8msM!"%OMkdv|_hz\4ݖ'aӕ4,K=]hL4$Sޓ/)q-Xv3NYYOx8t^GK{񶦤~8Ԛ}7u%m4u&Iyd8#mMY=,}DnGb_4ӗ>J>H߀sn HY?h_Bv#ҔqHs6f ݶzI7UG?/c7mg>\ oJQ^bs6#ښ:~g2mϲ Hؘq?肏Dbs6貎2gP(F'3aiSl-;Y 8̅9 NgBll-:?(1A!q Qa0?! :b?b&I#CC~QpƇ gxva]gPHͣqCh^J؞ PM %6PAv/d1Б욍C=I8*f!(u á^0,E+U5y()/0(GLU :GdPوHB|;C31uˠ,>}8쳈%>бeø~ x d;cuc:b[#(9XFeT,&[F.RTF1-53v:g|ctԯ9hOcc2Yx!ܺGC[aV`eSTl(GNJ:Ge{Bއoq;heߓQ܆tԧ9OY|G Heqx0T< IE(uc: v(9߁*#A|xBӒ;e'?kЦBvNL8gP[N,3#/?be p1D"< 4C(nNPj h9ī44I'NwmLGH좸*vO] 2;'r̝1p/>}:K{+3A E 9RTuȠ< IiBne!G@cRT _p.>}p#/8qwEGv/!ۃva\ qae|/gb v\;/]܌K*}fx8cP+/!(t`21R2 ɇ%&^]b((ܴt)Gdm9FBЧv!v3.>}ɉΐ>3Y-Q*!1! @+0A6yݔЛ ߤR)B'h/j|>peكw\ _gPX?ToK"o GcЭ P@+1ƞL(]!1>gCj:b gv ;3&# "c:{*}fx;? ϡOps *}'-rb"#Y@ 1+Bm43 LEj?;PVkQ; t= ]}-TO?VzEPp2v`W0*ñAc+n8E:0࿲6|GOv9f T8GUQ@S/q"\EefDhu<yE.wGoٞ;5`ΰ>ѳ",E60  !x,:qEq'1KMi&ju?;CəEƻ O#SQ`c3Qme OccFu>猚-,r~JNQ^-L;PXpCIOP%uF2fs!u/ 0|] Nˆt P俲\B++8 DXaxVCD;3pah| yELleWYw#MMv1?ԧv߸c2ѻG6(!eOXx1840_ NQ^QeL2C..tb4d`7n#(mܚ OM;a:SߎAoeOlqw,Wb(,035=E7E1lu4P:eAyg"o4 !ƧPNH/0'Qt#SSw/cSX8e\ _eRpK*}!g~/'ሊ2U G*ʢф|ÄX#(rMjjY)Ht[k!??#8|NGxa;p8EԧGgHG_S>x{cN"+ ',䴄TZ0,|eh(^p3 u n#MMv Pۍ;C53,>}Bm_࿲ض3U-G/+(eE*F*u:p 8)$xʂrBK) a7;C NSC:}K+>>Ow#bgC*,0; Eqo"exDǤi4ȡu:,৒xm]Jv:;CF@Z}J{3#/3YF"*Sqi* İ ?Nz~F>'ȬRT5J-৑E#('Q=Bpwc|yo7)gPX}JgHFoef2?`N&L U`Z0O2ˈع_Nq(%è*J9+FP50* En!v:gd~eв{.?x<-VW HN(F%5-(1s*K_31 e(=tc#-MLEeDݤWr*^!`_ 1عфu#CCAiSXXr>k-5T85}31]p_cJ.p#/S@(G3ijR0,`+uXT$hZw𷂎J-5C`…{cpj#p[RΠෲ,ɨec3K*;QUE V)FcʨYBP#| -R5# #]ap+1[M oa`j38f٩p~%gp8\\E`(f02GE_%a0U@XƇXEx)} QD"a= (q>" LM\@Noe όr1W 00Vp2#UYp/ٌΨT(|&[8hyG#Cct'l`nhfDa;Wԧ2ˆtfxJ!ŃLEFUlS J|ό /ɲ5NF!w2A (Qdtr1 诱RRAў#p;f'Y_!90B;YAUc( 󏐽dа^Z5~1c+pj!tx^F:Qԣ_~'1#-2_ "Q9*!`;RYЪرu!##hUHpk-QhFKy55Cg-rlGj[g vKt%fC(ᇍAC+,‘E!`;f1LQք| ,>Q-Dǃ5H m&:Wo'jcDG+P䷲cG~XB*x%\G,ǒtb[l#cÂ+ 1l#!G>E9X(v#۹50!Bp g(Ce(__f#,Ph|<QcY:6ؗEE*G3vتر(´:[Z/ YY&&:Bdx5NFɽ MDG46Fȱߐ>VWEPʎ}XQsX(âEb^P>'%8q:V=es : B_{99Gh()im@oe<<$瀊&WŜP3e(v,u!B>>q!T?ž eߏ ~EA B!ZcS;R8' wK{(ZN'.pBPYɅr})'Q3UEac=1OG ,>qP^?T'5aZ#%ܚ:BL->BQv{5EmhX7(fK0_ +;:*,G6{\U@.uG>3- ȉ!Z`CMEBc!^ɷSry58),w-;|倊 Ag"}bıPDw 8uB>B>'̨Qaxx;A컘T# I(f5;Pʸc&Z1ۉmhX8wG〦!F1YLܕEQ#]pbh:Ў!#G'8+Qde@߰CMDaWGp_OewK{*^&;#4)8C*,0EXK$)f]qV:||B/ G'o& ], P md (555]p2¯c^1ۉ-"QB+~6PYɄ}bVUB;eccB>Q>q)Ix; !Zv;,B0+›YW#^Grp0¯~Z1ۈ`[n\88J`8xSaYU ð,1V #+QDXB:B|hEhivjdeEʾMD#LWaZ]p]c{ʗߐ.E`cg 2"LR*Eb;fتOá ϐs :x2eƢ0+’Y1Ъ7xe\!{-:vx٬E|[t0V^nL.}EEE !`;e*w((G>T>wʊD1pFhSF0]pp̠d2=< v0l( T@䬸g(҄t!2-SǃXeAG"W 55 ix0P7u0߁Dh21~q+F&<*):)g*c"+)؃.?D|r^zBHEAᗑ рAŎ#&(8X|{"7LʂD9ŒDXEpU)aُcJbv%7c" B"E*A\EEtE/>g̨Qa#X!_"G e`\dPw(vۮ ǿ/F;\~O+ɌR2a,05>XX(,+Q@X:xuC6 MM|ML; V#  ٔ8T.f;1fPed8JwLQI"TXaE<>0`TD NGsROa ,B(*~+B, ve 9FSu2c߁D̠Ä) " >0*X(ڃ. yOA39gF(BD2v*̎(lvc߅Dˈ3v,ΑE%+02ǨDZ0-K;Pf*ׄt >p8 5BENC 2;J1ّ Mɏ~ۈ3~|^WVpTXai(TCa 8Q||`QxuAF^?EN0ZU,2dp9FPˮ2ciP3(3cLfgh.FQ.} U=!P(5;fЪرMD|D| - Ğ< 1=2Rvdp9FSuó &e[Rd8KqhPCCQIPT .<DXf@Uعu 8=F^GpPU*B2cXF`~ ;1;Ao6CxJxbc¢ʢL(- ؓU@X Ƨ>gi\0뺌Īr(*pB2cTɑlvc߁ &d1)`"J11QF+,h!*F5pb'bF5j|O .>c*pk8)bER#(V;U28r;1 ˈ2ʗ< O~O)1a,G3XHx|MO`xFOg)၊98P…iv"2df lɏ~(2ʗ!ߒfQx<  P1T@u TίP|Z=)\ CFRU*̙`?Su2ce[R3!%6p? "E|Xx QacQ$W (Q5|Ąh| -9'E<1 D1W2;U2 dif= v d8K~P/CC*Q .| Pd(kqk-S5F4}ͼXʢ QD(*p1 ѓ"Vd2.2c߁n {w Of /Š)8 T (,:0\wh%I)>5!&3SmΒV Ok$6hMu4u YoD'=Uv CK6  UxB U$bRvdp9FSPɏ~%2K{8",#q2'T*Q0UȡI#FPb ٔ8T)v ˈ3*[Lw~#T"f< E }Jь,jK\p5lҭҗ^\٫=[cjZ?oP٢-ԻE#H?EcH# 2;U̡(}ˮ IoeK8l~r+PIXT>$j5Q޲bVIsAu'9?KaCjp۷a4WqWW"$aVXAp*Q3u`ϔTf(!erax* adW:1 u7w5&,+j[jj(9,jnk#{p4+<{M&#(yx!,B!؂حJHʸ|c[RW|/g󗌬+5RNA߼+Ȼ!ڍl`Zb"Chh-#KCѥV&mhVY1݉^/c+H\M`NtIq'OVl;-00/ 3"D2v P~ ]q hvH[R;1C!j{ui?,L(lڦ#tT~Зut\ cNVL;-Wm͈Ѳ5妜~Ej mS O_Vh|I3Ծ BNZk&jƳf6P9#B" ح 9C0ˮ2*$wP"x"E zB#N'i-t:B7XkZ.&; #j䡖l bVȌh6hz6eF֓zBѪbR8ߏ'1hKG';kfVdT/GTUHQQ#(E\;2 e2끌h~$fC1b+C)-gAJ:;g+%}K_'4{TI bxj횭D7О׍ Ѯu%ua[O_~4[{Nv?`mZ7Xפּ߃E% #gC҄نn76q$*` 980eveJ.v*-Z1ߏB3>M5'"CpcaN^,BD2IB2ZLG}uE^ᡠF;"彔Si"XI#rQL[GjX64OrZ6m'n؟kŽG@]5˜f,5*br!Bó(f G(vnaWĶS>s_$F&!E|,,`Ķ+ApS3c=d|]JkvYAZ2qBs%"+Bó(f Fi,]p; * %x~!SspH>#rU3ئ;Pet4B֞%us+*br(Q#(E fPU,S߁ hkp8ow+*?iP9*A7]HhKPˇRE~i fPU CA"яQ˞#倭,%I#B`X2ux@^S_!pʆ:NjTQȡG B n C0R8C0u^1߈%E|g578)} f;}¨ DvaL֚#Xx3@x+xQ@p!ZhC*0SIۘevObx7~%ʾ3qǖ",M< 0XU+bf1skF1U9ˇRx~E a* ex@\M37Xm ƴ8~1*ib0y%|}s&ũֵQv.WU3k![bfЉ {Ǟiܚh}R? O5ȟ#jDؽZM, b~Ugg[ 67}ћ:O'y7G3d]'ftxTciiNkyT'ǃ<#i۞}yh;T~2W޺@8֫ӯ3Z'];aɍu^<_4 @sl{m~tʽշ:`;9e퓣sW/ɵDWrNX2Wй&q̼x3ϴm},Pj;o+1n23`rOO]}V$M?B''j/Fj'_w\ª{,oliWlu[ }4,߬O9%gVC_ln.Gc͘ϧK]?gzT{L5$Uw=}b6uV(+*jHf~}x4$#v1KV;^{ۏ߫3 ,d}Vi6bC.ͷBXW3=tJo㥙inSww84>F>kLZ _mWl^m{>*$n$M5vz?`ΪSS1Qk2rFa[{ٿg8 |.S|Z_ OY97ϸ!4zsfhjߗ?g?5om:UGF5,Oy*v9qϵ :s&6񬊡cݽ:eN̫d똬mݔԧYNnGxM1}gƦ0?VŪ}8v/[o)_ʕMUcᘻw⩻YOOwNF(Zҕry{Z^*?Jxk\ l̔G6/ϒQ=0+eΖ980$OgHDo<w96c^c|z}zʯۼkyϸc ={;ϸf}*i5uSiMOcto7>n>*vu@!_ŏo.ٞہA5?$]Eyo j&\2grZuX91'Ay] uSȚ]YY)tߵGy^"R>Kl/ZO2WȓnWz/sR ]<CG%imMy߁kǪpg>dvN/3̿+%6cuoСݞTӱ}s`cn6!xô{97ѿKH{|V~U;戲Ev >1{l޵VBz=goY_{govsåթkncoߞ;@nVʹa|^寸03d8|ӮVh?i ]K~jä]!0F;_d'a8=^xnSiF']u3ڌ.]X׋~%>1A! Q?:66K&z7L s (|='D tpO2E=C%v,B/(BDpXATB!\ps,CP|Όd2Yc b)L8)!bьbŧ:OCCg(v,pH .b Yݍ(t)HS/(G+0pXEB=úpCb:FH qs0Р$)".2wNcb@wgFB p De!peALU Xb@t;qgqOD2 .tXAMcT.NXP# bj_H |yy$-PSY1ttIqE qϸРw>| s//8#8Q"1wދT $?w=]2 ee%aL㺮!Zq .I !aB+<<,H e\#h qW(#TF*HCr YKXχ~ gC;+B1tde!XB8YjE!L±pOD81\wU(!j t$:K(d0!O1 Rx@~8;Bet$:K+!$qjçZ#Yx9SATZyBp;EYHDú蚋G2(pS!b;Bl:F%2B%Bø*HG\ PিD,PPWPH' a!C(d/XwKGW8,k ~:1B1tt$:He1BE19-bB}$11~q  .A!C) B$ySN)bDžbACwU .I 2 <;3-wkwV,B8 !$Q,,/ŭb;PK&!G (#Ttt$Q, __BJ9K^!C:p! C 5s::ctB8}=XLA1tde!C! q ktb:<#wZD1V20,y"WW C1꿏5կ.sP_1ttI ! A"s_cXb:|A !_O,%x?>kX<,P_lH$OGDM薐/D!<^>kŭU(#t.ǟOmRN > k9k:#?g H  uD,>ků]9cX1R2 to< ('Şj;ps1 tPSuSbdž*bBxypP{Zx1 tPS*TB6&6jB1*&lKhO?P k_x1cqW⾈4}GC^>=GK|c__|qgbACu~~x6 ߈ (g!BŌc_xq9wUŜ; :7/ǿ |Z⧿&(stXt:He„A;:>gc‡78*AF(Aw#Xǽ;:>kkqb C tw8!k?1A !Q0?X `N Ok5C3*%h5~~cqb )k98oGኔ"c_NsKAAAѓE,☣5]#1RYS:?V+ +X9FO:<|tcu p++>y |#)!x^[ŎW?HG8(;F:<|5c9X!e"ς;x" #0ќ?ppx,Pӣ),Tb-cGJ_G<%n:tx1k߃*8+1 12EY1Ogr2q\PӣoU![o>Q ƸK;5Úbbb)҄*cp:2Oc+`cGs1Mx? (tCE[LBb?. i w#ҵL:txMc:3p!XءLS(TUc‡I܍}:wk:3†!h(V,:'b~'r<)ǎF!SSLB) iw(tS\p>(B^(E2g p,ALYXtc>YPcGZ,"("(T5b(1<]TGF!ptSV(To7AP8=tg1Q+| xV(Tc~jnjZ3lg1Q C- b(E3}.s^1zќ*1!LQlP}>҅Jz^S=Cw-FsVŊ-h;JO}MSws5Lg* _FsQb/NTY'!1AQqa ?nK)BBO5:UwcA_[3 DI7)vF4kC]ZˏCZdZc R*n W$;`LoS}r"5%zZ?~jBa8KǍJJ]EÙ)GŲ&5#W"baY!'m/Э\ۗаCK=Dhh5z=du@"K C$Qmc-DIePTa""C -&6ԑuIc:U B_BѠXSDG!8Dȁ+jZ"By Y7&ZoCA~øf%: U${Hhy[ h'簞{ oa'$N}ľE´$밖fzIQeU; -*z$g l*qM~En3u}ZiKB.һk=6LL _BI[_bvFGgQp5: A,,U?#if^NZ4y|lgK7)16Ǥ%+Q;,6 Jk/LHy(k'$u!y$D㡙NS:]a.ܱ! uD3Oqwc Ef]9pTZF@,K`$JSȱk% Uℏ-5)ڒb޾J 85e`ՈZ}W ];%4{_B+D12EB Y$ %DE͋nmv1`o 2ayp6],]?VĖ]OK=n3ߑ,2'%e{*ӰǷk3ؔ5"{skXks ̒-伙uʼn(,oB,JUfC/ m7&/1qKQsQk2Jߓ:J)wV] LcldqlWx֫U,._u#(J+%ng%1\?К_ ^ܡvN>t=u>AfOTLzb-OY}$IǮ|_hIwΥ.ɗ9FR0udLq%dZ"[0¤kU3(Y%͉ )bi"BS1z HVSv1^j.dj$A#UL@ɉZ] %D~Z5 %BO.?ݢq5ox>(%"4P;x2 %hj&P#Cr~ΌiQ'w})zѧVb5s+զK1BѪ~HYt̋$LAPأ&U#2~bRh5 j'tn} sjitT*nȅzK6ZIo%[ж'VD`])qĝ Jqka )dŧ7,$՜ A>!#*qEnjEi.)><<ɳyFGMm;p#(uݓ/ K6e"@Q.e-B<.Nsyэ;Z#Uz}Z)LΫ cJJ].ƙz)e2'x#;<ؔlf9$v|(YXt&ÊYly1oAzDD~"gEԢfO.`z"BG4*o[lzA 0Kتч/cpE$H{SU IV~SS lNQh5/OWWmI< W7:T'tIFE_Q2 R' !Hu7"X4iiI[ ZNv E9#l$Hî c쏝E,ӦHcq/'t"',}u)'a#Jp'(tGYHp4=hϗ~of5{>a87b|f짣?ϱ_glhe] س.!QUcv25 ֚wMh7Jn[Vo cAʔ=+ӰoQF猑M8z}тPͬF !nMp%κ2xDiJ}B\VvDDj<4Mzt<1f;IyK~Ae?"NӝݴcÿLKiFk#0#M Hx!T-< D*+tȑJ{H35J$E"_XfҏX/'/@HR0pQ<-}3mOyV7=ߺL2ghCN;C:a8#ǔV>k4W(eG#i_f%gQ(cM\آJDXҗߨ#oEw,$EwS ]?d_V^ۓK8^OcD~AtV+u+-E eCNsy:'QгnkuTዲf2F(dJCBG %t%?S5n]ȐDؔ<$ $Ecx*yN5] NupC(Ԫǘ'9W7~_!Z eXm2ŷ6Y?$`YzQp4K< =EFPlbq,BcZBK`Iy3O O Z^Q ܒn#a~%ݎ Cc%D?$ػd{*3ycnt+;uZB55w )}>b EJ&W?d\Oj?㱗_cx#o9]Fi={C3 lmBU||NXX~)5KRsi#p'kAx}-{*_&~'J.g)kp?n,3ٽM+7^l]Rz,@ T?ɲ<)k(tI$qD|&]Zǻ[vUtq =u"ɼUcKI*_fS%4IdH2{ s^hBO4%Ʌ$ةjeut&i6) / %x$JO% j0./>3.Y~?lr~1nuI!W qxٖ7b~6d8m4T&^NMvМ6GD&mMmt3jaH|oի6F| }uJdk41ȝ6W֣x{DTXxk<2>GwcYElz5z1M. =hk좞e}wlmHTMHQ""T,i˚b;/?gK5%/'DX /BȟH(X^?($%_g~NE{NF5=}֤w7&cʆ}#'g~oj ͘=*>?e /m'dĝZwگ#[j| v^̙}N>VFuĉی25<߬n#W!x̍+vq*k}-CinrLTDDͽ̖gFJ Q.8>94!$n1r͵0 ޿IFF;)t+ͦI,@nģ)Xj+рp"0$Ek_$wg} )%w3+F!^N`o;g`o7οhky]Fv5_emFsv:}=g:|z"V8.3Wb}&)bR;2v*LR60.9sR;s n5Vt޲n>בYo|%#iM1Kt2c6Ȳ ѩMYAqrRN-xتh 1!8>2p^3܃ _)U&!ӆ5ҡo>#NQ$Gmq/q.ՠ] Jgý5CXǤa(JV4NW^wjr?}5Їv_AnPÂi*`Jcƍ},u͏) /:QncAKq"mF7-̈́VɟɳM.y5~ɹk*ȥ.v"zf fX΃b6q:^>Su]F/ WLl%{59[l|\iaVJvDR"cMxk^ZHKLuFؗ1Ix[;^:GE+*3gESy _Pj|5Q5{=JDiL-Pzz"%z"<ӾUX㸐=Wx>cR8 QS}nO;'+a8}= Esh?xו7x݀;g/X]4ȴ1|7hgV_>,0$ky!XN8!JLh$> ů+ 8|f778&KBb!.~iӑ645dօ+Ds~ \=<7KP߱GI,,hr>9tjc]GL|t!\GR4&sdbQݍaoFƅ]]%KIFEoU7Nu1 lGQ3$#]zmN-$q_Umcb= Ez ?BG/oߨT*QkŜ K*EH| zݡ{uD֬ KՉ)nЉ6?1Į% x%~cTY˧/ /'=K!9̆7a ;5?DCؚ5dM #k~!Я,BlJ ]+FDx.dlYܐ,x/ _Ŏۡ&IT!g}{!8_b*B}{"kШ)pE9Xh NX=17~&Ȑ? - &?C@5Y=> OǤ|dJ2ʚl;=!F4=,ym7Sn9bmSѨ*G:5cCx-qvN^!+ NGōmUr|+3KޅM렗xs&^aL'[]Iꏱ#.soGfc֯&[IZjrǮ*P`Jw00Iz/Dz}h|FEiRzւ%/x,+Ey_{=\H,K:GA)Ƣ?v*8(=]Kx/ ns"\Д{a 7 ~_Br,q/HJxNzHyke D6솎Dc;<<FVbƜ2,~*>?|  s 6Ǚe\&EBSBrTeGēcÅ=MRhiC[}uh'Pj7˨W4Ƶ4y~V--A6 D %E,/'F?+t}WE/Bs@dyDNca/cG3zeS)̏&؝g'hp- ^gkt,;53a]~ȳo =/x]x#B̍s*tKG} W@[ga%4˹g O0M{E9%=+sshv=Ȟ\&*Q҄߱,q;M#~XxX|/ O)j$%=U.KN)%P>ȯ}=>O)"no/Bx5ǐ8Oq1Gs?cu?ᏒgoddgCMpY>%WXAFƖhkwQFgxߞ9cUd)n+ZÚaoM] [3щE9W¼ NO$}0Q M>f Mpx-?\%ǻP-vDE>⨻|9݋NGTFu%|;Ah̗Mm#Pۑ[ZDcRxҒoQ*LΦ ?^MV.صĊu';NЃCPoezlüI~bKȗn$Jn$¥H%WxE V13^@$LԶ7cCXc_u{^bxqb&3IsHz`xKAu#GuV4t<] ,b$;}-MW/ x1Ob#aCw59'oncKj h5\cKљa b{#W ݵ)ؔȓq4]%۸_Fcƌ-/lu.DI7D;z4ak fj$7C=[j#K~dh]+:7*kײueM9.5ӗgZ}9g.qK'm\h<65723FS)i<K0m-kJfUIeYN<7ɸɣVM1S(z`k8Z"%m%/z5Z*^$E0&ӗ Ȳȭi#ZP펴WFwPNj$jByS(JJ9Q/[p,*JĜ(* Ey lտ+`M=غ[zDl q4Hp8$Ɨz*j7^H'q4ihּ~ 1ggd>ba7Mi#cgO {P<=hF=b끓EvYdx8n2"WuBUrڶUюΌ?'촔*MHks.jLO9{NF %׬KHkE7L.V7mtec_I5/a+XlR띅VAt F* i!'IӅ oȰ{5SK7Dlqq/[ׂeiWs̼k-2X[oq"JtY=:80?̉HC__#$//%!^sb&ɑ8cO*qKB7PO Hͭ3ˁb[ipQ='yKx0.xkE3أC·,}kP֏f}m%.ӜO+A׿q;o_c+a [`zrJ7* Ho\mix2aAF}J["ލHvCQu%}1;nq(Z1ߩ `OU"U:=Q#ib(_eUؔeȔ֍Zb++gZB5M%;o$l[;iBJOܱBĉiZ>ϐ,w߁bHE/'{b^eOг! J>Br'p,7c5ꦲEyUQ kBKBHI:a~H]D^}J'[%?gmH_ք*'<h~ƞ! 01>4xݡotCc}ܿCރש4sc^rK'7| ~:hJ{X5jc*_:Iں'ѷ_< 2oay&N´⫡я-q3M:B| BNmE[žƳK(#YFbkOvE*߁R+uخ)=0.Iv/jq#^x$b.Lbnʼneķ.J^ GN#A7u[Vp58&QcҵCCUPc5n4?Nl7T<}ʔB̽F薻7{U-omԣu4T"a>]| [^ I_p kkb7MrEKBSTŅÆrM*&i{[v2Hݽ8| k/h'n(I{z V,5R8*`J%=fŝq՞ Jx=ϡ+š{BcׅO"с9I&Gn $own}F}=L'7-{Ԙg;,ڕУ4ӏ,lSQuەz1,s- SSPY%JcGbx/1XX_b 8'4!'4DzʱiRqpsB5ƕ4ܶByyCJӟcM-?L:JG^'"r<[[F?x^_~FK^w_4? Ml=m1>3xt,Mj9K!{w Feh)s &M$c㑏C#8c#CSSz%K7+n}2>;5S¸΅n{ 1XǸiʢ%fjobeo\OB9_"Vܦ>ֺf;D\HVD; %t%xc8boZ4M߉y)%{Aei4-\D+q^Z4빆^ d|3/,-0g _boOBl]Ĺu11*  9WKL#LTjƞt l`{:>zQR3zƦpA4{45!:3g{>G?%쒦<`d`Rٺ'+d BQs6=D[3[Qhҋ`(Krj to P2'S=k{e[n^53G-N㸔0NEkRS:D\f ^i0jVYq$kňVy]1顐]|XXYl%X߮5Q[;-F!L ;=!hyNGJ_L}ا3⾆O<ߠPڂm8qGCϲHׄ|8cn6=x}9SA&\,u%-T2y˱ܞ1;55}#|θz'}gRk;y9cf`^ _p$+D3GQ.F7>x݂#*oɫZⴵmlQNlFj< _EQެY| sLgߵ:hA'Mm%B׀5i{BֈH<D>m8zr,NEmNvCx_cr!z%/c{?sbI'ܾԸȱ>?G~Pa7mRx[ e_e/|Hj[Htj=uX~>LM;EJ׬rmvI!##/fK80ZI ;Mt$g3zdNUQ?nE=casT|5!">ĝkшA[NbS_ga!wؕ dI{g^ϋxww D= >DLo:<_Lxߐ7d)cOxdK9ՅWq ƣ64YbWD7, &7N .CQ0dn:1P}:dw_fR3Fb-$n\>>xb͙k:5F(fۤ$۶VZ[ ouOM&~rY4T_:P$aQ{4-S aNriZ%t"1Tc("ּxFGʓ&WYm iߍ ?'׵)$ve߁/ģ}ZYsʣ)&hĎ GQ!?5~?#|b~[ɯbgBp'"Ҿ"y,?+ݙ4Luጦ ĽiNk#u-q'|7gjЅŝͱ H<bu'gtlD_I㱳xĥ/bQ;w)%iтgГƄ'{><〥# (7&/ _LGlM42Cx_43άkyLc~OGc[k̨e1c}\hX}:P7肝L{?nOLh7mテSR'/~J2ŷ)Wg2;7k\ Zvnt"E 3'2~GMLF6ġoiƎAejEҸ5ɖ<$D&Qh*vQS v1z9r(LZ}JW%nL\D1hہ,6nhNFMZ#hٟ7Q dVW0tn?r%l'xBRJа04GlY,#5$by?l"~=ZyhB1ȯ|?NG󾌌1_̏J>i'Ʒqȃ#x{}Iu)[N<"fojv|#ݙߙ/cSEƦ?5ܙ5DVEL| ׫pb%˻%a4噅zA8cN?Hwȳ:.۱;)v,{-Zj*<-ڃy|m O26MJn580OrZ#bnu40܊~O>Bb'V`/s-/Jw\ Nbo ZؔG#B_bTVh=8 %xBSkBfَ_S񬾅\^Gȟн%C2'O胗QycOだhN nƷqnΣG&C߂. 26?Z(7nEKݓ=Tߵ._C7 7PWhneu239cu}m po{i{+#[%oRlfvW4FѢN!ڒZuʝ rN~Ȳy#S8I\ztؐb>'2,F,O W%(V+sJ!CCFs}$t)PӗF޻OYo;; f,:Lњ!wSOUאBJ, {HuڂN|="r#F|2yN`xcCz4=Woȏ S7 r3t*^Hwь+޽Y{|/jhCh$;'fy X( Yъcn/ n$7'@z> n'4Q>Pvf!ݏnş9EyG1}}Q4?kyeZg7'{zjJЛo1;oPӹ~Skܣ3S=+`(}nz9JUqJzjQ| | O8&nO1E ~$gIL]L,i!b:-V[~TV/|"ah=a}'Yuqݝ"Zm/-({hZEyt0<el_/dh|}YSnvM5{C=,}a}KS41tI2a5$uCEנD׏GbH O3o#G1WxCoGatD'({tq?aq0Oby _G>nGO6>r+ZvHo&Pnd{}GJPh#$[x$󑥽WMEW1DTP8qk6,jؗ*ZR2~ԘxWyaS /+ӔC(5+ˌp _b+[N~kK-ng+'Omr+{2~p:K񼞢\9ȫn|z.p=8X~a=w}$,[~dzH oMȃ\cWOLz<#&=>Pߍ |Nm ^ƶ6}p7j57ԟ8-Dۏ=oÜ2V{Xnˁx4.cP wG">Bju4+Zo}QTۈ]^;H =bagDŽK}jdN:^Ĭߢfz OdQl'[jw% P+,R?R1iKtO[WJp44ȑ[zKl=nlb+}!!){Kof:a]?3lx0pf0dw`4~cxǫ ;'ȿ o41o4ō-r?1 2> ?ICyRrq 2n?n&ΣA#GccKXT"2d0Vxhz(j77{o︕ ֵ:_b7YZZ$oW[rSkWq3/f6ҕվ-evꍾ"1 6U H]m8Ng)бtbgц2kSTPuC0C׾$@=[&{5.Yh2*t=Fbj̴zׁŦXQbNQv6FTr?w|hpjƗǻ{ RN Khy2!~y2v>}iy~x#+>m)k1Mj6Z F;Xw ۷hmc6ebVB*OICƸ&L;ʻ LU`J|ecQ;]~⤔&A |5N>]|n+kx;Y*hMIxȜV?de0QOr?exE:1%ц']EyhEVu1hy%Rl5{9|/pL x{\2},0v8>RH9FSdq9at5{=o'A[i;`oWS# # b?C4aC,<:THRd%nq 7 Rn9#Li|4a*շIX7V=*qRȢHS7C4OwEeVֽKRg'M+jk(&2F ѥe6Gk:(wxI<: wԢo6-[W8=g24of4Wi Q׷A3hNC5ͯc|~I?q`ᯂ|i7w/k嚾GpǑbv'^8~QxB>c&dka2;gz2~Q}S&܍]+O>+bȒ} bX 0*tWYGf$ )ISJ Fe6YC7}&a5r ag4IK:G_M +{?t(u޼;+%dp%8vUi+9'o8eD Ƹ+ɏuKm߱8oUdI|jY bXƕ(ie%LF~7fsRC@:;IKm/i % O2n 𘆾?^x7NO7=yO\nXڙ$;F{&Cw?MNd$M<jАCXnS':/M,w1 scL^ .'yZ ykvK3.LwMV*Oe5J#ih;"Y4wkBZ% VM,Uk_X2~XE-ے)T:ܐE5ה6J9+LKY}W2=-סo }Gg}jQYBUsv`@N<=} NO?{[Zp5/~s?ML=v1&&[}{;O13Dn7)ؑ9ox)6!hьv3wfB\Llhĥ386CKn~ͼqܦMQGgЯk2l;P]D:'v"ub\ri/TFv騸FyfcY[6m;kQKV}hMG7 )[u)&V{R6cF61Ii*x)i]c <^q/ftRft GN@*w$?c|CL k4q<= '44D? zDLez _1>gzP{ɰs=vysKY?u*v;mQ-|3%Ȑۋ.뢡Hv U-Ŝ-1dj+M}$_DBT&&QXp$-{HHۮp| D;WbÚr_N1en +=Du0^Ħ(jvaM'-&;!x,Kk W'!۩%,/.Ė;.οG}ҏ'"gVքx #Sf׆7,+o? j$g9M~{#o6;rHzA< ~hKFȾ!"|Ȱb/ỵ6vWG̱HjLYp"hy|L8{`w4;tD5Cb[MJ!vVZ)?)6oW (OfcIP3f:'RNdTٙ:as0"]q9*fIXF7>IK#LS ; kCQ !s2S=bf&%"U[2aFQ JYVEU$R'bse aZkY*lV : #WFx9; lς7ӗ4IGۛw׮7owCSXR:Y{ՓZ4kUZwcsˑ%C}dsfʜBOA>ꡨwFc|^؜ǿyZԿ6ښf秤x4'& z_ Vkot.#bƢZ О%ݒYʋ4shSM}>x& d7j#oae.k`Fd41G}N<DMD'}5Ԃy5eiԈzw(rR[#a}uuD-aIC8K&44#ƵX yPJZ{0k6r/:Z*7+(LiW+mvؒ؟,bXEƝGn%\ Ajk|zٕ*!L3/fodp{"T#KJ!TI"BDU_bJ{YW$q mS⹞xӸԩb&k-x[mF'ǡTiM=ඈQqa'457r}p6n`p#z5𐜒~0<(2Eߒ#~ġVvE|_['i695LizTH:>y~bB]ē![pH1U2_ H'a}IJxB]lI8;}Nn:xSJ,tӧw2zd ۃF2[^{N`i֕/qyQ(׶^ǕThb,1(ȳ" CBC̘h:W|V9b=JL u/55;, hIXR '5 $G&Q"FE/Oi*X,y3nOBEЅ 3i_c0Qpoe3qr)KUDRܢfVZLԉjT=Q5AKwVG-$j!vF TnxB6%ri5ZT'Qy1?;1fwHR&uCcG)%ќ3c,s:|2 X[n+-e+ɬْ?: NGT|') {E,NN1Uj݇Y1#fvh_bv'eQ9""w6+9g䑺>" {~d })- |5e߇G,YNOzȷ5RG.>:JԕiWNu:5ôv+HKP.߲rߠ|K H:߃ .HȒy1Y^ܪ[hęRӇ/%ƣJo?谨xfTlq44-o;l3jm*Qbɮ~ʨ鳡;EӁ0pa'B:~jivC¾zD'jN<$\`ۓW˷&X_(NEȖG?K+C6u'ii韱>6=:ocCeM[Kga,icS?nRÚJT[J>JY6cM1,H-|QzC\\ Eehv:X2BGYǡCOخ(ޯۡOAa^Mw]H #aT2\u&B@KHvp<24 g8Ŀe?Hj?d! GRxe>?Q_'ٕ dS%<+ KbbKBMk#N$0o/{PҌөlK.dꟴQ1-*r<&:>Iha^mȉr+,R~OYyD6pFJ۩-|_(T(HFꕣȕt0] 4 ÁS~WК7/m%%o#9ލw:v29mc*A3s{.["9Z7TT5Mj3&'e&Wh~?w,/qg(Ji2\_n1d@~??SG" FBI _ WAkB]辂HbӇt*ڮ >*% $ȩV^Mʳԍ`ד]ŕ; كWYƆWFb1޻Pם; IbqG]TAƷL9l98plEVwSWZ Vӧ}غ$"{6Y'Չ$)-7Bc_DV⦛|!!$ ZIipLXMmGx4"kp'RҦ' F_*ЂR*McIuq\TezC]?I!3ќZ ѓN#dN}mt$0'&z0'"[Oc>~Y14p' !e)fyةoG?rB[Q;3Ʀ}(`q[CƜ mZgObШ憧Y]*#q 2ixJ$+ ocQb{N;_ŦBy[74AҾFyoCTq'2^kС5"3 =|iw8 s'Y50Gr,ͿfTb _b#zwhkf;Ky__.ܿ?g,MB[FЦ*m0U.-9ZٟSb7%) ŶӷbvK>kQ+ٺ"ZD90P755ZLE݋atJ).:Ӄ%n1ڰ}oao,:\1cʂcS銗طudf=17 {!*CXxCMHXUhMuP4hiHcDWj4a[)Λ'ݾnnoBHLt{%F&H KK\)дs kT q0ӘXcdFNKFP4A1MpZ5餲x14e#}5kx>(t/){:/H Я?!tD [5;>;6˧Hwɓ4@G=xeɧ5|A}ck0 /1'ĢP} MJMt?cBcg"dߨ$X:U]rab$Fh%IM[Qö}ĩhu,^{ K/醧 B+G̩gޭ&,]mJ/=hYU͔3 C E;>:گc4H"n0ĥhcfzs,(_dj5=?Gq|KII be=h_04Ufިk_V'ʧڞTu$A=?0w?E"%*F'[ c찐h$ΤMm"c>Ą^EY G]]RbIyCT,-9p`,z_s]~\BriL.#K>JlXYl0Nf؜-7jF۠ _-8]({O1n$us&I:e4q~ ~yrQsQ GބQ^6։}B 5wDrcƭ4MvE^ W$$9ti:Wme)why)=&ŷ)dґv0zXB{4Pl9C&z: R !LLSǕv?%ȗ0]1a8bȫ}b޴/I3bd#CK%A$ш$wDHW Oln7G.Ě3װ/%v^<9yoNDuضXq)i_N6]iit\AKFlԯlг=HR%=Dbk?% Ie5fy]xFB9Ɣ&¹ݓ!G ɐXď/Ѝ{!KWd5'ͭUtԚ_,aZ.]U2Wr(;=r>8#ΨJH4L1rY!133"V& 2)7T\Zˊ]Y$4)nKoviYӕ-|i|ƣttF!Q!w!+x(,ʨ%;.GoI2(?bľĠ Lz\L4UCIk75RM*>2;o]GeaI.a8p?#RJ5u r: 63KfO)u=a@}Iz6z&L Or%׭_]_,aG<Z)`ٖ?5^TbnkajKFTk|HݬE2,mĘ4)IUCuN*J%I-I%;E!I"[%ҪyR&}\ r5cEKxدymzzC<} >]t0J;1kbď󾄠JfHK <|ct$7ȱ#?i ?=G !8(X/ԧ1)nƄSIVԞSX&l\TMB´jF8청]Fy븫fr%;D,"1crk>Z-IcQ|N g0Y6DVӼDCka"JountK+.K7amדW=b)7Iz깽\Znmݶc2L{p:yM0bPKSM2ǚr&2.ԕ[('3 xH37 bQ>JESX JOп8,(~.p,,bȈ bZ=g(8xEfq&, y<`X "pHd;b3ɧ# Dz'TŅ%"4f:poQY=woLňhFaZ[F%L2ha]v^JZ*4Xyä3xO 5Ȇ D`Պ+Vd̻UÕEr*?eMpmǔ=4P)uSQ 煁:ZjyS o-S+FBUZ\BBKw$|l!r$ i;Q[&5l~3 9&/GƯ>}HBR/zBq(Di>Qك5 ?OZۓ-Q>j7 K! j9_z}'g"sYD@YJ%CQ'%1'lJ3$5jby!14SQ/6f/XK)lj蟣M$f=4/gX7-"ѝltb~J6nF$T5 ("n)!N,Ls RVtyb4HZjjIɦBobo*%] 5-xlA6d{#/q̳#*=oτ X' 83%PG)k;er3 -蒑)f"=1jSBjF41\{C&T%_?R=ǕؔO{\;J_`Ĉ{Ď[;4|F! fOd"y3|w/ocBS?HH!qo+nEI^/'!G],T?(ƣS#i%*JМ $IQAB|Xcѣa]p3jbKHK8J9B[u,7Ȇt2iDxƷ83w"{x*ըF4"V dCY0l1rEza}cMP:tu(%n[H'vz7wqAiC*-7b'eAC`R2h$o%*V%Pp0gDLRc<(qNUhO r]<"N3JZPeL:{"3!5WKWxѤP8hRӒjN7+Mm ,IO]@4K Qx_9Fͥ[VpDДs@biBo ub•|_XZc#]C,TwDAiC5~'{a?Ho~ 6%odz*yJz!v3{Jy^v*˺#q!佞QzD(YH\*]% "J2 1 .uEc'"onqք Z+KVIPǢ˼ d."ֳM:&+F"ٱC*zT6^-fIB[iDJ )M+L4}0֔D C%6aڄyUc2RĤAC;#ŭ#W%:4-/MCjrWR`MopJȓL -p?B{KeZ$>p%8X"oaYlu!$VuN{_#%$4G):ג"IYݎ60a:,$iW,mԸkr xmdNicUCЂ J  Ȕ >+ш򾈲Ȓ#5`[ ZJd!q? }k,Yd].z[[C?NW6ꅷcZodj$6a+-!ք_C(v#4E2WЕNt!gFӰ}`]SG.!㝍[Q+tn$bj!ƪC1 Lm[Y- :D%K۰F?0P%Z|iB|n[Äh6g-t&V5CTwǜ(dq44O <k#|ctPW𔛋R8\%rNgzeP3Qq!ؤO$_%B [I "4+\FgDZQGBJ2/F&O_ԍyơE 4BB2 #]qNvYJDW_(L^a8,bI12+?D7FwzbTE7?,Kd}A2)/$%qi[>H$C$tecYBC?7X]܌,gضI~g%Q]HB溛ןeְF>0%.>E|@][e5WАZʜbGOfv.e/bYUb<+%;D;8!; 0~M4fCd7LbX=`$jTVڱh!aD]2Kw}<эzpOK>فuC#u%%"BF# 5*q$5sB%C)'%xBW,hؒ$?۫ BVQBcZY! uɦ<]R[]BB$Nڋ"y-547M[%9B$!bgy-{12G*E3!|KzO(/js&_YA龏\^"bGm'Z (0eּK!wh$oAnw%aSc%*DJ>43᯲alY☝N }_0\O)g-^Q)BL,0p'1,G o0b>ħ棴SY 3kLv*zh013LѳՍv:| <(|kW Oc ڪvN;cLZy J9g`%!x?.kyىBˡe1+oc_b\kk zFAm ySз(9va n~$G"<5,Oq3ɇ} d"z@~H]Hmuf!Y]3a"JK~H‹XF2S>DyON WײKƼ˯Gr5Xp~ۿrptQ?WW?OhYCOx?P4==?fPmסN !}TP/e(L(d|5hP (NyPބ[Q%/✶~Dp$񗸇}|O=Cs:}6Qf_[W&oЂD~KJ]O% Z~zHjԪc+#hˍP`y;Nl_L!#N#(O#e+z 1 qn7c|W T~* =xƅyI endstream endobj 6 0 obj <> stream xMO0 >OZf糑HIp Vv$-~uP|# ,Q*AK6XOn "_ԸfHjUb_x XۥG 0.Ёi`めobzT%VkXxX)0 Y*5avd- (lLXSD"c &.yHSn> stream xQMK@ﯘtfBmZ[ A> stream xPMK1W̹t2eA[ z[X UUڋ$Z-݅L潷 js1[gY](Ea^Pzn)EL K>?1VkW۽ jg^fVsB,[#M;/(ߌWr&Zƪjж&Uwd+Q8T¨m endstream endobj 13 0 obj 342 endobj 15 0 obj <> stream xSMKA ϯYd>vVX **7ZElag&yy2 { 6 mMww5[({݌$)G>q+8oi,nb`l6{>8- wpDa#M' $6Fx"DL21N@ׂBrlnZ:(po۪@Q36-z p8Rm=ځ 05,IxMͬ8IrlNk$okzK'EjVyYeԄcV, wh'%NIN1ȋM[{f<&-}B0k(CV^8GN$#GsaHڢ,!b1r{d8>Ӕ(ה~b)&Ý:'b'l9JX"e&lQ7 endstream endobj 16 0 obj 438 endobj 18 0 obj <> stream xPMk0 W\+rC-a촭h/儱n1؊߇9-ALVRbauz58LZԪ&(-%c[?fu{`~pv1f4>ϰ`w v|77cq'@JSBzRK zd)ǻI$b 2[xp17.dde(n]ʎyDŽ[riŽs=¢ V)b?ǑiٺY)|%Si.3\uJNΗbǭoֲ= ;j)0!vd,gk8Ԅ|1r#+e ?  endstream endobj 19 0 obj 335 endobj 21 0 obj <> stream xRKK@ ϯY&NJuAo '*If>Xf˗WlaH7-޹#xqnjNAg(>O$j裻?r+أOojKz㧬;9_X+ۯF糰N0HM<[)f JP1q=^ԌIGˉzbF&O훥=sA [Lp9#jVowYu[/.<᲎'ALM|i[{\ڙ9.̞'c(M 9gYv;2:j0x(ٺFnI$nI?$GEⳁ::nߪtv8q"E%OL*uZ(A>! .S3p 0LRw endstream endobj 22 0 obj 426 endobj 24 0 obj <> stream xPMK1W̹t& ,˶I"^N>VZmޛ7Ka@=^>A^WʢP*.$ʾB>\?6kV 'nî'Q, ]wiwM#>zy NDBLVt*l'q2R@Qw!7kebkiI>6ԑ!xdBiizf0Bϖre&@2/yuL%{-^gI1J}i`[wY aB2Pq[l1=ZunR47z endstream endobj 25 0 obj 334 endobj 27 0 obj <> stream xRMk0W9ΌF,0:`MI.ɛ&MXJm53O3 ; 6yHbo3xt>p88MJb}XIOww>}FX;^`l6]ga (D ܍HewKM]<#<"r%y$},ŏ|_0HGG (w{ޤihD}ِ䋀sY6ei@m(uڐ <}L,=>WIL].bo$Cpá"ڏz,ߺr|R(§g+dkZuKR?{N壗 ߺ%C'9wFwKOX(~>}1}d҅36@BFu> stream xMO0 >OZ$m1 n*q@.}1VJZ7)Z* W0x1?LؚTeD>Ĭ :ߍa,ǭNmr` cbHTC 0[jn\ %[&]m#x j\I7 bZnY:1$l0.j)Mu&@ǦU#"+{T7N9P.T$SiPÀ:t|e{ c'8HH"Qr973[ TB&>}nYVؾϋ endstream endobj 31 0 obj 385 endobj 33 0 obj <> stream xSKk@s<!ڛACmZJܒ\;)ii6H;37Oan# tkܲwû=`ݗꈧAެ jk|=;^>Sl9p4q8_-\B k1C2 z z?`A:@L@b@ sa0]M( #LZu z&ڎܐLb(5=NڋhXu Gg\XJ]虌VH ,%kd"wX/@tpNW6,:n3joҐ _, drPO2S=)jeΒغ*/2$/b> stream xMk1EWܵ`|yI&  n ЅjkEn,,H{!ŝ`LbLPͷo,s! Agoϣ =aB :ԜƍϖfcuADTg/6ZxCŶN'Zc8dDab^>J!TPp 坕ȥJ*7Y jyV endstream endobj 37 0 obj 213 endobj 39 0 obj <> stream x1k0+nD9=Kv C P:MK[?ϖ=@>G. t.\XGwyZK> stream x=k0Wrz|AJi qKG⡅P*gsEU;Cg\>C^ %$Bi0#^̍Vo,_Ϯ:<(c˅G:4m:6$= Kf6t9;.w5$UD R6Yrxa֓ U endstream endobj 43 0 obj 206 endobj 45 0 obj <> stream xMKAD+pR3!<'M*ſoNd.5ԫGy| nd >c~7\`|DJPw9ld/}}M,s$)bv]К-D;+"$c̓ !OP{-< qZ*UT\~lámPVlu>&+Tx endstream endobj 46 0 obj 205 endobj 48 0 obj <> stream x7ml[uGJ,cn阗}k)If;EK"EYE}0!,(!'v+ԠudI #x~2%bv}f _~K#ѲXO<daa>=/дSp FyUlM«qZ`O7aLpEgd<l&b;4݋+<; W>wC3VnVW~#wӶ}o +䝴5SSxlrb|,:z`84w,{ÇwuW[\͛ v(I e)$ɑNڑ IAejöGD8I |kI# AS2X$.z05~@dj,)AemG6#EKCFx.[ %1FR/+]Pkބ&RF%plfnq!9mDכ2Z΂~nh7IcZ\>餯%-(nU U0|F4`tܹbtJ!Ǭ uI {KՏ#-"[vG@C7xˆ;V WUyq2-QTTK!L7DhbqFJfᄵqة!iVF ~{%A.,6`Z09ab1*cq0~_c*akJK!٨Lcwa\Fo^ $,Ũ9j`Pk S8[F{ڶCavBR(i};DG|f#LƍA٪X@ 9 bdlearqb[ H,-#犆3fK Vn$~=j<1y}dx_m}5.)?ٗF^m?*0*#22YGo*k pcF (4hw96\!a*G Xʂ#l6 a76Xh!Z㜼H*۔DЌ|T||EG}l`bg%DӬQ0&v, ~AX&(b4KJIc^F5 ވ-JT`ap*#Iwյ*J.~Ǜw_i瑏y'QP{'l4a].=_sw)\S1L[.`"hI.vfjIH+zfEEI3G%tW'~2jMٮ5gԢ*i8fKMX0jpr"uRY]/UVƏϖefYfy}&&Fh %IW[sӘ+_jy&0$$!FA x>|#Ξ~AQď a|yzp9y6D7J.;Q]\ ڋTC>8>!I"\ 7?!~B'ߑHKqsӷo-ert9\ZrC}NA/{n~^ nnt߈ި0no1ZKK?,\8y хu!J".ϋ/|s/+K /ln _#dz0'c ܖWQ*q AMݗ}|ᲽlKϊg.=#\>'hZyҁbݠtptsNMu{;<m(=b8*u1y3z;*M-ag40*. *^vtr\ wx"=A``_l8=H^ojzX ;`x73m?-F1gL X 8WyStB/Nɥ7ظ2>l8 rh`kplh8o@lTF'x6Oča#@\׶C_BtCxWfRF4|Gi\\}GPq ˜>Sik9l.x8 endstream endobj 49 0 obj 3854 endobj 50 0 obj <> endobj 51 0 obj <> stream x]AO 96О&f&=?´؁L)VM<@x7kQ13.qe0HU5fߖsGcl_[2opzqwȁ&8_{'Hj[8=O6=u.;"_mKuw=.:dKƘۭUHw>,K1)t~ڀ[ITߓbک}Ymu endstream endobj 52 0 obj <> endobj 53 0 obj <> stream x{{|SU^瑓w$M{ 9mHiKë4Ţ(ЀІ>hT*TFA`Q@PPD eE~쓔{RrZkkއj>=F/تlهX$YU^ם%'Dؿ`ҺK"ĐFH> M2dD=!`Zn~1cf_XTz - ` rchQcnhb'KV]|fB'njYϝ}`GӴϓztד Ko)4 a7ı'˳(ylC|nĕq+=yFrq 4H_E9dBA9װW6?ۊ ukEO x՜ӧM LeWO*xW]1vQ#G ;$gLOFeZ&^'j ϱ 9 UQ6K<ŞPU?qHN**(pٞR rƟP/pUԏuPUJ%Xd҅GX^35eӊ+؂JH+GK׷WGPCXc):-0Ga֨t#-DS+'J!9&D"(˨fBT,EtZޓ~A _5xjBUDmgZAA|‘Fs<^kٴ~.v Q> 8wM̄(LHW>R 꺽#WvO=\& dqR`RUL+&MSeJB_'}n ZP9tE |DۦVu̗7eLG㘡`U۲Q.kR5:mu21KiY¼ QI5 rF%a n&Z1|'aV\A6 bOqUz2Qѥ^+X3V'?[p&ɌyQg|*b7LM͢ QRUo+J.nLx; }>2'* he5uQwTNң pSQT54SR^Q6S6uvŨ *Bae_S!l,\Hl -K?Q!K_ *B?V$Q vbNa+44MTτR)=~0c  "hJ)HѥK1zS z?PMQr\T*S,TIGt(3Zz+7zTK/AOJvlzgHPIQU@Y4]{~e1׏Vx&մ{WOnnQ2(+?$]=X5uVM]cU{`&TD\2!~ eT*RQ8MÊK1xXh  &`@2*̢vM;1'9iUX̯Z70FF h/B^SF`i|~IhC *1b`3Ď+4W=N6n+rb(۫b#NQiCA4S;>WE Hk& Nm8((0"zTj|TJ!(qD 0nd@~#Y +jyCPVZ}Vtkz5z=q2{_~~>_?DR<!kIvjEiaS%s2$RL֢kuڭNנ d "\y^,T E V IΓ .YuiVƎ> a{ճC?ޏu^k{iL²3coCfuEkӝ3Aa2粬ّ 甉U45(VRdYj(Yf H@[ Osopuq7Zmy^*#VGgd6dhjw F:4 (W`bv'l~OK/c<&5}U5s4 ֺҾm5ܘf[!ОXn`4o[pG9&fjE:ǫ<D<~&II Fg̘{|,g6tƁ ١ާ١̬̱Yt׽0fbT u8C'x16-<̓3P[yXiCPQY42- 0ߟET~}e0>~(;q pI*izHѧI6N!3Z~GD }vA']*p+]/=6BW`AuƂJ"u| xhf0,Î{|sݰxL39SscE:u#V2/yZ-Uf^LAmr࿹bU9 Z΋eN>;fDី=|A 1҇˅*L?ko7=ٞh5JWLo_x팕YR˦˜] IY ;.žH훝RstWн@ RViE9LSS"tam Dpc&™^"a E]+oj3`Q߿w<ɍ>@ߒJB6QԑT]fsjYGKǙcjU^ڟI)nlϭEmk ;w{/I?Y`YNS )psnҤ=c@+d#t!jFh3BUF=>^WX{ujgB]#GsG5]~yN6g ѧoLߒ֊7yE--^l@nx5YSԌ4o\^zecge^quH 3C؟ifqNע"Xѯ53@q9i8CH=/(1 zF>G }|W9Qyo߯qm$b.Ǩ߄1{0K ƧP ێ0oKpM½L2\Hq[ZYV8$XY+1P ! lΆlȎOR+#rnzHR|M}cf~.x.7_?|˝7,-Z[^> FpCj>G6|ktw9G8@*Ii%᪮!~ ߮1hFŀߜ] $;כqҟ/4Գ@,da5f53he `36:T y6{m+,lzc#A#`1{w]{)5GL1?b5J3mn,gPrͼMaysewEGDvF eZ;bo'upgGؙ?ao1G]؆س{V\~qf]nqjxޙVk$9K'k6`!J<3=ug))reAY?4~ R8V Vi`&j@&O}>\RJ`Z^%]s?\&Fa8 )N웮i'=ysS 0gbݻپW\xd/.uI3Ge;s˔g_}pOz6t1^;r0v8/~+- mlo\d93bg8,x뼊ۮUNv|\^Hc< `AL"t~8+R|7MzŭI%#Q"5(g Ze^DY1*:]Ӂ<´9HɘF׻^> wʣ'7IU`@}id:9̄s4ͦm&A$%H\'1'GY;MX{-mSV-xW>lUS7VliF7>?v{d-eۯ  Hgve"!S"-!6ZVJ䋀 ޡZT9!|7姱iB`%b8Ac6 G'(ukd,"ّDUEQEB/o'̻UDҐ\& Ow0'^qwq_6mR)d'Bb@'ҁ67|9YR @R/4R#@HF%M48jZZVW1[qU`0/ݮHЍX%%CzDwęN#/ Iz,K#8_?v Ul=wM˛o\qKW^޽?gKu[~X1Z¡,aQlu@r@6p1~ 32iLl9L,vߑW˾̓ k_~7ؚ ? 5/^87ģy"F[WӸ" `]YЙY]\f6WdRRXh.>c.~UV-UŠ`U7b;],xeEط//>|zű8=Y_A'8  ncQn#g6V#_hOYZel3n5vOS0:GcGvEAih()V*b`KO:4WB6?IGǢX+B1V#V#Ir4?:h!NpNJʠĢ ~Y't mJY}y$Mu I=gt`Ḍ5_CƾX l߷:6zXv 7o5'{45|{14k TI<+qN?9` L~,`mq;U]Jq~aQNL-h?[zC@~=7EzL^x4H?}4'{r37>үS=k!%,#Lz z.Y Y`4(oY,2on"K=3e GcL8d[VY3s?C厵l s"cKDؒGyxMWw&.ZSIU#b0j4@ИtJh6;AEdAyB JN6 TI _/J3~s*>{d2SV `dMkR6bΜ?wWl^xk^n! пeWӏVdѾPߪزԊgXD=o44b#L4k,uFp3FU#%:Wnʘg:c瀆w )>{$[aG[r]hEN57]IeVEബ@0SbEB f/|S^8䅧 z c(V6EV//H^8Ӵqz/x)煳^8`mo0Ž SJ[Pe '\*VLOx-yJ|/yxĕmާ q.[x^b&/s>sLIY23k_vC o]Ǝr;3xћ[/FfϿaQ޷u󎾖} =ў$#*YAվ~ k4'4h,*Z@ N&s޷ߨi}㲄c}|@Ҫ{st3OL{ܰӉM/ f_0cJI%T֌U rImq/5 IĊx{Տ?$4اc?3o|ۿ7 |c/|QbGaխHp/)pTVq*v Z X-V@ F(9{ /@긭PH|-'%A 6H%f $-]-͖AJ`Ko%Tci 6I\o Lx%H@/ - zFV IP)5IEO4[G%X.1s( 0$0J0IpR㒿 I%nIs$ B7S*:GnKpJ4RjHGSR!h]NdF#h3+o y{1W^/Bٔsu\s*`V }Fؒ|߾E<)jޟ:r gho;a?~%98sMűWaQSh8}byC X=\yG^4hʃ{Ùb'b= dZxpx>d{W>]WsR^Zͦ+98, IbH&"& LSLJ"S3z[S!z'=-ℋ;eUrn$=ԳfnؿTvat-fpmf 4kqdm9)* Ը` ƻ` 2]`sコ.w.M?/P|ԫCڠ7=D]]2J &Pp.\p.G#;]qi@qAGB='l/u}¬5m8^4+/M0"tIsrsm_lw/Ū&߭޵43k̞?}:[cfs[ױ#٢X^R>i((ٓX[}qסux?ct8XN7qp+w2rsd޹8B/<1<ދ^G8"aK #xFجfi2^])Ybb~ޅd{c1_s5i+~VA^z2ԛv;+HlXk`tAX9TαfwCjFEL![)->YM\P4}}l7z$~mAoۙ-*`ۃ`g=#\Fl҃& Q3l5Cf2C Y`JE[:k8m⚉cE& K*4GQѐZwݒD -XiǰRfP.D D.'"|!"*^a}&A?P ΊE =",aW00miN&3Qֈp{.R KDT z oaPDH#ϋMD0 OXHVʺGy >L|hU.wz\,,XzW` {\+ !aCy[wUuwfaVNL )rs2AV]lNL{wR87Jl_X?߹X?XfHYi|5 Wb]\`~(*B]TOyZ׀0e\yNRݤ^irEq.`2/ib;G| Iܡy@8apBQ[]=&,cNIXM!p1xig,,wY=dH٣796;Lsp> E '7*vZe'MQ?%('ȑF94wh TcC%iXԼ oJd24m-p!TMH,%͔$b>B&/2cMHDI.bt 4-.G)mIȡyLvۛLcDh&#W"!Ki!!uI1xJ(Z:T-HJ~šp5MHWKg.ZZ\3b: ЖZho2=N}5e5Xʹ q}^nvEkv1Jy +ōz$>.UgWaMD鷞CT5b]_G VRiw}Fh؇eue*"]%RTc!u!V#|!-Eմ#}zًP.n2DeOhoEZ*R ѵ>[,rSp 6 2SkPwm\3L,GU[-RTH/ލT kѬB0ޓ:3+uTPnC~AuT7-^D5γjQM&:k*Rmg Q6ۅj˲zjwa2cW@!127\nC|0Gs p0ݔ ߗ tdL]y4c>=t鵧w_}/J/EygS;YoDIg_R2㯤fvgW3v?dK*y81r KC``AVyɤ}MZl9z{e{aݳ}ςּh}l[t]F;'lg0ϜxY4t8}v&o{#ۻs6f!8iU>H(%Pj^GK ɰVZn"o"\--<,G <o'`2GE$"'5 endstream endobj 54 0 obj 12353 endobj 55 0 obj <> endobj 56 0 obj <> stream x]n0E -E qG/@~,юXhy/\qH Gl{a~;%=cmΥ'wHW]9Bq[0*~g?ҧu?ܗ${>xOwuIӤ;:_[{uf=xX!_cvPzwvdMčϪr:w&ya\U\p .W߃kr~an ~UV.7[+xG~5ir22n5oPпL\Zu_п艡u/胡՚/C Bj8K__9k.kYI?ޗпݏп]$[?ҿ],+ec7K} ީh -|,-i/u;pmrx0Z::Sat}fd7*{> endstream endobj 57 0 obj <> endobj 58 0 obj <> stream xU[oE>c{4mBIqYWέ(P)mMbq$v.Xg8M5HUZ%XjJPR B}F@U"P(Hu1@7͠+TPOzAB7Y$l;^(ϸDQu )TxJvNSDeQ&2;PzPզBF+.^ i,jR$#ĝ3/jb}`^ hSkDڷ,.T6Q1s :YKfp*aȈTh!P4nP1ᓇ9khy4 ;)϶D ϓ9v(#f3a̶6.TG.ҝ;OwN \xRqBX\],TNs瞽Ku]U&\M)aexb ֨T_UD|&giHU`oDB!?:'Zs9=Rጞ &GӉ>1в*:gstutҰ nІ^Da΃ǵ,!8Cg'x WZ DAq F4( xmv)cЍhC(> endobj 61 0 obj <> stream x]Ak0s=,Q7eC? & I1k[!Mt=u~`{L0zrKX" 8yRetD%Z7] Nm/_c)Arϳ/fFKix"Buyb%lhBUE($;a%YJzht~ڀ]I=WCܩm endstream endobj 62 0 obj <> endobj 63 0 obj <> endobj 64 0 obj <> /ProcSet[/PDF/Text/ImageC/ImageI/ImageB] >> endobj 1 0 obj <>/Contents 2 0 R>> endobj 5 0 obj <>/Contents 6 0 R>> endobj 8 0 obj <>/Contents 9 0 R>> endobj 11 0 obj <>/Contents 12 0 R>> endobj 14 0 obj <>/Contents 15 0 R>> endobj 17 0 obj <>/Contents 18 0 R>> endobj 20 0 obj <>/Contents 21 0 R>> endobj 23 0 obj <>/Contents 24 0 R>> endobj 26 0 obj <>/Contents 27 0 R>> endobj 29 0 obj <>/Contents 30 0 R>> endobj 32 0 obj <>/Contents 33 0 R>> endobj 35 0 obj <>/Contents 36 0 R>> endobj 38 0 obj <>/Contents 39 0 R>> endobj 41 0 obj <>/Contents 42 0 R>> endobj 44 0 obj <>/Contents 45 0 R>> endobj 65 0 obj <> endobj 66 0 obj < /Dest[1 0 R/XYZ 0 595 0]/Parent 65 0 R/Next 67 0 R>> endobj 67 0 obj < /Dest[5 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 66 0 R/Next 68 0 R>> endobj 68 0 obj < /Dest[8 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 67 0 R/Next 69 0 R>> endobj 69 0 obj < /Dest[11 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 68 0 R/Next 70 0 R>> endobj 70 0 obj < /Dest[14 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 69 0 R/Next 71 0 R>> endobj 71 0 obj < /Dest[17 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 70 0 R/Next 72 0 R>> endobj 72 0 obj < /Dest[20 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 71 0 R/Next 73 0 R>> endobj 73 0 obj < /Dest[23 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 72 0 R/Next 74 0 R>> endobj 74 0 obj < /Dest[26 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 73 0 R/Next 75 0 R>> endobj 75 0 obj < /Dest[29 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 74 0 R/Next 76 0 R>> endobj 76 0 obj < /Dest[32 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 75 0 R/Next 77 0 R>> endobj 77 0 obj < /Dest[35 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 76 0 R/Next 78 0 R>> endobj 78 0 obj < /Dest[38 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 77 0 R/Next 79 0 R>> endobj 79 0 obj < /Dest[41 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 78 0 R/Next 80 0 R>> endobj 80 0 obj < /Dest[44 0 R/XYZ 0 595 0]/Parent 65 0 R/Prev 79 0 R>> endobj 47 0 obj <> endobj 81 0 obj <> endobj 82 0 obj < /Producer /CreationDate(D:20150426050946+02'00')>> endobj xref 0 83 0000000000 65535 f 0000102005 00000 n 0000000019 00000 n 0000000312 00000 n 0000000332 00000 n 0000102149 00000 n 0000075347 00000 n 0000075734 00000 n 0000102293 00000 n 0000075754 00000 n 0000076209 00000 n 0000102437 00000 n 0000076230 00000 n 0000076645 00000 n 0000102583 00000 n 0000076666 00000 n 0000077177 00000 n 0000102729 00000 n 0000077198 00000 n 0000077606 00000 n 0000102875 00000 n 0000077627 00000 n 0000078126 00000 n 0000103021 00000 n 0000078147 00000 n 0000078554 00000 n 0000103167 00000 n 0000078575 00000 n 0000079103 00000 n 0000103313 00000 n 0000079124 00000 n 0000079582 00000 n 0000103459 00000 n 0000079603 00000 n 0000080193 00000 n 0000103605 00000 n 0000080214 00000 n 0000080500 00000 n 0000103751 00000 n 0000080521 00000 n 0000080801 00000 n 0000103897 00000 n 0000080822 00000 n 0000081101 00000 n 0000104043 00000 n 0000081122 00000 n 0000081400 00000 n 0000106253 00000 n 0000081421 00000 n 0000085361 00000 n 0000085383 00000 n 0000085580 00000 n 0000085871 00000 n 0000086037 00000 n 0000098477 00000 n 0000098500 00000 n 0000098696 00000 n 0000099256 00000 n 0000099662 00000 n 0000101186 00000 n 0000101208 00000 n 0000101400 00000 n 0000101692 00000 n 0000101853 00000 n 0000101906 00000 n 0000104189 00000 n 0000104246 00000 n 0000104367 00000 n 0000104500 00000 n 0000104633 00000 n 0000104767 00000 n 0000104901 00000 n 0000105035 00000 n 0000105169 00000 n 0000105303 00000 n 0000105437 00000 n 0000105575 00000 n 0000105713 00000 n 0000105851 00000 n 0000105989 00000 n 0000106127 00000 n 0000106450 00000 n 0000106552 00000 n trailer < <8EC7EE584DD4C6E26B4FE07EE6B5BB71> ] /DocChecksum /EC2E9519F4B9FC16E0EDBA85D13E86D9 >> startxref 106731 %%EOF Carla-2.1/data/presentation/lac2018/000077500000000000000000000000001364475620200171055ustar00rootroot00000000000000Carla-2.1/data/presentation/lac2018/.gitignore000066400000000000000000000000741364475620200210760ustar00rootroot00000000000000lac2018.aux lac2018.bbl lac2018.blg lac2018.log lac2018.pdf Carla-2.1/data/presentation/lac2018/Makefile000066400000000000000000000002611364475620200205440ustar00rootroot00000000000000SAMPLES=lac2018.pdf all: $(SAMPLES) clean: cleantmp rm -f *.pdf cleantmp: rm -f *.aux rm -f *.bbl rm -f *.blg rm -f *.log %.pdf: %.tex pdflatex "$<" .PHONY:all clean Carla-2.1/data/presentation/lac2018/acl.bst000066400000000000000000000610131364475620200203570ustar00rootroot00000000000000% BibTeX `acl' style file for BibTeX version 0.99c, LaTeX version 2.09 % This version was made by modifying `aaai-named' format based on the master % file by Oren Patashnik (PATASHNIK@SCORE.STANFORD.EDU) % Copyright (C) 1985, all rights reserved. % Modifications Copyright 1988, Peter F. Patel-Schneider % Further modifictions by Stuart Shieber, 1991, and Fernando Pereira, 1992. % Copying of this file is authorized only if either % (1) you make absolutely no changes to your copy, including name, or % (2) if you do make changes, you name it something other than % btxbst.doc, plain.bst, unsrt.bst, alpha.bst, and abbrv.bst. % This restriction helps ensure that all standard styles are identical. % There are undoubtably bugs in this style. If you make bug fixes, % improvements, etc. please let me know. My e-mail address is: % pfps@spar.slb.com % Citation format: [author-last-name, year] % [author-last-name and author-last-name, year] % [author-last-name {\em et al.}, year] % % Reference list ordering: alphabetical by author or whatever passes % for author in the absence of one. % % This BibTeX style has support for short (year only) citations. This % is done by having the citations actually look like % \citename{name-info, }year % The LaTeX style has to have the following % \let\@internalcite\cite % \def\cite{\def\citename##1{##1}\@internalcite} % \def\shortcite{\def\citename##1{}\@internalcite} % \def\@biblabel#1{\def\citename##1{##1}[#1]\hfill} % which makes \shortcite the macro for short citations. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Changes made by SMS for thesis style % no emphasis on "et al." % "Ph.D." includes periods (not "PhD") % moved year to immediately after author's name %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ENTRY { address author booktitle chapter edition editor howpublished institution journal key month note number organization pages publisher school series title type volume year } {} { label extra.label sort.label } INTEGERS { output.state before.all mid.sentence after.sentence after.block } FUNCTION {init.state.consts} { #0 'before.all := #1 'mid.sentence := #2 'after.sentence := #3 'after.block := } STRINGS { s t } FUNCTION {output.nonnull} { 's := output.state mid.sentence = { ", " * write$ } { output.state after.block = { add.period$ write$ newline$ "\newblock " write$ } { output.state before.all = 'write$ { add.period$ " " * write$ } if$ } if$ mid.sentence 'output.state := } if$ s } FUNCTION {output} { duplicate$ empty$ 'pop$ 'output.nonnull if$ } FUNCTION {output.check} { 't := duplicate$ empty$ { pop$ "empty " t * " in " * cite$ * warning$ } 'output.nonnull if$ } FUNCTION {output.bibitem} { newline$ "\bibitem[" write$ label write$ "]{" write$ cite$ write$ "}" write$ newline$ "" before.all 'output.state := } FUNCTION {fin.entry} { add.period$ write$ newline$ } FUNCTION {new.block} { output.state before.all = 'skip$ { after.block 'output.state := } if$ } FUNCTION {new.sentence} { output.state after.block = 'skip$ { output.state before.all = 'skip$ { after.sentence 'output.state := } if$ } if$ } FUNCTION {not} { { #0 } { #1 } if$ } FUNCTION {and} { 'skip$ { pop$ #0 } if$ } FUNCTION {or} { { pop$ #1 } 'skip$ if$ } FUNCTION {new.block.checka} { empty$ 'skip$ 'new.block if$ } FUNCTION {new.block.checkb} { empty$ swap$ empty$ and 'skip$ 'new.block if$ } FUNCTION {new.sentence.checka} { empty$ 'skip$ 'new.sentence if$ } FUNCTION {new.sentence.checkb} { empty$ swap$ empty$ and 'skip$ 'new.sentence if$ } FUNCTION {field.or.null} { duplicate$ empty$ { pop$ "" } 'skip$ if$ } FUNCTION {emphasize} { duplicate$ empty$ { pop$ "" } { "{\em " swap$ * "}" * } if$ } INTEGERS { nameptr namesleft numnames } FUNCTION {format.names} { 's := #1 'nameptr := s num.names$ 'numnames := numnames 'namesleft := { namesleft #0 > } { s nameptr "{ff~}{vv~}{ll}{, jj}" format.name$ 't := nameptr #1 > { namesleft #1 > { ", " * t * } { numnames #2 > { "," * } 'skip$ if$ t "others" = { " et~al." * } { " and " * t * } if$ } if$ } 't if$ nameptr #1 + 'nameptr := namesleft #1 - 'namesleft := } while$ } FUNCTION {format.authors} { author empty$ { "" } { author format.names } if$ } FUNCTION {format.editors} { editor empty$ { "" } { editor format.names editor num.names$ #1 > { ", editors" * } { ", editor" * } if$ } if$ } FUNCTION {format.title} { title empty$ { "" } { title "t" change.case$ } if$ } FUNCTION {n.dashify} { 't := "" { t empty$ not } { t #1 #1 substring$ "-" = { t #1 #2 substring$ "--" = not { "--" * t #2 global.max$ substring$ 't := } { { t #1 #1 substring$ "-" = } { "-" * t #2 global.max$ substring$ 't := } while$ } if$ } { t #1 #1 substring$ * t #2 global.max$ substring$ 't := } if$ } while$ } FUNCTION {format.date} { year empty$ { month empty$ { "" } { "there's a month but no year in " cite$ * warning$ month } if$ } { month empty$ { "" } { month } if$ } if$ } FUNCTION {format.btitle} { title emphasize } FUNCTION {tie.or.space.connect} { duplicate$ text.length$ #3 < { "~" } { " " } if$ swap$ * * } FUNCTION {either.or.check} { empty$ 'pop$ { "can't use both " swap$ * " fields in " * cite$ * warning$ } if$ } FUNCTION {format.bvolume} { volume empty$ { "" } { "volume" volume tie.or.space.connect series empty$ 'skip$ { " of " * series emphasize * } if$ "volume and number" number either.or.check } if$ } FUNCTION {format.number.series} { volume empty$ { number empty$ { series field.or.null } { output.state mid.sentence = { "number" } { "Number" } if$ number tie.or.space.connect series empty$ { "there's a number but no series in " cite$ * warning$ } { " in " * series * } if$ } if$ } { "" } if$ } FUNCTION {format.edition} { edition empty$ { "" } { output.state mid.sentence = { edition "l" change.case$ " edition" * } { edition "t" change.case$ " edition" * } if$ } if$ } INTEGERS { multiresult } FUNCTION {multi.page.check} { 't := #0 'multiresult := { multiresult not t empty$ not and } { t #1 #1 substring$ duplicate$ "-" = swap$ duplicate$ "," = swap$ "+" = or or { #1 'multiresult := } { t #2 global.max$ substring$ 't := } if$ } while$ multiresult } FUNCTION {format.pages} { pages empty$ { "" } { pages multi.page.check { "pages" pages n.dashify tie.or.space.connect } { "page" pages tie.or.space.connect } if$ } if$ } FUNCTION {format.year.label} { year extra.label * } FUNCTION {format.vol.num.pages} { volume field.or.null number empty$ 'skip$ { "(" number * ")" * * volume empty$ { "there's a number but no volume in " cite$ * warning$ } 'skip$ if$ } if$ pages empty$ 'skip$ { duplicate$ empty$ { pop$ format.pages } { ":" * pages n.dashify * } if$ } if$ } FUNCTION {format.chapter.pages} { chapter empty$ 'format.pages { type empty$ { "chapter" } { type "l" change.case$ } if$ chapter tie.or.space.connect pages empty$ 'skip$ { ", " * format.pages * } if$ } if$ } FUNCTION {format.in.ed.booktitle} { booktitle empty$ { "" } { editor empty$ { "In " booktitle emphasize * } { "In " format.editors * ", " * booktitle emphasize * } if$ } if$ } FUNCTION {empty.misc.check} { author empty$ title empty$ howpublished empty$ month empty$ year empty$ note empty$ and and and and and key empty$ not and { "all relevant fields are empty in " cite$ * warning$ } 'skip$ if$ } FUNCTION {format.thesis.type} { type empty$ 'skip$ { pop$ type "t" change.case$ } if$ } FUNCTION {format.tr.number} { type empty$ { "Technical Report" } 'type if$ number empty$ { "t" change.case$ } { number tie.or.space.connect } if$ } FUNCTION {format.article.crossref} { key empty$ { journal empty$ { "need key or journal for " cite$ * " to crossref " * crossref * warning$ "" } { "In {\em " journal * "\/}" * } if$ } { "In " key * } if$ " \cite{" * crossref * "}" * } FUNCTION {format.crossref.editor} { editor #1 "{vv~}{ll}" format.name$ editor num.names$ duplicate$ #2 > { pop$ " et~al." * } { #2 < 'skip$ { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" = { " et~al." * } { " and " * editor #2 "{vv~}{ll}" format.name$ * } if$ } if$ } if$ } FUNCTION {format.book.crossref} { volume empty$ { "empty volume in " cite$ * "'s crossref of " * crossref * warning$ "In " } { "Volume" volume tie.or.space.connect " of " * } if$ editor empty$ editor field.or.null author field.or.null = or { key empty$ { series empty$ { "need editor, key, or series for " cite$ * " to crossref " * crossref * warning$ "" * } { "{\em " * series * "\/}" * } if$ } { key * } if$ } { format.crossref.editor * } if$ " \cite{" * crossref * "}" * } FUNCTION {format.incoll.inproc.crossref} { editor empty$ editor field.or.null author field.or.null = or { key empty$ { booktitle empty$ { "need editor, key, or booktitle for " cite$ * " to crossref " * crossref * warning$ "" } { "In {\em " booktitle * "\/}" * } if$ } { "In " key * } if$ } { "In " format.crossref.editor * } if$ " \cite{" * crossref * "}" * } FUNCTION {article} { output.bibitem format.authors "author" output.check new.block format.year.label "year" output.check new.block format.title "title" output.check new.block crossref missing$ { journal emphasize "journal" output.check format.vol.num.pages output format.date output } { format.article.crossref output.nonnull format.pages output } if$ new.block note output fin.entry } FUNCTION {book} { output.bibitem author empty$ { format.editors "author and editor" output.check } { format.authors output.nonnull crossref missing$ { "author and editor" editor either.or.check } 'skip$ if$ } if$ new.block format.year.label "year" output.check new.block format.btitle "title" output.check crossref missing$ { format.bvolume output new.block format.number.series output new.sentence publisher "publisher" output.check address output } { new.block format.book.crossref output.nonnull } if$ format.edition output format.date output new.block note output fin.entry } FUNCTION {booklet} { output.bibitem format.authors output new.block format.year.label "year" output.check new.block format.title "title" output.check howpublished address new.block.checkb howpublished output address output format.date output new.block note output fin.entry } FUNCTION {inbook} { output.bibitem author empty$ { format.editors "author and editor" output.check } { format.authors output.nonnull crossref missing$ { "author and editor" editor either.or.check } 'skip$ if$ } if$ format.year.label "year" output.check new.block new.block format.btitle "title" output.check crossref missing$ { format.bvolume output format.chapter.pages "chapter and pages" output.check new.block format.number.series output new.sentence publisher "publisher" output.check address output } { format.chapter.pages "chapter and pages" output.check new.block format.book.crossref output.nonnull } if$ format.edition output format.date output new.block note output fin.entry } FUNCTION {incollection} { output.bibitem format.authors "author" output.check new.block format.year.label "year" output.check new.block format.title "title" output.check new.block crossref missing$ { format.in.ed.booktitle "booktitle" output.check format.bvolume output format.number.series output format.chapter.pages output new.sentence publisher "publisher" output.check address output format.edition output format.date output } { format.incoll.inproc.crossref output.nonnull format.chapter.pages output } if$ new.block note output fin.entry } FUNCTION {inproceedings} { output.bibitem format.authors "author" output.check new.block format.year.label "year" output.check new.block format.title "title" output.check new.block crossref missing$ { format.in.ed.booktitle "booktitle" output.check format.bvolume output format.number.series output format.pages output address empty$ { organization publisher new.sentence.checkb organization output publisher output format.date output } { address output.nonnull format.date output new.sentence organization output publisher output } if$ } { format.incoll.inproc.crossref output.nonnull format.pages output } if$ new.block note output fin.entry } FUNCTION {conference} { inproceedings } FUNCTION {manual} { output.bibitem author empty$ { organization empty$ 'skip$ { organization output.nonnull address output } if$ } { format.authors output.nonnull } if$ format.year.label "year" output.check new.block new.block format.btitle "title" output.check author empty$ { organization empty$ { address new.block.checka address output } 'skip$ if$ } { organization address new.block.checkb organization output address output } if$ format.edition output format.date output new.block note output fin.entry } FUNCTION {mastersthesis} { output.bibitem format.authors "author" output.check new.block format.year.label "year" output.check new.block format.title "title" output.check new.block "Master's thesis" format.thesis.type output.nonnull school "school" output.check address output format.date output new.block note output fin.entry } FUNCTION {misc} { output.bibitem format.authors output new.block format.year.label output new.block title howpublished new.block.checkb format.title output howpublished new.block.checka howpublished output format.date output new.block note output fin.entry empty.misc.check } FUNCTION {phdthesis} { output.bibitem format.authors "author" output.check new.block format.year.label "year" output.check new.block format.btitle "title" output.check new.block "{Ph.D.} thesis" format.thesis.type output.nonnull school "school" output.check address output format.date output new.block note output fin.entry } FUNCTION {proceedings} { output.bibitem editor empty$ { organization output } { format.editors output.nonnull } if$ new.block format.year.label "year" output.check new.block format.btitle "title" output.check format.bvolume output format.number.series output address empty$ { editor empty$ { publisher new.sentence.checka } { organization publisher new.sentence.checkb organization output } if$ publisher output format.date output } { address output.nonnull format.date output new.sentence editor empty$ 'skip$ { organization output } if$ publisher output } if$ new.block note output fin.entry } FUNCTION {techreport} { output.bibitem format.authors "author" output.check new.block format.year.label "year" output.check new.block format.title "title" output.check new.block format.tr.number output.nonnull institution "institution" output.check address output format.date output new.block note output fin.entry } FUNCTION {unpublished} { output.bibitem format.authors "author" output.check new.block format.year.label "year" output.check new.block format.title "title" output.check new.block note "note" output.check format.date output fin.entry } FUNCTION {default.type} { misc } MACRO {jan} {"January"} MACRO {feb} {"February"} MACRO {mar} {"March"} MACRO {apr} {"April"} MACRO {may} {"May"} MACRO {jun} {"June"} MACRO {jul} {"July"} MACRO {aug} {"August"} MACRO {sep} {"September"} MACRO {oct} {"October"} MACRO {nov} {"November"} MACRO {dec} {"December"} MACRO {acmcs} {"ACM Computing Surveys"} MACRO {acta} {"Acta Informatica"} MACRO {cacm} {"Communications of the ACM"} MACRO {ibmjrd} {"IBM Journal of Research and Development"} MACRO {ibmsj} {"IBM Systems Journal"} MACRO {ieeese} {"IEEE Transactions on Software Engineering"} MACRO {ieeetc} {"IEEE Transactions on Computers"} MACRO {ieeetcad} {"IEEE Transactions on Computer-Aided Design of Integrated Circuits"} MACRO {ipl} {"Information Processing Letters"} MACRO {jacm} {"Journal of the ACM"} MACRO {jcss} {"Journal of Computer and System Sciences"} MACRO {scp} {"Science of Computer Programming"} MACRO {sicomp} {"SIAM Journal on Computing"} MACRO {tocs} {"ACM Transactions on Computer Systems"} MACRO {tods} {"ACM Transactions on Database Systems"} MACRO {tog} {"ACM Transactions on Graphics"} MACRO {toms} {"ACM Transactions on Mathematical Software"} MACRO {toois} {"ACM Transactions on Office Information Systems"} MACRO {toplas} {"ACM Transactions on Programming Languages and Systems"} MACRO {tcs} {"Theoretical Computer Science"} READ FUNCTION {sortify} { purify$ "l" change.case$ } INTEGERS { len } FUNCTION {chop.word} { 's := 'len := s #1 len substring$ = { s len #1 + global.max$ substring$ } 's if$ } INTEGERS { et.al.char.used } FUNCTION {initialize.et.al.char.used} { #0 'et.al.char.used := } EXECUTE {initialize.et.al.char.used} FUNCTION {format.lab.names} { 's := s num.names$ 'numnames := numnames #1 = { s #1 "{vv }{ll}" format.name$ } { numnames #2 = { s #1 "{vv }{ll }and " format.name$ s #2 "{vv }{ll}" format.name$ * } { s #1 "{vv }{ll }\bgroup et al.\egroup " format.name$ } if$ } if$ } FUNCTION {author.key.label} { author empty$ { key empty$ { cite$ #1 #3 substring$ } { key #3 text.prefix$ } if$ } { author format.lab.names } if$ } FUNCTION {author.editor.key.label} { author empty$ { editor empty$ { key empty$ { cite$ #1 #3 substring$ } { key #3 text.prefix$ } if$ } { editor format.lab.names } if$ } { author format.lab.names } if$ } FUNCTION {author.key.organization.label} { author empty$ { key empty$ { organization empty$ { cite$ #1 #3 substring$ } { "The " #4 organization chop.word #3 text.prefix$ } if$ } { key #3 text.prefix$ } if$ } { author format.lab.names } if$ } FUNCTION {editor.key.organization.label} { editor empty$ { key empty$ { organization empty$ { cite$ #1 #3 substring$ } { "The " #4 organization chop.word #3 text.prefix$ } if$ } { key #3 text.prefix$ } if$ } { editor format.lab.names } if$ } FUNCTION {calc.label} { type$ "book" = type$ "inbook" = or 'author.editor.key.label { type$ "proceedings" = 'editor.key.organization.label { type$ "manual" = 'author.key.organization.label 'author.key.label if$ } if$ } if$ duplicate$ "\protect\citename{" swap$ * "}" * year field.or.null purify$ * 'label := year field.or.null purify$ * sortify 'sort.label := } FUNCTION {sort.format.names} { 's := #1 'nameptr := "" s num.names$ 'numnames := numnames 'namesleft := { namesleft #0 > } { nameptr #1 > { " " * } 'skip$ if$ s nameptr "{vv{ } }{ll{ }}{ ff{ }}{ jj{ }}" format.name$ 't := nameptr numnames = t "others" = and { "et al" * } { t sortify * } if$ nameptr #1 + 'nameptr := namesleft #1 - 'namesleft := } while$ } FUNCTION {sort.format.title} { 't := "A " #2 "An " #3 "The " #4 t chop.word chop.word chop.word sortify #1 global.max$ substring$ } FUNCTION {author.sort} { author empty$ { key empty$ { "to sort, need author or key in " cite$ * warning$ "" } { key sortify } if$ } { author sort.format.names } if$ } FUNCTION {author.editor.sort} { author empty$ { editor empty$ { key empty$ { "to sort, need author, editor, or key in " cite$ * warning$ "" } { key sortify } if$ } { editor sort.format.names } if$ } { author sort.format.names } if$ } FUNCTION {author.organization.sort} { author empty$ { organization empty$ { key empty$ { "to sort, need author, organization, or key in " cite$ * warning$ "" } { key sortify } if$ } { "The " #4 organization chop.word sortify } if$ } { author sort.format.names } if$ } FUNCTION {editor.organization.sort} { editor empty$ { organization empty$ { key empty$ { "to sort, need editor, organization, or key in " cite$ * warning$ "" } { key sortify } if$ } { "The " #4 organization chop.word sortify } if$ } { editor sort.format.names } if$ } FUNCTION {presort} { calc.label sort.label " " * type$ "book" = type$ "inbook" = or 'author.editor.sort { type$ "proceedings" = 'editor.organization.sort { type$ "manual" = 'author.organization.sort 'author.sort if$ } if$ } if$ * " " * year field.or.null sortify * " " * title field.or.null sort.format.title * #1 entry.max$ substring$ 'sort.key$ := } ITERATE {presort} SORT STRINGS { longest.label last.sort.label next.extra } INTEGERS { longest.label.width last.extra.num } FUNCTION {initialize.longest.label} { "" 'longest.label := #0 int.to.chr$ 'last.sort.label := "" 'next.extra := #0 'longest.label.width := #0 'last.extra.num := } FUNCTION {forward.pass} { last.sort.label sort.label = { last.extra.num #1 + 'last.extra.num := last.extra.num int.to.chr$ 'extra.label := } { "a" chr.to.int$ 'last.extra.num := "" 'extra.label := sort.label 'last.sort.label := } if$ } FUNCTION {reverse.pass} { next.extra "b" = { "a" 'extra.label := } 'skip$ if$ label extra.label * 'label := label width$ longest.label.width > { label 'longest.label := label width$ 'longest.label.width := } 'skip$ if$ extra.label 'next.extra := } EXECUTE {initialize.longest.label} ITERATE {forward.pass} REVERSE {reverse.pass} FUNCTION {begin.bib} { et.al.char.used { "\newcommand{\etalchar}[1]{$^{#1}$}" write$ newline$ } 'skip$ if$ preamble$ empty$ 'skip$ { preamble$ write$ newline$ } if$ "\begin{thebibliography}{" "}" * write$ newline$ } EXECUTE {begin.bib} EXECUTE {init.state.consts} ITERATE {call.type$} FUNCTION {end.bib} { newline$ "\end{thebibliography}" write$ newline$ } EXECUTE {end.bib} Carla-2.1/data/presentation/lac2018/lac2018.sty000066400000000000000000000550621364475620200207300ustar00rootroot00000000000000% % lac2018.sty % \typeout{} \typeout{LAC2018 Proceedings style -- January 2018} %\typeout{only slightly different from} %\typeout{Coling 2004 Proceedings style -- February 2004} %\typeout{only slightly different from} %\typeout{ACL-COLING 1998 Proceedings style -- March 31st 1998} \typeout{} % % ---------------------------------------------------------------------- % % This is the LaTeX style file for the Linux Audio Conference % It is an almost unmodified copy of colacl.sty, the style file % of Coling (International Conference on Computational Linguistics). % Many thanks to Coling for their permission to use it! % The original may be found here: % http://www.issco.unige.ch/coling2004/coling2004downloads.html % % ---------------------------------------------------------------------- % % This is the LaTeX style file for ACL-COLING 1998. It is based on % a series of similar files prepared for previous conferences by % Fernando Pereira, Paul Jacobs, Stuart Shieber, Peter F. % Patel-Schneider and others. Various changes have been made, chiefly % to save space in the final output or remove redundant definitions. % % colacl.sty is designed for use as a package or option with the % standard LaTeX article class, and the BibTeX style acl.bst. % % Author/title and citation formatting differs slightly from standard % LaTeX; see AUTHOR FORMATS and CITATION FORMATS below for more % information. % % This file is supplied as a hopefully convenient implementation of % some of the "instructions for authors" repeated below. It is not % guaranteed to work in any given LaTeX installation or in conjunction % with any given class, package or style, and it is not intended as % a LaTeX tutorial. % % ---------------------------------------------------------------------- % Instructions for authors % % (i) Maximum length of full papers: 8 pages. % % (ii) Paper size: A4. % % (iii) Margins: set so that text lies within a rectangle 9in (23cm) % high and 6.5in (16.5cm) wide. % % (iv) Body of text to be set in two columns. Full-width figures % (i.e. using \begin{figure*}) and tables may be used if % necessary. % % (v) Use standard fonts, e.g. Computer Modern Roman, Times Roman, no % smaller than 10pt. % % (vi) No page numbering. % % Items (iii), (iv) and (vi) are handled by this file, and should % therefore not be overridden by resetting \textwidth, \textheight, % \pagestyle etc. in your document, or by using styles or packages % which have the same effect. % % ---------------------------------------------------------------------- % To convert papers prepared with colaclsub.sty to the final format % for use with colacl.sty: % % (1) Remove commands specific to the original submission format % (\type, \subject, \contact, \conference, \makeidpage). % % (2) Replace \summary{...} with an abstract, using the normal % abstract environment, placed after \maketitle. % % A simple document template: % % \documentclass[11pt,letterpaper]{article} % \usepackage{lac2012} % \title{...} % \author{...} % see below for possible formats % \begin{document} % \maketitle % \begin{abstract} % ... % contents of abstract % \end{abstract} % ... % contents of article % \bibliographystyle{acl} % use acl.bst % \bibliography{...} % \end{document} % % Users of obsolete LaTeX versions can try: % % \documentstyle[lac2012]{article} % or [11pt,lac2012] % \title{...} % ... % % % ---------------------------------------------------------------------- % AUTHOR FORMATS % % Author information can be set in various styles. % % For several authors from the same institution: % \author{Author 1 \and ... \and Author n \\ % Address line \\ ... \\ Address line} % if the names do not fit well on one line use % Author 1 \\ {\bf Author 2} \\ ... \\ {\bf Author n} \\ % % For authors from different institutions: % \author{Author 1 \\ Address line \\ ... \\ Address line % \And ... \And % Author n \\ Address line \\ ... \\ Address line} % % To start a separate "row" of authors use \AND, as in % \author{Author 1 \\ Address line \\ ... \\ Address line % \AND % Author 2 \\ Address line \\ ... \\ Address line \And % Author 3 \\ Address line \\ ... \\ Address line} % % If the title and author information does not fit in the area allocated, % place \setlength\titlebox{} after \usepackage{colacl}, % where can be something larger than 2.0in % % ---------------------------------------------------------------------- % CITATION FORMATS % % Three possible citation formats: % "\cite{...}" produces a citation like "(Author, 1999)" % "\shortcite{...}" produces a citation like "(1999)" % "\newcite{...}" produces a citation like "Author (1999)" % % All three take an optional argument which can be used to add page % references, etc.: % "\newcite[1--6]{...}" produces a citation like "Author (1999, 1--6)" % % ---------------------------------------------------------------------- % IF IT DOESN'T WORK % % The error message "File `colacl.sty' not found." indicates that this % file has not been installed in a location which is visible to your % LaTeX. Try putting it in the same directory as your paper, and % running LaTeX there. Consult your `Local Guide' documentation or % your system administrator to find out how LaTeX searches for input % files. % % "\documentclass..." is a LaTeX2e declaration. An error message % "Undefined control sequence." followed by a line ending in % "\documentclass" indicates that you have used this with an obsolete % LaTeX installation. Use the "\documentstyle" variant shown above. % % As a last resort, forget about colacl.sty and simply copy the % following lines (uncommented, obviously) into your document before % the "\begin{document}": % % \setlength\topmargin{0.0in} % \setlength\oddsidemargin{-0.0in} % \setlength\textheight{9.0in} % \setlength\textwidth{6.5in} % \setlength\columnsep{0.25in} % \setlength\headheight{0pt} % \setlength\headsep{0pt} % \thispagestyle{empty} % \pagestyle{empty} % \flushbottom % \twocolumn % \sloppy % % Some interactions with other packages may still occur. In order to % remove the page number from the first page, you may have to place the % "\thispagestyle{empty}" command immediately after "\maketitle". % % ---------------------------------------------------------------------- % NOTE: Some laser printers have a serious problem printing TeX output. % These printing devices, commonly known as "write-white" laser % printers, tend to make characters too light. To get around this % problem, a darker set of fonts must be created for these devices. % % ---------------------------------------------------------------------- % Physical page layout - slightly modified from IJCAI by pj % Physical page layout - slightly modified by rg for LAC \newlength\myavierh \setlength\myavierh{297mm} %\message{The page height is \the\paperheight} \ifdim \paperheight = \myavierh \message{ !! Using ISO-A4 paper} %% A4paper \setlength\topmargin{0.0in} \setlength\oddsidemargin{-0.0in} \setlength\textheight{9.5in} %%sm was 9.0in \setlength\textwidth{6.5in} \setlength\columnsep{0.25in} \newlength\titlebox \setlength\titlebox{2.0in} % was 2.25in \setlength\headheight{0pt} \setlength\headsep{0pt} \setlength\footskip{0pt} % irrelevant when no footers. \else %% US-Letter \message{ !! Using US-Letter paper} \setlength{\pdfpagewidth}{8.5in} \setlength{\pdfpageheight}{11in} \setlength\topmargin{0.0in} \setlength\oddsidemargin{-0.2in} \setlength\textheight{8.8in} \setlength\textwidth{6.9in} \setlength\columnsep{0.4in} \newlength\titlebox \setlength\titlebox{2.1in} \setlength\headheight{0pt} \setlength\headsep{0pt} \setlength\footskip{0pt} % irrelevant when no footers. \fi \pagestyle{empty} % no page numbers \thispagestyle{empty} % no page numbers \flushbottom \twocolumn \sloppy % We're never going to need a table of contents, so just flush it to % save space --- suggested by drstrip@sandia-2 \def\addcontentsline#1#2#3{} % ---------------------------------------------------------------------- % Title stuff, taken from deproc. \def\maketitle{% \par% \begingroup% \def\thefootnote{\fnsymbol{footnote}}% \def\@makefnmark{\rlap{$^{\@thefnmark}$\hss}}% % no paragraph breaks in \thanks \long\def\@makefntext##1{% \parindent 1em\noindent% \hbox to 1em{$^{\@thefnmark}$}##1} \twocolumn[\@maketitle] \@thanks% \endgroup% \setcounter{footnote}{0}% \let\maketitle\relax\let\@maketitle\relax% \gdef\@thanks{}\gdef\@author{}\gdef\@title{}% \let\thanks\relax} % some vertical space removed here: skip above and below title % \def\@maketitle{% \vbox to \titlebox{% \hsize\textwidth\linewidth\hsize% \vskip 0.125in minus 0.05in% \centering{\Large\bf \@title \par}% \vskip 0.2in plus 0.1fil minus 0.1in {\def\and{\unskip\enspace{\rm and}\enspace}% \def\And{\end{tabular}\hss \egroup \hskip 1in plus 2fil \hbox to 0pt\bgroup\hss \begin{tabular}[t]{c}\bf}% \def\AND{\end{tabular}\hss\egroup \hfil\hfil\egroup \vskip 0.25in plus 1fil minus 0.125in \hbox to \linewidth\bgroup\large \hfil\hfil \hbox to 0pt\bgroup\hss \begin{tabular}[t]{c}\bf} \hbox to \linewidth \bgroup\large \hfil\hfil \hbox to 0pt\bgroup\hss \begin{tabular}[t]{c}\bf\@author \end{tabular}\hss\egroup \hfil\hfil\egroup} \vskip 0.3in plus 2fil minus 0.1in }} % ---------------------------------------------------------------------- % abstract, changed for LAC2005 % \renewenvironment{abstract}{\section*{\centerline{Abstract}}}{} \renewenvironment{abstract}{\section*{Abstract}}{} % ---------------------------------------------------------------------- % keywords, added for LAC2005 \def\keywords{\section*{Keywords}} % ---------------------------------------------------------------------- % bibliography and citations % most of cite format is from aclsub.sty by SMS % don't box citations, separate with ; and a space % Replaced for multiple citations (pj) % don't box citations and also add space, semicolon between multiple % citations % \def\@citex[#1]#2{\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi \def\@citea{}\@cite{\@for\@citeb:=#2\do {\@citea\def\@citea{; }\@ifundefined {b@\@citeb}{{\bf ?}\@warning {Citation `\@citeb' on page \thepage \space undefined}}% {\csname b@\@citeb\endcsname}}}{#1}} % Allow short (name-less) citations, when used in % conjunction with a bibliography style that creates labels like % \citename{, } % \let\@internalcite\cite \def\cite{\def\citename##1{##1, }\@internalcite} \def\longcite{\def\citename##1{##1, }\@internalcite} \def\shortcite{\def\citename##1{}\@internalcite} \def\newcite{\def\citename##1{{##1}\ (}\@internalciteb} % Macros for \newcite, which leaves name in running text, and is % otherwise like \shortcite. % \def\@citexb[#1]#2{\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi \def\@citea{}\@newcite{\@for\@citeb:=#2\do {\@citea\def\@citea{;\penalty\@m\ }\@ifundefined {b@\@citeb}{{\bf ?}\@warning {Citation `\@citeb' on page \thepage \space undefined}}% % gjr: hbox causes too many bad linebreaks %\hbox{\csname b@\@citeb\endcsname}}}{#1}} {\csname b@\@citeb\endcsname}}}{#1}} \def\@internalciteb{% \@ifnextchar [{\@tempswatrue\@citexb}{\@tempswafalse\@citexb[]}} \def\@newcite#1#2{{#1\if@tempswa, #2\fi)}} % gjr: no labels in this bibliography style % \def\@biblabel#1{\def\citename##1{##1}[#1]\hfill} \def\@biblabel#1{} % use square brackets after all %%% More changes made by SMS (originals in latex.tex) % Use parentheses instead of square brackets in the text. % \def\@cite#1#2{({#1\if@tempswa , #2\fi})} % Don't put a label in the bibliography at all. Just use the unlabeled format % instead. % gjr: removed \@mkboth -- no headers here. % gjr: reduced vertical space between entries (plus was .33em) % \def\thebibliography#1{\section*{References}\list {[\arabic{enumi}]}{\settowidth\labelwidth{[#1]}\leftmargin\labelwidth \advance\leftmargin\labelsep \usecounter{enumi}} \def\newblock{\hskip .11em plus .11em minus .07em} \sloppy\clubpenalty4000\widowpenalty4000 \sfcode`\.=1000\relax} \let\endthebibliography=\endlist % \def\thebibliography#1{% % \section*{References} % \list{}{\setlength{\labelwidth}{0pt} % \setlength{\leftmargin}{\parindent} % \setlength{\itemsep}{0.11ex plus 0.11ex} % \setlength{\parsep}{0ex} % \setlength{\itemindent}{-\parindent}} % \def\newblock{\hskip .11em plus .11em minus -.07em} % \sloppy\clubpenalty4000\widowpenalty4000 % \sfcode`\.=1000\relax} % \let\endthebibliography=\endlist % Allow for a bibliography of sources of attested examples \def\thesourcebibliography#1{% \section*{Sources of Attested Examples} \list{}{\setlength{\labelwidth}{0pt} \setlength{\leftmargin}{\parindent} \setlength{\itemsep}{0.11ex plus 0.11ex} \setlength{\parsep}{0ex} \setlength{\itemindent}{-\parindent}} \def\newblock{\hskip .11em plus .11em minus -.07em} \sloppy\clubpenalty4000\widowpenalty4000 \sfcode`\.=1000\relax} \let\endthesourcebibliography=\endlist \def\@lbibitem[#1]#2{\item[]\if@filesw { \def\protect##1{\string ##1\space}\immediate \write\@auxout{\string\bibcite{#2}{#1}}\fi\ignorespaces}} \def\@bibitem#1{\item\if@filesw \immediate\write\@auxout {\string\bibcite{#1}{\the\c@enumi}}\fi\ignorespaces} % ---------------------------------------------------------------------- % Section headings with less space \def\section{% \@startsection{section}{1}{\z@}% {-2.0ex plus -0.5ex minus -0.3ex}% {0.8ex plus 0.3ex minus 0.2ex}% {\large\bf\raggedright}} \def\subsection{% \@startsection{subsection}{2}{\z@}% {-1.4ex plus -0.4ex minus -0.2ex}% {0.6ex plus 0.2ex minus 0.1ex}% {\normalsize\bf\raggedright}} \def\subsubsection{% \@startsection{subsubsection}{3}{\z@}% {-0.8ex plus -0.3ex minus -0.1ex}% {0.4ex plus 0.1ex minus 0.1ex}% {\normalsize\bf\raggedright}} \def\paragraph{% \@startsection{paragraph}{4}{\z@}% {-0.8ex plus -0.3ex minus -0.1ex}% {-1em}% {\normalsize\bf}} \def\subparagraph{% \@startsection{subparagraph}{5}{\parindent}% {0.4ex plus 0.3ex minus 0.1ex}% {-1em}% {\normalsize\bf}} % ---------------------------------------------------------------------- % Footnotes %\footnotesep 6.65pt % %\skip\footins 9pt plus 4pt minus 2pt %\def\footnoterule{\kern-3pt \hrule width 5pc \kern 2.6pt } %\setcounter{footnote}{0} % ---------------------------------------------------------------------- % Lists and paragraphs \setlength\parindent{1em} \leftmargin 2em \leftmargini\leftmargin \leftmarginii 2em \leftmarginiii 1.5em \leftmarginiv 1.0em \leftmarginv .5em \leftmarginvi .5em \labelwidth\leftmargini\advance\labelwidth-\labelsep \labelsep 5pt % ---------------------------------------------------------------------- % Floats (figures, tables etc.) % % Allow a larger proportion of the column/page to be taken up with % floats than the standard classes. Also discourage the creation of % columns/pages containing only floats. % Maximum fraction of the page that can be occupied by floats: % \renewcommand\topfraction{.9} \renewcommand\bottomfraction{.5} \renewcommand\dbltopfraction{.9} % 2-column floats % Minimum fraction of page that can be occupied by text: % \renewcommand\textfraction{.1} % Maximum fraction of a page that can be occupied by floats before a % separate float page is produced: % \renewcommand\floatpagefraction{0.9} \renewcommand\dblfloatpagefraction{.9} % 2-column floats % ---------------------------------------------------------------------- % % Since we're using two columns, lines are short and we can get away % with less vertical space between lines, within lists and around % various kinds of display. % % Normally, these parameters are set in the size option to the class % file (standard definitions are in classes.dtx). Here we want to % accommodate 10pt, 11pt and 12pt, so we wrap the definitions in % \ifcase. % % \normalsize % \ifcase\@ptsize% \renewcommand{\normalsize}{% 10pt \@setsize\normalsize{11.3pt}\xpt\@xpt% \abovedisplayskip 10\p@\@plus2\p@\@minus5\p@% \abovedisplayshortskip\z@\@plus3\p@% \belowdisplayshortskip 4\p@\@plus3\p@\@minus3\p@% \belowdisplayskip\abovedisplayskip% \let\@listi\@listI}% \or% \renewcommand{\normalsize}{% 11pt \@setsize\normalsize{12.6pt}\xipt\@xipt% \abovedisplayskip11\p@\@plus2\p@\@minus4\p@% \abovedisplayshortskip\z@\@plus3\p@% \belowdisplayshortskip5\p@\@plus3\p@\@minus2\p@% \belowdisplayskip\abovedisplayskip% \let\@listi\@listI}% \or% \renewcommand{\normalsize}{% 12pt \@setsize\normalsize{13pt}\xiipt\@xiipt% \abovedisplayskip 11\p@ \@plus3\p@ \@minus5\p@% \abovedisplayshortskip \z@ \@plus3\p@% \belowdisplayshortskip 5\p@ \@plus3\p@ \@minus2\p@% \belowdisplayskip\abovedisplayskip% \let\@listi\@listI}% \fi % \small % \ifcase\@ptsize% \renewcommand{\small}{% 10pt \@setsize\small{10.5pt}\ixpt\@ixpt% \abovedisplayskip 8\p@ \@plus3\p@ \@minus3\p@% \abovedisplayshortskip \z@ \@plus2\p@% \belowdisplayshortskip 3\p@ \@plus2\p@ \@minus2\p@% \belowdisplayskip\abovedisplayskip% \def\@listi{\leftmargin\leftmargini% \topsep 3.5\p@ \@plus1.5\p@ \@minus1.5\p@% \parsep 1.5\p@ \@plus\p@ \@minus\p@% \itemsep \parsep}}% \or% \renewcommand{\small}{% 11pt \@setsize\small{11.3pt}\xpt\@xpt% \abovedisplayskip 9\p@ \@plus2\p@ \@minus4\p@% \abovedisplayshortskip \z@ \@plus3\p@% \belowdisplayshortskip 5\p@ \@plus2.5\p@ \@minus2.5\p@% \belowdisplayskip\abovedisplayskip% \def\@listi{\leftmargin\leftmargini% \topsep 5\p@ \@plus2\p@ \@minus2\p@% \parsep 2\p@ \@plus2\p@ \@minus\p@% \itemsep \parsep}}% \or% \renewcommand{\small}{% 12pt \@setsize\small{12pt}\xipt\@xipt% \abovedisplayskip 9\p@ \@plus3\p@ \@minus4\p@% \abovedisplayshortskip \z@ \@plus3\p@% \belowdisplayshortskip 5\p@ \@plus2.5\p@ \@minus2\p@% \belowdisplayskip\abovedisplayskip% \def\@listi{\leftmargin\leftmargini% \topsep 5.5\p@ \@plus2.5\p@ \@minus2.5\p@% \parsep 4\p@ \@plus1.5\p@ \@minus\p@% \itemsep \parsep}}% \fi % \footnotesize % \ifcase\@ptsize \renewcommand{\footnotesize}{% 10pt \@setsize\footnotesize{9.3pt}\viiipt\@viiipt% \abovedisplayskip 5\p@ \@plus2\p@ \@minus3\p@% \abovedisplayshortskip \z@ \@plus\p@% \belowdisplayshortskip 2.5\p@\@plus\p@\@minus2\p@% \belowdisplayskip\abovedisplayskip% \def\@listi{\leftmargin\leftmargini% \topsep 2.5\p@ \@plus\p@ \@minus\p@% \parsep 1.5\p@ \@plus\p@ \@minus\p@% \itemsep \parsep}}% \or% \renewcommand{\footnotesize}{% 11pt \@setsize\footnotesize{10.3pt}\ixpt\@ixpt% \abovedisplayskip 7\p@ \@plus2\p@ \@minus4\p@% \abovedisplayshortskip \z@ \@plus\p@% \belowdisplayshortskip 3\p@ \@plus2\p@ \@minus2\p@% \belowdisplayskip\abovedisplayskip% \def\@listi{\leftmargin\leftmargini% \topsep 3\p@ \@plus2\p@ \@minus2\p@% \parsep 2\p@ \@plus\p@ \@minus\p@% \itemsep \parsep}}% \or% \renewcommand{\footnotesize}{% 12pt \@setsize\footnotesize{11pt}\xpt\@xpt% \abovedisplayskip 9\p@ \@plus2\p@ \@minus4\p@% \abovedisplayshortskip \z@ \@plus3\p@% \belowdisplayshortskip 5\p@ \@plus3\p@ \@minus3\p@% \belowdisplayskip\abovedisplayskip% \def\@listi{\leftmargin\leftmargini% \topsep 4.5\p@ \@plus2\p@ \@minus2\p@% \parsep 3\p@ \@plus\p@ \@minus\p@% \itemsep \parsep}}% \fi % \large % \ifcase\@ptsize% \renewcommand{\large}{\@setsize\large{13pt}\xiipt\@xiipt}% 10pt \or% \renewcommand{\large}{\@setsize\large{13pt}\xiipt\@xiipt}% 11pt \or% \renewcommand{\large}{\@setsize\large{16pt}\xivpt\@xivpt}% 12pt \fi % \Large % \ifcase\@ptsize% \renewcommand{\Large}{\@setsize\Large{16pt}\xivpt\@xivpt}% 10pt \or% \renewcommand{\Large}{\@setsize\Large{16pt}\xivpt\@xivpt}% 11pt \or% \renewcommand{\Large}{\@setsize\Large{16pt}\xivpt\@xivpt}% 12pt \fi % Leave \scriptsize, \tiny, \huge, \Huge unchanged? % % Float separations, single and double-column % \ifcase\@ptsize% \setlength\floatsep{10\p@ \@plus 2\p@ \@minus 2\p@}% 10pt \setlength\textfloatsep{16\p@ \@plus 2\p@ \@minus 4\p@}% \setlength\intextsep{10\p@ \@plus 2\p@ \@minus 2\p@}% \setlength\dblfloatsep{10\p@ \@plus 2\p@ \@minus 2\p@}% \setlength\dbltextfloatsep{16\p@ \@plus 2\p@ \@minus 4\p@}% \or% \setlength\floatsep{10\p@ \@plus 2\p@ \@minus 2\p@}% 11pt \setlength\textfloatsep{16\p@ \@plus 2\p@ \@minus 4\p@}% \setlength\intextsep{10\p@ \@plus 2\p@ \@minus 2\p@}% \setlength\dblfloatsep{10\p@ \@plus 2\p@ \@minus 2\p@}% \setlength\dbltextfloatsep{16\p@ \@plus 2\p@ \@minus 4\p@}% \or% \setlength\floatsep{12\p@ \@plus 3\p@ \@minus 3\p@}% 12pt \setlength\textfloatsep{18\p@ \@plus 2\p@ \@minus 4\p@}% \setlength\intextsep{12\p@ \@plus 3\p@ \@minus 3\p@}% \setlength\dblfloatsep{12\p@ \@plus 2\p@ \@minus 4\p@}% \setlength\dbltextfloatsep{18\p@ \@plus 2\p@ \@minus 4\p@}% \fi % % Top-level list in \normalsize text % \ifcase\@ptsize% \def\@listi{\leftmargin\leftmargini% 10pt \topsep 6\p@ \@plus2\p@ \@minus2\p@% \parsep 2\p@ \@plus0.5\p@ \@minus\p@% \itemsep 2.5\p@ \@plus\p@ \@minus0.5\p@}% \or% \def\@listi{\leftmargin\leftmargini% 11pt \topsep 8\p@ \@plus2\p@ \@minus2\p@% \parsep 3\p@ \@plus1.5\p@ \@minus\p@% \itemsep 3\p@ \@plus1.5\p@ \@minus\p@}% \or% \def\@listi{\leftmargin\leftmargini% 12pt \topsep 9\p@ \@plus3\p@ \@minus4\p@% \parsep 4\p@ \@plus2\p@ \@minus\p@% \itemsep 4\p@ \@plus2\p@ \@minus\p@}% \fi \let\@listI\@listi % % Embedded lists unchanged. % % ---------------------------------------------------------------------- % End of colacl.sty % ---------------------------------------------------------------------- Carla-2.1/data/presentation/lac2018/lac2018.tex000066400000000000000000000064071364475620200207100ustar00rootroot00000000000000\documentclass[11pt,a4paper]{article} \usepackage{lac2018} \sloppy \newenvironment{contentsmall}{\small} \title{Carla Plugin Host - Feature overview and workflows, c-base Berlin} %see lac2018.sty for how to format multiple authors! \author {Filipe Coelho \\ falkTX, Linux Audio Developer \\ Berlin, Germany, \\ falktx@falktx.com } \begin{document} \maketitle \begin{abstract} \begin{contentsmall} Carla is a fully-featured audio plugin host with support for many plugin formats, featuring automation of plugin parameters via MIDI CC, remote control over OSC, among others. This workshop plans to give a quick overview of Carla and go through some workflows together with the audience. \end{contentsmall} \end{abstract} \keywords{ \begin{contentsmall} Plugin, Host, Modular, MIDI, OSC, Rack, Patchbay \end{contentsmall} } \section{Introduction} The first part of the workshop is a quick personal introduction, followed by a small musical demo. The demo features a MIDI sequencer to generate events, but the entire output sound comes from Carla. It serves as a demonstration of what we can with it. \section{Overview} After showing a demo song, the workshop continues by a quick overview of Carla's features and its graphical interface. This will allow for those that don't know Carla yet to easily catch up on its current status. \subsection{Features} First, we describe the main Carla features, to inform those that don't know the application yet. \subsection{Interface} Next, we go through the most important elements of Carla's UI and explain what they do, and what they mean. We also describe the possible settings, and do a local scan for plugins (so we can actually use them). \section{Workflows} This is the main content of the workshop. We will go through a few Carla setups to cover as many use-cases as possible. \subsection{The First Sound} To get the audience acquainted with Carla, we will first load a few plugins and have them make some sound. We introduce managing plugins and connections here. If possible, we demonstrate the use of a MIDI keyboard together with Carla. \subsection{Rack Mode} One of the main features of Carla is the Rack mode. We will describe how it works, and how we can use it in creative ways to produce sounds using multiple plugins. \subsection{Sequencing MIDI} In a modular host, we can create sound without user input by using MIDI generator plugins. We will demonstrate two of such plugins. and use them to drive a basic drum kit and synth. \subsection{Modular Side-chain} Modular setups make it easy to setup side-chains. We will quickly go through one of these, using what we learned so far. \subsection{Carla as a plugin} Carla works as a plugin, not just a standalone application. We will show some possible use-cases for this feature, showing Carla running inside Carla and in regular DAWs. \subsection{Remote OSC Control} OSC is a common protocol used to control audio applications remotely. Carla-Control can be used to control a remote Carla instance over the network. We will connect two Carla instances together, running on different systems. \section{Questions} We reserve a space at the end of the workshop for questions from the audience. \section{Conclusions} We conclude the workshop with a thank you to the audience. \end{document} Carla-2.1/data/presentation/lac2018/projects/000077500000000000000000000000001364475620200207365ustar00rootroot00000000000000Carla-2.1/data/presentation/lac2018/projects/1.carxp000066400000000000000000017462141364475620200221540ustar00rootroot00000000000000 false false true false 200 4000 DSSI EQ10Q Stereo /usr/lib/dssi/ls16.so Yes 1 0x0 0 Mute 01 0 1 Mute 02 0 2 Mute 03 0 3 Mute 04 0 4 Mute 05 0 5 Mute 06 0 6 Mute 07 0 7 Mute 08 0 8 Mute 09 0 9 Mute 10 0 10 Mute 11 0 11 Mute 12 0 12 Mute 13 0 13 Mute 14 1 14 Mute 15 1 15 Mute 16 1 16 Solo 01 1 17 Solo 02 1 18 Solo 03 1 19 Solo 04 1 20 Solo 05 1 21 Solo 06 1 22 Solo 07 1 23 Solo 08 1 24 Solo 09 1 25 Solo 10 1 26 Solo 11 1 27 Solo 12 1 28 Solo 13 1 29 Solo 14 1 30 Solo 15 1 31 Solo 16 1 32 Volume 01 1 1 0 33 Volume 02 3.16227769851685 34 Volume 03 3.16227769851685 35 Volume 04 3.16227769851685 36 Volume 05 3.16227769851685 37 Volume 06 3.16227769851685 38 Volume 07 3.16227769851685 39 Volume 08 3.16227769851685 40 Volume 09 3.16227769851685 41 Volume 10 3.16227769851685 42 Volume 11 2 43 Volume 12 0 44 Volume 13 0 45 Volume 14 0 46 Volume 15 0 47 Volume 16 0 48 Pan 01 0 49 Pan 02 0 50 Pan 03 0 51 Pan 04 0 52 Pan 05 0 53 Pan 06 0 54 Pan 07 0 55 Pan 08 0 56 Pan 09 0 57 Pan 10 0 58 Pan 11 0 59 Pan 12 0 60 Pan 13 0 61 Pan 14 0 62 Pan 15 0 63 Pan 16 0 http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted false VST2 Minihost Modular /home/falktx/.wineflstudio/drive_c/Program Files (x86)/VstPlugins/IL Minihost Modular.dll 1296583985 Yes 1 0x1e9 http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted false GBcfHxIRzasDAVJmvKuaGUlMR1JBUEgAABAAWGMAAAcQAAAABgAAAAIAR3JhcGgACgAEAAgABhAAAE1vZHVsZQAFAAAACGdyYXBoT2JqZWN0AAAQAAAABgAA AAIAVW50aXRsZWQgR3JhcGgABQAAAAAABQAAAAAABQAAAMhCBQAAAABCAgA8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJVVEYtOCI/Pg0KDQptZXRh ZGF0YQ0KPG1ldGFkYXRhIGJwbT0iMTIwIiBzaHVmZmxlPSIwIiBtZXRyb25vbWVWb2x1bWU9IjAiLz4NCgADZWRpdG9yWAD/////A2VkaXRvclkA/////wFl ZGl0b3JPcGVuAAABc2xlZXBFbmFibGVkAAEIAAkQAAAAAQAAAAMAAAAAAAgAChAAAAABAAAAAwAAAAAACAAIEAAAAAUAAAADAAQAAAAIAAMQAAAABAAAAAgA ARAAAFBpbgADAAAACAAAEAAAAAYAAAACAEF1ZGlvIEluAAUAAAAgQQUAAAAgQQUAAADIQQUAAAAgQQIAAAMAAAAAAAMAAAAAAAMAAgAAAAEAAQMAAAAAAAgA AhAAAAADAAAACAABEAAAUGluAAMAAAAIAAAQAAAABgAAAAIATUlESSBJbgAFAAAAIEEFAAAA8EEFAAAAyEEFAAAAIEECAAADAAAAAAADAAEAAAABAAEDAAAA AAAIAAMQAAAABAAAAAgAARAAAFBpbgADAAAACAAAEAAAAAYAAAACAEF1ZGlvIE91dAAFAAAASEQFAAAAIEEFAAAAyEEFAAAAIEECAAADAAEAAAADAAAAAAAD AAIAAAABAAEDAAAAAAAIAAIQAAAAAwAAAAgAARAAAFBpbgADAAAACAAAEAAAAAYAAAACAE1JREkgT3V0AAUAAABIRAUAAADwQQUAAADIQQUAAAAgQQIAAAMA AQAAAAMAAQAAAAEAAQMAAAAAAFYDAABYAgAA VST2 DirectWave VSTi /home/falktx/.wineflstudio/drive_c/Program Files (x86)/VstPlugins/DirectWave/DirectWave VSTi.dll 1095976023 Yes 1 0x1e8 http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted false JQAAAAYAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAgAABQAAAAAAAAAAAAAAAAUAAAB0AgAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAJpNJPwAAAD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAdAIAAAAAAAABAAAAPAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACaTST8AAAA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAHQCAAAAAAAAAgAAADwAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAMgAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmk0k/AAAAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAB0AgAAAAAA AAMAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAADIAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJpNJPwAAAD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF AAAAdAIAAAAAAAAEAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAA AAAAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACaTST8AAAA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAABQAAAHQCAAAAAAAABQAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAUAAAAAAAAAAAAAAMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmk0k/AAAAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAUAAAB0AgAAAAAAAAYAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAAAAADIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJpNJPwAAAD8AAIA/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAdAIAAAAAAAAHAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACaTST8AAAA/AACAPwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAHQCAAAAAAAACAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmk0k/AAAA PwAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAB0AgAAAAAAAAkAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAAAAADIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAJpNJPwAAAD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAdAIAAAAAAAAKAAAAPAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACaTST8AAAA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAHQCAAAAAAAACwAAADwAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAMgAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmk0k/AAAAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAB0AgAAAAAA AAwAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAADIAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJpNJPwAAAD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF AAAAdAIAAAAAAAANAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAAAAAAA AAAAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACaTST8AAAA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAABQAAAHQCAAAAAAAADgAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AA4AAAAAAAAAAAAAAMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmk0k/AAAAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAUAAAB0AgAAAAAAAA8AAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAPAAAAAAAAAAAAAADIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJpNJPwAAAD8AAIA/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAA AAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4A AAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3M zD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAA AAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAA AACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAA AAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA EgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAA AACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAA AAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA JAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAA AACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAA AAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA NgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAA AACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAA AAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA SAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAA AACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAA AAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA WgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAA AACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAA AAAAAAEAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAA AAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAA AAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAA AAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABu AAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABu AAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABu AAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABu AAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABu AAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABu AAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAA AAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAAgAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0t ZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8A AIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAA AAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACA PwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAA AAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACA PwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAA AAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACA PwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAA AAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACA PwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAA AAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACA PwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAA AABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACA PwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAA AABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAADAAAA AAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAA AEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADN zMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAA AAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0A AAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAA DQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8A AAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEA AAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAA DQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMA AAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAA DQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUA AAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAA DQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAA AAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAAQAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAA AAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAAR AAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0A AAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAA AABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAP AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAA AABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAh AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAA AABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAz AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAA AABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABF AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAA AABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABX AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAABQAAAAAAAACAPwAA AAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8A AAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8A AAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAA AAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAA AACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAA AAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA EQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAA AACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAA AAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA IwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAA AACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAA AAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA NQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAA AACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAA AAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA RwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAA AACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAA AAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA WQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAA AACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAA AAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAAGAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAA CgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAA AACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAA AAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABu AAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABu AAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABu AAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABu AAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABu AAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABu AAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAAcAAAAAAAAAgD8AAAAAAAAAAAAA AAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9q AAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABs AAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAA AAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAA AAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACA PwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAA AAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACA PwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAA AAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACA PwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAA AAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACA PwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAA AABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACA PwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAA AABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAA AAMLAAAAAAAAZAAAAB4AAAAAAAAACAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAA AAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/ AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0A AAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwA AAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4A AAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAA AAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAA DQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIA AAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAA DQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQA AAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAA DQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAAJAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAA AABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAA AAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAA AAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAA AA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAA AABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAO AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAA AABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAg AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAA AABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAy AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAA AABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABE AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAA AABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABW AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAA AGQAAAAeAAAAAAAAAAoAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAA AABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAA bAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAA AAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAA AACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAA AAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA EAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAA AACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAA AAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA IgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAA AACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAA AAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA NAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAA AACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAA AAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA RgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAA AACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAA AAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA WAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAA AACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAA AAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAACwAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMA AAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+ AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADN zMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAA AAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABu AAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABu AAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABu AAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABu AAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABu AAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABu AAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAA AAAAAAAMAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIA AAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAA AAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0A AAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAA AAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACA PwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAA AAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACA PwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAA AAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACA PwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAA AAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACA PwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAA AABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACA PwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAA AABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAA AAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAA0AAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0t LWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/ AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8A AAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsA AAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0A AAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8A AAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEA AAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAA DQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMA AAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAA DQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAADgAA AAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAA AABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAA zczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAA AAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAA AABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAN AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAA AABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAf AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAA AABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAx AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAA AABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABD AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAA AABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABV AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAA AAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAAPAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAA AAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAA EQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABt AAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAA AACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAA AAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA DwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAA AACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAA AAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA IQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAA AACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAA AAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA MwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAA AACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAA AAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA RQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAA AACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAA AAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA VwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAA AACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAA AAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAABAAAAAAAAAAgD8A AAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/ AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/ AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0A AAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABu AAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABu AAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABu AAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABu AAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABu AAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABu AAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAA AAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAEQAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAA AAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAA AAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAA AAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAA AAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACA PwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAA AAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACA PwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAA AAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACA PwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAA AAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACA PwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAA AABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACA PwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAA AABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAASAAAAAAAAAIA/AAAAAAAAAAAA AAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/ agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAA bAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAA AAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoA AAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwA AAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4A AAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAA AAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAA DQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIA AAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAA DQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEA AAADCwAAAAAAAGQAAAAeAAAAAAAAABMAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAA AAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAA PwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABt AAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAA AABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAM AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAA AABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAe AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAA AABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAw AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAA AABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABC AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAA AABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABU AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAA AABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAFAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAA AAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAA AAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAA AAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4A AAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAA AACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAA AAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA DgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAA AACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAA AAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA IAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAA AACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAA AAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA MgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAA AACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAA AAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA RAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAA AACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAA AAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA VgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAA AACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAA AAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAA AABkAAAAHgAAAAAAAAAVAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAA AAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAA AGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAA AAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABu AAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABu AAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABu AAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABu AAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABu AAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABu AAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAABYAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAAD AAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACA PgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAA zczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAA AAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACA PwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAA AAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACA PwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAA AAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACA PwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAA AAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACA PwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAA AABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACA PwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAA AABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4A AAAAAAAAFwAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAAS AAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAA AAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABt AAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkA AAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAA DQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsA AAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0A AAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8A AAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAA DQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEA AAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAA DQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMA AAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAAYAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAt LS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABA PwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/ AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAA AABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAL AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAA AABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAd AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAA AABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAv AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAA AABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABB AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAA AABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABT AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAA AABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAABkA AAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAA AAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAA AM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAA AAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAA AACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAA AAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA DQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAA AACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAA AAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA HwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAA AACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAA AAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA MQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAA AACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAA AAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA QwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAA AACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAA AAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA VQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAA AACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAA AAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8A AAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAGgAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAA AAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAA ABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAA bQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABu AAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABu AAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABu AAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABu AAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABu AAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABu AAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAAbAAAAAAAAAIA/ AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABA PwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACA PwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABt AAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACA PwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAA AAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACA PwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAA AAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACA PwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAA AAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACA PwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAA AABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACA PwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAA AABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAA AAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAABwAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgA AAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAA AAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAA AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgA AAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoA AAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwA AAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4A AAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAA DQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAA AAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAA DQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIA AAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAHQAAAAAAAACAPwAAAAAAAAAA AAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABA P2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAA AGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAA AAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAA AABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAK AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAA AABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAc AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAA AABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAu AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAA AABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABA AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAA AABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABS AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAA AABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAAB AAAAAwsAAAAAAABkAAAAHgAAAAAAAAAeAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAA AAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAA AD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAA bQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAA AACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAA AAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA DAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAA AACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAA AAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA HgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAA AACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAA AAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA MAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAA AACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAA AAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA QgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAA AACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAA AAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA VAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAA AACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAA AAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAB8AAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAA AAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAA AAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAA AAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABu AAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABu AAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABu AAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABu AAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABu AAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABu AAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAA AAAAZAAAAB4AAAAAAAAAIAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAA AAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAA AABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAA AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACA PwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAA AAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACA PwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAA AAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACA PwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAA AAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACA PwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAA AABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACA PwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAA AABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAAhAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAA AwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAA gD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAA AM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAA AAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcA AAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAA DQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkA AAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsA AAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0A AAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAA DQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8A AAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAA DQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEA AAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAe AAAAAAAAACIAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAA EgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQA AAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAA bQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAA AABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJ AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAA AABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAb AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAA AABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAt AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAA AABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/ AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAA AABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABR AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAA AABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABj AAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAIwAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAA LS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAA QD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACA PwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAA AACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAA AAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA CwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAA AACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAA AAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA HQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAA AACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAA AAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA LwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAA AACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAA AAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA QQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAA AACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAA AAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA UwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAA AACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAA AAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAAk AAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAA AAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAA AADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAA AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABu AAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABu AAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABu AAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABu AAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABu AAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/ AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAACUAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAA AAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsA AAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAA AG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACA PwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAA AAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACA PwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAA AAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACA PwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAA AAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACA PwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAA AABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACA PwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAA AABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAJgAAAAAAAACA PwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAA QD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAA gD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAA bQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYA AAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgA AAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoA AAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwA AAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAA DQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4A AAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAA DQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAA AAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAA AAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAAnAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABo AAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAA AAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAA AAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAA AABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAI AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAA AABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAa AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAA AABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAs AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAA AABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+ AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAA AABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQ AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAA AABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABi AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAACgAAAAAAAAAgD8AAAAAAAAA AAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAA QD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAA AABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAA AAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAA AAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA CgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAA AACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAA AAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA HAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAA AACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAA AAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA LgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAA AACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAA AAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA QAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAA AACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAA AAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA UgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAA AACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAA AAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAA AQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAKQAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAA AAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4A AAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAA AG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABu AAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABu AAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABu AAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABu AAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABu AAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAAqAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAA AAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEA AAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQA AAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAA bgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACA PwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAA AAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACA PwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAA AAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACA PwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAA AAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACA PwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAA AABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACA PwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAA AABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAA AAAAAGQAAAAeAAAAAAAAACsAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAA AAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4A AAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAA AAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUA AAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcA AAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkA AAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsA AAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAA DQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0A AAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAA DQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8A AAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAA DQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAALAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAA AAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAA AIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAA AADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAA AAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAA AABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAH AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAA AABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZ AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAA AABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAr AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAA AABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9 AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAA AABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABP AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAA AABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABh AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAA HgAAAAAAAAAtAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAA ABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAU AAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAA AG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAA AAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA CQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAA AACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAA AAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA GwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAA AACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAA AAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA LQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAA AACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAA AAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA PwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAA AACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAA AAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA UQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAA AACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAA AAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA YwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAC4AAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAA AC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8A AEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAA gD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABu AAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABu AAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABu AAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABu AAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABu AAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAA LwAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAA AAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAA AAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAA AAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACA PwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAA AAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACA PwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAA AAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACA PwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAA AAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACA PwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAA AABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACA PwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAA AABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACA PwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAAwAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAA AAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5r AAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAA AABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQA AAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYA AAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgA AAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoA AAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAA DQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwA AAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAA DQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4A AAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAA DQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAADEAAAAAAAAA gD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8A AEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0A AIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAA AG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAA AABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAG AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAA AABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAY AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAA AABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAq AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAA AABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8 AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAA AABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABO AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAA AABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABg AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAA AAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAMgAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAA aAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAA AAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQA AAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAA AAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA CAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAA AACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAA AAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA GgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAA AACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAA AAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA LAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAA AACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAA AAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA PgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAA AACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAA AAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA UAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAA AACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAA AAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA YgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAAzAAAAAAAAAIA/AAAAAAAA AAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8A AEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAA AAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAA AAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABu AAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABu AAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABu AAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABu AAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABu AAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAA AAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAADQAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAA AAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+ AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAA AABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACA PwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAA AAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACA PwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAA AAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACA PwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAA AAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACA PwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAA AABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACA PwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAA AABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACA PwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAANQAAAAAAAACAPwAAAAAAAAAAAAAAAAAA AAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAAR AAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAU AAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAA AG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMA AAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUA AAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcA AAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAA DQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkA AAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAA DQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsA AAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAA DQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0A AAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAA DQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsA AAAAAABkAAAAHgAAAAAAAAA2AAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAA AAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+ AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQA AAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAA AABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAF AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAA AABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAX AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAA AABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAp AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAA AABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7 AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAA AABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABN AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAA AABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABf AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAADcAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYA AAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAA AACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAA AAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAA AAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA BwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAA AACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAA AAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA GQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAA AACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAA AAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA KwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAA AACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAA AAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA PQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAA AACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAA AAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA TwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAA AACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAA AAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA YQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAA AB4AAAAAAAAAOAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkA AAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAA FAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAA AABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABu AAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABu AAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABu AAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABu AAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABu AAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAA5AAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAA AAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/ AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0A AIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACA PwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAA AAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACA PwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAA AAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACA PwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAA AAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACA PwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAA AABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACA PwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAA AABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACA PwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAA ADoAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAA AAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAA AAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQA AAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIA AAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQA AAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYA AAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgA AAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAA DQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoA AAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAA DQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwA AAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAA DQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAA gD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAOwAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAA AAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+ awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAA AAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAA AABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAE AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAA AABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAW AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAA AABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAo AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAA AABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6 AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAA AABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABM AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAA AABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABe AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAA8AAAAAAAA AIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/ AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9 AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAA AABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA BgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAA AACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAA AAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA GAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAA AACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAA AAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA KgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAA AACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAA AAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA PAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAA AACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAA AAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA TgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAA AACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAA AAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA YAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIA AAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAD0AAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAA AGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAA AAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAE AAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABu AAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABu AAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABu AAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABu AAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABu AAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAPgAAAAAAAACAPwAAAAAA AAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/ AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAA AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQA AAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACA PwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAA AAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACA PwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAA AAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACA PwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAA AAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACA PwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAA AABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACA PwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAA AABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACA PwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAA AAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAA/AAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAA AAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACA PgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAA AAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEA AAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMA AAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUA AAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAA DQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcA AAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAA DQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkA AAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAA DQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsA AAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAA DQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAEAAAAAAAAAAgD8AAAAAAAAAAAAAAAAA AAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAA EQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAA FAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAA AABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAD AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAA AABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAV AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAA AABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAn AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAA AABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5 AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAA AABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABL AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAA AABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABd AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAML AAAAAAAAZAAAAB4AAAAAAAAAQQAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAA AAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACA PgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAE AAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA BQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAA AACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAA AAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA FwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAA AACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAA AAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA KQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAA AACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAA AAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA OwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAA AACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAA AAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA TQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAA AACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAA AAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA XwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAABCAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABm AAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAA AAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAA AAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0A AAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABu AAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABu AAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABu AAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABu AAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABu AAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQA AAAeAAAAAAAAAEMAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABp AAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAA ABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAA AAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACA PwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAA AAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACA PwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAA AAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACA PwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAA AAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACA PwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAA AAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACA PwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAA AABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACA PwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAA AABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAARAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAA AAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAA PwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9 AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAA AAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIA AAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQA AAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYA AAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAA DQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgA AAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAA DQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoA AAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAA DQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAA AABFAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAA AAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAA AAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAE AAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAC AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAA AABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAU AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAA AABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAm AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAA AABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4 AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAA AABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABK AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAA AABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABc AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAA AIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAEYAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcA AAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACA PmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAA AAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA BAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAA AACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAA AAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA FgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAA AACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAA AAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA KAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAA AACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAA AAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA OgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAA AACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAA AAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA TAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAA AACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAA AAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA XgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAARwAAAAAA AACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABA PwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczM PQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAA AAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABu AAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABu AAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABu AAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABu AAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABu AAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAAC AAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAABIAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAA AABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAA AAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAA BAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACA PwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAA AAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACA PwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAA AAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACA PwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAA AAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACA PwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAA AAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACA PwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAA AABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACA PwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAA AABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAEkAAAAAAAAAgD8AAAAA AAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAA PwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAA AAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAE AAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAA DQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEA AAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMA AAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUA AAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAA DQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcA AAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAA DQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkA AAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAA DQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAA AAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAASgAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoA AAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAA gD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAA AAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAB AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAA AABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAT AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAA AABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAl AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAA AABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3 AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAA AABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJ AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAA AABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABb AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAABLAAAAAAAAAIA/AAAAAAAAAAAAAAAA AAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAA ABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAA ABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAA AAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA AwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAA AACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAA AAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA FQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAA AACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAA AAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA JwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAA AACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAA AAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA OQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAA AACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAA AAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA SwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAA AACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAA AAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA XQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAAD CwAAAAAAAGQAAAAeAAAAAAAAAEwAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAA AAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAA gD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAA BAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABu AAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABu AAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABu AAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABu AAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABu AAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABu AAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAATQAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAA ZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAA AAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAA AAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAAN AAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACA PwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAA AAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACA PwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAA AAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACA PwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAA AAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACA PwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAA AAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACA PwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAA AABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACA PwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAA AABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABk AAAAHgAAAAAAAABOAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAA aQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwA AAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAA AAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAA DQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAA AAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIA AAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQA AAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAA DQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYA AAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAA DQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgA AAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAA DQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAE8AAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAA AAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAA AD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczM PQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAA AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAA AABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAS AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAA AABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAk AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAA AABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2 AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAA AABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABI AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAA AABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABa AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAA AAAAUAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAA AAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAA AAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAA BAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA AgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAA AACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAA AAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA FAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAA AACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAA AAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA JgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAA AACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAA AAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA OAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAA AACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAA AAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA SgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAA AACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAA AAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA XAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAA AACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAABRAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1n AAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAA gD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAA AAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABu AAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABu AAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABu AAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABu AAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABu AAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABu AAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAFIAAAAA AAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAA QD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3M zD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAA AAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACA PwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAA AAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACA PwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAA AAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACA PwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAA AAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACA PwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAA AAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACA PwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAA AABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACA PwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAA AABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAA AgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAUwAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAA AAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEA AAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAA AAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAA DQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8A AAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAA DQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEA AAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMA AAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAA DQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUA AAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAA DQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcA AAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAA DQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAABUAAAAAAAAAIA/AAAA AAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAA AD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAA AAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAA BAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAA AABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAR AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAA AABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAj AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAA AABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1 AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAA AABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABH AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAA AABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZ AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAA AAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAFUAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAK AAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAA AIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAA AAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA AQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAA AACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAA AAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA EwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAA AACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAA AAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA JQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAA AACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAA AAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA NwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAA AACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAA AAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA SQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAA AACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAA AAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA WwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAA AACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAVgAAAAAAAACAPwAAAAAAAAAAAAAA AAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oA AAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwA AAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAA AAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABu AAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABu AAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABu AAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABu AAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABu AAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABu AAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAA AwsAAAAAAABkAAAAHgAAAAAAAABXAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAA AAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8A AIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAA AAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACA PwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAA AAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACA PwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAA AAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACA PwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAA AAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACA PwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAA AAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACA PwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAA AABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACA PwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAA AABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAFgAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAA AGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAA AAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAA AAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAA DQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4A AAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAA DQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAA AAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIA AAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAA DQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQA AAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAA DQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYA AAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAA DQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAA ZAAAAB4AAAAAAAAAWQAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAA AGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABs AAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAA AAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAA AABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQ AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAA AABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAi AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAA AABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0 AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAA AABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABG AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAA AABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABY AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAABaAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAA AAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4A AAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3M zD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAA AAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAA AACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAA AAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA EgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAA AACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAA AAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA JAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAA AACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAA AAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA NgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAA AACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAA AAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA SAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAA AACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAA AAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA WgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAA AACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAA AAAAAFsAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAA AAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAA AAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAA AAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABu AAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABu AAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABu AAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABu AAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABu AAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABu AAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAA AAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAXAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0t ZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8A AIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAA AAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACA PwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAA AAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACA PwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAA AAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACA PwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAA AAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACA PwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAA AAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACA PwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAA AABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACA PwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAA AABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAABdAAAA AAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAA AEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADN zMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAA AAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0A AAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAA DQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8A AAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEA AAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAA DQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMA AAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAA DQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUA AAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAA DQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAA AAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAF4AAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAA AAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAAR AAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0A AAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAA AABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAP AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAA AABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAh AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAA AABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAz AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAA AABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABF AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAA AABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABX AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAXwAAAAAAAACAPwAA AAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8A AAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8A AAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAA AAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAA AACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAA AAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA EQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAA AACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAA AAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA IwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAA AACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAA AAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA NQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAA AACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAA AAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA RwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAA AACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAA AAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA WQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAA AACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAA AAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAABgAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAA CgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAA AACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAA AAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABu AAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABu AAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABu AAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABu AAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABu AAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABu AAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAGEAAAAAAAAAgD8AAAAAAAAAAAAA AAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9q AAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABs AAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAA AAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAA AAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACA PwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAA AAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACA PwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAA AAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACA PwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAA AAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACA PwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAA AABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACA PwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAA AABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAA AAMLAAAAAAAAZAAAAB4AAAAAAAAAYgAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAA AAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/ AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0A AAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwA AAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4A AAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAA AAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAA DQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIA AAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAA DQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQA AAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAA DQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAABjAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAA AABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAA AAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAA AAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAA AA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAA AABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAO AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAA AABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAg AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAA AABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAy AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAA AABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABE AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAA AABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABW AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAA AGQAAAAeAAAAAAAAAGQAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAA AABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAA bAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAA AAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAA AACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAA AAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA EAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAA AACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAA AAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA IgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAA AACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAA AAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA NAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAA AACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAA AAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA RgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAA AACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAA AAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA WAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAA AACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAA AAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAZQAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMA AAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+ AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADN zMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAA AAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABu AAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABu AAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABu AAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABu AAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABu AAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABu AAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAA AAAAAABmAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIA AAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAA AAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0A AAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAA AAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACA PwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAA AAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACA PwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAA AAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACA PwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAA AAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACA PwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAA AABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACA PwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAA AABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAA AAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAGcAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0t LWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/ AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8A AAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsA AAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0A AAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8A AAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEA AAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAA DQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMA AAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAA DQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAaAAA AAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAA AABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAA zczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAA AAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAA AABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAN AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAA AABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAf AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAA AABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAx AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAA AABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABD AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAA AABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABV AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAA AAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAABpAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAA AAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAA EQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABt AAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAA AACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAA AAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA DwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAA AACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAA AAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA IQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAA AACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAA AAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA MwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAA AACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAA AAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA RQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAA AACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAA AAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA VwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAA AACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAA AAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAGoAAAAAAAAAgD8A AAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/ AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/ AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0A AAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABu AAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABu AAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABu AAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABu AAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABu AAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABu AAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAA AAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAawAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAA AAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAA AAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAA AAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAA AAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACA PwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAA AAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACA PwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAA AAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACA PwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAA AAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACA PwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAA AABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACA PwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAA AABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAABsAAAAAAAAAIA/AAAAAAAAAAAA AAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/ agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAA bAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAA AAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoA AAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwA AAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4A AAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAA AAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAA DQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIA AAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAA DQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEA AAADCwAAAAAAAGQAAAAeAAAAAAAAAG0AAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAA AAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAA PwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABt AAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAA AABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAM AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAA AABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAe AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAA AABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAw AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAA AABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABC AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAA AABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABU AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAA AABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAbgAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAA AAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAA AAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAA AAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4A AAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAA AACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAA AAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA DgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAA AACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAA AAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA IAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAA AACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAA AAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA MgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAA AACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAA AAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA RAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAA AACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAA AAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA VgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAA AACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAA AAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAA AABkAAAAHgAAAAAAAABvAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAA AAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAA AGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAA AAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABu AAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABu AAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABu AAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABu AAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABu AAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABu AAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAHAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAAD AAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACA PgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAA zczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAA AAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACA PwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAA AAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACA PwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAA AAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACA PwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAA AAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACA PwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAA AABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACA PwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAA AABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4A AAAAAAAAcQAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAAS AAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAA AAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABt AAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkA AAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAA DQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsA AAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0A AAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8A AAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAA DQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEA AAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAA DQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMA AAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAByAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAt LS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABA PwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/ AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAA AABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAL AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAA AABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAd AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAA AABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAv AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAA AABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABB AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAA AABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABT AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAA AABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAHMA AAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAA AAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAA AM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAA AAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAA AACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAA AAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA DQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAA AACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAA AAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA HwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAA AACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAA AAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA MQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAA AACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAA AAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA QwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAA AACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAA AAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA VQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAA AACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAA AAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8A AAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAdAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAA AAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAA ABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAA bQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABu AAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABu AAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABu AAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABu AAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABu AAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABu AAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAB1AAAAAAAAAIA/ AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABA PwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACA PwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABt AAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACA PwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAA AAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACA PwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAA AAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACA PwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAA AAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACA PwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAA AABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACA PwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAA AABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAA AAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAHYAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgA AAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAA AAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAA AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgA AAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoA AAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwA AAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4A AAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAA DQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAA AAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAA DQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIA AAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAdwAAAAAAAACAPwAAAAAAAAAA AAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABA P2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAA AGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAA AAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAA AABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAK AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAA AABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAc AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAA AABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAu AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAA AABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABA AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAA AABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABS AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAA AABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAAB AAAAAwsAAAAAAABkAAAAHgAAAAAAAAB4AAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAA AAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAA AD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAA bQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAA AACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAA AAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA DAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAA AACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAA AAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA HgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAA AACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAA AAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA MAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAA AACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAA AAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA QgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAA AACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAA AAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA VAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAA AACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAA AAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAHkAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAA AAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAA AAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAA AAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABu AAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABu AAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABu AAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABu AAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABu AAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABu AAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAA AAAAZAAAAB4AAAAAAAAAegAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAALS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAA AAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAAQD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAA AABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAA AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAAAACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACA PwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAA AAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAAAACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACA PwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAA AAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACA PwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAA AAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAAAACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAAAAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACA PwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAA AABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAAAACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAAAAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACA PwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAA AABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAAAACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAAAAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAB7AAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAA AwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAAAAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAA gD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAA AM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAA AAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcA AAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAA DQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABuAAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkA AAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAA DQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsA AAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAA DQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABuAAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0A AAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAA DQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABuAAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8A AAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAA DQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAA gD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABuAAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAA AAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAA AG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEA AAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAe AAAAAAAAAHwAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAAAAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAA EgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsAAAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQA AAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAA bQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAA AABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJ AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAA AABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAb AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAA AABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAt AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAAAAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAA AABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/ AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACAPwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAAAABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAA AABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABR AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACAPwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAA AA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAAAABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAA AIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAA AAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAA AABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABj AAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAAAQAAAAMLAAAAAAAAZAAAAB4AAAAAAAAAfQAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAZgAAAAMAAAAAAAAA LS0tZwAAAAAAAAAAAAAAaAAAAAoAAAAAAAAAAAAAAAAAAAAAAGkAAAASAAAAAAAAAAAAAABAPwAAQD8AAAA/AABAP2oAAAARAAAAAAAAAAAAAIA+AAAAPwAA QD8AAIA+awAAABEAAAAAAAAAAAAAgD4AAAA/AACAPgAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAAAGwAAAAUAAAAAAAAAAAAAADNzMw9AACA PwAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG4AAAANAAAAAAAAAAAAAAAA AACAPwAAAABuAAAADQAAAAAAAAABAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAAgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAMAAAAAAACAPwAAAABuAAAADQAA AAAAAAAEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAHAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAACAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAKAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA CwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAwAAAAAAACAPwAAAABuAAAADQAAAAAAAAANAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAA8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABIAAAAA AACAPwAAAABuAAAADQAAAAAAAAATAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABUAAAAAAACAPwAAAABuAAAADQAA AAAAAAAWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAZAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAGgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAcAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA HQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAfAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAACEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACQAAAAA AACAPwAAAABuAAAADQAAAAAAAAAlAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACcAAAAAAACAPwAAAABuAAAADQAA AAAAAAAoAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACoAAAAAAACAPwAAAABuAAAADQAAAAAAAAArAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAALAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAuAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA LwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADAAAAAAAACAPwAAAABuAAAADQAAAAAAAAAxAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAADMAAAAAAACAPwAAAABuAAAADQAAAAAAAAA0AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADYAAAAA AACAPwAAAABuAAAADQAAAAAAAAA3AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADkAAAAAAACAPwAAAABuAAAADQAA AAAAAAA6AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADwAAAAAAACAPwAAAABuAAAADQAAAAAAAAA9AAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAPgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD8AAAAAAACAPwAAAABuAAAADQAAAAAAAABAAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA QQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEIAAAAAAACAPwAAAABuAAAADQAAAAAAAABDAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARAAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAEUAAAAAAACAPwAAAABuAAAADQAAAAAAAABGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEgAAAAA AACAPwAAAABuAAAADQAAAAAAAABJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEsAAAAAAACAPwAAAABuAAAADQAA AAAAAABMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE4AAAAAAACAPwAAAABuAAAADQAAAAAAAABPAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAUAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFEAAAAAAACAPwAAAABuAAAADQAAAAAAAABSAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAA UwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFQAAAAAAACAPwAAAABuAAAADQAAAAAAAABVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVgAAAAAAAIA/AAAAAG4A AAANAAAAAAAAAFcAAAAAAACAPwAAAABuAAAADQAAAAAAAABYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFoAAAAA AACAPwAAAABuAAAADQAAAAAAAABbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF0AAAAAAACAPwAAAABuAAAADQAA AAAAAABeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGAAAAAAAACAPwAAAABuAAAADQAAAAAAAABhAAAAAAAAgD8A AAAAbgAAAA0AAAAAAAAAYgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGMAAAAAAACAPwAAAAACAAAAAAAAAAAAAAABAAAAAwsAAAAAAABkAAAAHgAAAAAAAAB+ AAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAABmAAAAAwAAAAAAAAAtLS1nAAAAAAAAAAAAAABoAAAACgAAAAAAAAAAAAAAAAAAAAAAaQAAABIAAAAAAAAA AAAAAEA/AABAPwAAAD8AAEA/agAAABEAAAAAAAAAAAAAgD4AAAA/AABAPwAAgD5rAAAAEQAAAAAAAAAAAACAPgAAAD8AAIA+AAAAAGwAAAAUAAAAAAAAAAAA AADNzMw9AACAPwAAAAAAAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAA AAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbgAAAA0AAAAAAAAAAAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAEAAAAAAACAPwAAAABuAAAADQAAAAAAAAACAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAAwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAFAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAABgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAIAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAAoAAAAAAACAPwAAAABuAAAADQAAAAAAAAALAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AA0AAAAAAACAPwAAAABuAAAADQAAAAAAAAAOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABAAAAAAAACAPwAAAABu AAAADQAAAAAAAAARAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAUAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAFQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAXAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAGAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAaAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAABwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AB8AAAAAAACAPwAAAABuAAAADQAAAAAAAAAgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACIAAAAAAACAPwAAAABu AAAADQAAAAAAAAAjAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAJAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAmAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAJwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACgAAAAAAACAPwAAAABuAAAADQAAAAAAAAApAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAKgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACsAAAAAAACAPwAAAABuAAAADQAAAAAAAAAsAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAC4AAAAAAACAPwAAAABuAAAADQAAAAAAAAAvAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA ADEAAAAAAACAPwAAAABuAAAADQAAAAAAAAAyAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADQAAAAAAACAPwAAAABu AAAADQAAAAAAAAA1AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADcAAAAAAACAPwAAAABuAAAADQAAAAAAAAA4AAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAOQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADoAAAAAAACAPwAAAABuAAAADQAAAAAAAAA7AAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAPAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAD0AAAAAAACAPwAAAABuAAAADQAAAAAAAAA+AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPwAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAEAAAAAAAACAPwAAAABuAAAADQAAAAAAAABBAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQgAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AEMAAAAAAACAPwAAAABuAAAADQAAAAAAAABEAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEYAAAAAAACAPwAAAABu AAAADQAAAAAAAABHAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAASAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEkAAAAAAACAPwAAAABuAAAADQAAAAAAAABKAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAASwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEwAAAAAAACAPwAAAABuAAAADQAAAAAAAABNAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAATgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAE8AAAAAAACAPwAAAABuAAAADQAAAAAAAABQAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUQAAAAAAAIA/ AAAAAG4AAAANAAAAAAAAAFIAAAAAAACAPwAAAABuAAAADQAAAAAAAABTAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVAAAAAAAAIA/AAAAAG4AAAANAAAAAAAA AFUAAAAAAACAPwAAAABuAAAADQAAAAAAAABWAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFgAAAAAAACAPwAAAABu AAAADQAAAAAAAABZAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFsAAAAAAACAPwAAAABuAAAADQAAAAAAAABcAAAA AAAAgD8AAAAAbgAAAA0AAAAAAAAAXQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAF4AAAAAAACAPwAAAABuAAAADQAAAAAAAABfAAAAAAAAgD8AAAAAbgAAAA0A AAAAAAAAYAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAGEAAAAAAACAPwAAAABuAAAADQAAAAAAAABiAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYwAAAAAAAIA/ AAAAAAIAAAAAAAAAAAAAAAEAAAADCwAAAAAAAGQAAAAeAAAAAAAAAH8AAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAGYAAAADAAAAAAAAAC0tLWcAAAAA AAAAAAAAAGgAAAAKAAAAAAAAAAAAAAAAAAAAAABpAAAAEgAAAAAAAAAAAAAAQD8AAEA/AAAAPwAAQD9qAAAAEQAAAAAAAAAAAACAPgAAAD8AAEA/AACAPmsA AAARAAAAAAAAAAAAAIA+AAAAPwAAgD4AAAAAbAAAABQAAAAAAAAAAAAAAM3MzD0AAIA/AAAAAAAAAABsAAAAFAAAAAAAAAAAAAAAzczMPQAAgD8AAAAAAAAA AG0AAAAEAAAAAAAAAAAAAABtAAAABAAAAAAAAAAAAAAAbQAAAAQAAAAAAAAAAAAAAG0AAAAEAAAAAAAAAAAAAABuAAAADQAAAAAAAAAAAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAAQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAIAAAAAAACAPwAAAABuAAAADQAAAAAAAAADAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAAUAAAAAAACAPwAAAABuAAAADQAAAAAAAAAGAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAABwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAAgAAAAAAACAPwAAAABuAAAADQAAAAAAAAAJAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAACgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAAsAAAAAAACA PwAAAABuAAAADQAAAAAAAAAMAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAADQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAA4AAAAAAACAPwAAAABuAAAADQAAAAAA AAAPAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAEAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABEAAAAAAACAPwAAAABuAAAADQAAAAAAAAASAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAEwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAABQAAAAAAACAPwAAAABuAAAADQAAAAAAAAAVAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAFgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAABcAAAAAAACAPwAAAABuAAAADQAAAAAAAAAYAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAGQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAABoAAAAAAACAPwAAAABuAAAADQAAAAAAAAAbAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAB0AAAAAAACA PwAAAABuAAAADQAAAAAAAAAeAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAHwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACAAAAAAAACAPwAAAABuAAAADQAAAAAA AAAhAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAIgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACMAAAAAAACAPwAAAABuAAAADQAAAAAAAAAkAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAJQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAACYAAAAAAACAPwAAAABuAAAADQAAAAAAAAAnAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAACkAAAAAAACAPwAAAABuAAAADQAAAAAAAAAqAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAKwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAACwAAAAAAACAPwAAAABuAAAADQAAAAAAAAAtAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAALgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAC8AAAAAAACA PwAAAABuAAAADQAAAAAAAAAwAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAMQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADIAAAAAAACAPwAAAABuAAAADQAAAAAA AAAzAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAANAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADUAAAAAAACAPwAAAABuAAAADQAAAAAAAAA2AAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAANwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAADgAAAAAAACAPwAAAABuAAAADQAAAAAAAAA5AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAOgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAADsAAAAAAACAPwAAAABuAAAADQAAAAAAAAA8AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAPQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAD4AAAAAAACAPwAAAABuAAAADQAAAAAAAAA/AAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEEAAAAAAACA PwAAAABuAAAADQAAAAAAAABCAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAQwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEQAAAAAAACAPwAAAABuAAAADQAAAAAA AABFAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAARgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEcAAAAAAACAPwAAAABuAAAADQAAAAAAAABIAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAASQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAEoAAAAAAACAPwAAAABuAAAADQAAAAAAAABLAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATAAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAE0AAAAAAACAPwAAAABuAAAADQAAAAAAAABOAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAATwAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAFAAAAAAAACAPwAAAABuAAAADQAAAAAAAABRAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAUgAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFMAAAAAAACA PwAAAABuAAAADQAAAAAAAABUAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAVQAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFYAAAAAAACAPwAAAABuAAAADQAAAAAA AABXAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAWAAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFkAAAAAAACAPwAAAABuAAAADQAAAAAAAABaAAAAAAAAgD8AAAAA bgAAAA0AAAAAAAAAWwAAAAAAAIA/AAAAAG4AAAANAAAAAAAAAFwAAAAAAACAPwAAAABuAAAADQAAAAAAAABdAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAXgAA AAAAAIA/AAAAAG4AAAANAAAAAAAAAF8AAAAAAACAPwAAAABuAAAADQAAAAAAAABgAAAAAAAAgD8AAAAAbgAAAA0AAAAAAAAAYQAAAAAAAIA/AAAAAG4AAAAN AAAAAAAAAGIAAAAAAACAPwAAAABuAAAADQAAAAAAAABjAAAAAAAAgD8AAAAAAgAAAAAAAAAAAAAA system:capture_1 PulseAudio JACK Source:front-left system:capture_2 PulseAudio JACK Source:front-right PulseAudio JACK Sink:front-left system:playback_1 PulseAudio JACK Sink:front-right system:playback_2 Carla-2.1/data/presentation/lac2018/projects/2.carxp000066400000000000000000001024511364475620200221410ustar00rootroot00000000000000 false false true false 200 4000 INTERNAL ZynReverb Yes 0 1 0x5 0 Time 93 1 Delay 15 2 Feedback 0 5 Low-Pass Filter 114 6 High-Pass Filter 0 7 Damp 77 8 Type 0 9 Room size 95 10 Bandwidth 20 1 12 SFZ AcousticGuitar /home/falktx/Personal/Muzyks/Kits/SFZ/AcousticGuitarFREE Samples/AcousticGuitar.sfz Yes 1 0x1f0 1 AcousticGuitar http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted true LV2 MIDI Seq Guitar http://gareus.org/oss/lv2/stepseq#s8n8 Yes 1 0x1 0 Sync sync 1 1 BPM bpm 120 2 Step Duration (4/4) div 2 3 Swing swing 0 4 Drum Mode drummode 0 5 Midi Channel chn 0 6 MIDI Panic panic 0 9 Note 1 note1 69 10 Note 2 note2 67 11 Note 3 note3 65 12 Note 4 note4 64 13 Note 5 note5 62 14 Note 6 note6 60 15 Note 7 note7 59 16 Note 8 note8 57 17 Grid S: 1 N: 1 grid_1_1 127 18 Grid S: 2 N: 1 grid_2_1 0 19 Grid S: 3 N: 1 grid_3_1 127 20 Grid S: 4 N: 1 grid_4_1 127 21 Grid S: 5 N: 1 grid_5_1 0 22 Grid S: 6 N: 1 grid_6_1 0 23 Grid S: 7 N: 1 grid_7_1 0 24 Grid S: 8 N: 1 grid_8_1 0 25 Grid S: 1 N: 2 grid_1_2 0 26 Grid S: 2 N: 2 grid_2_2 127 27 Grid S: 3 N: 2 grid_3_2 0 28 Grid S: 4 N: 2 grid_4_2 0 29 Grid S: 5 N: 2 grid_5_2 0 30 Grid S: 6 N: 2 grid_6_2 0 31 Grid S: 7 N: 2 grid_7_2 0 32 Grid S: 8 N: 2 grid_8_2 0 33 Grid S: 1 N: 3 grid_1_3 0 34 Grid S: 2 N: 3 grid_2_3 0 35 Grid S: 3 N: 3 grid_3_3 0 36 Grid S: 4 N: 3 grid_4_3 0 37 Grid S: 5 N: 3 grid_5_3 0 38 Grid S: 6 N: 3 grid_6_3 0 39 Grid S: 7 N: 3 grid_7_3 127 40 Grid S: 8 N: 3 grid_8_3 127 41 Grid S: 1 N: 4 grid_1_4 0 42 Grid S: 2 N: 4 grid_2_4 0 43 Grid S: 3 N: 4 grid_3_4 0 44 Grid S: 4 N: 4 grid_4_4 0 45 Grid S: 5 N: 4 grid_5_4 127 46 Grid S: 6 N: 4 grid_6_4 0 47 Grid S: 7 N: 4 grid_7_4 0 48 Grid S: 8 N: 4 grid_8_4 0 49 Grid S: 1 N: 5 grid_1_5 0 50 Grid S: 2 N: 5 grid_2_5 0 51 Grid S: 3 N: 5 grid_3_5 0 52 Grid S: 4 N: 5 grid_4_5 0 53 Grid S: 5 N: 5 grid_5_5 0 54 Grid S: 6 N: 5 grid_6_5 127 55 Grid S: 7 N: 5 grid_7_5 0 56 Grid S: 8 N: 5 grid_8_5 0 57 Grid S: 1 N: 6 grid_1_6 0 58 Grid S: 2 N: 6 grid_2_6 0 59 Grid S: 3 N: 6 grid_3_6 0 60 Grid S: 4 N: 6 grid_4_6 0 61 Grid S: 5 N: 6 grid_5_6 0 62 Grid S: 6 N: 6 grid_6_6 0 63 Grid S: 7 N: 6 grid_7_6 0 64 Grid S: 8 N: 6 grid_8_6 0 65 Grid S: 1 N: 7 grid_1_7 0 66 Grid S: 2 N: 7 grid_2_7 0 67 Grid S: 3 N: 7 grid_3_7 0 68 Grid S: 4 N: 7 grid_4_7 0 69 Grid S: 5 N: 7 grid_5_7 0 70 Grid S: 6 N: 7 grid_6_7 0 71 Grid S: 7 N: 7 grid_7_7 0 72 Grid S: 8 N: 7 grid_8_7 0 73 Grid S: 1 N: 8 grid_1_8 0 74 Grid S: 2 N: 8 grid_2_8 0 75 Grid S: 3 N: 8 grid_3_8 0 76 Grid S: 4 N: 8 grid_4_8 0 77 Grid S: 5 N: 8 grid_5_8 0 78 Grid S: 6 N: 8 grid_6_8 0 79 Grid S: 7 N: 8 grid_7_8 0 80 Grid S: 8 N: 8 grid_8_8 0 LV2 x42-eq - Parametric Equalizer Stereo http://gareus.org/oss/lv2/fil4#stereo No 1 0x0 0 Enable enable 1 1 Gain gain 0 3 Reset Peak Hold peakreset 1 4 Highpass HighPass 0 5 Highpass Frequency HPfreq 20 6 HighPass Resonance HPQ 0.699999988079071 7 Lowpass LowPass 1 8 Lowpass Frequency LPfreq 3006.10034179688 9 LowPass Resonance LPQ 1 10 Lowshelf LSsec 1 11 Lowshelf Frequency LSfreq 80 12 Lowshelf Bandwidth LSq 1 13 Lowshelf Gain LSgain 0 14 Section 1 sec1 1 15 Frequency 1 freq1 159.999984741211 16 Bandwidth 1 q1 0.600000023841858 17 Gain 1 gain1 0 18 Section 2 sec2 1 19 Frequency 2 freq2 397.000030517578 20 Bandwidth 2 q2 0.600000023841858 21 Gain 2 gain2 0 22 Section 3 sec3 1 23 Frequency 3 freq3 1250.00012207031 24 Bandwidth 3 q3 0.600000023841858 25 Gain 3 gain3 0 26 Section 4 sec4 1 27 Frequency 4 freq4 2500.00024414062 28 Bandwidth 4 q4 0.600000023841858 29 Gain 4 gain4 0 30 Highshelf HSsec 1 31 Highshelf Frequency HSfreq 3131.60424804688 32 Highshelf Bandwidth HSq 1 33 Highshelf Gain HSgain -18 http://lv2plug.in/ns/ext/atom#Float http://gareus.org/oss/lv2/fil4#dbscale AADwQQ== http://lv2plug.in/ns/ext/atom#Float http://gareus.org/oss/lv2/fil4#fftgain AAAAAA== http://lv2plug.in/ns/ext/atom#Float http://gareus.org/oss/lv2/fil4#uiscale AACAPw== http://lv2plug.in/ns/ext/atom#Int http://gareus.org/oss/lv2/fil4#fftmode ARIAAA== http://lv2plug.in/ns/ext/atom#Int http://gareus.org/oss/lv2/fil4#fftchannel /////w== LV2 MIDI Seq Drums http://gareus.org/oss/lv2/stepseq#s8n8 No 1 0x1 0 Sync sync 1 1 BPM bpm 120 2 Step Duration (4/4) div 1 3 Swing swing 0 4 Drum Mode drummode 1 5 Midi Channel chn 0 6 MIDI Panic panic 0 9 Note 1 note1 36 10 Note 2 note2 56 11 Note 3 note3 61 12 Note 4 note4 51 13 Note 5 note5 47 14 Note 6 note6 60 15 Note 7 note7 59 16 Note 8 note8 57 17 Grid S: 1 N: 1 grid_1_1 127 18 Grid S: 2 N: 1 grid_2_1 0 19 Grid S: 3 N: 1 grid_3_1 0 20 Grid S: 4 N: 1 grid_4_1 0 21 Grid S: 5 N: 1 grid_5_1 127 22 Grid S: 6 N: 1 grid_6_1 0 23 Grid S: 7 N: 1 grid_7_1 0 24 Grid S: 8 N: 1 grid_8_1 0 25 Grid S: 1 N: 2 grid_1_2 0 26 Grid S: 2 N: 2 grid_2_2 0 27 Grid S: 3 N: 2 grid_3_2 0 28 Grid S: 4 N: 2 grid_4_2 38 29 Grid S: 5 N: 2 grid_5_2 0 30 Grid S: 6 N: 2 grid_6_2 39 31 Grid S: 7 N: 2 grid_7_2 0 32 Grid S: 8 N: 2 grid_8_2 0 33 Grid S: 1 N: 3 grid_1_3 0 34 Grid S: 2 N: 3 grid_2_3 0 35 Grid S: 3 N: 3 grid_3_3 127 36 Grid S: 4 N: 3 grid_4_3 0 37 Grid S: 5 N: 3 grid_5_3 0 38 Grid S: 6 N: 3 grid_6_3 0 39 Grid S: 7 N: 3 grid_7_3 127 40 Grid S: 8 N: 3 grid_8_3 0 41 Grid S: 1 N: 4 grid_1_4 0 42 Grid S: 2 N: 4 grid_2_4 0 43 Grid S: 3 N: 4 grid_3_4 0 44 Grid S: 4 N: 4 grid_4_4 0 45 Grid S: 5 N: 4 grid_5_4 0 46 Grid S: 6 N: 4 grid_6_4 0 47 Grid S: 7 N: 4 grid_7_4 0 48 Grid S: 8 N: 4 grid_8_4 0 49 Grid S: 1 N: 5 grid_1_5 0 50 Grid S: 2 N: 5 grid_2_5 0 51 Grid S: 3 N: 5 grid_3_5 0 52 Grid S: 4 N: 5 grid_4_5 0 53 Grid S: 5 N: 5 grid_5_5 0 54 Grid S: 6 N: 5 grid_6_5 60 55 Grid S: 7 N: 5 grid_7_5 0 56 Grid S: 8 N: 5 grid_8_5 57 57 Grid S: 1 N: 6 grid_1_6 0 58 Grid S: 2 N: 6 grid_2_6 0 59 Grid S: 3 N: 6 grid_3_6 0 60 Grid S: 4 N: 6 grid_4_6 0 61 Grid S: 5 N: 6 grid_5_6 0 62 Grid S: 6 N: 6 grid_6_6 0 63 Grid S: 7 N: 6 grid_7_6 0 64 Grid S: 8 N: 6 grid_8_6 0 65 Grid S: 1 N: 7 grid_1_7 0 66 Grid S: 2 N: 7 grid_2_7 0 67 Grid S: 3 N: 7 grid_3_7 0 68 Grid S: 4 N: 7 grid_4_7 0 69 Grid S: 5 N: 7 grid_5_7 0 70 Grid S: 6 N: 7 grid_6_7 0 71 Grid S: 7 N: 7 grid_7_7 0 72 Grid S: 8 N: 7 grid_8_7 0 73 Grid S: 1 N: 8 grid_1_8 0 74 Grid S: 2 N: 8 grid_2_8 0 75 Grid S: 3 N: 8 grid_3_8 0 76 Grid S: 4 N: 8 grid_4_8 0 77 Grid S: 5 N: 8 grid_5_8 0 78 Grid S: 6 N: 8 grid_6_8 0 79 Grid S: 7 N: 8 grid_7_8 0 80 Grid S: 8 N: 8 grid_8_8 0 LV2 ZamCompX2 urn:zamaudio:ZamCompX2 Yes 0.1987794 1 0x4 0 Attack att 10 1 Release rel 10 2 Knee kn 1 3 Ratio rat 5 4 Threshold thr -18 5 Makeup mak 6 6 Slew slew 20 7 Stereo Detection stereodet 1 8 Sidechain sidechain 1 LV2 Black Pearl Drumkit http://gareus.org/oss/lv2/avldrums#BlackPearl Yes 1 0x1e0 system:capture_1 PulseAudio JACK Source:front-left system:capture_2 PulseAudio JACK Source:front-right PulseAudio JACK Sink:front-left system:playback_1 PulseAudio JACK Sink:front-right system:playback_2 ZynReverb:output_1 ZamCompX2:Audio Input 1 ZynReverb:output_2 ZamCompX2:Audio Input 2 x42-eq - Parametric Equalizer Stereo:Out Left ZamCompX2:Audio Input 1 MIDI Seq Guitar:events-out AcousticGuitar:events-in MIDI Seq Drums:events-out Black Pearl Drumkit:events-in AcousticGuitar:out-left x42-eq - Parametric Equalizer Stereo:In Left AcousticGuitar:out-left ZynReverb:input_1 AcousticGuitar:out-right x42-eq - Parametric Equalizer Stereo:In Right AcousticGuitar:out-right ZynReverb:input_2 x42-eq - Parametric Equalizer Stereo:Out Right ZamCompX2:Audio Input 2 ZamCompX2:Audio Output 1 system:playback_1 ZamCompX2:Audio Output 2 system:playback_2 Black Pearl Drumkit:Output Left ZamCompX2:Sidechain Input Black Pearl Drumkit:Output Left system:playback_1 Black Pearl Drumkit:Output Right system:playback_2 Black Pearl Drumkit:Output Right ZamCompX2:Sidechain Input Carla-2.1/data/presentation/lac2018/projects/3.carxp000066400000000000000000002241751364475620200221520ustar00rootroot00000000000000 false false true false 200 4000 LV2 MIDI Step Sequencer8x8 http://gareus.org/oss/lv2/stepseq#s8n8 Yes 1 0x1 0 Sync sync 1 1 BPM bpm 120 2 Step Duration (4/4) div 7 3 Swing swing 0 4 Drum Mode drummode 0 5 Midi Channel chn 0 6 MIDI Panic panic 0 9 Note 1 note1 69 10 Note 2 note2 67 11 Note 3 note3 65 12 Note 4 note4 64 13 Note 5 note5 62 14 Note 6 note6 60 15 Note 7 note7 59 16 Note 8 note8 57 17 Grid S: 1 N: 1 grid_1_1 127 18 Grid S: 2 N: 1 grid_2_1 0 19 Grid S: 3 N: 1 grid_3_1 0 20 Grid S: 4 N: 1 grid_4_1 0 21 Grid S: 5 N: 1 grid_5_1 0 22 Grid S: 6 N: 1 grid_6_1 0 23 Grid S: 7 N: 1 grid_7_1 0 24 Grid S: 8 N: 1 grid_8_1 0 25 Grid S: 1 N: 2 grid_1_2 0 26 Grid S: 2 N: 2 grid_2_2 127 27 Grid S: 3 N: 2 grid_3_2 0 28 Grid S: 4 N: 2 grid_4_2 0 29 Grid S: 5 N: 2 grid_5_2 0 30 Grid S: 6 N: 2 grid_6_2 0 31 Grid S: 7 N: 2 grid_7_2 0 32 Grid S: 8 N: 2 grid_8_2 127 33 Grid S: 1 N: 3 grid_1_3 0 34 Grid S: 2 N: 3 grid_2_3 0 35 Grid S: 3 N: 3 grid_3_3 127 36 Grid S: 4 N: 3 grid_4_3 0 37 Grid S: 5 N: 3 grid_5_3 127 38 Grid S: 6 N: 3 grid_6_3 0 39 Grid S: 7 N: 3 grid_7_3 127 40 Grid S: 8 N: 3 grid_8_3 0 41 Grid S: 1 N: 4 grid_1_4 0 42 Grid S: 2 N: 4 grid_2_4 0 43 Grid S: 3 N: 4 grid_3_4 0 44 Grid S: 4 N: 4 grid_4_4 127 45 Grid S: 5 N: 4 grid_5_4 0 46 Grid S: 6 N: 4 grid_6_4 127 47 Grid S: 7 N: 4 grid_7_4 0 48 Grid S: 8 N: 4 grid_8_4 0 49 Grid S: 1 N: 5 grid_1_5 0 50 Grid S: 2 N: 5 grid_2_5 0 51 Grid S: 3 N: 5 grid_3_5 0 52 Grid S: 4 N: 5 grid_4_5 0 53 Grid S: 5 N: 5 grid_5_5 0 54 Grid S: 6 N: 5 grid_6_5 0 55 Grid S: 7 N: 5 grid_7_5 0 56 Grid S: 8 N: 5 grid_8_5 0 57 Grid S: 1 N: 6 grid_1_6 0 58 Grid S: 2 N: 6 grid_2_6 0 59 Grid S: 3 N: 6 grid_3_6 0 60 Grid S: 4 N: 6 grid_4_6 0 61 Grid S: 5 N: 6 grid_5_6 0 62 Grid S: 6 N: 6 grid_6_6 0 63 Grid S: 7 N: 6 grid_7_6 0 64 Grid S: 8 N: 6 grid_8_6 0 65 Grid S: 1 N: 7 grid_1_7 0 66 Grid S: 2 N: 7 grid_2_7 0 67 Grid S: 3 N: 7 grid_3_7 0 68 Grid S: 4 N: 7 grid_4_7 0 69 Grid S: 5 N: 7 grid_5_7 0 70 Grid S: 6 N: 7 grid_6_7 0 71 Grid S: 7 N: 7 grid_7_7 0 72 Grid S: 8 N: 7 grid_8_7 0 73 Grid S: 1 N: 8 grid_1_8 0 74 Grid S: 2 N: 8 grid_2_8 0 75 Grid S: 3 N: 8 grid_3_8 0 76 Grid S: 4 N: 8 grid_4_8 0 77 Grid S: 5 N: 8 grid_5_8 0 78 Grid S: 6 N: 8 grid_6_8 0 79 Grid S: 7 N: 8 grid_7_8 0 80 Grid S: 8 N: 8 grid_8_8 0 LV2 Pianoteq 5 http://pianoteq.com/lv2/Pianoteq5 Yes 1 0x1e5 0 Sustain Pedal lv2_port_1 0 1 Soft Pedal lv2_port_2 0 2 Sostenuto Pedal lv2_port_3 0 3 Harmonic Pedal lv2_port_4 0 4 Pitch Bend lv2_port_5 0.5 5 Volume lv2_port_6 0.727272748947144 6 Dynamics lv2_port_7 0.393939405679703 7 Diapason lv2_port_8 0.333333343267441 8 Temperament lv2_port_9 0 9 Microtonal lv2_port_10 0 10 Octave Stretch. lv2_port_11 0.231088206171989 11 Unison Width lv2_port_12 0.5 12 Direct Sound Duration lv2_port_13 0.5 13 Hard. Piano lv2_port_14 0.150000005960464 14 Hard. Mezzo lv2_port_15 0.400000005960464 15 Hard. Forte lv2_port_16 0.800000011920929 16 Profile 1 lv2_port_17 0.5 17 Profile 2 lv2_port_18 0.5 18 Profile 3 lv2_port_19 0.5 19 Profile 4 lv2_port_20 0.5 20 Profile 5 lv2_port_21 0.5 21 Profile 6 lv2_port_22 0.5 22 Profile 7 lv2_port_23 0.5 23 Profile 8 lv2_port_24 0.5 24 Hammer Noise lv2_port_25 0.28571429848671 25 Strike Point lv2_port_26 0.551161646842957 26 Character lv2_port_27 0.5 27 Pickup Symmetry lv2_port_28 0 28 Pickup Distance lv2_port_29 0.444444477558136 29 Soft Level lv2_port_30 0.300000011920929 30 Impedance lv2_port_31 0.5 31 Cutoff lv2_port_32 0.5 32 Q Factor lv2_port_33 0.5 33 String Length lv2_port_34 0.5 34 Sympa lv2_port_35 0.5 35 Duplex lv2_port_36 0.499999970197678 36 Quadratic Effect lv2_port_37 0.569824278354645 37 Bounce Switch lv2_port_38 0 38 Bounce Delay lv2_port_39 0.458333343267441 39 Bounce Sync lv2_port_40 0 40 MBSyncS lv2_port_41 0.56521737575531 41 MBVelS lv2_port_42 0.5 42 MBAccel lv2_port_43 0.5 43 MBVelL lv2_port_44 0.5 44 MBHuma lv2_port_45 0.5 45 Eff 1 Switch lv2_port_46 1 46 Eff 1 Param 1 lv2_port_47 0.100000001490116 47 Eff 1 Param 2 lv2_port_48 0.22833614051342 48 Eff 1 Param 3 lv2_port_49 0 49 Eff 1 Param 4 lv2_port_50 0.25 50 Eff 1 Param 5 lv2_port_51 1 51 Eff 1 Param 6 lv2_port_52 0 52 Eff 1 Param 7 lv2_port_53 0 53 Eff 1 Param 8 lv2_port_54 0 54 Eff 2 Switch lv2_port_55 0 55 Eff 2 Param 1 lv2_port_56 0 56 Eff 2 Param 2 lv2_port_57 0 57 Eff 2 Param 3 lv2_port_58 0 58 Eff 2 Param 4 lv2_port_59 0 59 Eff 2 Param 5 lv2_port_60 0 60 Eff 2 Param 6 lv2_port_61 0 61 Eff 2 Param 7 lv2_port_62 0 62 Eff 2 Param 8 lv2_port_63 0 63 Eff 3 Switch lv2_port_64 0 64 Eff 3 Param 1 lv2_port_65 0 65 Eff 3 Param 2 lv2_port_66 0 66 Eff 3 Param 3 lv2_port_67 0 67 Eff 3 Param 4 lv2_port_68 0 68 Eff 3 Param 5 lv2_port_69 0 69 Eff 3 Param 6 lv2_port_70 0 70 Eff 3 Param 7 lv2_port_71 0 71 Eff 3 Param 8 lv2_port_72 0 72 Reverb Switch lv2_port_73 1 73 Reverb Duration lv2_port_74 0.273276418447495 74 Reverb Mix lv2_port_75 0.5 75 Room Dimensions lv2_port_76 0.333333343267441 76 Reverb Pre-delay lv2_port_77 0.52955836057663 77 RevEarl lv2_port_78 0.5 78 Reverb Tone lv2_port_79 0.5 79 Reverb Envelope lv2_port_80 1 80 RevRes lv2_port_81 0.5 81 Limiter Switch lv2_port_82 1 82 Limiter Sharp. lv2_port_83 0.5 83 Limiter Thresh. lv2_port_84 0.519999980926514 84 Limiter Gain lv2_port_85 0.833333313465118 85 Damper Noise lv2_port_86 0.499999970197678 86 Damper Position lv2_port_87 0.668858230113983 87 Last Damper lv2_port_88 0.7109375 88 Pedal Noise lv2_port_89 0.5 89 Key Rel. Noise lv2_port_90 0.5 90 Damping Duration lv2_port_91 0.5 91 Lid Position lv2_port_92 1 92 Output Mode lv2_port_93 0.666666686534882 93 Mic Level Comp. lv2_port_94 1 94 Mic Delay Comp. lv2_port_95 0 95 Head X position lv2_port_96 0.534999966621399 96 Head Y position lv2_port_97 0.5 97 Head Z position lv2_port_98 0.371428549289703 98 Head Diameter lv2_port_99 0.200000002980232 99 Head Angle lv2_port_100 0.5 100 Mic 1 Mic Switch lv2_port_101 1 101 Mic 1 X position lv2_port_102 0.574999988079071 102 Mic 1 Y position lv2_port_103 0.604166686534882 103 Mic 1 Z position lv2_port_104 0.428571432828903 104 Mic 1 Azimuth lv2_port_105 0 105 Mic 1 Elevation lv2_port_106 0.488764733076096 106 Mic 1 Level 1 lv2_port_107 0.837499976158142 107 Mic 1 Delay 1 lv2_port_108 0.5 108 Mic 1 Level 2 lv2_port_109 0.59375 109 Mic 1 Delay 2 lv2_port_110 0.6875 110 Mic 1 Level 3 lv2_port_111 0 111 Mic 1 Delay 3 lv2_port_112 0.5 112 Mic 1 Level 4 lv2_port_113 0 113 Mic 1 Delay 4 lv2_port_114 0.5 114 Mic 1 Level 5 lv2_port_115 0 115 Mic 1 Delay 5 lv2_port_116 0.5 116 Mic 2 Mic Switch lv2_port_117 1 117 Mic 2 X position lv2_port_118 0.574999988079071 118 Mic 2 Y position lv2_port_119 0.5625 119 Mic 2 Z position lv2_port_120 0.428571432828903 120 Mic 2 Azimuth lv2_port_121 0.625 121 Mic 2 Elevation lv2_port_122 0.488764733076096 122 Mic 2 Level 1 lv2_port_123 0.59375 123 Mic 2 Delay 1 lv2_port_124 0.75 124 Mic 2 Level 2 lv2_port_125 0.837499976158142 125 Mic 2 Delay 2 lv2_port_126 0.509375035762787 126 Mic 2 Level 3 lv2_port_127 0 127 Mic 2 Delay 3 lv2_port_128 0.5 128 Mic 2 Level 4 lv2_port_129 0 129 Mic 2 Delay 4 lv2_port_130 0.5 130 Mic 2 Level 5 lv2_port_131 0 131 Mic 2 Delay 5 lv2_port_132 0.5 132 Mic 3 Mic Switch lv2_port_133 0 133 Mic 3 X position lv2_port_134 0.596000015735626 134 Mic 3 Y position lv2_port_135 0.429999977350235 135 Mic 3 Z position lv2_port_136 0.262857139110565 136 Mic 3 Azimuth lv2_port_137 0.75 137 Mic 3 Elevation lv2_port_138 0.5 138 Mic 3 Level 1 lv2_port_139 0.512499988079071 139 Mic 3 Delay 1 lv2_port_140 0.5 140 Mic 3 Level 2 lv2_port_141 0.512499988079071 141 Mic 3 Delay 2 lv2_port_142 0.5 142 Mic 3 Level 3 lv2_port_143 0 143 Mic 3 Delay 3 lv2_port_144 0.5 144 Mic 3 Level 4 lv2_port_145 0 145 Mic 3 Delay 4 lv2_port_146 0.5 146 Mic 3 Level 5 lv2_port_147 0 147 Mic 3 Delay 5 lv2_port_148 0.5 148 Mic 4 Mic Switch lv2_port_149 0 149 Mic 4 X position lv2_port_150 0.465000003576279 150 Mic 4 Y position lv2_port_151 0.531666696071625 151 Mic 4 Z position lv2_port_152 0.251428574323654 152 Mic 4 Azimuth lv2_port_153 0.5 153 Mic 4 Elevation lv2_port_154 0.5 154 Mic 4 Level 1 lv2_port_155 0.512499988079071 155 Mic 4 Delay 1 lv2_port_156 0.5 156 Mic 4 Level 2 lv2_port_157 0.512499988079071 157 Mic 4 Delay 2 lv2_port_158 0.5 158 Mic 4 Level 3 lv2_port_159 0 159 Mic 4 Delay 3 lv2_port_160 0.5 160 Mic 4 Level 4 lv2_port_161 0 161 Mic 4 Delay 4 lv2_port_162 0.5 162 Mic 4 Level 5 lv2_port_163 0 163 Mic 4 Delay 5 lv2_port_164 0.5 164 Mic 5 Mic Switch lv2_port_165 0 165 Mic 5 X position lv2_port_166 0.577000021934509 166 Mic 5 Y position lv2_port_167 0.569999992847443 167 Mic 5 Z position lv2_port_168 0.502857148647308 168 Mic 5 Azimuth lv2_port_169 0.5 169 Mic 5 Elevation lv2_port_170 0.5 170 Mic 5 Level 1 lv2_port_171 0.512499988079071 171 Mic 5 Delay 1 lv2_port_172 0.5 172 Mic 5 Level 2 lv2_port_173 0.512499988079071 173 Mic 5 Delay 2 lv2_port_174 0.5 174 Mic 5 Level 3 lv2_port_175 0 175 Mic 5 Delay 3 lv2_port_176 0.5 176 Mic 5 Level 4 lv2_port_177 0 177 Mic 5 Delay 4 lv2_port_178 0.5 178 Mic 5 Level 5 lv2_port_179 0 179 Mic 5 Delay 5 lv2_port_180 0.5 180 Stereo Width lv2_port_181 0.674031317234039 181 Sound Speed lv2_port_182 0.500000059604645 182 Mute lv2_port_183 0 183 Clavinet Low Mic lv2_port_184 1 184 ClvMicH lv2_port_185 1 185 Equalizer Switch lv2_port_186 1 186 HTinNois lv2_port_187 0.5 187 Blooming Energy lv2_port_188 0 188 Blooming Inertia lv2_port_189 0.5 189 Aftertouch lv2_port_190 0 190 Wall distance lv2_port_191 0 191 Unison Balance lv2_port_192 0.5 192 Condition lv2_port_193 0 193 Condition Seed lv2_port_194 0.12341234087944 194 Rattle Pedal lv2_port_195 0 195 Lute Stop Pedal lv2_port_196 0 196 Celeste Pedal lv2_port_197 0 197 Super Sostenuto lv2_port_198 0 http://lv2plug.in/ns/ext/atom#Chunk urn:juce:stateBinary UHJWSxQAAAJYRlRQpBsAAAoAAAAyMDE3LzExLzA0FwAAAFBpYW5vdGVxIDUuMy4wLzIwMTUwNzE1o9QvMCuNhmEarickC02mrGRsbGFjGwAAdGR0TXIGAAARAAAARDQgRGFpbHkgUHJhY3RpY2UAAAAAGgAAAENvcHlyaWdodCAoYykgMjAxNSBNb2RhcnR0hwAAAFRoaXMgcHJlc2V0IG9mZmVycyBhIGNsZWFuIHNvdW5kLCB5b3UgbWF5IGxpa2UgdG8gdXNlIGl0IGZvciB5b3VyIGRhaWx5IHByYWN0aWNlLiBBbHNvIGEgZ29vZCBzdGFydGluZyBwb2ludCBmb3IgcHJlcGFyaW5nIG5ldyBwcmVzZXRzLgAAAACEAAAAEQAAAEQ0IERhaWx5IFByYWN0aWNlAAAAAIsFAABHUlVVAAAABgAAAAEDwE1UcmsAAAV1AP8CDyBQaWV0IERlIFJpZGRlcgCQKil4gCpVBpArJIMxgCsNaJAkKoIHgCQcMpA3LYEJgDdPgmaQPDGBToA8RVaQKyoFPzuBTIA/bFaQQy8qNyCBGIBDUgQ3K0orJYERkD80CCUlcoA/Wz0lTVKQQisIJiKBOoBCSoEskDkhghSAOUqBICYbNJA+MINMLUKBIoAtSoJCkDI9gVeAMjtCkCsyQoA+bIMlkDItghwvPCCAK2kKMi19L09FkDpPCjVKgVWAOmMbkDs+CYA1IoImO0AEkDw4gSuAPGlHkEFBFDI5gSKAMmZYkDhQgk0kSoJXgDhggSaQNz4GP083gEFFgxYkCSiQMEGBcoA3QB6QK0EqgDA2Zz9dfJAwOFKAKwUcMFKBAJAkUIEggCRjbZA8RYFwgDxmB5A/MYIJQVkGgD9yFJAwQoFggEFveTAFfpBCZoE5gEJSLpBDVFIwLXeAQ2k6kERPgR6AME81RGk5kEVGBCYxhBIwLiiAJm+BaZBDVS+ARVuCQjA0YZBEWgyAQ00AkC1BBTA2gR2AMF0ARGxVkEVeEjAdgRaAMGAtRWktkEZbCSo3UIAtNBxGYzQqYFSQR0wNKzGBeIBHLQmQQSCBcIBBWx2QQiqBSIBCWwkrGUyQQ1UIMkaBMYAyYCVDbIF2kEttgQyAS2OCZZAvPQ1KXoEzgEpFWy9pBpBIPAQwOYFugEhpMDA9gTaQJC+BQ4AkJ2eQQ2OBSIBDRYIpkEJVCjBVcoBCZoEEkENFaoAwIYEEkCstEkZFIYBDY4EmRmkCK0U3kChKBUhbggmASGMZkEZCHYAoSoELRjiCPpA0TQA6RwBATzkiNIFZgDpsWjRsRUBsPSIyGJAoRoF7LlBPgChsgSOQPV+BNIA9WwkuZkWQPkULKUWBYYA+YCSQPC6BV4A8VYFkKUdIkDhLHDA2gx+AOGwhkDdZgRqAMGkyN1sukDVQCyxUgSyALFgvNWANkDdGEDA9gU+AN2AIMEookCZPAjhFgS+AOG9XkDkvggQ8LCCAORxJJlWBJ5A/SwiAPGkPkDBQgSuAMEUukEJgEjAJD4A/aWxCbzswSjqQRWgtMBJjgEVsEjBmV5BEViYqRoFYQ1AzgERNIENjHypmgQWQQkoTK0KBHoBCaVCQQzmBNYBDYEaQRE9/gERpRitYTpBFaAYvU4F/gEVsSC82gRmQMloARmeBO4BGbCuQR0w8gDIYgUKQL0qBL4AvXQRHYz2QSFsHMGaBX4BIbA0wWxKQS28bM2hQgEtsgQczW4FSkEhVADBkgQGASGBlMEIokENpEStMgSCAQ2A7K2ZQkCc4BD9FgTeAJz0NP2aBNZBDVgAra4EggENjbpAnSwI/PBWAK1V9P0ceJ2ZOkCZNAj48gTOAPi07kCo4AEJAboAmUhRCPSUqW1SQRWQTLVUALxSBB4BFaUYvbBQtZoF/kCxqBERqgUOARGktLGmBXJAqYQdCZ4ExgEJsISpvM5ArWgJDVoExgCtvE0NmghqQRmEEQV8EK1g5R18agEZyc0FmPStVH0dggVOQMmcJSmoCQWmCD4BBJ0gyQhVKY4QbkDA6gXAzPiWAMACBcJA3K4EcgDcALzMAHZA8U4F/gDwACpA/U4FsQ1IQgD8AgUJDAB6QSEqBEYBIAHqQSzuCHIBLAAOQT1CBVIBPAIJPkFBjCCtcB0piAjdkBFNggVCASgARUAAAUwBjNwACKwCCVZAkZwIwZAhPYgNIVwRUYxJLXwArYAVRXIELgCsAE1QABCQAC1EAJ0sAMTAAEU8AgQ0kQAArQAAwQAAzQAA3QAA8QAA/QABDQABIQABKQABLQABPQABQQABRQABTQABUQAD/LwBQcnNV4RQAACoAAAACAAAAZDQAAAAACAAAAEdyYW5kIEQ0AAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAEAAAAAAAAA3H8iPgMAAAAKAAAAAACoQQAA6EEAABhCAAAgQgAAJEIAACxCAABgQgAAkkIAAJRCAAC2QgoAAABhpkk/CNJOPwnMaT94/Fw/WUNUPzMOYD8dCIA/jz6zP48+sz+PPrM/AAAAAAAAtkIAAAAAAwAAAAEAAAAAAHBCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACgwAAAoEAAAAAAAwAAAAIAAAAAAKhBAADYQgIAAAAAAAAAAAAAAAAAAAADAAAAAgAAAAAAqEEAANhCAgAAAAAAgD8AAIA/AAAAAIAAAAAAAAAA0gQAAAAAgD8DAAAAAQAAAAAAcEIBAAAAAAAAAAAAAAADAAAAaQAAAAAAEEEAACBBAAAwQQAAQEEAAFBBAABgQQAAcEEAAIBBAACIQQAAkEEAAJhBAACgQQAAqEEAALBBAAC4QQAAwEEAAMhBAADQQQAA2EEAAOBBAADoQQAA8EEAAPhBAAAAQgAABEIAAAhCAAAMQgAAEEIAABRCAAAYQgAAHEIAACBCAAAkQgAAKEIAACxCAAAwQgAANEIAADhCAAA8QgAAQEIAAERCAABIQgAATEIAAFBCAABUQgAAWEIAAFxCAABgQgAAZEIAAGhCAABsQgAAcEIAAHRCAAB4QgAAfEIAAIBCAACCQgAAhEIAAIZCAACIQgAAikIAAIxCAACOQgAAkEIAAJJCAACUQgAAlkIAAJhCAACaQgAAnEIAAJ5CAACgQgAAokIAAKRCAACmQgAAqEIAAKpCAACsQgAArkIAALBCAACyQgAAtEIAALZCAAC4QgAAukIAALxCAAC+QgAAwEIAAMJCAADEQgAAxkIAAMhCAADKQgAAzEIAAM5CAADQQgAA0kIAANRCAADWQgAA2EIAANpCAADcQgAA3kIAAOBCAADiQmkAAAAAAADAAACAvwAAQMAAAEDAAABAQAAAAEAAAMBAAACAPwAAgD8AAMBAAABAQAAAgEAAAADAAABAwAAAgEAAAIBAAACgQAAAwEAAAIBAAAAAgAAAgD8AAADAAACAPwAAQMAAAEDAAABAQAAAgEAAAKBAAACgQAAAQMAAAKBAAAAAgAAAAEAAAEDAAACgQAAAoEAAAEBAAACAQAAAAEAAAADAAACAPwAAgEAAAABAAACgQAAAQEAAAEDAAAAAgAAAgEAAAEDAAAAAgAAAgD8AAIC/AABAwAAAoEAAAEDAAAAAwAAAAIAAAACAAACgQAAAQMAAAADAAACAvwAAQMAAAEDAAACgQAAAAMAAAEDAAABAwAAAgEAAAIA/AABAwAAAgEAAAAAAAACAQAAAgL8AAABAAACgQAAAQMAAAIC/AAAAwAAAwEAAAKBAAABAwAAAQMAAAADAAACAPwAAQMAAAEDAAACAvwAAgL8AAMBAAACAQAAAQMAAAAAAAAAAAAAAgD8AAEDAAAAAwAAAwEAAAEDAAADAQAAAQMAAAEDAAABAwAAAAEAAAAAAAwAAAAIAAAAAAKhBAADYQgIAAAAAAIA/AACAPwAAAAAAANxDAAAAAAEAAAAAAAAABwAAAERlZmF1bHQMAAAAAADIQgAASEMAAJZDAADIQwAA+kMAABZEAAAvRAAASEQAAGFEAAB6RACAiUQAAJZEAQAAAAAA3EM8AAAARQAAAAAAAAAAAAAABwAAAERlZmF1bHQDAAAABAAAAAAAwEEAABBCAABAQgAA2EIEAAAAAACgwAAAgL8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AwAAAAIAAAAAAKhBAADYQgIAAAAAAIA/AACAPwAAAAADAAAAAgAAAAAAqEEAANhCAgAAAAAAgD8AAIA/AAAAAAAAAAADAAAAAQAAAAAAcEIBAAAAAAAAAAAAAAAAAIA/AwAAAAEAAAAAAHBCAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAzczMvc3MzD0BAAAAAAAAAAAAAAAAAAC/AAAAPwAAgD8DAAAAAwAAAAAAqEEAAHBCAADYQgMAAAAAAIA/AACAPwAAgD8AAAAAAAAAAAMAAAACAAAAAACoQQAA2EICAAAAAAAAAAAAAAAAAAAAAACAPwMAAAACAAAAAACoQQAA2EICAAAAAACAPwAAgD8AAAAAAAAgQgMAAAAHAAAAAACoQQAAkEIAAKhCAAC0QgAAwEIAAMhCAADYQgcAAAAAAAAAAAAAAAAAQEAAAMBAAAAQQQAAIEEAADBBAAAAAAAAgD8DAAAAAwAAAAAAqEEAAHBCAADYQgMAAAAAAIA/AACAPwAAgD8AAAAAAwAAAAAAAAABAAAAAAAAAAAAAAABAAAAAwAAAAIAAAAAAAAAAACAPwIAAAAAAAAAAACAPwAAAAADAAAAAgAAAAAAAAAAAIA/AgAAAAAAgD8AAIA/AAAAAAMAAAAEAAAAAAAAACaTST7+fj8/AACAPwQAAAAAAAAAAAAAAAAAgD8AAIA/AAAAAAMAAAACAAAAAAAAAAAAgD8CAAAAAAAAAAAAAAAAAAAAzcwsQAMAAAACAAAAAACoQQAA2EICAAAAAACAPwAAgD8AAAAAAACAvwAAAD8DAAAAAgAAAAAAwEEAAMBCAgAAAAAAgD8AAIA/AAAAAAEAAAABAAAAAQAAAAoAAABTbWFsbCBIYWxsCwAAAG1lZGl1bWhhbGwxAAAAAAAAoEEAAIA/ZmZmPwAAAABCYGU9AAAAAAAAAAAAAAAAAACqQwAAgD8AAIA/BQAAAAAAgD8AAIA/AwAAAF0AAAAAAKhBAACwQQAAuEEAAMBBAADIQQAA0EEAANhBAADgQQAA6EEAAPBBAAD4QQAAAEIAAARCAAAIQgAADEIAABBCAAAUQgAAGEIAABxCAAAgQgAAJEIAAChCAAAsQgAAMEIAADRCAAA4QgAAPEIAAEBCAABEQgAASEIAAExCAABQQgAAVEIAAFhCAABcQgAAYEIAAGRCAABoQgAAbEIAAHBCAAB0QgAAeEIAAHxCAACAQgAAgkIAAIRCAACGQgAAiEIAAIpCAACMQgAAjkIAAJBCAACSQgAAlEIAAJZCAACYQgAAmkIAAJxCAACeQgAAoEIAAKJCAACkQgAApkIAAKhCAACqQgAArEIAAK5CAACwQgAAskIAALRCAAC2QgAAuEIAALpCAAC8QgAAvkIAAMBCAADCQgAAxEIAAMZCAADIQgAAykIAAMxCAADOQgAA0EIAANJCAADUQgAA1kIAANhCAADaQgAA3EIAAN5CAADgQgAA4kJdAAAAAACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD9xPYo/heuRP/YonD/sUZg/j8KVP3E9ij+amZk/j8KVP3sUjj+PwpU/mpmZP7gepT/NzIw/CtejP1K4nj+amZk/16OQP9ejkD+4HqU/KVyPP+F6lD89Cpc/exSOP4/ClT9I4Zo/exSuP65HoT8AAIA/KVyPP1K4nj8AAIA/4XqUP1yPoj/sUZg/XI+iPx+Fqz+kcJ0/MzOzP3sUrj+uR6E/SOGaP3E9ij9cj6I/w/WIP+xRmD/NzIw/FK6HPx+Fiz/sUZg/UrieP3sUjj+uR6E/KVyPP5qZmT9cj6I/CtejP2Zmpj+kcJ0/MzOTP4/CtT9SuJ4/mpmZP5qZuT+4HqU/AACgP83MrD+ambk/pHCdP0jhmj/NzKw/PQqXPylcjz/D9ag/PQqXP6RwnT+amZk/cT2qP0jhmj9SuJ4/UrieP0jhmj97FK4/4XqUP/YonD+kcJ0/AAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAwAAAF0AAAAAAKhBAACwQQAAuEEAAMBBAADIQQAA0EEAANhBAADgQQAA6EEAAPBBAAD4QQAAAEIAAARCAAAIQgAADEIAABBCAAAUQgAAGEIAABxCAAAgQgAAJEIAAChCAAAsQgAAMEIAADRCAAA4QgAAPEIAAEBCAABEQgAASEIAAExCAABQQgAAVEIAAFhCAABcQgAAYEIAAGRCAABoQgAAbEIAAHBCAAB0QgAAeEIAAHxCAACAQgAAgkIAAIRCAACGQgAAiEIAAIpCAACMQgAAjkIAAJBCAACSQgAAlEIAAJZCAACYQgAAmkIAAJxCAACeQgAAoEIAAKJCAACkQgAApkIAAKhCAACqQgAArEIAAK5CAACwQgAAskIAALRCAAC2QgAAuEIAALpCAAC8QgAAvkIAAMBCAADCQgAAxEIAAMZCAADIQgAAykIAAMxCAADOQgAA0EIAANJCAADUQgAA1kIAANhCAADaQgAA3EIAAN5CAADgQgAA4kJdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxmuW8SOFIvRdVB71AGWE80EJ4vV/YST2wNkm93jniudhVqr0uuGu9OCETOtdjgLwW24S9RFIFPaiJjzyCl7C67ryqPZLitb218bo92mxJPUMvoT3kFqu7vQhvvQR/oL3X3K292xWdPYeDQz28BZW9MjXGPNl7sb1R4a68jIzyPHT/wT1b5ja7ZmKPuhApuj3cZ7M9IC6aPaW0Er3O34W8jcm2PFJHqDxKNLo9cuRnvbkagD3/Na291GWdPYkdXTw2jls9rlyQvTrpXb1gYKE8fIdGPRFnCj2OWQM9G/zWO8bUsbxXGHs9ARhlvR18wjwzmiS9TzBSvUlvOr33Tk49bNO2Pcm2J70VS6U9PV6dPUUter0+pHg9leXfvB3hl7wlwYw9fkrZOWb3xz1aWSE9lUvOPAMPnL3ammu9bMGSPSgz8Dwlv7O97aNfPUb8jj2w+UC9AAAAAAMAAAAAAIA/AACAPwAAgD8DAAAAAwAAAAAAqEEAAHBCAADYQgMAAAAAAIA/AACAPwAAgD8AAAAAAwAAAAMAAAAAAKhBAABwQgAA2EIDAAAAAACAPwAAgD8AAIA/AAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAgD8AAIA/AACAPwAAAAAAAIA/AACAPwYAAAAAAIA/mpmZPs3MTD/NzMw/mpmZPggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAgD8AAIA/AACAPwAAAAADAAAAAwAAAAAAqEEAAHBCAADYQgMAAAAAAIA/AACAPwAAgD8AAAAAAwAAAAMAAAAAAKhBAABwQgAA2EIDAAAAAACAPwAAgD8AAIA/AAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAgD8AAIA/AACAPwAAAAABAAAAAQAAAAAAcEIDAAAAAQAAAAAAAAABAAAAAAAAAAAAAABOI9g9AwAAABYAAAAAABBBAACoQQAAwEEAAOBBAADoQQAAAEIAAAhCAAAYQgAAJEIAADBCAABAQgAATEIAAGBCAABwQgAAgEIAAIhCAACQQgAAmEIAAKBCAACoQgAAwEIAANhCFgAAAHh0JD/p5Y8/DGGSP3jylD9Ng5Q/TYOUP02DlD9Ng5Q/6oqRP02DlD9Ng5Q/6oqRP1mwjj/qipE/WbCOP1mwjj9ZsI4/54RcP+eEXD9+JEo/2kMtPzGS8j4AAAAAAQAAAAAAAAABAAAAMzMzP2Zmpj8BAAAAAQAAAAEAAABmZmY/zcyMPwEAAAAAAAAAAADwQgAAAAAOAAAAAAAAP83MzD3NzEw+AAAAPwQAAAACAAAAAwAAAAQAAAABAAAAAgAAAAcAAAABAAAAAAAAAA4AAAAQAAAAAAAAAM3MzD0AAIA/AAAAAAAAAL8AAHBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAOAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAADgAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAIA/AABAwQAAAAACAAAAAwAAAAEAAAAFAAAABAAAAAEAAAADAAAAAADAPwAAoD8AAMA/AABhwxxugcAAAAAABQAAAAAAAAAAABDBAADAwgAAwMIAAMDCBQAAAAAAAACPwvU8AAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAEAAAAAQAAAAMAAAAAAMA/AABAPwAAwD8AADRCHG6BwAAAAAAFAAAAAAAQwQAAAAAAAMDCAADAwgAAwMIFAAAACtcjPaabxDoAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAQAAAAAAAAAAwAAAI/C9T89Cle/H4VrPwAAtEIAAAAAAAAAAAUAAAAAAEDBAABAwQAAcMIAAHDCAABwwgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAABAAAAAAAAAADAAAAMzMzv1yPwj6uR2E/AAAAAAAAAAAAAAAABQAAAAAAQMEAAEDBAABwwgAAcMIAAHDCBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAEAAAAAAAAAAMAAAC4HsU/PQpXP65H4T8AAAAAAAAAAAAAAAAFAAAAAABAwQAAQMEAAHDCAABwwgAAcMIFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAMAAAAzMzM/AAAAAGZmpj8AAJBBAAAAAAAAAAAAAAAA LV2 MIDI Chord http://gareus.org/oss/lv2/midifilter#midichord Yes 1 0x1e1 1 Filter Channel channelf 0 2 Scale scale 0 3 prime c1 1 4 3rd c3 1 5 5th c5 1 6 6th c6 0 7 7th c7 1 8 octave c8 1 9 9th c9 0 10 11th c11 0 11 13th c13 0 12 bass _8 0 http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted true INTERNAL Carla-Rack (no midi out) Yes 1 0x3e0 http://kxstudio.sf.net/ns/carla/chunk State <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE CARLA-PROJECT> <CARLA-PROJECT VERSION='2.0'> <EngineSettings> <ForceStereo>false</ForceStereo> <PreferPluginBridges>false</PreferPluginBridges> <PreferUiBridges>true</PreferUiBridges> <UIsAlwaysOnTop>false</UIsAlwaysOnTop> <MaxParameters>200</MaxParameters> <UIBridgesTimeout>4000</UIBridgesTimeout> <LADSPA_PATH>/home/falktx/.ladspa:/usr/lib/ladspa:/usr/local/lib/ladspa</LADSPA_PATH> <DSSI_PATH>/home/falktx/.dssi:/usr/lib/dssi:/usr/local/lib/dssi</DSSI_PATH> <LV2_PATH>/home/falktx/.lv2:/usr/lib/lv2:/usr/local/lib/lv2</LV2_PATH> <VST2_PATH>/home/falktx/.vst:/usr/lib/vst:/usr/local/lib/vst</VST2_PATH> <GIG_PATH>/home/falktx/.sounds/gig:/usr/share/sounds/gig</GIG_PATH> <SF2_PATH>/home/falktx/.sounds/sf2:/home/falktx/Personal/Muzyks/Kits/SoundFonts:/usr/share/sounds/sf2</SF2_PATH> <SFZ_PATH>/home/falktx/.sounds/sfz:/home/falktx/Personal/Muzyks/Kits/SFZ:/usr/share/sounds/sfz</SFZ_PATH> </EngineSettings> <!-- QMidiArp Arp --> <Plugin> <Info> <Type>LV2</Type> <Name>QMidiArp Arp</Name> <URI>https://git.code.sf.net/p/qmidiarp/arp</URI> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1e1</Options> <Parameter> <Index>0</Index> <Name>Attack</Name> <Symbol>ATTACK</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>1</Index> <Name>Release</Name> <Symbol>RELEASE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>2</Index> <Name>Random Tick</Name> <Symbol>RANDOM_TICK</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>3</Index> <Name>Random Length</Name> <Symbol>RANDOM_LEN</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>4</Index> <Name>Random Velocity</Name> <Symbol>RANDOM_VEL</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>5</Index> <Name>Output Channel</Name> <Symbol>CH_OUT</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>6</Index> <Name>Input Channel</Name> <Symbol>CH_IN</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>8</Index> <Name>Restart</Name> <Symbol>ENABLE_RESTARTBYKBD</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>9</Index> <Name>Trigger</Name> <Symbol>ENABLE_TRIGBYKBD</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>10</Index> <Name>Mute Output</Name> <Symbol>MUTE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>11</Index> <Name>Latch mode</Name> <Symbol>LATCH_MODE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>12</Index> <Name>Octave Mode</Name> <Symbol>OCTAVE_MODE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>13</Index> <Name>Low octave limit</Name> <Symbol>OCTAVE_LOW</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>14</Index> <Name>High octave limit</Name> <Symbol>OCTAVE_HIGH</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>15</Index> <Name>Index In 1</Name> <Symbol>INDEX_IN1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>16</Index> <Name>Index In 2</Name> <Symbol>INDEX_IN2</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>17</Index> <Name>Range In 1</Name> <Symbol>RANGE_IN1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>18</Index> <Name>Range In 2</Name> <Symbol>RANGE_IN2</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>19</Index> <Name>Trigger Legato</Name> <Symbol>ENABLE_TRIGLEGATO</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>20</Index> <Name>Repeat Mode</Name> <Symbol>REPEAT_MODE</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>22</Index> <Name>Defer mute</Name> <Symbol>DEFER</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>23</Index> <Name>Pattern Preset</Name> <Symbol>PATTERN_PRESET</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>24</Index> <Name>Transport Mode</Name> <Symbol>TRANSPORT_MODE</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>25</Index> <Name>Internal Tempo</Name> <Symbol>TEMPO</Symbol> <Value>120</Value> </Parameter> <CustomData> <Type>http://lv2plug.in/ns/ext/atom#String</Type> <Key>https://git.code.sf.net/p/qmidiarp#ARPPATTERN</Key> <Value>&gt;0</Value> </CustomData> </Data> </Plugin> <Plugin> <Info> <Type>SFZ</Type> <Name>concert_harp</Name> <Filename>/home/falktx/Personal/Muzyks/Kits/SFZ/Sonatina Symphonic Orchestra/concert_harp.sfz</Filename> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1f0</Options> <CurrentProgramIndex>1</CurrentProgramIndex> <CurrentProgramName>concert_harp</CurrentProgramName> </Data> </Plugin> </CARLA-PROJECT> http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted true INTERNAL arp xylo + 3d delay Yes 1 0x3e0 http://kxstudio.sf.net/ns/carla/chunk State <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE CARLA-PROJECT> <CARLA-PROJECT VERSION='2.0'> <EngineSettings> <ForceStereo>false</ForceStereo> <PreferPluginBridges>false</PreferPluginBridges> <PreferUiBridges>true</PreferUiBridges> <UIsAlwaysOnTop>false</UIsAlwaysOnTop> <MaxParameters>200</MaxParameters> <UIBridgesTimeout>4000</UIBridgesTimeout> <LADSPA_PATH>/home/falktx/.ladspa:/usr/lib/ladspa:/usr/local/lib/ladspa</LADSPA_PATH> <DSSI_PATH>/home/falktx/.dssi:/usr/lib/dssi:/usr/local/lib/dssi</DSSI_PATH> <LV2_PATH>/home/falktx/.lv2:/usr/lib/lv2:/usr/local/lib/lv2</LV2_PATH> <VST2_PATH>/home/falktx/.vst:/usr/lib/vst:/usr/local/lib/vst</VST2_PATH> <GIG_PATH>/home/falktx/.sounds/gig:/usr/share/sounds/gig</GIG_PATH> <SF2_PATH>/home/falktx/.sounds/sf2:/home/falktx/Personal/Muzyks/Kits/SoundFonts:/usr/share/sounds/sf2</SF2_PATH> <SFZ_PATH>/home/falktx/.sounds/sfz:/home/falktx/Personal/Muzyks/Kits/SFZ:/usr/share/sounds/sfz</SFZ_PATH> </EngineSettings> <!-- QMidiArp Arp --> <Plugin> <Info> <Type>LV2</Type> <Name>QMidiArp Arp</Name> <URI>https://git.code.sf.net/p/qmidiarp/arp</URI> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1e1</Options> <Parameter> <Index>0</Index> <Name>Attack</Name> <Symbol>ATTACK</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>1</Index> <Name>Release</Name> <Symbol>RELEASE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>2</Index> <Name>Random Tick</Name> <Symbol>RANDOM_TICK</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>3</Index> <Name>Random Length</Name> <Symbol>RANDOM_LEN</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>4</Index> <Name>Random Velocity</Name> <Symbol>RANDOM_VEL</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>5</Index> <Name>Output Channel</Name> <Symbol>CH_OUT</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>6</Index> <Name>Input Channel</Name> <Symbol>CH_IN</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>8</Index> <Name>Restart</Name> <Symbol>ENABLE_RESTARTBYKBD</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>9</Index> <Name>Trigger</Name> <Symbol>ENABLE_TRIGBYKBD</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>10</Index> <Name>Mute Output</Name> <Symbol>MUTE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>11</Index> <Name>Latch mode</Name> <Symbol>LATCH_MODE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>12</Index> <Name>Octave Mode</Name> <Symbol>OCTAVE_MODE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>13</Index> <Name>Low octave limit</Name> <Symbol>OCTAVE_LOW</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>14</Index> <Name>High octave limit</Name> <Symbol>OCTAVE_HIGH</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>15</Index> <Name>Index In 1</Name> <Symbol>INDEX_IN1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>16</Index> <Name>Index In 2</Name> <Symbol>INDEX_IN2</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>17</Index> <Name>Range In 1</Name> <Symbol>RANGE_IN1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>18</Index> <Name>Range In 2</Name> <Symbol>RANGE_IN2</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>19</Index> <Name>Trigger Legato</Name> <Symbol>ENABLE_TRIGLEGATO</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>20</Index> <Name>Repeat Mode</Name> <Symbol>REPEAT_MODE</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>22</Index> <Name>Defer mute</Name> <Symbol>DEFER</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>23</Index> <Name>Pattern Preset</Name> <Symbol>PATTERN_PRESET</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>24</Index> <Name>Transport Mode</Name> <Symbol>TRANSPORT_MODE</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>25</Index> <Name>Internal Tempo</Name> <Symbol>TEMPO</Symbol> <Value>120</Value> </Parameter> <CustomData> <Type>http://lv2plug.in/ns/ext/atom#String</Type> <Key>https://git.code.sf.net/p/qmidiarp#ARPPATTERN</Key> <Value>0</Value> </CustomData> </Data> </Plugin> <Plugin> <Info> <Type>SFZ</Type> <Name>percussion_-_xylophone</Name> <Filename>/home/falktx/Personal/Muzyks/Kits/SFZ/Sonatina Symphonic Orchestra/percussion_-_xylophone.sfz</Filename> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1f0</Options> <CurrentProgramIndex>1</CurrentProgramIndex> <CurrentProgramName>percussion_-_xylophone</CurrentProgramName> </Data> </Plugin> <!-- 3D Triple Delay (Stereo) --> <Plugin> <Info> <Type>LV2</Type> <Name>3D Triple Delay (Stereo)</Name> <URI>http://harrisonconsoles.com/lv2/har_delay/stereo</URI> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x0</Options> <Parameter> <Index>0</Index> <Name>Wet Mix</Name> <Symbol>mix</Symbol> <Value>100</Value> </Parameter> <Parameter> <Index>1</Index> <Name>Output Trim</Name> <Symbol>out_trim</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>2</Index> <Name>Input High Cut</Name> <Symbol>hicut</Symbol> <Value>18000</Value> </Parameter> <Parameter> <Index>3</Index> <Name>Input Low Cut</Name> <Symbol>locut</Symbol> <Value>100</Value> </Parameter> <Parameter> <Index>4</Index> <Name>Left Input</Name> <Symbol>inputlev_l</Symbol> <Value>-2.79999995231628</Value> </Parameter> <Parameter> <Index>5</Index> <Name>Left Output</Name> <Symbol>level_l</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>6</Index> <Name>Left Pan</Name> <Symbol>pan_l</Symbol> <Value>-90</Value> </Parameter> <Parameter> <Index>7</Index> <Name>Left Delay (16ths)</Name> <Symbol>delay_16_l</Symbol> <Value>2</Value> </Parameter> <Parameter> <Index>8</Index> <Name>Left Delay (fine)</Name> <Symbol>delay_fine_l</Symbol> <Value>11</Value> </Parameter> <Parameter> <Index>9</Index> <Name>Center Input</Name> <Symbol>inputlev_c</Symbol> <Value>-70</Value> </Parameter> <Parameter> <Index>10</Index> <Name>Center Output</Name> <Symbol>level_c</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>11</Index> <Name>Center Pan</Name> <Symbol>pan_c</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>12</Index> <Name>Center Delay (16ths)</Name> <Symbol>delay_16_c</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>13</Index> <Name>Center Delay (fine)</Name> <Symbol>delay_fine_c</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>14</Index> <Name>Right Input</Name> <Symbol>inputlev_r</Symbol> <Value>-70</Value> </Parameter> <Parameter> <Index>15</Index> <Name>Right Output</Name> <Symbol>level_r</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>16</Index> <Name>Right Pan</Name> <Symbol>pan_r</Symbol> <Value>90</Value> </Parameter> <Parameter> <Index>17</Index> <Name>Right Delay (16ths)</Name> <Symbol>delay_16_r</Symbol> <Value>2</Value> </Parameter> <Parameter> <Index>18</Index> <Name>Right Delay (fine)</Name> <Symbol>delay_fine_r</Symbol> <Value>7</Value> </Parameter> <Parameter> <Index>19</Index> <Name>Linear Feedback</Name> <Symbol>linear_feedback</Symbol> <Value>-17.2999992370605</Value> </Parameter> <Parameter> <Index>20</Index> <Name>Linear Damping</Name> <Symbol>linear_damping</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>21</Index> <Name>Feedback: LR-C-LR</Name> <Symbol>feedback_lrc</Symbol> <Value>-0.0399999991059303</Value> </Parameter> <Parameter> <Index>22</Index> <Name>Feedback: L-R</Name> <Symbol>feedback_lr</Symbol> <Value>5</Value> </Parameter> <Parameter> <Index>23</Index> <Name>Feedback Override</Name> <Symbol>feedback_all</Symbol> <Value>0.899999976158142</Value> </Parameter> <Parameter> <Index>24</Index> <Name>Modulation</Name> <Symbol>modulation</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>25</Index> <Name>BPM (User)</Name> <Symbol>bpm</Symbol> <Value>59.4000015258789</Value> </Parameter> <Parameter> <Index>26</Index> <Name>BPM Sync</Name> <Symbol>bpm_sync</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>27</Index> <Name>Snap</Name> <Symbol>snap</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>31</Index> <Name>Oversample</Name> <Symbol>oversample</Symbol> <Value>1</Value> </Parameter> </Data> </Plugin> </CARLA-PROJECT> http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted true LV2 MIDI Strum http://gareus.org/oss/lv2/midifilter#midistrum Yes 1 0x1e1 1 BPM source bpmsrc 1 2 BPM bpm 120 3 Strum Direction mode 2 4 Note Collect Timeout [ms] collect 15 5 Strum Duration in Beats duration 1.39999997615814 6 Strum Acceleration adjspeed 0 7 Velocity Change adjvelocity 0 8 Randomize Acceleration randspeed 0 9 Randomize Velocity randvelocity 0 SFZ AcousticGuitar /home/falktx/Personal/Muzyks/Kits/SFZ/AcousticGuitarFREE Samples/AcousticGuitar.sfz Yes 0.3500588 1 0x1f0 1 AcousticGuitar system:capture_1 PulseAudio JACK Source:front-left system:capture_2 PulseAudio JACK Source:front-right Carla:audio-out1 system:playback_1 Carla:audio-out2 system:playback_2 Carla-2.1/data/presentation/lac2018/projects/3_2.carxp000066400000000000000000003151241364475620200223660ustar00rootroot00000000000000 false false true false 200 4000 INTERNAL Carla-Rack Yes 1 0x3e0 http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted false http://kxstudio.sf.net/ns/carla/chunk State <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE CARLA-PROJECT> <CARLA-PROJECT VERSION='2.0'> <EngineSettings> <ForceStereo>false</ForceStereo> <PreferPluginBridges>false</PreferPluginBridges> <PreferUiBridges>true</PreferUiBridges> <UIsAlwaysOnTop>false</UIsAlwaysOnTop> <MaxParameters>200</MaxParameters> <UIBridgesTimeout>4000</UIBridgesTimeout> <LADSPA_PATH>/home/falktx/.ladspa:/usr/lib/ladspa:/usr/local/lib/ladspa</LADSPA_PATH> <DSSI_PATH>/home/falktx/.dssi:/usr/lib/dssi:/usr/local/lib/dssi</DSSI_PATH> <LV2_PATH>/home/falktx/.lv2:/usr/lib/lv2:/usr/local/lib/lv2</LV2_PATH> <VST2_PATH>/home/falktx/.vst:/home/falktx/.wineflstudio/drive_c/Program Files (x86)/VstPlugins/:/usr/lib/vst:/usr/local/lib/vst</VST2_PATH> <GIG_PATH>/home/falktx/.sounds/gig:/usr/share/sounds/gig</GIG_PATH> <SF2_PATH>/home/falktx/.sounds/sf2:/home/falktx/Personal/Muzyks/Kits/SoundFonts:/usr/share/sounds/sf2</SF2_PATH> <SFZ_PATH>/home/falktx/.sounds/sfz:/home/falktx/Personal/Muzyks/Kits/SFZ:/usr/share/sounds/sfz</SFZ_PATH> </EngineSettings> <!-- MIDI Step Sequencer8x8 --> <Plugin> <Info> <Type>LV2</Type> <Name>MIDI Step Sequencer8x8</Name> <URI>http://gareus.org/oss/lv2/stepseq#s8n8</URI> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1</Options> <Parameter> <Index>0</Index> <Name>Sync</Name> <Symbol>sync</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>1</Index> <Name>BPM</Name> <Symbol>bpm</Symbol> <Value>120</Value> </Parameter> <Parameter> <Index>2</Index> <Name>Step Duration (4/4)</Name> <Symbol>div</Symbol> <Value>7</Value> </Parameter> <Parameter> <Index>3</Index> <Name>Swing</Name> <Symbol>swing</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>4</Index> <Name>Drum Mode</Name> <Symbol>drummode</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>5</Index> <Name>Midi Channel</Name> <Symbol>chn</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>6</Index> <Name>MIDI Panic</Name> <Symbol>panic</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>9</Index> <Name>Note 1</Name> <Symbol>note1</Symbol> <Value>69</Value> </Parameter> <Parameter> <Index>10</Index> <Name>Note 2</Name> <Symbol>note2</Symbol> <Value>67</Value> </Parameter> <Parameter> <Index>11</Index> <Name>Note 3</Name> <Symbol>note3</Symbol> <Value>65</Value> </Parameter> <Parameter> <Index>12</Index> <Name>Note 4</Name> <Symbol>note4</Symbol> <Value>64</Value> </Parameter> <Parameter> <Index>13</Index> <Name>Note 5</Name> <Symbol>note5</Symbol> <Value>62</Value> </Parameter> <Parameter> <Index>14</Index> <Name>Note 6</Name> <Symbol>note6</Symbol> <Value>60</Value> </Parameter> <Parameter> <Index>15</Index> <Name>Note 7</Name> <Symbol>note7</Symbol> <Value>59</Value> </Parameter> <Parameter> <Index>16</Index> <Name>Note 8</Name> <Symbol>note8</Symbol> <Value>57</Value> </Parameter> <Parameter> <Index>17</Index> <Name>Grid S: 1 N: 1</Name> <Symbol>grid_1_1</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>18</Index> <Name>Grid S: 2 N: 1</Name> <Symbol>grid_2_1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>19</Index> <Name>Grid S: 3 N: 1</Name> <Symbol>grid_3_1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>20</Index> <Name>Grid S: 4 N: 1</Name> <Symbol>grid_4_1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>21</Index> <Name>Grid S: 5 N: 1</Name> <Symbol>grid_5_1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>22</Index> <Name>Grid S: 6 N: 1</Name> <Symbol>grid_6_1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>23</Index> <Name>Grid S: 7 N: 1</Name> <Symbol>grid_7_1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>24</Index> <Name>Grid S: 8 N: 1</Name> <Symbol>grid_8_1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>25</Index> <Name>Grid S: 1 N: 2</Name> <Symbol>grid_1_2</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>26</Index> <Name>Grid S: 2 N: 2</Name> <Symbol>grid_2_2</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>27</Index> <Name>Grid S: 3 N: 2</Name> <Symbol>grid_3_2</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>28</Index> <Name>Grid S: 4 N: 2</Name> <Symbol>grid_4_2</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>29</Index> <Name>Grid S: 5 N: 2</Name> <Symbol>grid_5_2</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>30</Index> <Name>Grid S: 6 N: 2</Name> <Symbol>grid_6_2</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>31</Index> <Name>Grid S: 7 N: 2</Name> <Symbol>grid_7_2</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>32</Index> <Name>Grid S: 8 N: 2</Name> <Symbol>grid_8_2</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>33</Index> <Name>Grid S: 1 N: 3</Name> <Symbol>grid_1_3</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>34</Index> <Name>Grid S: 2 N: 3</Name> <Symbol>grid_2_3</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>35</Index> <Name>Grid S: 3 N: 3</Name> <Symbol>grid_3_3</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>36</Index> <Name>Grid S: 4 N: 3</Name> <Symbol>grid_4_3</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>37</Index> <Name>Grid S: 5 N: 3</Name> <Symbol>grid_5_3</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>38</Index> <Name>Grid S: 6 N: 3</Name> <Symbol>grid_6_3</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>39</Index> <Name>Grid S: 7 N: 3</Name> <Symbol>grid_7_3</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>40</Index> <Name>Grid S: 8 N: 3</Name> <Symbol>grid_8_3</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>41</Index> <Name>Grid S: 1 N: 4</Name> <Symbol>grid_1_4</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>42</Index> <Name>Grid S: 2 N: 4</Name> <Symbol>grid_2_4</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>43</Index> <Name>Grid S: 3 N: 4</Name> <Symbol>grid_3_4</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>44</Index> <Name>Grid S: 4 N: 4</Name> <Symbol>grid_4_4</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>45</Index> <Name>Grid S: 5 N: 4</Name> <Symbol>grid_5_4</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>46</Index> <Name>Grid S: 6 N: 4</Name> <Symbol>grid_6_4</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>47</Index> <Name>Grid S: 7 N: 4</Name> <Symbol>grid_7_4</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>48</Index> <Name>Grid S: 8 N: 4</Name> <Symbol>grid_8_4</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>49</Index> <Name>Grid S: 1 N: 5</Name> <Symbol>grid_1_5</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>50</Index> <Name>Grid S: 2 N: 5</Name> <Symbol>grid_2_5</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>51</Index> <Name>Grid S: 3 N: 5</Name> <Symbol>grid_3_5</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>52</Index> <Name>Grid S: 4 N: 5</Name> <Symbol>grid_4_5</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>53</Index> <Name>Grid S: 5 N: 5</Name> <Symbol>grid_5_5</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>54</Index> <Name>Grid S: 6 N: 5</Name> <Symbol>grid_6_5</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>55</Index> <Name>Grid S: 7 N: 5</Name> <Symbol>grid_7_5</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>56</Index> <Name>Grid S: 8 N: 5</Name> <Symbol>grid_8_5</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>57</Index> <Name>Grid S: 1 N: 6</Name> <Symbol>grid_1_6</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>58</Index> <Name>Grid S: 2 N: 6</Name> <Symbol>grid_2_6</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>59</Index> <Name>Grid S: 3 N: 6</Name> <Symbol>grid_3_6</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>60</Index> <Name>Grid S: 4 N: 6</Name> <Symbol>grid_4_6</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>61</Index> <Name>Grid S: 5 N: 6</Name> <Symbol>grid_5_6</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>62</Index> <Name>Grid S: 6 N: 6</Name> <Symbol>grid_6_6</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>63</Index> <Name>Grid S: 7 N: 6</Name> <Symbol>grid_7_6</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>64</Index> <Name>Grid S: 8 N: 6</Name> <Symbol>grid_8_6</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>65</Index> <Name>Grid S: 1 N: 7</Name> <Symbol>grid_1_7</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>66</Index> <Name>Grid S: 2 N: 7</Name> <Symbol>grid_2_7</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>67</Index> <Name>Grid S: 3 N: 7</Name> <Symbol>grid_3_7</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>68</Index> <Name>Grid S: 4 N: 7</Name> <Symbol>grid_4_7</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>69</Index> <Name>Grid S: 5 N: 7</Name> <Symbol>grid_5_7</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>70</Index> <Name>Grid S: 6 N: 7</Name> <Symbol>grid_6_7</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>71</Index> <Name>Grid S: 7 N: 7</Name> <Symbol>grid_7_7</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>72</Index> <Name>Grid S: 8 N: 7</Name> <Symbol>grid_8_7</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>73</Index> <Name>Grid S: 1 N: 8</Name> <Symbol>grid_1_8</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>74</Index> <Name>Grid S: 2 N: 8</Name> <Symbol>grid_2_8</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>75</Index> <Name>Grid S: 3 N: 8</Name> <Symbol>grid_3_8</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>76</Index> <Name>Grid S: 4 N: 8</Name> <Symbol>grid_4_8</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>77</Index> <Name>Grid S: 5 N: 8</Name> <Symbol>grid_5_8</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>78</Index> <Name>Grid S: 6 N: 8</Name> <Symbol>grid_6_8</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>79</Index> <Name>Grid S: 7 N: 8</Name> <Symbol>grid_7_8</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>80</Index> <Name>Grid S: 8 N: 8</Name> <Symbol>grid_8_8</Symbol> <Value>0</Value> </Parameter> </Data> </Plugin> <!-- Pianoteq 5 --> <Plugin> <Info> <Type>LV2</Type> <Name>Pianoteq 5</Name> <URI>http://pianoteq.com/lv2/Pianoteq5</URI> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1e5</Options> <Parameter> <Index>0</Index> <Name>Sustain Pedal</Name> <Symbol>lv2_port_1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>1</Index> <Name>Soft Pedal</Name> <Symbol>lv2_port_2</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>2</Index> <Name>Sostenuto Pedal</Name> <Symbol>lv2_port_3</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>3</Index> <Name>Harmonic Pedal</Name> <Symbol>lv2_port_4</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>4</Index> <Name>Pitch Bend</Name> <Symbol>lv2_port_5</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>5</Index> <Name>Volume</Name> <Symbol>lv2_port_6</Symbol> <Value>0.727272748947144</Value> </Parameter> <Parameter> <Index>6</Index> <Name>Dynamics</Name> <Symbol>lv2_port_7</Symbol> <Value>0.393939405679703</Value> </Parameter> <Parameter> <Index>7</Index> <Name>Diapason</Name> <Symbol>lv2_port_8</Symbol> <Value>0.333333343267441</Value> </Parameter> <Parameter> <Index>8</Index> <Name>Temperament</Name> <Symbol>lv2_port_9</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>9</Index> <Name>Microtonal</Name> <Symbol>lv2_port_10</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>10</Index> <Name>Octave Stretch.</Name> <Symbol>lv2_port_11</Symbol> <Value>0.231088206171989</Value> </Parameter> <Parameter> <Index>11</Index> <Name>Unison Width</Name> <Symbol>lv2_port_12</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>12</Index> <Name>Direct Sound Duration</Name> <Symbol>lv2_port_13</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>13</Index> <Name>Hard. Piano</Name> <Symbol>lv2_port_14</Symbol> <Value>0.150000005960464</Value> </Parameter> <Parameter> <Index>14</Index> <Name>Hard. Mezzo</Name> <Symbol>lv2_port_15</Symbol> <Value>0.400000005960464</Value> </Parameter> <Parameter> <Index>15</Index> <Name>Hard. Forte</Name> <Symbol>lv2_port_16</Symbol> <Value>0.800000011920929</Value> </Parameter> <Parameter> <Index>16</Index> <Name>Profile 1</Name> <Symbol>lv2_port_17</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>17</Index> <Name>Profile 2</Name> <Symbol>lv2_port_18</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>18</Index> <Name>Profile 3</Name> <Symbol>lv2_port_19</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>19</Index> <Name>Profile 4</Name> <Symbol>lv2_port_20</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>20</Index> <Name>Profile 5</Name> <Symbol>lv2_port_21</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>21</Index> <Name>Profile 6</Name> <Symbol>lv2_port_22</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>22</Index> <Name>Profile 7</Name> <Symbol>lv2_port_23</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>23</Index> <Name>Profile 8</Name> <Symbol>lv2_port_24</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>24</Index> <Name>Hammer Noise</Name> <Symbol>lv2_port_25</Symbol> <Value>0.28571429848671</Value> </Parameter> <Parameter> <Index>25</Index> <Name>Strike Point</Name> <Symbol>lv2_port_26</Symbol> <Value>0.551161646842957</Value> </Parameter> <Parameter> <Index>26</Index> <Name>Character</Name> <Symbol>lv2_port_27</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>27</Index> <Name>Pickup Symmetry</Name> <Symbol>lv2_port_28</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>28</Index> <Name>Pickup Distance</Name> <Symbol>lv2_port_29</Symbol> <Value>0.444444477558136</Value> </Parameter> <Parameter> <Index>29</Index> <Name>Soft Level</Name> <Symbol>lv2_port_30</Symbol> <Value>0.300000011920929</Value> </Parameter> <Parameter> <Index>30</Index> <Name>Impedance</Name> <Symbol>lv2_port_31</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>31</Index> <Name>Cutoff</Name> <Symbol>lv2_port_32</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>32</Index> <Name>Q Factor</Name> <Symbol>lv2_port_33</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>33</Index> <Name>String Length</Name> <Symbol>lv2_port_34</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>34</Index> <Name>Sympa</Name> <Symbol>lv2_port_35</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>35</Index> <Name>Duplex</Name> <Symbol>lv2_port_36</Symbol> <Value>0.499999970197678</Value> </Parameter> <Parameter> <Index>36</Index> <Name>Quadratic Effect</Name> <Symbol>lv2_port_37</Symbol> <Value>0.569824278354645</Value> </Parameter> <Parameter> <Index>37</Index> <Name>Bounce Switch</Name> <Symbol>lv2_port_38</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>38</Index> <Name>Bounce Delay</Name> <Symbol>lv2_port_39</Symbol> <Value>0.458333343267441</Value> </Parameter> <Parameter> <Index>39</Index> <Name>Bounce Sync</Name> <Symbol>lv2_port_40</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>40</Index> <Name>MBSyncS</Name> <Symbol>lv2_port_41</Symbol> <Value>0.56521737575531</Value> </Parameter> <Parameter> <Index>41</Index> <Name>MBVelS</Name> <Symbol>lv2_port_42</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>42</Index> <Name>MBAccel</Name> <Symbol>lv2_port_43</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>43</Index> <Name>MBVelL</Name> <Symbol>lv2_port_44</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>44</Index> <Name>MBHuma</Name> <Symbol>lv2_port_45</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>45</Index> <Name>Eff 1 Switch</Name> <Symbol>lv2_port_46</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>46</Index> <Name>Eff 1 Param 1</Name> <Symbol>lv2_port_47</Symbol> <Value>0.100000001490116</Value> </Parameter> <Parameter> <Index>47</Index> <Name>Eff 1 Param 2</Name> <Symbol>lv2_port_48</Symbol> <Value>0.22833614051342</Value> </Parameter> <Parameter> <Index>48</Index> <Name>Eff 1 Param 3</Name> <Symbol>lv2_port_49</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>49</Index> <Name>Eff 1 Param 4</Name> <Symbol>lv2_port_50</Symbol> <Value>0.25</Value> </Parameter> <Parameter> <Index>50</Index> <Name>Eff 1 Param 5</Name> <Symbol>lv2_port_51</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>51</Index> <Name>Eff 1 Param 6</Name> <Symbol>lv2_port_52</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>52</Index> <Name>Eff 1 Param 7</Name> <Symbol>lv2_port_53</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>53</Index> <Name>Eff 1 Param 8</Name> <Symbol>lv2_port_54</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>54</Index> <Name>Eff 2 Switch</Name> <Symbol>lv2_port_55</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>55</Index> <Name>Eff 2 Param 1</Name> <Symbol>lv2_port_56</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>56</Index> <Name>Eff 2 Param 2</Name> <Symbol>lv2_port_57</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>57</Index> <Name>Eff 2 Param 3</Name> <Symbol>lv2_port_58</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>58</Index> <Name>Eff 2 Param 4</Name> <Symbol>lv2_port_59</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>59</Index> <Name>Eff 2 Param 5</Name> <Symbol>lv2_port_60</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>60</Index> <Name>Eff 2 Param 6</Name> <Symbol>lv2_port_61</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>61</Index> <Name>Eff 2 Param 7</Name> <Symbol>lv2_port_62</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>62</Index> <Name>Eff 2 Param 8</Name> <Symbol>lv2_port_63</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>63</Index> <Name>Eff 3 Switch</Name> <Symbol>lv2_port_64</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>64</Index> <Name>Eff 3 Param 1</Name> <Symbol>lv2_port_65</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>65</Index> <Name>Eff 3 Param 2</Name> <Symbol>lv2_port_66</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>66</Index> <Name>Eff 3 Param 3</Name> <Symbol>lv2_port_67</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>67</Index> <Name>Eff 3 Param 4</Name> <Symbol>lv2_port_68</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>68</Index> <Name>Eff 3 Param 5</Name> <Symbol>lv2_port_69</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>69</Index> <Name>Eff 3 Param 6</Name> <Symbol>lv2_port_70</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>70</Index> <Name>Eff 3 Param 7</Name> <Symbol>lv2_port_71</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>71</Index> <Name>Eff 3 Param 8</Name> <Symbol>lv2_port_72</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>72</Index> <Name>Reverb Switch</Name> <Symbol>lv2_port_73</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>73</Index> <Name>Reverb Duration</Name> <Symbol>lv2_port_74</Symbol> <Value>0.273276418447495</Value> </Parameter> <Parameter> <Index>74</Index> <Name>Reverb Mix</Name> <Symbol>lv2_port_75</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>75</Index> <Name>Room Dimensions</Name> <Symbol>lv2_port_76</Symbol> <Value>0.333333343267441</Value> </Parameter> <Parameter> <Index>76</Index> <Name>Reverb Pre-delay</Name> <Symbol>lv2_port_77</Symbol> <Value>0.52955836057663</Value> </Parameter> <Parameter> <Index>77</Index> <Name>RevEarl</Name> <Symbol>lv2_port_78</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>78</Index> <Name>Reverb Tone</Name> <Symbol>lv2_port_79</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>79</Index> <Name>Reverb Envelope</Name> <Symbol>lv2_port_80</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>80</Index> <Name>RevRes</Name> <Symbol>lv2_port_81</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>81</Index> <Name>Limiter Switch</Name> <Symbol>lv2_port_82</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>82</Index> <Name>Limiter Sharp.</Name> <Symbol>lv2_port_83</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>83</Index> <Name>Limiter Thresh.</Name> <Symbol>lv2_port_84</Symbol> <Value>0.519999980926514</Value> </Parameter> <Parameter> <Index>84</Index> <Name>Limiter Gain</Name> <Symbol>lv2_port_85</Symbol> <Value>0.833333313465118</Value> </Parameter> <Parameter> <Index>85</Index> <Name>Damper Noise</Name> <Symbol>lv2_port_86</Symbol> <Value>0.499999970197678</Value> </Parameter> <Parameter> <Index>86</Index> <Name>Damper Position</Name> <Symbol>lv2_port_87</Symbol> <Value>0.668858230113983</Value> </Parameter> <Parameter> <Index>87</Index> <Name>Last Damper</Name> <Symbol>lv2_port_88</Symbol> <Value>0.7109375</Value> </Parameter> <Parameter> <Index>88</Index> <Name>Pedal Noise</Name> <Symbol>lv2_port_89</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>89</Index> <Name>Key Rel. Noise</Name> <Symbol>lv2_port_90</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>90</Index> <Name>Damping Duration</Name> <Symbol>lv2_port_91</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>91</Index> <Name>Lid Position</Name> <Symbol>lv2_port_92</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>92</Index> <Name>Output Mode</Name> <Symbol>lv2_port_93</Symbol> <Value>0.666666686534882</Value> </Parameter> <Parameter> <Index>93</Index> <Name>Mic Level Comp.</Name> <Symbol>lv2_port_94</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>94</Index> <Name>Mic Delay Comp.</Name> <Symbol>lv2_port_95</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>95</Index> <Name>Head X position</Name> <Symbol>lv2_port_96</Symbol> <Value>0.534999966621399</Value> </Parameter> <Parameter> <Index>96</Index> <Name>Head Y position</Name> <Symbol>lv2_port_97</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>97</Index> <Name>Head Z position</Name> <Symbol>lv2_port_98</Symbol> <Value>0.371428549289703</Value> </Parameter> <Parameter> <Index>98</Index> <Name>Head Diameter</Name> <Symbol>lv2_port_99</Symbol> <Value>0.200000002980232</Value> </Parameter> <Parameter> <Index>99</Index> <Name>Head Angle</Name> <Symbol>lv2_port_100</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>100</Index> <Name>Mic 1 Mic Switch</Name> <Symbol>lv2_port_101</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>101</Index> <Name>Mic 1 X position</Name> <Symbol>lv2_port_102</Symbol> <Value>0.574999988079071</Value> </Parameter> <Parameter> <Index>102</Index> <Name>Mic 1 Y position</Name> <Symbol>lv2_port_103</Symbol> <Value>0.604166686534882</Value> </Parameter> <Parameter> <Index>103</Index> <Name>Mic 1 Z position</Name> <Symbol>lv2_port_104</Symbol> <Value>0.428571432828903</Value> </Parameter> <Parameter> <Index>104</Index> <Name>Mic 1 Azimuth</Name> <Symbol>lv2_port_105</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>105</Index> <Name>Mic 1 Elevation</Name> <Symbol>lv2_port_106</Symbol> <Value>0.488764733076096</Value> </Parameter> <Parameter> <Index>106</Index> <Name>Mic 1 Level 1</Name> <Symbol>lv2_port_107</Symbol> <Value>0.837499976158142</Value> </Parameter> <Parameter> <Index>107</Index> <Name>Mic 1 Delay 1</Name> <Symbol>lv2_port_108</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>108</Index> <Name>Mic 1 Level 2</Name> <Symbol>lv2_port_109</Symbol> <Value>0.59375</Value> </Parameter> <Parameter> <Index>109</Index> <Name>Mic 1 Delay 2</Name> <Symbol>lv2_port_110</Symbol> <Value>0.6875</Value> </Parameter> <Parameter> <Index>110</Index> <Name>Mic 1 Level 3</Name> <Symbol>lv2_port_111</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>111</Index> <Name>Mic 1 Delay 3</Name> <Symbol>lv2_port_112</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>112</Index> <Name>Mic 1 Level 4</Name> <Symbol>lv2_port_113</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>113</Index> <Name>Mic 1 Delay 4</Name> <Symbol>lv2_port_114</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>114</Index> <Name>Mic 1 Level 5</Name> <Symbol>lv2_port_115</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>115</Index> <Name>Mic 1 Delay 5</Name> <Symbol>lv2_port_116</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>116</Index> <Name>Mic 2 Mic Switch</Name> <Symbol>lv2_port_117</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>117</Index> <Name>Mic 2 X position</Name> <Symbol>lv2_port_118</Symbol> <Value>0.574999988079071</Value> </Parameter> <Parameter> <Index>118</Index> <Name>Mic 2 Y position</Name> <Symbol>lv2_port_119</Symbol> <Value>0.5625</Value> </Parameter> <Parameter> <Index>119</Index> <Name>Mic 2 Z position</Name> <Symbol>lv2_port_120</Symbol> <Value>0.428571432828903</Value> </Parameter> <Parameter> <Index>120</Index> <Name>Mic 2 Azimuth</Name> <Symbol>lv2_port_121</Symbol> <Value>0.625</Value> </Parameter> <Parameter> <Index>121</Index> <Name>Mic 2 Elevation</Name> <Symbol>lv2_port_122</Symbol> <Value>0.488764733076096</Value> </Parameter> <Parameter> <Index>122</Index> <Name>Mic 2 Level 1</Name> <Symbol>lv2_port_123</Symbol> <Value>0.59375</Value> </Parameter> <Parameter> <Index>123</Index> <Name>Mic 2 Delay 1</Name> <Symbol>lv2_port_124</Symbol> <Value>0.75</Value> </Parameter> <Parameter> <Index>124</Index> <Name>Mic 2 Level 2</Name> <Symbol>lv2_port_125</Symbol> <Value>0.837499976158142</Value> </Parameter> <Parameter> <Index>125</Index> <Name>Mic 2 Delay 2</Name> <Symbol>lv2_port_126</Symbol> <Value>0.509375035762787</Value> </Parameter> <Parameter> <Index>126</Index> <Name>Mic 2 Level 3</Name> <Symbol>lv2_port_127</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>127</Index> <Name>Mic 2 Delay 3</Name> <Symbol>lv2_port_128</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>128</Index> <Name>Mic 2 Level 4</Name> <Symbol>lv2_port_129</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>129</Index> <Name>Mic 2 Delay 4</Name> <Symbol>lv2_port_130</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>130</Index> <Name>Mic 2 Level 5</Name> <Symbol>lv2_port_131</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>131</Index> <Name>Mic 2 Delay 5</Name> <Symbol>lv2_port_132</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>132</Index> <Name>Mic 3 Mic Switch</Name> <Symbol>lv2_port_133</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>133</Index> <Name>Mic 3 X position</Name> <Symbol>lv2_port_134</Symbol> <Value>0.596000015735626</Value> </Parameter> <Parameter> <Index>134</Index> <Name>Mic 3 Y position</Name> <Symbol>lv2_port_135</Symbol> <Value>0.429999977350235</Value> </Parameter> <Parameter> <Index>135</Index> <Name>Mic 3 Z position</Name> <Symbol>lv2_port_136</Symbol> <Value>0.262857139110565</Value> </Parameter> <Parameter> <Index>136</Index> <Name>Mic 3 Azimuth</Name> <Symbol>lv2_port_137</Symbol> <Value>0.75</Value> </Parameter> <Parameter> <Index>137</Index> <Name>Mic 3 Elevation</Name> <Symbol>lv2_port_138</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>138</Index> <Name>Mic 3 Level 1</Name> <Symbol>lv2_port_139</Symbol> <Value>0.512499988079071</Value> </Parameter> <Parameter> <Index>139</Index> <Name>Mic 3 Delay 1</Name> <Symbol>lv2_port_140</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>140</Index> <Name>Mic 3 Level 2</Name> <Symbol>lv2_port_141</Symbol> <Value>0.512499988079071</Value> </Parameter> <Parameter> <Index>141</Index> <Name>Mic 3 Delay 2</Name> <Symbol>lv2_port_142</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>142</Index> <Name>Mic 3 Level 3</Name> <Symbol>lv2_port_143</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>143</Index> <Name>Mic 3 Delay 3</Name> <Symbol>lv2_port_144</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>144</Index> <Name>Mic 3 Level 4</Name> <Symbol>lv2_port_145</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>145</Index> <Name>Mic 3 Delay 4</Name> <Symbol>lv2_port_146</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>146</Index> <Name>Mic 3 Level 5</Name> <Symbol>lv2_port_147</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>147</Index> <Name>Mic 3 Delay 5</Name> <Symbol>lv2_port_148</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>148</Index> <Name>Mic 4 Mic Switch</Name> <Symbol>lv2_port_149</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>149</Index> <Name>Mic 4 X position</Name> <Symbol>lv2_port_150</Symbol> <Value>0.465000003576279</Value> </Parameter> <Parameter> <Index>150</Index> <Name>Mic 4 Y position</Name> <Symbol>lv2_port_151</Symbol> <Value>0.531666696071625</Value> </Parameter> <Parameter> <Index>151</Index> <Name>Mic 4 Z position</Name> <Symbol>lv2_port_152</Symbol> <Value>0.251428574323654</Value> </Parameter> <Parameter> <Index>152</Index> <Name>Mic 4 Azimuth</Name> <Symbol>lv2_port_153</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>153</Index> <Name>Mic 4 Elevation</Name> <Symbol>lv2_port_154</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>154</Index> <Name>Mic 4 Level 1</Name> <Symbol>lv2_port_155</Symbol> <Value>0.512499988079071</Value> </Parameter> <Parameter> <Index>155</Index> <Name>Mic 4 Delay 1</Name> <Symbol>lv2_port_156</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>156</Index> <Name>Mic 4 Level 2</Name> <Symbol>lv2_port_157</Symbol> <Value>0.512499988079071</Value> </Parameter> <Parameter> <Index>157</Index> <Name>Mic 4 Delay 2</Name> <Symbol>lv2_port_158</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>158</Index> <Name>Mic 4 Level 3</Name> <Symbol>lv2_port_159</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>159</Index> <Name>Mic 4 Delay 3</Name> <Symbol>lv2_port_160</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>160</Index> <Name>Mic 4 Level 4</Name> <Symbol>lv2_port_161</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>161</Index> <Name>Mic 4 Delay 4</Name> <Symbol>lv2_port_162</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>162</Index> <Name>Mic 4 Level 5</Name> <Symbol>lv2_port_163</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>163</Index> <Name>Mic 4 Delay 5</Name> <Symbol>lv2_port_164</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>164</Index> <Name>Mic 5 Mic Switch</Name> <Symbol>lv2_port_165</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>165</Index> <Name>Mic 5 X position</Name> <Symbol>lv2_port_166</Symbol> <Value>0.577000021934509</Value> </Parameter> <Parameter> <Index>166</Index> <Name>Mic 5 Y position</Name> <Symbol>lv2_port_167</Symbol> <Value>0.569999992847443</Value> </Parameter> <Parameter> <Index>167</Index> <Name>Mic 5 Z position</Name> <Symbol>lv2_port_168</Symbol> <Value>0.502857148647308</Value> </Parameter> <Parameter> <Index>168</Index> <Name>Mic 5 Azimuth</Name> <Symbol>lv2_port_169</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>169</Index> <Name>Mic 5 Elevation</Name> <Symbol>lv2_port_170</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>170</Index> <Name>Mic 5 Level 1</Name> <Symbol>lv2_port_171</Symbol> <Value>0.512499988079071</Value> </Parameter> <Parameter> <Index>171</Index> <Name>Mic 5 Delay 1</Name> <Symbol>lv2_port_172</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>172</Index> <Name>Mic 5 Level 2</Name> <Symbol>lv2_port_173</Symbol> <Value>0.512499988079071</Value> </Parameter> <Parameter> <Index>173</Index> <Name>Mic 5 Delay 2</Name> <Symbol>lv2_port_174</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>174</Index> <Name>Mic 5 Level 3</Name> <Symbol>lv2_port_175</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>175</Index> <Name>Mic 5 Delay 3</Name> <Symbol>lv2_port_176</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>176</Index> <Name>Mic 5 Level 4</Name> <Symbol>lv2_port_177</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>177</Index> <Name>Mic 5 Delay 4</Name> <Symbol>lv2_port_178</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>178</Index> <Name>Mic 5 Level 5</Name> <Symbol>lv2_port_179</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>179</Index> <Name>Mic 5 Delay 5</Name> <Symbol>lv2_port_180</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>180</Index> <Name>Stereo Width</Name> <Symbol>lv2_port_181</Symbol> <Value>0.674031317234039</Value> </Parameter> <Parameter> <Index>181</Index> <Name>Sound Speed</Name> <Symbol>lv2_port_182</Symbol> <Value>0.500000059604645</Value> </Parameter> <Parameter> <Index>182</Index> <Name>Mute</Name> <Symbol>lv2_port_183</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>183</Index> <Name>Clavinet Low Mic</Name> <Symbol>lv2_port_184</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>184</Index> <Name>ClvMicH</Name> <Symbol>lv2_port_185</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>185</Index> <Name>Equalizer Switch</Name> <Symbol>lv2_port_186</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>186</Index> <Name>HTinNois</Name> <Symbol>lv2_port_187</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>187</Index> <Name>Blooming Energy</Name> <Symbol>lv2_port_188</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>188</Index> <Name>Blooming Inertia</Name> <Symbol>lv2_port_189</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>189</Index> <Name>Aftertouch</Name> <Symbol>lv2_port_190</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>190</Index> <Name>Wall distance</Name> <Symbol>lv2_port_191</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>191</Index> <Name>Unison Balance</Name> <Symbol>lv2_port_192</Symbol> <Value>0.5</Value> </Parameter> <Parameter> <Index>192</Index> <Name>Condition</Name> <Symbol>lv2_port_193</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>193</Index> <Name>Condition Seed</Name> <Symbol>lv2_port_194</Symbol> <Value>0.12341234087944</Value> </Parameter> <Parameter> <Index>194</Index> <Name>Rattle Pedal</Name> <Symbol>lv2_port_195</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>195</Index> <Name>Lute Stop Pedal</Name> <Symbol>lv2_port_196</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>196</Index> <Name>Celeste Pedal</Name> <Symbol>lv2_port_197</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>197</Index> <Name>Super Sostenuto</Name> <Symbol>lv2_port_198</Symbol> <Value>0</Value> </Parameter> <CustomData> <Type>http://lv2plug.in/ns/ext/atom#Chunk</Type> <Key>urn:juce:stateBinary</Key> <Value> UHJWSxQAAAJYRlRQpBsAAAoAAAAyMDE3LzEyLzEzFwAAAFBpYW5vdGVxIDUuMy4wLzIwMTUwNzE1o9QvMCuNhmEarickC02mrGRsbGFjGwAAdGR0TXIGAAARAAAARDQgRGFpbHkgUHJhY3RpY2UAAAAAGgAAAENvcHlyaWdodCAoYykgMjAxNSBNb2RhcnR0hwAAAFRoaXMgcHJlc2V0IG9mZmVycyBhIGNsZWFuIHNvdW5kLCB5b3UgbWF5IGxpa2UgdG8gdXNlIGl0IGZvciB5b3VyIGRhaWx5IHByYWN0aWNlLiBBbHNvIGEgZ29vZCBzdGFydGluZyBwb2ludCBmb3IgcHJlcGFyaW5nIG5ldyBwcmVzZXRzLgAAAACEAAAAEQAAAEQ0IERhaWx5IFByYWN0aWNlAAAAAIsFAABHUlVVAAAABgAAAAEDwE1UcmsAAAV1AP8CDyBQaWV0IERlIFJpZGRlcgCQKil4gCpVBpArJIMxgCsNaJAkKoIHgCQcMpA3LYEJgDdPgmaQPDGBToA8RVaQKyoFPzuBTIA/bFaQQy8qNyCBGIBDUgQ3K0orJYERkD80CCUlcoA/Wz0lTVKQQisIJiKBOoBCSoEskDkhghSAOUqBICYbNJA+MINMLUKBIoAtSoJCkDI9gVeAMjtCkCsyQoA+bIMlkDItghwvPCCAK2kKMi19L09FkDpPCjVKgVWAOmMbkDs+CYA1IoImO0AEkDw4gSuAPGlHkEFBFDI5gSKAMmZYkDhQgk0kSoJXgDhggSaQNz4GP083gEFFgxYkCSiQMEGBcoA3QB6QK0EqgDA2Zz9dfJAwOFKAKwUcMFKBAJAkUIEggCRjbZA8RYFwgDxmB5A/MYIJQVkGgD9yFJAwQoFggEFveTAFfpBCZoE5gEJSLpBDVFIwLXeAQ2k6kERPgR6AME81RGk5kEVGBCYxhBIwLiiAJm+BaZBDVS+ARVuCQjA0YZBEWgyAQ00AkC1BBTA2gR2AMF0ARGxVkEVeEjAdgRaAMGAtRWktkEZbCSo3UIAtNBxGYzQqYFSQR0wNKzGBeIBHLQmQQSCBcIBBWx2QQiqBSIBCWwkrGUyQQ1UIMkaBMYAyYCVDbIF2kEttgQyAS2OCZZAvPQ1KXoEzgEpFWy9pBpBIPAQwOYFugEhpMDA9gTaQJC+BQ4AkJ2eQQ2OBSIBDRYIpkEJVCjBVcoBCZoEEkENFaoAwIYEEkCstEkZFIYBDY4EmRmkCK0U3kChKBUhbggmASGMZkEZCHYAoSoELRjiCPpA0TQA6RwBATzkiNIFZgDpsWjRsRUBsPSIyGJAoRoF7LlBPgChsgSOQPV+BNIA9WwkuZkWQPkULKUWBYYA+YCSQPC6BV4A8VYFkKUdIkDhLHDA2gx+AOGwhkDdZgRqAMGkyN1sukDVQCyxUgSyALFgvNWANkDdGEDA9gU+AN2AIMEookCZPAjhFgS+AOG9XkDkvggQ8LCCAORxJJlWBJ5A/SwiAPGkPkDBQgSuAMEUukEJgEjAJD4A/aWxCbzswSjqQRWgtMBJjgEVsEjBmV5BEViYqRoFYQ1AzgERNIENjHypmgQWQQkoTK0KBHoBCaVCQQzmBNYBDYEaQRE9/gERpRitYTpBFaAYvU4F/gEVsSC82gRmQMloARmeBO4BGbCuQR0w8gDIYgUKQL0qBL4AvXQRHYz2QSFsHMGaBX4BIbA0wWxKQS28bM2hQgEtsgQczW4FSkEhVADBkgQGASGBlMEIokENpEStMgSCAQ2A7K2ZQkCc4BD9FgTeAJz0NP2aBNZBDVgAra4EggENjbpAnSwI/PBWAK1V9P0ceJ2ZOkCZNAj48gTOAPi07kCo4AEJAboAmUhRCPSUqW1SQRWQTLVUALxSBB4BFaUYvbBQtZoF/kCxqBERqgUOARGktLGmBXJAqYQdCZ4ExgEJsISpvM5ArWgJDVoExgCtvE0NmghqQRmEEQV8EK1g5R18agEZyc0FmPStVH0dggVOQMmcJSmoCQWmCD4BBJ0gyQhVKY4QbkDA6gXAzPiWAMACBcJA3K4EcgDcALzMAHZA8U4F/gDwACpA/U4FsQ1IQgD8AgUJDAB6QSEqBEYBIAHqQSzuCHIBLAAOQT1CBVIBPAIJPkFBjCCtcB0piAjdkBFNggVCASgARUAAAUwBjNwACKwCCVZAkZwIwZAhPYgNIVwRUYxJLXwArYAVRXIELgCsAE1QABCQAC1EAJ0sAMTAAEU8AgQ0kQAArQAAwQAAzQAA3QAA8QAA/QABDQABIQABKQABLQABPQABQQABRQABTQABUQAD/LwBQcnNV4RQAACoAAAACAAAAZDQAAAAACAAAAEdyYW5kIEQ0AAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAEAAAAAAAAA3H8iPgMAAAAKAAAAAACoQQAA6EEAABhCAAAgQgAAJEIAACxCAABgQgAAkkIAAJRCAAC2QgoAAABhpkk/CNJOPwnMaT94/Fw/WUNUPzMOYD8dCIA/jz6zP48+sz+PPrM/AAAAAAAAtkIAAAAAAwAAAAEAAAAAAHBCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACgwAAAoEAAAAAAAwAAAAIAAAAAAKhBAADYQgIAAAAAAAAAAAAAAAAAAAADAAAAAgAAAAAAqEEAANhCAgAAAAAAgD8AAIA/AAAAAIAAAAAAAAAA0gQAAAAAgD8DAAAAAQAAAAAAcEIBAAAAAAAAAAAAAAADAAAAaQAAAAAAEEEAACBBAAAwQQAAQEEAAFBBAABgQQAAcEEAAIBBAACIQQAAkEEAAJhBAACgQQAAqEEAALBBAAC4QQAAwEEAAMhBAADQQQAA2EEAAOBBAADoQQAA8EEAAPhBAAAAQgAABEIAAAhCAAAMQgAAEEIAABRCAAAYQgAAHEIAACBCAAAkQgAAKEIAACxCAAAwQgAANEIAADhCAAA8QgAAQEIAAERCAABIQgAATEIAAFBCAABUQgAAWEIAAFxCAABgQgAAZEIAAGhCAABsQgAAcEIAAHRCAAB4QgAAfEIAAIBCAACCQgAAhEIAAIZCAACIQgAAikIAAIxCAACOQgAAkEIAAJJCAACUQgAAlkIAAJhCAACaQgAAnEIAAJ5CAACgQgAAokIAAKRCAACmQgAAqEIAAKpCAACsQgAArkIAALBCAACyQgAAtEIAALZCAAC4QgAAukIAALxCAAC+QgAAwEIAAMJCAADEQgAAxkIAAMhCAADKQgAAzEIAAM5CAADQQgAA0kIAANRCAADWQgAA2EIAANpCAADcQgAA3kIAAOBCAADiQmkAAAAAAADAAACAvwAAQMAAAEDAAABAQAAAAEAAAMBAAACAPwAAgD8AAMBAAABAQAAAgEAAAADAAABAwAAAgEAAAIBAAACgQAAAwEAAAIBAAAAAgAAAgD8AAADAAACAPwAAQMAAAEDAAABAQAAAgEAAAKBAAACgQAAAQMAAAKBAAAAAgAAAAEAAAEDAAACgQAAAoEAAAEBAAACAQAAAAEAAAADAAACAPwAAgEAAAABAAACgQAAAQEAAAEDAAAAAgAAAgEAAAEDAAAAAgAAAgD8AAIC/AABAwAAAoEAAAEDAAAAAwAAAAIAAAACAAACgQAAAQMAAAADAAACAvwAAQMAAAEDAAACgQAAAAMAAAEDAAABAwAAAgEAAAIA/AABAwAAAgEAAAAAAAACAQAAAgL8AAABAAACgQAAAQMAAAIC/AAAAwAAAwEAAAKBAAABAwAAAQMAAAADAAACAPwAAQMAAAEDAAACAvwAAgL8AAMBAAACAQAAAQMAAAAAAAAAAAAAAgD8AAEDAAAAAwAAAwEAAAEDAAADAQAAAQMAAAEDAAABAwAAAAEAAAAAAAwAAAAIAAAAAAKhBAADYQgIAAAAAAIA/AACAPwAAAAAAANxDAAAAAAEAAAAAAAAABwAAAERlZmF1bHQMAAAAAADIQgAASEMAAJZDAADIQwAA+kMAABZEAAAvRAAASEQAAGFEAAB6RACAiUQAAJZEAQAAAAAA3EM8AAAARQAAAAAAAAAAAAAABwAAAERlZmF1bHQDAAAABAAAAAAAwEEAABBCAABAQgAA2EIEAAAAAACgwAAAgL8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AwAAAAIAAAAAAKhBAADYQgIAAAAAAIA/AACAPwAAAAADAAAAAgAAAAAAqEEAANhCAgAAAAAAgD8AAIA/AAAAAAAAAAADAAAAAQAAAAAAcEIBAAAAAAAAAAAAAAAAAIA/AwAAAAEAAAAAAHBCAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAzczMvc3MzD0BAAAAAAAAAAAAAAAAAAC/AAAAPwAAgD8DAAAAAwAAAAAAqEEAAHBCAADYQgMAAAAAAIA/AACAPwAAgD8AAAAAAAAAAAMAAAACAAAAAACoQQAA2EICAAAAAAAAAAAAAAAAAAAAAACAPwMAAAACAAAAAACoQQAA2EICAAAAAACAPwAAgD8AAAAAAAAgQgMAAAAHAAAAAACoQQAAkEIAAKhCAAC0QgAAwEIAAMhCAADYQgcAAAAAAAAAAAAAAAAAQEAAAMBAAAAQQQAAIEEAADBBAAAAAAAAgD8DAAAAAwAAAAAAqEEAAHBCAADYQgMAAAAAAIA/AACAPwAAgD8AAAAAAwAAAAAAAAABAAAAAAAAAAAAAAABAAAAAwAAAAIAAAAAAAAAAACAPwIAAAAAAAAAAACAPwAAAAADAAAAAgAAAAAAAAAAAIA/AgAAAAAAgD8AAIA/AAAAAAMAAAAEAAAAAAAAACaTST7+fj8/AACAPwQAAAAAAAAAAAAAAAAAgD8AAIA/AAAAAAMAAAACAAAAAAAAAAAAgD8CAAAAAAAAAAAAAAAAAAAAzcwsQAMAAAACAAAAAACoQQAA2EICAAAAAACAPwAAgD8AAAAAAACAvwAAAD8DAAAAAgAAAAAAwEEAAMBCAgAAAAAAgD8AAIA/AAAAAAEAAAABAAAAAQAAAAoAAABTbWFsbCBIYWxsCwAAAG1lZGl1bWhhbGwxAAAAAAAAoEEAAIA/ZmZmPwAAAABCYGU9AAAAAAAAAAAAAAAAAACqQwAAgD8AAIA/BQAAAAAAgD8AAIA/AwAAAF0AAAAAAKhBAACwQQAAuEEAAMBBAADIQQAA0EEAANhBAADgQQAA6EEAAPBBAAD4QQAAAEIAAARCAAAIQgAADEIAABBCAAAUQgAAGEIAABxCAAAgQgAAJEIAAChCAAAsQgAAMEIAADRCAAA4QgAAPEIAAEBCAABEQgAASEIAAExCAABQQgAAVEIAAFhCAABcQgAAYEIAAGRCAABoQgAAbEIAAHBCAAB0QgAAeEIAAHxCAACAQgAAgkIAAIRCAACGQgAAiEIAAIpCAACMQgAAjkIAAJBCAACSQgAAlEIAAJZCAACYQgAAmkIAAJxCAACeQgAAoEIAAKJCAACkQgAApkIAAKhCAACqQgAArEIAAK5CAACwQgAAskIAALRCAAC2QgAAuEIAALpCAAC8QgAAvkIAAMBCAADCQgAAxEIAAMZCAADIQgAAykIAAMxCAADOQgAA0EIAANJCAADUQgAA1kIAANhCAADaQgAA3EIAAN5CAADgQgAA4kJdAAAAAACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD9xPYo/heuRP/YonD/sUZg/j8KVP3E9ij+amZk/j8KVP3sUjj+PwpU/mpmZP7gepT/NzIw/CtejP1K4nj+amZk/16OQP9ejkD+4HqU/KVyPP+F6lD89Cpc/exSOP4/ClT9I4Zo/exSuP65HoT8AAIA/KVyPP1K4nj8AAIA/4XqUP1yPoj/sUZg/XI+iPx+Fqz+kcJ0/MzOzP3sUrj+uR6E/SOGaP3E9ij9cj6I/w/WIP+xRmD/NzIw/FK6HPx+Fiz/sUZg/UrieP3sUjj+uR6E/KVyPP5qZmT9cj6I/CtejP2Zmpj+kcJ0/MzOTP4/CtT9SuJ4/mpmZP5qZuT+4HqU/AACgP83MrD+ambk/pHCdP0jhmj/NzKw/PQqXPylcjz/D9ag/PQqXP6RwnT+amZk/cT2qP0jhmj9SuJ4/UrieP0jhmj97FK4/4XqUP/YonD+kcJ0/AAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAwAAAF0AAAAAAKhBAACwQQAAuEEAAMBBAADIQQAA0EEAANhBAADgQQAA6EEAAPBBAAD4QQAAAEIAAARCAAAIQgAADEIAABBCAAAUQgAAGEIAABxCAAAgQgAAJEIAAChCAAAsQgAAMEIAADRCAAA4QgAAPEIAAEBCAABEQgAASEIAAExCAABQQgAAVEIAAFhCAABcQgAAYEIAAGRCAABoQgAAbEIAAHBCAAB0QgAAeEIAAHxCAACAQgAAgkIAAIRCAACGQgAAiEIAAIpCAACMQgAAjkIAAJBCAACSQgAAlEIAAJZCAACYQgAAmkIAAJxCAACeQgAAoEIAAKJCAACkQgAApkIAAKhCAACqQgAArEIAAK5CAACwQgAAskIAALRCAAC2QgAAuEIAALpCAAC8QgAAvkIAAMBCAADCQgAAxEIAAMZCAADIQgAAykIAAMxCAADOQgAA0EIAANJCAADUQgAA1kIAANhCAADaQgAA3EIAAN5CAADgQgAA4kJdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxmuW8SOFIvRdVB71AGWE80EJ4vV/YST2wNkm93jniudhVqr0uuGu9OCETOtdjgLwW24S9RFIFPaiJjzyCl7C67ryqPZLitb218bo92mxJPUMvoT3kFqu7vQhvvQR/oL3X3K292xWdPYeDQz28BZW9MjXGPNl7sb1R4a68jIzyPHT/wT1b5ja7ZmKPuhApuj3cZ7M9IC6aPaW0Er3O34W8jcm2PFJHqDxKNLo9cuRnvbkagD3/Na291GWdPYkdXTw2jls9rlyQvTrpXb1gYKE8fIdGPRFnCj2OWQM9G/zWO8bUsbxXGHs9ARhlvR18wjwzmiS9TzBSvUlvOr33Tk49bNO2Pcm2J70VS6U9PV6dPUUter0+pHg9leXfvB3hl7wlwYw9fkrZOWb3xz1aWSE9lUvOPAMPnL3ammu9bMGSPSgz8Dwlv7O97aNfPUb8jj2w+UC9AAAAAAMAAAAAAIA/AACAPwAAgD8DAAAAAwAAAAAAqEEAAHBCAADYQgMAAAAAAIA/AACAPwAAgD8AAAAAAwAAAAMAAAAAAKhBAABwQgAA2EIDAAAAAACAPwAAgD8AAIA/AAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAgD8AAIA/AACAPwAAAAAAAIA/AACAPwYAAAAAAIA/mpmZPs3MTD/NzMw/mpmZPggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAgD8AAIA/AACAPwAAAAADAAAAAwAAAAAAqEEAAHBCAADYQgMAAAAAAIA/AACAPwAAgD8AAAAAAwAAAAMAAAAAAKhBAABwQgAA2EIDAAAAAACAPwAAgD8AAIA/AAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAgD8AAIA/AACAPwAAAAABAAAAAQAAAAAAcEIDAAAAAQAAAAAAAAABAAAAAAAAAAAAAABOI9g9AwAAABYAAAAAABBBAACoQQAAwEEAAOBBAADoQQAAAEIAAAhCAAAYQgAAJEIAADBCAABAQgAATEIAAGBCAABwQgAAgEIAAIhCAACQQgAAmEIAAKBCAACoQgAAwEIAANhCFgAAAHh0JD/p5Y8/DGGSP3jylD9Ng5Q/TYOUP02DlD9Ng5Q/6oqRP02DlD9Ng5Q/6oqRP1mwjj/qipE/WbCOP1mwjj9ZsI4/54RcP+eEXD9+JEo/2kMtPzGS8j4AAAAAAQAAAAAAAAABAAAAMzMzP2Zmpj8BAAAAAQAAAAEAAABmZmY/zcyMPwEAAAAAAAAAAADwQgAAAAAOAAAAAAAAP83MzD3NzEw+AAAAPwQAAAACAAAAAwAAAAQAAAABAAAAAgAAAAcAAAABAAAAAAAAAA4AAAAQAAAAAAAAAM3MzD0AAIA/AAAAAAAAAL8AAHBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAOAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAADgAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAIA/AABAwQAAAAACAAAAAwAAAAEAAAAFAAAABAAAAAEAAAADAAAAAADAPwAAoD8AAMA/AABhwxxugcAAAAAABQAAAAAAAAAAABDBAADAwgAAwMIAAMDCBQAAAAAAAACPwvU8AAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAEAAAAAQAAAAMAAAAAAMA/AABAPwAAwD8AADRCHG6BwAAAAAAFAAAAAAAQwQAAAAAAAMDCAADAwgAAwMIFAAAACtcjPaabxDoAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAQAAAAAAAAAAwAAAI/C9T89Cle/H4VrPwAAtEIAAAAAAAAAAAUAAAAAAEDBAABAwQAAcMIAAHDCAABwwgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAABAAAAAAAAAADAAAAMzMzv1yPwj6uR2E/AAAAAAAAAAAAAAAABQAAAAAAQMEAAEDBAABwwgAAcMIAAHDCBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAEAAAAAAAAAAMAAAC4HsU/PQpXP65H4T8AAAAAAAAAAAAAAAAFAAAAAABAwQAAQMEAAHDCAABwwgAAcMIFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAMAAAAzMzM/AAAAAGZmpj8AAJBBAAAAAAAAAAAAAAAA </Value> </CustomData> </Data> </Plugin> <!-- MIDI Chord --> <Plugin> <Info> <Type>LV2</Type> <Name>MIDI Chord</Name> <URI>http://gareus.org/oss/lv2/midifilter#midichord</URI> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1e1</Options> <Parameter> <Index>1</Index> <Name>Filter Channel</Name> <Symbol>channelf</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>2</Index> <Name>Scale</Name> <Symbol>scale</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>3</Index> <Name>prime</Name> <Symbol>c1</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>4</Index> <Name>3rd</Name> <Symbol>c3</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>5</Index> <Name>5th</Name> <Symbol>c5</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>6</Index> <Name>6th</Name> <Symbol>c6</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>7</Index> <Name>7th</Name> <Symbol>c7</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>8</Index> <Name>octave</Name> <Symbol>c8</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>9</Index> <Name>9th</Name> <Symbol>c9</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>10</Index> <Name>11th</Name> <Symbol>c11</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>11</Index> <Name>13th</Name> <Symbol>c13</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>12</Index> <Name>bass</Name> <Symbol>_8</Symbol> <Value>0</Value> </Parameter> <CustomData> <Type>http://kxstudio.sf.net/ns/carla/property</Type> <Key>CarlaSkinIsCompacted</Key> <Value>true</Value> </CustomData> </Data> </Plugin> <!-- Carla-Rack (no midi out) --> <Plugin> <Info> <Type>INTERNAL</Type> <Name>Carla-Rack (no midi out)</Name> <Label>carlarack-nomidiout</Label> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x3e0</Options> <CustomData> <Type>http://kxstudio.sf.net/ns/carla/chunk</Type> <Key>State</Key> <Value> &lt;?xml version=&apos;1.0&apos; encoding=&apos;UTF-8&apos;?&gt; &lt;!DOCTYPE CARLA-PROJECT&gt; &lt;CARLA-PROJECT VERSION=&apos;2.0&apos;&gt; &lt;EngineSettings&gt; &lt;ForceStereo&gt;false&lt;/ForceStereo&gt; &lt;PreferPluginBridges&gt;false&lt;/PreferPluginBridges&gt; &lt;PreferUiBridges&gt;true&lt;/PreferUiBridges&gt; &lt;UIsAlwaysOnTop&gt;false&lt;/UIsAlwaysOnTop&gt; &lt;MaxParameters&gt;200&lt;/MaxParameters&gt; &lt;UIBridgesTimeout&gt;4000&lt;/UIBridgesTimeout&gt; &lt;LADSPA_PATH&gt;/home/falktx/.ladspa:/usr/lib/ladspa:/usr/local/lib/ladspa&lt;/LADSPA_PATH&gt; &lt;DSSI_PATH&gt;/home/falktx/.dssi:/usr/lib/dssi:/usr/local/lib/dssi&lt;/DSSI_PATH&gt; &lt;LV2_PATH&gt;/home/falktx/.lv2:/usr/lib/lv2:/usr/local/lib/lv2&lt;/LV2_PATH&gt; &lt;VST2_PATH&gt;/home/falktx/.vst:/home/falktx/.wineflstudio/drive_c/Program Files (x86)/VstPlugins/:/usr/lib/vst:/usr/local/lib/vst&lt;/VST2_PATH&gt; &lt;GIG_PATH&gt;/home/falktx/.sounds/gig:/usr/share/sounds/gig&lt;/GIG_PATH&gt; &lt;SF2_PATH&gt;/home/falktx/.sounds/sf2:/home/falktx/Personal/Muzyks/Kits/SoundFonts:/usr/share/sounds/sf2&lt;/SF2_PATH&gt; &lt;SFZ_PATH&gt;/home/falktx/.sounds/sfz:/home/falktx/Personal/Muzyks/Kits/SFZ:/usr/share/sounds/sfz&lt;/SFZ_PATH&gt; &lt;/EngineSettings&gt; &lt;!-- QMidiArp Arp --&gt; &lt;Plugin&gt; &lt;Info&gt; &lt;Type&gt;LV2&lt;/Type&gt; &lt;Name&gt;QMidiArp Arp&lt;/Name&gt; &lt;URI&gt;https://git.code.sf.net/p/qmidiarp/arp&lt;/URI&gt; &lt;/Info&gt; &lt;Data&gt; &lt;Active&gt;Yes&lt;/Active&gt; &lt;ControlChannel&gt;1&lt;/ControlChannel&gt; &lt;Options&gt;0x1e1&lt;/Options&gt; &lt;Parameter&gt; &lt;Index&gt;0&lt;/Index&gt; &lt;Name&gt;Attack&lt;/Name&gt; &lt;Symbol&gt;ATTACK&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;1&lt;/Index&gt; &lt;Name&gt;Release&lt;/Name&gt; &lt;Symbol&gt;RELEASE&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;2&lt;/Index&gt; &lt;Name&gt;Random Tick&lt;/Name&gt; &lt;Symbol&gt;RANDOM_TICK&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;3&lt;/Index&gt; &lt;Name&gt;Random Length&lt;/Name&gt; &lt;Symbol&gt;RANDOM_LEN&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;4&lt;/Index&gt; &lt;Name&gt;Random Velocity&lt;/Name&gt; &lt;Symbol&gt;RANDOM_VEL&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;5&lt;/Index&gt; &lt;Name&gt;Output Channel&lt;/Name&gt; &lt;Symbol&gt;CH_OUT&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;6&lt;/Index&gt; &lt;Name&gt;Input Channel&lt;/Name&gt; &lt;Symbol&gt;CH_IN&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;8&lt;/Index&gt; &lt;Name&gt;Restart&lt;/Name&gt; &lt;Symbol&gt;ENABLE_RESTARTBYKBD&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;9&lt;/Index&gt; &lt;Name&gt;Trigger&lt;/Name&gt; &lt;Symbol&gt;ENABLE_TRIGBYKBD&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;10&lt;/Index&gt; &lt;Name&gt;Mute Output&lt;/Name&gt; &lt;Symbol&gt;MUTE&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;11&lt;/Index&gt; &lt;Name&gt;Latch mode&lt;/Name&gt; &lt;Symbol&gt;LATCH_MODE&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;12&lt;/Index&gt; &lt;Name&gt;Octave Mode&lt;/Name&gt; &lt;Symbol&gt;OCTAVE_MODE&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;13&lt;/Index&gt; &lt;Name&gt;Low octave limit&lt;/Name&gt; &lt;Symbol&gt;OCTAVE_LOW&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;14&lt;/Index&gt; &lt;Name&gt;High octave limit&lt;/Name&gt; &lt;Symbol&gt;OCTAVE_HIGH&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;15&lt;/Index&gt; &lt;Name&gt;Index In 1&lt;/Name&gt; &lt;Symbol&gt;INDEX_IN1&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;16&lt;/Index&gt; &lt;Name&gt;Index In 2&lt;/Name&gt; &lt;Symbol&gt;INDEX_IN2&lt;/Symbol&gt; &lt;Value&gt;127&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;17&lt;/Index&gt; &lt;Name&gt;Range In 1&lt;/Name&gt; &lt;Symbol&gt;RANGE_IN1&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;18&lt;/Index&gt; &lt;Name&gt;Range In 2&lt;/Name&gt; &lt;Symbol&gt;RANGE_IN2&lt;/Symbol&gt; &lt;Value&gt;127&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;19&lt;/Index&gt; &lt;Name&gt;Trigger Legato&lt;/Name&gt; &lt;Symbol&gt;ENABLE_TRIGLEGATO&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;20&lt;/Index&gt; &lt;Name&gt;Repeat Mode&lt;/Name&gt; &lt;Symbol&gt;REPEAT_MODE&lt;/Symbol&gt; &lt;Value&gt;1&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;22&lt;/Index&gt; &lt;Name&gt;Defer mute&lt;/Name&gt; &lt;Symbol&gt;DEFER&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;23&lt;/Index&gt; &lt;Name&gt;Pattern Preset&lt;/Name&gt; &lt;Symbol&gt;PATTERN_PRESET&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;24&lt;/Index&gt; &lt;Name&gt;Transport Mode&lt;/Name&gt; &lt;Symbol&gt;TRANSPORT_MODE&lt;/Symbol&gt; &lt;Value&gt;1&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;25&lt;/Index&gt; &lt;Name&gt;Internal Tempo&lt;/Name&gt; &lt;Symbol&gt;TEMPO&lt;/Symbol&gt; &lt;Value&gt;120&lt;/Value&gt; &lt;/Parameter&gt; &lt;CustomData&gt; &lt;Type&gt;http://lv2plug.in/ns/ext/atom#String&lt;/Type&gt; &lt;Key&gt;https://git.code.sf.net/p/qmidiarp#ARPPATTERN&lt;/Key&gt; &lt;Value&gt;&amp;gt;0&lt;/Value&gt; &lt;/CustomData&gt; &lt;/Data&gt; &lt;/Plugin&gt; &lt;Plugin&gt; &lt;Info&gt; &lt;Type&gt;SFZ&lt;/Type&gt; &lt;Name&gt;concert_harp&lt;/Name&gt; &lt;Filename&gt;/home/falktx/Personal/Muzyks/Kits/SFZ/Sonatina Symphonic Orchestra/concert_harp.sfz&lt;/Filename&gt; &lt;/Info&gt; &lt;Data&gt; &lt;Active&gt;Yes&lt;/Active&gt; &lt;ControlChannel&gt;1&lt;/ControlChannel&gt; &lt;Options&gt;0x1f0&lt;/Options&gt; &lt;CurrentProgramIndex&gt;1&lt;/CurrentProgramIndex&gt; &lt;CurrentProgramName&gt;concert_harp&lt;/CurrentProgramName&gt; &lt;/Data&gt; &lt;/Plugin&gt; &lt;/CARLA-PROJECT&gt; </Value> </CustomData> <CustomData> <Type>http://kxstudio.sf.net/ns/carla/property</Type> <Key>CarlaSkinIsCompacted</Key> <Value>true</Value> </CustomData> </Data> </Plugin> <!-- Carla-Rack (no midi out) --> <Plugin> <Info> <Type>INTERNAL</Type> <Name>arp xylo + 3d delay</Name> <Label>carlarack-nomidiout</Label> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x3e0</Options> <CustomData> <Type>http://kxstudio.sf.net/ns/carla/chunk</Type> <Key>State</Key> <Value> &lt;?xml version=&apos;1.0&apos; encoding=&apos;UTF-8&apos;?&gt; &lt;!DOCTYPE CARLA-PROJECT&gt; &lt;CARLA-PROJECT VERSION=&apos;2.0&apos;&gt; &lt;EngineSettings&gt; &lt;ForceStereo&gt;false&lt;/ForceStereo&gt; &lt;PreferPluginBridges&gt;false&lt;/PreferPluginBridges&gt; &lt;PreferUiBridges&gt;true&lt;/PreferUiBridges&gt; &lt;UIsAlwaysOnTop&gt;false&lt;/UIsAlwaysOnTop&gt; &lt;MaxParameters&gt;200&lt;/MaxParameters&gt; &lt;UIBridgesTimeout&gt;4000&lt;/UIBridgesTimeout&gt; &lt;LADSPA_PATH&gt;/home/falktx/.ladspa:/usr/lib/ladspa:/usr/local/lib/ladspa&lt;/LADSPA_PATH&gt; &lt;DSSI_PATH&gt;/home/falktx/.dssi:/usr/lib/dssi:/usr/local/lib/dssi&lt;/DSSI_PATH&gt; &lt;LV2_PATH&gt;/home/falktx/.lv2:/usr/lib/lv2:/usr/local/lib/lv2&lt;/LV2_PATH&gt; &lt;VST2_PATH&gt;/home/falktx/.vst:/home/falktx/.wineflstudio/drive_c/Program Files (x86)/VstPlugins/:/usr/lib/vst:/usr/local/lib/vst&lt;/VST2_PATH&gt; &lt;GIG_PATH&gt;/home/falktx/.sounds/gig:/usr/share/sounds/gig&lt;/GIG_PATH&gt; &lt;SF2_PATH&gt;/home/falktx/.sounds/sf2:/home/falktx/Personal/Muzyks/Kits/SoundFonts:/usr/share/sounds/sf2&lt;/SF2_PATH&gt; &lt;SFZ_PATH&gt;/home/falktx/.sounds/sfz:/home/falktx/Personal/Muzyks/Kits/SFZ:/usr/share/sounds/sfz&lt;/SFZ_PATH&gt; &lt;/EngineSettings&gt; &lt;!-- QMidiArp Arp --&gt; &lt;Plugin&gt; &lt;Info&gt; &lt;Type&gt;LV2&lt;/Type&gt; &lt;Name&gt;QMidiArp Arp&lt;/Name&gt; &lt;URI&gt;https://git.code.sf.net/p/qmidiarp/arp&lt;/URI&gt; &lt;/Info&gt; &lt;Data&gt; &lt;Active&gt;Yes&lt;/Active&gt; &lt;ControlChannel&gt;1&lt;/ControlChannel&gt; &lt;Options&gt;0x1e1&lt;/Options&gt; &lt;Parameter&gt; &lt;Index&gt;0&lt;/Index&gt; &lt;Name&gt;Attack&lt;/Name&gt; &lt;Symbol&gt;ATTACK&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;1&lt;/Index&gt; &lt;Name&gt;Release&lt;/Name&gt; &lt;Symbol&gt;RELEASE&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;2&lt;/Index&gt; &lt;Name&gt;Random Tick&lt;/Name&gt; &lt;Symbol&gt;RANDOM_TICK&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;3&lt;/Index&gt; &lt;Name&gt;Random Length&lt;/Name&gt; &lt;Symbol&gt;RANDOM_LEN&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;4&lt;/Index&gt; &lt;Name&gt;Random Velocity&lt;/Name&gt; &lt;Symbol&gt;RANDOM_VEL&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;5&lt;/Index&gt; &lt;Name&gt;Output Channel&lt;/Name&gt; &lt;Symbol&gt;CH_OUT&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;6&lt;/Index&gt; &lt;Name&gt;Input Channel&lt;/Name&gt; &lt;Symbol&gt;CH_IN&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;8&lt;/Index&gt; &lt;Name&gt;Restart&lt;/Name&gt; &lt;Symbol&gt;ENABLE_RESTARTBYKBD&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;9&lt;/Index&gt; &lt;Name&gt;Trigger&lt;/Name&gt; &lt;Symbol&gt;ENABLE_TRIGBYKBD&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;10&lt;/Index&gt; &lt;Name&gt;Mute Output&lt;/Name&gt; &lt;Symbol&gt;MUTE&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;11&lt;/Index&gt; &lt;Name&gt;Latch mode&lt;/Name&gt; &lt;Symbol&gt;LATCH_MODE&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;12&lt;/Index&gt; &lt;Name&gt;Octave Mode&lt;/Name&gt; &lt;Symbol&gt;OCTAVE_MODE&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;13&lt;/Index&gt; &lt;Name&gt;Low octave limit&lt;/Name&gt; &lt;Symbol&gt;OCTAVE_LOW&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;14&lt;/Index&gt; &lt;Name&gt;High octave limit&lt;/Name&gt; &lt;Symbol&gt;OCTAVE_HIGH&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;15&lt;/Index&gt; &lt;Name&gt;Index In 1&lt;/Name&gt; &lt;Symbol&gt;INDEX_IN1&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;16&lt;/Index&gt; &lt;Name&gt;Index In 2&lt;/Name&gt; &lt;Symbol&gt;INDEX_IN2&lt;/Symbol&gt; &lt;Value&gt;127&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;17&lt;/Index&gt; &lt;Name&gt;Range In 1&lt;/Name&gt; &lt;Symbol&gt;RANGE_IN1&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;18&lt;/Index&gt; &lt;Name&gt;Range In 2&lt;/Name&gt; &lt;Symbol&gt;RANGE_IN2&lt;/Symbol&gt; &lt;Value&gt;127&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;19&lt;/Index&gt; &lt;Name&gt;Trigger Legato&lt;/Name&gt; &lt;Symbol&gt;ENABLE_TRIGLEGATO&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;20&lt;/Index&gt; &lt;Name&gt;Repeat Mode&lt;/Name&gt; &lt;Symbol&gt;REPEAT_MODE&lt;/Symbol&gt; &lt;Value&gt;1&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;22&lt;/Index&gt; &lt;Name&gt;Defer mute&lt;/Name&gt; &lt;Symbol&gt;DEFER&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;23&lt;/Index&gt; &lt;Name&gt;Pattern Preset&lt;/Name&gt; &lt;Symbol&gt;PATTERN_PRESET&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;24&lt;/Index&gt; &lt;Name&gt;Transport Mode&lt;/Name&gt; &lt;Symbol&gt;TRANSPORT_MODE&lt;/Symbol&gt; &lt;Value&gt;1&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;25&lt;/Index&gt; &lt;Name&gt;Internal Tempo&lt;/Name&gt; &lt;Symbol&gt;TEMPO&lt;/Symbol&gt; &lt;Value&gt;120&lt;/Value&gt; &lt;/Parameter&gt; &lt;CustomData&gt; &lt;Type&gt;http://lv2plug.in/ns/ext/atom#String&lt;/Type&gt; &lt;Key&gt;https://git.code.sf.net/p/qmidiarp#ARPPATTERN&lt;/Key&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/CustomData&gt; &lt;/Data&gt; &lt;/Plugin&gt; &lt;Plugin&gt; &lt;Info&gt; &lt;Type&gt;SFZ&lt;/Type&gt; &lt;Name&gt;percussion_-_xylophone (2)&lt;/Name&gt; &lt;Filename&gt;/home/falktx/Personal/Muzyks/Kits/SFZ/Sonatina Symphonic Orchestra/percussion_-_xylophone.sfz&lt;/Filename&gt; &lt;/Info&gt; &lt;Data&gt; &lt;Active&gt;Yes&lt;/Active&gt; &lt;ControlChannel&gt;1&lt;/ControlChannel&gt; &lt;Options&gt;0x1f0&lt;/Options&gt; &lt;CurrentProgramIndex&gt;1&lt;/CurrentProgramIndex&gt; &lt;CurrentProgramName&gt;percussion_-_xylophone&lt;/CurrentProgramName&gt; &lt;CustomData&gt; &lt;Type&gt;http://kxstudio.sf.net/ns/carla/property&lt;/Type&gt; &lt;Key&gt;CarlaSkinIsCompacted&lt;/Key&gt; &lt;Value&gt;false&lt;/Value&gt; &lt;/CustomData&gt; &lt;/Data&gt; &lt;/Plugin&gt; &lt;!-- 3D Triple Delay (Stereo) --&gt; &lt;Plugin&gt; &lt;Info&gt; &lt;Type&gt;LV2&lt;/Type&gt; &lt;Name&gt;3D Triple Delay (Stereo)&lt;/Name&gt; &lt;URI&gt;http://harrisonconsoles.com/lv2/har_delay/stereo&lt;/URI&gt; &lt;/Info&gt; &lt;Data&gt; &lt;Active&gt;Yes&lt;/Active&gt; &lt;ControlChannel&gt;1&lt;/ControlChannel&gt; &lt;Options&gt;0x0&lt;/Options&gt; &lt;Parameter&gt; &lt;Index&gt;0&lt;/Index&gt; &lt;Name&gt;Wet Mix&lt;/Name&gt; &lt;Symbol&gt;mix&lt;/Symbol&gt; &lt;Value&gt;100&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;1&lt;/Index&gt; &lt;Name&gt;Output Trim&lt;/Name&gt; &lt;Symbol&gt;out_trim&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;2&lt;/Index&gt; &lt;Name&gt;Input High Cut&lt;/Name&gt; &lt;Symbol&gt;hicut&lt;/Symbol&gt; &lt;Value&gt;18000&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;3&lt;/Index&gt; &lt;Name&gt;Input Low Cut&lt;/Name&gt; &lt;Symbol&gt;locut&lt;/Symbol&gt; &lt;Value&gt;100&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;4&lt;/Index&gt; &lt;Name&gt;Left Input&lt;/Name&gt; &lt;Symbol&gt;inputlev_l&lt;/Symbol&gt; &lt;Value&gt;-2.79999995231628&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;5&lt;/Index&gt; &lt;Name&gt;Left Output&lt;/Name&gt; &lt;Symbol&gt;level_l&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;6&lt;/Index&gt; &lt;Name&gt;Left Pan&lt;/Name&gt; &lt;Symbol&gt;pan_l&lt;/Symbol&gt; &lt;Value&gt;-90&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;7&lt;/Index&gt; &lt;Name&gt;Left Delay (16ths)&lt;/Name&gt; &lt;Symbol&gt;delay_16_l&lt;/Symbol&gt; &lt;Value&gt;2&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;8&lt;/Index&gt; &lt;Name&gt;Left Delay (fine)&lt;/Name&gt; &lt;Symbol&gt;delay_fine_l&lt;/Symbol&gt; &lt;Value&gt;11&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;9&lt;/Index&gt; &lt;Name&gt;Center Input&lt;/Name&gt; &lt;Symbol&gt;inputlev_c&lt;/Symbol&gt; &lt;Value&gt;-70&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;10&lt;/Index&gt; &lt;Name&gt;Center Output&lt;/Name&gt; &lt;Symbol&gt;level_c&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;11&lt;/Index&gt; &lt;Name&gt;Center Pan&lt;/Name&gt; &lt;Symbol&gt;pan_c&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;12&lt;/Index&gt; &lt;Name&gt;Center Delay (16ths)&lt;/Name&gt; &lt;Symbol&gt;delay_16_c&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;13&lt;/Index&gt; &lt;Name&gt;Center Delay (fine)&lt;/Name&gt; &lt;Symbol&gt;delay_fine_c&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;14&lt;/Index&gt; &lt;Name&gt;Right Input&lt;/Name&gt; &lt;Symbol&gt;inputlev_r&lt;/Symbol&gt; &lt;Value&gt;-70&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;15&lt;/Index&gt; &lt;Name&gt;Right Output&lt;/Name&gt; &lt;Symbol&gt;level_r&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;16&lt;/Index&gt; &lt;Name&gt;Right Pan&lt;/Name&gt; &lt;Symbol&gt;pan_r&lt;/Symbol&gt; &lt;Value&gt;90&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;17&lt;/Index&gt; &lt;Name&gt;Right Delay (16ths)&lt;/Name&gt; &lt;Symbol&gt;delay_16_r&lt;/Symbol&gt; &lt;Value&gt;2&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;18&lt;/Index&gt; &lt;Name&gt;Right Delay (fine)&lt;/Name&gt; &lt;Symbol&gt;delay_fine_r&lt;/Symbol&gt; &lt;Value&gt;7&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;19&lt;/Index&gt; &lt;Name&gt;Linear Feedback&lt;/Name&gt; &lt;Symbol&gt;linear_feedback&lt;/Symbol&gt; &lt;Value&gt;-17.2999992370605&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;20&lt;/Index&gt; &lt;Name&gt;Linear Damping&lt;/Name&gt; &lt;Symbol&gt;linear_damping&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;21&lt;/Index&gt; &lt;Name&gt;Feedback: LR-C-LR&lt;/Name&gt; &lt;Symbol&gt;feedback_lrc&lt;/Symbol&gt; &lt;Value&gt;-0.0399999991059303&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;22&lt;/Index&gt; &lt;Name&gt;Feedback: L-R&lt;/Name&gt; &lt;Symbol&gt;feedback_lr&lt;/Symbol&gt; &lt;Value&gt;5&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;23&lt;/Index&gt; &lt;Name&gt;Feedback Override&lt;/Name&gt; &lt;Symbol&gt;feedback_all&lt;/Symbol&gt; &lt;Value&gt;0.899999976158142&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;24&lt;/Index&gt; &lt;Name&gt;Modulation&lt;/Name&gt; &lt;Symbol&gt;modulation&lt;/Symbol&gt; &lt;Value&gt;0&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;25&lt;/Index&gt; &lt;Name&gt;BPM (User)&lt;/Name&gt; &lt;Symbol&gt;bpm&lt;/Symbol&gt; &lt;Value&gt;59.4000015258789&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;26&lt;/Index&gt; &lt;Name&gt;BPM Sync&lt;/Name&gt; &lt;Symbol&gt;bpm_sync&lt;/Symbol&gt; &lt;Value&gt;1&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;27&lt;/Index&gt; &lt;Name&gt;Snap&lt;/Name&gt; &lt;Symbol&gt;snap&lt;/Symbol&gt; &lt;Value&gt;1&lt;/Value&gt; &lt;/Parameter&gt; &lt;Parameter&gt; &lt;Index&gt;31&lt;/Index&gt; &lt;Name&gt;Oversample&lt;/Name&gt; &lt;Symbol&gt;oversample&lt;/Symbol&gt; &lt;Value&gt;1&lt;/Value&gt; &lt;/Parameter&gt; &lt;/Data&gt; &lt;/Plugin&gt; &lt;/CARLA-PROJECT&gt; </Value> </CustomData> <CustomData> <Type>http://kxstudio.sf.net/ns/carla/property</Type> <Key>CarlaSkinIsCompacted</Key> <Value>true</Value> </CustomData> </Data> </Plugin> <!-- MIDI Strum --> <Plugin> <Info> <Type>LV2</Type> <Name>MIDI Strum</Name> <URI>http://gareus.org/oss/lv2/midifilter#midistrum</URI> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1e1</Options> <Parameter> <Index>1</Index> <Name>BPM source</Name> <Symbol>bpmsrc</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>2</Index> <Name>BPM</Name> <Symbol>bpm</Symbol> <Value>120</Value> </Parameter> <Parameter> <Index>3</Index> <Name>Strum Direction</Name> <Symbol>mode</Symbol> <Value>2</Value> </Parameter> <Parameter> <Index>4</Index> <Name>Note Collect Timeout [ms]</Name> <Symbol>collect</Symbol> <Value>15</Value> </Parameter> <Parameter> <Index>5</Index> <Name>Strum Duration in Beats</Name> <Symbol>duration</Symbol> <Value>1.39999997615814</Value> </Parameter> <Parameter> <Index>6</Index> <Name>Strum Acceleration</Name> <Symbol>adjspeed</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>7</Index> <Name>Velocity Change</Name> <Symbol>adjvelocity</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>8</Index> <Name>Randomize Acceleration</Name> <Symbol>randspeed</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>9</Index> <Name>Randomize Velocity</Name> <Symbol>randvelocity</Symbol> <Value>0</Value> </Parameter> </Data> </Plugin> <Plugin> <Info> <Type>SFZ</Type> <Name>AcousticGuitar</Name> <Filename>/home/falktx/Personal/Muzyks/Kits/SFZ/AcousticGuitarFREE Samples/AcousticGuitar.sfz</Filename> </Info> <Data> <Active>Yes</Active> <Volume>0.3500588</Volume> <ControlChannel>1</ControlChannel> <Options>0x1f0</Options> <CurrentProgramIndex>1</CurrentProgramIndex> <CurrentProgramName>AcousticGuitar</CurrentProgramName> </Data> </Plugin> </CARLA-PROJECT> system:capture_1 PulseAudio JACK Source:front-left system:capture_2 PulseAudio JACK Source:front-right PulseAudio JACK Sink:front-left system:playback_1 PulseAudio JACK Sink:front-right system:playback_2 Carla-Rack:output_1 system:playback_1 Carla-Rack:output_2 system:playback_2 Carla-2.1/data/presentation/lac2018/projects/4.carxp000066400000000000000000002010051364475620200221360ustar00rootroot00000000000000 false false true false 200 4000 INTERNAL MIDI Through Yes 1 0x3e0 http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted false LV2 MIDI Chord http://gareus.org/oss/lv2/midifilter#midichord Yes 1 0x1e1 1 Filter Channel channelf 0 2 Scale scale 0 3 prime c1 1 4 3rd c3 1 5 5th c5 1 6 6th c6 0 7 7th c7 0 8 octave c8 1 9 9th c9 0 10 11th c11 0 11 13th c13 0 12 bass _8 0 http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted false LV2 Pianoteq 5 http://pianoteq.com/lv2/Pianoteq5 Yes 0.7841 1 0x1e5 0 Sustain Pedal lv2_port_1 0 1 Soft Pedal lv2_port_2 0 2 Sostenuto Pedal lv2_port_3 0 3 Harmonic Pedal lv2_port_4 0 4 Pitch Bend lv2_port_5 0.5 5 Volume lv2_port_6 0.727272748947144 6 Dynamics lv2_port_7 0.393939405679703 7 Diapason lv2_port_8 0.333333343267441 8 Temperament lv2_port_9 0 9 Microtonal lv2_port_10 0 10 Octave Stretch. lv2_port_11 0.231088206171989 11 Unison Width lv2_port_12 0.5 12 Direct Sound Duration lv2_port_13 0.5 13 Hard. Piano lv2_port_14 0.150000005960464 14 Hard. Mezzo lv2_port_15 0.400000005960464 15 Hard. Forte lv2_port_16 0.800000011920929 16 Profile 1 lv2_port_17 0.5 17 Profile 2 lv2_port_18 0.5 18 Profile 3 lv2_port_19 0.5 19 Profile 4 lv2_port_20 0.5 20 Profile 5 lv2_port_21 0.5 21 Profile 6 lv2_port_22 0.5 22 Profile 7 lv2_port_23 0.5 23 Profile 8 lv2_port_24 0.5 24 Hammer Noise lv2_port_25 0.28571429848671 25 Strike Point lv2_port_26 0.551161646842957 26 Character lv2_port_27 0.5 27 Pickup Symmetry lv2_port_28 0 28 Pickup Distance lv2_port_29 0.444444477558136 29 Soft Level lv2_port_30 0.300000011920929 30 Impedance lv2_port_31 0.5 31 Cutoff lv2_port_32 0.5 32 Q Factor lv2_port_33 0.5 33 String Length lv2_port_34 0.5 34 Sympa lv2_port_35 0.5 35 Duplex lv2_port_36 0.499999970197678 36 Quadratic Effect lv2_port_37 0.569824278354645 37 Bounce Switch lv2_port_38 0 38 Bounce Delay lv2_port_39 0.458333343267441 39 Bounce Sync lv2_port_40 0 40 MBSyncS lv2_port_41 0.56521737575531 41 MBVelS lv2_port_42 0.5 42 MBAccel lv2_port_43 0.5 43 MBVelL lv2_port_44 0.5 44 MBHuma lv2_port_45 0.5 45 Eff 1 Switch lv2_port_46 1 46 Eff 1 Param 1 lv2_port_47 0.100000001490116 47 Eff 1 Param 2 lv2_port_48 0.22833614051342 48 Eff 1 Param 3 lv2_port_49 0 49 Eff 1 Param 4 lv2_port_50 0.25 50 Eff 1 Param 5 lv2_port_51 1 51 Eff 1 Param 6 lv2_port_52 0 52 Eff 1 Param 7 lv2_port_53 0 53 Eff 1 Param 8 lv2_port_54 0 54 Eff 2 Switch lv2_port_55 0 55 Eff 2 Param 1 lv2_port_56 0 56 Eff 2 Param 2 lv2_port_57 0 57 Eff 2 Param 3 lv2_port_58 0 58 Eff 2 Param 4 lv2_port_59 0 59 Eff 2 Param 5 lv2_port_60 0 60 Eff 2 Param 6 lv2_port_61 0 61 Eff 2 Param 7 lv2_port_62 0 62 Eff 2 Param 8 lv2_port_63 0 63 Eff 3 Switch lv2_port_64 0 64 Eff 3 Param 1 lv2_port_65 0 65 Eff 3 Param 2 lv2_port_66 0 66 Eff 3 Param 3 lv2_port_67 0 67 Eff 3 Param 4 lv2_port_68 0 68 Eff 3 Param 5 lv2_port_69 0 69 Eff 3 Param 6 lv2_port_70 0 70 Eff 3 Param 7 lv2_port_71 0 71 Eff 3 Param 8 lv2_port_72 0 72 Reverb Switch lv2_port_73 1 73 Reverb Duration lv2_port_74 0.273276418447495 74 Reverb Mix lv2_port_75 0.5 75 Room Dimensions lv2_port_76 0.333333343267441 76 Reverb Pre-delay lv2_port_77 0.52955836057663 77 RevEarl lv2_port_78 0.5 78 Reverb Tone lv2_port_79 0.5 79 Reverb Envelope lv2_port_80 1 80 RevRes lv2_port_81 0.5 81 Limiter Switch lv2_port_82 1 82 Limiter Sharp. lv2_port_83 0.5 83 Limiter Thresh. lv2_port_84 0.519999980926514 84 Limiter Gain lv2_port_85 0.833333313465118 85 Damper Noise lv2_port_86 0.499999970197678 86 Damper Position lv2_port_87 0.668858230113983 87 Last Damper lv2_port_88 0.7109375 88 Pedal Noise lv2_port_89 0.5 89 Key Rel. Noise lv2_port_90 0.5 90 Damping Duration lv2_port_91 0.5 91 Lid Position lv2_port_92 1 92 Output Mode lv2_port_93 0.666666686534882 93 Mic Level Comp. lv2_port_94 1 94 Mic Delay Comp. lv2_port_95 0 95 Head X position lv2_port_96 0.534999966621399 96 Head Y position lv2_port_97 0.5 97 Head Z position lv2_port_98 0.371428549289703 98 Head Diameter lv2_port_99 0.200000002980232 99 Head Angle lv2_port_100 0.5 100 Mic 1 Mic Switch lv2_port_101 1 101 Mic 1 X position lv2_port_102 0.574999988079071 102 Mic 1 Y position lv2_port_103 0.604166686534882 103 Mic 1 Z position lv2_port_104 0.428571432828903 104 Mic 1 Azimuth lv2_port_105 0 105 Mic 1 Elevation lv2_port_106 0.488764733076096 106 Mic 1 Level 1 lv2_port_107 0.837499976158142 107 Mic 1 Delay 1 lv2_port_108 0.5 108 Mic 1 Level 2 lv2_port_109 0.59375 109 Mic 1 Delay 2 lv2_port_110 0.6875 110 Mic 1 Level 3 lv2_port_111 0 111 Mic 1 Delay 3 lv2_port_112 0.5 112 Mic 1 Level 4 lv2_port_113 0 113 Mic 1 Delay 4 lv2_port_114 0.5 114 Mic 1 Level 5 lv2_port_115 0 115 Mic 1 Delay 5 lv2_port_116 0.5 116 Mic 2 Mic Switch lv2_port_117 1 117 Mic 2 X position lv2_port_118 0.574999988079071 118 Mic 2 Y position lv2_port_119 0.5625 119 Mic 2 Z position lv2_port_120 0.428571432828903 120 Mic 2 Azimuth lv2_port_121 0.625 121 Mic 2 Elevation lv2_port_122 0.488764733076096 122 Mic 2 Level 1 lv2_port_123 0.59375 123 Mic 2 Delay 1 lv2_port_124 0.75 124 Mic 2 Level 2 lv2_port_125 0.837499976158142 125 Mic 2 Delay 2 lv2_port_126 0.509375035762787 126 Mic 2 Level 3 lv2_port_127 0 127 Mic 2 Delay 3 lv2_port_128 0.5 128 Mic 2 Level 4 lv2_port_129 0 129 Mic 2 Delay 4 lv2_port_130 0.5 130 Mic 2 Level 5 lv2_port_131 0 131 Mic 2 Delay 5 lv2_port_132 0.5 132 Mic 3 Mic Switch lv2_port_133 0 133 Mic 3 X position lv2_port_134 0.596000015735626 134 Mic 3 Y position lv2_port_135 0.429999977350235 135 Mic 3 Z position lv2_port_136 0.262857139110565 136 Mic 3 Azimuth lv2_port_137 0.75 137 Mic 3 Elevation lv2_port_138 0.5 138 Mic 3 Level 1 lv2_port_139 0.512499988079071 139 Mic 3 Delay 1 lv2_port_140 0.5 140 Mic 3 Level 2 lv2_port_141 0.512499988079071 141 Mic 3 Delay 2 lv2_port_142 0.5 142 Mic 3 Level 3 lv2_port_143 0 143 Mic 3 Delay 3 lv2_port_144 0.5 144 Mic 3 Level 4 lv2_port_145 0 145 Mic 3 Delay 4 lv2_port_146 0.5 146 Mic 3 Level 5 lv2_port_147 0 147 Mic 3 Delay 5 lv2_port_148 0.5 148 Mic 4 Mic Switch lv2_port_149 0 149 Mic 4 X position lv2_port_150 0.465000003576279 150 Mic 4 Y position lv2_port_151 0.531666696071625 151 Mic 4 Z position lv2_port_152 0.251428574323654 152 Mic 4 Azimuth lv2_port_153 0.5 153 Mic 4 Elevation lv2_port_154 0.5 154 Mic 4 Level 1 lv2_port_155 0.512499988079071 155 Mic 4 Delay 1 lv2_port_156 0.5 156 Mic 4 Level 2 lv2_port_157 0.512499988079071 157 Mic 4 Delay 2 lv2_port_158 0.5 158 Mic 4 Level 3 lv2_port_159 0 159 Mic 4 Delay 3 lv2_port_160 0.5 160 Mic 4 Level 4 lv2_port_161 0 161 Mic 4 Delay 4 lv2_port_162 0.5 162 Mic 4 Level 5 lv2_port_163 0 163 Mic 4 Delay 5 lv2_port_164 0.5 164 Mic 5 Mic Switch lv2_port_165 0 165 Mic 5 X position lv2_port_166 0.577000021934509 166 Mic 5 Y position lv2_port_167 0.569999992847443 167 Mic 5 Z position lv2_port_168 0.502857148647308 168 Mic 5 Azimuth lv2_port_169 0.5 169 Mic 5 Elevation lv2_port_170 0.5 170 Mic 5 Level 1 lv2_port_171 0.512499988079071 171 Mic 5 Delay 1 lv2_port_172 0.5 172 Mic 5 Level 2 lv2_port_173 0.512499988079071 173 Mic 5 Delay 2 lv2_port_174 0.5 174 Mic 5 Level 3 lv2_port_175 0 175 Mic 5 Delay 3 lv2_port_176 0.5 176 Mic 5 Level 4 lv2_port_177 0 177 Mic 5 Delay 4 lv2_port_178 0.5 178 Mic 5 Level 5 lv2_port_179 0 179 Mic 5 Delay 5 lv2_port_180 0.5 180 Stereo Width lv2_port_181 0.674031317234039 181 Sound Speed lv2_port_182 0.500000059604645 182 Mute lv2_port_183 0 183 Clavinet Low Mic lv2_port_184 1 184 ClvMicH lv2_port_185 1 185 Equalizer Switch lv2_port_186 1 186 HTinNois lv2_port_187 0.5 187 Blooming Energy lv2_port_188 0 188 Blooming Inertia lv2_port_189 0.5 189 Aftertouch lv2_port_190 0 190 Wall distance lv2_port_191 0 191 Unison Balance lv2_port_192 0.5 192 Condition lv2_port_193 0 193 Condition Seed lv2_port_194 0.12341234087944 194 Rattle Pedal lv2_port_195 0 195 Lute Stop Pedal lv2_port_196 0 196 Celeste Pedal lv2_port_197 0 197 Super Sostenuto lv2_port_198 0 http://lv2plug.in/ns/ext/atom#Chunk urn:juce:stateBinary UHJWSxQAAAJYRlRQpBsAAAoAAAAyMDE3LzExLzA0FwAAAFBpYW5vdGVxIDUuMy4wLzIwMTUwNzE1o9QvMCuNhmEarickC02mrGRsbGFjGwAAdGR0TXIGAAARAAAARDQgRGFpbHkgUHJhY3RpY2UAAAAAGgAAAENvcHlyaWdodCAoYykgMjAxNSBNb2RhcnR0hwAAAFRoaXMgcHJlc2V0IG9mZmVycyBhIGNsZWFuIHNvdW5kLCB5b3UgbWF5IGxpa2UgdG8gdXNlIGl0IGZvciB5b3VyIGRhaWx5IHByYWN0aWNlLiBBbHNvIGEgZ29vZCBzdGFydGluZyBwb2ludCBmb3IgcHJlcGFyaW5nIG5ldyBwcmVzZXRzLgAAAACEAAAAEQAAAEQ0IERhaWx5IFByYWN0aWNlAAAAAIsFAABHUlVVAAAABgAAAAEDwE1UcmsAAAV1AP8CDyBQaWV0IERlIFJpZGRlcgCQKil4gCpVBpArJIMxgCsNaJAkKoIHgCQcMpA3LYEJgDdPgmaQPDGBToA8RVaQKyoFPzuBTIA/bFaQQy8qNyCBGIBDUgQ3K0orJYERkD80CCUlcoA/Wz0lTVKQQisIJiKBOoBCSoEskDkhghSAOUqBICYbNJA+MINMLUKBIoAtSoJCkDI9gVeAMjtCkCsyQoA+bIMlkDItghwvPCCAK2kKMi19L09FkDpPCjVKgVWAOmMbkDs+CYA1IoImO0AEkDw4gSuAPGlHkEFBFDI5gSKAMmZYkDhQgk0kSoJXgDhggSaQNz4GP083gEFFgxYkCSiQMEGBcoA3QB6QK0EqgDA2Zz9dfJAwOFKAKwUcMFKBAJAkUIEggCRjbZA8RYFwgDxmB5A/MYIJQVkGgD9yFJAwQoFggEFveTAFfpBCZoE5gEJSLpBDVFIwLXeAQ2k6kERPgR6AME81RGk5kEVGBCYxhBIwLiiAJm+BaZBDVS+ARVuCQjA0YZBEWgyAQ00AkC1BBTA2gR2AMF0ARGxVkEVeEjAdgRaAMGAtRWktkEZbCSo3UIAtNBxGYzQqYFSQR0wNKzGBeIBHLQmQQSCBcIBBWx2QQiqBSIBCWwkrGUyQQ1UIMkaBMYAyYCVDbIF2kEttgQyAS2OCZZAvPQ1KXoEzgEpFWy9pBpBIPAQwOYFugEhpMDA9gTaQJC+BQ4AkJ2eQQ2OBSIBDRYIpkEJVCjBVcoBCZoEEkENFaoAwIYEEkCstEkZFIYBDY4EmRmkCK0U3kChKBUhbggmASGMZkEZCHYAoSoELRjiCPpA0TQA6RwBATzkiNIFZgDpsWjRsRUBsPSIyGJAoRoF7LlBPgChsgSOQPV+BNIA9WwkuZkWQPkULKUWBYYA+YCSQPC6BV4A8VYFkKUdIkDhLHDA2gx+AOGwhkDdZgRqAMGkyN1sukDVQCyxUgSyALFgvNWANkDdGEDA9gU+AN2AIMEookCZPAjhFgS+AOG9XkDkvggQ8LCCAORxJJlWBJ5A/SwiAPGkPkDBQgSuAMEUukEJgEjAJD4A/aWxCbzswSjqQRWgtMBJjgEVsEjBmV5BEViYqRoFYQ1AzgERNIENjHypmgQWQQkoTK0KBHoBCaVCQQzmBNYBDYEaQRE9/gERpRitYTpBFaAYvU4F/gEVsSC82gRmQMloARmeBO4BGbCuQR0w8gDIYgUKQL0qBL4AvXQRHYz2QSFsHMGaBX4BIbA0wWxKQS28bM2hQgEtsgQczW4FSkEhVADBkgQGASGBlMEIokENpEStMgSCAQ2A7K2ZQkCc4BD9FgTeAJz0NP2aBNZBDVgAra4EggENjbpAnSwI/PBWAK1V9P0ceJ2ZOkCZNAj48gTOAPi07kCo4AEJAboAmUhRCPSUqW1SQRWQTLVUALxSBB4BFaUYvbBQtZoF/kCxqBERqgUOARGktLGmBXJAqYQdCZ4ExgEJsISpvM5ArWgJDVoExgCtvE0NmghqQRmEEQV8EK1g5R18agEZyc0FmPStVH0dggVOQMmcJSmoCQWmCD4BBJ0gyQhVKY4QbkDA6gXAzPiWAMACBcJA3K4EcgDcALzMAHZA8U4F/gDwACpA/U4FsQ1IQgD8AgUJDAB6QSEqBEYBIAHqQSzuCHIBLAAOQT1CBVIBPAIJPkFBjCCtcB0piAjdkBFNggVCASgARUAAAUwBjNwACKwCCVZAkZwIwZAhPYgNIVwRUYxJLXwArYAVRXIELgCsAE1QABCQAC1EAJ0sAMTAAEU8AgQ0kQAArQAAwQAAzQAA3QAA8QAA/QABDQABIQABKQABLQABPQABQQABRQABTQABUQAD/LwBQcnNV4RQAACoAAAACAAAAZDQAAAAACAAAAEdyYW5kIEQ0AAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAEAAAAAAAAA3H8iPgMAAAAKAAAAAACoQQAA6EEAABhCAAAgQgAAJEIAACxCAABgQgAAkkIAAJRCAAC2QgoAAABhpkk/CNJOPwnMaT94/Fw/WUNUPzMOYD8dCIA/jz6zP48+sz+PPrM/AAAAAAAAtkIAAAAAAwAAAAEAAAAAAHBCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACgwAAAoEAAAAAAAwAAAAIAAAAAAKhBAADYQgIAAAAAAAAAAAAAAAAAAAADAAAAAgAAAAAAqEEAANhCAgAAAAAAgD8AAIA/AAAAAIAAAAAAAAAA0gQAAAAAgD8DAAAAAQAAAAAAcEIBAAAAAAAAAAAAAAADAAAAaQAAAAAAEEEAACBBAAAwQQAAQEEAAFBBAABgQQAAcEEAAIBBAACIQQAAkEEAAJhBAACgQQAAqEEAALBBAAC4QQAAwEEAAMhBAADQQQAA2EEAAOBBAADoQQAA8EEAAPhBAAAAQgAABEIAAAhCAAAMQgAAEEIAABRCAAAYQgAAHEIAACBCAAAkQgAAKEIAACxCAAAwQgAANEIAADhCAAA8QgAAQEIAAERCAABIQgAATEIAAFBCAABUQgAAWEIAAFxCAABgQgAAZEIAAGhCAABsQgAAcEIAAHRCAAB4QgAAfEIAAIBCAACCQgAAhEIAAIZCAACIQgAAikIAAIxCAACOQgAAkEIAAJJCAACUQgAAlkIAAJhCAACaQgAAnEIAAJ5CAACgQgAAokIAAKRCAACmQgAAqEIAAKpCAACsQgAArkIAALBCAACyQgAAtEIAALZCAAC4QgAAukIAALxCAAC+QgAAwEIAAMJCAADEQgAAxkIAAMhCAADKQgAAzEIAAM5CAADQQgAA0kIAANRCAADWQgAA2EIAANpCAADcQgAA3kIAAOBCAADiQmkAAAAAAADAAACAvwAAQMAAAEDAAABAQAAAAEAAAMBAAACAPwAAgD8AAMBAAABAQAAAgEAAAADAAABAwAAAgEAAAIBAAACgQAAAwEAAAIBAAAAAgAAAgD8AAADAAACAPwAAQMAAAEDAAABAQAAAgEAAAKBAAACgQAAAQMAAAKBAAAAAgAAAAEAAAEDAAACgQAAAoEAAAEBAAACAQAAAAEAAAADAAACAPwAAgEAAAABAAACgQAAAQEAAAEDAAAAAgAAAgEAAAEDAAAAAgAAAgD8AAIC/AABAwAAAoEAAAEDAAAAAwAAAAIAAAACAAACgQAAAQMAAAADAAACAvwAAQMAAAEDAAACgQAAAAMAAAEDAAABAwAAAgEAAAIA/AABAwAAAgEAAAAAAAACAQAAAgL8AAABAAACgQAAAQMAAAIC/AAAAwAAAwEAAAKBAAABAwAAAQMAAAADAAACAPwAAQMAAAEDAAACAvwAAgL8AAMBAAACAQAAAQMAAAAAAAAAAAAAAgD8AAEDAAAAAwAAAwEAAAEDAAADAQAAAQMAAAEDAAABAwAAAAEAAAAAAAwAAAAIAAAAAAKhBAADYQgIAAAAAAIA/AACAPwAAAAAAANxDAAAAAAEAAAAAAAAABwAAAERlZmF1bHQMAAAAAADIQgAASEMAAJZDAADIQwAA+kMAABZEAAAvRAAASEQAAGFEAAB6RACAiUQAAJZEAQAAAAAA3EM8AAAARQAAAAAAAAAAAAAABwAAAERlZmF1bHQDAAAABAAAAAAAwEEAABBCAABAQgAA2EIEAAAAAACgwAAAgL8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AwAAAAIAAAAAAKhBAADYQgIAAAAAAIA/AACAPwAAAAADAAAAAgAAAAAAqEEAANhCAgAAAAAAgD8AAIA/AAAAAAAAAAADAAAAAQAAAAAAcEIBAAAAAAAAAAAAAAAAAIA/AwAAAAEAAAAAAHBCAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAzczMvc3MzD0BAAAAAAAAAAAAAAAAAAC/AAAAPwAAgD8DAAAAAwAAAAAAqEEAAHBCAADYQgMAAAAAAIA/AACAPwAAgD8AAAAAAAAAAAMAAAACAAAAAACoQQAA2EICAAAAAAAAAAAAAAAAAAAAAACAPwMAAAACAAAAAACoQQAA2EICAAAAAACAPwAAgD8AAAAAAAAgQgMAAAAHAAAAAACoQQAAkEIAAKhCAAC0QgAAwEIAAMhCAADYQgcAAAAAAAAAAAAAAAAAQEAAAMBAAAAQQQAAIEEAADBBAAAAAAAAgD8DAAAAAwAAAAAAqEEAAHBCAADYQgMAAAAAAIA/AACAPwAAgD8AAAAAAwAAAAAAAAABAAAAAAAAAAAAAAABAAAAAwAAAAIAAAAAAAAAAACAPwIAAAAAAAAAAACAPwAAAAADAAAAAgAAAAAAAAAAAIA/AgAAAAAAgD8AAIA/AAAAAAMAAAAEAAAAAAAAACaTST7+fj8/AACAPwQAAAAAAAAAAAAAAAAAgD8AAIA/AAAAAAMAAAACAAAAAAAAAAAAgD8CAAAAAAAAAAAAAAAAAAAAzcwsQAMAAAACAAAAAACoQQAA2EICAAAAAACAPwAAgD8AAAAAAACAvwAAAD8DAAAAAgAAAAAAwEEAAMBCAgAAAAAAgD8AAIA/AAAAAAEAAAABAAAAAQAAAAoAAABTbWFsbCBIYWxsCwAAAG1lZGl1bWhhbGwxAAAAAAAAoEEAAIA/ZmZmPwAAAABCYGU9AAAAAAAAAAAAAAAAAACqQwAAgD8AAIA/BQAAAAAAgD8AAIA/AwAAAF0AAAAAAKhBAACwQQAAuEEAAMBBAADIQQAA0EEAANhBAADgQQAA6EEAAPBBAAD4QQAAAEIAAARCAAAIQgAADEIAABBCAAAUQgAAGEIAABxCAAAgQgAAJEIAAChCAAAsQgAAMEIAADRCAAA4QgAAPEIAAEBCAABEQgAASEIAAExCAABQQgAAVEIAAFhCAABcQgAAYEIAAGRCAABoQgAAbEIAAHBCAAB0QgAAeEIAAHxCAACAQgAAgkIAAIRCAACGQgAAiEIAAIpCAACMQgAAjkIAAJBCAACSQgAAlEIAAJZCAACYQgAAmkIAAJxCAACeQgAAoEIAAKJCAACkQgAApkIAAKhCAACqQgAArEIAAK5CAACwQgAAskIAALRCAAC2QgAAuEIAALpCAAC8QgAAvkIAAMBCAADCQgAAxEIAAMZCAADIQgAAykIAAMxCAADOQgAA0EIAANJCAADUQgAA1kIAANhCAADaQgAA3EIAAN5CAADgQgAA4kJdAAAAAACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD9xPYo/heuRP/YonD/sUZg/j8KVP3E9ij+amZk/j8KVP3sUjj+PwpU/mpmZP7gepT/NzIw/CtejP1K4nj+amZk/16OQP9ejkD+4HqU/KVyPP+F6lD89Cpc/exSOP4/ClT9I4Zo/exSuP65HoT8AAIA/KVyPP1K4nj8AAIA/4XqUP1yPoj/sUZg/XI+iPx+Fqz+kcJ0/MzOzP3sUrj+uR6E/SOGaP3E9ij9cj6I/w/WIP+xRmD/NzIw/FK6HPx+Fiz/sUZg/UrieP3sUjj+uR6E/KVyPP5qZmT9cj6I/CtejP2Zmpj+kcJ0/MzOTP4/CtT9SuJ4/mpmZP5qZuT+4HqU/AACgP83MrD+ambk/pHCdP0jhmj/NzKw/PQqXPylcjz/D9ag/PQqXP6RwnT+amZk/cT2qP0jhmj9SuJ4/UrieP0jhmj97FK4/4XqUP/YonD+kcJ0/AAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAwAAAF0AAAAAAKhBAACwQQAAuEEAAMBBAADIQQAA0EEAANhBAADgQQAA6EEAAPBBAAD4QQAAAEIAAARCAAAIQgAADEIAABBCAAAUQgAAGEIAABxCAAAgQgAAJEIAAChCAAAsQgAAMEIAADRCAAA4QgAAPEIAAEBCAABEQgAASEIAAExCAABQQgAAVEIAAFhCAABcQgAAYEIAAGRCAABoQgAAbEIAAHBCAAB0QgAAeEIAAHxCAACAQgAAgkIAAIRCAACGQgAAiEIAAIpCAACMQgAAjkIAAJBCAACSQgAAlEIAAJZCAACYQgAAmkIAAJxCAACeQgAAoEIAAKJCAACkQgAApkIAAKhCAACqQgAArEIAAK5CAACwQgAAskIAALRCAAC2QgAAuEIAALpCAAC8QgAAvkIAAMBCAADCQgAAxEIAAMZCAADIQgAAykIAAMxCAADOQgAA0EIAANJCAADUQgAA1kIAANhCAADaQgAA3EIAAN5CAADgQgAA4kJdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxmuW8SOFIvRdVB71AGWE80EJ4vV/YST2wNkm93jniudhVqr0uuGu9OCETOtdjgLwW24S9RFIFPaiJjzyCl7C67ryqPZLitb218bo92mxJPUMvoT3kFqu7vQhvvQR/oL3X3K292xWdPYeDQz28BZW9MjXGPNl7sb1R4a68jIzyPHT/wT1b5ja7ZmKPuhApuj3cZ7M9IC6aPaW0Er3O34W8jcm2PFJHqDxKNLo9cuRnvbkagD3/Na291GWdPYkdXTw2jls9rlyQvTrpXb1gYKE8fIdGPRFnCj2OWQM9G/zWO8bUsbxXGHs9ARhlvR18wjwzmiS9TzBSvUlvOr33Tk49bNO2Pcm2J70VS6U9PV6dPUUter0+pHg9leXfvB3hl7wlwYw9fkrZOWb3xz1aWSE9lUvOPAMPnL3ammu9bMGSPSgz8Dwlv7O97aNfPUb8jj2w+UC9AAAAAAMAAAAAAIA/AACAPwAAgD8DAAAAAwAAAAAAqEEAAHBCAADYQgMAAAAAAIA/AACAPwAAgD8AAAAAAwAAAAMAAAAAAKhBAABwQgAA2EIDAAAAAACAPwAAgD8AAIA/AAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAgD8AAIA/AACAPwAAAAAAAIA/AACAPwYAAAAAAIA/mpmZPs3MTD/NzMw/mpmZPggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAgD8AAIA/AACAPwAAAAADAAAAAwAAAAAAqEEAAHBCAADYQgMAAAAAAIA/AACAPwAAgD8AAAAAAwAAAAMAAAAAAKhBAABwQgAA2EIDAAAAAACAPwAAgD8AAIA/AAAAAAMAAAADAAAAAACoQQAAcEIAANhCAwAAAAAAgD8AAIA/AACAPwAAAAABAAAAAQAAAAAAcEIDAAAAAQAAAAAAAAABAAAAAAAAAAAAAABOI9g9AwAAABYAAAAAABBBAACoQQAAwEEAAOBBAADoQQAAAEIAAAhCAAAYQgAAJEIAADBCAABAQgAATEIAAGBCAABwQgAAgEIAAIhCAACQQgAAmEIAAKBCAACoQgAAwEIAANhCFgAAAHh0JD/p5Y8/DGGSP3jylD9Ng5Q/TYOUP02DlD9Ng5Q/6oqRP02DlD9Ng5Q/6oqRP1mwjj/qipE/WbCOP1mwjj9ZsI4/54RcP+eEXD9+JEo/2kMtPzGS8j4AAAAAAQAAAAAAAAABAAAAMzMzP2Zmpj8BAAAAAQAAAAEAAABmZmY/zcyMPwEAAAAAAAAAAADwQgAAAAAOAAAAAAAAP83MzD3NzEw+AAAAPwQAAAACAAAAAwAAAAQAAAABAAAAAgAAAAcAAAABAAAAAAAAAA4AAAAQAAAAAAAAAM3MzD0AAIA/AAAAAAAAAL8AAHBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAOAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAADgAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAIA/AABAwQAAAAACAAAAAwAAAAEAAAAFAAAABAAAAAEAAAADAAAAAADAPwAAoD8AAMA/AABhwxxugcAAAAAABQAAAAAAAAAAABDBAADAwgAAwMIAAMDCBQAAAAAAAACPwvU8AAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAEAAAAAQAAAAMAAAAAAMA/AABAPwAAwD8AADRCHG6BwAAAAAAFAAAAAAAQwQAAAAAAAMDCAADAwgAAwMIFAAAACtcjPaabxDoAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAQAAAAAAAAAAwAAAI/C9T89Cle/H4VrPwAAtEIAAAAAAAAAAAUAAAAAAEDBAABAwQAAcMIAAHDCAABwwgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAABAAAAAAAAAADAAAAMzMzv1yPwj6uR2E/AAAAAAAAAAAAAAAABQAAAAAAQMEAAEDBAABwwgAAcMIAAHDCBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAEAAAAAAAAAAMAAAC4HsU/PQpXP65H4T8AAAAAAAAAAAAAAAAFAAAAAABAwQAAQMEAAHDCAABwwgAAcMIFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAMAAAAzMzM/AAAAAGZmpj8AAJBBAAAAAAAAAAAAAAAA http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted false INTERNAL Carla-Rack (no midi out) Yes 1 0x3e0 http://kxstudio.sf.net/ns/carla/chunk State <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE CARLA-PROJECT> <CARLA-PROJECT VERSION='2.0'> <EngineSettings> <ForceStereo>false</ForceStereo> <PreferPluginBridges>false</PreferPluginBridges> <PreferUiBridges>true</PreferUiBridges> <UIsAlwaysOnTop>false</UIsAlwaysOnTop> <MaxParameters>200</MaxParameters> <UIBridgesTimeout>4000</UIBridgesTimeout> <LADSPA_PATH>/home/falktx/.ladspa:/usr/lib/ladspa:/usr/local/lib/ladspa</LADSPA_PATH> <DSSI_PATH>/home/falktx/.dssi:/usr/lib/dssi:/usr/local/lib/dssi</DSSI_PATH> <LV2_PATH>/home/falktx/.lv2:/usr/lib/lv2:/usr/local/lib/lv2</LV2_PATH> <VST2_PATH>/home/falktx/.vst:/usr/lib/vst:/usr/local/lib/vst</VST2_PATH> <GIG_PATH>/home/falktx/.sounds/gig:/usr/share/sounds/gig</GIG_PATH> <SF2_PATH>/home/falktx/.sounds/sf2:/home/falktx/Personal/Muzyks/Kits/SoundFonts:/usr/share/sounds/sf2</SF2_PATH> <SFZ_PATH>/home/falktx/.sounds/sfz:/home/falktx/Personal/Muzyks/Kits/SFZ:/usr/share/sounds/sfz</SFZ_PATH> </EngineSettings> <!-- QMidiArp Arp --> <Plugin> <Info> <Type>LV2</Type> <Name>QMidiArp Arp</Name> <URI>https://git.code.sf.net/p/qmidiarp/arp</URI> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1e1</Options> <Parameter> <Index>0</Index> <Name>Attack</Name> <Symbol>ATTACK</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>1</Index> <Name>Release</Name> <Symbol>RELEASE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>2</Index> <Name>Random Tick</Name> <Symbol>RANDOM_TICK</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>3</Index> <Name>Random Length</Name> <Symbol>RANDOM_LEN</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>4</Index> <Name>Random Velocity</Name> <Symbol>RANDOM_VEL</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>5</Index> <Name>Output Channel</Name> <Symbol>CH_OUT</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>6</Index> <Name>Input Channel</Name> <Symbol>CH_IN</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>8</Index> <Name>Restart</Name> <Symbol>ENABLE_RESTARTBYKBD</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>9</Index> <Name>Trigger</Name> <Symbol>ENABLE_TRIGBYKBD</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>10</Index> <Name>Mute Output</Name> <Symbol>MUTE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>11</Index> <Name>Latch mode</Name> <Symbol>LATCH_MODE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>12</Index> <Name>Octave Mode</Name> <Symbol>OCTAVE_MODE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>13</Index> <Name>Low octave limit</Name> <Symbol>OCTAVE_LOW</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>14</Index> <Name>High octave limit</Name> <Symbol>OCTAVE_HIGH</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>15</Index> <Name>Index In 1</Name> <Symbol>INDEX_IN1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>16</Index> <Name>Index In 2</Name> <Symbol>INDEX_IN2</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>17</Index> <Name>Range In 1</Name> <Symbol>RANGE_IN1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>18</Index> <Name>Range In 2</Name> <Symbol>RANGE_IN2</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>19</Index> <Name>Trigger Legato</Name> <Symbol>ENABLE_TRIGLEGATO</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>20</Index> <Name>Repeat Mode</Name> <Symbol>REPEAT_MODE</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>22</Index> <Name>Defer mute</Name> <Symbol>DEFER</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>23</Index> <Name>Pattern Preset</Name> <Symbol>PATTERN_PRESET</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>24</Index> <Name>Transport Mode</Name> <Symbol>TRANSPORT_MODE</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>25</Index> <Name>Internal Tempo</Name> <Symbol>TEMPO</Symbol> <Value>120</Value> </Parameter> <CustomData> <Type>http://lv2plug.in/ns/ext/atom#String</Type> <Key>https://git.code.sf.net/p/qmidiarp#ARPPATTERN</Key> <Value>&gt;0</Value> </CustomData> </Data> </Plugin> <Plugin> <Info> <Type>SFZ</Type> <Name>concert_harp</Name> <Filename>/home/falktx/Personal/Muzyks/Kits/SFZ/Sonatina Symphonic Orchestra/concert_harp.sfz</Filename> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1f0</Options> <CurrentProgramIndex>1</CurrentProgramIndex> <CurrentProgramName>concert_harp</CurrentProgramName> </Data> </Plugin> </CARLA-PROJECT> http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted false INTERNAL Carla-Rack (no midi out) (2) Yes 1 0x3e0 http://kxstudio.sf.net/ns/carla/chunk State <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE CARLA-PROJECT> <CARLA-PROJECT VERSION='2.0'> <EngineSettings> <ForceStereo>false</ForceStereo> <PreferPluginBridges>false</PreferPluginBridges> <PreferUiBridges>true</PreferUiBridges> <UIsAlwaysOnTop>false</UIsAlwaysOnTop> <MaxParameters>200</MaxParameters> <UIBridgesTimeout>4000</UIBridgesTimeout> <LADSPA_PATH>/home/falktx/.ladspa:/usr/lib/ladspa:/usr/local/lib/ladspa</LADSPA_PATH> <DSSI_PATH>/home/falktx/.dssi:/usr/lib/dssi:/usr/local/lib/dssi</DSSI_PATH> <LV2_PATH>/home/falktx/.lv2:/usr/lib/lv2:/usr/local/lib/lv2</LV2_PATH> <VST2_PATH>/home/falktx/.vst:/usr/lib/vst:/usr/local/lib/vst</VST2_PATH> <GIG_PATH>/home/falktx/.sounds/gig:/usr/share/sounds/gig</GIG_PATH> <SF2_PATH>/home/falktx/.sounds/sf2:/home/falktx/Personal/Muzyks/Kits/SoundFonts:/usr/share/sounds/sf2</SF2_PATH> <SFZ_PATH>/home/falktx/.sounds/sfz:/home/falktx/Personal/Muzyks/Kits/SFZ:/usr/share/sounds/sfz</SFZ_PATH> </EngineSettings> <!-- QMidiArp Arp --> <Plugin> <Info> <Type>LV2</Type> <Name>QMidiArp Arp</Name> <URI>https://git.code.sf.net/p/qmidiarp/arp</URI> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1e1</Options> <Parameter> <Index>0</Index> <Name>Attack</Name> <Symbol>ATTACK</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>1</Index> <Name>Release</Name> <Symbol>RELEASE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>2</Index> <Name>Random Tick</Name> <Symbol>RANDOM_TICK</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>3</Index> <Name>Random Length</Name> <Symbol>RANDOM_LEN</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>4</Index> <Name>Random Velocity</Name> <Symbol>RANDOM_VEL</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>5</Index> <Name>Output Channel</Name> <Symbol>CH_OUT</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>6</Index> <Name>Input Channel</Name> <Symbol>CH_IN</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>8</Index> <Name>Restart</Name> <Symbol>ENABLE_RESTARTBYKBD</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>9</Index> <Name>Trigger</Name> <Symbol>ENABLE_TRIGBYKBD</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>10</Index> <Name>Mute Output</Name> <Symbol>MUTE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>11</Index> <Name>Latch mode</Name> <Symbol>LATCH_MODE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>12</Index> <Name>Octave Mode</Name> <Symbol>OCTAVE_MODE</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>13</Index> <Name>Low octave limit</Name> <Symbol>OCTAVE_LOW</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>14</Index> <Name>High octave limit</Name> <Symbol>OCTAVE_HIGH</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>15</Index> <Name>Index In 1</Name> <Symbol>INDEX_IN1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>16</Index> <Name>Index In 2</Name> <Symbol>INDEX_IN2</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>17</Index> <Name>Range In 1</Name> <Symbol>RANGE_IN1</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>18</Index> <Name>Range In 2</Name> <Symbol>RANGE_IN2</Symbol> <Value>127</Value> </Parameter> <Parameter> <Index>19</Index> <Name>Trigger Legato</Name> <Symbol>ENABLE_TRIGLEGATO</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>20</Index> <Name>Repeat Mode</Name> <Symbol>REPEAT_MODE</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>22</Index> <Name>Defer mute</Name> <Symbol>DEFER</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>23</Index> <Name>Pattern Preset</Name> <Symbol>PATTERN_PRESET</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>24</Index> <Name>Transport Mode</Name> <Symbol>TRANSPORT_MODE</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>25</Index> <Name>Internal Tempo</Name> <Symbol>TEMPO</Symbol> <Value>120</Value> </Parameter> <CustomData> <Type>http://lv2plug.in/ns/ext/atom#String</Type> <Key>https://git.code.sf.net/p/qmidiarp#ARPPATTERN</Key> <Value>-0</Value> </CustomData> </Data> </Plugin> <Plugin> <Info> <Type>SFZ</Type> <Name>percussion_-_xylophone</Name> <Filename>/home/falktx/Personal/Muzyks/Kits/SFZ/Sonatina Symphonic Orchestra/percussion_-_xylophone.sfz</Filename> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1f0</Options> <CurrentProgramIndex>1</CurrentProgramIndex> <CurrentProgramName>percussion_-_xylophone</CurrentProgramName> </Data> </Plugin> <!-- 3D Triple Delay (Stereo) --> <Plugin> <Info> <Type>LV2</Type> <Name>3D Triple Delay (Stereo)</Name> <URI>http://harrisonconsoles.com/lv2/har_delay/stereo</URI> </Info> <Data> <Active>Yes</Active> <ControlChannel>1</ControlChannel> <Options>0x1</Options> <Parameter> <Index>0</Index> <Name>Wet Mix</Name> <Symbol>mix</Symbol> <Value>100</Value> </Parameter> <Parameter> <Index>1</Index> <Name>Output Trim</Name> <Symbol>out_trim</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>2</Index> <Name>Input High Cut</Name> <Symbol>hicut</Symbol> <Value>18000</Value> </Parameter> <Parameter> <Index>3</Index> <Name>Input Low Cut</Name> <Symbol>locut</Symbol> <Value>100</Value> </Parameter> <Parameter> <Index>4</Index> <Name>Left Input</Name> <Symbol>inputlev_l</Symbol> <Value>-2.79999995231628</Value> </Parameter> <Parameter> <Index>5</Index> <Name>Left Output</Name> <Symbol>level_l</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>6</Index> <Name>Left Pan</Name> <Symbol>pan_l</Symbol> <Value>-90</Value> </Parameter> <Parameter> <Index>7</Index> <Name>Left Delay (16ths)</Name> <Symbol>delay_16_l</Symbol> <Value>2</Value> </Parameter> <Parameter> <Index>8</Index> <Name>Left Delay (fine)</Name> <Symbol>delay_fine_l</Symbol> <Value>11</Value> </Parameter> <Parameter> <Index>9</Index> <Name>Center Input</Name> <Symbol>inputlev_c</Symbol> <Value>-70</Value> </Parameter> <Parameter> <Index>10</Index> <Name>Center Output</Name> <Symbol>level_c</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>11</Index> <Name>Center Pan</Name> <Symbol>pan_c</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>12</Index> <Name>Center Delay (16ths)</Name> <Symbol>delay_16_c</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>13</Index> <Name>Center Delay (fine)</Name> <Symbol>delay_fine_c</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>14</Index> <Name>Right Input</Name> <Symbol>inputlev_r</Symbol> <Value>-70</Value> </Parameter> <Parameter> <Index>15</Index> <Name>Right Output</Name> <Symbol>level_r</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>16</Index> <Name>Right Pan</Name> <Symbol>pan_r</Symbol> <Value>90</Value> </Parameter> <Parameter> <Index>17</Index> <Name>Right Delay (16ths)</Name> <Symbol>delay_16_r</Symbol> <Value>2</Value> </Parameter> <Parameter> <Index>18</Index> <Name>Right Delay (fine)</Name> <Symbol>delay_fine_r</Symbol> <Value>7</Value> </Parameter> <Parameter> <Index>19</Index> <Name>Linear Feedback</Name> <Symbol>linear_feedback</Symbol> <Value>-17.2999992370605</Value> </Parameter> <Parameter> <Index>20</Index> <Name>Linear Damping</Name> <Symbol>linear_damping</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>21</Index> <Name>Feedback: LR-C-LR</Name> <Symbol>feedback_lrc</Symbol> <Value>-0.0399999991059303</Value> </Parameter> <Parameter> <Index>22</Index> <Name>Feedback: L-R</Name> <Symbol>feedback_lr</Symbol> <Value>5</Value> </Parameter> <Parameter> <Index>23</Index> <Name>Feedback Override</Name> <Symbol>feedback_all</Symbol> <Value>0.899999976158142</Value> </Parameter> <Parameter> <Index>24</Index> <Name>Modulation</Name> <Symbol>modulation</Symbol> <Value>0</Value> </Parameter> <Parameter> <Index>25</Index> <Name>BPM (User)</Name> <Symbol>bpm</Symbol> <Value>59.4000015258789</Value> </Parameter> <Parameter> <Index>26</Index> <Name>BPM Sync</Name> <Symbol>bpm_sync</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>27</Index> <Name>Snap</Name> <Symbol>snap</Symbol> <Value>1</Value> </Parameter> <Parameter> <Index>31</Index> <Name>Oversample</Name> <Symbol>oversample</Symbol> <Value>1</Value> </Parameter> </Data> </Plugin> </CARLA-PROJECT> http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted false LV2 MIDI Strum http://gareus.org/oss/lv2/midifilter#midistrum Yes 1 0x1e1 1 BPM source bpmsrc 1 2 BPM bpm 120 3 Strum Direction mode 2 4 Note Collect Timeout [ms] collect 15 5 Strum Duration in Beats duration 1 6 Strum Acceleration adjspeed 0 7 Velocity Change adjvelocity 0 8 Randomize Acceleration randspeed 0 9 Randomize Velocity randvelocity 0 http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted false SFZ AcousticGuitar /home/falktx/Personal/Muzyks/Kits/SFZ/AcousticGuitarFREE Samples/AcousticGuitar.sfz Yes 0.1326648 1 0x1f0 1 AcousticGuitar http://kxstudio.sf.net/ns/carla/property CarlaSkinIsCompacted false system:capture_1 PulseAudio JACK Source:front-left system:capture_2 PulseAudio JACK Source:front-right PulseAudio JACK Sink:front-left system:playback_1 PulseAudio JACK Sink:front-right system:playback_2 Carla:audio-out1 system:playback_1 Carla:audio-out2 system:playback_2 Carla-2.1/data/presentation/sonoj2017.odg000066400000000000000000003174411364475620200202020ustar00rootroot00000000000000PKYdK.++mimetypeapplication/vnd.oasis.opendocument.graphicsPKYdKPPThumbnails/thumbnail.pngPNG  IHDRнEPLTE    $ (%( &!*$0 &#,&1)4-9+6-:0=1="16#4<(6<*9>3@7H9J5B8F;J>P#6A#9D =L+H >P1>C@N@REYI\K`!@N.@G,AJ"BS$FX&I[*DP(GY(K]2@E4EK4HO8FL;IM2IS2O]QW=RY%Ma)Na"Pf$Tk$Xo+Qd,Ui.Xm&Zs&^x-[q)_x3Sa0Vj0Yn;Xf1\r'b})a|3`v5cz6h~8f~8hANOANRCQUETYGX]ITUJVYMZ\Q\]M]aQ^`UbcUfiVhlXccYfh]jjbmkbopepniqnfrrfvxjtroxunyxpwsqyus|yx}wx{+e+i-k.p.r7f6h8g8j0q0t1w1x2z4s~z}56789:<=>t{~@@ACDFGHGHJKLNõǸƷǸʺξоݱܘNIDATxu {[.7ؖ,k{h-Q$:l\3S)mCЏP(-Ü^*.:-H$(RhBIﵞ-9+Il˶{^z;pNFolc<lW*m]'4FTJZnT>Jb)}ϱ]׶}\p<|##KM߲K.v?HgOO_oſ!SxˤK:dv݌6k{?[i[ZNjvɕVZU*ΗxP B10r9NΕW4,"VZv:eOely Ķda|L 2 d$aR.t"]T&)$ 0om4uq68m.1 wj\X:뇁 @h@aEOhtb,\^:@`Ո_ZibL r,p7'ޥe@JM{R.-mH1,^L+@jbB5'ܳX%%eE8~0`$`8q_tڇNy4Z\%,ח9^iG/,TKQa |JׯFS0-dim 0eN2[J%sW1P0Irl'uNg}m}k"}74<6:k;:M Yq[B0 kj0'RPJ d@S` ,apS梧F?g(ge`)XDoRd8x^xNaK~p}?t 6:u\cSt㳫pqV+ڢ^|jPڞe ,xBI;"07> =]tv*;A5*HK;{;? Lfh5qc0`:0d@1&P_.e@CXTQX[$j"8}2LpC cY\|5~p7DO ~z01.>ecd`X?VwZkƑk6iNPGXTd@"" Vid@5^D26=CY( M}L`0Ǵ~Dؗ*/"9qh%.SpE)ʀh}ka@}HІTM*e*"rVJ`6`ѐ_ݠPL K/d yiSҰiiXa &p&Y!;,B2'D4Mnv@ r\?>2/|U4@ X]zgaZki49X&AuRB۠ D q,z-/@ xC_ӒM&%Oչd0`6! ]~j9dLjfz #@ hAZ?lh$ MMHN / cjO@ g X<R+䋔om6)2 %bp rq?;m 24 2 M@2`^F` hV!Vh?-UEE  Xx0a 0C  p&A8k2;3w @+0! ةieM5t^}_kXáX5 ^ny~,PT+|&`!Z}j/q(8BVz,]} e65 Q@CWL[J/fC#f!qA pcp c4:ԀVV*aT\\i O0S y ;Gf욝2 q 4\|&c' ``M3\6]&`a"(CIEӪ7G\`0r18^Z! PuBq": O6B$ HI S/ʦ4ó2i[6f2>  $SYxw{"dM=em`D___ې\@h7Au @Rd@}2ERP "`0@ ȥ|pSDC+ @it L",&І18Z6KH7XX 嘆+u~~UWGl@0y(T:|AԺ~}Ҕ&" 0򧳮y/`<5ppJjPoam;\Bn 1h2X5 ; ؄’|O!a[( 4L.#_`%&2n".㛶'3F7g q0T?A/(zD ! -t #Ìi@H!#- X*SlepcZ糬0`2>Mՙ1 E,,+bƚFa;@$U8?bQq5^RPj8D0—N[)c0@uc:LSPY?)Z z>~`@d`9>rX}U0RbFV:k  .ȹ" X͔`f8 )rZE lq-00T`eܳkܬ`\n t^llxO/X @kÄ8rA ..,hI(^@TE&|&D.ZZY RH49|O$o2!ddy * sCGX#X^ޣF0//)G4^M "IY/ "D 'l@p (/)XfMG$4yp=}8TЦM1e2R\]l8hH0  05h>LbP1 zA"h֏?لXcR[?ئDΙ@O4y"K ;آ \.u6KK˝#GliRo/0A)*!L`* Z܊IX >da"0`KCpFggt_A*䖛֭C߄4h5Нusƴ~:Ru 9({"n*̢(Њ4KrkHpX[X$| %$V`bV8J[I,>&(.T>|4?S# (,I0|9 B_1A:cQmZ&H& x!1 { pd8Y uAma"@rpA6r!CÀ{M XW֏|~J[ hX0P1t&`Bs] G5q\$LWerisc\ @lu]K`QS5a |& cqrQ\5VTeN5Z?xa<Hcb =a.0`7F4`+/:FK,ՀO@ f 6,pZ$s0yX6#M9@\(!m uẂ@֋ (~CJ?4 0[c $Ed(ToR@OJMn7H֏_YEp S> "@*@d (Xaמ*bfuWbw@Qo0Wn 065-d@LtxlǢ8 ( $h i[dmm*p"hy Эt7a+񶚀#( 9BC?חZ]OÝk2![eP9ƗLn֙朚@6Ua [p$nR ț.?@dL@SMzZjr_>,OMJ ;~"VE2G dX(U\h謑t1}@k}H` hE X.Ѣ+F`%,K #,$ pE(`S̔0*Ep|;E=ÕbLʾVL>_e0tM.k P/ `2`V&3؄nvi?VdN:Z[M`   Ҙ€Tbvv:\?dOf,|CWU@aX5Ux1T *HpF|3d?XUDn`OI P@6kR@Y 8y.>XTEUI/ mr53T5PwCFBC_ckk#aZʶY Xc0`j2359JL=_9lR p F^c&2D4:v}iAXj0^[LZUhMRtgD$ޠo0p +#Nv>쪊0LӉ~/* {t)G"1 QiNPnKIi?. `@CJiJ8iސ6Q6KSj"SP !LL@I:, )0dOΥ?gNE)Y&b( c6~kF  a|PjRjW j F%i`@R[F_nq\/rkL;Df%TX"&*ڰa׀W~PW#g؀0T'"Y\v)|Pl?Fc`\B3' ax">ШU.56V%&* y>bTjhYܘfCUf=29eZ;2 fe`Ol]T(*x!obp1 bp8=D|?QBu# HpMd M@H N0%`@'a Pf /6v^ KKe@Po_>2H(#5+1̥$-StYn5HxRl2n!T8- "ax@aBhzPS]vش <Urʮf2ETݫe2g`}1wyCEޚ{hSydP " F?@v!^tb%Vq#"d 0-nGQ?8>HM -AϬ SY @1,WK5XP"d0nճ 5$T*Q@!% r_!h \V`Q/oWVP+E帹 cuu<$X K*[08sx$DM=oI(r4JȆtzH `{C<l/Si u 0 tm^XB7dyh@C~%\k f- *<4E .,G Pnw6BS n?Vi 4Uj@^Y0l&C<5 a/>S~ZJU,bS@4rYR'+1bGN\ILȡ(!@|?>h2D26xFM@f'+.) EL)l9MΨ >^\QaxQ[1p1,l"Zq+$" ;h2UW "KEk$}k_;z8+77^ӵv^ontLxFL@ !X?&PVU\Ņ"캈X ^_; | /<$f2ATTk0=6'gȀ W/;{nǧ|/ .=}f0{HOD5reӕ"Wp!_[F<ňGfhܠnXXP+@H0mD<"j+uT] . "Jrn ym^wzW}w|K7OmH7I@'p02<aߋzy$a@L ZeK#@59 @k* E=" x'ͱ~W]o߼GW~>.womq=kg4Wr)32 =np R$ZW`qKѨ/*!b}UQ9--E<`>VJX]Oͳ^`$(lq[z~K{owKf#=ޗl"̛%d# & :IuJK# "{T(F7<ymjFHvN,APR.("4Xt(+|vjٜ;ugﯧȀ;3^})0-5 H0 ,9j#m?au-@6WFT+$lT/FkĚ$WT՚`R0 M<P D&WϺ/_)??NoǎWw;h>Y zM`U}F|G@ p Aa/WxYA7U aX Uɣh1bԀO%dO$UP8|M/tWAWZ 5ar7lf BрAn,%PS6T@PkVR<+ iBiy/I_^doW5#JKƞ2@!j0+zvH/!o9*<秦+'DFD|B/ gXpTlz #0UG%D]+C}X(WED@H"$2 Hx€)Wf>} %#ۑP,Sb@>UaArn64aT.@f`&C[Q!@Xh~1ڮa#~$"XσR>2 dfH9smOq&|7XA+rj4dH/hduqڛV( @I X+2O*Ȃ"*#bMODR(|y?<st7ݤ"&G^S `RS L?&@/T*|}^.$r;F/]A)c @U D"G`/jd AU]`(+kZ 1cBT,SAQ @NL Z pH6 T`lZA Kqvضen0T>0 4*/|^#^@5LQFM @H8(҆^0`cX ҐZHZX$&@+ b(W$AF!(H P4ݾ  {?ܒ6Sdd~:$D IUؓyx)Ex+(׵Ò' M(`?"˵޸D|LYcRL"RZD 0@1A<  Eb3y(G|q9,[&0"RHL-鏴BRv&l7,z=#&`u"XA>bAW>9 *ڑ3bM<(!40 F̑N3tYeis|YR`=?P=) 績pt9iIO0S/R2?ɇ @ HWϏj\~αc}. 2Ru?, t! `Fc+ʀyрP=BNsv( #XÒ@뾀NX- ݘM)#A65x Fsp, Ba`YF Ze!Ք4DP<~x!DŽrqb7GH3UeB B %O쩬tI8B"arKLpq%";y&t T/fG2( ^50S bbݍƜPk$HjEbd3HbA)r o"iJA0pnne2_"Az/'Bjt8 HDP2 ,Ph_!j c^Yod |X#ʦ͈K Ք}"1axq֝{ V\gG~珺5l6CH!03{C@ҏ8.5Q H [J`y oVrg}},VҼoK)U" > Ďd\7}xhóz4tƋ]o||e/@~&-M%z~k߲x^pxg`@r $a]IWV(gDOkA\28ŗQ)a (WJ fD9}>f`0=nxpqy;,fp~s!6>1s7W_~NH4Ciwȡ({&+}I[M5"q) a`7MHjrS2 OCD3_| %,ؘ7ꏽ~2Z0lW8/'|5߸tY|=+?=:{(B_ш<- h[WU$aʚjxY;Վ- ЋrPjtkz hKQ8˶` -C{a^'nv/o'/g";;{t{>x?Kz":X2 4 5 \i5Tpb@sy _P,} ({CBiD 6~ep={۟9g{7߼@p{{ _7ot9A^t9À+ @ZVC:enbqGxχ0)p҄bIdȀ|C}VYN)~#bM7_][0s_ nPvny? ;?NN}7.&oyo`h〒ho5$x5 0~פA!yD k5$ʖϱ H ߾;8= {iŷ޻{v~7x㥋oz- -m@ ;TɀCí 4{5՗vB;$S(|% B]~ 3W 5z\>g` HӽAQ~2︀]9 x OEP4 A!psl\yב)r#j[Gxo7Qr4b#ab_c&D AT mtMne.xr7| IU7չ7xM_ḒW~NV5>yk˙ O kW_oHIGhraoωZM+]@17, ui H0 gxi; ؊]d7pqL0Kf'y`2XyX3RCVAҙ ꎐM@^hj L`d\i  R!d (%'|T` H?ˆ(@3ந41tdAmC`ʹS# ٌ "ö27x@3I%BPibR]j0C[  _ǼH'Lr/z_6RNŤ@)!F$~# XV3-.JIt3|fc|@KbʀT0n-T} Pjc /BRWh׏yO(4VQ$+na#X'NIr'uDzS/5ȳ7 'kF' t$ `NŃ,΂qʢx0U\it_ Lݐvn׍fĂkf̿<& Q`(<) tV !يKHoe(1sdJ(Sa@&8uG2g C3Cΐ-;cTzEQWM@d7rArΌ||9 4ucSAA2anN2 q"+{J1׌tQՃ eAX$& ^ #mұh, Ǧ SYP D}0(DRs|HdJ{;ܽYpH} &%V 0DY9 k] fJBҜ0r {CƗ%UzH5^@fH-{: 2@L@) X֘\G. ⭠8Ź抌YWQVϚpsq}c:WB}x= e=$ Y1~$^.HϬr-/ Ҏ4q-$ ,,P%um57z,t:@ <9^!`YL"ܕ C\+& m*NSNrhL͙S`)2&  Qȹ~p vz{m&@hcS(92[j14 a`&=8NpIA!z:WU81iFcI=a5 p>4^C$(@`1*Cj mMb3DlXd7 nķJ>Wz3~k߃G\]>X93<+9*.f$n[ɘi E}E -dj{K4-4qS_ko9}Fx$9 L7R9@bصAa[w t / ]mNƈTO7 #COaRy:1U0apEQݠ2оbVsN~N.n&Jy @|;a_еr-œV+ːl8PtJgTψ`F'^* A2L@0ir/p$t3nLVX;9T7mŽpaAo6 C97g~W>eCTl2 z>zHxI$7I>T+uG:+2XNAeڻ|Ffa1wrď=t1q1 x:s?~‰>'O?؍d 'Nv=M#'PbhQ"AŽjn,4t'@#t2 9OWr_$O~^Ai}Пu[׽ x xzCdڽ'yEy~SO~Խ;Lv") M@5TȀ B[Hp Á)3ɝ!V2 d8x_=S?u? {/ď3>}詧:y!?.#X`}{=KpOe#/xB`a;Pxg0S 0 (Vhb yGZG66d2 5{F,T\RN(d TmϺ wwScO8O;~t??&'BǞ>y>'_9~K?}@?O5Aƈ\ D R JmA@lS)0U\w)z[Hhc?~*vsJǎ?=뉟3O=SO>jn'ǽG=X{ڵ}|z>ݏ<缻yرsDӪ0$0Ĥ"$yehrk!یc! <`$<7!O6S~|jdk rz(G XV7 uDGgW4 P  (VdO{ 8Ī 71Nbf\똹綂 C <30 k&YJ#.Fr'-3gϓʴT;#w<:.:-3`%BZԝ!)kӬl?1"٪ƈުh@jG/3#`h(9= m4GS}(:(+߯7> u[ XNmcfCG\<)J& :ӎ45do^ ΐޫNgmL@o5#C\Gp\ϵ p+{||!,ՀS x! 5ɀmNAiRrC.魋aؐ+^Y-QXi[{euIed$n:5'헆Gוaf)'H()!XǗ<鷙ha 4)en(`rͼ GFsD*l!F d&Pb}X+6H'ys`܈v;G=cV1=ҏ_LkA@ZXi2?7Y>q'b$Pƭp(*^&GR{.1nIb)#WZsPa冶Ȭm \{)F33z cFJE[=À 5l}9Nq C2:'[o,ĔeƒY@97- xby)U [#p@+ 6InKLYf>E5pȀaM"гQ%Qd4촥òeZx%qcoyrdF9/,2s1i'\0 *%zV@.Tv DT>(}Z[ IC$*S>!ɠX'c!)@4@ -7(hrrMz}Ah4J:tIL T : rދǬyzƚQ2tnds u)Y3*mdu8wlNRi€e<9^a_m[a CvRJJ-P\;%2Aʞ "rWl@: tDHuR߆ۣNjiG%!1Fxр1o 4Nќ(VYx†tŘzl5+lrLG3JSi'p)R{P/{W5qOH3HuI ,IxsE'mN}O' pKQ1A;z@^ZeIJTepQ 4:u$C>909սݹs`f?<տOյSWΞ{){Ͻqޙ^q>{g` g?>Xybӧ3z>8ssgr p c?Cvz F-GfFnh>wLqH 2\sxUE7nKW{:zNٹ+~{w?~r[`z/՛g>{f w\ys7^.]]۫N*}C>|zƿ}|cS~n:{7{ٻ{]<GDŠqzh*Ks '& H<ټGc`4Iܺ8ߵpg޿cOw O_ީޗ.o?k?yų9ޥGKߙů~ypW~9]z:7r߃ <:Wo_gfţ]A2}cMDJoI-Дaܢ5{q2g{) ް#0O}ػ΋3/wto]sMfөW7i󣋎k\]<{[Nqۼ3oG_Eqzt6 ج96Wd-Gd@iު(&~n 0%RHPSvފG4 (q/wW9wFpާl }%wΣw*n~۷oq^u͝owv޿&O7k>*onFp~s"ȄQ"g5v<?d8L==nL@m`Je@HmIFD ́/]5 z_wO)߳K뛽)$z!Ǡw[6L|oy/{>^f[R}`CF!A`bOMNəl^0 MW92˟ j[w ׏o&w字_~NңrS;ϝS^4jo*۾_+Qhs~ r-g:w٣PR7{on{M_s}[-寺r7G<=1&}9AdW#&`w hR&Xdf&$(,- IfLqHaALx0j .ŏHhXyɌ%FS33xH=^{=oo QX9<1 Op26y{ nRcx +oixxf*#lA?;тHtpOa$ wي1b:H.% M BwJZ2Bcb~qcQƽ07ࠬ{5Cƹt@Bަ&1aOμ {f>ĕeBKk|ŪVz9ZY#$L;@u7(1\4ij0m=ՔےolΤ Q3ҫd>RKҽzH>k% I SI71~F5rܖ,usJ2Iʖ)2D(C`iڒ9B0qJܞ`ʘP E[F0;3b[ 5 ag~!#r!x, w$c3i$%&ay2E*y9BΏ;ػ;4zr=!jt-A:@|mS>?kl)I_17;tW^UfWmvԦZ|׽P[f]p]g(}ȓz4DUk,+v|b =H[ެ[mW~>5FP^\֏?NyC`E鿷?s*F7JO^u7wsVTwhFҞ.n:qLpZVΗV:GJf2+( (""(sNr1+K(!͕NѶ34Ւ .Ӎ 3裱z6):wu]NX3>^7#4y::}G/OG2hù: ogu|{x\#YjҬ;GNW<啅ϭ:1SJC9QE Ω:OYYea;+k3txStg ,]sDxHgNyyv9qɪ~>7Wъ<\׻hu<#s\Y˟n֎vv@yJѮ.^GNW`<'7W(/ uee"U*%gI*q% i;bt) C0 GD9 LoQ(q6u.^;co4<':95gX.j>VG##c)yrN^qno+QJAstǍk>2<ӱwvʛ-x0ܻ=o33\4O7G4c\Ɏjˬ.aA8;+&7HUӞӊѱᎮID\AeYe.BDcj˝tU\A:SX'JS++VV8ɝsYVCrv18u~:9Ypgv&Ey[Ymhdltb7G0Pzrsts_K5Q: 7;:cZ[X U+.6g;V^@ym ^^aXZ8hΒK2*$W\ӤE#ie5RtEerXS);:`ڳ5xǨThdltb77O)f5N\YO.ۃy4W8c%qӭpOwk0Ѹ;ʲ.^GNyo ^NQX^Lv4gI p060FwizPWQ<jJkR9Շ XJQ<󬱳iYC5.cMgҳκz5CO73Mhߞ}yR;öַ=y󳪀  s۞Oz;;ƴD!Ѭ1B #Csʑ>L7>cN5AFc;GbN*85r=9go7rttg]W!kFrណp0Ҭ-fVԊ:km@)*.$e]eY)DqAYXҴqC.tq;DN@ӛ]P^7묞t(Ls9дԓ|0T{x T254+ާ>jN+7g^x80*N:y3daUt DSdm+jˍ7rdjN1+fVJK\sFMNN2kf|hSV7͉K#6լq"fF.F>{.ß_J~5OW;k-䁴><.\b "U::VI;diVUŊe"ڰƦ:&VT ޓƲlB+%Kγsr hzyY8xQ?z5BN]Jt4qNSwii! i[y=\z9ہ ;$dhZ})Ϝ$x_Z24i*ޗ觞g}+u8`ul.kg}jWz99FFVZ*8 :M s+9bήEeY8e]jdWJNGHΎ4&!XnN>!G5yޔ;ӟuR98XqKNtC}uTrETBFo=a$8_ 25RC7|70[!5Ɲ Zkжt99JGVZ*[tTss655aGMsIVYNImY[|xچ9Qҳ'I CŔRt5Pӟ}8G}9N8ݒtC }`rvϔD[ d9``ʒicc#t؋:O*8vfVs˟^Rw*)پvK2fC#!\a:YxUL0FbKt$p0MX6Thda2 39dDVJ[aY(dfVGYBHcnhضVU:NgId}cVA牤<굙[Nз^.xXD$nN__NvCJbᩕ0sT XEHw15dry<l֪\Ӥ 2R#(+b3ml51S@jt1H TToo 19ZJtIt/=ϫuHVU5^Y5Yk}y7*I)ӝ;/b3MŲdeA`9|5aZK,0bl44r| !V4ற5'Ga*XCaYXPmjTGMdeY *Q"U): zYXnN:|V.T5G.}9:tƓFJuruo}7/ fFHV*Cˬ2(d(Z6I"7W3͐0]YuA9dt V1lD Emf0Dtq VUSխV"UgFVsxcuu YT/zrחXۧtga^NYRXTLn_~{k?JfF*ӈ0l 0 JrOՈ+*m Z:K`aZ]Hs57G`EDeeAN  ($P GwZ61It:N%I)9xcurYS:N(Yӧ& $m,t#g}tF_;8{7 +32m0"%HGRj̭XKY' ]#+K MΉD2ZGm%Ycb(hf`jDڀed'l9ZU#h:R^tg:~N.,҆?;ւ N<,;`E 0"peGFj̦eXXYm''mMeiueLq:)-2ӎ.F:::&M](;PVQYVYqڱoiWxheQ3:q4Xg=?txb 0" ֘XV;P+:: r'm57GVT'AӢS+-0e'b mfVMV:&Ru tZ5#h9'IL:G&gU>ׇϧq8|/}ϡMvOw?v}Zη=Җu>ܱIaMQ#+-1څeZژ2ttf)II8Z\jnJ*Lmul 1ձ5a](ң1i]u'YI+9捣*>n秷oS?34m~t绚V_Đ|Hh u0"!])5j[F-8"Ή[,AOqet,G QҘ9:Rƌ:8mM (:t2:ea2AJ#lqfWr6,641%eκXEud;l8]Z6D&UgG'g<}K۝>Ww57}>?kW?I9=g_JJY YY +SmձvA,AAh$v6t) RrAB49eYҬP;fdVuwCQ XjUuβv.J//Md5o>=Fwk}J|D>ߕ>3|{=[Y׫\GYt >y_!:IɬlISYk_YCY] +V8 )!4j D F 0: l[N"B2jUgJVQ!`Gb:$lDJB*;J& J.FmK~5'Se q~ZKzse_οGY:=+_W9=:;w{7>.|:ɝ%66>oaed,XQQ3+11 XZѲKb,mIut&PYgZ&.+Z;dlg:;VV **:J&҉Dd;m;l=Ǎz>{U}޾$O'ZyN"yDkS^G'voF}n|;y29֍io5amg>oYud"cD̎B@.I )ف6ڦPYZiD U4:GATU:J&ʈ3eFϞBNpʲK\FۣNGί%^y8omg͝J@gVR4F7rk?>A+ez`VmG̎ 'bu`² VTvj*Y5BҰ5 C- <蕃.;VVTU:J&1ԉD4GmGѾ6:NeYPtqyIcX8oIYz^W{z/Ä  CXќFςq&uj;d`E8:!X :$1ڃ$ vXѢT:C gj6KF:Lӂ(tJJ F0 ˝1NVDt6!hހ"%DVT^UX6:ޗs# {{icNiXpk*S>*9nZ2퐂 R! ts$2՝PkJҭD: d05JxQdj*LAflMI6ن:8#;J&14gS 2؏Mm/YYbt$Ʋ卡|X{8agao<; 5ʲjI, 12A3B!"0#$%գQ?#/RAW7kG` S Njh\?/}W>辐DA_E_O踻_DR%NrW}B#',vڎov~qSj~ښ?a m˵9j67rNM˳ df𜍆 o,RѬ KZScڷj:y4~0ݬ;"jrln '&ق3q#qp\]R†1.v[-]N͎X[i#$a=|ibx(~ajr: etPEM0p#!stP*fvl:)bx(~5~FaXv9j67tprn](k- 6: 0spphȊJ(eOHfSeS4|NTےufFOCg#0ݬ;CNZ' f  6: 0s&#&xU=!]M,)x(~Y~fhrv-FNM˳ dd`c ; aP k5vU6v,־OYg#0ݍhr:NM˳#YnM 6: aLÑ 9IyO jfϚI۪NÁk_XfaF'&ق`a6 nphȊKE7<*TڞϚIߒueEUږ&wfbx,~ ]9w3g`u˂(dF3qAl0q naLNG+D#+NMz➳[uSj[Twg+l.dbG 6 ; +NMzmMmVh{;[1<q ?݃Ń6v ˂(#r68`#&ʗ)5U6Io`\0@Žqgl6 $dbE 68`Gi'n 'ol6 PG21#76 aLÑ ;GߩXLoaj*G.T"_G[*?8|uZj?G4ߵwhol2p"(#l9vpcD0"< ԍZaZhSM^p.pGNoQF=|0$Ri'nB{=6\cv\C'21#7(8cpsnsCUЛ0O+G?oEJBȅ_#ܩu OӥV7絟޻>٤?Ӌ;g`A.PE[ltA9v0cD5]/̭Ay>y%Q:RJ/ٴʗQeZCyp?)c_])'noȳӋ;g`A.sq&'a3G+GaUbJ>.6{SC}VWc7}v}ҪooG/$v,"ݞ{!v  .PEs#Ynn0QqMNF84CTr#Wu45*~m'Rw¼$ULn* UYe*n(9x.!kCX!Wv|GuSn(@{g`A.sq6 ð#&cK))icx\7?~7|*7g4wU6W{g`AEPG25lnx9A5@oy{&㾉jU:D*|pTUj/(^Y_LS/}jA_T=-WSʦ֋݁`Wm흂A95;25M3~oSS}*+|+g|>"z-47>mOO?ehm Y(lqgl67e ɩّ7(8cp6:ߧ|&=Oy2ߏ~yLg~)ժy4/AsH>^FFΚhm2_`A.PNMN̍eQdvV3V$~g)QjPu&|Bv/_e_UOWySi S?_?QM<3¦|=*TE@1_>ڃ.hmh68vyA95;25AFAx97E%XƩ[}s> _S/#|J'>n!U|U?srb;*Yyv Y W ݗA97.̍em|A9v0r4CTr";r_~:~/Ԯpr- }UC.#b:68f\2v\eu eQq'a3F84CE%"WPўO w:ު.O2b;'$Og8fBΣ!7e ɹvessc 1u^* \#qcQk:/CDzt/}1˵bbZ!e=G_cQk/C#!Ǫ=*\ƺ/D>e=л2qWX1hcɗ4G k!!xN1hcɗ5z{.Qk!/ -cɗ4GUvS׀|1ˑz=Q2qWX-cɗ4\=|T.զ]*C&\8BUWucZ#.eCUFU^cZ#.eC{GxLqupǃ2q1ouh늽Q y2qp.6VųQ y2qcZ:xLqDeL\=ccCǓ.GBͽգ/%1.e=c6V^bFF<#pc^Kbpǃ2qp!91.e=c|1ϑЇ7XF\1˚#Їb-1hL[Cf3. 4| 8Ţ_?Ţ&\?ўnhcɕhXC1CBᒮ?| |TfW1و_F\1Ob:[;!Oz-y6|:Ţ5'Xf1?1jc 01@AP?MVynx0zFhf,36<l=g4c[)G4cŸSeH#Zs6<lb5h/-0zpa>ѱS1akN 2 )ȏHa5V}/-,L&>Fˁe9"O8E. 7K)GUi{EŠ-Zy MU}! {Fl&>gpj83 Qm3akN>G#֞q>֜}>֞ql0ig+q >iF >i[ >i_~^Өg3US8s?!H? }4}4}4m8 0!@Pq1Q"Aa2Bbr#R`3c?k4!dЩk_m`歅%KZ18 =X)/l-jx=X)/l-jx(;նR_5l(,4*ZQŧLI|հdЩkS'G3k%VBlN33k%Wͅ%KZG3k%VBlNn-:f jQXhTۋNl-jx(Ӧm`jQXhTQŦr jQXhT_GNl-r =X(yaFaR֧Nn-:f K歅%K\n-: kQXhTۋJk5l(,4*Z(9{k5l(,4*Z(ҧFC%KZ18 =^C%KZ18 8ZTcm`BOZc,/n(ydЩkQML7l-jx(9{k7l-kbp{3caiSa{qC%K\jl-*`,(PyF-jx8νkV4*ZQҦmpo(CBOZTU[ m-jx(fҦ4*Z(:Ҧmpo(CBLNfhQMO7ЩkҔq[J QyK\Xl-*`*G7ЩkS(fҦ7ЩkQ͍LX(j?4Q qK&}R'X(3s5 YzJM^pmz8'_ޤ}~'6.N~rB{G47G/ǴV|﷦i]sx(/s],p$Ϲ7/U]ixQK~|~}8I,m,lj㞎Aқ9G~qxez{Kͩ,ryMY7ٓoh%Mͷ7&>VYZ2_QϜ|~o4ϦsrLcs}qMjo=6jGq qb^SK=hfDzѼIrf1vco}xI_^U%=(G`(F'3aNN)>`NJlzq B>d#w K/60aaޔ\̈́.&{ >GhOڥXu2k )&_iv|SLgy Yz@~.:Ҕq Y?m.ix?ѥ6'M 3å!G'#A7}Y?4Lu`(F|pHy}s^W{r&ӘF6x5u%}6iƮpF+mڲ~JGBSՉ>IT7č[ΰ{ű? ?hO[^UGw{rkKm4q.XG84%>]9xAi$8e&GM,43$&GO/{;:~$M94 pVWB77 cf6)6?L nps՗5fׇoA5=}ƞÿ3V^~3,/8wG<|ve6#Bmif8msM!"%OMkdv|_hz\4ݖ'aӕ4,K=]hL4$Sޓ/)q-Xv3NYYOx8t^GK{񶦤~8Ԛ}7u%m4u&Iyd8#mMY=,}DnGb_4ӗ>J>H߀sn HY?h_Bv#ҔqHs6f ݶzI7UG?/c7mg>\ oJQ^bs6#ښ:~g2mϲ Hؘq?肏Dbs6貎2gP(F'3aiSl-;Y 8̅9 NgBll-:?(1A!q Qa0?! :b?b&I#CC~QpƇ gxva]gPHͣqCh^J؞ PM %6PAv/d1Б욍C=I8*f!(u á^0,E+U5y()/0(GLU :GdPوHB|;C31uˠ,>}8쳈%>бeø~ x d;cuc:b[#(9XFeT,&[F.RTF1-53v:g|ctԯ9hOcc2Yx!ܺGC[aV`eSTl(GNJ:Ge{Bއoq;heߓQ܆tԧ9OY|G Heqx0T< IE(uc: v(9߁*#A|xBӒ;e'?kЦBvNL8gP[N,3#/?be p1D"< 4C(nNPj h9ī44I'NwmLGH좸*vO] 2;'r̝1p/>}:K{+3A E 9RTuȠ< IiBne!G@cRT _p.>}p#/8qwEGv/!ۃva\ qae|/gb v\;/]܌K*}fx8cP+/!(t`21R2 ɇ%&^]b((ܴt)Gdm9FBЧv!v3.>}ɉΐ>3Y-Q*!1! @+0A6yݔЛ ߤR)B'h/j|>peكw\ _gPX?ToK"o GcЭ P@+1ƞL(]!1>gCj:b gv ;3&# "c:{*}fx;? ϡOps *}'-rb"#Y@ 1+Bm43 LEj?;PVkQ; t= ]}-TO?VzEPp2v`W0*ñAc+n8E:0࿲6|GOv9f T8GUQ@S/q"\EefDhu<yE.wGoٞ;5`ΰ>ѳ",E60  !x,:qEq'1KMi&ju?;CəEƻ O#SQ`c3Qme OccFu>猚-,r~JNQ^-L;PXpCIOP%uF2fs!u/ 0|] Nˆt P俲\B++8 DXaxVCD;3pah| yELleWYw#MMv1?ԧv߸c2ѻG6(!eOXx1840_ NQ^QeL2C..tb4d`7n#(mܚ OM;a:SߎAoeOlqw,Wb(,035=E7E1lu4P:eAyg"o4 !ƧPNH/0'Qt#SSw/cSX8e\ _eRpK*}!g~/'ሊ2U G*ʢф|ÄX#(rMjjY)Ht[k!??#8|NGxa;p8EԧGgHG_S>x{cN"+ ',䴄TZ0,|eh(^p3 u n#MMv Pۍ;C53,>}Bm_࿲ض3U-G/+(eE*F*u:p 8)$xʂrBK) a7;C NSC:}K+>>Ow#bgC*,0; Eqo"exDǤi4ȡu:,৒xm]Jv:;CF@Z}J{3#/3YF"*Sqi* İ ?Nz~F>'ȬRT5J-৑E#('Q=Bpwc|yo7)gPX}JgHFoef2?`N&L U`Z0O2ˈع_Nq(%è*J9+FP50* En!v:gd~eв{.?x<-VW HN(F%5-(1s*K_31 e(=tc#-MLEeDݤWr*^!`_ 1عфu#CCAiSXXr>k-5T85}31]p_cJ.p#/S@(G3ijR0,`+uXT$hZw𷂎J-5C`…{cpj#p[RΠෲ,ɨec3K*;QUE V)FcʨYBP#| -R5# #]ap+1[M oa`j38f٩p~%gp8\\E`(f02GE_%a0U@XƇXEx)} QD"a= (q>" LM\@Noe όr1W 00Vp2#UYp/ٌΨT(|&[8hyG#Cct'l`nhfDa;Wԧ2ˆtfxJ!ŃLEFUlS J|ό /ɲ5NF!w2A (Qdtr1 诱RRAў#p;f'Y_!90B;YAUc( 󏐽dа^Z5~1c+pj!tx^F:Qԣ_~'1#-2_ "Q9*!`;RYЪرu!##hUHpk-QhFKy55Cg-rlGj[g vKt%fC(ᇍAC+,‘E!`;f1LQք| ,>Q-Dǃ5H m&:Wo'jcDG+P䷲cG~XB*x%\G,ǒtb[l#cÂ+ 1l#!G>E9X(v#۹50!Bp g(Ce(__f#,Ph|<QcY:6ؗEE*G3vتر(´:[Z/ YY&&:Bdx5NFɽ MDG46Fȱߐ>VWEPʎ}XQsX(âEb^P>'%8q:V=es : B_{99Gh()im@oe<<$瀊&WŜP3e(v,u!B>>q!T?ž eߏ ~EA B!ZcS;R8' wK{(ZN'.pBPYɅr})'Q3UEac=1OG ,>qP^?T'5aZ#%ܚ:BL->BQv{5EmhX7(fK0_ +;:*,G6{\U@.uG>3- ȉ!Z`CMEBc!^ɷSry58),w-;|倊 Ag"}bıPDw 8uB>B>'̨Qaxx;A컘T# I(f5;Pʸc&Z1ۉmhX8wG〦!F1YLܕEQ#]pbh:Ў!#G'8+Qde@߰CMDaWGp_OewK{*^&;#4)8C*,0EXK$)f]qV:||B/ G'o& ], P md (555]p2¯c^1ۉ-"QB+~6PYɄ}bVUB;eccB>Q>q)Ix; !Zv;,B0+›YW#^Grp0¯~Z1ۈ`[n\88J`8xSaYU ð,1V #+QDXB:B|hEhivjdeEʾMD#LWaZ]p]c{ʗߐ.E`cg 2"LR*Eb;fتOá ϐs :x2eƢ0+’Y1Ъ7xe\!{-:vx٬E|[t0V^nL.}EEE !`;e*w((G>T>wʊD1pFhSF0]pp̠d2=< v0l( T@䬸g(҄t!2-SǃXeAG"W 55 ix0P7u0߁Dh21~q+F&<*):)g*c"+)؃.?D|r^zBHEAᗑ рAŎ#&(8X|{"7LʂD9ŒDXEpU)aُcJbv%7c" B"E*A\EEtE/>g̨Qa#X!_"G e`\dPw(vۮ ǿ/F;\~O+ɌR2a,05>XX(,+Q@X:xuC6 MM|ML; V#  ٔ8T.f;1fPed8JwLQI"TXaE<>0`TD NGsROa ,B(*~+B, ve 9FSu2c߁D̠Ä) " >0*X(ڃ. yOA39gF(BD2v*̎(lvc߅Dˈ3v,ΑE%+02ǨDZ0-K;Pf*ׄt >p8 5BENC 2;J1ّ Mɏ~ۈ3~|^WVpTXai(TCa 8Q||`QxuAF^?EN0ZU,2dp9FPˮ2ciP3(3cLfgh.FQ.} U=!P(5;fЪرMD|D| - Ğ< 1=2Rvdp9FSuó &e[Rd8KqhPCCQIPT .<DXf@Uعu 8=F^GpPU*B2cXF`~ ;1;Ao6CxJxbc¢ʢL(- ؓU@X Ƨ>gi\0뺌Īr(*pB2cTɑlvc߁ &d1)`"J11QF+,h!*F5pb'bF5j|O .>c*pk8)bER#(V;U28r;1 ˈ2ʗ< O~O)1a,G3XHx|MO`xFOg)၊98P…iv"2df lɏ~(2ʗ!ߒfQx<  P1T@u TίP|Z=)\ CFRU*̙`?Su2ce[R3!%6p? "E|Xx QacQ$W (Q5|Ąh| -9'E<1 D1W2;U2 dif= v d8K~P/CC*Q .| Pd(kqk-S5F4}ͼXʢ QD(*p1 ѓ"Vd2.2c߁n {w Of /Š)8 T (,:0\wh%I)>5!&3SmΒV Ok$6hMu4u YoD'=Uv CK6  UxB U$bRvdp9FSPɏ~%2K{8",#q2'T*Q0UȡI#FPb ٔ8T)v ˈ3*[Lw~#T"f< E }Jь,jK\p5lҭҗ^\٫=[cjZ?oP٢-ԻE#H?EcH# 2;U̡(}ˮ IoeK8l~r+PIXT>$j5Q޲bVIsAu'9?KaCjp۷a4WqWW"$aVXAp*Q3u`ϔTf(!erax* adW:1 u7w5&,+j[jj(9,jnk#{p4+<{M&#(yx!,B!؂حJHʸ|c[RW|/g󗌬+5RNA߼+Ȼ!ڍl`Zb"Chh-#KCѥV&mhVY1݉^/c+H\M`NtIq'OVl;-00/ 3"D2v P~ ]q hvH[R;1C!j{ui?,L(lڦ#tT~Зut\ cNVL;-Wm͈Ѳ5妜~Ej mS O_Vh|I3Ծ BNZk&jƳf6P9#B" ح 9C0ˮ2*$wP"x"E zB#N'i-t:B7XkZ.&; #j䡖l bVȌh6hz6eF֓zBѪbR8ߏ'1hKG';kfVdT/GTUHQQ#(E\;2 e2끌h~$fC1b+C)-gAJ:;g+%}K_'4{TI bxj횭D7О׍ Ѯu%ua[O_~4[{Nv?`mZ7Xפּ߃E% #gC҄نn76q$*` 980eveJ.v*-Z1ߏB3>M5'"CpcaN^,BD2IB2ZLG}uE^ᡠF;"彔Si"XI#rQL[GjX64OrZ6m'n؟kŽG@]5˜f,5*br!Bó(f G(vnaWĶS>s_$F&!E|,,`Ķ+ApS3c=d|]JkvYAZ2qBs%"+Bó(f Fi,]p; * %x~!SspH>#rU3ئ;Pet4B֞%us+*br(Q#(E fPU,S߁ hkp8ow+*?iP9*A7]HhKPˇRE~i fPU CA"яQ˞#倭,%I#B`X2ux@^S_!pʆ:NjTQȡG B n C0R8C0u^1߈%E|g578)} f;}¨ DvaL֚#Xx3@x+xQ@p!ZhC*0SIۘevObx7~%ʾ3qǖ",M< 0XU+bf1skF1U9ˇRx~E a* ex@\M37Xm ƴ8~1*ib0y%|}s&ũֵQv.WU3k![bfЉ {Ǟiܚh}R? O5ȟ#jDؽZM, b~Ugg[ 67}ћ:O'y7G3d]'ftxTciiNkyT'ǃ<#i۞}yh;T~2W޺@8֫ӯ3Z'];aɍu^<_4 @sl{m~tʽշ:`;9e퓣sW/ɵDWrNX2Wй&q̼x3ϴm},Pj;o+1n23`rOO]}V$M?B''j/Fj'_w\ª{,oliWlu[ }4,߬O9%gVC_ln.Gc͘ϧK]?gzT{L5$Uw=}b6uV(+*jHf~}x4$#v1KV;^{ۏ߫3 ,d}Vi6bC.ͷBXW3=tJo㥙inSww84>F>kLZ _mWl^m{>*$n$M5vz?`ΪSS1Qk2rFa[{ٿg8 |.S|Z_ OY97ϸ!4zsfhjߗ?g?5om:UGF5,Oy*v9qϵ :s&6񬊡cݽ:eN̫d똬mݔԧYNnGxM1}gƦ0?VŪ}8v/[o)_ʕMUcᘻw⩻YOOwNF(Zҕry{Z^*?Jxk\ l̔G6/ϒQ=0+eΖ980$OgHDo<w96c^c|z}zʯۼkyϸc ={;ϸf}*i5uSiMOcto7>n>*vu@!_ŏo.ٞہA5?$]Eyo j&\2grZuX91'Ay] uSȚ]YY)tߵGy^"R>Kl/ZO2WȓnWz/sR ]<CG%imMy߁kǪpg>dvN/3̿+%6cuoСݞTӱ}s`cn6!xô{97ѿKH{|V~U;戲Ev >1{l޵VBz=goY_{govsåթkncoߞ;@nVʹa|^寸03d8|ӮVh?i ]K~jä]!0F;_d'a8=^xnSiF']u3ڌ.]X׋~%>1A! Q?:66K&z7L s (|='D tpO2E=C%v,B/(BDpXATB!\ps,CP|Όd2Yc b)L8)!bьbŧ:OCCg(v,pH .b Yݍ(t)HS/(G+0pXEB=úpCb:FH qs0Р$)".2wNcb@wgFB p De!peALU Xb@t;qgqOD2 .tXAMcT.NXP# bj_H |yy$-PSY1ttIqE qϸРw>| s//8#8Q"1wދT $?w=]2 ee%aL㺮!Zq .I !aB+<<,H e\#h qW(#TF*HCr YKXχ~ gC;+B1tde!XB8YjE!L±pOD81\wU(!j t$:K(d0!O1 Rx@~8;Bet$:K+!$qjçZ#Yx9SATZyBp;EYHDú蚋G2(pS!b;Bl:F%2B%Bø*HG\ PিD,PPWPH' a!C(d/XwKGW8,k ~:1B1tt$:He1BE19-bB}$11~q  .A!C) B$ySN)bDžbACwU .I 2 <;3-wkwV,B8 !$Q,,/ŭb;PK&!G (#Ttt$Q, __BJ9K^!C:p! C 5s::ctB8}=XLA1tde!C! q ktb:<#wZD1V20,y"WW C1꿏5կ.sP_1ttI ! A"s_cXb:|A !_O,%x?>kX<,P_lH$OGDM薐/D!<^>kŭU(#t.ǟOmRN > k9k:#?g H  uD,>ků]9cX1R2 to< ('Şj;ps1 tPSuSbdž*bBxypP{Zx1 tPS*TB6&6jB1*&lKhO?P k_x1cqW⾈4}GC^>=GK|c__|qgbACu~~x6 ߈ (g!BŌc_xq9wUŜ; :7/ǿ |Z⧿&(stXt:He„A;:>gc‡78*AF(Aw#Xǽ;:>kkqb C tw8!k?1A !Q0?X `N Ok5C3*%h5~~cqb )k98oGኔ"c_NsKAAAѓE,☣5]#1RYS:?V+ +X9FO:<|tcu p++>y |#)!x^[ŎW?HG8(;F:<|5c9X!e"ς;x" #0ќ?ppx,Pӣ),Tb-cGJ_G<%n:tx1k߃*8+1 12EY1Ogr2q\PӣoU![o>Q ƸK;5Úbbb)҄*cp:2Oc+`cGs1Mx? (tCE[LBb?. i w#ҵL:txMc:3p!XءLS(TUc‡I܍}:wk:3†!h(V,:'b~'r<)ǎF!SSLB) iw(tS\p>(B^(E2g p,ALYXtc>YPcGZ,"("(T5b(1<]TGF!ptSV(To7AP8=tg1Q+| xV(Tc~jnjZ3lg1Q C- b(E3}.s^1zќ*1!LQlP}>҅Jz^S=Cw-FsVŊ-h;JO}MSws5Lg* _FsQb/NTY'!1AQqa ?nK)BBO5:UwcA_[3 DI7)vF4kC]ZˏCZdZc R*n W$;`LoS}r"5%zZ?~jBa8KǍJJ]EÙ)GŲ&5#W"baY!'m/Э\ۗаCK=Dhh5z=du@"K C$Qmc-DIePTa""C -&6ԑuIc:U B_BѠXSDG!8Dȁ+jZ"By Y7&ZoCA~øf%: U${Hhy[ h'簞{ oa'$N}ľE´$밖fzIQeU; -*z$g l*qM~En3u}ZiKB.һk=6LL _BI[_bvFGgQp5: A,,U?#if^NZ4y|lgK7)16Ǥ%+Q;,6 Jk/LHy(k'$u!y$D㡙NS:]a.ܱ! uD3Oqwc Ef]9pTZF@,K`$JSȱk% Uℏ-5)ڒb޾J 85e`ՈZ}W ];%4{_B+D12EB Y$ %DE͋nmv1`o 2ayp6],]?VĖ]OK=n3ߑ,2'%e{*ӰǷk3ؔ5"{skXks ̒-伙uʼn(,oB,JUfC/ m7&/1qKQsQk2Jߓ:J)wV] LcldqlWx֫U,._u#(J+%ng%1\?К_ ^ܡvN>t=u>AfOTLzb-OY}$IǮ|_hIwΥ.ɗ9FR0udLq%dZ"[0¤kU3(Y%͉ )bi"BS1z HVSv1^j.dj$A#UL@ɉZ] %D~Z5 %BO.?ݢq5ox>(%"4P;x2 %hj&P#Cr~ΌiQ'w})zѧVb5s+զK1BѪ~HYt̋$LAPأ&U#2~bRh5 j'tn} sjitT*nȅzK6ZIo%[ж'VD`])qĝ Jqka )dŧ7,$՜ A>!#*qEnjEi.)><<ɳyFGMm;p#(uݓ/ K6e"@Q.e-B<.Nsyэ;Z#Uz}Z)LΫ cJJ].ƙz)e2'x#;<ؔlf9$v|(YXt&ÊYly1oAzDD~"gEԢfO.`z"BG4*o[lzA 0Kتч/cpE$H{SU IV~SS lNQh5/OWWmI< W7:T'tIFE_Q2 R' !Hu7"X4iiI[ ZNv E9#l$Hî c쏝E,ӦHcq/'t"',}u)'a#Jp'(tGYHp4=hϗ~of5{>a87b|f짣?ϱ_glhe] س.!QUcv25 ֚wMh7Jn[Vo cAʔ=+ӰoQF猑M8z}тPͬF !nMp%κ2xDiJ}B\VvDDj<4Mzt<1f;IyK~Ae?"NӝݴcÿLKiFk#0#M Hx!T-< D*+tȑJ{H35J$E"_XfҏX/'/@HR0pQ<-}3mOyV7=ߺL2ghCN;C:a8#ǔV>k4W(eG#i_f%gQ(cM\آJDXҗߨ#oEw,$EwS ]?d_V^ۓK8^OcD~AtV+u+-E eCNsy:'QгnkuTዲf2F(dJCBG %t%?S5n]ȐDؔ<$ $Ecx*yN5] NupC(Ԫǘ'9W7~_!Z eXm2ŷ6Y?$`YzQp4K< =EFPlbq,BcZBK`Iy3O O Z^Q ܒn#a~%ݎ Cc%D?$ػd{*3ycnt+;uZB55w )}>b EJ&W?d\Oj?㱗_cx#o9]Fi={C3 lmBU||NXX~)5KRsi#p'kAx}-{*_&~'J.g)kp?n,3ٽM+7^l]Rz,@ T?ɲ<)k(tI$qD|&]Zǻ[vUtq =u"ɼUcKI*_fS%4IdH2{ s^hBO4%Ʌ$ةjeut&i6) / %x$JO% j0./>3.Y~?lr~1nuI!W qxٖ7b~6d8m4T&^NMvМ6GD&mMmt3jaH|oի6F| }uJdk41ȝ6W֣x{DTXxk<2>GwcYElz5z1M. =hk좞e}wlmHTMHQ""T,i˚b;/?gK5%/'DX /BȟH(X^?($%_g~NE{NF5=}֤w7&cʆ}#'g~oj ͘=*>?e /m'dĝZwگ#[j| v^̙}N>VFuĉی25<߬n#W!x̍+vq*k}-CinrLTDDͽ̖gFJ Q.8>94!$n1r͵0 ޿IFF;)t+ͦI,@nģ)Xj+рp"0$Ek_$wg} )%w3+F!^N`o;g`o7οhky]Fv5_emFsv:}=g:|z"V8.3Wb}&)bR;2v*LR60.9sR;s n5Vt޲n>בYo|%#iM1Kt2c6Ȳ ѩMYAqrRN-xتh 1!8>2p^3܃ _)U&!ӆ5ҡo>#NQ$Gmq/q.ՠ] Jgý5CXǤa(JV4NW^wjr?}5Їv_AnPÂi*`Jcƍ},u͏) /:QncAKq"mF7-̈́VɟɳM.y5~ɹk*ȥ.v"zf fX΃b6q:^>Su]F/ WLl%{59[l|\iaVJvDR"cMxk^ZHKLuFؗ1Ix[;^:GE+*3gESy _Pj|5Q5{=JDiL-Pzz"%z"<ӾUX㸐=Wx>cR8 QS}nO;'+a8}= Esh?xו7x݀;g/X]4ȴ1|7hgV_>,0$ky!XN8!JLh$> ů+ 8|f778&KBb!.~iӑ645dօ+Ds~ \=<7KP߱GI,,hr>9tjc]GL|t!\GR4&sdbQݍaoFƅ]]%KIFEoU7Nu1 lGQ3$#]zmN-$q_Umcb= Ez ?BG/oߨT*QkŜ K*EH| zݡ{uD֬ KՉ)nЉ6?1Į% x%~cTY˧/ /'=K!9̆7a ;5?DCؚ5dM #k~!Я,BlJ ]+FDx.dlYܐ,x/ _Ŏۡ&IT!g}{!8_b*B}{"kШ)pE9Xh NX=17~&Ȑ? - &?C@5Y=> OǤ|dJ2ʚl;=!F4=,ym7Sn9bmSѨ*G:5cCx-qvN^!+ NGōmUr|+3KޅM렗xs&^aL'[]Iꏱ#.soGfc֯&[IZjrǮ*P`Jw00Iz/Dz}h|FEiRzւ%/x,+Ey_{=\H,K:GA)Ƣ?v*8(=]Kx/ ns"\Д{a 7 ~_Br,q/HJxNzHyke D6솎Dc;<<FVbƜ2,~*>?|  s 6Ǚe\&EBSBrTeGēcÅ=MRhiC[}uh'Pj7˨W4Ƶ4y~V--A6 D %E,/'F?+t}WE/Bs@dyDNca/cG3zeS)̏&؝g'hp- ^gkt,;53a]~ȳo =/x]x#B̍s*tKG} W@[ga%4˹g O0M{E9%=+sshv=Ȟ\&*Q҄߱,q;M#~XxX|/ O)j$%=U.KN)%P>ȯ}=>O)"no/Bx5ǐ8Oq1Gs?cu?ᏒgoddgCMpY>%WXAFƖhkwQFgxߞ9cUd)n+ZÚaoM] [3щE9W¼ NO$}0Q M>f Mpx-?\%ǻP-vDE>⨻|9݋NGTFu%|;Ah̗Mm#Pۑ[ZDcRxҒoQ*LΦ ?^MV.صĊu';NЃCPoezlüI~bKȗn$Jn$¥H%WxE V13^@$LԶ7cCXc_u{^bxqb&3IsHz`xKAu#GuV4t<] ,b$;}-MW/ x1Ob#aCw59'oncKj h5\cKљa b{#W ݵ)ؔȓq4]%۸_Fcƌ-/lu.DI7D;z4ak fj$7C=[j#K~dh]+:7*kײueM9.5ӗgZ}9g.qK'm\h<65723FS)i<K0m-kJfUIeYN<7ɸɣVM1S(z`k8Z"%m%/z5Z*^$E0&ӗ Ȳȭi#ZP펴WFwPNj$jByS(JJ9Q/[p,*JĜ(* Ey lտ+`M=غ[zDl q4Hp8$Ɨz*j7^H'q4ihּ~ 1ggd>ba7Mi#cgO {P<=hF=b끓EvYdx8n2"WuBUrڶUюΌ?'촔*MHks.jLO9{NF %׬KHkE7L.V7mtec_I5/a+XlR띅VAt F* i!'IӅ oȰ{5SK7Dlqq/[ׂeiWs̼k-2X[oq"JtY=:80?̉HC__#$//%!^sb&ɑ8cO*qKB7PO Hͭ3ˁb[ipQ='yKx0.xkE3أC·,}kP֏f}m%.ӜO+A׿q;o_c+a [`zrJ7* Ho\mix2aAF}J["ލHvCQu%}1;nq(Z1ߩ `OU"U:=Q#ib(_eUؔeȔ֍Zb++gZB5M%;o$l[;iBJOܱBĉiZ>ϐ,w߁bHE/'{b^eOг! J>Br'p,7c5ꦲEyUQ kBKBHI:a~H]D^}J'[%?gmH_ք*'<h~ƞ! 01>4xݡotCc}ܿCރש4sc^rK'7| ~:hJ{X5jc*_:Iں'ѷ_< 2oay&N´⫡я-q3M:B| BNmE[žƳK(#YFbkOvE*߁R+uخ)=0.Iv/jq#^x$b.Lbnʼneķ.J^ GN#A7u[Vp58&QcҵCCUPc5n4?Nl7T<}ʔB̽F薻7{U-omԣu4T"a>]| [^ I_p kkb7MrEKBSTŅÆrM*&i{[v2Hݽ8| k/h'n(I{z V,5R8*`J%=fŝq՞ Jx=ϡ+š{BcׅO"с9I&Gn $own}F}=L'7-{Ԙg;,ڕУ4ӏ,lSQuەz1,s- SSPY%JcGbx/1XX_b 8'4!'4DzʱiRqpsB5ƕ4ܶByyCJӟcM-?L:JG^'"r<[[F?x^_~FK^w_4? Ml=m1>3xt,Mj9K!{w Feh)s &M$c㑏C#8c#CSSz%K7+n}2>;5S¸΅n{ 1XǸiʢ%fjobeo\OB9_"Vܦ>ֺf;D\HVD; %t%xc8boZ4M߉y)%{Aei4-\D+q^Z4빆^ d|3/,-0g _boOBl]Ĺu11*  9WKL#LTjƞt l`{:>zQR3zƦpA4{45!:3g{>G?%쒦<`d`Rٺ'+d BQs6=D[3[Qhҋ`(Krj to P2'S=k{e[n^53G-N㸔0NEkRS:D\f ^i0jVYq$kňVy]1顐]|XXYl%X߮5Q[;-F!L ;=!hyNGJ_L}ا3⾆O<ߠPڂm8qGCϲHׄ|8cn6=x}9SA&\,u%-T2y˱ܞ1;55}#|θz'}gRk;y9cf`^ _p$+D3GQ.F7>x݂#*oɫZⴵmlQNlFj< _EQެY| sLgߵ:hA'Mm%B׀5i{BֈH<D>m8zr,NEmNvCx_cr!z%/c{?sbI'ܾԸȱ>?G~Pa7mRx[ e_e/|Hj[Htj=uX~>LM;EJ׬rmvI!##/fK80ZI ;Mt$g3zdNUQ?nE=casT|5!">ĝkшA[NbS_ga!wؕ dI{g^ϋxww D= >DLo:<_Lxߐ7d)cOxdK9ՅWq ƣ64YbWD7, &7N .CQ0dn:1P}:dw_fR3Fb-$n\>>xb͙k:5F(fۤ$۶VZ[ ouOM&~rY4T_:P$aQ{4-S aNriZ%t"1Tc("ּxFGʓ&WYm iߍ ?'׵)$ve߁/ģ}ZYsʣ)&hĎ GQ!?5~?#|b~[ɯbgBp'"Ҿ"y,?+ݙ4Luጦ ĽiNk#u-q'|7gjЅŝͱ H<bu'gtlD_I㱳xĥ/bQ;w)%iтgГƄ'{><〥# (7&/ _LGlM42Cx_43άkyLc~OGc[k̨e1c}\hX}:P7肝L{?nOLh7mテSR'/~J2ŷ)Wg2;7k\ Zvnt"E 3'2~GMLF6ġoiƎAejEҸ5ɖ<$D&Qh*vQS v1z9r(LZ}JW%nL\D1hہ,6nhNFMZ#hٟ7Q dVW0tn?r%l'xBRJа04GlY,#5$by?l"~=ZyhB1ȯ|?NG󾌌1_̏J>i'Ʒqȃ#x{}Iu)[N<"fojv|#ݙߙ/cSEƦ?5ܙ5DVEL| ׫pb%˻%a4噅zA8cN?Hwȳ:.۱;)v,{-Zj*<-ڃy|m O26MJn580OrZ#bnu40܊~O>Bb'V`/s-/Jw\ Nbo ZؔG#B_bTVh=8 %xBSkBfَ_S񬾅\^Gȟн%C2'O胗QycOだhN nƷqnΣG&C߂. 26?Z(7nEKݓ=Tߵ._C7 7PWhneu239cu}m po{i{+#[%oRlfvW4FѢN!ڒZuʝ rN~Ȳy#S8I\ztؐb>'2,F,O W%(V+sJ!CCFs}$t)PӗF޻OYo;; f,:Lњ!wSOUאBJ, {HuڂN|="r#F|2yN`xcCz4=Woȏ S7 r3t*^Hwь+޽Y{|/jhCh$;'fy X( Yъcn/ n$7'@z> n'4Q>Pvf!ݏnş9EyG1}}Q4?kyeZg7'{zjJЛo1;oPӹ~Skܣ3S=+`(}nz9JUqJzjQ| | O8&nO1E ~$gIL]L,i!b:-V[~TV/|"ah=a}'Yuqݝ"Zm/-({hZEyt0<el_/dh|}YSnvM5{C=,}a}KS41tI2a5$uCEנD׏GbH O3o#G1WxCoGatD'({tq?aq0Oby _G>nGO6>r+ZvHo&Pnd{}GJPh#$[x$󑥽WMEW1DTP8qk6,jؗ*ZR2~ԘxWyaS /+ӔC(5+ˌp _b+[N~kK-ng+'Omr+{2~p:K񼞢\9ȫn|z.p=8X~a=w}$,[~dzH oMȃ\cWOLz<#&=>Pߍ |Nm ^ƶ6}p7j57ԟ8-Dۏ=oÜ2V{Xnˁx4.cP wG">Bju4+Zo}QTۈ]^;H =bagDŽK}jdN:^Ĭߢfz OdQl'[jw% P+,R?R1iKtO[WJp44ȑ[zKl=nlb+}!!){Kof:a]?3lx0pf0dw`4~cxǫ ;'ȿ o41o4ō-r?1 2> ?ICyRrq 2n?n&ΣA#GccKXT"2d0Vxhz(j77{o︕ ֵ:_b7YZZ$oW[rSkWq3/f6ҕվ-evꍾ"1 6U H]m8Ng)бtbgц2kSTPuC0C׾$@=[&{5.Yh2*t=Fbj̴zׁŦXQbNQv6FTr?w|hpjƗǻ{ RN Khy2!~y2v>}iy~x#+>m)k1Mj6Z F;Xw ۷hmc6ebVB*OICƸ&L;ʻ LU`J|ecQ;]~⤔&A |5N>]|n+kx;Y*hMIxȜV?de0QOr?exE:1%ц']EyhEVu1hy%Rl5{9|/pL x{\2},0v8>RH9FSdq9at5{=o'A[i;`oWS# # b?C4aC,<:THRd%nq 7 Rn9#Li|4a*շIX7V=*qRȢHS7C4OwEeVֽKRg'M+jk(&2F ѥe6Gk:(wxI<: wԢo6-[W8=g24of4Wi Q׷A3hNC5ͯc|~I?q`ᯂ|i7w/k嚾GpǑbv'^8~QxB>c&dka2;gz2~Q}S&܍]+O>+bȒ} bX 0*tWYGf$ )ISJ Fe6YC7}&a5r ag4IK:G_M +{?t(u޼;+%dp%8vUi+9'o8eD Ƹ+ɏuKm߱8oUdI|jY bXƕ(ie%LF~7fsRC@:;IKm/i % O2n 𘆾?^x7NO7=yO\nXڙ$;F{&Cw?MNd$M<jАCXnS':/M,w1 scL^ .'yZ ykvK3.LwMV*Oe5J#ih;"Y4wkBZ% VM,Uk_X2~XE-ے)T:ܐE5ה6J9+LKY}W2=-סo }Gg}jQYBUsv`@N<=} NO?{[Zp5/~s?ML=v1&&[}{;O13Dn7)ؑ9ox)6!hьv3wfB\Llhĥ386CKn~ͼqܦMQGgЯk2l;P]D:'v"ub\ri/TFv騸FyfcY[6m;kQKV}hMG7 )[u)&V{R6cF61Ii*x)i]c <^q/ftRft GN@*w$?c|CL k4q<= '44D? zDLez _1>gzP{ɰs=vysKY?u*v;mQ-|3%Ȑۋ.뢡Hv U-Ŝ-1dj+M}$_DBT&&QXp$-{HHۮp| D;WbÚr_N1en +=Du0^Ħ(jvaM'-&;!x,Kk W'!۩%,/.Ė;.οG}ҏ'"gVքx #Sf׆7,+o? j$g9M~{#o6;rHzA< ~hKFȾ!"|Ȱb/ỵ6vWG̱HjLYp"hy|L8{`w4;tD5Cb[MJ!vVZ)?)6oW (OfcIP3f:'RNdTٙ:as0"]q9*fIXF7>IK#LS ; kCQ !s2S=bf&%"U[2aFQ JYVEU$R'bse aZkY*lV : #WFx9; lς7ӗ4IGۛw׮7owCSXR:Y{ՓZ4kUZwcsˑ%C}dsfʜBOA>ꡨwFc|^؜ǿyZԿ6ښf秤x4'& z_ Vkot.#bƢZ О%ݒYʋ4shSM}>x& d7j#oae.k`Fd41G}N<DMD'}5Ԃy5eiԈzw(rR[#a}uuD-aIC8K&44#ƵX yPJZ{0k6r/:Z*7+(LiW+mvؒ؟,bXEƝGn%\ Ajk|zٕ*!L3/fodp{"T#KJ!TI"BDU_bJ{YW$q mS⹞xӸԩb&k-x[mF'ǡTiM=ඈQqa'457r}p6n`p#z5𐜒~0<(2Eߒ#~ġVvE|_['i695LizTH:>y~bB]ē![pH1U2_ H'a}IJxB]lI8;}Nn:xSJ,tӧw2zd ۃF2[^{N`i֕/qyQ(׶^ǕThb,1(ȳ" CBC̘h:W|V9b=JL u/55;, hIXR '5 $G&Q"FE/Oi*X,y3nOBEЅ 3i_c0Qpoe3qr)KUDRܢfVZLԉjT=Q5AKwVG-$j!vF TnxB6%ri5ZT'Qy1?;1fwHR&uCcG)%ќ3c,s:|2 X[n+-e+ɬْ?: NGT|') {E,NN1Uj݇Y1#fvh_bv'eQ9""w6+9g䑺>" {~d })- |5e߇G,YNOzȷ5RG.>:JԕiWNu:5ôv+HKP.߲rߠ|K H:߃ .HȒy1Y^ܪ[hęRӇ/%ƣJo?谨xfTlq44-o;l3jm*Qbɮ~ʨ鳡;EӁ0pa'B:~jivC¾zD'jN<$\`ۓW˷&X_(NEȖG?K+C6u'ii韱>6=:ocCeM[Kga,icS?nRÚJT[J>JY6cM1,H-|QzC\\ Eehv:X2BGYǡCOخ(ޯۡOAa^Mw]H #aT2\u&B@KHvp<24 g8Ŀe?Hj?d! GRxe>?Q_'ٕ dS%<+ KbbKBMk#N$0o/{PҌөlK.dꟴQ1-*r<&:>Iha^mȉr+,R~OYyD6pFJ۩-|_(T(HFꕣȕt0] 4 ÁS~WК7/m%%o#9ލw:v29mc*A3s{.["9Z7TT5Mj3&'e&Wh~?w,/qg(Ji2\_n1d@~??SG" FBI _ WAkB]辂HbӇt*ڮ >*% $ȩV^Mʳԍ`ד]ŕ; كWYƆWFb1޻Pם; IbqG]TAƷL9l98plEVwSWZ Vӧ}غ$"{6Y'Չ$)-7Bc_DV⦛|!!$ ZIipLXMmGx4"kp'RҦ' F_*ЂR*McIuq\TezC]?I!3ќZ ѓN#dN}mt$0'&z0'"[Oc>~Y14p' !e)fyةoG?rB[Q;3Ʀ}(`q[CƜ mZgObШ憧Y]*#q 2ixJ$+ ocQb{N;_ŦBy[74AҾFyoCTq'2^kС5"3 =|iw8 s'Y50Gr,ͿfTb _b#zwhkf;Ky__.ܿ?g,MB[FЦ*m0U.-9ZٟSb7%) ŶӷbvK>kQ+ٺ"ZD90P755ZLE݋atJ).:Ӄ%n1ڰ}oao,:\1cʂcS銗طudf=17 {!*CXxCMHXUhMuP4hiHcDWj4a[)Λ'ݾnnoBHLt{%F&H KK\)дs kT q0ӘXcdFNKFP4A1MpZ5餲x14e#}5kx>(t/){:/H Я?!tD [5;>;6˧Hwɓ4@G=xeɧ5|A}ck0 /1'ĢP} MJMt?cBcg"dߨ$X:U]rab$Fh%IM[Qö}ĩhu,^{ K/醧 B+G̩gޭ&,]mJ/=hYU͔3 C E;>:گc4H"n0ĥhcfzs,(_dj5=?Gq|KII be=h_04Ufިk_V'ʧڞTu$A=?0w?E"%*F'[ c찐h$ΤMm"c>Ą^EY G]]RbIyCT,-9p`,z_s]~\BriL.#K>JlXYl0Nf؜-7jF۠ _-8]({O1n$us&I:e4q~ ~yrQsQ GބQ^6։}B 5wDrcƭ4MvE^ W$$9ti:Wme)why)=&ŷ)dґv0zXB{4Pl9C&z: R !LLSǕv?%ȗ0]1a8bȫ}b޴/I3bd#CK%A$ш$wDHW Oln7G.Ě3װ/%v^<9yoNDuضXq)i_N6]iit\AKFlԯlг=HR%=Dbk?% Ie5fy]xFB9Ɣ&¹ݓ!G ɐXď/Ѝ{!KWd5'ͭUtԚ_,aZ.]U2Wr(;=r>8#ΨJH4L1rY!133"V& 2)7T\Zˊ]Y$4)nKoviYӕ-|i|ƣttF!Q!w!+x(,ʨ%;.GoI2(?bľĠ Lz\L4UCIk75RM*>2;o]GeaI.a8p?#RJ5u r: 63KfO)u=a@}Iz6z&L Or%׭_]_,aG<Z)`ٖ?5^TbnkajKFTk|HݬE2,mĘ4)IUCuN*J%I-I%;E!I"[%ҪyR&}\ r5cEKxدymzzC<} >]t0J;1kbď󾄠JfHK <|ct$7ȱ#?i ?=G !8(X/ԧ1)nƄSIVԞSX&l\TMB´jF8청]Fy븫fr%;D,"1crk>Z-IcQ|N g0Y6DVӼDCka"JountK+.K7amדW=b)7Iz깽\Znmݶc2L{p:yM0bPKSM2ǚr&2.ԕ[('3 xH37 bQ>JESX JOп8,(~.p,,bȈ bZ=g(8xEfq&, y<`X "pHd;b3ɧ# Dz'TŅ%"4f:poQY=woLňhFaZ[F%L2ha]v^JZ*4Xyä3xO 5Ȇ D`Պ+Vd̻UÕEr*?eMpmǔ=4P)uSQ 煁:ZjyS o-S+FBUZ\BBKw$|l!r$ i;Q[&5l~3 9&/GƯ>}HBR/zBq(Di>Qك5 ?OZۓ-Q>j7 K! j9_z}'g"sYD@YJ%CQ'%1'lJ3$5jby!14SQ/6f/XK)lj蟣M$f=4/gX7-"ѝltb~J6nF$T5 ("n)!N,Ls RVtyb4HZjjIɦBobo*%] 5-xlA6d{#/q̳#*=oτ X' 83%PG)k;er3 -蒑)f"=1jSBjF41\{C&T%_?R=ǕؔO{\;J_`Ĉ{Ď[;4|F! fOd"y3|w/ocBS?HH!qo+nEI^/'!G],T?(ƣS#i%*JМ $IQAB|Xcѣa]p3jbKHK8J9B[u,7Ȇt2iDxƷ83w"{x*ըF4"V dCY0l1rEza}cMP:tu(%n[H'vz7wqAiC*-7b'eAC`R2h$o%*V%Pp0gDLRc<(qNUhO r]<"N3JZPeL:{"3!5WKWxѤP8hRӒjN7+Mm ,IO]@4K Qx_9Fͥ[VpDДs@biBo ub•|_XZc#]C,TwDAiC5~'{a?Ho~ 6%odz*yJz!v3{Jy^v*˺#q!佞QzD(YH\*]% "J2 1 .uEc'"onqք Z+KVIPǢ˼ d."ֳM:&+F"ٱC*zT6^-fIB[iDJ )M+L4}0֔D C%6aڄyUc2RĤAC;#ŭ#W%:4-/MCjrWR`MopJȓL -p?B{KeZ$>p%8X"oaYlu!$VuN{_#%$4G):ג"IYݎ60a:,$iW,mԸkr xmdNicUCЂ J  Ȕ >+ш򾈲Ȓ#5`[ ZJd!q? }k,Yd].z[[C?NW6ꅷcZodj$6a+-!ք_C(v#4E2WЕNt!gFӰ}`]SG.!㝍[Q+tn$bj!ƪC1 Lm[Y- :D%K۰F?0P%Z|iB|n[Äh6g-t&V5CTwǜ(dq44O <k#|ctPW𔛋R8\%rNgzeP3Qq!ؤO$_%B [I "4+\FgDZQGBJ2/F&O_ԍyơE 4BB2 #]qNvYJDW_(L^a8,bI12+?D7FwzbTE7?,Kd}A2)/$%qi[>H$C$tecYBC?7X]܌,gضI~g%Q]HB溛ןeְF>0%.>E|@][e5WАZʜbGOfv.e/bYUb<+%;D;8!; 0~M4fCd7LbX=`$jTVڱh!aD]2Kw}<эzpOK>فuC#u%%"BF# 5*q$5sB%C)'%xBW,hؒ$?۫ BVQBcZY! uɦ<]R[]BB$Nڋ"y-547M[%9B$!bgy-{12G*E3!|KzO(/js&_YA龏\^"bGm'Z (0eּK!wh$oAnw%aSc%*DJ>43᯲alY☝N }_0\O)g-^Q)BL,0p'1,G o0b>ħ棴SY 3kLv*zh013LѳՍv:| <(|kW Oc ڪvN;cLZy J9g`%!x?.kyىBˡe1+oc_b\kk zFAm ySз(9va n~$G"<5,Oq3ɇ} d"z@~H]Hmuf!Y]3a"JK~H‹XF2S>DyON WײKƼ˯Gr5Xp~ۿrptQ?WW?OhYCOx?P4==?fPmסN !}TP/e(L(d|5hP (NyPބ[Q%/✶~Dp$񗸇}|O=Cs:}6Qf_[W&oЂD~KJ]O% Z~zHjԪc+#hˍP`y;Nl_L!#N#(O#e+z 1 qn7c|W T~* =xƅyIPKYdK settings.xmlZ[s6~x3! L`a$47a@,y$9#) 6qdir$g pGpOOhة\8_\ɄzPuE8Dt '.I7GcFSÙi]w>OZoCC g#ܜI >Ӭ(ћ̈́bGGhPˌx"QW +ꥪkWa"Nsmk3h^6gB5FVƆg Wq<;UfZP^r4+'ՋKw]=DZnߩgI'5  t:K\|B/os<9horE1̻L%Z4vQۉ]ڏ- wHpaI2ʉ'S#rJ*|Ql/tGY/Q9H3P-6'ט.r-tW0PN4[eRv5\eHM+jz{m)P8{q%ؕ#̀co|7ۑr&$^{3 |^(pWŦp'E|Ũ4} &&>G,0|38t+ Zc%ݖ&D*HU_=lykχo|{UC/=Vϒh!Kb;`RX /G98k447$=UQ)DBl 7׫=y5|8G C)Dfj\豗?K[U3" CI}ZJcEN & `&%D`+6D)&UqZ=;1D [j F9؇` ~GUO:B͵QBn: ආ2"n 5C؆)dp:#))~v'rKW%٦@BGz,_δVBW" DP@yhX_?Μ5}f;Q =2@6tZ]歨NH;C#4D\@Kv'@ZQrk6a4uu.YSbΈ1\I;wLc&H Z Ҕ {rߺ[!=(tibW UfPCIYjXD#Ut煛'ꨒD4M.8Q&;^ڱh?X~#.r?叅oޯ'0_{й'\D+ iG-.q#`/2dd{"f:]E?n(}BB;_>M \@m;?^=LEtAg]yk3pM+䓏'#9r9Q_)zb9ޅ5P!i7#qwf7h`QS699Ƙ26GLɽTo7}C\]k=`H?Ĵ .&z"b@9 cE}^II%PN?1e"qZƇh>O, K\Q\#w&!.h-ɟev&"ip#TR6n0vdpd[fU~:P5mP!/+/I HK.YfE`:X4`裱X=$Xf~ Es'=ʖ~L~yw=n^XUmUE^VQ#01h\2%hأ!26,`hƣ*my4 0%2;uL&n y߭c0Ls4$h%Tkѭc*ьy(|̣;SǏ1?6{yt2!Nh)|ăEŔq{>-1(4m4c*KL^T I1x% Q۫|hkQjQ; )|{RM0 ,Px^b&REfY:F=E9*͑+L@đ$U"b{yI[$I3= ҄7PSĤT|'ɬ@F.$ͨ1 GQMɐj҃]ˎN&'fn*'Ԛ#ύyC˦[C&O?$^tzcW`RNypNRKҹFKnbF/̤O;/= =GK/!7dH^$Bzo)@{!H|yv !iG^ZOe מ6^ϒ%9Nΐ dƒפܜ-OvzɅ. b&׸di'$wj5.>ӫ"uK zRws`.=_'Q,S"Or 2^5$("ٶ5`׏#*K'weGXW!̯b>Bؽjv&oxT`#d7"dv"*T 4{a%>{i5cu 2ȶfh@3˰;:^[I8&GPRΒ;K,/pg9Fg[ƅ8f#e3cD妵\@`rrьL~MYd'e(!4`REͰQebdYW<=Mt#Q?n߼}|Jx;%~)s5K]OU ͟by:gyqw<8,3(.J˛0h>\v5OndwDxޒ3<̠khu^P׿}+aNIuoCdxLcK8xLc k5dak8(@׹=/%pfuK/1>$zz]X OC888DYgqqYKfqR 9ov,ZL'F1r~(KnGi$xK7OW_Dq&SP1c0# `JN8fݬ@ bs0vs,[,g,C{1Go 釭"?N^~ l8Ly grq&Ǚgr/ɍK/gD]9k qz䖓aFH쀒:k  W_Ƞ{zdIb?龓¯_<_< v9y;-P=S_޿}/$ ٍ0O9U#Xï!y{b ŧľl,'8,8FgqqYq ?~= E<(t7ȏA;k{ enUeƻòC8[6Q0o2:3@>@@DH 8H┞qgy8YΎ!xM9bZ,]7H<; BO#X)~-Ôn;\a*~"rB: a44 VEyxP 7e'SZLW t-[7H奅mNd>2zF; 9"紜^*Oi{&sZVNX%}sڎӲZK&ܺJ8Q2 P~=PƬe+ÜHsVl[}ӽC+ 1"d'ov2q@ Vrͤb&4(=`XL0!E0BsJE&8x y#݋x;ň/cl1ڼ'BcKw1[t:,aV'H/$ɖeY6dTNZ60Y%h,ŗnO5\GC,=xP'K SXUF"!Gۤ[z r/ MPKӃS9PKYdKmeta.xmlˎ } 8a..jRwLJN >87)08l~$/iJtP<ΦEJ[ c=q\SՀF9O,>PKAbPKYdK.++mimetypePKYdKPPQThumbnails/thumbnail.pngPKYdKE:& ^Qstyles.xmlPKYdKXConfigurations2/popupmenu/PKYdKYConfigurations2/toolpanel/PKYdK@YConfigurations2/menubar/PKYdK'vYConfigurations2/accelerator/current.xmlPKYdKYConfigurations2/statusbar/PKYdKZConfigurations2/floater/PKYdK;ZConfigurations2/toolbar/PKYdKqZConfigurations2/images/Bitmaps/PKYdKZConfigurations2/progressbar/PKYdKvf$f$5ZPictures/100000000000040000000300B5F9E555E6F721F5.jpgPKYdKzn# settings.xmlPKYdKӃS9 ߄content.xmlPKYdKکmeta.xmlPKYdKAbMETA-INF/manifest.xmlPKrCarla-2.1/data/stoat-supression.txt000066400000000000000000000000511364475620200174170ustar00rootroot00000000000000getBridgeInstance JackBridge::JackBridge Carla-2.1/data/stoat-whitelist.txt000066400000000000000000000000661364475620200172270ustar00rootroot00000000000000jackbridge_port_get_buffer jackbridge_transport_query Carla-2.1/data/stoat/000077500000000000000000000000001364475620200144525ustar00rootroot00000000000000Carla-2.1/data/stoat/blacklist.txt000066400000000000000000000002411364475620200171600ustar00rootroot00000000000000malloc free realloc fwrite vfprintf access pthread_mutex_lock std::mutex::lock std::condition_variable::wait getcwd open _ZNSo5flushEv _ZdlPv _ZdaPv _Znwm _Znaj Carla-2.1/data/stoat/run-stoat.sh000077500000000000000000000005571364475620200167540ustar00rootroot00000000000000#!/bin/bash cd $(dirname $0)/../.. # make distclean export CC=stoat-compile export CXX=stoat-compile++ export CFLAGS="-DJACKBRIDGE_DIRECT=1 -DSTOAT_TEST_BUILD=1" export CXXFLAGS=${CFLAGS} export LDFLAGS="-ljack" make -j 8 EXTERNAL_PLUGINS=false backend && \ stoat --recursive build/ -b data/stoat/blacklist.txt -w data/stoat/whitelist.txt # -G stoat-output.png Carla-2.1/data/stoat/whitelist.txt000066400000000000000000000076461364475620200172440ustar00rootroot00000000000000cos cosl cosf sin sinl sinf tan tanl tanf tanh tanhl tanhf abs fabs fabsf fabsl cabs fmin fminf fminl fmax fmaxf fmaxl exp exp2f expf expl pow powf powl fmod fmodf fmodl memset memcpy strlen strcpy strcmp snprintf strtol strcasecmp toupper towupper strcasestr index jack_port_get_buffer jack_midi_clear_buffer jack_midi_get_event_count jack_midi_event_get jack_get_sample_rate jack_ringbuffer_read_space jack_ringbuffer_read_advance jack_ringbuffer_write_space jack_ringbuffer_get_read_vector jack_transport_query jack_get_current_transport_frame jack_get_buffer_size jack_midi_event_write jack_ringbuffer_peek jack_last_frame_time jack_midi_max_event_size jack_client_thread_id jack_get_cycle_times std::__throw_bad_function_call std::__throw_bad_alloc std::_Rb_tree_increment sem_post sem_getvalue sem_trywait pthread_cond_signal pthread_mutex_trylock pthread_mutex_unlock pthread_rwlock_unlock pthread_rwlock_tryrdlock pthread_self pthread_setspecific pthread_getspecific jack_ringbuffer_read jack_ringbuffer_write jack_midi_event_reserve (process_callback) isalnum isalpha isascii isblank iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit sprintf # std::basic_string, std::allocator >::c_str _ZNKSs5c_strEv _ZNKSs6lengthEv ceil ceilf rint isnan atoi atof strncmp strstr memmove strncpy sinh log logf logl log10 log10f log10l log2 log2f log2l asinh atan atanh atanf sqrt floor floorf sqrtf ffs ffsl ffsll rint rintf rintl lrint lrintf lrintl llrint llrintf llrintl nearbyintf round roundf roundl trunc truncf truncl modf modff modfl carg asinf copysign copysignf copysignl errx warnx cexp cabsf __fmod_finite __fmodf_finite __expf_finite __logf_finite __log_finite __log10_finite __exp_finite __expf_finite __muldc3 __asinf_finite __log10f_finite __sinh_finite __sinhf_finite __ctype_b_loc std::rint rint strcat strncat memcmp vsnprintf abort __assert_fail fftw_execute rtosc_message rtosc_vmessage rtosc_amessage rtosc_narguments rtosc_type rtosc_argument rtosc_message_length rtosc_message_ring_length rtosc_argument_string rtosc_bundle rtosc_bundle_elements rtosc_bundle_fetch rtosc_bundle_size rtosc_bundle_p rtosc_bundle_timetag rtosc_match rtosc_match_path rtosc::Ports::dispatch rtosc::RtData::RtData std::__throw_out_of_range std::__throw_length_error __cxa_begin_catch __cxa_rethrow __cxa_call_unexpected __cxa_end_catch __cxa_guard_acquire __cxa_atexit __cxa_guard_release __cxa_guard_abort __dynamic_cast _ZSt9terminatev rand scalbnf strchr __log2_finite __divdc3 __mulsc3 _ZNSt6chrono3_V212system_clock3nowEv _ZNSt3__16chrono12steady_clock3nowEv _ZNSt18condition_variable10notify_allEv _ZNSt18condition_variable10notify_oneEv # hacks here struct.rtosc::RtData0 struct.rtosc::RtData1 struct.rtosc::RtData2 # This might not be 100% RT safe, but they're external libs outside of our control fluid_synth_all_notes_off fluid_synth_all_sounds_off fluid_synth_cc fluid_synth_channel_pressure fluid_synth_get_active_voice_count fluid_synth_noteoff fluid_synth_noteon fluid_synth_program_select fluid_synth_pitch_bend fluid_synth_process fluid_synth_write_float LinuxSampler::AudioOutputDevice::RenderAudio LinuxSampler::AudioOutputDevicePlugin::Render LinuxSampler::MidiInputPort::DispatchControlChange LinuxSampler::MidiInputPort::DispatchNoteOff LinuxSampler::MidiInputPort::DispatchNoteOn LinuxSampler::MidiInputPort::DispatchControlChange LinuxSampler::MidiInputPort::DispatchRaw LinuxSampler::EngineChannel::GetDiskStreamCount LinuxSampler::EngineChannel::GetVoiceCount # TODO __carla_fopen carla_safe_assert carla_stderr2 carla_sem_timedwait # TODO: recheck LinuxSampler::AudioOutputDevice::Channel # FIXME: real non-rt safe stuff fluid_synth_set_reverb_on fluid_synth_set_reverb fluid_synth_set_chorus_on fluid_synth_set_chorus fluid_synth_set_polyphony fluid_synth_set_interp_method LinuxSampler::InstrumentManager::LoadInstrumentInBackground # Report upstream llround llabs clock_gettime RtLinkedList$vtable3 Carla-2.1/data/valgrind.sh000077500000000000000000000013621364475620200154670ustar00rootroot00000000000000#!/bin/bash export CARLA_VALGRIND_TEST=1 export WINEDEBUG=-all # export CARLA_DEV=1 # export PYTHONMALLOC=malloc # export SKIP_STRIPPING=true valgrind \ --tool=memcheck \ --leak-check=full \ --show-leak-kinds=all \ --track-origins=yes \ --gen-suppressions=all \ --suppressions=./data/valgrind.supp \ -- ./bin/carla-bridge-native internal "" carlapatchbay & PID=$! while true; do if jack_lsp | grep -q Carla-Patchbay:output_1; then jack_connect Carla-Patchbay:output_2 system:playback_2 jack_connect Carla-Patchbay:output_1 system:playback_1 # jack_connect Carla-Patchbay:events-out "a2j:ZynAddSubFX [129] (playback): ZynAddSubFX" break else sleep 1 fi done wait ${PID} Carla-2.1/data/valgrind.supp000066400000000000000000000015121364475620200160360ustar00rootroot00000000000000# ld related errors, unfixed since the dawn of time { _dl_init-1 Memcheck:Leak match-leak-kinds: reachable ... fun:call_init fun:_dl_init obj:/lib/x86_64-linux-gnu/ld-2.27.so } { _dl_init-2 Memcheck:Leak match-leak-kinds: possible ... fun:call_init fun:_dl_init obj:/lib/x86_64-linux-gnu/ld-2.27.so } { _dl_init-3 Memcheck:Leak match-leak-kinds: definite ... fun:call_init fun:_dl_init obj:/lib/x86_64-linux-gnu/ld-2.27.so } { dlclose-1 Memcheck:Leak match-leak-kinds: reachable fun:calloc fun:_dlerror_run fun:dlopen@@GLIBC_2.2.5 ... } { dlclose-2 Memcheck:Leak match-leak-kinds: reachable ... fun:_dl_open ... } # XInitThreads { XInitThreads Memcheck:Leak match-leak-kinds: reachable fun:malloc fun:XInitThreads ... } Carla-2.1/data/windows/000077500000000000000000000000001364475620200150125ustar00rootroot00000000000000Carla-2.1/data/windows/Dockerfile000066400000000000000000000032231364475620200170040ustar00rootroot00000000000000FROM ubuntu:18.04 MAINTAINER falkTX ENV DEBIAN_FRONTEND noninteractive # enable i386 RUN dpkg --add-architecture i386 RUN echo "deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu/ bionic main restricted universe multiverse" > /etc/apt/sources.list && \ echo "deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu/ bionic-updates main restricted universe multiverse" >> /etc/apt/sources.list && \ echo "deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu/ bionic-backports main restricted universe multiverse" >> /etc/apt/sources.list && \ echo "deb [arch=amd64,i386] http://security.ubuntu.com/ubuntu bionic-security main restricted universe multiverse" >> /etc/apt/sources.list # update and upgrade system RUN apt-get update && apt-get upgrade -qy && apt-get clean # install packages RUN apt-get install -qy mingw-w64 && \ apt-get install -qy qemu-user-static libwine-development-dev wine64-development-tools && \ apt-get install -qy locales acl bash bash-completion git nano patch python3 tar wget && \ apt-get install -qy automake binutils build-essential cmake libglib2.0-dev-bin libtool-bin && \ apt-get clean # basic setup RUN locale-gen en_US.UTF-8 RUN echo "source /etc/bash_completion" >> $HOME/.bashrc # user configurations ENV USER builder ENV HOME /home/$USER # create user RUN useradd -d $HOME -m -G sudo $USER # switch user USER $USER # checkout scripts dir RUN mkdir $HOME/scripts RUN mkdir $HOME/scripts/patches COPY common.env build-*.sh $HOME/scripts/ COPY patches/* $HOME/scripts/patches/ # build deps WORKDIR $HOME/scripts RUN ./build-deps.sh RUN ./build-pyqt.sh # CMD CMD ["bash"] Carla-2.1/data/windows/README.txt000066400000000000000000000025361364475620200165160ustar00rootroot00000000000000# --- README for Carla - Windows build --- What is Carla? --------------- Carla is a fully-featured audio plugin host, with support for many audio drivers and plugin formats.
It's open source and licensed under the GNU General Public License, version 2 or later. Features --------- * LADSPA, DSSI, LV2 and VST2 and VST3 plugin formats * SF2/3 and SFZ sound banks * Internal audio and midi file player * Automation of plugin parameters via MIDI CC * Remote control over OSC * Rack and Patchbay processing modes, plus Single and Multi-Client if using JACK * Native audio drivers (ALSA, DirectSound, CoreAudio, etc) and JACK * Transport controls, sync with JACK Transport or Ableton Link In experimental phase / work in progress: * Export any Carla loadable plugin or sound bank as an LV2 plugin * Plugin bridge support (such as running 32bit plugins on a 64bit Carla, or Windows plugins on Linux) Carla is also available as an LV2 and VST2 plugin for Windows. For the LV2 plugin, create the "C:\Program Files\Common Files\LV2" folder (if it does not exist yet), then copy Carla.lv2 into it and restart your LV2 host. For the VST2 plugin, create the "C:\Program Files\Common Files\VST2" folder (if it does not exist yet), then copy Carla.vst into it and restart your VST2 host. For a complete and updated description of Carla, please check: https://kx.studio/carla Carla-2.1/data/windows/app-console.py000066400000000000000000000022211364475620200176010ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------------------------------------ # Imports (cx_Freeze) from cx_Freeze import setup, Executable # ------------------------------------------------------------------------------------------------------------ # Imports (Custom Stuff) from carla_host import VERSION # ------------------------------------------------------------------------------------------------------------ options = { "zip_include_packages": ["*"], "zip_exclude_packages": ["PyQt5"], "replace_paths": [["*",".\\lib\\"]], "build_exe": ".\\Carla\\", "optimize": True, } exe_options = { "script": "..\\..\\source\\frontend\\carla", "icon": "..\\..\\resources\\ico\\carla.ico", "copyright": "Copyright (C) 2011-2019 Filipe Coelho", "targetName": "CarlaDebug.exe", } setup(name = "Carla", version = VERSION, description = "Carla Plugin Host", options = {"build_exe": options}, executables = [Executable(**exe_options)]) # ------------------------------------------------------------------------------------------------------------ Carla-2.1/data/windows/app-control.py000066400000000000000000000023121364475620200176200ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------------------------------------ # Imports (cx_Freeze) from cx_Freeze import setup, Executable # ------------------------------------------------------------------------------------------------------------ # Imports (Custom Stuff) from carla_host import VERSION # ------------------------------------------------------------------------------------------------------------ options = { "zip_include_packages": ["*"], "zip_exclude_packages": ["PyQt5"], "replace_paths": [["*",".\\lib\\"]], "build_exe": ".\\CarlaControl\\", "optimize": True, } exe_options = { "script": "..\\..\\source\\frontend\\carla-control", "icon": "..\\..\\resources\\ico\\carla-control.ico", "copyright": "Copyright (C) 2011-2019 Filipe Coelho", "base": "Win32GUI", "targetName": "CarlaControl.exe", } setup(name = "CarlaControl", version = VERSION, description = "Carla Remote Control", options = {"build_exe": options}, executables = [Executable(**exe_options)]) # ------------------------------------------------------------------------------------------------------------ Carla-2.1/data/windows/app-gui.py000066400000000000000000000022421364475620200167260ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------------------------------------ # Imports (cx_Freeze) from cx_Freeze import setup, Executable # ------------------------------------------------------------------------------------------------------------ # Imports (Custom Stuff) from carla_host import VERSION # ------------------------------------------------------------------------------------------------------------ options = { "zip_include_packages": ["*"], "zip_exclude_packages": ["PyQt5"], "replace_paths": [["*",".\\lib\\"]], "build_exe": ".\\Carla\\", "optimize": True, } exe_options = { "script": "..\\..\\source\\frontend\\carla", "icon": "..\\..\\resources\\ico\\carla.ico", "copyright": "Copyright (C) 2011-2020 Filipe Coelho", "base": "Win32GUI", "targetName": "Carla.exe", } setup(name = "Carla", version = VERSION, description = "Carla Plugin Host", options = {"build_exe": options}, executables = [Executable(**exe_options)]) # ------------------------------------------------------------------------------------------------------------ Carla-2.1/data/windows/app-plugin-ui.py000066400000000000000000000023411364475620200200530ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------------------------------------ # Imports (cx_Freeze) from cx_Freeze import setup, Executable # ------------------------------------------------------------------------------------------------------------ # Imports (Custom Stuff) from carla_host import VERSION from os import getenv # ------------------------------------------------------------------------------------------------------------ name = getenv("TARGET_NAME") options = { "zip_include_packages": ["*"], "zip_exclude_packages": ["PyQt5"], "replace_paths": [["*",".\\lib\\"]], "build_exe": ".\\Carla\\resources\\", "optimize": True, } exe_options = { "script": "..\\..\\bin\\resources\\{}".format(name), "icon": "..\\..\\resources\\ico\\carla.ico", "copyright": "Copyright (C) 2011-2019 Filipe Coelho", "base": "Win32GUI", "targetName": "{}.exe".format(name), } setup(name = name, version = VERSION, description = name, options = {"build_exe": options}, executables = [Executable(**exe_options)]) # ------------------------------------------------------------------------------------------------------------ Carla-2.1/data/windows/build-deps.sh000077500000000000000000000275071364475620200174140ustar00rootroot00000000000000#!/bin/bash # --------------------------------------------------------------------------------------------------------------------- # stop on error set -e # --------------------------------------------------------------------------------------------------------------------- # cd to correct path cd $(dirname $0) # --------------------------------------------------------------------------------------------------------------------- # set variables source common.env # --------------------------------------------------------------------------------------------------------------------- # function to remove old stuff cleanup_prefix() { rm -rf ${TARGETDIR}/carla-w32nosse ${TARGETDIR}/carla-w32 ${TARGETDIR}/carla-w64 } cleanup_pkgs() { rm -rf Carla rm -rf Carla.exe rm -rf Carla.lv2 rm -rf Carla.vst rm -rf Carla_* rm -rf flac-* rm -rf fluidsynth-* rm -rf fftw-* rm -rf glib-* rm -rf liblo-* rm -rf libogg-* rm -rf libsndfile-* rm -rf libvorbis-* rm -rf mxml-* rm -rf pkg-config-* rm -rf pyliblo-* rm -rf zlib-* } cleanup() { cleanup_prefix cleanup_pkgs exit 0 } # ------------------------------------------------------------------------------------ # function to build base libs build_base() { # --------------------------------------------------------------------------------------------------------------------- # clean env unset AR unset CC unset CXX unset STRIP unset WINDRES unset PKG_CONFIG_PATH unset CFLAGS unset CPPFLAGS unset CXXFLAGS unset LDFLAGS export PREFIX=${TARGETDIR}/carla-w${ARCH_PREFIX} export PATH=${PREFIX}/bin:/usr/sbin:/usr/bin:/sbin:/bin export PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig # --------------------------------------------------------------------------------------------------------------------- # pkgconfig if [ ! -d pkg-config-${PKG_CONFIG_VERSION} ]; then wget -c https://pkg-config.freedesktop.org/releases/pkg-config-${PKG_CONFIG_VERSION}.tar.gz tar -xf pkg-config-${PKG_CONFIG_VERSION}.tar.gz fi if [ ! -f pkg-config-${PKG_CONFIG_VERSION}/build-done ]; then cd pkg-config-${PKG_CONFIG_VERSION} env AR="ar" CC="gcc" STRIP="strip" CFLAGS="" LDFLAGS="" PATH="/usr/sbin:/usr/bin:/sbin:/bin" \ ./configure --enable-indirect-deps --with-internal-glib --with-pc-path=${PKG_CONFIG_PATH} --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # setup if [ x"${ARCH}" != x"32" ]; then CPUARCH="x86_64" else CPUARCH="i686" fi HOST_ARCH=$(dpkg-architecture -qDEB_BUILD_GNU_TYPE) MINGW_PREFIX="${CPUARCH}-w64-mingw32" export AR=${MINGW_PREFIX}-ar export CC=${MINGW_PREFIX}-gcc export CXX=${MINGW_PREFIX}-g++ export STRIP=${MINGW_PREFIX}-strip export WINDRES=${MINGW_PREFIX}-windres if [ -z "${NOSSE}" ]; then export CFLAGS="-O3 -mtune=generic -msse -msse2 -mfpmath=sse -mstackrealign -fvisibility=hidden -fdata-sections -ffunction-sections" else export CFLAGS="-O2 -mstackrealign -fvisibility=hidden -fdata-sections -ffunction-sections" fi export CFLAGS="${CFLAGS} -DNDEBUG -DPTW32_STATIC_LIB -DFLUIDSYNTH_NOT_A_DLL -I${PREFIX}/include -I/opt/mingw${ARCH}/include" export CXXFLAGS="${CFLAGS} -fvisibility-inlines-hidden" export CPPFLAGS="-DPIC -DNDEBUG -DPTW32_STATIC_LIB -I${PREFIX}/include -I/opt/mingw${ARCH}/include" export LDFLAGS="-fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed -Wl,--strip-all" export LDFLAGS="${LDFLAGS} -L${PREFIX}/lib -L/opt/mingw${ARCH}/lib" # --------------------------------------------------------------------------------------------------------------------- # liblo if [ ! -d liblo-${LIBLO_VERSION} ]; then wget -c https://github.com/radarsat1/liblo/releases/download/${LIBLO_VERSION}/liblo-${LIBLO_VERSION}.tar.gz tar -xf liblo-${LIBLO_VERSION}.tar.gz fi if [ ! -f liblo-${LIBLO_VERSION}/build-done ]; then cd liblo-${LIBLO_VERSION} sed -i "s/@extralibs@/@extralibs@ -lm/" liblo.pc.in ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --target=${MINGW_PREFIX} --host=${MINGW_PREFIX} --build=${HOST_ARCH} \ --enable-threads \ --disable-examples --disable-tools make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # zlib if [ ! -d zlib-${ZLIB_VERSION} ]; then wget -c https://github.com/madler/zlib/archive/v${ZLIB_VERSION}.tar.gz -O zlib-${ZLIB_VERSION}.tar.gz tar -xf zlib-${ZLIB_VERSION}.tar.gz fi if [ ! -f zlib-${ZLIB_VERSION}/build-done ]; then cd zlib-${ZLIB_VERSION} ./configure --static --prefix=${PREFIX} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # libogg if [ ! -d libogg-${LIBOGG_VERSION} ]; then wget -c https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-${LIBOGG_VERSION}.tar.gz tar -xf libogg-${LIBOGG_VERSION}.tar.gz fi if [ ! -f libogg-${LIBOGG_VERSION}/build-done ]; then cd libogg-${LIBOGG_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --target=${MINGW_PREFIX} --host=${MINGW_PREFIX} --build=${HOST_ARCH} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # libvorbis if [ ! -d libvorbis-${LIBVORBIS_VERSION} ]; then wget -c https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-${LIBVORBIS_VERSION}.tar.gz tar -xf libvorbis-${LIBVORBIS_VERSION}.tar.gz fi if [ ! -f libvorbis-${LIBVORBIS_VERSION}/build-done ]; then cd libvorbis-${LIBVORBIS_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --target=${MINGW_PREFIX} --host=${MINGW_PREFIX} --build=${HOST_ARCH} make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # flac if [ ! -d flac-${FLAC_VERSION} ]; then wget -c https://ftp.osuosl.org/pub/xiph/releases/flac/flac-${FLAC_VERSION}.tar.xz tar -xf flac-${FLAC_VERSION}.tar.xz fi if [ ! -f flac-${FLAC_VERSION}/build-done ]; then cd flac-${FLAC_VERSION} chmod +x configure install-sh ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --target=${MINGW_PREFIX} --host=${MINGW_PREFIX} --build=${HOST_ARCH} \ --disable-cpplibs make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # libsndfile if [ ! -d libsndfile-${LIBSNDFILE_VERSION} ]; then wget -c http://www.mega-nerd.com/libsndfile/files/libsndfile-${LIBSNDFILE_VERSION}.tar.gz tar -xf libsndfile-${LIBSNDFILE_VERSION}.tar.gz fi if [ ! -f libsndfile-${LIBSNDFILE_VERSION}/build-done ]; then cd libsndfile-${LIBSNDFILE_VERSION} ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --target=${MINGW_PREFIX} --host=${MINGW_PREFIX} --build=${HOST_ARCH} \ --disable-full-suite --disable-alsa --disable-sqlite make ${MAKE_ARGS} make install touch build-done cd .. fi # ------------------------------------------------------------------------------------ # glib if [ ! -d glib-${GLIB_VERSION} ]; then wget -c http://caesar.ftp.acc.umu.se/pub/GNOME/sources/glib/${GLIB_MVERSION}/glib-${GLIB_VERSION}.tar.gz tar -xf glib-${GLIB_VERSION}.tar.gz fi if [ ! -f glib-${GLIB_VERSION}/build-done ]; then cd glib-${GLIB_VERSION} if [ ! -f patched ]; then patch -p1 -i ../../patches/glib_skip-gettext.patch sed -i "s|po docs|po|" Makefile.in touch patched fi chmod +x configure install-sh autoconf ./configure --enable-static --disable-shared --disable-docs --prefix=${PREFIX} \ --target=${MINGW_PREFIX} --host=${MINGW_PREFIX} --build=${HOST_ARCH} \ --with-threads=win32 make ${MAKE_ARGS} make install touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # fluidsynth if [ ! -d fluidsynth-${FLUIDSYNTH_VERSION} ]; then wget -c https://github.com/FluidSynth/fluidsynth/archive/v${FLUIDSYNTH_VERSION}.tar.gz -O fluidsynth-${FLUIDSYNTH_VERSION}.tar.gz tar -xf fluidsynth-${FLUIDSYNTH_VERSION}.tar.gz fi if [ ! -f fluidsynth-${FLUIDSYNTH_VERSION}/build-done ]; then cd fluidsynth-${FLUIDSYNTH_VERSION} if [ ! -f patched ]; then patch -p1 -i ../../patches/fluidsynth-skip-drivers-build.patch touch patched fi cmake . -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${PREFIX} -DBUILD_SHARED_LIBS=OFF \ -Denable-debug=OFF -Denable-profiling=OFF -Denable-ladspa=OFF -Denable-fpe-check=OFF -Denable-portaudio=OFF \ -Denable-trap-on-fpe=OFF -Denable-aufile=OFF -Denable-dbus=OFF -Denable-ipv6=OFF -Denable-jack=OFF \ -Denable-midishare=OFF -Denable-oss=OFF -Denable-pulseaudio=OFF -Denable-readline=OFF -Denable-ladcca=OFF \ -Denable-lash=OFF -Denable-alsa=OFF -Denable-coreaudio=OFF -Denable-coremidi=OFF -Denable-framework=OFF \ -Denable-floats=ON \ -DCMAKE_C_COMPILER_WORKS=1 \ -DCMAKE_CROSSCOMPILING=1 \ -DCMAKE_SYSTEM_NAME="Windows" \ -DCMAKE_HOST_SYSTEM_NAME=${HOST_ARCH} make ${MAKE_ARGS} make install sed -i -e "s|-lfluidsynth|-lfluidsynth -lglib-2.0 -lgthread-2.0 -lsndfile -lFLAC -lvorbisenc -lvorbis -logg -lm -ldsound -lwinmm -lole32 -lws2_32|" ${PREFIX}/lib/pkgconfig/fluidsynth.pc touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # mxml if [ ! -d mxml-${MXML_VERSION} ]; then wget -c https://github.com/michaelrsweet/mxml/releases/download/v${MXML_VERSION}/mxml-${MXML_VERSION}.tar.gz -O mxml-${MXML_VERSION}.tar.gz tar -xf mxml-${MXML_VERSION}.tar.gz fi if [ ! -f mxml-${MXML_VERSION}/build-done ]; then cd mxml-${MXML_VERSION} ./configure --disable-shared --prefix=${PREFIX} \ --target=${MINGW_PREFIX} --host=${MINGW_PREFIX} --build=${HOST_ARCH} make libmxml.a cp *.a ${PREFIX}/lib/ cp *.pc ${PREFIX}/lib/pkgconfig/ cp mxml.h ${PREFIX}/include/ touch build-done cd .. fi # --------------------------------------------------------------------------------------------------------------------- # fftw3 (needs to be last as it modifies C[XX]FLAGS) if [ ! -d fftw-${FFTW3_VERSION} ]; then curl -O http://www.fftw.org/fftw-${FFTW3_VERSION}.tar.gz tar -xf fftw-${FFTW3_VERSION}.tar.gz fi if [ ! -f fftw-${FFTW3_VERSION}/build-done ]; then export CFLAGS="${CFLAGS} -ffast-math" export CXXFLAGS="${CXXFLAGS} -ffast-math" EXTRA_ARGS="" cd fftw-${FFTW3_VERSION} if [ -z "${NOSSE}" ]; then EXTRA_ARGS="--enable-sse2" fi ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --target=${MINGW_PREFIX} --host=${MINGW_PREFIX} --build=${HOST_ARCH} \ ${EXTRA_ARGS} \ --disable-debug --disable-alloca --disable-fortran \ --with-our-malloc make make install make clean if [ -z "${NOSSE}" ]; then EXTRA_ARGS="--enable-sse2 --enable-sse" fi ./configure --enable-static --disable-shared --prefix=${PREFIX} \ --target=${MINGW_PREFIX} --host=${MINGW_PREFIX} --build=${HOST_ARCH} \ ${EXTRA_ARGS} --enable-single \ --disable-debug --disable-alloca --disable-fortran \ --with-our-malloc make make install make clean touch build-done cd .. fi } # --------------------------------------------------------------------------------------------------------------------- # build base libs cleanup_prefix cleanup_pkgs export ARCH=32 export ARCH_PREFIX=32nosse export NOSSE=1 build_base cleanup_pkgs unset NOSSE export ARCH=32 export ARCH_PREFIX=32 build_base cleanup_pkgs export ARCH=64 export ARCH_PREFIX=64 build_base cleanup_pkgs # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/data/windows/build-pyqt.sh000077500000000000000000000144561364475620200174550ustar00rootroot00000000000000#!/bin/bash # --------------------------------------------------------------------------------------------------------------------- # stop on error set -e # --------------------------------------------------------------------------------------------------------------------- # cd to correct path cd $(dirname $0) # --------------------------------------------------------------------------------------------------------------------- # set variables source common.env # --------------------------------------------------------------------------------------------------------------------- # function to remove old stuff cleanup_prefix() { rm -rf ${TARGETDIR}/msys2-i686 ${TARGETDIR}/msys2-x86_64 rm -rf python-pkgs-* } cleanup_pkgs() { rm -rf Carla rm -rf Carla.exe rm -rf Carla.lv2 rm -rf Carla.vst rm -rf Carla_* rm -rf pyliblo-* } cleanup() { cleanup_prefix cleanup_pkgs exit 0 } # --------------------------------------------------------------------------------------------------------------------- # function to download python stuff from msys2 download_python() { # --------------------------------------------------------------------------------------------------------------------- # setup if [ x"${ARCH}" != x"32" ]; then CPUARCH="x86_64" else CPUARCH="i686" fi # --------------------------------------------------------------------------------------------------------------------- # list packages PACKAGES=( "binutils-2.32-3" "bzip2-1.0.8-1" "crt-git-7.0.0.5524.2346384e-1" "dbus-1.12.8-1" "double-conversion-3.1.5-1" "expat-2.2.8-1" "freetype-2.10.1-1" "gcc-9.2.0-2" "gcc-libs-9.2.0-2" "gettext-0.19.8.1-8" "glib2-2.62.1-1" "gmp-6.1.2-1" "graphite2-1.3.13-1" "harfbuzz-2.6.2-1" "icu-64.2-1" "jasper-2.0.16-1" "libffi-3.2.1-4" "libiconv-1.16-1" "libjpeg-turbo-2.0.3-1" "libpng-1.6.37-3" "libtiff-4.0.9-2" "libwebp-1.0.3-1" "libxml2-2.9.9-2" "libxslt-1.1.33-1" "libwinpthread-git-7.0.0.5522.977a9720-1" "headers-git-7.0.0.5524.2346384e-1" "openssl-1.1.1.d-1" "pcre-8.43-1" "pcre2-10.33-1" "pyqt5-common-5.13.1-1" "python3-3.7.4-7" "python3-cx_Freeze-5.1.1-3" "python3-nuitka-0.6.4-1" "python3-sip-4.19.19-1" "python3-pyqt5-5.13.1-1" "qt5-5.13.1-1" "qtwebkit-5.212.0alpha2-6" "sqlite3-3.30.0-1" "windows-default-manifest-6.4-3" "winpthreads-git-7.0.0.5522.977a9720-1" "xz-5.2.4-1" "zlib-1.2.11-7" "zstd-1.4.3-1" ) # qt5-static-5.12.4-1 PKG_DIR="$(pwd)/python-pkgs-${CPUARCH}" PKG_PREFIX="mingw-w64-${CPUARCH}-" PKG_SUFFIX="-any.pkg.tar.xz" REPO_URL="http://repo.msys2.org/mingw/${CPUARCH}" # --------------------------------------------------------------------------------------------------------------------- # download stuff mkdir -p "${PKG_DIR}" pushd "${PKG_DIR}" for PKG in ${PACKAGES[@]}; do wget -c "${REPO_URL}/${PKG_PREFIX}${PKG}${PKG_SUFFIX}" done popd # --------------------------------------------------------------------------------------------------------------------- # extract into target dir rm -rf "${TARGETDIR}/msys2-${CPUARCH}" mkdir "${TARGETDIR}/msys2-${CPUARCH}" pushd "${TARGETDIR}/msys2-${CPUARCH}" for PKG in ${PACKAGES[@]}; do tar xf "${PKG_DIR}/${PKG_PREFIX}${PKG}${PKG_SUFFIX}" done sed -i "s|E:/mingwbuild/mingw-w64-qt5/pkg/mingw-w64-${CPUARCH}-qt5|${TARGETDIR}/msys2-${CPUARCH}|" ./mingw${ARCH}/lib/pkgconfig/Qt5*.pc popd } # --------------------------------------------------------------------------------------------------------------------- # function to build python modules build_python() { # --------------------------------------------------------------------------------------------------------------------- # setup if [ x"${ARCH}" != x"32" ]; then CPUARCH="x86_64" else CPUARCH="i686" fi # --------------------------------------------------------------------------------------------------------------------- # clean env unset AR unset CC unset CXX unset STRIP unset WINDRES unset CFLAGS unset CPPFLAGS unset CXXFLAGS unset LDFLAGS export DEPS_PREFIX=${TARGETDIR}/carla-w${ARCH_PREFIX} export MSYS2_PREFIX=${TARGETDIR}/msys2-${CPUARCH}/mingw${ARCH} export PATH=${DEPS_PREFIX}/bin:${MSYS2_PREFIX}/bin:/usr/sbin:/usr/bin:/sbin:/bin export PKG_CONFIG_PATH=${DEPS_PREFIX}/lib/pkgconfig:${MSYS2_PREFIX}/lib/pkgconfig HOST_ARCH=$(dpkg-architecture -qDEB_BUILD_GNU_TYPE) MINGW_PREFIX="${CPUARCH}-w64-mingw32" export AR=${MINGW_PREFIX}-ar export CC=${MINGW_PREFIX}-gcc export CXX=${MINGW_PREFIX}-g++ export STRIP=${MINGW_PREFIX}-strip export WINDRES=${MINGW_PREFIX}-windres export CFLAGS="-O2 -DNDEBUG -mstackrealign -fvisibility=hidden -fdata-sections -ffunction-sections" export CFLAGS="${CFLAGS} -I${DEPS_PREFIX}/include -I${MSYS2_PREFIX}/include" export CXXFLAGS="${CFLAGS} -fvisibility-inlines-hidden" export LDFLAGS="-Wl,--gc-sections -Wl,-O1 -Wl,--as-needed -Wl,--strip-all" export LDFLAGS="${LDFLAGS} -L${DEPS_PREFIX}/lib -L${MSYS2_PREFIX}/lib" # --------------------------------------------------------------------------------------------------------------------- # pyliblo if [ ! -d pyliblo-${PYLIBLO_VERSION} ]; then wget -c http://das.nasophon.de/download/pyliblo-${PYLIBLO_VERSION}.tar.gz tar -xf pyliblo-${PYLIBLO_VERSION}.tar.gz fi if [ ! -f pyliblo-${PYLIBLO_VERSION}/build-done ]; then cd pyliblo-${PYLIBLO_VERSION} if [ ! -f patched ]; then patch -p1 -i ../../patches/pyliblo-python3.7.patch touch patched fi mkdir -p build # build ${CC} -pthread -Wall ${CFLAGS} \ src/liblo.c -c -o build/liblo.o \ $(python3-config --cflags | awk 'sub("-ne ","")') \ -D_FORTIFY_SOURCE=2 -fPIC -fno-strict-aliasing \ -Wdate-time -Werror-implicit-function-declaration -Wfatal-errors # link ${CC} -pthread -shared ${LDFLAGS} \ build/liblo.o -o build/liblo-cpython-37m.dll \ -llo $(python3-config --ldflags | awk 'sub("-ne ","")') -lws2_32 -liphlpapi # install install -m 644 build/liblo-cpython-37m.dll ${MSYS2_PREFIX}/lib/python3.7/site-packages/ touch build-done cd .. fi } # --------------------------------------------------------------------------------------------------------------------- # build base libs export ARCH=32 export ARCH_PREFIX=32nosse download_python build_python cleanup_pkgs export ARCH=64 export ARCH_PREFIX=64 download_python build_python cleanup_pkgs # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/data/windows/build-win-all.sh000077500000000000000000000016261364475620200200160ustar00rootroot00000000000000#!/bin/bash VERSION="2.1" # --------------------------------------------------------------------------------------------------------------------- # stop on error set -e # --------------------------------------------------------------------------------------------------------------------- # cd to correct path if [ ! -f Makefile ]; then cd $(dirname $0)/../.. fi # --------------------------------------------------------------------------------------------------------------------- # start make distclean pushd data/windows ./build-win.sh 32nosse ./pack-win.sh 32nosse mv Carla_${VERSION}-win32.zip Carla_${VERSION}-win32-nosse.zip popd make distclean pushd data/windows ./build-win.sh 32 ./pack-win.sh 32 popd make distclean pushd data/windows ./build-win.sh 64 ./pack-win.sh 64 popd # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/data/windows/build-win.sh000077500000000000000000000055101364475620200172440ustar00rootroot00000000000000#!/bin/bash # --------------------------------------------------------------------------------------------------------------------- # check input ARCH="${1}" ARCH_PREFIX="${1}" if [ x"${ARCH}" != x"32" ] && [ x"${ARCH}" != x"32nosse" ] && [ x"${ARCH}" != x"64" ]; then echo "usage: $0 32|32nonosse|64" exit 1 fi # --------------------------------------------------------------------------------------------------------------------- # stop on error set -e # --------------------------------------------------------------------------------------------------------------------- # cd to correct path if [ ! -f Makefile ]; then cd $(dirname $0)/../.. fi # --------------------------------------------------------------------------------------------------------------------- # set variables source data/windows/common.env if [ x"${ARCH}" = x"32nosse" ]; then ARCH="32" MAKE_ARGS="${MAKE_ARGS} NOOPT=true" fi MAKE_ARGS="${MAKE_ARGS} BUILDING_FOR_WINDOWS=true USING_JUCE=true" export WIN32=true if [ x"${ARCH}" != x"32" ]; then export WIN64=true CPUARCH="x86_64" else CPUARCH="i686" fi # --------------------------------------------------------------------------------------------------------------------- export_vars() { local _ARCH="${1}" local _ARCH_PREFIX="${2}" local _MINGW_PREFIX="${3}-w64-mingw32" export DEPS_PREFIX=${TARGETDIR}/carla-w${ARCH_PREFIX} export MSYS2_PREFIX=${TARGETDIR}/msys2-${CPUARCH}/mingw${ARCH} export PATH=${DEPS_PREFIX}/bin:/opt/wine-staging/bin:/usr/sbin:/usr/bin:/sbin:/bin export PKG_CONFIG_PATH=${DEPS_PREFIX}/lib/pkgconfig:${MSYS2_PREFIX}/lib/pkgconfig export AR=${_MINGW_PREFIX}-ar export CC=${_MINGW_PREFIX}-gcc export CXX=${_MINGW_PREFIX}-g++ export STRIP=${_MINGW_PREFIX}-strip export WINDRES=${_MINGW_PREFIX}-windres export CFLAGS="-DPTW32_STATIC_LIB -DFLUIDSYNTH_NOT_A_DLL" export CFLAGS="${CFLAGS} -I${DEPS_PREFIX}/include" export CXXFLAGS="${CFLAGS}" export LDFLAGS="-L${DEPS_PREFIX}/lib" export MOC_QT5="wine ${MSYS2_PREFIX}/bin/moc.exe" export RCC_QT5="wine ${MSYS2_PREFIX}/bin/rcc.exe" export UIC_QT5="wine ${MSYS2_PREFIX}/bin/uic.exe" } # --------------------------------------------------------------------------------------------------------------------- export_vars "${ARCH}" "${ARCH_PREFIX}" "${CPUARCH}" export WINEARCH=win${ARCH} export WINEDEBUG=-all export WINEPREFIX=~/.winepy3_x${ARCH} export PYTHON_EXE="wine ${MSYS2_PREFIX}/bin/python.exe" export PYRCC5="${PYTHON_EXE} -m PyQt5.pyrcc_main" export PYUIC5="${PYTHON_EXE} -m PyQt5.uic.pyuic" make ${MAKE_ARGS} if [ x"${ARCH}" != x"32" ]; then export_vars "32" "32" "i686" make ${MAKE_ARGS} win32 fi # Testing: echo "export WINEPREFIX=~/.winepy3_x${ARCH}" echo "/opt/wine-staging/bin/${PYTHON_EXE} ./source/frontend/carla" # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/data/windows/common.env000066400000000000000000000005401364475620200170130ustar00rootroot00000000000000#!/bin/bash PKG_CONFIG_VERSION=0.28 LIBLO_VERSION=0.30 ZLIB_VERSION=1.2.11 FILE_VERSION=5.34 LIBOGG_VERSION=1.3.4 LIBVORBIS_VERSION=1.3.6 FLAC_VERSION=1.3.2 LIBSNDFILE_VERSION=1.0.28 GLIB_VERSION=2.22.5 GLIB_MVERSION=2.22 FLUIDSYNTH_VERSION=1.1.11 MXML_VERSION=2.12 FFTW3_VERSION=3.3.8 PYLIBLO_VERSION=0.9.2 MAKE_ARGS="-j 4" TARGETDIR=${HOME}/builds Carla-2.1/data/windows/create-wineprefixes.sh000077500000000000000000000013221364475620200213200ustar00rootroot00000000000000#!/bin/bash rm -rf ~/.winepy3 rm -rf ~/.winepy3_x32 rm -rf ~/.winepy3_x86 rm -rf ~/.winepy3_x64 export WINEARCH=win32 export WINEPREFIX=~/.winepy3_x32 wineboot winetricks winxp winetricks vcrun2010 winetricks corefonts winetricks fontsmooth=rgb # cd data/windows/python # msiexec /i python-3.4.4.msi /qn # wine cx_Freeze-4.3.4.win32-py3.4.exe # wine PyQt5-5.5.1-gpl-Py3.4-Qt5.5.1-x32.exe # cd ../../.. export WINEARCH=win64 export WINEPREFIX=~/.winepy3_x64 wineboot winetricks win7 winetricks vcrun2010 winetricks corefonts winetricks fontsmooth=rgb # cd data/windows/python # msiexec /i python-3.4.4.amd64.msi /qn # wine cx_Freeze-4.3.4.win-amd64-py3.4.exe # wine PyQt5-5.5.1-gpl-Py3.4-Qt5.5.1-x64.exe # cd ../../.. Carla-2.1/data/windows/pack-win.sh000077500000000000000000000222541364475620200170670ustar00rootroot00000000000000#!/bin/bash # --------------------------------------------------------------------------------------------------------------------- # check input ARCH="${1}" ARCH_PREFIX="${1}" if [ x"${ARCH}" != x"32" ] && [ x"${ARCH}" != x"32nosse" ] && [ x"${ARCH}" != x"64" ]; then echo "usage: $0 32|32nosse|64" exit 1 fi if [ x"${ARCH}" = x"32nosse" ]; then ARCH="32" MAKE_ARGS="NOOPT=true" fi # --------------------------------------------------------------------------------------------------------------------- # stop on error set -e # --------------------------------------------------------------------------------------------------------------------- # cd to correct path if [ ! -f Makefile ]; then cd $(dirname $0)/../.. fi # --------------------------------------------------------------------------------------------------------------------- # set variables source data/windows/common.env PKG_FOLDER="Carla_2.1-win${ARCH}" export WIN32=true if [ x"${ARCH}" != x"32" ]; then export WIN64=true CPUARCH="x86_64" else CPUARCH="i686" fi export PYTHONPATH="$(pwd)/source/frontend" # --------------------------------------------------------------------------------------------------------------------- export_vars() { local _ARCH="${1}" local _ARCH_PREFIX="${2}" local _MINGW_PREFIX="${3}-w64-mingw32" export DEPS_PREFIX=${TARGETDIR}/carla-w${ARCH_PREFIX} export MSYS2_PREFIX=${TARGETDIR}/msys2-${CPUARCH}/mingw${ARCH} export PATH=${DEPS_PREFIX}/bin:/opt/wine-staging/bin:/usr/sbin:/usr/bin:/sbin:/bin export PKG_CONFIG_PATH=${DEPS_PREFIX}/lib/pkgconfig:${MSYS2_PREFIX}/lib/pkgconfig export AR=${_MINGW_PREFIX}-ar export CC=${_MINGW_PREFIX}-gcc export CXX=${_MINGW_PREFIX}-g++ export STRIP=${_MINGW_PREFIX}-strip export WINDRES=${_MINGW_PREFIX}-windres export CFLAGS="-DPTW32_STATIC_LIB -DFLUIDSYNTH_NOT_A_DLL" export CFLAGS="${CFLAGS} -I${DEPS_PREFIX}/include" export CXXFLAGS="${CFLAGS}" export LDFLAGS="-L${DEPS_PREFIX}/lib" export WINEARCH=win${ARCH} export WINEDEBUG=-all export WINEPREFIX=~/.winepy3_x${ARCH} export PYTHON_EXE="wine ${MSYS2_PREFIX}/bin/python.exe" export CXFREEZE="${PYTHON_EXE} ${MSYS2_PREFIX}/bin/cxfreeze" } # --------------------------------------------------------------------------------------------------------------------- export_vars "${ARCH}" "${ARCH_PREFIX}" "${CPUARCH}" # --------------------------------------------------------------------------------------------------------------------- cd data/windows/ rm -rf Carla Carla.lv2 Carla.vst CarlaControl # --------------------------------------------------------------------------------------------------------------------- # freeze carla (console and gui) ${PYTHON_EXE} ./app-console.py build_exe mv Carla/lib/library.zip Carla/lib/library-console.zip ${PYTHON_EXE} ./app-gui.py build_exe mv Carla/lib/library.zip Carla/lib/library-gui.zip mkdir Carla/lib/_lib pushd Carla/lib/_lib unzip -o ../library-console.zip unzip -o ../library-gui.zip zip -r -9 ../library.zip * popd rm -r Carla/lib/_lib Carla/lib/library-*.zip # --------------------------------------------------------------------------------------------------------------------- # freeze carla-control ${PYTHON_EXE} ./app-control.py build_exe # --------------------------------------------------------------------------------------------------------------------- # freeze pyqt plugin uis (resources) TARGET_NAME="bigmeter-ui" ${PYTHON_EXE} ./app-plugin-ui.py build_exe mv Carla/resources/lib/library.zip Carla/resources/lib/library-bigmeter.zip TARGET_NAME="midipattern-ui" ${PYTHON_EXE} ./app-plugin-ui.py build_exe mv Carla/resources/lib/library.zip Carla/resources/lib/library-midipattern.zip TARGET_NAME="notes-ui" ${PYTHON_EXE} ./app-plugin-ui.py build_exe mv Carla/resources/lib/library.zip Carla/resources/lib/library-notes.zip TARGET_NAME="carla-plugin" ${PYTHON_EXE} ./app-plugin-ui.py build_exe mv Carla/resources/lib/library.zip Carla/resources/lib/library-carla1.zip TARGET_NAME="carla-plugin-patchbay" ${PYTHON_EXE} ./app-plugin-ui.py build_exe mv Carla/resources/lib/library.zip Carla/resources/lib/library-carla2.zip mkdir Carla/resources/lib/_lib pushd Carla/resources/lib/_lib unzip -o ../library-bigmeter.zip unzip -o ../library-midipattern.zip unzip -o ../library-notes.zip unzip -o ../library-carla1.zip unzip -o ../library-carla2.zip zip -r -9 ../library.zip * popd rm -r Carla/resources/lib/_lib Carla/resources/lib/library-*.zip # --------------------------------------------------------------------------------------------------------------------- # cleanup pyqt stuff find Carla CarlaControl -name "QAxContainer*" -delete find Carla CarlaControl -name "QtDBus*" -delete find Carla CarlaControl -name "QtDesigner*" -delete find Carla CarlaControl -name "QtBluetooth*" -delete find Carla CarlaControl -name "QtHelp*" -delete find Carla CarlaControl -name "QtLocation*" -delete find Carla CarlaControl -name "QtMultimedia*" -delete find Carla CarlaControl -name "QtMultimediaWidgets*" -delete find Carla CarlaControl -name "QtNetwork*" -delete find Carla CarlaControl -name "QtNetworkAuth*" -delete find Carla CarlaControl -name "QtNfc*" -delete find Carla CarlaControl -name "QtPositioning*" -delete find Carla CarlaControl -name "QtPrintSupport*" -delete find Carla CarlaControl -name "QtQml*" -delete find Carla CarlaControl -name "QtQuick*" -delete find Carla CarlaControl -name "QtQuickWidgets*" -delete find Carla CarlaControl -name "QtRemoteObjects*" -delete find Carla CarlaControl -name "QtSensors*" -delete find Carla CarlaControl -name "QtSerialPort*" -delete find Carla CarlaControl -name "QtSql*" -delete find Carla CarlaControl -name "QtTest*" -delete find Carla CarlaControl -name "QtWebChannel*" -delete find Carla CarlaControl -name "QtWebKit*" -delete find Carla CarlaControl -name "QtWebKitWidgets*" -delete find Carla CarlaControl -name "QtWebSockets*" -delete find Carla CarlaControl -name "QtWinExtras*" -delete find Carla CarlaControl -name "QtXml*" -delete find Carla CarlaControl -name "QtXmlPatterns*" -delete find Carla CarlaControl -name "*.pyi" -delete # --------------------------------------------------------------------------------------------------------------------- # copy relevant files to binary dir cp ../../bin/libcarla_standalone2.dll Carla/ cp ../../bin/libcarla_utils.dll Carla/ cp ../../bin/carla-bridge-lv2.dll Carla/ cp ../../bin/carla-bridge-*.exe Carla/ cp ../../bin/carla-discovery-win*.exe Carla/ mkdir -p Carla/imageformats cp ${MSYS2_PREFIX}/share/qt5/plugins/imageformats/qsvg.dll Carla/imageformats/ mkdir -p Carla/platforms cp ${MSYS2_PREFIX}/share/qt5/plugins/platforms/qwindows.dll Carla/platforms/ mkdir -p Carla/styles cp ../../bin/styles/carlastyle.dll Carla/styles/ # --------------------------------------------------------------------------------------------------------------------- # also for CarlaControl cp ../../bin/libcarla_utils.dll CarlaControl/ mkdir -p CarlaControl/imageformats cp ${MSYS2_PREFIX}/share/qt5/plugins/imageformats/qsvg.dll CarlaControl/imageformats/ mkdir -p CarlaControl/platforms cp ${MSYS2_PREFIX}/share/qt5/plugins/platforms/qwindows.dll CarlaControl/platforms/ mkdir -p CarlaControl/styles cp ../../bin/styles/carlastyle.dll CarlaControl/styles/ # --------------------------------------------------------------------------------------------------------------------- # prepare lv2 bundle mkdir -p Carla.lv2 cp -r Carla/* Carla.lv2/ cp ../../bin/carla.lv2/*.dll Carla.lv2/ cp ../../bin/carla.lv2/*.ttl Carla.lv2/ rm Carla.lv2/Carla.exe rm Carla.lv2/CarlaDebug.exe # --------------------------------------------------------------------------------------------------------------------- # copy relevant files to binary dir mkdir -p Carla.vst cp -r Carla/* Carla.vst/ cp ../../bin/CarlaVst*.dll Carla.vst/ rm Carla.vst/Carla.exe rm Carla.vst/CarlaDebug.exe # --------------------------------------------------------------------------------------------------------------------- # stop here for development if [ x"${CARLA_DEV}" != x"" ]; then exit 0 fi # --------------------------------------------------------------------------------------------------------------------- # create self-contained zip # Build unzipfx make -C unzipfx-carla -f Makefile.win32 clean make -C unzipfx-carla -f Makefile.win32 ${MAKE_ARGS} # Build unzipfx-control make -C unzipfx-carla-control -f Makefile.win32 clean make -C unzipfx-carla-control -f Makefile.win32 ${MAKE_ARGS} # Create zip of Carla and CarlaControl rm -f Carla.zip CarlaControl.zip mv Carla Carla-2.1 mv CarlaControl CarlaControl-2.1 zip -r -9 Carla.zip Carla-2.1 zip -r -9 CarlaControl.zip CarlaControl-2.1 # Create static builds rm -f Carla.exe cat unzipfx-carla/unzipfx2cat.exe Carla.zip > Carla.exe chmod +x Carla.exe rm -f CarlaControl.exe cat unzipfx-carla-control/unzipfx2cat.exe CarlaControl.zip > CarlaControl.exe chmod +x CarlaControl.exe # Cleanup rm -f Carla.zip CarlaControl.zip rm -rf Carla-2.1 CarlaControl-2.1 # Create release zip rm -rf ${PKG_FOLDER} mkdir ${PKG_FOLDER} cp -r Carla.exe CarlaControl.exe Carla.lv2 Carla.vst README.txt ${PKG_FOLDER} unix2dos ${PKG_FOLDER}/README.txt zip -r -9 ${PKG_FOLDER}.zip ${PKG_FOLDER} cd ../.. # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/data/windows/unzipfx-carla-control/000077500000000000000000000000001364475620200212535ustar00rootroot00000000000000Carla-2.1/data/windows/unzipfx-carla-control/.gitignore000066400000000000000000000000411364475620200232360ustar00rootroot00000000000000 *~ *.o *.exe *.zip unzipfx2cat Carla-2.1/data/windows/unzipfx-carla-control/Makefile.linux000066400000000000000000000012051364475620200240470ustar00rootroot00000000000000#!/usr/bin/Makefile -f CC ?= gcc BUILD_FLAGS = -DSFX -DLINUX -I. -I.. $(CFLAGS) -O2 BUILD_FLAGS += -DLARGE_FILE_SUPPORT -DUNICODE_SUPPORT -DUNICODE_WCHAR -DUTF8_MAYBE_NATIVE BUILD_FLAGS += -DNO_LCHMOD -DHAVE_DIRENT_H -DHAVE_TERMIOS_H -D_MBCS LINK_FLAGS = -static $(LDFLAGS) OBJ = crc32.o crypt.o extract.o fileio.o globals.o inflate.o match.o process.o ttyio.o ubz2err.o unzip.o zipinfo.o OBJ += unix/unix.o OBJ += unzipfx/appDetails.o # ----------------------------- all: unzipfx2cat unzipfx2cat: $(OBJ) $(CC) $^ $(LINK_FLAGS) -o $@ clean: rm -f *~ $(OBJ) # ----------------------------- .c.o: $(CC) $< $(BUILD_FLAGS) -c -o $@ Carla-2.1/data/windows/unzipfx-carla-control/Makefile.win32000066400000000000000000000015361364475620200236610ustar00rootroot00000000000000#!/usr/bin/Makefile -f CC ?= gcc WINDRES ?= windres BUILD_FLAGS = -DSFX -DWIN32 -DWINDOWS -DFORCE_UNIX_OVER_WIN32 -I. -I.. $(CFLAGS) -O2 BUILD_FLAGS += -DLARGE_FILE_SUPPORT -DUNICODE_SUPPORT -DUNICODE_WCHAR -DUTF8_MAYBE_NATIVE BUILD_FLAGS += -DNO_LCHMOD -DHAVE_DIRENT_H -DHAVE_TERMIOS_H -D_MBCS LINK_FLAGS = -static -mwindows -lkernel32 -lshell32 $(LDFLAGS) OBJ = crc32.o crypt.o extract.o fileio.o globals.o inflate.o match.o process.o ttyio.o ubz2err.o unzip.o zipinfo.o OBJ += win32/nt.o win32/win32.o win32/win32i64.o OBJ += unzipfx/appDetails.o OBJ += icon.o # ----------------------------- all: unzipfx2cat.exe unzipfx2cat.exe: $(OBJ) $(CC) $^ $(LINK_FLAGS) -o $@ icon.o: ../../../resources/ico/carla-control.rc $(WINDRES) -i $< -o $@ -O coff clean: rm -f *~ $(OBJ) # ----------------------------- .c.o: $(CC) $< $(BUILD_FLAGS) -c -o $@ Carla-2.1/data/windows/unzipfx-carla-control/README000066400000000000000000000016061364475620200221360ustar00rootroot00000000000000This is a special build of unzip's unzipfx tool, modified to allow full application bundles. You get a static linked binary that extracts your files into a temporary location, then executes the main program (defined by you). Currently working under Linux only, but should be fairly easy to get it into other OSes (unzip itself is already available in many, including Windows, MacOS, Linux and BeOS). To get a static unzipfx application, you do: 1 - create a zip file of your application bundle, with a single parent/root directory (this directory and the main app-name must match) 2 - edit unzipfx/appDetails.h and set SFX_APP_MININAME as the directory name set in step 1 3 - compile this tool using the appropriate makefile (eg: make -f Makefile.linux). That will give you 'unzipfx2cat' binary 4 - concatenate your zip file over the 'unzipfx2cat' binary (eg: cat unzipfx2cat myapp.zip > myapp) Carla-2.1/data/windows/unzipfx-carla-control/consts.h000066400000000000000000000037341364475620200227440ustar00rootroot00000000000000/* Copyright (c) 1990-2001 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- consts.h This file contains global, initialized variables that never change. It is included by unzip.c and windll/windll.c. ---------------------------------------------------------------------------*/ /* And'ing with mask_bits[n] masks the lower n bits */ ZCONST unsigned near mask_bits[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; ZCONST char Far VersionDate[] = UZ_VERSION_DATE; /* now defined in unzvers.h */ #ifndef SFX ZCONST char Far EndSigMsg[] = "\nnote: didn't find end-of-central-dir signature at end of central dir.\n"; #endif ZCONST char Far CentSigMsg[] = "error: expected central file header signature not found (file #%lu).\n"; ZCONST char Far SeekMsg[] = "error [%s]: attempt to seek before beginning of zipfile\n%s"; ZCONST char Far FilenameNotMatched[] = "caution: filename not matched: %s\n"; ZCONST char Far ExclFilenameNotMatched[] = "caution: excluded filename not matched: %s\n"; #ifdef VMS ZCONST char Far ReportMsg[] = "\ (please check that you have transferred or created the zipfile in the\n\ appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\n"; #else ZCONST char Far ReportMsg[] = "\ (please check that you have transferred or created the zipfile in the\n\ appropriate BINARY mode and that you have compiled UnZip properly)\n"; #endif #ifndef SFX ZCONST char Far Zipnfo[] = "zipinfo"; ZCONST char Far CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n"; #endif Carla-2.1/data/windows/unzipfx-carla-control/crc32.c000066400000000000000000001133561364475620200223440ustar00rootroot00000000000000/* Copyright (c) 1990-2007 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2005-Feb-10 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crc32.c -- compute the CRC-32 of a data stream * Copyright (C) 1995 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing * tables for updating the shift register in one step with three exclusive-ors * instead of four steps with four exclusive-ors. This results about a factor * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. */ /* $Id: crc32.c,v 2.0 2007/01/07 05:20:36 spc Exp $ */ #define __CRC32_C /* identifies this source module */ #include "zip.h" #if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) #ifndef ZCONST # define ZCONST const #endif #include "crc32.h" /* When only the table of precomputed CRC values is needed, only the basic system-independent table containing 256 entries is created; any support for "unfolding" optimization is disabled. */ #if (defined(USE_ZLIB) || defined(CRC_TABLE_ONLY)) # ifdef IZ_CRCOPTIM_UNFOLDTBL # undef IZ_CRCOPTIM_UNFOLDTBL # endif #endif /* (USE_ZLIB || CRC_TABLE_ONLY) */ #if defined(IZ_CRCOPTIM_UNFOLDTBL) # define CRC_TBLS 4 #else # define CRC_TBLS 1 #endif /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. Polynomials over GF(2) are represented in binary, one bit per coefficient, with the lowest powers in the most significant bit. Then adding polynomials is just exclusive-or, and multiplying a polynomial by x is a right shift by one. If we call the above polynomial p, and represent a byte as the polynomial q, also with the lowest power in the most significant bit (so the byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, where a mod b means the remainder after dividing a by b. This calculation is done using the shift-register method of multiplying and taking the remainder. The register is initialized to zero, and for each incoming bit, x^32 is added mod p to the register if the bit is a one (where x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x (which is shifting right by one and adding x^32 mod p if the bit shifted out is a one). We start with the highest power (least significant bit) of q and repeat for all eight bits of q. The first (or only) table is simply the CRC of all possible eight bit values. This is all the information needed to generate CRC's on data a byte-at-a-time for all combinations of CRC register values and incoming bytes. The remaining 3 tables (if IZ_CRCOPTIM_UNFOLDTBL is enabled) allow for word-at-a-time CRC calculation, where a word is four bytes. */ #ifdef DYNAMIC_CRC_TABLE /* ========================================================================= * Make the crc table. This function is needed only if you want to compute * the table dynamically. */ local void make_crc_table OF((void)); #if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT)) error: Dynamic allocation of CRC table not safe with reentrant code. #endif /* DYNALLOC_CRCTAB && REENTRANT */ #ifdef DYNALLOC_CRCTAB local ulg near *crc_table = NULL; # if 0 /* not used, since sizeof("near *") <= sizeof(int) */ /* Use this section when access to a "local int" is faster than access to a "local pointer" (e.g.: i86 16bit code with far pointers). */ local int crc_table_empty = 1; # define CRC_TABLE_IS_EMPTY (crc_table_empty != 0) # define MARK_CRCTAB_FILLED crc_table_empty = 0 # define MARK_CRCTAB_EMPTY crc_table_empty = 1 # else /* Use this section on systems where the size of pointers and ints is equal (e.g.: all 32bit systems). */ # define CRC_TABLE_IS_EMPTY (crc_table == NULL) # define MARK_CRCTAB_FILLED crc_table = crctab_p # define MARK_CRCTAB_EMPTY crc_table = NULL # endif #else /* !DYNALLOC_CRCTAB */ local ulg near crc_table[CRC_TBLS*256]; local int crc_table_empty = 1; # define CRC_TABLE_IS_EMPTY (crc_table_empty != 0) # define MARK_CRCTAB_FILLED crc_table_empty = 0 #endif /* ?DYNALLOC_CRCTAB */ local void make_crc_table() { ulg c; /* crc shift register */ int n; /* counter for all possible eight bit values */ int k; /* byte being shifted into crc apparatus */ #ifdef DYNALLOC_CRCTAB ulg near *crctab_p; /* temporary pointer to allocated crc_table area */ #else /* !DYNALLOC_CRCTAB */ # define crctab_p crc_table #endif /* DYNALLOC_CRCTAB */ #ifdef COMPUTE_XOR_PATTERN /* This piece of code has been left here to explain how the XOR pattern * used in the creation of the crc_table values can be recomputed. * For production versions of this function, it is more efficient to * supply the resultant pattern at compile time. */ ulg xor; /* polynomial exclusive-or pattern */ /* terms of polynomial defining this crc (except x^32): */ static ZCONST uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; /* make exclusive-or pattern from polynomial (0xedb88320L) */ xor = 0L; for (n = 0; n < sizeof(p)/sizeof(uch); n++) xor |= 1L << (31 - p[n]); #else # define xor 0xedb88320L #endif #ifdef DYNALLOC_CRCTAB crctab_p = (ulg near *) nearmalloc (CRC_TBLS*256*sizeof(ulg)); if (crctab_p == NULL) { ziperr(ZE_MEM, "crc_table allocation"); } #endif /* DYNALLOC_CRCTAB */ /* generate a crc for every 8-bit value */ for (n = 0; n < 256; n++) { c = (ulg)n; for (k = 8; k; k--) c = c & 1 ? xor ^ (c >> 1) : c >> 1; crctab_p[n] = REV_BE(c); } #ifdef IZ_CRCOPTIM_UNFOLDTBL /* generate crc for each value followed by one, two, and three zeros */ for (n = 0; n < 256; n++) { c = crctab_p[n]; for (k = 1; k < 4; k++) { c = CRC32(c, 0, crctab_p); crctab_p[k*256+n] = c; } } #endif /* IZ_CRCOPTIM_UNFOLDTBL */ MARK_CRCTAB_FILLED; } #else /* !DYNAMIC_CRC_TABLE */ #ifdef DYNALLOC_CRCTAB error: Inconsistent flags, DYNALLOC_CRCTAB without DYNAMIC_CRC_TABLE. #endif /* ======================================================================== * Table of CRC-32's of all single-byte values (made by make_crc_table) */ local ZCONST ulg near crc_table[CRC_TBLS*256] = { # ifdef IZ_CRC_BE_OPTIMIZ 0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L, 0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L, 0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L, 0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L, 0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L, 0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L, 0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L, 0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L, 0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L, 0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L, 0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL, 0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L, 0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L, 0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L, 0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L, 0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L, 0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL, 0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L, 0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL, 0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L, 0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L, 0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L, 0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL, 0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL, 0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L, 0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL, 0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L, 0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL, 0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L, 0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L, 0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L, 0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L, 0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L, 0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL, 0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L, 0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L, 0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L, 0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L, 0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L, 0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L, 0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L, 0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L, 0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL, 0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L, 0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L, 0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L, 0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L, 0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L, 0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL, 0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L, 0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL, 0x8def022dL # ifdef IZ_CRCOPTIM_UNFOLDTBL , 0x00000000L, 0x41311b19L, 0x82623632L, 0xc3532d2bL, 0x04c56c64L, 0x45f4777dL, 0x86a75a56L, 0xc796414fL, 0x088ad9c8L, 0x49bbc2d1L, 0x8ae8effaL, 0xcbd9f4e3L, 0x0c4fb5acL, 0x4d7eaeb5L, 0x8e2d839eL, 0xcf1c9887L, 0x5112c24aL, 0x1023d953L, 0xd370f478L, 0x9241ef61L, 0x55d7ae2eL, 0x14e6b537L, 0xd7b5981cL, 0x96848305L, 0x59981b82L, 0x18a9009bL, 0xdbfa2db0L, 0x9acb36a9L, 0x5d5d77e6L, 0x1c6c6cffL, 0xdf3f41d4L, 0x9e0e5acdL, 0xa2248495L, 0xe3159f8cL, 0x2046b2a7L, 0x6177a9beL, 0xa6e1e8f1L, 0xe7d0f3e8L, 0x2483dec3L, 0x65b2c5daL, 0xaaae5d5dL, 0xeb9f4644L, 0x28cc6b6fL, 0x69fd7076L, 0xae6b3139L, 0xef5a2a20L, 0x2c09070bL, 0x6d381c12L, 0xf33646dfL, 0xb2075dc6L, 0x715470edL, 0x30656bf4L, 0xf7f32abbL, 0xb6c231a2L, 0x75911c89L, 0x34a00790L, 0xfbbc9f17L, 0xba8d840eL, 0x79dea925L, 0x38efb23cL, 0xff79f373L, 0xbe48e86aL, 0x7d1bc541L, 0x3c2ade58L, 0x054f79f0L, 0x447e62e9L, 0x872d4fc2L, 0xc61c54dbL, 0x018a1594L, 0x40bb0e8dL, 0x83e823a6L, 0xc2d938bfL, 0x0dc5a038L, 0x4cf4bb21L, 0x8fa7960aL, 0xce968d13L, 0x0900cc5cL, 0x4831d745L, 0x8b62fa6eL, 0xca53e177L, 0x545dbbbaL, 0x156ca0a3L, 0xd63f8d88L, 0x970e9691L, 0x5098d7deL, 0x11a9ccc7L, 0xd2fae1ecL, 0x93cbfaf5L, 0x5cd76272L, 0x1de6796bL, 0xdeb55440L, 0x9f844f59L, 0x58120e16L, 0x1923150fL, 0xda703824L, 0x9b41233dL, 0xa76bfd65L, 0xe65ae67cL, 0x2509cb57L, 0x6438d04eL, 0xa3ae9101L, 0xe29f8a18L, 0x21cca733L, 0x60fdbc2aL, 0xafe124adL, 0xeed03fb4L, 0x2d83129fL, 0x6cb20986L, 0xab2448c9L, 0xea1553d0L, 0x29467efbL, 0x687765e2L, 0xf6793f2fL, 0xb7482436L, 0x741b091dL, 0x352a1204L, 0xf2bc534bL, 0xb38d4852L, 0x70de6579L, 0x31ef7e60L, 0xfef3e6e7L, 0xbfc2fdfeL, 0x7c91d0d5L, 0x3da0cbccL, 0xfa368a83L, 0xbb07919aL, 0x7854bcb1L, 0x3965a7a8L, 0x4b98833bL, 0x0aa99822L, 0xc9fab509L, 0x88cbae10L, 0x4f5def5fL, 0x0e6cf446L, 0xcd3fd96dL, 0x8c0ec274L, 0x43125af3L, 0x022341eaL, 0xc1706cc1L, 0x804177d8L, 0x47d73697L, 0x06e62d8eL, 0xc5b500a5L, 0x84841bbcL, 0x1a8a4171L, 0x5bbb5a68L, 0x98e87743L, 0xd9d96c5aL, 0x1e4f2d15L, 0x5f7e360cL, 0x9c2d1b27L, 0xdd1c003eL, 0x120098b9L, 0x533183a0L, 0x9062ae8bL, 0xd153b592L, 0x16c5f4ddL, 0x57f4efc4L, 0x94a7c2efL, 0xd596d9f6L, 0xe9bc07aeL, 0xa88d1cb7L, 0x6bde319cL, 0x2aef2a85L, 0xed796bcaL, 0xac4870d3L, 0x6f1b5df8L, 0x2e2a46e1L, 0xe136de66L, 0xa007c57fL, 0x6354e854L, 0x2265f34dL, 0xe5f3b202L, 0xa4c2a91bL, 0x67918430L, 0x26a09f29L, 0xb8aec5e4L, 0xf99fdefdL, 0x3accf3d6L, 0x7bfde8cfL, 0xbc6ba980L, 0xfd5ab299L, 0x3e099fb2L, 0x7f3884abL, 0xb0241c2cL, 0xf1150735L, 0x32462a1eL, 0x73773107L, 0xb4e17048L, 0xf5d06b51L, 0x3683467aL, 0x77b25d63L, 0x4ed7facbL, 0x0fe6e1d2L, 0xccb5ccf9L, 0x8d84d7e0L, 0x4a1296afL, 0x0b238db6L, 0xc870a09dL, 0x8941bb84L, 0x465d2303L, 0x076c381aL, 0xc43f1531L, 0x850e0e28L, 0x42984f67L, 0x03a9547eL, 0xc0fa7955L, 0x81cb624cL, 0x1fc53881L, 0x5ef42398L, 0x9da70eb3L, 0xdc9615aaL, 0x1b0054e5L, 0x5a314ffcL, 0x996262d7L, 0xd85379ceL, 0x174fe149L, 0x567efa50L, 0x952dd77bL, 0xd41ccc62L, 0x138a8d2dL, 0x52bb9634L, 0x91e8bb1fL, 0xd0d9a006L, 0xecf37e5eL, 0xadc26547L, 0x6e91486cL, 0x2fa05375L, 0xe836123aL, 0xa9070923L, 0x6a542408L, 0x2b653f11L, 0xe479a796L, 0xa548bc8fL, 0x661b91a4L, 0x272a8abdL, 0xe0bccbf2L, 0xa18dd0ebL, 0x62defdc0L, 0x23efe6d9L, 0xbde1bc14L, 0xfcd0a70dL, 0x3f838a26L, 0x7eb2913fL, 0xb924d070L, 0xf815cb69L, 0x3b46e642L, 0x7a77fd5bL, 0xb56b65dcL, 0xf45a7ec5L, 0x370953eeL, 0x763848f7L, 0xb1ae09b8L, 0xf09f12a1L, 0x33cc3f8aL, 0x72fd2493L , 0x00000000L, 0x376ac201L, 0x6ed48403L, 0x59be4602L, 0xdca80907L, 0xebc2cb06L, 0xb27c8d04L, 0x85164f05L, 0xb851130eL, 0x8f3bd10fL, 0xd685970dL, 0xe1ef550cL, 0x64f91a09L, 0x5393d808L, 0x0a2d9e0aL, 0x3d475c0bL, 0x70a3261cL, 0x47c9e41dL, 0x1e77a21fL, 0x291d601eL, 0xac0b2f1bL, 0x9b61ed1aL, 0xc2dfab18L, 0xf5b56919L, 0xc8f23512L, 0xff98f713L, 0xa626b111L, 0x914c7310L, 0x145a3c15L, 0x2330fe14L, 0x7a8eb816L, 0x4de47a17L, 0xe0464d38L, 0xd72c8f39L, 0x8e92c93bL, 0xb9f80b3aL, 0x3cee443fL, 0x0b84863eL, 0x523ac03cL, 0x6550023dL, 0x58175e36L, 0x6f7d9c37L, 0x36c3da35L, 0x01a91834L, 0x84bf5731L, 0xb3d59530L, 0xea6bd332L, 0xdd011133L, 0x90e56b24L, 0xa78fa925L, 0xfe31ef27L, 0xc95b2d26L, 0x4c4d6223L, 0x7b27a022L, 0x2299e620L, 0x15f32421L, 0x28b4782aL, 0x1fdeba2bL, 0x4660fc29L, 0x710a3e28L, 0xf41c712dL, 0xc376b32cL, 0x9ac8f52eL, 0xada2372fL, 0xc08d9a70L, 0xf7e75871L, 0xae591e73L, 0x9933dc72L, 0x1c259377L, 0x2b4f5176L, 0x72f11774L, 0x459bd575L, 0x78dc897eL, 0x4fb64b7fL, 0x16080d7dL, 0x2162cf7cL, 0xa4748079L, 0x931e4278L, 0xcaa0047aL, 0xfdcac67bL, 0xb02ebc6cL, 0x87447e6dL, 0xdefa386fL, 0xe990fa6eL, 0x6c86b56bL, 0x5bec776aL, 0x02523168L, 0x3538f369L, 0x087faf62L, 0x3f156d63L, 0x66ab2b61L, 0x51c1e960L, 0xd4d7a665L, 0xe3bd6464L, 0xba032266L, 0x8d69e067L, 0x20cbd748L, 0x17a11549L, 0x4e1f534bL, 0x7975914aL, 0xfc63de4fL, 0xcb091c4eL, 0x92b75a4cL, 0xa5dd984dL, 0x989ac446L, 0xaff00647L, 0xf64e4045L, 0xc1248244L, 0x4432cd41L, 0x73580f40L, 0x2ae64942L, 0x1d8c8b43L, 0x5068f154L, 0x67023355L, 0x3ebc7557L, 0x09d6b756L, 0x8cc0f853L, 0xbbaa3a52L, 0xe2147c50L, 0xd57ebe51L, 0xe839e25aL, 0xdf53205bL, 0x86ed6659L, 0xb187a458L, 0x3491eb5dL, 0x03fb295cL, 0x5a456f5eL, 0x6d2fad5fL, 0x801b35e1L, 0xb771f7e0L, 0xeecfb1e2L, 0xd9a573e3L, 0x5cb33ce6L, 0x6bd9fee7L, 0x3267b8e5L, 0x050d7ae4L, 0x384a26efL, 0x0f20e4eeL, 0x569ea2ecL, 0x61f460edL, 0xe4e22fe8L, 0xd388ede9L, 0x8a36abebL, 0xbd5c69eaL, 0xf0b813fdL, 0xc7d2d1fcL, 0x9e6c97feL, 0xa90655ffL, 0x2c101afaL, 0x1b7ad8fbL, 0x42c49ef9L, 0x75ae5cf8L, 0x48e900f3L, 0x7f83c2f2L, 0x263d84f0L, 0x115746f1L, 0x944109f4L, 0xa32bcbf5L, 0xfa958df7L, 0xcdff4ff6L, 0x605d78d9L, 0x5737bad8L, 0x0e89fcdaL, 0x39e33edbL, 0xbcf571deL, 0x8b9fb3dfL, 0xd221f5ddL, 0xe54b37dcL, 0xd80c6bd7L, 0xef66a9d6L, 0xb6d8efd4L, 0x81b22dd5L, 0x04a462d0L, 0x33cea0d1L, 0x6a70e6d3L, 0x5d1a24d2L, 0x10fe5ec5L, 0x27949cc4L, 0x7e2adac6L, 0x494018c7L, 0xcc5657c2L, 0xfb3c95c3L, 0xa282d3c1L, 0x95e811c0L, 0xa8af4dcbL, 0x9fc58fcaL, 0xc67bc9c8L, 0xf1110bc9L, 0x740744ccL, 0x436d86cdL, 0x1ad3c0cfL, 0x2db902ceL, 0x4096af91L, 0x77fc6d90L, 0x2e422b92L, 0x1928e993L, 0x9c3ea696L, 0xab546497L, 0xf2ea2295L, 0xc580e094L, 0xf8c7bc9fL, 0xcfad7e9eL, 0x9613389cL, 0xa179fa9dL, 0x246fb598L, 0x13057799L, 0x4abb319bL, 0x7dd1f39aL, 0x3035898dL, 0x075f4b8cL, 0x5ee10d8eL, 0x698bcf8fL, 0xec9d808aL, 0xdbf7428bL, 0x82490489L, 0xb523c688L, 0x88649a83L, 0xbf0e5882L, 0xe6b01e80L, 0xd1dadc81L, 0x54cc9384L, 0x63a65185L, 0x3a181787L, 0x0d72d586L, 0xa0d0e2a9L, 0x97ba20a8L, 0xce0466aaL, 0xf96ea4abL, 0x7c78ebaeL, 0x4b1229afL, 0x12ac6fadL, 0x25c6adacL, 0x1881f1a7L, 0x2feb33a6L, 0x765575a4L, 0x413fb7a5L, 0xc429f8a0L, 0xf3433aa1L, 0xaafd7ca3L, 0x9d97bea2L, 0xd073c4b5L, 0xe71906b4L, 0xbea740b6L, 0x89cd82b7L, 0x0cdbcdb2L, 0x3bb10fb3L, 0x620f49b1L, 0x55658bb0L, 0x6822d7bbL, 0x5f4815baL, 0x06f653b8L, 0x319c91b9L, 0xb48adebcL, 0x83e01cbdL, 0xda5e5abfL, 0xed3498beL , 0x00000000L, 0x6567bcb8L, 0x8bc809aaL, 0xeeafb512L, 0x5797628fL, 0x32f0de37L, 0xdc5f6b25L, 0xb938d79dL, 0xef28b4c5L, 0x8a4f087dL, 0x64e0bd6fL, 0x018701d7L, 0xb8bfd64aL, 0xddd86af2L, 0x3377dfe0L, 0x56106358L, 0x9f571950L, 0xfa30a5e8L, 0x149f10faL, 0x71f8ac42L, 0xc8c07bdfL, 0xada7c767L, 0x43087275L, 0x266fcecdL, 0x707fad95L, 0x1518112dL, 0xfbb7a43fL, 0x9ed01887L, 0x27e8cf1aL, 0x428f73a2L, 0xac20c6b0L, 0xc9477a08L, 0x3eaf32a0L, 0x5bc88e18L, 0xb5673b0aL, 0xd00087b2L, 0x6938502fL, 0x0c5fec97L, 0xe2f05985L, 0x8797e53dL, 0xd1878665L, 0xb4e03addL, 0x5a4f8fcfL, 0x3f283377L, 0x8610e4eaL, 0xe3775852L, 0x0dd8ed40L, 0x68bf51f8L, 0xa1f82bf0L, 0xc49f9748L, 0x2a30225aL, 0x4f579ee2L, 0xf66f497fL, 0x9308f5c7L, 0x7da740d5L, 0x18c0fc6dL, 0x4ed09f35L, 0x2bb7238dL, 0xc518969fL, 0xa07f2a27L, 0x1947fdbaL, 0x7c204102L, 0x928ff410L, 0xf7e848a8L, 0x3d58149bL, 0x583fa823L, 0xb6901d31L, 0xd3f7a189L, 0x6acf7614L, 0x0fa8caacL, 0xe1077fbeL, 0x8460c306L, 0xd270a05eL, 0xb7171ce6L, 0x59b8a9f4L, 0x3cdf154cL, 0x85e7c2d1L, 0xe0807e69L, 0x0e2fcb7bL, 0x6b4877c3L, 0xa20f0dcbL, 0xc768b173L, 0x29c70461L, 0x4ca0b8d9L, 0xf5986f44L, 0x90ffd3fcL, 0x7e5066eeL, 0x1b37da56L, 0x4d27b90eL, 0x284005b6L, 0xc6efb0a4L, 0xa3880c1cL, 0x1ab0db81L, 0x7fd76739L, 0x9178d22bL, 0xf41f6e93L, 0x03f7263bL, 0x66909a83L, 0x883f2f91L, 0xed589329L, 0x546044b4L, 0x3107f80cL, 0xdfa84d1eL, 0xbacff1a6L, 0xecdf92feL, 0x89b82e46L, 0x67179b54L, 0x027027ecL, 0xbb48f071L, 0xde2f4cc9L, 0x3080f9dbL, 0x55e74563L, 0x9ca03f6bL, 0xf9c783d3L, 0x176836c1L, 0x720f8a79L, 0xcb375de4L, 0xae50e15cL, 0x40ff544eL, 0x2598e8f6L, 0x73888baeL, 0x16ef3716L, 0xf8408204L, 0x9d273ebcL, 0x241fe921L, 0x41785599L, 0xafd7e08bL, 0xcab05c33L, 0x3bb659edL, 0x5ed1e555L, 0xb07e5047L, 0xd519ecffL, 0x6c213b62L, 0x094687daL, 0xe7e932c8L, 0x828e8e70L, 0xd49eed28L, 0xb1f95190L, 0x5f56e482L, 0x3a31583aL, 0x83098fa7L, 0xe66e331fL, 0x08c1860dL, 0x6da63ab5L, 0xa4e140bdL, 0xc186fc05L, 0x2f294917L, 0x4a4ef5afL, 0xf3762232L, 0x96119e8aL, 0x78be2b98L, 0x1dd99720L, 0x4bc9f478L, 0x2eae48c0L, 0xc001fdd2L, 0xa566416aL, 0x1c5e96f7L, 0x79392a4fL, 0x97969f5dL, 0xf2f123e5L, 0x05196b4dL, 0x607ed7f5L, 0x8ed162e7L, 0xebb6de5fL, 0x528e09c2L, 0x37e9b57aL, 0xd9460068L, 0xbc21bcd0L, 0xea31df88L, 0x8f566330L, 0x61f9d622L, 0x049e6a9aL, 0xbda6bd07L, 0xd8c101bfL, 0x366eb4adL, 0x53090815L, 0x9a4e721dL, 0xff29cea5L, 0x11867bb7L, 0x74e1c70fL, 0xcdd91092L, 0xa8beac2aL, 0x46111938L, 0x2376a580L, 0x7566c6d8L, 0x10017a60L, 0xfeaecf72L, 0x9bc973caL, 0x22f1a457L, 0x479618efL, 0xa939adfdL, 0xcc5e1145L, 0x06ee4d76L, 0x6389f1ceL, 0x8d2644dcL, 0xe841f864L, 0x51792ff9L, 0x341e9341L, 0xdab12653L, 0xbfd69aebL, 0xe9c6f9b3L, 0x8ca1450bL, 0x620ef019L, 0x07694ca1L, 0xbe519b3cL, 0xdb362784L, 0x35999296L, 0x50fe2e2eL, 0x99b95426L, 0xfcdee89eL, 0x12715d8cL, 0x7716e134L, 0xce2e36a9L, 0xab498a11L, 0x45e63f03L, 0x208183bbL, 0x7691e0e3L, 0x13f65c5bL, 0xfd59e949L, 0x983e55f1L, 0x2106826cL, 0x44613ed4L, 0xaace8bc6L, 0xcfa9377eL, 0x38417fd6L, 0x5d26c36eL, 0xb389767cL, 0xd6eecac4L, 0x6fd61d59L, 0x0ab1a1e1L, 0xe41e14f3L, 0x8179a84bL, 0xd769cb13L, 0xb20e77abL, 0x5ca1c2b9L, 0x39c67e01L, 0x80fea99cL, 0xe5991524L, 0x0b36a036L, 0x6e511c8eL, 0xa7166686L, 0xc271da3eL, 0x2cde6f2cL, 0x49b9d394L, 0xf0810409L, 0x95e6b8b1L, 0x7b490da3L, 0x1e2eb11bL, 0x483ed243L, 0x2d596efbL, 0xc3f6dbe9L, 0xa6916751L, 0x1fa9b0ccL, 0x7ace0c74L, 0x9461b966L, 0xf10605deL # endif /* IZ_CRCOPTIM_UNFOLDTBL */ # else /* !IZ_CRC_BE_OPTIMIZ */ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL # ifdef IZ_CRCOPTIM_UNFOLDTBL , 0x00000000L, 0x191b3141L, 0x32366282L, 0x2b2d53c3L, 0x646cc504L, 0x7d77f445L, 0x565aa786L, 0x4f4196c7L, 0xc8d98a08L, 0xd1c2bb49L, 0xfaefe88aL, 0xe3f4d9cbL, 0xacb54f0cL, 0xb5ae7e4dL, 0x9e832d8eL, 0x87981ccfL, 0x4ac21251L, 0x53d92310L, 0x78f470d3L, 0x61ef4192L, 0x2eaed755L, 0x37b5e614L, 0x1c98b5d7L, 0x05838496L, 0x821b9859L, 0x9b00a918L, 0xb02dfadbL, 0xa936cb9aL, 0xe6775d5dL, 0xff6c6c1cL, 0xd4413fdfL, 0xcd5a0e9eL, 0x958424a2L, 0x8c9f15e3L, 0xa7b24620L, 0xbea97761L, 0xf1e8e1a6L, 0xe8f3d0e7L, 0xc3de8324L, 0xdac5b265L, 0x5d5daeaaL, 0x44469febL, 0x6f6bcc28L, 0x7670fd69L, 0x39316baeL, 0x202a5aefL, 0x0b07092cL, 0x121c386dL, 0xdf4636f3L, 0xc65d07b2L, 0xed705471L, 0xf46b6530L, 0xbb2af3f7L, 0xa231c2b6L, 0x891c9175L, 0x9007a034L, 0x179fbcfbL, 0x0e848dbaL, 0x25a9de79L, 0x3cb2ef38L, 0x73f379ffL, 0x6ae848beL, 0x41c51b7dL, 0x58de2a3cL, 0xf0794f05L, 0xe9627e44L, 0xc24f2d87L, 0xdb541cc6L, 0x94158a01L, 0x8d0ebb40L, 0xa623e883L, 0xbf38d9c2L, 0x38a0c50dL, 0x21bbf44cL, 0x0a96a78fL, 0x138d96ceL, 0x5ccc0009L, 0x45d73148L, 0x6efa628bL, 0x77e153caL, 0xbabb5d54L, 0xa3a06c15L, 0x888d3fd6L, 0x91960e97L, 0xded79850L, 0xc7cca911L, 0xece1fad2L, 0xf5facb93L, 0x7262d75cL, 0x6b79e61dL, 0x4054b5deL, 0x594f849fL, 0x160e1258L, 0x0f152319L, 0x243870daL, 0x3d23419bL, 0x65fd6ba7L, 0x7ce65ae6L, 0x57cb0925L, 0x4ed03864L, 0x0191aea3L, 0x188a9fe2L, 0x33a7cc21L, 0x2abcfd60L, 0xad24e1afL, 0xb43fd0eeL, 0x9f12832dL, 0x8609b26cL, 0xc94824abL, 0xd05315eaL, 0xfb7e4629L, 0xe2657768L, 0x2f3f79f6L, 0x362448b7L, 0x1d091b74L, 0x04122a35L, 0x4b53bcf2L, 0x52488db3L, 0x7965de70L, 0x607eef31L, 0xe7e6f3feL, 0xfefdc2bfL, 0xd5d0917cL, 0xcccba03dL, 0x838a36faL, 0x9a9107bbL, 0xb1bc5478L, 0xa8a76539L, 0x3b83984bL, 0x2298a90aL, 0x09b5fac9L, 0x10aecb88L, 0x5fef5d4fL, 0x46f46c0eL, 0x6dd93fcdL, 0x74c20e8cL, 0xf35a1243L, 0xea412302L, 0xc16c70c1L, 0xd8774180L, 0x9736d747L, 0x8e2de606L, 0xa500b5c5L, 0xbc1b8484L, 0x71418a1aL, 0x685abb5bL, 0x4377e898L, 0x5a6cd9d9L, 0x152d4f1eL, 0x0c367e5fL, 0x271b2d9cL, 0x3e001cddL, 0xb9980012L, 0xa0833153L, 0x8bae6290L, 0x92b553d1L, 0xddf4c516L, 0xc4eff457L, 0xefc2a794L, 0xf6d996d5L, 0xae07bce9L, 0xb71c8da8L, 0x9c31de6bL, 0x852aef2aL, 0xca6b79edL, 0xd37048acL, 0xf85d1b6fL, 0xe1462a2eL, 0x66de36e1L, 0x7fc507a0L, 0x54e85463L, 0x4df36522L, 0x02b2f3e5L, 0x1ba9c2a4L, 0x30849167L, 0x299fa026L, 0xe4c5aeb8L, 0xfdde9ff9L, 0xd6f3cc3aL, 0xcfe8fd7bL, 0x80a96bbcL, 0x99b25afdL, 0xb29f093eL, 0xab84387fL, 0x2c1c24b0L, 0x350715f1L, 0x1e2a4632L, 0x07317773L, 0x4870e1b4L, 0x516bd0f5L, 0x7a468336L, 0x635db277L, 0xcbfad74eL, 0xd2e1e60fL, 0xf9ccb5ccL, 0xe0d7848dL, 0xaf96124aL, 0xb68d230bL, 0x9da070c8L, 0x84bb4189L, 0x03235d46L, 0x1a386c07L, 0x31153fc4L, 0x280e0e85L, 0x674f9842L, 0x7e54a903L, 0x5579fac0L, 0x4c62cb81L, 0x8138c51fL, 0x9823f45eL, 0xb30ea79dL, 0xaa1596dcL, 0xe554001bL, 0xfc4f315aL, 0xd7626299L, 0xce7953d8L, 0x49e14f17L, 0x50fa7e56L, 0x7bd72d95L, 0x62cc1cd4L, 0x2d8d8a13L, 0x3496bb52L, 0x1fbbe891L, 0x06a0d9d0L, 0x5e7ef3ecL, 0x4765c2adL, 0x6c48916eL, 0x7553a02fL, 0x3a1236e8L, 0x230907a9L, 0x0824546aL, 0x113f652bL, 0x96a779e4L, 0x8fbc48a5L, 0xa4911b66L, 0xbd8a2a27L, 0xf2cbbce0L, 0xebd08da1L, 0xc0fdde62L, 0xd9e6ef23L, 0x14bce1bdL, 0x0da7d0fcL, 0x268a833fL, 0x3f91b27eL, 0x70d024b9L, 0x69cb15f8L, 0x42e6463bL, 0x5bfd777aL, 0xdc656bb5L, 0xc57e5af4L, 0xee530937L, 0xf7483876L, 0xb809aeb1L, 0xa1129ff0L, 0x8a3fcc33L, 0x9324fd72L , 0x00000000L, 0x01c26a37L, 0x0384d46eL, 0x0246be59L, 0x0709a8dcL, 0x06cbc2ebL, 0x048d7cb2L, 0x054f1685L, 0x0e1351b8L, 0x0fd13b8fL, 0x0d9785d6L, 0x0c55efe1L, 0x091af964L, 0x08d89353L, 0x0a9e2d0aL, 0x0b5c473dL, 0x1c26a370L, 0x1de4c947L, 0x1fa2771eL, 0x1e601d29L, 0x1b2f0bacL, 0x1aed619bL, 0x18abdfc2L, 0x1969b5f5L, 0x1235f2c8L, 0x13f798ffL, 0x11b126a6L, 0x10734c91L, 0x153c5a14L, 0x14fe3023L, 0x16b88e7aL, 0x177ae44dL, 0x384d46e0L, 0x398f2cd7L, 0x3bc9928eL, 0x3a0bf8b9L, 0x3f44ee3cL, 0x3e86840bL, 0x3cc03a52L, 0x3d025065L, 0x365e1758L, 0x379c7d6fL, 0x35dac336L, 0x3418a901L, 0x3157bf84L, 0x3095d5b3L, 0x32d36beaL, 0x331101ddL, 0x246be590L, 0x25a98fa7L, 0x27ef31feL, 0x262d5bc9L, 0x23624d4cL, 0x22a0277bL, 0x20e69922L, 0x2124f315L, 0x2a78b428L, 0x2bbade1fL, 0x29fc6046L, 0x283e0a71L, 0x2d711cf4L, 0x2cb376c3L, 0x2ef5c89aL, 0x2f37a2adL, 0x709a8dc0L, 0x7158e7f7L, 0x731e59aeL, 0x72dc3399L, 0x7793251cL, 0x76514f2bL, 0x7417f172L, 0x75d59b45L, 0x7e89dc78L, 0x7f4bb64fL, 0x7d0d0816L, 0x7ccf6221L, 0x798074a4L, 0x78421e93L, 0x7a04a0caL, 0x7bc6cafdL, 0x6cbc2eb0L, 0x6d7e4487L, 0x6f38fadeL, 0x6efa90e9L, 0x6bb5866cL, 0x6a77ec5bL, 0x68315202L, 0x69f33835L, 0x62af7f08L, 0x636d153fL, 0x612bab66L, 0x60e9c151L, 0x65a6d7d4L, 0x6464bde3L, 0x662203baL, 0x67e0698dL, 0x48d7cb20L, 0x4915a117L, 0x4b531f4eL, 0x4a917579L, 0x4fde63fcL, 0x4e1c09cbL, 0x4c5ab792L, 0x4d98dda5L, 0x46c49a98L, 0x4706f0afL, 0x45404ef6L, 0x448224c1L, 0x41cd3244L, 0x400f5873L, 0x4249e62aL, 0x438b8c1dL, 0x54f16850L, 0x55330267L, 0x5775bc3eL, 0x56b7d609L, 0x53f8c08cL, 0x523aaabbL, 0x507c14e2L, 0x51be7ed5L, 0x5ae239e8L, 0x5b2053dfL, 0x5966ed86L, 0x58a487b1L, 0x5deb9134L, 0x5c29fb03L, 0x5e6f455aL, 0x5fad2f6dL, 0xe1351b80L, 0xe0f771b7L, 0xe2b1cfeeL, 0xe373a5d9L, 0xe63cb35cL, 0xe7fed96bL, 0xe5b86732L, 0xe47a0d05L, 0xef264a38L, 0xeee4200fL, 0xeca29e56L, 0xed60f461L, 0xe82fe2e4L, 0xe9ed88d3L, 0xebab368aL, 0xea695cbdL, 0xfd13b8f0L, 0xfcd1d2c7L, 0xfe976c9eL, 0xff5506a9L, 0xfa1a102cL, 0xfbd87a1bL, 0xf99ec442L, 0xf85cae75L, 0xf300e948L, 0xf2c2837fL, 0xf0843d26L, 0xf1465711L, 0xf4094194L, 0xf5cb2ba3L, 0xf78d95faL, 0xf64fffcdL, 0xd9785d60L, 0xd8ba3757L, 0xdafc890eL, 0xdb3ee339L, 0xde71f5bcL, 0xdfb39f8bL, 0xddf521d2L, 0xdc374be5L, 0xd76b0cd8L, 0xd6a966efL, 0xd4efd8b6L, 0xd52db281L, 0xd062a404L, 0xd1a0ce33L, 0xd3e6706aL, 0xd2241a5dL, 0xc55efe10L, 0xc49c9427L, 0xc6da2a7eL, 0xc7184049L, 0xc25756ccL, 0xc3953cfbL, 0xc1d382a2L, 0xc011e895L, 0xcb4dafa8L, 0xca8fc59fL, 0xc8c97bc6L, 0xc90b11f1L, 0xcc440774L, 0xcd866d43L, 0xcfc0d31aL, 0xce02b92dL, 0x91af9640L, 0x906dfc77L, 0x922b422eL, 0x93e92819L, 0x96a63e9cL, 0x976454abL, 0x9522eaf2L, 0x94e080c5L, 0x9fbcc7f8L, 0x9e7eadcfL, 0x9c381396L, 0x9dfa79a1L, 0x98b56f24L, 0x99770513L, 0x9b31bb4aL, 0x9af3d17dL, 0x8d893530L, 0x8c4b5f07L, 0x8e0de15eL, 0x8fcf8b69L, 0x8a809decL, 0x8b42f7dbL, 0x89044982L, 0x88c623b5L, 0x839a6488L, 0x82580ebfL, 0x801eb0e6L, 0x81dcdad1L, 0x8493cc54L, 0x8551a663L, 0x8717183aL, 0x86d5720dL, 0xa9e2d0a0L, 0xa820ba97L, 0xaa6604ceL, 0xaba46ef9L, 0xaeeb787cL, 0xaf29124bL, 0xad6fac12L, 0xacadc625L, 0xa7f18118L, 0xa633eb2fL, 0xa4755576L, 0xa5b73f41L, 0xa0f829c4L, 0xa13a43f3L, 0xa37cfdaaL, 0xa2be979dL, 0xb5c473d0L, 0xb40619e7L, 0xb640a7beL, 0xb782cd89L, 0xb2cddb0cL, 0xb30fb13bL, 0xb1490f62L, 0xb08b6555L, 0xbbd72268L, 0xba15485fL, 0xb853f606L, 0xb9919c31L, 0xbcde8ab4L, 0xbd1ce083L, 0xbf5a5edaL, 0xbe9834edL , 0x00000000L, 0xb8bc6765L, 0xaa09c88bL, 0x12b5afeeL, 0x8f629757L, 0x37def032L, 0x256b5fdcL, 0x9dd738b9L, 0xc5b428efL, 0x7d084f8aL, 0x6fbde064L, 0xd7018701L, 0x4ad6bfb8L, 0xf26ad8ddL, 0xe0df7733L, 0x58631056L, 0x5019579fL, 0xe8a530faL, 0xfa109f14L, 0x42acf871L, 0xdf7bc0c8L, 0x67c7a7adL, 0x75720843L, 0xcdce6f26L, 0x95ad7f70L, 0x2d111815L, 0x3fa4b7fbL, 0x8718d09eL, 0x1acfe827L, 0xa2738f42L, 0xb0c620acL, 0x087a47c9L, 0xa032af3eL, 0x188ec85bL, 0x0a3b67b5L, 0xb28700d0L, 0x2f503869L, 0x97ec5f0cL, 0x8559f0e2L, 0x3de59787L, 0x658687d1L, 0xdd3ae0b4L, 0xcf8f4f5aL, 0x7733283fL, 0xeae41086L, 0x525877e3L, 0x40edd80dL, 0xf851bf68L, 0xf02bf8a1L, 0x48979fc4L, 0x5a22302aL, 0xe29e574fL, 0x7f496ff6L, 0xc7f50893L, 0xd540a77dL, 0x6dfcc018L, 0x359fd04eL, 0x8d23b72bL, 0x9f9618c5L, 0x272a7fa0L, 0xbafd4719L, 0x0241207cL, 0x10f48f92L, 0xa848e8f7L, 0x9b14583dL, 0x23a83f58L, 0x311d90b6L, 0x89a1f7d3L, 0x1476cf6aL, 0xaccaa80fL, 0xbe7f07e1L, 0x06c36084L, 0x5ea070d2L, 0xe61c17b7L, 0xf4a9b859L, 0x4c15df3cL, 0xd1c2e785L, 0x697e80e0L, 0x7bcb2f0eL, 0xc377486bL, 0xcb0d0fa2L, 0x73b168c7L, 0x6104c729L, 0xd9b8a04cL, 0x446f98f5L, 0xfcd3ff90L, 0xee66507eL, 0x56da371bL, 0x0eb9274dL, 0xb6054028L, 0xa4b0efc6L, 0x1c0c88a3L, 0x81dbb01aL, 0x3967d77fL, 0x2bd27891L, 0x936e1ff4L, 0x3b26f703L, 0x839a9066L, 0x912f3f88L, 0x299358edL, 0xb4446054L, 0x0cf80731L, 0x1e4da8dfL, 0xa6f1cfbaL, 0xfe92dfecL, 0x462eb889L, 0x549b1767L, 0xec277002L, 0x71f048bbL, 0xc94c2fdeL, 0xdbf98030L, 0x6345e755L, 0x6b3fa09cL, 0xd383c7f9L, 0xc1366817L, 0x798a0f72L, 0xe45d37cbL, 0x5ce150aeL, 0x4e54ff40L, 0xf6e89825L, 0xae8b8873L, 0x1637ef16L, 0x048240f8L, 0xbc3e279dL, 0x21e91f24L, 0x99557841L, 0x8be0d7afL, 0x335cb0caL, 0xed59b63bL, 0x55e5d15eL, 0x47507eb0L, 0xffec19d5L, 0x623b216cL, 0xda874609L, 0xc832e9e7L, 0x708e8e82L, 0x28ed9ed4L, 0x9051f9b1L, 0x82e4565fL, 0x3a58313aL, 0xa78f0983L, 0x1f336ee6L, 0x0d86c108L, 0xb53aa66dL, 0xbd40e1a4L, 0x05fc86c1L, 0x1749292fL, 0xaff54e4aL, 0x322276f3L, 0x8a9e1196L, 0x982bbe78L, 0x2097d91dL, 0x78f4c94bL, 0xc048ae2eL, 0xd2fd01c0L, 0x6a4166a5L, 0xf7965e1cL, 0x4f2a3979L, 0x5d9f9697L, 0xe523f1f2L, 0x4d6b1905L, 0xf5d77e60L, 0xe762d18eL, 0x5fdeb6ebL, 0xc2098e52L, 0x7ab5e937L, 0x680046d9L, 0xd0bc21bcL, 0x88df31eaL, 0x3063568fL, 0x22d6f961L, 0x9a6a9e04L, 0x07bda6bdL, 0xbf01c1d8L, 0xadb46e36L, 0x15080953L, 0x1d724e9aL, 0xa5ce29ffL, 0xb77b8611L, 0x0fc7e174L, 0x9210d9cdL, 0x2aacbea8L, 0x38191146L, 0x80a57623L, 0xd8c66675L, 0x607a0110L, 0x72cfaefeL, 0xca73c99bL, 0x57a4f122L, 0xef189647L, 0xfdad39a9L, 0x45115eccL, 0x764dee06L, 0xcef18963L, 0xdc44268dL, 0x64f841e8L, 0xf92f7951L, 0x41931e34L, 0x5326b1daL, 0xeb9ad6bfL, 0xb3f9c6e9L, 0x0b45a18cL, 0x19f00e62L, 0xa14c6907L, 0x3c9b51beL, 0x842736dbL, 0x96929935L, 0x2e2efe50L, 0x2654b999L, 0x9ee8defcL, 0x8c5d7112L, 0x34e11677L, 0xa9362eceL, 0x118a49abL, 0x033fe645L, 0xbb838120L, 0xe3e09176L, 0x5b5cf613L, 0x49e959fdL, 0xf1553e98L, 0x6c820621L, 0xd43e6144L, 0xc68bceaaL, 0x7e37a9cfL, 0xd67f4138L, 0x6ec3265dL, 0x7c7689b3L, 0xc4caeed6L, 0x591dd66fL, 0xe1a1b10aL, 0xf3141ee4L, 0x4ba87981L, 0x13cb69d7L, 0xab770eb2L, 0xb9c2a15cL, 0x017ec639L, 0x9ca9fe80L, 0x241599e5L, 0x36a0360bL, 0x8e1c516eL, 0x866616a7L, 0x3eda71c2L, 0x2c6fde2cL, 0x94d3b949L, 0x090481f0L, 0xb1b8e695L, 0xa30d497bL, 0x1bb12e1eL, 0x43d23e48L, 0xfb6e592dL, 0xe9dbf6c3L, 0x516791a6L, 0xccb0a91fL, 0x740cce7aL, 0x66b96194L, 0xde0506f1L # endif /* IZ_CRCOPTIM_UNFOLDTBL */ # endif /* ? IZ_CRC_BE_OPTIMIZ */ }; #endif /* ?DYNAMIC_CRC_TABLE */ /* use "OF((void))" here to work around a Borland TC++ 1.0 problem */ #ifdef USE_ZLIB ZCONST uLongf *get_crc_table OF((void)) #else ZCONST ulg near *get_crc_table OF((void)) #endif { #ifdef DYNAMIC_CRC_TABLE if (CRC_TABLE_IS_EMPTY) make_crc_table(); #endif #ifdef USE_ZLIB return (ZCONST uLongf *)crc_table; #else return crc_table; #endif } #ifdef DYNALLOC_CRCTAB void free_crc_table() { if (!CRC_TABLE_IS_EMPTY) { nearfree((ulg near *)crc_table); MARK_CRCTAB_EMPTY; } } #endif #ifndef USE_ZLIB #ifndef CRC_TABLE_ONLY #ifndef ASM_CRC #define DO1(crc, buf) crc = CRC32(crc, *buf++, crc_32_tab) #define DO2(crc, buf) DO1(crc, buf); DO1(crc, buf) #define DO4(crc, buf) DO2(crc, buf); DO2(crc, buf) #define DO8(crc, buf) DO4(crc, buf); DO4(crc, buf) #if (defined(IZ_CRC_BE_OPTIMIZ) || defined(IZ_CRC_LE_OPTIMIZ)) # ifdef IZ_CRCOPTIM_UNFOLDTBL # ifdef IZ_CRC_BE_OPTIMIZ # define DO_OPT4(c, buf4) c ^= *(buf4)++; \ c = crc_32_tab[c & 0xff] ^ crc_32_tab[256+((c>>8) & 0xff)] ^ \ crc_32_tab[2*256+((c>>16) & 0xff)] ^ crc_32_tab[3*256+(c>>24)] # else /* !IZ_CRC_BE_OPTIMIZ */ # define DO_OPT4(c, buf4) c ^= *(buf4)++; \ c = crc_32_tab[3*256+(c & 0xff)] ^ crc_32_tab[2*256+((c>>8) & 0xff)] \ ^ crc_32_tab[256+((c>>16) & 0xff)] ^ crc_32_tab[c>>24] # endif /* ?IZ_CRC_BE_OPTIMIZ */ # else /* !IZ_CRCOPTIM_UNFOLDTBL */ # define DO_OPT4(c, buf4) c ^= *(buf4)++; \ c = CRC32UPD(c, crc_32_tab); \ c = CRC32UPD(c, crc_32_tab); \ c = CRC32UPD(c, crc_32_tab); \ c = CRC32UPD(c, crc_32_tab) # endif /* ?IZ_CRCOPTIM_UNFOLDTBL */ # define DO_OPT16(crc, buf4) DO_OPT4(crc, buf4); DO_OPT4(crc, buf4); \ DO_OPT4(crc, buf4); DO_OPT4(crc, buf4); #endif /* (IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */ /* ========================================================================= */ ulg crc32(crc, buf, len) ulg crc; /* crc shift register */ register ZCONST uch *buf; /* pointer to bytes to pump through */ extent len; /* number of bytes in buf[] */ /* Run a set of bytes through the crc shift register. If buf is a NULL pointer, then initialize the crc shift register contents instead. Return the current crc in either case. */ { register z_uint4 c; register ZCONST ulg near *crc_32_tab; if (buf == NULL) return 0L; crc_32_tab = get_crc_table(); c = (REV_BE((z_uint4)crc) ^ 0xffffffffL); #if (defined(IZ_CRC_BE_OPTIMIZ) || defined(IZ_CRC_LE_OPTIMIZ)) /* Align buf pointer to next DWORD boundary. */ while (len && ((ptrdiff_t)buf & 3)) { DO1(c, buf); len--; } { ZCONST z_uint4 *buf4 = (ZCONST z_uint4 *)buf; while (len >= 16) { DO_OPT16(c, buf4); len -= 16; } while (len >= 4) { DO_OPT4(c, buf4); len -= 4; } buf = (ZCONST uch *)buf4; } #else /* !(IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */ #ifndef NO_UNROLLED_LOOPS while (len >= 8) { DO8(c, buf); len -= 8; } #endif /* !NO_UNROLLED_LOOPS */ #endif /* ?(IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */ if (len) do { DO1(c, buf); } while (--len); return REV_BE(c) ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ } #endif /* !ASM_CRC */ #endif /* !CRC_TABLE_ONLY */ #endif /* !USE_ZLIB */ #endif /* !USE_ZLIB || USE_OWN_CRCTAB */ Carla-2.1/data/windows/unzipfx-carla-control/crc32.h000066400000000000000000000033611364475620200223430ustar00rootroot00000000000000/* Copyright (c) 1990-2008 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crc32.h -- compute the CRC-32 of a data stream * Copyright (C) 1995 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #ifndef __crc32_h #define __crc32_h /* identifies this source module */ /* This header should be read AFTER zip.h resp. unzip.h * (the latter with UNZIP_INTERNAL defined...). */ #ifndef OF # define OF(a) a #endif #ifndef ZCONST # define ZCONST const #endif #ifdef DYNALLOC_CRCTAB void free_crc_table OF((void)); #endif #ifndef USE_ZLIB ZCONST ulg near *get_crc_table OF((void)); #endif #if (defined(USE_ZLIB) || defined(CRC_TABLE_ONLY)) # ifdef IZ_CRC_BE_OPTIMIZ # undef IZ_CRC_BE_OPTIMIZ # endif #else /* !(USE_ZLIB || CRC_TABLE_ONLY) */ ulg crc32 OF((ulg crc, ZCONST uch *buf, extent len)); #endif /* ?(USE_ZLIB || CRC_TABLE_ONLY) */ #ifndef CRC_32_TAB # define CRC_32_TAB crc_32_tab #endif #ifdef CRC32 # undef CRC32 #endif #ifdef IZ_CRC_BE_OPTIMIZ # define CRC32UPD(c, crctab) (crctab[((c) >> 24)] ^ ((c) << 8)) # define CRC32(c, b, crctab) (crctab[(((int)(c) >> 24) ^ (b))] ^ ((c) << 8)) # define REV_BE(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ (((w)&0xff00)<<8)+(((w)&0xff)<<24)) #else # define CRC32UPD(c, crctab) (crctab[((int)(c)) & 0xff] ^ ((c) >> 8)) # define CRC32(c, b, crctab) (crctab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) # define REV_BE(w) w #endif #endif /* !__crc32_h */ Carla-2.1/data/windows/unzipfx-carla-control/crypt.c000066400000000000000000000533761364475620200225760ustar00rootroot00000000000000/* Copyright (c) 1990-2007 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2005-Feb-10 or later (the contents of which are also included in (un)zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] The main encryption/decryption source code for Info-Zip software was originally written in Europe. To the best of our knowledge, it can be freely distributed in both source and object forms from any country, including the USA under License Exception TSU of the U.S. Export Administration Regulations (section 740.13(e)) of 6 June 2002. NOTE on copyright history: Previous versions of this source package (up to version 2.8) were not copyrighted and put in the public domain. If you cannot comply with the Info-Zip LICENSE, you may want to look for one of those public domain versions. */ /* This encryption code is a direct transcription of the algorithm from Roger Schlafly, described by Phil Katz in the file appnote.txt. This file (appnote.txt) is distributed with the PKZIP program (even in the version without encryption capabilities). */ #define ZCRYPT_INTERNAL #include "zip.h" #include "crypt.h" #include "ttyio.h" #if CRYPT #ifndef FALSE # define FALSE 0 #endif #ifdef ZIP /* For the encoding task used in Zip (and ZipCloak), we want to initialize the crypt algorithm with some reasonably unpredictable bytes, see the crypthead() function. The standard rand() library function is used to supply these `random' bytes, which in turn is initialized by a srand() call. The srand() function takes an "unsigned" (at least 16bit) seed value as argument to determine the starting point of the rand() pseudo-random number generator. This seed number is constructed as "Seed = Seed1 .XOR. Seed2" with Seed1 supplied by the current time (= "(unsigned)time()") and Seed2 as some (hopefully) nondeterministic bitmask. On many (most) systems, we use some "process specific" number, as the PID or something similar, but when nothing unpredictable is available, a fixed number may be sufficient. NOTE: 1.) This implementation requires the availability of the following standard UNIX C runtime library functions: time(), rand(), srand(). On systems where some of them are missing, the environment that incorporates the crypt routines must supply suitable replacement functions. 2.) It is a very bad idea to use a second call to time() to set the "Seed2" number! In this case, both "Seed1" and "Seed2" would be (almost) identical, resulting in a (mostly) "zero" constant seed number passed to srand(). The implementation environment defined in the "zip.h" header should supply a reasonable definition for ZCR_SEED2 (an unsigned number; for most implementations of rand() and srand(), only the lower 16 bits are significant!). An example that works on many systems would be "#define ZCR_SEED2 (unsigned)getpid()". The default definition for ZCR_SEED2 supplied below should be regarded as a fallback to allow successful compilation in "beta state" environments. */ # include /* time() function supplies first part of crypt seed */ /* "last resort" source for second part of crypt seed pattern */ # ifndef ZCR_SEED2 # define ZCR_SEED2 (unsigned)3141592654L /* use PI as default pattern */ # endif # ifdef GLOBAL /* used in Amiga system headers, maybe others too */ # undef GLOBAL # endif # define GLOBAL(g) g #else /* !ZIP */ # define GLOBAL(g) G.g #endif /* ?ZIP */ #ifdef UNZIP /* char *key = (char *)NULL; moved to globals.h */ # ifndef FUNZIP local int testp OF((__GPRO__ ZCONST uch *h)); local int testkey OF((__GPRO__ ZCONST uch *h, ZCONST char *key)); # endif #endif /* UNZIP */ #ifndef UNZIP /* moved to globals.h for UnZip */ # ifndef Z_UINT4_DEFINED # if !defined(NO_LIMITS_H) # if (defined(UINT_MAX) && (UINT_MAX == 0xffffffffUL)) typedef unsigned int z_uint4; # define Z_UINT4_DEFINED # else # if (defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL)) typedef unsigned long z_uint4; # define Z_UINT4_DEFINED # else # if (defined(USHRT_MAX) && (USHRT_MAX == 0xffffffffUL)) typedef unsigned short z_uint4; # define Z_UINT4_DEFINED # endif # endif # endif # endif /* !NO_LIMITS_H */ # endif /* !Z_UINT4_DEFINED */ # ifndef Z_UINT4_DEFINED typedef ulg z_uint4; # define Z_UINT4_DEFINED # endif local z_uint4 keys[3]; /* keys defining the pseudo-random sequence */ #endif /* !UNZIP */ #ifndef Trace # ifdef CRYPT_DEBUG # define Trace(x) fprintf x # else # define Trace(x) # endif #endif #include "crc32.h" #ifdef IZ_CRC_BE_OPTIMIZ local z_uint4 near crycrctab[256]; local z_uint4 near *cry_crctb_p = NULL; local z_uint4 near *crytab_init OF((__GPRO)); # define CRY_CRC_TAB cry_crctb_p # undef CRC32 # define CRC32(c, b, crctab) (crctab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) #else # define CRY_CRC_TAB CRC_32_TAB #endif /* ?IZ_CRC_BE_OPTIMIZ */ /*********************************************************************** * Return the next byte in the pseudo-random sequence */ int decrypt_byte(__G) __GDEF { unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an * unpredictable manner on 16-bit systems; not a problem * with any known compiler so far, though */ temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2; return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); } /*********************************************************************** * Update the encryption keys with the next byte of plain text */ int update_keys(__G__ c) __GDEF int c; /* byte of plain text */ { GLOBAL(keys[0]) = CRC32(GLOBAL(keys[0]), c, CRY_CRC_TAB); GLOBAL(keys[1]) = (GLOBAL(keys[1]) + (GLOBAL(keys[0]) & 0xff)) * 134775813L + 1; { register int keyshift = (int)(GLOBAL(keys[1]) >> 24); GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift, CRY_CRC_TAB); } return c; } /*********************************************************************** * Initialize the encryption keys and the random header according to * the given password. */ void init_keys(__G__ passwd) __GDEF ZCONST char *passwd; /* password string with which to modify keys */ { #ifdef IZ_CRC_BE_OPTIMIZ if (cry_crctb_p == NULL) { cry_crctb_p = crytab_init(__G); } #endif GLOBAL(keys[0]) = 305419896L; GLOBAL(keys[1]) = 591751049L; GLOBAL(keys[2]) = 878082192L; while (*passwd != '\0') { update_keys(__G__ (int)*passwd); passwd++; } } /*********************************************************************** * Initialize the local copy of the table of precomputed crc32 values. * Whereas the public crc32-table is optimized for crc32 calculations * on arrays of bytes, the crypt code needs the crc32 values in an * byte-order-independent form as 32-bit unsigned numbers. On systems * with Big-Endian byte order using the optimized crc32 code, this * requires inverting the byte-order of the values in the * crypt-crc32-table. */ #ifdef IZ_CRC_BE_OPTIMIZ local z_uint4 near *crytab_init(__G) __GDEF { int i; for (i = 0; i < 256; i++) { crycrctab[i] = REV_BE(CRC_32_TAB[i]); } return crycrctab; } #endif #ifdef ZIP /*********************************************************************** * Write encryption header to file zfile using the password passwd * and the cyclic redundancy check crc. */ void crypthead(passwd, crc, zfile) ZCONST char *passwd; /* password string */ ulg crc; /* crc of file being encrypted */ FILE *zfile; /* where to write header */ { int n; /* index in random header */ int t; /* temporary */ int c; /* random byte */ uch header[RAND_HEAD_LEN]; /* random header */ static unsigned calls = 0; /* ensure different random header each time */ /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the * output of rand() to get less predictability, since rand() is * often poorly implemented. */ if (++calls == 1) { srand((unsigned)time(NULL) ^ ZCR_SEED2); } init_keys(passwd); for (n = 0; n < RAND_HEAD_LEN-2; n++) { c = (rand() >> 7) & 0xff; header[n] = (uch)zencode(c, t); } /* Encrypt random header (last two bytes is high word of crc) */ init_keys(passwd); for (n = 0; n < RAND_HEAD_LEN-2; n++) { header[n] = (uch)zencode(header[n], t); } header[RAND_HEAD_LEN-2] = (uch)zencode((int)(crc >> 16) & 0xff, t); header[RAND_HEAD_LEN-1] = (uch)zencode((int)(crc >> 24) & 0xff, t); fwrite(header, 1, RAND_HEAD_LEN, f); } #ifdef UTIL /*********************************************************************** * Encrypt the zip entry described by z from file source to file dest * using the password passwd. Return an error code in the ZE_ class. */ int zipcloak(z, source, dest, passwd) struct zlist far *z; /* zip entry to encrypt */ FILE *source, *dest; /* source and destination files */ ZCONST char *passwd; /* password string */ { int c; /* input byte */ int res; /* result code */ ulg n; /* holds offset and counts size */ ush flag; /* previous flags */ int t; /* temporary */ int ztemp; /* temporary storage for zencode value */ /* Set encrypted bit, clear extended local header bit and write local header to output file */ if ((n = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; z->off = n; flag = z->flg; z->flg |= 1, z->flg &= ~8; z->lflg |= 1, z->lflg &= ~8; z->siz += RAND_HEAD_LEN; if ((res = putlocal(z, dest)) != ZE_OK) return res; /* Initialize keys with password and write random header */ crypthead(passwd, z->crc, dest); /* Skip local header in input file */ if (fseek(source, (long)((4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext), SEEK_CUR)) { return ferror(source) ? ZE_READ : ZE_EOF; } /* Encrypt data */ for (n = z->siz - RAND_HEAD_LEN; n; n--) { if ((c = getc(source)) == EOF) { return ferror(source) ? ZE_READ : ZE_EOF; } ztemp = zencode(c, t); putc(ztemp, dest); } /* Skip extended local header in input file if there is one */ if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { return ferror(source) ? ZE_READ : ZE_EOF; } if (fflush(dest) == EOF) return ZE_TEMP; /* Update number of bytes written to output file */ tempzn += (4 + LOCHEAD) + z->nam + z->ext + z->siz; return ZE_OK; } /*********************************************************************** * Decrypt the zip entry described by z from file source to file dest * using the password passwd. Return an error code in the ZE_ class. */ int zipbare(z, source, dest, passwd) struct zlist far *z; /* zip entry to encrypt */ FILE *source, *dest; /* source and destination files */ ZCONST char *passwd; /* password string */ { #ifdef ZIP10 int c0 /* byte preceding the last input byte */ #endif int c1; /* last input byte */ ulg offset; /* used for file offsets */ ulg size; /* size of input data */ int r; /* size of encryption header */ int res; /* return code */ ush flag; /* previous flags */ /* Save position and skip local header in input file */ if ((offset = (ulg)ftell(source)) == (ulg)-1L || fseek(source, (long)((4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext), SEEK_CUR)) { return ferror(source) ? ZE_READ : ZE_EOF; } /* Initialize keys with password */ init_keys(passwd); /* Decrypt encryption header, save last two bytes */ c1 = 0; for (r = RAND_HEAD_LEN; r; r--) { #ifdef ZIP10 c0 = c1; #endif if ((c1 = getc(source)) == EOF) { return ferror(source) ? ZE_READ : ZE_EOF; } Trace((stdout, " (%02x)", c1)); zdecode(c1); Trace((stdout, " %02x", c1)); } Trace((stdout, "\n")); /* If last two bytes of header don't match crc (or file time in the * case of an extended local header), back up and just copy. For * pkzip 2.0, the check has been reduced to one byte only. */ #ifdef ZIP10 if ((ush)(c0 | (c1<<8)) != (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) { #else if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) { #endif if (fseek(source, offset, SEEK_SET)) { return ferror(source) ? ZE_READ : ZE_EOF; } if ((res = zipcopy(z, source, dest)) != ZE_OK) return res; return ZE_MISS; } /* Clear encrypted bit and local header bit, and write local header to output file */ if ((offset = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; z->off = offset; flag = z->flg; z->flg &= ~9; z->lflg &= ~9; z->siz -= RAND_HEAD_LEN; if ((res = putlocal(z, dest)) != ZE_OK) return res; /* Decrypt data */ for (size = z->siz; size; size--) { if ((c1 = getc(source)) == EOF) { return ferror(source) ? ZE_READ : ZE_EOF; } zdecode(c1); putc(c1, dest); } /* Skip extended local header in input file if there is one */ if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { return ferror(source) ? ZE_READ : ZE_EOF; } if (fflush(dest) == EOF) return ZE_TEMP; /* Update number of bytes written to output file */ tempzn += (4 + LOCHEAD) + z->nam + z->ext + z->siz; return ZE_OK; } #else /* !UTIL */ /*********************************************************************** * If requested, encrypt the data in buf, and in any case call fwrite() * with the arguments to zfwrite(). Return what fwrite() returns. * * A bug has been found when encrypting large files. See trees.c * for details and the fix. */ unsigned zfwrite(buf, item_size, nb, f) zvoid *buf; /* data buffer */ extent item_size; /* size of each item in bytes */ extent nb; /* number of items */ FILE *f; /* file to write to */ { int t; /* temporary */ if (key != (char *)NULL) { /* key is the global password pointer */ ulg size; /* buffer size */ char *p = (char*)buf; /* steps through buffer */ /* Encrypt data in buffer */ for (size = item_size*(ulg)nb; size != 0; p++, size--) { *p = (char)zencode(*p, t); } } /* Write the buffer out */ return fwrite(buf, item_size, nb, f); } #endif /* ?UTIL */ #endif /* ZIP */ #if (defined(UNZIP) && !defined(FUNZIP)) /*********************************************************************** * Get the password and set up keys for current zipfile member. * Return PK_ class error. */ int decrypt(__G__ passwrd) __GDEF ZCONST char *passwrd; { ush b; int n, r; uch h[RAND_HEAD_LEN]; Trace((stdout, "\n[incnt = %d]: ", GLOBAL(incnt))); /* get header once (turn off "encrypted" flag temporarily so we don't * try to decrypt the same data twice) */ GLOBAL(pInfo->encrypted) = FALSE; defer_leftover_input(__G); for (n = 0; n < RAND_HEAD_LEN; n++) { b = NEXTBYTE; h[n] = (uch)b; Trace((stdout, " (%02x)", h[n])); } undefer_input(__G); GLOBAL(pInfo->encrypted) = TRUE; if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */ GLOBAL(newzip) = FALSE; if (passwrd != (char *)NULL) { /* user gave password on command line */ if (!GLOBAL(key)) { if ((GLOBAL(key) = (char *)malloc(strlen(passwrd)+1)) == (char *)NULL) return PK_MEM2; strcpy(GLOBAL(key), passwrd); GLOBAL(nopwd) = TRUE; /* inhibit password prompting! */ } } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */ free(GLOBAL(key)); GLOBAL(key) = (char *)NULL; } } /* if have key already, test it; else allocate memory for it */ if (GLOBAL(key)) { if (!testp(__G__ h)) return PK_COOL; /* existing password OK (else prompt for new) */ else if (GLOBAL(nopwd)) return PK_WARN; /* user indicated no more prompting */ } else if ((GLOBAL(key) = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL) return PK_MEM2; /* try a few keys */ n = 0; do { r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), IZ_PWLEN+1, GLOBAL(zipfn), GLOBAL(filename)); if (r == IZ_PW_ERROR) { /* internal error in fetch of PW */ free (GLOBAL(key)); GLOBAL(key) = NULL; return PK_MEM2; } if (r != IZ_PW_ENTERED) { /* user replied "skip" or "skip all" */ *GLOBAL(key) = '\0'; /* We try the NIL password, ... */ n = 0; /* and cancel fetch for this item. */ } if (!testp(__G__ h)) return PK_COOL; if (r == IZ_PW_CANCELALL) /* User replied "Skip all" */ GLOBAL(nopwd) = TRUE; /* inhibit any further PW prompt! */ } while (n > 0); return PK_WARN; } /* end function decrypt() */ /*********************************************************************** * Test the password. Return -1 if bad, 0 if OK. */ local int testp(__G__ h) __GDEF ZCONST uch *h; { int r; char *key_translated; /* On systems with "obscure" native character coding (e.g., EBCDIC), * the first test translates the password to the "main standard" * character coding. */ #ifdef STR_TO_CP1 /* allocate buffer for translated password */ if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) return -1; /* first try, test password translated "standard" charset */ r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key))); #else /* !STR_TO_CP1 */ /* first try, test password as supplied on the extractor's host */ r = testkey(__G__ h, GLOBAL(key)); #endif /* ?STR_TO_CP1 */ #ifdef STR_TO_CP2 if (r != 0) { #ifndef STR_TO_CP1 /* now prepare for second (and maybe third) test with translated pwd */ if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) return -1; #endif /* second try, password translated to alternate ("standard") charset */ r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key))); #ifdef STR_TO_CP3 if (r != 0) /* third try, password translated to another "standard" charset */ r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key))); #endif #ifndef STR_TO_CP1 free(key_translated); #endif } #endif /* STR_TO_CP2 */ #ifdef STR_TO_CP1 free(key_translated); if (r != 0) { /* last resort, test password as supplied on the extractor's host */ r = testkey(__G__ h, GLOBAL(key)); } #endif /* STR_TO_CP1 */ return r; } /* end function testp() */ local int testkey(__G__ h, key) __GDEF ZCONST uch *h; /* decrypted header */ ZCONST char *key; /* decryption password to test */ { ush b; #ifdef ZIP10 ush c; #endif int n; uch *p; uch hh[RAND_HEAD_LEN]; /* decrypted header */ /* set keys and save the encrypted header */ init_keys(__G__ key); memcpy(hh, h, RAND_HEAD_LEN); /* check password */ for (n = 0; n < RAND_HEAD_LEN; n++) { zdecode(hh[n]); Trace((stdout, " %02x", hh[n])); } Trace((stdout, "\n lrec.crc= %08lx crec.crc= %08lx pInfo->ExtLocHdr= %s\n", GLOBAL(lrec.crc32), GLOBAL(pInfo->crc), GLOBAL(pInfo->ExtLocHdr) ? "true":"false")); Trace((stdout, " incnt = %d unzip offset into zipfile = %ld\n", GLOBAL(incnt), GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf)))); /* same test as in zipbare(): */ #ifdef ZIP10 /* check two bytes */ c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1]; Trace((stdout, " (c | (b<<8)) = %04x (crc >> 16) = %04x lrec.time = %04x\n", (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16), ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff)))); if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ? ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff) : (ush)(GLOBAL(lrec.crc32) >> 16))) return -1; /* bad */ #else b = hh[RAND_HEAD_LEN-1]; Trace((stdout, " b = %02x (crc >> 24) = %02x (lrec.time >> 8) = %02x\n", b, (ush)(GLOBAL(lrec.crc32) >> 24), ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff)); if (b != (GLOBAL(pInfo->ExtLocHdr) ? ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff : (ush)(GLOBAL(lrec.crc32) >> 24))) return -1; /* bad */ #endif /* password OK: decrypt current buffer contents before leaving */ for (n = (long)GLOBAL(incnt) > GLOBAL(csize) ? (int)GLOBAL(csize) : GLOBAL(incnt), p = GLOBAL(inptr); n--; p++) zdecode(*p); return 0; /* OK */ } /* end function testkey() */ #endif /* UNZIP && !FUNZIP */ #else /* !CRYPT */ /* something "externally visible" to shut up compiler/linker warnings */ int zcr_dummy; #endif /* ?CRYPT */ Carla-2.1/data/windows/unzipfx-carla-control/crypt.h000066400000000000000000000112251364475620200225660ustar00rootroot00000000000000/* Copyright (c) 1990-2007 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2005-Feb-10 or later (the contents of which are also included in (un)zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crypt.h (full version) by Info-ZIP. Last revised: [see CR_VERSION_DATE] The main encryption/decryption source code for Info-Zip software was originally written in Europe. To the best of our knowledge, it can be freely distributed in both source and object forms from any country, including the USA under License Exception TSU of the U.S. Export Administration Regulations (section 740.13(e)) of 6 June 2002. NOTE on copyright history: Previous versions of this source package (up to version 2.8) were not copyrighted and put in the public domain. If you cannot comply with the Info-Zip LICENSE, you may want to look for one of those public domain versions. */ #ifndef __crypt_h /* don't include more than once */ #define __crypt_h #ifdef CRYPT # undef CRYPT #endif /* Logic of selecting "full crypt" code: a) default behaviour: - dummy crypt code when compiling UnZipSFX stub, to minimize size - full crypt code when used to compile Zip, UnZip and fUnZip b) USE_CRYPT defined: - always full crypt code c) NO_CRYPT defined: - never full crypt code NO_CRYPT takes precedence over USE_CRYPT */ #if defined(NO_CRYPT) # define CRYPT 0 /* dummy version */ #else #if defined(USE_CRYPT) # define CRYPT 1 /* full version */ #else #if !defined(SFX) # define CRYPT 1 /* full version for zip and main unzip */ #else # define CRYPT 0 /* dummy version for unzip sfx */ #endif #endif /* ?USE_CRYPT */ #endif /* ?NO_CRYPT */ #if CRYPT /* full version */ #ifdef CR_BETA # undef CR_BETA /* this is not a beta release */ #endif #define CR_MAJORVER 2 #define CR_MINORVER 11 #ifdef CR_BETA # define CR_BETA_VER "c BETA" # define CR_VERSION_DATE "05 Jan 2007" /* last real code change */ #else # define CR_BETA_VER "" # define CR_VERSION_DATE "05 Jan 2007" /* last public release date */ # define CR_RELEASE #endif #ifndef __G /* UnZip only, for now (DLL stuff) */ # define __G # define __G__ # define __GDEF # define __GPRO void # define __GPRO__ #endif #if defined(MSDOS) || defined(OS2) || defined(WIN32) # ifndef DOS_OS2_W32 # define DOS_OS2_W32 # endif #endif #if defined(DOS_OS2_W32) || defined(__human68k__) # ifndef DOS_H68_OS2_W32 # define DOS_H68_OS2_W32 # endif #endif #if defined(VM_CMS) || defined(MVS) # ifndef CMS_MVS # define CMS_MVS # endif #endif /* To allow combining of Zip and UnZip static libraries in a single binary, * the Zip and UnZip versions of the crypt core functions have to be named * differently. */ #ifdef ZIP # ifdef REALLY_SHORT_SYMS # define decrypt_byte zdcrby # else # define decrypt_byte zp_decrypt_byte # endif # define update_keys zp_update_keys # define init_keys zp_init_keys #else /* !ZIP */ # ifdef REALLY_SHORT_SYMS # define decrypt_byte dcrbyt # endif #endif /* ?ZIP */ #define IZ_PWLEN 80 /* input buffer size for reading encryption key */ #ifndef PWLEN /* for compatibility with previous zcrypt release... */ # define PWLEN IZ_PWLEN #endif #define RAND_HEAD_LEN 12 /* length of encryption random header */ /* the crc_32_tab array has to be provided externally for the crypt calculus */ /* encode byte c, using temp t. Warning: c must not have side effects. */ #define zencode(c,t) (t=decrypt_byte(__G), update_keys(c), t^(c)) /* decode byte c in place */ #define zdecode(c) update_keys(__G__ c ^= decrypt_byte(__G)) int decrypt_byte OF((__GPRO)); int update_keys OF((__GPRO__ int c)); void init_keys OF((__GPRO__ ZCONST char *passwd)); #ifdef ZIP void crypthead OF((ZCONST char *, ulg, FILE *)); # ifdef UTIL int zipcloak OF((struct zlist far *, FILE *, FILE *, ZCONST char *)); int zipbare OF((struct zlist far *, FILE *, FILE *, ZCONST char *)); # else unsigned zfwrite OF((zvoid *, extent, extent, FILE *)); extern char *key; # endif #endif /* ZIP */ #if (defined(UNZIP) && !defined(FUNZIP)) int decrypt OF((__GPRO__ ZCONST char *passwrd)); #endif #ifdef FUNZIP extern int encrypted; # ifdef NEXTBYTE # undef NEXTBYTE # endif # define NEXTBYTE \ (encrypted? update_keys(__G__ getc(G.in)^decrypt_byte(__G)) : getc(G.in)) #endif /* FUNZIP */ #else /* !CRYPT */ /* dummy version */ #define zencode #define zdecode #define zfwrite fwrite #endif /* ?CRYPT */ #endif /* !__crypt_h */ Carla-2.1/data/windows/unzipfx-carla-control/ebcdic.h000066400000000000000000000365531364475620200226510ustar00rootroot00000000000000/* Copyright (c) 1990-2008 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- ebcdic.h The CECP 1047 (Extended de-facto EBCDIC) <-> ISO 8859-1 conversion tables, from ftp://aix1.segi.ulg.ac.be/pub/docs/iso8859/iso8859.networking NOTES: (OS/390 port 12/97) These table no longer represent the standard mappings (for example in the OS/390 iconv utility). In order to follow current standards I remapped ebcdic x0a to ascii x15 and ebcdic x85 to ascii x25 (and vice-versa) Without these changes, newlines in auto-convert text files appeared as literal \045. I'm not sure what effect this remap would have on the MVS and CMS ports, so I ifdef'd these changes. Hopefully these ifdef's can be removed when the MVS/CMS folks test the new mappings. Christian Spieler , 27-Apr-1998 The problem mentioned by Paul von Behren was already observed previously on VM/CMS, during the preparation of the CMS&MVS port of UnZip 5.20 in 1996. At that point, the ebcdic tables were not changed since they seemed to be an adopted standard (to my knowledge, these tables are still used as presented in mainfraime KERMIT). Instead, the "end-of-line" conversion feature of Zip's and UnZip's "text-translation" mode was used to force correct mappings between ASCII and EBCDIC newline markers. Before interchanging the ASCII mappings of the EBCDIC control characters "NL" 0x25 and "LF" 0x15 according to the OS/390 setting, we have to make sure that EBCDIC 0x15 is never used as line termination. ---------------------------------------------------------------------------*/ #ifndef __ebcdic_h /* prevent multiple inclusions */ #define __ebcdic_h #ifndef ZCONST # define ZCONST const #endif #ifdef EBCDIC #ifndef MTS /* MTS uses a slightly "special" EBCDIC code page */ ZCONST uch ebcdic[] = { 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 00 - 07 */ #ifdef OS390 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ #else 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ #endif 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /* 10 - 17 */ 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /* 20 - 27 */ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /* 28 - 2F */ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /* 30 - 37 */ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /* 38 - 3F */ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 40 - 47 */ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /* 48 - 4F */ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /* 50 - 57 */ 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, /* 58 - 5F */ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60 - 67 */ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 68 - 6F */ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /* 70 - 77 */ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, /* 78 - 7F */ #ifdef OS390 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17, /* 80 - 87 */ #else 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, /* 80 - 87 */ #endif 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, /* 88 - 8F */ 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, /* 90 - 97 */ 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF, /* 98 - 9F */ 0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, /* A0 - A7 */ 0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC, /* A8 - AF */ 0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, /* B0 - B7 */ 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB, /* B8 - BF */ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, /* C0 - C7 */ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* C8 - CF */ 0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, /* D0 - D7 */ 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59, /* D8 - DF */ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, /* E0 - E7 */ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* E8 - EF */ 0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, /* F0 - F7 */ 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF /* F8 - FF */ }; #if (defined(ZIP) || CRYPT) ZCONST uch ascii[] = { 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, /* 00 - 07 */ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ #ifdef OS390 0x10, 0x11, 0x12, 0x13, 0x9D, 0x0A, 0x08, 0x87, /* 10 - 17 */ #else 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, /* 10 - 17 */ #endif 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ #ifdef OS390 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1B, /* 20 - 27 */ #else 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, /* 20 - 27 */ #endif 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, /* 28 - 2F */ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30 - 37 */ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, /* 38 - 3F */ 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, /* 40 - 47 */ 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, /* 48 - 4F */ 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, /* 50 - 57 */ 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, /* 58 - 5F */ 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, /* 60 - 67 */ 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 68 - 6F */ 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, /* 70 - 77 */ 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /* 78 - 7F */ 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80 - 87 */ 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, /* 88 - 8F */ 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 90 - 97 */ 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, /* 98 - 9F */ 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* A0 - A7 */ 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE, /* A8 - AF */ 0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, /* B0 - B7 */ 0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7, /* B8 - BF */ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 - C7 */ 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, /* C8 - CF */ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* D0 - D7 */ 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, /* D8 - DF */ 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* E0 - E7 */ 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, /* E8 - EF */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* F0 - F7 */ 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F /* F8 - FF */ }; #endif /* ZIP || CRYPT */ #else /* MTS */ /* * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1 * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC. */ ZCONST uch ebcdic[] = { 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 00 - 07 */ 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /* 10 - 17 */ 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /* 20 - 27 */ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /* 28 - 2F */ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /* 30 - 37 */ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /* 38 - 3F */ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 40 - 47 */ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /* 48 - 4F */ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /* 50 - 57 */ 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D, /* 58 - 5F */ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60 - 67 */ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 68 - 6F */ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /* 70 - 77 */ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, /* 78 - 7F */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, /* 80 - 87 */ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, /* 88 - 8F */ 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, /* 90 - 97 */ 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF, /* 98 - 9F */ 0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, /* A0 - A7 */ 0xBD, 0xB4, 0x9A, 0x8A, 0x5F, 0xCA, 0xAF, 0xBC, /* A8 - AF */ 0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, /* B0 - B7 */ 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB, /* B8 - BF */ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, /* C0 - C7 */ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* C8 - CF */ 0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, /* D0 - D7 */ 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xAD, 0xAE, 0x59, /* D8 - DF */ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, /* E0 - E7 */ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* E8 - EF */ 0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, /* F0 - F7 */ 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF /* F8 - FF */ }; #if (defined(ZIP) || CRYPT) ZCONST uch ascii[] = { 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, /* 00 - 07 */ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, /* 10 - 17 */ 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, /* 20 - 27 */ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, /* 28 - 2F */ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30 - 37 */ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, /* 38 - 3F */ 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, /* 40 - 47 */ 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, /* 48 - 4F */ 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, /* 50 - 57 */ 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC, /* 58 - 5F */ 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, /* 60 - 67 */ 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 68 - 6F */ 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, /* 70 - 77 */ 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /* 78 - 7F */ 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80 - 87 */ 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, /* 88 - 8F */ 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 90 - 97 */ 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, /* 98 - 9F */ 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* A0 - A7 */ 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE, /* A8 - AF */ 0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, /* B0 - B7 */ 0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7, /* B8 - BF */ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 - C7 */ 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, /* C8 - CF */ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* D0 - D7 */ 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, /* D8 - DF */ 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* E0 - E7 */ 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, /* E8 - EF */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* F0 - F7 */ 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F /* F8 - FF */ }; #endif /* ZIP || CRYPT */ #endif /* ?MTS */ #endif /* EBCDIC */ /*--------------------------------------------------------------------------- The following conversion tables translate between IBM PC CP 850 (OEM codepage) and the "Western Europe & America" Windows codepage 1252. The Windows codepage 1252 contains the ISO 8859-1 "Latin 1" codepage, with some additional printable characters in the range (0x80 - 0x9F), that is reserved to control codes in the ISO 8859-1 character table. The ISO <--> OEM conversion tables were constructed with the help of the WIN32 (Win16?) API's OemToAnsi() and AnsiToOem() conversion functions and have been checked against the CP850 and LATIN1 tables provided in the MS-Kermit 3.14 distribution. ---------------------------------------------------------------------------*/ #ifdef IZ_ISO2OEM_ARRAY ZCONST uch Far iso2oem_850[] = { 0x3F, 0x3F, 0x27, 0x9F, 0x22, 0x2E, 0xC5, 0xCE, /* 80 - 87 */ 0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F, /* 88 - 8F */ 0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D, /* 90 - 97 */ 0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59, /* 98 - 9F */ 0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5, /* A0 - A7 */ 0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE, /* A8 - AF */ 0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA, /* B0 - B7 */ 0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8, /* B8 - BF */ 0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80, /* C0 - C7 */ 0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8, /* C8 - CF */ 0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E, /* D0 - D7 */ 0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1, /* D8 - DF */ 0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87, /* E0 - E7 */ 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B, /* E8 - EF */ 0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6, /* F0 - F7 */ 0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98 /* F8 - FF */ }; #endif /* IZ_ISO2OEM_ARRAY */ #ifdef IZ_OEM2ISO_ARRAY ZCONST uch Far oem2iso_850[] = { 0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7, /* 80 - 87 */ 0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5, /* 88 - 8F */ 0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9, /* 90 - 97 */ 0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, 0x83, /* 98 - 9F */ 0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA, /* A0 - A7 */ 0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB, /* A8 - AF */ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xC1, 0xC2, 0xC0, /* B0 - B7 */ 0xA9, 0xA6, 0xA6, 0x2B, 0x2B, 0xA2, 0xA5, 0x2B, /* B8 - BF */ 0x2B, 0x2D, 0x2D, 0x2B, 0x2D, 0x2B, 0xE3, 0xC3, /* C0 - C7 */ 0x2B, 0x2B, 0x2D, 0x2D, 0xA6, 0x2D, 0x2B, 0xA4, /* C8 - CF */ 0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x69, 0xCD, 0xCE, /* D0 - D7 */ 0xCF, 0x2B, 0x2B, 0xA6, 0x5F, 0xA6, 0xCC, 0xAF, /* D8 - DF */ 0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE, /* E0 - E7 */ 0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4, /* E8 - EF */ 0xAD, 0xB1, 0x3D, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8, /* F0 - F7 */ 0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, 0xA6, 0xA0 /* F8 - FF */ }; #endif /* IZ_OEM2ISO_ARRAY */ /* The following pointers to the OEM<-->ISO translation tables are used by the translation code portions. They may get initialized at program startup to point to the matching static translation tables, or to NULL to disable OEM-ISO translation. The compile-time initialization used here provides the backward compatible setting, as can be found in UnZip 5.52 and earlier. In case this mechanism will ever get used on a multithreading system that allows different codepage setups for concurrently running threads, these pointers should get moved into UnZip's thread-safe global data structure. */ #ifdef IZ_ISO2OEM_ARRAY ZCONST uch Far *iso2oem = iso2oem_850; /* backward compatibility default */ #endif /* IZ_ISO2OEM_ARRAY */ #ifdef IZ_OEM2ISO_ARRAY ZCONST uch Far *oem2iso = oem2iso_850; /* backward compatibility default */ #endif /* IZ_OEM2ISO_ARRAY */ #if defined(THEOS) || defined(THEOS_SUPPORT) # include "theos/charconv.h" #endif #endif /* __ebcdic_h */ Carla-2.1/data/windows/unzipfx-carla-control/extract.c000066400000000000000000003137161364475620200231040ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- extract.c This file contains the high-level routines ("driver routines") for extrac- ting and testing zipfile members. It calls the low-level routines in files explode.c, inflate.c, unreduce.c and unshrink.c. Contains: extract_or_test_files() store_info() find_compr_idx() extract_or_test_entrylist() extract_or_test_member() TestExtraField() test_compr_eb() memextract() memflush() extract_izvms_block() (VMS or VMS_TEXT_CONV) set_deferred_symlink() (SYMLINKS only) fnfilter() dircomp() (SET_DIR_ATTRIB only) UZbunzip2() (USE_BZIP2 only) ---------------------------------------------------------------------------*/ #define __EXTRACT_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" #ifdef WINDLL # ifdef POCKET_UNZIP # include "wince/intrface.h" # else # include "windll/windll.h" # endif #endif #include "crc32.h" #include "crypt.h" #define GRRDUMP(buf,len) { \ int i, j; \ \ for (j = 0; j < (len)/16; ++j) { \ printf(" "); \ for (i = 0; i < 16; ++i) \ printf("%02x ", (uch)(buf)[i+(j<<4)]); \ printf("\n "); \ for (i = 0; i < 16; ++i) { \ char c = (char)(buf)[i+(j<<4)]; \ \ if (c == '\n') \ printf("\\n "); \ else if (c == '\r') \ printf("\\r "); \ else \ printf(" %c ", c); \ } \ printf("\n"); \ } \ if ((len) % 16) { \ printf(" "); \ for (i = j<<4; i < (len); ++i) \ printf("%02x ", (uch)(buf)[i]); \ printf("\n "); \ for (i = j<<4; i < (len); ++i) { \ char c = (char)(buf)[i]; \ \ if (c == '\n') \ printf("\\n "); \ else if (c == '\r') \ printf("\\r "); \ else \ printf(" %c ", c); \ } \ printf("\n"); \ } \ } static int store_info OF((__GPRO)); #ifdef SET_DIR_ATTRIB static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk, ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes, unsigned *pnum_dirs, direntry **pdirlist, int error_in_archive)); #else static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk, ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes, int error_in_archive)); #endif static int extract_or_test_member OF((__GPRO)); #ifndef SFX static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len)); static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size, unsigned compr_offset, int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, uch *eb_ucptr, ulg eb_ucsize))); #endif #if (defined(VMS) || defined(VMS_TEXT_CONV)) static void decompress_bits OF((uch *outptr, unsigned needlen, ZCONST uch *bitptr)); #endif #ifdef SYMLINKS static void set_deferred_symlink OF((__GPRO__ slinkentry *slnk_entry)); #endif #ifdef SET_DIR_ATTRIB static int Cdecl dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b)); #endif /*******************************/ /* Strings used in extract.c */ /*******************************/ static ZCONST char Far VersionMsg[] = " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n"; static ZCONST char Far ComprMsgNum[] = " skipping: %-22s unsupported compression method %u\n"; #ifndef SFX static ZCONST char Far ComprMsgName[] = " skipping: %-22s `%s' method not supported\n"; static ZCONST char Far CmprNone[] = "store"; static ZCONST char Far CmprShrink[] = "shrink"; static ZCONST char Far CmprReduce[] = "reduce"; static ZCONST char Far CmprImplode[] = "implode"; static ZCONST char Far CmprTokenize[] = "tokenize"; static ZCONST char Far CmprDeflate[] = "deflate"; static ZCONST char Far CmprDeflat64[] = "deflate64"; static ZCONST char Far CmprDCLImplode[] = "DCL implode"; static ZCONST char Far CmprBzip[] = "bzip2"; static ZCONST char Far CmprLZMA[] = "LZMA"; static ZCONST char Far CmprIBMTerse[] = "IBM/Terse"; static ZCONST char Far CmprIBMLZ77[] = "IBM LZ77"; static ZCONST char Far CmprWavPack[] = "WavPack"; static ZCONST char Far CmprPPMd[] = "PPMd"; static ZCONST char Far *ComprNames[NUM_METHODS] = { CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce, CmprImplode, CmprTokenize, CmprDeflate, CmprDeflat64, CmprDCLImplode, CmprBzip, CmprLZMA, CmprIBMTerse, CmprIBMLZ77, CmprWavPack, CmprPPMd }; static ZCONST unsigned ComprIDs[NUM_METHODS] = { STORED, SHRUNK, REDUCED1, REDUCED2, REDUCED3, REDUCED4, IMPLODED, TOKENIZED, DEFLATED, ENHDEFLATED, DCLIMPLODED, BZIPPED, LZMAED, IBMTERSED, IBMLZ77ED, WAVPACKED, PPMDED }; #endif /* !SFX */ static ZCONST char Far FilNamMsg[] = "%s: bad filename length (%s)\n"; #ifndef SFX static ZCONST char Far WarnNoMemCFName[] = "%s: warning, no memory for comparison with local header\n"; static ZCONST char Far LvsCFNamMsg[] = "%s: mismatching \"local\" filename (%s),\n\ continuing with \"central\" filename version\n"; #endif /* !SFX */ #if (!defined(SFX) && defined(UNICODE_SUPPORT)) static ZCONST char Far GP11FlagsDiffer[] = "file #%lu (%s):\n\ mismatch between local and central GPF bit 11 (\"UTF-8\"),\n\ continuing with central flag (IsUTF8 = %d)\n"; #endif /* !SFX && UNICODE_SUPPORT */ static ZCONST char Far WrnStorUCSizCSizDiff[] = "%s: ucsize %s <> csize %s for STORED entry\n\ continuing with \"compressed\" size value\n"; static ZCONST char Far ExtFieldMsg[] = "%s: bad extra field length (%s)\n"; static ZCONST char Far OffsetMsg[] = "file #%lu: bad zipfile offset (%s): %ld\n"; static ZCONST char Far ExtractMsg[] = "%8sing: %-22s %s%s"; #ifndef SFX static ZCONST char Far LengthMsg[] = "%s %s: %s bytes required to uncompress to %s bytes;\n %s\ supposed to require %s bytes%s%s%s\n"; #endif static ZCONST char Far BadFileCommLength[] = "%s: bad file comment length\n"; static ZCONST char Far LocalHdrSig[] = "local header sig"; static ZCONST char Far BadLocalHdr[] = "file #%lu: bad local header\n"; static ZCONST char Far AttemptRecompensate[] = " (attempting to re-compensate)\n"; #ifndef SFX static ZCONST char Far BackslashPathSep[] = "warning: %s appears to use backslashes as path separators\n"; #endif static ZCONST char Far AbsolutePathWarning[] = "warning: stripped absolute path spec from %s\n"; static ZCONST char Far SkipVolumeLabel[] = " skipping: %-22s %svolume label\n"; #ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */ static ZCONST char Far DirlistEntryNoMem[] = "warning: cannot alloc memory for dir times/permissions/UID/GID\n"; static ZCONST char Far DirlistSortNoMem[] = "warning: cannot alloc memory to sort dir times/perms/etc.\n"; static ZCONST char Far DirlistSetAttrFailed[] = "warning: set times/attribs failed for %s\n"; static ZCONST char Far DirlistFailAttrSum[] = " failed setting times/attribs for %lu dir entries"; #endif #ifdef SYMLINKS /* messages of the deferred symlinks handler */ static ZCONST char Far SymLnkWarnNoMem[] = "warning: deferred symlink (%s) failed:\n\ out of memory\n"; static ZCONST char Far SymLnkWarnInvalid[] = "warning: deferred symlink (%s) failed:\n\ invalid placeholder file\n"; static ZCONST char Far SymLnkDeferred[] = "finishing deferred symbolic links:\n"; static ZCONST char Far SymLnkFinish[] = " %-22s -> %s\n"; #endif #ifndef WINDLL static ZCONST char Far ReplaceQuery[] = # ifdef VMS "new version of %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; # else "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; # endif static ZCONST char Far AssumeNone[] = " NULL\n(EOF or read error, treating as \"[N]one\" ...)\n"; static ZCONST char Far NewNameQuery[] = "new name: "; static ZCONST char Far InvalidResponse[] = "error: invalid response [%s]\n"; #endif /* !WINDLL */ static ZCONST char Far ErrorInArchive[] = "At least one %serror was detected in %s.\n"; static ZCONST char Far ZeroFilesTested[] = "Caution: zero files tested in %s.\n"; #ifndef VMS static ZCONST char Far VMSFormatQuery[] = "\n%s: stored in VMS format. Extract anyway? (y/n) "; #endif #if CRYPT static ZCONST char Far SkipCannotGetPasswd[] = " skipping: %-22s unable to get password\n"; static ZCONST char Far SkipIncorrectPasswd[] = " skipping: %-22s incorrect password\n"; static ZCONST char Far FilesSkipBadPasswd[] = "%lu file%s skipped because of incorrect password.\n"; static ZCONST char Far MaybeBadPasswd[] = " (may instead be incorrect password)\n"; #else static ZCONST char Far SkipEncrypted[] = " skipping: %-22s encrypted (not supported)\n"; #endif static ZCONST char Far NoErrInCompData[] = "No errors detected in compressed data of %s.\n"; static ZCONST char Far NoErrInTestedFiles[] = "No errors detected in %s for the %lu file%s tested.\n"; static ZCONST char Far FilesSkipped[] = "%lu file%s skipped because of unsupported compression or encoding.\n"; static ZCONST char Far ErrUnzipFile[] = " error: %s%s %s\n"; static ZCONST char Far ErrUnzipNoFile[] = "\n error: %s%s\n"; static ZCONST char Far NotEnoughMem[] = "not enough memory to "; static ZCONST char Far InvalidComprData[] = "invalid compressed data to "; static ZCONST char Far Inflate[] = "inflate"; #ifdef USE_BZIP2 static ZCONST char Far BUnzip[] = "bunzip"; #endif #ifndef SFX static ZCONST char Far Explode[] = "explode"; #ifndef LZW_CLEAN static ZCONST char Far Unshrink[] = "unshrink"; #endif #endif #if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK)) static ZCONST char Far FileTruncated[] = "warning: %s is probably truncated\n"; #endif static ZCONST char Far FileUnknownCompMethod[] = "%s: unknown compression method\n"; static ZCONST char Far BadCRC[] = " bad CRC %08lx (should be %08lx)\n"; /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */ char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s"; char ZCONST Far TruncNTSD[] = " compressed WinNT security data missing (%d bytes)%s"; #ifndef SFX static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \ EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n"; static ZCONST char Far InvalidComprDataEAs[] = " invalid compressed data for EAs\n"; # if (defined(WIN32) && defined(NTSD_EAS)) static ZCONST char Far InvalidSecurityEAs[] = " EAs fail security check\n"; # endif static ZCONST char Far UnsuppNTSDVersEAs[] = " unsupported NTSD EAs version %d\n"; static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n"; static ZCONST char Far UnknComprMethodEAs[] = " unknown compression method for EAs (%u)\n"; static ZCONST char Far NotEnoughMemEAs[] = " out of memory while inflating EAs\n"; static ZCONST char Far UnknErrorEAs[] = " unknown error on extended attributes\n"; #endif /* !SFX */ static ZCONST char Far UnsupportedExtraField[] = "\nerror: unsupported extra-field compression type (%u)--skipping\n"; static ZCONST char Far BadExtraFieldCRC[] = "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n"; /**************************************/ /* Function extract_or_test_files() */ /**************************************/ int extract_or_test_files(__G) /* return PK-type error code */ __GDEF { unsigned i, j; zoff_t cd_bufstart; uch *cd_inptr; int cd_incnt; ulg filnum=0L, blknum=0L; int reached_end; #ifndef SFX int no_endsig_found; #endif int error, error_in_archive=PK_COOL; int *fn_matched=NULL, *xn_matched=NULL; zucn_t members_processed; ulg num_skipped=0L, num_bad_pwd=0L; zoff_t old_extra_bytes = 0L; #ifdef SET_DIR_ATTRIB unsigned num_dirs=0; direntry *dirlist=(direntry *)NULL, **sorted_dirlist=(direntry **)NULL; #endif /* * First, two general initializations are applied. These have been moved * here from process_zipfiles() because they are only needed for accessing * and/or extracting the data content of the zip archive. */ /* a) initialize the CRC table pointer (once) */ if (CRC_32_TAB == NULL) { if ((CRC_32_TAB = get_crc_table()) == NULL) { return PK_MEM; } } #if (!defined(SFX) || defined(SFX_EXDIR)) /* b) check out if specified extraction root directory exists */ if (uO.exdir != (char *)NULL && G.extract_flag) { G.create_dirs = !uO.fflag; if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) { /* out of memory, or file in way */ return (error == MPN_NOMEM ? PK_MEM : PK_ERR); } } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- The basic idea of this function is as follows. Since the central di- rectory lies at the end of the zipfile and the member files lie at the beginning or middle or wherever, it is not very desirable to simply read a central directory entry, jump to the member and extract it, and then jump back to the central directory. In the case of a large zipfile this would lead to a whole lot of disk-grinding, especially if each mem- ber file is small. Instead, we read from the central directory the per- tinent information for a block of files, then go extract/test the whole block. Thus this routine contains two small(er) loops within a very large outer loop: the first of the small ones reads a block of files from the central directory; the second extracts or tests each file; and the outer one loops over blocks. There's some file-pointer positioning stuff in between, but that's about it. Btw, it's because of this jump- ing around that we can afford to be lenient if an error occurs in one of the member files: we should still be able to go find the other members, since we know the offset of each from the beginning of the zipfile. ---------------------------------------------------------------------------*/ G.pInfo = G.info; #if CRYPT G.newzip = TRUE; #endif #ifndef SFX G.reported_backslash = FALSE; #endif /* malloc space for check on unmatched filespecs (OK if one or both NULL) */ if (G.filespecs > 0 && (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL) for (i = 0; i < G.filespecs; ++i) fn_matched[i] = FALSE; if (G.xfilespecs > 0 && (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL) for (i = 0; i < G.xfilespecs; ++i) xn_matched[i] = FALSE; /*--------------------------------------------------------------------------- Begin main loop over blocks of member files. We know the entire central directory is on this disk: we would not have any of this information un- less the end-of-central-directory record was on this disk, and we would not have gotten to this routine unless this is also the disk on which the central directory starts. In practice, this had better be the ONLY disk in the archive, but we'll add multi-disk support soon. ---------------------------------------------------------------------------*/ members_processed = 0; #ifndef SFX no_endsig_found = FALSE; #endif reached_end = FALSE; while (!reached_end) { j = 0; #ifdef AMIGA memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *)); #endif /* * Loop through files in central directory, storing offsets, file * attributes, case-conversion and text-conversion flags until block * size is reached. */ while ((j < DIR_BLKSIZ)) { G.pInfo = &G.info[j]; if (readbuf(__G__ G.sig, 4) == 0) { error_in_archive = PK_EOF; reached_end = TRUE; /* ...so no more left to do */ break; } if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a new entry? */ /* no new central directory entry * -> is the number of processed entries compatible with the * number of entries as stored in the end_central record? */ if ((members_processed & (G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16)) == G.ecrec.total_entries_central_dir) { #ifndef SFX /* yes, so look if we ARE back at the end_central record */ no_endsig_found = ( (memcmp(G.sig, (G.ecrec.have_ecr64 ? end_central64_sig : end_central_sig), 4) != 0) && (!G.ecrec.is_zip64_archive) && (memcmp(G.sig, end_central_sig, 4) != 0) ); #endif /* !SFX */ } else { /* no; we have found an error in the central directory * -> report it and stop searching for more Zip entries */ Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1)); Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); error_in_archive = PK_BADERR; } reached_end = TRUE; /* ...so no more left to do */ break; } /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */ if ((error = process_cdir_file_hdr(__G)) != PK_COOL) { error_in_archive = error; /* only PK_EOF defined */ reached_end = TRUE; /* ...so no more left to do */ break; } if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { /* fatal: no more left to do */ Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg), FnFilter1(G.filename), "central")); reached_end = TRUE; break; } } if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { /* fatal */ Info(slide, 0x401, ((char *)slide, LoadFarString(ExtFieldMsg), FnFilter1(G.filename), "central")); reached_end = TRUE; break; } } #ifdef AMIGA G.filenote_slot = j; if ((error = do_string(__G__ G.crec.file_comment_length, uO.N_flag ? FILENOTE : SKIP)) != PK_COOL) #else if ((error = do_string(__G__ G.crec.file_comment_length, SKIP)) != PK_COOL) #endif { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { /* fatal */ Info(slide, 0x421, ((char *)slide, LoadFarString(BadFileCommLength), FnFilter1(G.filename))); reached_end = TRUE; break; } } if (G.process_all_files) { if (store_info(__G)) ++j; /* file is OK; info[] stored; continue with next */ else ++num_skipped; } else { int do_this_file; if (G.filespecs == 0) do_this_file = TRUE; else { /* check if this entry matches an `include' argument */ do_this_file = FALSE; for (i = 0; i < G.filespecs; i++) if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) { do_this_file = TRUE; /* ^-- ignore case or not? */ if (fn_matched) fn_matched[i] = TRUE; break; /* found match, so stop looping */ } } if (do_this_file) { /* check if this is an excluded file */ for (i = 0; i < G.xfilespecs; i++) if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) { do_this_file = FALSE; /* ^-- ignore case or not? */ if (xn_matched) xn_matched[i] = TRUE; break; } } if (do_this_file) { if (store_info(__G)) ++j; /* file is OK */ else ++num_skipped; /* unsupp. compression or encryption */ } } /* end if (process_all_files) */ members_processed++; } /* end while-loop (adding files to current block) */ /* save position in central directory so can come back later */ cd_bufstart = G.cur_zipfile_bufstart; cd_inptr = G.inptr; cd_incnt = G.incnt; /*----------------------------------------------------------------------- Second loop: process files in current block, extracting or testing each one. -----------------------------------------------------------------------*/ error = extract_or_test_entrylist(__G__ j, &filnum, &num_bad_pwd, &old_extra_bytes, #ifdef SET_DIR_ATTRIB &num_dirs, &dirlist, #endif error_in_archive); if (error != PK_COOL) { if (error > error_in_archive) error_in_archive = error; /* ...and keep going (unless disk full or user break) */ if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) { /* clear reached_end to signal premature stop ... */ reached_end = FALSE; /* ... and cancel scanning the central directory */ break; } } /* * Jump back to where we were in the central directory, then go and do * the next batch of files. */ #ifdef USE_STRM_INPUT zfseeko(G.zipfd, cd_bufstart, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, cd_bufstart, SEEK_SET); #endif /* ?USE_STRM_INPUT */ read(G.zipfd, (char *)G.inbuf, INBUFSIZ); /* been here before... */ G.inptr = cd_inptr; G.incnt = cd_incnt; ++blknum; #ifdef TEST printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart); printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart, cur_zipfile_bufstart); printf("inptr-inbuf = %d\n", G.inptr-G.inbuf); printf("incnt = %d\n\n", G.incnt); #endif } /* end while-loop (blocks of files in central directory) */ /*--------------------------------------------------------------------------- Process the list of deferred symlink extractions and finish up the symbolic links. ---------------------------------------------------------------------------*/ #ifdef SYMLINKS if (G.slink_last != NULL) { if (QCOND2) Info(slide, 0, ((char *)slide, LoadFarString(SymLnkDeferred))); while (G.slink_head != NULL) { set_deferred_symlink(__G__ G.slink_head); /* remove the processed entry from the chain and free its memory */ G.slink_last = G.slink_head; G.slink_head = G.slink_last->next; free(G.slink_last); } G.slink_last = NULL; } #endif /* SYMLINKS */ /*--------------------------------------------------------------------------- Go back through saved list of directories, sort and set times/perms/UIDs and GIDs from the deepest level on up. ---------------------------------------------------------------------------*/ #ifdef SET_DIR_ATTRIB if (num_dirs > 0) { sorted_dirlist = (direntry **)malloc(num_dirs*sizeof(direntry *)); if (sorted_dirlist == (direntry **)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(DirlistSortNoMem))); while (dirlist != (direntry *)NULL) { direntry *d = dirlist; dirlist = dirlist->next; free(d); } } else { ulg ndirs_fail = 0; if (num_dirs == 1) sorted_dirlist[0] = dirlist; else { for (i = 0; i < num_dirs; ++i) { sorted_dirlist[i] = dirlist; dirlist = dirlist->next; } qsort((char *)sorted_dirlist, num_dirs, sizeof(direntry *), dircomp); } Trace((stderr, "setting directory times/perms/attributes\n")); for (i = 0; i < num_dirs; ++i) { direntry *d = sorted_dirlist[i]; Trace((stderr, "dir = %s\n", d->fn)); if ((error = set_direc_attribs(__G__ d)) != PK_OK) { ndirs_fail++; Info(slide, 0x201, ((char *)slide, LoadFarString(DirlistSetAttrFailed), d->fn)); if (!error_in_archive) error_in_archive = error; } free(d); } free(sorted_dirlist); if (!uO.tflag && QCOND2) { if (ndirs_fail > 0) Info(slide, 0, ((char *)slide, LoadFarString(DirlistFailAttrSum), ndirs_fail)); } } } #endif /* SET_DIR_ATTRIB */ /*--------------------------------------------------------------------------- Check for unmatched filespecs on command line and print warning if any found. Free allocated memory. (But suppress check when central dir scan was interrupted prematurely.) ---------------------------------------------------------------------------*/ if (fn_matched) { if (reached_end) for (i = 0; i < G.filespecs; ++i) if (!fn_matched[i]) { #ifdef DLL if (!G.redirect_data && !G.redirect_text) Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameNotMatched), G.pfnames[i])); else setFileNotFound(__G); #else Info(slide, 1, ((char *)slide, LoadFarString(FilenameNotMatched), G.pfnames[i])); #endif if (error_in_archive <= PK_WARN) error_in_archive = PK_FIND; /* some files not found */ } free((zvoid *)fn_matched); } if (xn_matched) { if (reached_end) for (i = 0; i < G.xfilespecs; ++i) if (!xn_matched[i]) Info(slide, 0x401, ((char *)slide, LoadFarString(ExclFilenameNotMatched), G.pxnames[i])); free((zvoid *)xn_matched); } /*--------------------------------------------------------------------------- Now, all locally allocated memory has been released. When the central directory processing has been interrupted prematurely, it is safe to return immediately. All completeness checks and summary messages are skipped in this case. ---------------------------------------------------------------------------*/ if (!reached_end) return error_in_archive; /*--------------------------------------------------------------------------- Double-check that we're back at the end-of-central-directory record, and print quick summary of results, if we were just testing the archive. We send the summary to stdout so that people doing the testing in the back- ground and redirecting to a file can just do a "tail" on the output file. ---------------------------------------------------------------------------*/ #ifndef SFX if (no_endsig_found) { /* just to make sure */ Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); if (!error_in_archive) /* don't overwrite stronger error */ error_in_archive = PK_WARN; } #endif /* !SFX */ if (uO.tflag) { ulg num = filnum - num_bad_pwd; if (uO.qflag < 2) { /* GRR 930710: was (uO.qflag == 1) */ if (error_in_archive) Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive), (error_in_archive == PK_WARN)? "warning-" : "", G.zipfn)); else if (num == 0L) Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested), G.zipfn)); else if (G.process_all_files && (num_skipped+num_bad_pwd == 0L)) Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData), G.zipfn)); else Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles) , G.zipfn, num, (num==1L)? "":"s")); if (num_skipped > 0L) Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped), num_skipped, (num_skipped==1L)? "":"s")); #if CRYPT if (num_bad_pwd > 0L) Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd) , num_bad_pwd, (num_bad_pwd==1L)? "":"s")); #endif /* CRYPT */ } } /* give warning if files not tested or extracted (first condition can still * happen if zipfile is empty and no files specified on command line) */ if ((filnum == 0) && error_in_archive <= PK_WARN) { if (num_skipped > 0L) error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */ else error_in_archive = PK_FIND; /* no files found at all */ } #if CRYPT else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN) error_in_archive = IZ_BADPWD; /* bad passwd => all files skipped */ #endif else if ((num_skipped > 0L) && error_in_archive <= PK_WARN) error_in_archive = IZ_UNSUP; /* was PK_WARN; Jean-loup complained */ #if CRYPT else if ((num_bad_pwd > 0L) && !error_in_archive) error_in_archive = PK_WARN; #endif return error_in_archive; } /* end function extract_or_test_files() */ /***************************/ /* Function store_info() */ /***************************/ static int store_info(__G) /* return 0 if skipping, 1 if OK */ __GDEF { #ifdef USE_BZIP2 # define UNKN_BZ2 (G.crec.compression_method!=BZIPPED) #else # define UNKN_BZ2 TRUE /* bzip2 unknown */ #endif #ifdef USE_LZMA # define UNKN_LZMA (G.crec.compression_method!=LZMAED) #else # define UNKN_LZMA TRUE /* LZMA unknown */ #endif #ifdef USE_WAVP # define UNKN_WAVP (G.crec.compression_method!=WAVPACKED) #else # define UNKN_WAVP TRUE /* WavPack unknown */ #endif #ifdef USE_PPMD # define UNKN_PPMD (G.crec.compression_method!=PPMDED) #else # define UNKN_PPMD TRUE /* PPMd unknown */ #endif #ifdef SFX # ifdef USE_DEFLATE64 # define UNKN_COMPR \ (G.crec.compression_method!=STORED && G.crec.compression_methodENHDEFLATED \ && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD) # else # define UNKN_COMPR \ (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\ && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD) # endif #else # ifdef COPYRIGHT_CLEAN /* no reduced files */ # define UNKN_RED (G.crec.compression_method >= REDUCED1 && \ G.crec.compression_method <= REDUCED4) # else # define UNKN_RED FALSE /* reducing not unknown */ # endif # ifdef LZW_CLEAN /* no shrunk files */ # define UNKN_SHR (G.crec.compression_method == SHRUNK) # else # define UNKN_SHR FALSE /* unshrinking not unknown */ # endif # ifdef USE_DEFLATE64 # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ G.crec.compression_method==TOKENIZED || \ (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \ && UNKN_WAVP && UNKN_PPMD)) # else # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ G.crec.compression_method==TOKENIZED || \ (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \ && UNKN_WAVP && UNKN_PPMD)) # endif #endif #if (defined(USE_BZIP2) && (UNZIP_VERSION < UNZIP_BZ2VERS)) int unzvers_support = (UNKN_BZ2 ? UNZIP_VERSION : UNZIP_BZ2VERS); # define UNZVERS_SUPPORT unzvers_support #else # define UNZVERS_SUPPORT UNZIP_VERSION #endif /*--------------------------------------------------------------------------- Check central directory info for version/compatibility requirements. ---------------------------------------------------------------------------*/ G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1; /* bit field */ G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8; /* bit */ G.pInfo->textfile = G.crec.internal_file_attributes & 1; /* bit field */ G.pInfo->crc = G.crec.crc32; G.pInfo->compr_size = G.crec.csize; G.pInfo->uncompr_size = G.crec.ucsize; switch (uO.aflag) { case 0: G.pInfo->textmode = FALSE; /* bit field */ break; case 1: G.pInfo->textmode = G.pInfo->textfile; /* auto-convert mode */ break; default: /* case 2: */ G.pInfo->textmode = TRUE; break; } if (G.crec.version_needed_to_extract[1] == VMS_) { if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg), FnFilter1(G.filename), "VMS", G.crec.version_needed_to_extract[0] / 10, G.crec.version_needed_to_extract[0] % 10, VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10)); return 0; } #ifndef VMS /* won't be able to use extra field, but still have data */ else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */ Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery), FnFilter1(G.filename))); fgets(G.answerbuf, sizeof(G.answerbuf), stdin); if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y')) return 0; } #endif /* !VMS */ /* usual file type: don't need VMS to extract */ } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg), FnFilter1(G.filename), "PK", G.crec.version_needed_to_extract[0] / 10, G.crec.version_needed_to_extract[0] % 10, UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10)); return 0; } if (UNKN_COMPR) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) { #ifndef SFX unsigned cmpridx; if ((cmpridx = find_compr_idx(G.crec.compression_method)) < NUM_METHODS) Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName), FnFilter1(G.filename), LoadFarStringSmall(ComprNames[cmpridx]))); else #endif Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum), FnFilter1(G.filename), G.crec.compression_method)); } return 0; } #if (!CRYPT) if (G.pInfo->encrypted) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted), FnFilter1(G.filename))); return 0; } #endif /* !CRYPT */ #ifndef SFX /* store a copy of the central header filename for later comparison */ if ((G.pInfo->cfilname = zfmalloc(strlen(G.filename) + 1)) == NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(WarnNoMemCFName), FnFilter1(G.filename))); } else zfstrcpy(G.pInfo->cfilname, G.filename); #endif /* !SFX */ /* map whatever file attributes we have into the local format */ mapattr(__G); /* GRR: worry about return value later */ G.pInfo->diskstart = G.crec.disk_number_start; G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header; return 1; } /* end function store_info() */ #ifndef SFX /*******************************/ /* Function find_compr_idx() */ /*******************************/ unsigned find_compr_idx(compr_methodnum) unsigned compr_methodnum; { unsigned i; for (i = 0; i < NUM_METHODS; i++) { if (ComprIDs[i] == compr_methodnum) break; } return i; } #endif /* !SFX */ /******************************************/ /* Function extract_or_test_entrylist() */ /******************************************/ static int extract_or_test_entrylist(__G__ numchunk, pfilnum, pnum_bad_pwd, pold_extra_bytes, #ifdef SET_DIR_ATTRIB pnum_dirs, pdirlist, #endif error_in_archive) /* return PK-type error code */ __GDEF unsigned numchunk; ulg *pfilnum; ulg *pnum_bad_pwd; zoff_t *pold_extra_bytes; #ifdef SET_DIR_ATTRIB unsigned *pnum_dirs; direntry **pdirlist; #endif int error_in_archive; { unsigned i; int renamed, query; int skip_entry; zoff_t bufstart, inbuf_offset, request; int error, errcode; /* possible values for local skip_entry flag: */ #define SKIP_NO 0 /* do not skip this entry */ #define SKIP_Y_EXISTING 1 /* skip this entry, do not overwrite file */ #define SKIP_Y_NONEXIST 2 /* skip this entry, do not create new file */ /*----------------------------------------------------------------------- Second loop: process files in current block, extracting or testing each one. -----------------------------------------------------------------------*/ for (i = 0; i < numchunk; ++i) { (*pfilnum)++; /* *pfilnum = i + blknum*DIR_BLKSIZ + 1; */ G.pInfo = &G.info[i]; #ifdef NOVELL_BUG_FAILSAFE G.dne = FALSE; /* assume file exists until stat() says otherwise */ #endif /* if the target position is not within the current input buffer * (either haven't yet read far enough, or (maybe) skipping back- * ward), skip to the target position and reset readbuf(). */ /* seek_zipf(__G__ pInfo->offset); */ request = G.pInfo->offset + G.extra_bytes; inbuf_offset = request % INBUFSIZ; bufstart = request - inbuf_offset; Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n", (long)request, (long)inbuf_offset)); Trace((stderr, "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", (long)bufstart, (long)G.cur_zipfile_bufstart)); if (request < 0) { Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg), G.zipfn, LoadFarString(ReportMsg))); error_in_archive = PK_ERR; if (*pfilnum == 1 && G.extra_bytes != 0L) { Info(slide, 0x401, ((char *)slide, LoadFarString(AttemptRecompensate))); *pold_extra_bytes = G.extra_bytes; G.extra_bytes = 0L; request = G.pInfo->offset; /* could also check if != 0 */ inbuf_offset = request % INBUFSIZ; bufstart = request - inbuf_offset; Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n", (long)request, (long)inbuf_offset)); Trace((stderr, "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", (long)bufstart, (long)G.cur_zipfile_bufstart)); /* try again */ if (request < 0) { Trace((stderr, "debug: recompensated request still < 0\n")); Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg), G.zipfn, LoadFarString(ReportMsg))); error_in_archive = PK_BADERR; continue; } } else { error_in_archive = PK_BADERR; continue; /* this one hosed; try next */ } } if (bufstart != G.cur_zipfile_bufstart) { Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n")); #ifdef USE_STRM_INPUT zfseeko(G.zipfd, bufstart, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, bufstart, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) { Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), *pfilnum, "lseek", (long)bufstart)); error_in_archive = PK_BADERR; continue; /* can still do next file */ } G.inptr = G.inbuf + (int)inbuf_offset; G.incnt -= (int)inbuf_offset; } else { G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset; G.inptr = G.inbuf + (int)inbuf_offset; } /* should be in proper position now, so check for sig */ if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */ Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), *pfilnum, "EOF", (long)request)); error_in_archive = PK_BADERR; continue; /* but can still try next one */ } if (memcmp(G.sig, local_hdr_sig, 4)) { Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request)); /* GRRDUMP(G.sig, 4) GRRDUMP(local_hdr_sig, 4) */ error_in_archive = PK_ERR; if ((*pfilnum == 1 && G.extra_bytes != 0L) || (G.extra_bytes == 0L && *pold_extra_bytes != 0L)) { Info(slide, 0x401, ((char *)slide, LoadFarString(AttemptRecompensate))); if (G.extra_bytes) { *pold_extra_bytes = G.extra_bytes; G.extra_bytes = 0L; } else G.extra_bytes = *pold_extra_bytes; /* third attempt */ if (((error = seek_zipf(__G__ G.pInfo->offset)) != PK_OK) || (readbuf(__G__ G.sig, 4) == 0)) { /* bad offset */ if (error != PK_BADERR) Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), *pfilnum, "EOF", (long)request)); error_in_archive = PK_BADERR; continue; /* but can still try next one */ } if (memcmp(G.sig, local_hdr_sig, 4)) { Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request)); error_in_archive = PK_BADERR; continue; } } else continue; /* this one hosed; try next */ } if ((error = process_local_file_hdr(__G)) != PK_COOL) { Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr), *pfilnum)); error_in_archive = error; /* only PK_EOF defined */ continue; /* can still try next one */ } #if (!defined(SFX) && defined(UNICODE_SUPPORT)) if (((G.lrec.general_purpose_bit_flag & (1 << 11)) == (1 << 11)) != (G.pInfo->GPFIsUTF8 != 0)) { if (QCOND2) { # ifdef SMALL_MEM char *temp_cfilnam = slide + (7 * (WSIZE>>3)); zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname); # define cFile_PrintBuf temp_cfilnam # else # define cFile_PrintBuf G.pInfo->cfilname # endif Info(slide, 0x421, ((char *)slide, LoadFarStringSmall2(GP11FlagsDiffer), *pfilnum, FnFilter1(cFile_PrintBuf), G.pInfo->GPFIsUTF8)); # undef cFile_PrintBuf } if (error_in_archive < PK_WARN) error_in_archive = PK_WARN; } #endif /* !SFX && UNICODE_SUPPORT */ if ((error = do_string(__G__ G.lrec.filename_length, DS_FN_L)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg), FnFilter1(G.filename), "local")); continue; /* go on to next one */ } } if (G.extra_field != (uch *)NULL) { free(G.extra_field); G.extra_field = (uch *)NULL; } if ((error = do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { Info(slide, 0x401, ((char *)slide, LoadFarString(ExtFieldMsg), FnFilter1(G.filename), "local")); continue; /* go on */ } } #ifndef SFX /* Filename consistency checks must come after reading in the local * extra field, so that a UTF-8 entry name e.f. block has already * been processed. */ if (G.pInfo->cfilname != (char Far *)NULL) { if (zfstrcmp(G.pInfo->cfilname, G.filename) != 0) { # ifdef SMALL_MEM char *temp_cfilnam = slide + (7 * (WSIZE>>3)); zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname); # define cFile_PrintBuf temp_cfilnam # else # define cFile_PrintBuf G.pInfo->cfilname # endif Info(slide, 0x401, ((char *)slide, LoadFarStringSmall2(LvsCFNamMsg), FnFilter2(cFile_PrintBuf), FnFilter1(G.filename))); # undef cFile_PrintBuf zfstrcpy(G.filename, G.pInfo->cfilname); if (error_in_archive < PK_WARN) error_in_archive = PK_WARN; } zffree(G.pInfo->cfilname); G.pInfo->cfilname = (char Far *)NULL; } #endif /* !SFX */ /* Size consistency checks must come after reading in the local extra * field, so that any Zip64 extension local e.f. block has already * been processed. */ if (G.lrec.compression_method == STORED) { zusz_t csiz_decrypted = G.lrec.csize; if (G.pInfo->encrypted) csiz_decrypted -= 12; if (G.lrec.ucsize != csiz_decrypted) { Info(slide, 0x401, ((char *)slide, LoadFarStringSmall2(WrnStorUCSizCSizDiff), FnFilter1(G.filename), FmZofft(G.lrec.ucsize, NULL, "u"), FmZofft(csiz_decrypted, NULL, "u"))); G.lrec.ucsize = csiz_decrypted; if (error_in_archive < PK_WARN) error_in_archive = PK_WARN; } } #if CRYPT if (G.pInfo->encrypted && (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) { if (error == PK_WARN) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) Info(slide, 0x401, ((char *)slide, LoadFarString(SkipIncorrectPasswd), FnFilter1(G.filename))); ++(*pnum_bad_pwd); } else { /* (error > PK_WARN) */ if (error > error_in_archive) error_in_archive = error; Info(slide, 0x401, ((char *)slide, LoadFarString(SkipCannotGetPasswd), FnFilter1(G.filename))); } continue; /* go on to next file */ } #endif /* CRYPT */ /* * just about to extract file: if extracting to disk, check if * already exists, and if so, take appropriate action according to * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper * loop because we don't store the possibly renamed filename[] in * info[]) */ #ifdef DLL if (!uO.tflag && !uO.cflag && !G.redirect_data) #else if (!uO.tflag && !uO.cflag) #endif { renamed = FALSE; /* user hasn't renamed output file yet */ startover: query = FALSE; skip_entry = SKIP_NO; /* for files from DOS FAT, check for use of backslash instead * of slash as directory separator (bug in some zipper(s); so * far, not a problem in HPFS, NTFS or VFAT systems) */ #ifndef SFX if (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/')) { char *p=G.filename; if (*p) do { if (*p == '\\') { if (!G.reported_backslash) { Info(slide, 0x21, ((char *)slide, LoadFarString(BackslashPathSep), G.zipfn)); G.reported_backslash = TRUE; if (!error_in_archive) error_in_archive = PK_WARN; } *p = '/'; } } while (*PREINCSTR(p)); } #endif /* !SFX */ if (!renamed) { /* remove absolute path specs */ if (G.filename[0] == '/') { Info(slide, 0x401, ((char *)slide, LoadFarString(AbsolutePathWarning), FnFilter1(G.filename))); if (!error_in_archive) error_in_archive = PK_WARN; do { char *p = G.filename + 1; do { *(p-1) = *p; } while (*p++ != '\0'); } while (G.filename[0] == '/'); } } /* mapname can create dirs if not freshening or if renamed */ error = mapname(__G__ renamed); if ((errcode = error & ~MPN_MASK) != PK_OK && error_in_archive < errcode) error_in_archive = errcode; if ((errcode = error & MPN_MASK) > MPN_INF_TRUNC) { if (errcode == MPN_CREATED_DIR) { #ifdef SET_DIR_ATTRIB direntry *d_entry; error = defer_dir_attribs(__G__ &d_entry); if (d_entry == (direntry *)NULL) { /* There may be no dir_attribs info available, or * we have encountered a mem allocation error. * In case of an error, report it and set program * error state to warning level. */ if (error) { Info(slide, 0x401, ((char *)slide, LoadFarString(DirlistEntryNoMem))); if (!error_in_archive) error_in_archive = PK_WARN; } } else { d_entry->next = (*pdirlist); (*pdirlist) = d_entry; ++(*pnum_dirs); } #endif /* SET_DIR_ATTRIB */ } else if (errcode == MPN_VOL_LABEL) { #ifdef DOS_OS2_W32 Info(slide, 0x401, ((char *)slide, LoadFarString(SkipVolumeLabel), FnFilter1(G.filename), uO.volflag? "hard disk " : "")); #else Info(slide, 1, ((char *)slide, LoadFarString(SkipVolumeLabel), FnFilter1(G.filename), "")); #endif } else if (errcode > MPN_INF_SKIP && error_in_archive < PK_ERR) error_in_archive = PK_ERR; Trace((stderr, "mapname(%s) returns error code = %d\n", FnFilter1(G.filename), error)); continue; /* go on to next file */ } #ifdef QDOS QFilename(__G__ G.filename); #endif switch (check_for_newer(__G__ G.filename)) { case DOES_NOT_EXIST: #ifdef NOVELL_BUG_FAILSAFE G.dne = TRUE; /* stat() says file DOES NOT EXIST */ #endif /* freshen (no new files): skip unless just renamed */ if (uO.fflag && !renamed) skip_entry = SKIP_Y_NONEXIST; break; case EXISTS_AND_OLDER: #ifdef UNIXBACKUP if (!uO.B_flag) #endif { if (IS_OVERWRT_NONE) /* never overwrite: skip file */ skip_entry = SKIP_Y_EXISTING; else if (!IS_OVERWRT_ALL) query = TRUE; } break; case EXISTS_AND_NEWER: /* (or equal) */ #ifdef UNIXBACKUP if ((!uO.B_flag && IS_OVERWRT_NONE) || #else if (IS_OVERWRT_NONE || #endif (uO.uflag && !renamed)) { /* skip if update/freshen & orig name */ skip_entry = SKIP_Y_EXISTING; } else { #ifdef UNIXBACKUP if (!IS_OVERWRT_ALL && !uO.B_flag) #else if (!IS_OVERWRT_ALL) #endif query = TRUE; } break; } #ifdef VMS /* 2008-07-24 SMS. * On VMS, if the file name includes a version number, * and "-V" ("retain VMS version numbers", V_flag) is in * effect, then the VMS-specific code will handle any * conflicts with an existing file, making this query * redundant. (Implicit "y" response here.) */ if (query && uO.V_flag) { /* Not discarding file versions. Look for one. */ int cndx = strlen(G.filename) - 1; while ((cndx > 0) && (isdigit(G.filename[cndx]))) cndx--; if (G.filename[cndx] == ';') /* File version found; skip the generic query, * proceeding with its default response "y". */ query = FALSE; } #endif /* VMS */ if (query) { #ifdef WINDLL switch (G.lpUserFunctions->replace != NULL ? (*G.lpUserFunctions->replace)(G.filename, FILNAMSIZ) : IDM_REPLACE_NONE) { case IDM_REPLACE_RENAME: _ISO_INTERN(G.filename); renamed = TRUE; goto startover; case IDM_REPLACE_ALL: G.overwrite_mode = OVERWRT_ALWAYS; /* FALL THROUGH, extract */ case IDM_REPLACE_YES: break; case IDM_REPLACE_NONE: G.overwrite_mode = OVERWRT_NEVER; /* FALL THROUGH, skip */ case IDM_REPLACE_NO: skip_entry = SKIP_Y_EXISTING; break; } #else /* !WINDLL */ extent fnlen; reprompt: Info(slide, 0x81, ((char *)slide, LoadFarString(ReplaceQuery), FnFilter1(G.filename))); if (fgets(G.answerbuf, sizeof(G.answerbuf), stdin) == (char *)NULL) { Info(slide, 1, ((char *)slide, LoadFarString(AssumeNone))); *G.answerbuf = 'N'; if (!error_in_archive) error_in_archive = 1; /* not extracted: warning */ } switch (*G.answerbuf) { case 'r': case 'R': do { Info(slide, 0x81, ((char *)slide, LoadFarString(NewNameQuery))); fgets(G.filename, FILNAMSIZ, stdin); /* usually get \n here: better check for it */ fnlen = strlen(G.filename); if (lastchar(G.filename, fnlen) == '\n') G.filename[--fnlen] = '\0'; } while (fnlen == 0); #ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */ _OEM_INTERN(G.filename); #endif renamed = TRUE; goto startover; /* sorry for a goto */ case 'A': /* dangerous option: force caps */ G.overwrite_mode = OVERWRT_ALWAYS; /* FALL THROUGH, extract */ case 'y': case 'Y': break; case 'N': G.overwrite_mode = OVERWRT_NEVER; /* FALL THROUGH, skip */ case 'n': /* skip file */ skip_entry = SKIP_Y_EXISTING; break; case '\n': case '\r': /* Improve echo of '\n' and/or '\r' (sizeof(G.answerbuf) == 10 (see globals.h), so there is enough space for the provided text...) */ strcpy(G.answerbuf, "{ENTER}"); /* fall through ... */ default: /* usually get \n here: remove it for nice display (fnlen can be re-used here, we are outside the "enter new filename" loop) */ fnlen = strlen(G.answerbuf); if (lastchar(G.answerbuf, fnlen) == '\n') G.answerbuf[--fnlen] = '\0'; Info(slide, 1, ((char *)slide, LoadFarString(InvalidResponse), G.answerbuf)); goto reprompt; /* yet another goto? */ } /* end switch (*answerbuf) */ #endif /* ?WINDLL */ } /* end if (query) */ if (skip_entry != SKIP_NO) { #ifdef WINDLL if (skip_entry == SKIP_Y_EXISTING) { /* report skipping of an existing entry */ Info(slide, 0, ((char *)slide, ((IS_OVERWRT_NONE || !uO.uflag || renamed) ? "Target file exists. Skipping %s\n" : "Target file newer. Skipping %s\n"), FnFilter1(G.filename))); } #endif /* WINDLL */ continue; } } /* end if (extracting to disk) */ #ifdef DLL if ((G.statreportcb != NULL) && (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn, G.filename, NULL)) { return IZ_CTRLC; /* cancel operation by user request */ } #endif #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ UserStop(); #endif #ifdef AMIGA G.filenote_slot = i; #endif G.disk_full = 0; if ((error = extract_or_test_member(__G)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; /* ...and keep going */ #ifdef DLL if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) { #else if (G.disk_full > 1) { #endif return error_in_archive; /* (unless disk full) */ } } #ifdef DLL if ((G.statreportcb != NULL) && (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn, G.filename, (zvoid *)&G.lrec.ucsize)) { return IZ_CTRLC; /* cancel operation by user request */ } #endif #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ UserStop(); #endif } /* end for-loop (i: files in current block) */ return error_in_archive; } /* end function extract_or_test_entrylist() */ /* wsize is used in extract_or_test_member() and UZbunzip2() */ #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) # define wsize G._wsize /* wsize is a variable */ #else # define wsize WSIZE /* wsize is a constant */ #endif /***************************************/ /* Function extract_or_test_member() */ /***************************************/ static int extract_or_test_member(__G) /* return PK-type error code */ __GDEF { char *nul="[empty] ", *txt="[text] ", *bin="[binary]"; #ifdef CMS_MVS char *ebc="[ebcdic]"; #endif register int b; int r, error=PK_COOL; /*--------------------------------------------------------------------------- Initialize variables, buffers, etc. ---------------------------------------------------------------------------*/ G.bits_left = 0; G.bitbuf = 0L; /* unreduce and unshrink only */ G.zipeof = 0; G.newfile = TRUE; G.crc32val = CRCVAL_INITIAL; #ifdef SYMLINKS /* If file is a (POSIX-compatible) symbolic link and we are extracting * to disk, prepare to restore the link. */ G.symlnk = (G.pInfo->symlink && !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0)); #endif /* SYMLINKS */ if (uO.tflag) { if (!uO.qflag) Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test", FnFilter1(G.filename), "", "")); } else { #ifdef DLL if (uO.cflag && !G.redirect_data) #else if (uO.cflag) #endif { #if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200)) G.outfile = freopen("", "wb", stdout); /* VAC++ ignores setmode */ #else G.outfile = stdout; #endif #ifdef DOS_FLX_NLM_OS2_W32 #if (defined(__HIGHC__) && !defined(FLEXOS)) setmode(G.outfile, _BINARY); #else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */ setmode(fileno(G.outfile), O_BINARY); #endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */ # define NEWLINE "\r\n" #else /* !DOS_FLX_NLM_OS2_W32 */ # define NEWLINE "\n" #endif /* ?DOS_FLX_NLM_OS2_W32 */ #ifdef VMS /* VMS: required even for stdout! */ if ((r = open_outfile(__G)) != 0) switch (r) { case OPENOUT_SKIPOK: return PK_OK; case OPENOUT_SKIPWARN: return PK_WARN; default: return PK_DISK; } } else if ((r = open_outfile(__G)) != 0) switch (r) { case OPENOUT_SKIPOK: return PK_OK; case OPENOUT_SKIPWARN: return PK_WARN; default: return PK_DISK; } #else /* !VMS */ } else if (open_outfile(__G)) return PK_DISK; #endif /* ?VMS */ } /*--------------------------------------------------------------------------- Unpack the file. ---------------------------------------------------------------------------*/ defer_leftover_input(__G); /* so NEXTBYTE bounds check will work */ switch (G.lrec.compression_method) { case STORED: if (!uO.tflag && QCOND2) { #ifdef SYMLINKS if (G.symlnk) /* can also be deflated, but rarer... */ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "link", FnFilter1(G.filename), "", "")); else #endif /* SYMLINKS */ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "extract", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt : bin)), uO.cflag? NEWLINE : "")); } #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) { wsize = G.redirect_size; redirSlide = G.redirect_buffer; } else { wsize = WSIZE; redirSlide = slide; } #endif G.outptr = redirSlide; G.outcnt = 0L; while ((b = NEXTBYTE) != EOF) { *G.outptr++ = (uch)b; if (++G.outcnt == wsize) { error = flush(__G__ redirSlide, G.outcnt, 0); G.outptr = redirSlide; G.outcnt = 0L; if (error != PK_COOL || G.disk_full) break; } } if (G.outcnt) { /* flush final (partial) buffer */ r = flush(__G__ redirSlide, G.outcnt, 0); if (error < r) error = r; } break; #ifndef SFX #ifndef LZW_CLEAN case SHRUNK: if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), LoadFarStringSmall(Unshrink), FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } if ((r = unshrink(__G)) != PK_COOL) { if (r < PK_DISK) { if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipFile), r == PK_MEM3 ? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Unshrink), FnFilter1(G.filename))); else Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == PK_MEM3 ? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Unshrink))); } error = r; } break; #endif /* !LZW_CLEAN */ #ifndef COPYRIGHT_CLEAN case REDUCED1: case REDUCED2: case REDUCED3: case REDUCED4: if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "unreduc", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } if ((r = unreduce(__G)) != PK_COOL) { /* unreduce() returns only PK_COOL, PK_DISK, or IZ_CTRLC */ error = r; } break; #endif /* !COPYRIGHT_CLEAN */ case IMPLODED: if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "explod", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } if ((r = explode(__G)) != 0) { if (r == 5) { /* treat 5 specially */ int warning = ((zusz_t)G.used_csize <= G.lrec.csize); if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg), "", warning ? "warning" : "error", FmZofft(G.used_csize, NULL, NULL), FmZofft(G.lrec.ucsize, NULL, "u"), warning ? " " : "", FmZofft(G.lrec.csize, NULL, "u"), " [", FnFilter1(G.filename), "]")); else Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg), "\n", warning ? "warning" : "error", FmZofft(G.used_csize, NULL, NULL), FmZofft(G.lrec.ucsize, NULL, "u"), warning ? " " : "", FmZofft(G.lrec.csize, NULL, "u"), "", "", ".")); error = warning ? PK_WARN : PK_ERR; } else if (r < PK_DISK) { if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Explode), FnFilter1(G.filename))); else Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Explode))); error = ((r == 3) ? PK_MEM3 : PK_ERR); } else { error = r; } } break; #endif /* !SFX */ case DEFLATED: #ifdef USE_DEFLATE64 case ENHDEFLATED: #endif if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "inflat", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } #ifndef USE_ZLIB /* zlib's function is called inflate(), too */ # define UZinflate inflate #endif if ((r = UZinflate(__G__ (G.lrec.compression_method == ENHDEFLATED))) != 0) { if (r < PK_DISK) { if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Inflate), FnFilter1(G.filename))); else Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Inflate))); error = ((r == 3) ? PK_MEM3 : PK_ERR); } else { error = r; } } break; #ifdef USE_BZIP2 case BZIPPED: if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "bunzipp", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } if ((r = UZbunzip2(__G)) != 0) { if (r < PK_DISK) { if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(BUnzip), FnFilter1(G.filename))); else Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(BUnzip))); error = ((r == 3) ? PK_MEM3 : PK_ERR); } else { error = r; } } break; #endif /* USE_BZIP2 */ default: /* should never get to this point */ Info(slide, 0x401, ((char *)slide, LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename))); /* close and delete file before return? */ undefer_input(__G); return PK_WARN; } /* end switch (compression method) */ /*--------------------------------------------------------------------------- Close the file and set its date and time (not necessarily in that order), and make sure the CRC checked out OK. Logical-AND the CRC for 64-bit machines (redundant on 32-bit machines). ---------------------------------------------------------------------------*/ #ifdef VMS /* VMS: required even for stdout! (final flush) */ if (!uO.tflag) /* don't close NULL file */ close_outfile(__G); #else #ifdef DLL if (!uO.tflag && (!uO.cflag || G.redirect_data)) { if (G.redirect_data) FINISH_REDIRECT(); else close_outfile(__G); } #else if (!uO.tflag && !uO.cflag) /* don't close NULL file or stdout */ close_outfile(__G); #endif #endif /* VMS */ /* GRR: CONVERT close_outfile() TO NON-VOID: CHECK FOR ERRORS! */ if (G.disk_full) { /* set by flush() */ if (G.disk_full > 1) { #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK)) /* delete the incomplete file if we can */ if (unlink(G.filename) != 0) Trace((stderr, "extract.c: could not delete %s\n", FnFilter1(G.filename))); #else /* warn user about the incomplete file */ Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated), FnFilter1(G.filename))); #endif error = PK_DISK; } else { error = PK_WARN; } } if (error > PK_WARN) {/* don't print redundant CRC error if error already */ undefer_input(__G); return error; } if (G.crc32val != G.lrec.crc32) { /* if quiet enough, we haven't output the filename yet: do it */ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, "%-22s ", FnFilter1(G.filename))); Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val, G.lrec.crc32)); #if CRYPT if (G.pInfo->encrypted) Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd))); #endif error = PK_ERR; } else if (uO.tflag) { #ifndef SFX if (G.extra_field) { if ((r = TestExtraField(__G__ G.extra_field, G.lrec.extra_field_length)) > error) error = r; } else #endif /* !SFX */ if (!uO.qflag) Info(slide, 0, ((char *)slide, " OK\n")); } else { if (QCOND2 && !error) /* GRR: is stdout reset to text mode yet? */ Info(slide, 0, ((char *)slide, "\n")); } undefer_input(__G); return error; } /* end function extract_or_test_member() */ #ifndef SFX /*******************************/ /* Function TestExtraField() */ /*******************************/ static int TestExtraField(__G__ ef, ef_len) __GDEF uch *ef; unsigned ef_len; { ush ebID; unsigned ebLen; unsigned eb_cmpr_offs = 0; int r; /* we know the regular compressed file data tested out OK, or else we * wouldn't be here ==> print filename if any extra-field errors found */ while (ef_len >= EB_HEADSIZE) { ebID = makeword(ef); ebLen = (unsigned)makeword(ef+EB_LEN); if (ebLen > (ef_len - EB_HEADSIZE)) { /* Discovered some extra field inconsistency! */ if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength), ebLen, (ef_len - EB_HEADSIZE))); return PK_ERR; } switch (ebID) { case EF_OS2: case EF_ACL: case EF_MAC3: case EF_BEOS: case EF_ATHEOS: switch (ebID) { case EF_OS2: case EF_ACL: eb_cmpr_offs = EB_OS2_HLEN; break; case EF_MAC3: if (ebLen >= EB_MAC3_HLEN && (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_M3_FL_UNCMPR) && (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN)) eb_cmpr_offs = 0; else eb_cmpr_offs = EB_MAC3_HLEN; break; case EF_BEOS: case EF_ATHEOS: if (ebLen >= EB_BEOS_HLEN && (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) && (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN)) eb_cmpr_offs = 0; else eb_cmpr_offs = EB_BEOS_HLEN; break; } if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL)) != PK_OK) { if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); switch (r) { case IZ_EF_TRUNC: Info(slide, 1, ((char *)slide, LoadFarString(TruncEAs), ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n")); break; case PK_ERR: Info(slide, 1, ((char *)slide, LoadFarString(InvalidComprDataEAs))); break; case PK_MEM3: case PK_MEM4: Info(slide, 1, ((char *)slide, LoadFarString(NotEnoughMemEAs))); break; default: if ((r & 0xff) != PK_ERR) Info(slide, 1, ((char *)slide, LoadFarString(UnknErrorEAs))); else { ush m = (ush)(r >> 8); if (m == DEFLATED) /* GRR KLUDGE! */ Info(slide, 1, ((char *)slide, LoadFarString(BadCRC_EAs))); else Info(slide, 1, ((char *)slide, LoadFarString(UnknComprMethodEAs), m)); } break; } return r; } break; case EF_NTSD: Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen)); r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC : ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ? (PK_WARN | 0x4000) : test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD)); if (r != PK_OK) { if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); switch (r) { case IZ_EF_TRUNC: Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD), ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n")); break; #if (defined(WIN32) && defined(NTSD_EAS)) case PK_WARN: Info(slide, 1, ((char *)slide, LoadFarString(InvalidSecurityEAs))); break; #endif case PK_ERR: Info(slide, 1, ((char *)slide, LoadFarString(InvalidComprDataEAs))); break; case PK_MEM3: case PK_MEM4: Info(slide, 1, ((char *)slide, LoadFarString(NotEnoughMemEAs))); break; case (PK_WARN | 0x4000): Info(slide, 1, ((char *)slide, LoadFarString(UnsuppNTSDVersEAs), (int)ef[EB_HEADSIZE+EB_NTSD_VERSION])); r = PK_WARN; break; default: if ((r & 0xff) != PK_ERR) Info(slide, 1, ((char *)slide, LoadFarString(UnknErrorEAs))); else { ush m = (ush)(r >> 8); if (m == DEFLATED) /* GRR KLUDGE! */ Info(slide, 1, ((char *)slide, LoadFarString(BadCRC_EAs))); else Info(slide, 1, ((char *)slide, LoadFarString(UnknComprMethodEAs), m)); } break; } return r; } break; case EF_PKVMS: if (makelong(ef+EB_HEADSIZE) != crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4), (extent)(ebLen-4))) Info(slide, 1, ((char *)slide, LoadFarString(BadCRC_EAs))); break; case EF_PKW32: case EF_PKUNIX: case EF_ASIUNIX: case EF_IZVMS: case EF_IZUNIX: case EF_VMCMS: case EF_MVS: case EF_SPARK: case EF_TANDEM: case EF_THEOS: case EF_AV: default: break; } ef_len -= (ebLen + EB_HEADSIZE); ef += (ebLen + EB_HEADSIZE); } if (!uO.qflag) Info(slide, 0, ((char *)slide, " OK\n")); return PK_COOL; } /* end function TestExtraField() */ /******************************/ /* Function test_compr_eb() */ /******************************/ #ifdef PROTO static int test_compr_eb( __GPRO__ uch *eb, unsigned eb_size, unsigned compr_offset, int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, uch *eb_ucptr, ulg eb_ucsize)) #else /* !PROTO */ static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata) __GDEF uch *eb; unsigned eb_size; unsigned compr_offset; int (*test_uc_ebdata)(); #endif /* ?PROTO */ { ulg eb_ucsize; uch *eb_ucptr; int r; if (compr_offset < 4) /* field is not compressed: */ return PK_OK; /* do nothing and signal OK */ if ((eb_size < (EB_UCSIZE_P + 4)) || ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L && eb_size <= (compr_offset + EB_CMPRHEADLEN))) return IZ_EF_TRUNC; /* no compressed data! */ if ( #ifdef INT_16BIT (((ulg)(extent)eb_ucsize) != eb_ucsize) || #endif (eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL) return PK_MEM4; r = memextract(__G__ eb_ucptr, eb_ucsize, eb + (EB_HEADSIZE + compr_offset), (ulg)(eb_size - compr_offset)); if (r == PK_OK && test_uc_ebdata != NULL) r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize); free(eb_ucptr); return r; } /* end function test_compr_eb() */ #endif /* !SFX */ /***************************/ /* Function memextract() */ /***************************/ int memextract(__G__ tgt, tgtsize, src, srcsize) /* extract compressed */ __GDEF /* extra field block; */ uch *tgt; /* return PK-type error */ ulg tgtsize; /* level */ ZCONST uch *src; ulg srcsize; { zoff_t old_csize=G.csize; uch *old_inptr=G.inptr; int old_incnt=G.incnt; int r, error=PK_OK; ush method; ulg extra_field_crc; method = makeword(src); extra_field_crc = makelong(src+2); /* compressed extra field exists completely in memory at this location: */ G.inptr = (uch *)src + (2 + 4); /* method and extra_field_crc */ G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4))); G.mem_mode = TRUE; G.outbufptr = tgt; G.outsize = tgtsize; switch (method) { case STORED: memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt); G.outcnt = (ulg)G.csize; /* for CRC calculation */ break; case DEFLATED: #ifdef USE_DEFLATE64 case ENHDEFLATED: #endif G.outcnt = 0L; if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) { if (!uO.tflag) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Inflate))); error = (r == 3)? PK_MEM3 : PK_ERR; } if (G.outcnt == 0L) /* inflate's final FLUSH sets outcnt */ break; break; default: if (uO.tflag) error = PK_ERR | ((int)method << 8); else { Info(slide, 0x401, ((char *)slide, LoadFarString(UnsupportedExtraField), method)); error = PK_ERR; /* GRR: should be passed on up via SetEAs() */ } break; } G.inptr = old_inptr; G.incnt = old_incnt; G.csize = old_csize; G.mem_mode = FALSE; if (!error) { register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt); if (crcval != extra_field_crc) { if (uO.tflag) error = PK_ERR | (DEFLATED << 8); /* kludge for now */ else { Info(slide, 0x401, ((char *)slide, LoadFarString(BadExtraFieldCRC), G.zipfn, crcval, extra_field_crc)); error = PK_ERR; } } } return error; } /* end function memextract() */ /*************************/ /* Function memflush() */ /*************************/ int memflush(__G__ rawbuf, size) __GDEF ZCONST uch *rawbuf; ulg size; { if (size > G.outsize) /* Here, PK_DISK is a bit off-topic, but in the sense of marking "overflow of output space", its use may be tolerated. */ return PK_DISK; /* more data than output buffer can hold */ memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size); G.outbufptr += (unsigned int)size; G.outsize -= size; G.outcnt += size; return 0; } /* end function memflush() */ #if (defined(VMS) || defined(VMS_TEXT_CONV)) /************************************/ /* Function extract_izvms_block() */ /************************************/ /* * Extracts block from p. If resulting length is less than needed, fill * extra space with corresponding bytes from 'init'. * Currently understands 3 formats of block compression: * - Simple storing * - Compression of zero bytes to zero bits * - Deflation (see memextract()) * The IZVMS block data is returned in malloc'd space. */ uch *extract_izvms_block(__G__ ebdata, size, retlen, init, needlen) __GDEF ZCONST uch *ebdata; unsigned size; unsigned *retlen; ZCONST uch *init; unsigned needlen; { uch *ucdata; /* Pointer to block allocated */ int cmptype; unsigned usiz, csiz; cmptype = (makeword(ebdata+EB_IZVMS_FLGS) & EB_IZVMS_BCMASK); csiz = size - EB_IZVMS_HLEN; usiz = (cmptype == EB_IZVMS_BCSTOR ? csiz : makeword(ebdata+EB_IZVMS_UCSIZ)); if (retlen) *retlen = usiz; if ((ucdata = (uch *)malloc(MAX(needlen, usiz))) == NULL) return NULL; if (init && (usiz < needlen)) memcpy((char *)ucdata, (ZCONST char *)init, needlen); switch (cmptype) { case EB_IZVMS_BCSTOR: /* The simplest case */ memcpy(ucdata, ebdata+EB_IZVMS_HLEN, usiz); break; case EB_IZVMS_BC00: decompress_bits(ucdata, usiz, ebdata+EB_IZVMS_HLEN); break; case EB_IZVMS_BCDEFL: memextract(__G__ ucdata, (ulg)usiz, ebdata+EB_IZVMS_HLEN, (ulg)csiz); break; default: free(ucdata); ucdata = NULL; } return ucdata; } /* end of extract_izvms_block */ /********************************/ /* Function decompress_bits() */ /********************************/ /* * Simple uncompression routine. The compression uses bit stream. * Compression scheme: * * if (byte!=0) * putbit(1),putbyte(byte) * else * putbit(0) */ static void decompress_bits(outptr, needlen, bitptr) uch *outptr; /* Pointer into output block */ unsigned needlen; /* Size of uncompressed block */ ZCONST uch *bitptr; /* Pointer into compressed data */ { ulg bitbuf = 0; int bitcnt = 0; #define _FILL { bitbuf |= (*bitptr++) << bitcnt;\ bitcnt += 8; \ } while (needlen--) { if (bitcnt <= 0) _FILL; if (bitbuf & 1) { bitbuf >>= 1; if ((bitcnt -= 1) < 8) _FILL; *outptr++ = (uch)bitbuf; bitcnt -= 8; bitbuf >>= 8; } else { *outptr++ = '\0'; bitcnt -= 1; bitbuf >>= 1; } } } /* end function decompress_bits() */ #endif /* VMS || VMS_TEXT_CONV */ #ifdef SYMLINKS /***********************************/ /* Function set_deferred_symlink() */ /***********************************/ static void set_deferred_symlink(__G__ slnk_entry) __GDEF slinkentry *slnk_entry; { extent ucsize = slnk_entry->targetlen; char *linkfname = slnk_entry->fname; char *linktarget = (char *)malloc(ucsize+1); if (!linktarget) { Info(slide, 0x201, ((char *)slide, LoadFarString(SymLnkWarnNoMem), FnFilter1(linkfname))); return; } linktarget[ucsize] = '\0'; G.outfile = zfopen(linkfname, FOPR); /* open link placeholder for reading */ /* Check that the following conditions are all fulfilled: * a) the placeholder file exists, * b) the placeholder file contains exactly "ucsize" bytes * (read the expected placeholder content length + 1 extra byte, this * should return the expected content length), * c) the placeholder content matches the link target specification as * stored in the symlink control structure. */ if (!G.outfile || fread(linktarget, 1, ucsize+1, G.outfile) != ucsize || strcmp(slnk_entry->target, linktarget)) { Info(slide, 0x201, ((char *)slide, LoadFarString(SymLnkWarnInvalid), FnFilter1(linkfname))); free(linktarget); if (G.outfile) fclose(G.outfile); return; } fclose(G.outfile); /* close "data" file for good... */ unlink(linkfname); /* ...and delete it */ if (QCOND2) Info(slide, 0, ((char *)slide, LoadFarString(SymLnkFinish), FnFilter1(linkfname), FnFilter2(linktarget))); if (symlink(linktarget, linkfname)) /* create the real link */ perror("symlink error"); free(linktarget); #ifdef SET_SYMLINK_ATTRIBS set_symlnk_attribs(__G__ slnk_entry); #endif return; /* can't set time on symlinks */ } /* end function set_deferred_symlink() */ #endif /* SYMLINKS */ /*************************/ /* Function fnfilter() */ /* here instead of in list.c for SFX */ /*************************/ char *fnfilter(raw, space, size) /* convert name to safely printable form */ ZCONST char *raw; uch *space; extent size; { #ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */ ZCONST uch *r=(ZCONST uch *)raw; uch *s=space; uch *slim=NULL; uch *se=NULL; int have_overflow = FALSE; if (size > 0) { slim = space + size #ifdef _MBCS - (MB_CUR_MAX - 1) #endif - 4; } while (*r) { if (size > 0 && s >= slim && se == NULL) { se = s; } #ifdef QDOS if (qlflag & 2) { if (*r == '/' || *r == '.') { if (se != NULL && (s > (space + (size-3)))) { have_overflow = TRUE; break; } ++r; *s++ = '_'; continue; } } else #endif #ifdef HAVE_WORKING_ISPRINT # ifndef UZ_FNFILTER_REPLACECHAR /* A convenient choice for the replacement of unprintable char codes is * the "single char wildcard", as this character is quite unlikely to * appear in filenames by itself. The following default definition * sets the replacement char to a question mark as the most common * "single char wildcard"; this setting should be overridden in the * appropiate system-specific configuration header when needed. */ # define UZ_FNFILTER_REPLACECHAR '?' # endif if (!isprint(*r)) { if (*r < 32) { /* ASCII control codes are escaped as "^{letter}". */ if (se != NULL && (s > (space + (size-4)))) { have_overflow = TRUE; break; } *s++ = '^', *s++ = (uch)(64 + *r++); } else { /* Other unprintable codes are replaced by the * placeholder character. */ if (se != NULL && (s > (space + (size-3)))) { have_overflow = TRUE; break; } *s++ = UZ_FNFILTER_REPLACECHAR; INCSTR(r); } #else /* !HAVE_WORKING_ISPRINT */ if (*r < 32) { /* ASCII control codes are escaped as "^{letter}". */ if (se != NULL && (s > (space + (size-4)))) { have_overflow = TRUE; break; } *s++ = '^', *s++ = (uch)(64 + *r++); #endif /* ?HAVE_WORKING_ISPRINT */ } else { #ifdef _MBCS unsigned i = CLEN(r); if (se != NULL && (s > (space + (size-i-2)))) { have_overflow = TRUE; break; } for (; i > 0; i--) *s++ = *r++; #else if (se != NULL && (s > (space + (size-3)))) { have_overflow = TRUE; break; } *s++ = *r++; #endif } } if (have_overflow) { strcpy((char *)se, "..."); } else { *s = '\0'; } #ifdef WINDLL INTERN_TO_ISO((char *)space, (char *)space); /* translate to ANSI */ #else #if (defined(WIN32) && !defined(_WIN32_WCE)) /* Win9x console always uses OEM character coding, and WinNT console is set to OEM charset by default, too */ INTERN_TO_OEM((char *)space, (char *)space); #endif /* (WIN32 && !_WIN32_WCE) */ #endif /* ?WINDLL */ return (char *)space; #else /* NATIVE: EBCDIC or whatever */ return (char *)raw; #endif } /* end function fnfilter() */ #ifdef SET_DIR_ATTRIB /* must sort saved directories so can set perms from bottom up */ /************************/ /* Function dircomp() */ /************************/ static int Cdecl dircomp(a, b) /* used by qsort(); swiped from Zip */ ZCONST zvoid *a, *b; { /* order is significant: this sorts in reverse order (deepest first) */ return strcmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */ } #endif /* SET_DIR_ATTRIB */ #ifdef USE_BZIP2 /**************************/ /* Function UZbunzip2() */ /**************************/ int UZbunzip2(__G) __GDEF /* decompress a bzipped entry using the libbz2 routines */ { int retval = 0; /* return code: 0 = "no error" */ int err=BZ_OK; int repeated_buf_err; bz_stream bstrm; #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) wsize = G.redirect_size, redirSlide = G.redirect_buffer; else wsize = WSIZE, redirSlide = slide; #endif bstrm.next_out = (char *)redirSlide; bstrm.avail_out = wsize; bstrm.next_in = (char *)G.inptr; bstrm.avail_in = G.incnt; { /* local buffer for efficiency */ /* $TODO Check for BZIP LIB version? */ bstrm.bzalloc = NULL; bstrm.bzfree = NULL; bstrm.opaque = NULL; Trace((stderr, "initializing bzlib()\n")); err = BZ2_bzDecompressInit(&bstrm, 0, 0); if (err == BZ_MEM_ERROR) return 3; else if (err != BZ_OK) Trace((stderr, "oops! (BZ2_bzDecompressInit() err = %d)\n", err)); } #ifdef FUNZIP while (err != BZ_STREAM_END) { #else /* !FUNZIP */ while (G.csize > 0) { Trace((stderr, "first loop: G.csize = %ld\n", G.csize)); #endif /* ?FUNZIP */ while (bstrm.avail_out > 0) { err = BZ2_bzDecompress(&bstrm); if (err == BZ_DATA_ERROR) { retval = 2; goto uzbunzip_cleanup_exit; } else if (err == BZ_MEM_ERROR) { retval = 3; goto uzbunzip_cleanup_exit; } else if (err != BZ_OK && err != BZ_STREAM_END) Trace((stderr, "oops! (bzip(first loop) err = %d)\n", err)); #ifdef FUNZIP if (err == BZ_STREAM_END) /* "END-of-entry-condition" ? */ #else /* !FUNZIP */ if (G.csize <= 0L) /* "END-of-entry-condition" ? */ #endif /* ?FUNZIP */ break; if (bstrm.avail_in == 0) { if (fillinbuf(__G) == 0) { /* no "END-condition" yet, but no more data */ retval = 2; goto uzbunzip_cleanup_exit; } bstrm.next_in = (char *)G.inptr; bstrm.avail_in = G.incnt; } Trace((stderr, " avail_in = %u\n", bstrm.avail_in)); } /* flush slide[] */ if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0) goto uzbunzip_cleanup_exit; Trace((stderr, "inside loop: flushing %ld bytes (ptr diff = %ld)\n", (long)(wsize - bstrm.avail_out), (long)(bstrm.next_out-(char *)redirSlide))); bstrm.next_out = (char *)redirSlide; bstrm.avail_out = wsize; } /* no more input, so loop until we have all output */ Trace((stderr, "beginning final loop: err = %d\n", err)); repeated_buf_err = FALSE; while (err != BZ_STREAM_END) { err = BZ2_bzDecompress(&bstrm); if (err == BZ_DATA_ERROR) { retval = 2; goto uzbunzip_cleanup_exit; } else if (err == BZ_MEM_ERROR) { retval = 3; goto uzbunzip_cleanup_exit; } else if (err != BZ_OK && err != BZ_STREAM_END) { Trace((stderr, "oops! (bzip(final loop) err = %d)\n", err)); DESTROYGLOBALS(); EXIT(PK_MEM3); } /* final flush of slide[] */ if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0) goto uzbunzip_cleanup_exit; Trace((stderr, "final loop: flushing %ld bytes (ptr diff = %ld)\n", (long)(wsize - bstrm.avail_out), (long)(bstrm.next_out-(char *)redirSlide))); bstrm.next_out = (char *)redirSlide; bstrm.avail_out = wsize; } #ifdef LARGE_FILE_SUPPORT Trace((stderr, "total in = %llu, total out = %llu\n", (zusz_t)(bstrm.total_in_lo32) + ((zusz_t)(bstrm.total_in_hi32))<<32, (zusz_t)(bstrm.total_out_lo32) + ((zusz_t)(bstrm.total_out_hi32))<<32)); #else Trace((stderr, "total in = %lu, total out = %lu\n", bstrm.total_in_lo32, bstrm.total_out_lo32)); #endif G.inptr = (uch *)bstrm.next_in; G.incnt = (G.inbuf + INBUFSIZ) - G.inptr; /* reset for other routines */ uzbunzip_cleanup_exit: err = BZ2_bzDecompressEnd(&bstrm); if (err != BZ_OK) Trace((stderr, "oops! (BZ2_bzDecompressEnd() err = %d)\n", err)); return retval; } /* end function UZbunzip2() */ #endif /* USE_BZIP2 */ Carla-2.1/data/windows/unzipfx-carla-control/fileio.c000066400000000000000000002707121364475620200226770ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- fileio.c This file contains routines for doing direct but relatively generic input/ output, file-related sorts of things, plus some miscellaneous stuff. Most of the stuff has to do with opening, closing, reading and/or writing files. Contains: open_input_file() open_outfile() (not: VMS, AOS/VS, CMSMVS, MACOS, TANDEM) undefer_input() defer_leftover_input() readbuf() readbyte() fillinbuf() seek_zipf() flush() (non-VMS) is_vms_varlen_txt() (non-VMS, VMS_TEXT_CONV only) disk_error() (non-VMS) UzpMessagePrnt() UzpMessageNull() (DLL only) UzpInput() UzpMorePause() UzpPassword() (non-WINDLL) handler() dos_to_unix_time() (non-VMS, non-VM/CMS, non-MVS) check_for_newer() (non-VMS, non-OS/2, non-VM/CMS, non-MVS) do_string() makeword() makelong() makeint64() fzofft() str2iso() (CRYPT && NEED_STR2ISO, only) str2oem() (CRYPT && NEED_STR2OEM, only) memset() (ZMEM only) memcpy() (ZMEM only) zstrnicmp() (NO_STRNICMP only) zstat() (REGULUS only) plastchar() (_MBCS only) uzmbclen() (_MBCS && NEED_UZMBCLEN, only) uzmbschr() (_MBCS && NEED_UZMBSCHR, only) uzmbsrchr() (_MBCS && NEED_UZMBSRCHR, only) fLoadFarString() (SMALL_MEM only) fLoadFarStringSmall() (SMALL_MEM only) fLoadFarStringSmall2() (SMALL_MEM only) zfstrcpy() (SMALL_MEM only) zfstrcmp() (SMALL_MEM && !(SFX || FUNZIP) only) ---------------------------------------------------------------------------*/ #define __FILEIO_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" #ifdef WINDLL # ifdef POCKET_UNZIP # include "wince/intrface.h" # else # include "windll/windll.h" # endif # include #endif #include "crc32.h" #include "crypt.h" #include "ttyio.h" /* setup of codepage conversion for decryption passwords */ #if CRYPT # if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY)) # define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */ # endif # if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY)) # define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */ # endif #endif #include "ebcdic.h" /* definition/initialization of ebcdic[] */ /* Note: Under Windows, the maximum size of the buffer that can be used with any of the *printf calls is 16,384, so win_fprintf was used to feed the fprintf clone no more than 16K chunks at a time. This should be valid for anything up to 64K (and probably beyond, assuming your buffers are that big). */ #ifdef WINDLL # define WriteError(buf,len,strm) \ (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len)) #else /* !WINDLL */ # ifdef USE_FWRITE # define WriteError(buf,len,strm) \ ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len)) # else # define WriteError(buf,len,strm) \ ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len)) # endif #endif /* ?WINDLL */ /* 2005-09-16 SMS. On VMS, when output is redirected to a file, as in a command like "PIPE UNZIP -v > X.OUT", the output file is created with VFC record format, and multiple calls to write() or fwrite() will produce multiple records, even when there's no newline terminator in the buffer. The result is unsightly output with spurious newlines. Using fprintf() instead of write() here, and disabling a fflush(stdout) in UzpMessagePrnt() below, together seem to solve the problem. According to the C RTL manual, "The write and decc$record_write functions always generate at least one record." Also, "[T]he fwrite function always generates at least records." So, "fwrite(buf, len, 1, strm)" is much better ("1" record) than "fwrite(buf, 1, len, strm)" ("len" (1-character) records, _really_ ugly), but neither is better than write(). Similarly, "The fflush function always generates a record if there is unwritten data in the buffer." Apparently fprintf() buffers the stuff somewhere, and puts out a record (only) when it sees a newline. */ #ifdef VMS # define WriteTxtErr(buf,len,strm) \ ((extent)fprintf(strm, "%.*s", len, buf) != (extent)(len)) #else # define WriteTxtErr(buf,len,strm) WriteError(buf,len,strm) #endif #if (defined(USE_DEFLATE64) && defined(__16BIT__)) static int partflush OF((__GPRO__ uch *rawbuf, ulg size, int unshrink)); #endif #ifdef VMS_TEXT_CONV static int is_vms_varlen_txt OF((__GPRO__ uch *ef_buf, unsigned ef_len)); #endif static int disk_error OF((__GPRO)); /****************************/ /* Strings used in fileio.c */ /****************************/ static ZCONST char Far CannotOpenZipfile[] = "error: cannot open zipfile [ %s ]\n %s\n"; #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) #if (!defined(TANDEM)) #if (defined(ATH_BEO_THS_UNX) || defined(DOS_FLX_NLM_OS2_W32)) static ZCONST char Far CannotDeleteOldFile[] = "error: cannot delete old %s\n %s\n"; #ifdef UNIXBACKUP static ZCONST char Far CannotRenameOldFile[] = "error: cannot rename old %s\n %s\n"; static ZCONST char Far BackupSuffix[] = "~"; #endif #endif /* ATH_BEO_THS_UNX || DOS_FLX_NLM_OS2_W32 */ #ifdef NOVELL_BUG_FAILSAFE static ZCONST char Far NovellBug[] = "error: %s: stat() says does not exist, but fopen() found anyway\n"; #endif static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n %s\n"; #endif /* !TANDEM */ #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */ static ZCONST char Far ReadError[] = "error: zipfile read error\n"; static ZCONST char Far FilenameTooLongTrunc[] = "warning: filename too long--truncating.\n"; #ifdef UNICODE_SUPPORT static ZCONST char Far UFilenameTooLongTrunc[] = "warning: Converted unicode filename too long--truncating.\n"; #endif static ZCONST char Far ExtraFieldTooLong[] = "warning: extra field too long (%d). Ignoring...\n"; #ifdef WINDLL static ZCONST char Far DiskFullQuery[] = "%s: write error (disk full?).\n"; #else static ZCONST char Far DiskFullQuery[] = "%s: write error (disk full?). Continue? (y/n/^C) "; static ZCONST char Far ZipfileCorrupt[] = "error: zipfile probably corrupt (%s)\n"; # ifdef SYMLINKS static ZCONST char Far FileIsSymLink[] = "%s exists and is a symbolic link%s.\n"; # endif # ifdef MORE static ZCONST char Far MorePrompt[] = "--More--(%lu)"; # endif static ZCONST char Far QuitPrompt[] = "--- Press `Q' to quit, or any other key to continue ---"; static ZCONST char Far HidePrompt[] = /* "\r \r"; */ "\r \r"; # if CRYPT # ifdef MACOS /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */ static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: "; # else static ZCONST char Far PasswPrompt[] = "[%s] %s password: "; # endif static ZCONST char Far PasswPrompt2[] = "Enter password: "; static ZCONST char Far PasswRetry[] = "password incorrect--reenter: "; # endif /* CRYPT */ #endif /* !WINDLL */ /******************************/ /* Function open_input_file() */ /******************************/ int open_input_file(__G) /* return 1 if open failed */ __GDEF { /* * open the zipfile for reading and in BINARY mode to prevent cr/lf * translation, which would corrupt the bitstreams */ #ifdef VMS G.zipfd = open(G.zipfn, O_RDONLY, 0, OPNZIP_RMS_ARGS); #else /* !VMS */ #ifdef MACOS G.zipfd = open(G.zipfn, 0); #else /* !MACOS */ #ifdef CMS_MVS G.zipfd = vmmvs_open_infile(__G); #else /* !CMS_MVS */ #ifdef USE_STRM_INPUT G.zipfd = fopen(G.zipfn, FOPR); #else /* !USE_STRM_INPUT */ G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY); #endif /* ?USE_STRM_INPUT */ #endif /* ?CMS_MVS */ #endif /* ?MACOS */ #endif /* ?VMS */ #ifdef USE_STRM_INPUT if (G.zipfd == NULL) #else /* if (G.zipfd < 0) */ /* no good for Windows CE port */ if (G.zipfd == -1) #endif { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile), G.zipfn, strerror(errno))); return 1; } return 0; } /* end function open_input_file() */ #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) #if (!defined(TANDEM)) /***************************/ /* Function open_outfile() */ /***************************/ int open_outfile(__G) /* return 1 if fail */ __GDEF { #ifdef DLL if (G.redirect_data) return (redirect_outfile(__G) == FALSE); #endif #ifdef QDOS QFilename(__G__ G.filename); #endif #if (defined(DOS_FLX_NLM_OS2_W32) || defined(ATH_BEO_THS_UNX)) #ifdef BORLAND_STAT_BUG /* Borland 5.0's stat() barfs if the filename has no extension and the * file doesn't exist. */ if (access(G.filename, 0) == -1) { FILE *tmp = fopen(G.filename, "wb+"); /* file doesn't exist, so create a dummy file to keep stat() from * failing (will be over-written anyway) */ fputc('0', tmp); /* just to have something in the file */ fclose(tmp); } #endif /* BORLAND_STAT_BUG */ #ifdef SYMLINKS if (SSTAT(G.filename, &G.statbuf) == 0 || lstat(G.filename, &G.statbuf) == 0) #else if (SSTAT(G.filename, &G.statbuf) == 0) #endif /* ?SYMLINKS */ { Trace((stderr, "open_outfile: stat(%s) returns 0: file exists\n", FnFilter1(G.filename))); #ifdef UNIXBACKUP if (uO.B_flag) { /* do backup */ char *tname; z_stat tmpstat; int blen, flen, tlen; blen = strlen(BackupSuffix); flen = strlen(G.filename); tlen = flen + blen + 6; /* includes space for 5 digits */ if (tlen >= FILNAMSIZ) { /* in case name is too long, truncate */ tname = (char *)malloc(FILNAMSIZ); if (tname == NULL) return 1; /* in case we run out of space */ tlen = FILNAMSIZ - 1 - blen; strcpy(tname, G.filename); /* make backup name */ tname[tlen] = '\0'; if (flen > tlen) flen = tlen; tlen = FILNAMSIZ; } else { tname = (char *)malloc(tlen); if (tname == NULL) return 1; /* in case we run out of space */ strcpy(tname, G.filename); /* make backup name */ } strcpy(tname+flen, BackupSuffix); if (IS_OVERWRT_ALL) { /* If there is a previous backup file, delete it, * otherwise the following rename operation may fail. */ if (SSTAT(tname, &tmpstat) == 0) unlink(tname); } else { /* Check if backupname exists, and, if it's true, try * appending numbers of up to 5 digits (or the maximum * "unsigned int" number on 16-bit systems) to the * BackupSuffix, until an unused name is found. */ unsigned maxtail, i; char *numtail = tname + flen + blen; /* take account of the "unsigned" limit on 16-bit systems: */ maxtail = ( ((~0) >= 99999L) ? 99999 : (~0) ); switch (tlen - flen - blen - 1) { case 4: maxtail = 9999; break; case 3: maxtail = 999; break; case 2: maxtail = 99; break; case 1: maxtail = 9; break; case 0: maxtail = 0; break; } /* while filename exists */ for (i = 0; (i < maxtail) && (SSTAT(tname, &tmpstat) == 0);) sprintf(numtail,"%u", ++i); } if (rename(G.filename, tname) != 0) { /* move file */ Info(slide, 0x401, ((char *)slide, LoadFarString(CannotRenameOldFile), FnFilter1(G.filename), strerror(errno))); free(tname); return 1; } Trace((stderr, "open_outfile: %s now renamed into %s\n", FnFilter1(G.filename), FnFilter2(tname))); free(tname); } else #endif /* UNIXBACKUP */ { #ifdef DOS_FLX_OS2_W32 if (!(G.statbuf.st_mode & S_IWRITE)) { Trace((stderr, "open_outfile: existing file %s is read-only\n", FnFilter1(G.filename))); chmod(G.filename, S_IREAD | S_IWRITE); Trace((stderr, "open_outfile: %s now writable\n", FnFilter1(G.filename))); } #endif /* DOS_FLX_OS2_W32 */ #ifdef NLM /* Give the file read/write permission (non-POSIX shortcut) */ chmod(G.filename, 0); #endif /* NLM */ if (unlink(G.filename) != 0) { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename), strerror(errno))); return 1; } Trace((stderr, "open_outfile: %s now deleted\n", FnFilter1(G.filename))); } } #endif /* DOS_FLX_NLM_OS2_W32 || ATH_BEO_THS_UNX */ #ifdef RISCOS if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) { Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), FnFilter1(G.filename), strerror(errno))); return 1; } #endif /* RISCOS */ #ifdef TOPS20 char *tfilnam; if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL) return 1; strcpy(tfilnam, G.filename); upper(tfilnam); enquote(tfilnam); if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) { Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), tfilnam, strerror(errno))); free(tfilnam); return 1; } free(tfilnam); #else /* !TOPS20 */ #ifdef MTS if (uO.aflag) G.outfile = zfopen(G.filename, FOPWT); else G.outfile = zfopen(G.filename, FOPW); if (G.outfile == (FILE *)NULL) { Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), FnFilter1(G.filename), strerror(errno))); return 1; } #else /* !MTS */ #ifdef DEBUG Info(slide, 1, ((char *)slide, "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G.filename))); if ((G.outfile = zfopen(G.filename, FOPR)) == (FILE *)NULL) Info(slide, 1, ((char *)slide, "open_outfile: fopen(%s) for reading failed: does not exist\n", FnFilter1(G.filename))); else { Info(slide, 1, ((char *)slide, "open_outfile: fopen(%s) for reading succeeded: file exists\n", FnFilter1(G.filename))); fclose(G.outfile); } #endif /* DEBUG */ #ifdef NOVELL_BUG_FAILSAFE if (G.dne && ((G.outfile = zfopen(G.filename, FOPR)) != (FILE *)NULL)) { Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug), FnFilter1(G.filename))); fclose(G.outfile); return 1; /* with "./" fix in checkdir(), should never reach here */ } #endif /* NOVELL_BUG_FAILSAFE */ Trace((stderr, "open_outfile: doing fopen(%s) for writing\n", FnFilter1(G.filename))); { #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM) mode_t umask_sav = umask(0077); #endif #if defined(SYMLINKS) || defined(QLZIP) /* These features require the ability to re-read extracted data from the output files. Output files are created with Read&Write access. */ G.outfile = zfopen(G.filename, FOPWR); #else G.outfile = zfopen(G.filename, FOPW); #endif #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM) umask(umask_sav); #endif } if (G.outfile == (FILE *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile), FnFilter1(G.filename), strerror(errno))); return 1; } Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n", FnFilter1(G.filename))); #endif /* !MTS */ #endif /* !TOPS20 */ #ifdef USE_FWRITE #ifdef DOS_NLM_OS2_W32 /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */ setbuf(G.outfile, (char *)NULL); /* make output unbuffered */ #else /* !DOS_NLM_OS2_W32 */ #ifndef RISCOS #ifdef _IOFBF /* make output fully buffered (works just about like write()) */ setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE); #else setbuf(G.outfile, (char *)slide); #endif #endif /* !RISCOS */ #endif /* ?DOS_NLM_OS2_W32 */ #endif /* USE_FWRITE */ #ifdef OS2_W32 /* preallocate the final file size to prevent file fragmentation */ SetFileSize(G.outfile, G.lrec.ucsize); #endif return 0; } /* end function open_outfile() */ #endif /* !TANDEM */ #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */ /* * These functions allow NEXTBYTE to function without needing two bounds * checks. Call defer_leftover_input() if you ever have filled G.inbuf * by some means other than readbyte(), and you then want to start using * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call * undefer_input(). For example, extract_or_test_member brackets its * central section that does the decompression with these two functions. * If you need to check the number of bytes remaining in the current * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize. */ /****************************/ /* function undefer_input() */ /****************************/ void undefer_input(__G) __GDEF { if (G.incnt > 0) G.csize += G.incnt; if (G.incnt_leftover > 0) { /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int: * This condition was checked when G.incnt_leftover was set > 0 in * defer_leftover_input(), and it is NOT allowed to touch G.csize * before calling undefer_input() when (G.incnt_leftover > 0) * (single exception: see read_byte()'s "G.csize <= 0" handling) !! */ G.incnt = G.incnt_leftover + (int)G.csize; G.inptr = G.inptr_leftover - (int)G.csize; G.incnt_leftover = 0; } else if (G.incnt < 0) G.incnt = 0; } /* end function undefer_input() */ /***********************************/ /* function defer_leftover_input() */ /***********************************/ void defer_leftover_input(__G) __GDEF { if ((zoff_t)G.incnt > G.csize) { /* (G.csize < MAXINT), we can safely cast it to int !! */ if (G.csize < 0L) G.csize = 0L; G.inptr_leftover = G.inptr + (int)G.csize; G.incnt_leftover = G.incnt - (int)G.csize; G.incnt = (int)G.csize; } else G.incnt_leftover = 0; G.csize -= G.incnt; } /* end function defer_leftover_input() */ /**********************/ /* Function readbuf() */ /**********************/ unsigned readbuf(__G__ buf, size) /* return number of bytes read into buf */ __GDEF char *buf; register unsigned size; { register unsigned count; unsigned n; n = size; while (size) { if (G.incnt <= 0) { if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) return (n-size); else if (G.incnt < 0) { /* another hack, but no real harm copying same thing twice */ (*G.message)((zvoid *)&G, (uch *)LoadFarString(ReadError), /* CANNOT use slide */ (ulg)strlen(LoadFarString(ReadError)), 0x401); return 0; /* discarding some data; better than lock-up */ } /* buffer ALWAYS starts on a block boundary: */ G.cur_zipfile_bufstart += INBUFSIZ; G.inptr = G.inbuf; } count = MIN(size, (unsigned)G.incnt); memcpy(buf, G.inptr, count); buf += count; G.inptr += count; G.incnt -= count; size -= count; } return n; } /* end function readbuf() */ /***********************/ /* Function readbyte() */ /***********************/ int readbyte(__G) /* refill inbuf and return a byte if available, else EOF */ __GDEF { if (G.mem_mode) return EOF; if (G.csize <= 0) { G.csize--; /* for tests done after exploding */ G.incnt = 0; return EOF; } if (G.incnt <= 0) { if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) { return EOF; } else if (G.incnt < 0) { /* "fail" (abort, retry, ...) returns this */ /* another hack, but no real harm copying same thing twice */ (*G.message)((zvoid *)&G, (uch *)LoadFarString(ReadError), (ulg)strlen(LoadFarString(ReadError)), 0x401); echon(); #ifdef WINDLL longjmp(dll_error_return, 1); #else DESTROYGLOBALS(); EXIT(PK_BADERR); /* totally bailing; better than lock-up */ #endif } G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */ G.inptr = G.inbuf; defer_leftover_input(__G); /* decrements G.csize */ } #if CRYPT if (G.pInfo->encrypted) { uch *p; int n; /* This was previously set to decrypt one byte beyond G.csize, when * incnt reached that far. GRR said, "but it's required: why?" This * was a bug in fillinbuf() -- was it also a bug here? */ for (n = G.incnt, p = G.inptr; n--; p++) zdecode(*p); } #endif /* CRYPT */ --G.incnt; return *G.inptr++; } /* end function readbyte() */ #if defined(USE_ZLIB) || defined(USE_BZIP2) /************************/ /* Function fillinbuf() */ /************************/ int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */ __GDEF { if (G.mem_mode || (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) return 0; G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on a block boundary */ G.inptr = G.inbuf; defer_leftover_input(__G); /* decrements G.csize */ #if CRYPT if (G.pInfo->encrypted) { uch *p; int n; for (n = G.incnt, p = G.inptr; n--; p++) zdecode(*p); } #endif /* CRYPT */ return G.incnt; } /* end function fillinbuf() */ #endif /* USE_ZLIB || USE_BZIP2 */ /************************/ /* Function seek_zipf() */ /************************/ int seek_zipf(__G__ abs_offset) __GDEF zoff_t abs_offset; { /* * Seek to the block boundary of the block which includes abs_offset, * then read block into input buffer and set pointers appropriately. * If block is already in the buffer, just set the pointers. This function * is used by do_seekable (process.c), extract_or_test_entrylist (extract.c) * and do_string (fileio.c). Also, a slightly modified version is embedded * within extract_or_test_entrylist (extract.c). readbyte() and readbuf() * (fileio.c) are compatible. NOTE THAT abs_offset is intended to be the * "proper offset" (i.e., if there were no extra bytes prepended); * cur_zipfile_bufstart contains the corrected offset. * * Since seek_zipf() is never used during decompression, it is safe to * use the slide[] buffer for the error message. * * returns PK error codes: * PK_BADERR if effective offset in zipfile is negative * PK_EOF if seeking past end of zipfile * PK_OK when seek was successful */ zoff_t request = abs_offset + G.extra_bytes; zoff_t inbuf_offset = request % INBUFSIZ; zoff_t bufstart = request - inbuf_offset; if (request < 0) { Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg), G.zipfn, LoadFarString(ReportMsg))); return(PK_BADERR); } else if (bufstart != G.cur_zipfile_bufstart) { Trace((stderr, "fpos_zip: abs_offset = %s, G.extra_bytes = %s\n", FmZofft(abs_offset, NULL, NULL), FmZofft(G.extra_bytes, NULL, NULL))); #ifdef USE_STRM_INPUT zfseeko(G.zipfd, bufstart, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, bufstart, SEEK_SET); #endif /* ?USE_STRM_INPUT */ Trace((stderr, " request = %s, (abs+extra) = %s, inbuf_offset = %s\n", FmZofft(request, NULL, NULL), FmZofft((abs_offset+G.extra_bytes), NULL, NULL), FmZofft(inbuf_offset, NULL, NULL))); Trace((stderr, " bufstart = %s, cur_zipfile_bufstart = %s\n", FmZofft(bufstart, NULL, NULL), FmZofft(G.cur_zipfile_bufstart, NULL, NULL))); if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) return(PK_EOF); G.incnt -= (int)inbuf_offset; G.inptr = G.inbuf + (int)inbuf_offset; } else { G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset; G.inptr = G.inbuf + (int)inbuf_offset; } return(PK_OK); } /* end function seek_zipf() */ #ifndef VMS /* for VMS use code in vms.c */ /********************/ /* Function flush() */ /* returns PK error codes: */ /********************/ /* if tflag => always 0; PK_DISK if write error */ int flush(__G__ rawbuf, size, unshrink) __GDEF uch *rawbuf; ulg size; int unshrink; #if (defined(USE_DEFLATE64) && defined(__16BIT__)) { int ret; /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions * cannot handle writes of 64k blocks at once. For these systems, the * blocks to flush are split into pieces of 32k or less. */ while (size > 0x8000L) { ret = partflush(__G__ rawbuf, 0x8000L, unshrink); if (ret != PK_OK) return ret; size -= 0x8000L; rawbuf += (extent)0x8000; } return partflush(__G__ rawbuf, size, unshrink); } /* end function flush() */ /************************/ /* Function partflush() */ /* returns PK error codes: */ /************************/ /* if tflag => always 0; PK_DISK if write error */ static int partflush(__G__ rawbuf, size, unshrink) __GDEF uch *rawbuf; /* cannot be ZCONST, gets passed to (*G.message)() */ ulg size; int unshrink; #endif /* USE_DEFLATE64 && __16BIT__ */ { register uch *p; register uch *q; uch *transbuf; #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) ulg transbufsiz; #endif /* static int didCRlast = FALSE; moved to globals.h */ /*--------------------------------------------------------------------------- Compute the CRC first; if testing or if disk is full, that's it. ---------------------------------------------------------------------------*/ G.crc32val = crc32(G.crc32val, rawbuf, (extent)size); #ifdef DLL if ((G.statreportcb != NULL) && (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL)) return IZ_CTRLC; /* cancel operation by user request */ #endif if (uO.tflag || size == 0L) /* testing or nothing to write: all done */ return PK_OK; if (G.disk_full) return PK_DISK; /* disk already full: ignore rest of file */ /*--------------------------------------------------------------------------- Write the bytes rawbuf[0..size-1] to the output device, first converting end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT defined, outbuf is assumed to be at least as large as rawbuf and is not necessarily checked for overflow. ---------------------------------------------------------------------------*/ if (!G.pInfo->textmode) { /* write raw binary data */ /* GRR: note that for standard MS-DOS compilers, size argument to * fwrite() can never be more than 65534, so WriteError macro will * have to be rewritten if size can ever be that large. For now, * never more than 32K. Also note that write() returns an int, which * doesn't necessarily limit size to 32767 bytes if write() is used * on 16-bit systems but does make it more of a pain; however, because * at least MSC 5.1 has a lousy implementation of fwrite() (as does * DEC Ultrix cc), write() is used anyway. */ #ifdef DLL if (G.redirect_data) { #ifdef NO_SLIDE_REDIR if (writeToMemory(__G__ rawbuf, (extent)size)) return PK_ERR; #else writeToMemory(__G__ rawbuf, (extent)size); #endif } else #endif if (!uO.cflag && WriteError(rawbuf, size, G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0)) return PK_OK; } else { /* textmode: aflag is true */ if (unshrink) { /* rawbuf = outbuf */ transbuf = G.outbuf2; #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) transbufsiz = TRANSBUFSIZ; #endif } else { /* rawbuf = slide */ transbuf = G.outbuf; #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) transbufsiz = OUTBUFSIZ; Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", (unsigned)OUTBUFSIZ)); #endif } if (G.newfile) { #ifdef VMS_TEXT_CONV if (G.pInfo->hostnum == VMS_ && G.extra_field && is_vms_varlen_txt(__G__ G.extra_field, G.lrec.extra_field_length)) G.VMS_line_state = 0; /* 0: ready to read line length */ else G.VMS_line_state = -1; /* -1: don't treat as VMS text */ #endif G.didCRlast = FALSE; /* no previous buffers written */ G.newfile = FALSE; } #ifdef VMS_TEXT_CONV if (G.VMS_line_state >= 0) { p = rawbuf; q = transbuf; while ((extent)(p-rawbuf) < (extent)size) { switch (G.VMS_line_state) { /* 0: ready to read line length */ case 0: G.VMS_line_length = 0; if ((extent)(p-rawbuf) == (extent)size-1) { /* last char */ G.VMS_line_length = (unsigned)(*p++); G.VMS_line_state = 1; } else { G.VMS_line_length = makeword(p); p += 2; G.VMS_line_state = 2; } G.VMS_line_pad = ((G.VMS_line_length & 1) != 0); /* odd */ break; /* 1: read one byte of length, need second */ case 1: G.VMS_line_length += ((unsigned)(*p++) << 8); G.VMS_line_state = 2; break; /* 2: ready to read VMS_line_length chars */ case 2: { extent remaining = (extent)size+(rawbuf-p); extent outroom; if (G.VMS_line_length < remaining) { remaining = G.VMS_line_length; G.VMS_line_state = 3; } outroom = transbuf+(extent)transbufsiz-q; if (remaining >= outroom) { remaining -= outroom; for (;outroom > 0; p++, outroom--) *q++ = native(*p); #ifdef DLL if (G.redirect_data) { if (writeToMemory(__G__ transbuf, (extent)(q-transbuf))) return PK_ERR; } else #endif if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf), G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)(q-transbuf), 0)) return PK_OK; q = transbuf; /* fall through to normal case */ } G.VMS_line_length -= remaining; for (;remaining > 0; p++, remaining--) *q++ = native(*p); } break; /* 3: ready to PutNativeEOL */ case 3: if (q > transbuf+(extent)transbufsiz-lenEOL) { #ifdef DLL if (G.redirect_data) { if (writeToMemory(__G__ transbuf, (extent)(q-transbuf))) return PK_ERR; } else #endif if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf), G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)(q-transbuf), 0)) return PK_OK; q = transbuf; } PutNativeEOL G.VMS_line_state = G.VMS_line_pad ? 4 : 0; break; /* 4: ready to read pad byte */ case 4: ++p; G.VMS_line_state = 0; break; } } /* end while */ } else #endif /* VMS_TEXT_CONV */ /*----------------------------------------------------------------------- Algorithm: CR/LF => native; lone CR => native; lone LF => native. This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e., stream-oriented files, not record-oriented). -----------------------------------------------------------------------*/ /* else not VMS text */ { p = rawbuf; if (*p == LF && G.didCRlast) ++p; G.didCRlast = FALSE; for (q = transbuf; (extent)(p-rawbuf) < (extent)size; ++p) { if (*p == CR) { /* lone CR or CR/LF: treat as EOL */ PutNativeEOL if ((extent)(p-rawbuf) == (extent)size-1) /* last char in buffer */ G.didCRlast = TRUE; else if (p[1] == LF) /* get rid of accompanying LF */ ++p; } else if (*p == LF) /* lone LF */ PutNativeEOL else #ifndef DOS_FLX_OS2_W32 if (*p != CTRLZ) /* lose all ^Z's */ #endif *q++ = native(*p); #if (defined(SMALL_MEM) || defined(MED_MEM)) # if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */ if (!unshrink) # endif /* check for danger of buffer overflow and flush */ if (q > transbuf+(extent)transbufsiz-lenEOL) { Trace((stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n", (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size)); if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf), G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)(q-transbuf), 0)) return PK_OK; q = transbuf; continue; } #endif /* SMALL_MEM || MED_MEM */ } } /*----------------------------------------------------------------------- Done translating: write whatever we've got to file (or screen). -----------------------------------------------------------------------*/ Trace((stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n", (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size)); if (q > transbuf) { #ifdef DLL if (G.redirect_data) { if (writeToMemory(__G__ transbuf, (extent)(q-transbuf))) return PK_ERR; } else #endif if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf), G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)(q-transbuf), 0)) return PK_OK; } } return PK_OK; } /* end function flush() [resp. partflush() for 16-bit Deflate64 support] */ #ifdef VMS_TEXT_CONV /********************************/ /* Function is_vms_varlen_txt() */ /********************************/ static int is_vms_varlen_txt(__G__ ef_buf, ef_len) __GDEF uch *ef_buf; /* buffer containing extra field */ unsigned ef_len; /* total length of extra field */ { unsigned eb_id; unsigned eb_len; uch *eb_data; unsigned eb_datlen; #define VMSREC_C_UNDEF 0 #define VMSREC_C_VAR 2 uch vms_rectype = VMSREC_C_UNDEF; /* uch vms_fileorg = 0; */ /* currently, fileorg is not used... */ #define VMSPK_ITEMID 0 #define VMSPK_ITEMLEN 2 #define VMSPK_ITEMHEADSZ 4 #define VMSATR_C_RECATTR 4 #define VMS_FABSIG 0x42414656 /* "VFAB" */ /* offsets of interesting fields in VMS fabdef structure */ #define VMSFAB_B_RFM 31 /* record format byte */ #define VMSFAB_B_ORG 29 /* file organization byte */ if (ef_len == 0 || ef_buf == NULL) return FALSE; while (ef_len >= EB_HEADSIZE) { eb_id = makeword(EB_ID + ef_buf); eb_len = makeword(EB_LEN + ef_buf); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ Trace((stderr, "is_vms_varlen_txt: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } switch (eb_id) { case EF_PKVMS: /* The PKVMS e.f. raw data part consists of: * a) 4 bytes CRC checksum * b) list of uncompressed variable-length data items * Each data item is introduced by a fixed header * - 2 bytes data type ID * - 2 bytes of data * - bytes of actual attribute data */ /* get pointer to start of data and its total length */ eb_data = ef_buf+(EB_HEADSIZE+4); eb_datlen = eb_len-4; /* test the CRC checksum */ if (makelong(ef_buf+EB_HEADSIZE) != crc32(CRCVAL_INITIAL, eb_data, (extent)eb_datlen)) { Info(slide, 1, ((char *)slide, "[Warning: CRC error, discarding PKWARE extra field]\n")); /* skip over the data analysis code */ break; } /* scan through the attribute data items */ while (eb_datlen > 4) { unsigned fldsize = makeword(&eb_data[VMSPK_ITEMLEN]); /* check the item type word */ switch (makeword(&eb_data[VMSPK_ITEMID])) { case VMSATR_C_RECATTR: /* we have found the (currently only) interesting * data item */ if (fldsize >= 1) { vms_rectype = eb_data[VMSPK_ITEMHEADSZ] & 15; /* vms_fileorg = eb_data[VMSPK_ITEMHEADSZ] >> 4; */ } break; default: break; } /* skip to next data item */ eb_datlen -= fldsize + VMSPK_ITEMHEADSZ; eb_data += fldsize + VMSPK_ITEMHEADSZ; } break; case EF_IZVMS: if (makelong(ef_buf+EB_HEADSIZE) == VMS_FABSIG) { if ((eb_data = extract_izvms_block(__G__ ef_buf+EB_HEADSIZE, eb_len, &eb_datlen, NULL, 0)) != NULL) { if (eb_datlen >= VMSFAB_B_RFM+1) { vms_rectype = eb_data[VMSFAB_B_RFM] & 15; /* vms_fileorg = eb_data[VMSFAB_B_ORG] >> 4; */ } free(eb_data); } } break; default: break; } /* Skip this extra field block */ ef_buf += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return (vms_rectype == VMSREC_C_VAR); } /* end function is_vms_varlen_txtfile() */ #endif /* VMS_TEXT_CONV */ /*************************/ /* Function disk_error() */ /*************************/ static int disk_error(__G) __GDEF { /* OK to use slide[] here because this file is finished regardless */ Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery), FnFilter1(G.filename))); #ifndef WINDLL fgets(G.answerbuf, sizeof(G.answerbuf), stdin); if (*G.answerbuf == 'y') /* stop writing to this file */ G.disk_full = 1; /* (outfile bad?), but new OK */ else #endif G.disk_full = 2; /* no: exit program */ return PK_DISK; } /* end function disk_error() */ #endif /* !VMS */ /*****************************/ /* Function UzpMessagePrnt() */ /*****************************/ int UZ_EXP UzpMessagePrnt(pG, buf, size, flag) zvoid *pG; /* globals struct: always passed */ uch *buf; /* preformatted string to be printed */ ulg size; /* length of string (may include nulls) */ int flag; /* flag bits */ { /* IMPORTANT NOTE: * The name of the first parameter of UzpMessagePrnt(), which passes * the "Uz_Globs" address, >>> MUST <<< be identical to the string * expansion of the __G__ macro in the REENTRANT case (see globals.h). * This name identity is mandatory for the LoadFarString() macro * (in the SMALL_MEM case) !!! */ int error; uch *q=buf, *endbuf=buf+(unsigned)size; #ifdef MORE uch *p=buf; #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) int islinefeed = FALSE; #endif #endif FILE *outfp; /*--------------------------------------------------------------------------- These tests are here to allow fine-tuning of UnZip's output messages, but none of them will do anything without setting the appropriate bit in the flag argument of every Info() statement which is to be turned *off*. That is, all messages are currently turned on for all ports. To turn off *all* messages, use the UzpMessageNull() function instead of this one. ---------------------------------------------------------------------------*/ #if (defined(OS2) && defined(DLL)) if (MSG_NO_DLL2(flag)) /* if OS/2 DLL bit is set, do NOT print this msg */ return 0; #endif #ifdef WINDLL if (MSG_NO_WDLL(flag)) return 0; #endif #ifdef WINDLL if (MSG_NO_WGUI(flag)) return 0; #endif /* #ifdef ACORN_GUI if (MSG_NO_AGUI(flag)) return 0; #endif */ #ifdef DLL /* don't display message if data is redirected */ if (((Uz_Globs *)pG)->redirect_data && !((Uz_Globs *)pG)->redirect_text) return 0; #endif if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag) outfp = (FILE *)stderr; else outfp = (FILE *)stdout; #ifdef QUERY_TRNEWLN /* some systems require termination of query prompts with '\n' to force * immediate display */ if (MSG_MNEWLN(flag)) { /* assumes writable buffer (e.g., slide[]) */ *endbuf++ = '\n'; /* with room for one more char at end of buf */ ++size; /* (safe assumption: only used for four */ } /* short queries in extract.c and fileio.c) */ #endif if (MSG_TNEWLN(flag)) { /* again assumes writable buffer: fragile... */ if ((!size && !((Uz_Globs *)pG)->sol) || (size && (endbuf[-1] != '\n'))) { *endbuf++ = '\n'; ++size; } } #ifdef MORE # ifdef SCREENSIZE /* room for --More-- and one line of overlap: */ # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) SCREENSIZE(&((Uz_Globs *)pG)->height, &((Uz_Globs *)pG)->width); # else SCREENSIZE(&((Uz_Globs *)pG)->height, (int *)NULL); # endif ((Uz_Globs *)pG)->height -= 2; # else /* room for --More-- and one line of overlap: */ ((Uz_Globs *)pG)->height = SCREENLINES - 2; # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) ((Uz_Globs *)pG)->width = SCREENWIDTH; # endif # endif #endif /* MORE */ if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) { /* not at start of line: want newline */ #ifdef OS2DLL if (!((Uz_Globs *)pG)->redirect_text) { #endif putc('\n', outfp); fflush(outfp); #ifdef MORE if (((Uz_Globs *)pG)->M_flag) { #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) ((Uz_Globs *)pG)->chars = 0; #endif ++((Uz_Globs *)pG)->numlines; ++((Uz_Globs *)pG)->lines; if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height) (*((Uz_Globs *)pG)->mpause)((zvoid *)pG, LoadFarString(MorePrompt), 1); } #endif /* MORE */ if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && !isatty(1) && isatty(2)) { /* error output from testing redirected: also send to stderr */ putc('\n', stderr); fflush(stderr); } #ifdef OS2DLL } else REDIRECTC('\n'); #endif ((Uz_Globs *)pG)->sol = TRUE; } /* put zipfile name, filename and/or error/warning keywords here */ #ifdef MORE if (((Uz_Globs *)pG)->M_flag #ifdef OS2DLL && !((Uz_Globs *)pG)->redirect_text #endif ) { while (p < endbuf) { if (*p == '\n') { #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) islinefeed = TRUE; } else if (SCREENLWRAP) { if (*p == '\r') { ((Uz_Globs *)pG)->chars = 0; } else { # ifdef TABSIZE if (*p == '\t') ((Uz_Globs *)pG)->chars += (TABSIZE - (((Uz_Globs *)pG)->chars % TABSIZE)); else # endif ++((Uz_Globs *)pG)->chars; if (((Uz_Globs *)pG)->chars >= ((Uz_Globs *)pG)->width) islinefeed = TRUE; } } if (islinefeed) { islinefeed = FALSE; ((Uz_Globs *)pG)->chars = 0; #endif /* (SCREENWIDTH && SCREEN_LWRAP) */ ++((Uz_Globs *)pG)->numlines; ++((Uz_Globs *)pG)->lines; if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height) { if ((error = WriteTxtErr(q, p-q+1, outfp)) != 0) return error; fflush(outfp); ((Uz_Globs *)pG)->sol = TRUE; q = p + 1; (*((Uz_Globs *)pG)->mpause)((zvoid *)pG, LoadFarString(MorePrompt), 1); } } INCSTR(p); } /* end while */ size = (ulg)(p - q); /* remaining text */ } #endif /* MORE */ if (size) { #ifdef OS2DLL if (!((Uz_Globs *)pG)->redirect_text) { #endif if ((error = WriteTxtErr(q, size, outfp)) != 0) return error; #ifndef VMS /* 2005-09-16 SMS. See note at "WriteTxtErr()", above. */ fflush(outfp); #endif if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && !isatty(1) && isatty(2)) { /* error output from testing redirected: also send to stderr */ if ((error = WriteTxtErr(q, size, stderr)) != 0) return error; fflush(stderr); } #ifdef OS2DLL } else { /* GRR: this is ugly: hide with macro */ if ((error = REDIRECTPRINT(q, size)) != 0) return error; } #endif /* OS2DLL */ ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n'); } return 0; } /* end function UzpMessagePrnt() */ #ifdef DLL /*****************************/ /* Function UzpMessageNull() */ /* convenience routine for no output at all */ /*****************************/ int UZ_EXP UzpMessageNull(pG, buf, size, flag) zvoid *pG; /* globals struct: always passed */ uch *buf; /* preformatted string to be printed */ ulg size; /* length of string (may include nulls) */ int flag; /* flag bits */ { return 0; } /* end function UzpMessageNull() */ #endif /* DLL */ /***********************/ /* Function UzpInput() */ /* GRR: this is a placeholder for now */ /***********************/ int UZ_EXP UzpInput(pG, buf, size, flag) zvoid *pG; /* globals struct: always passed */ uch *buf; /* preformatted string to be printed */ int *size; /* (address of) size of buf and of returned string */ int flag; /* flag bits (bit 0: no echo) */ { /* tell picky compilers to shut up about "unused variable" warnings */ pG = pG; buf = buf; flag = flag; *size = 0; return 0; } /* end function UzpInput() */ #if (!defined(WINDLL) && !defined(MACOS)) /***************************/ /* Function UzpMorePause() */ /***************************/ void UZ_EXP UzpMorePause(pG, prompt, flag) zvoid *pG; /* globals struct: always passed */ ZCONST char *prompt; /* "--More--" prompt */ int flag; /* 0 = any char OK; 1 = accept only '\n', ' ', q */ { uch c; /*--------------------------------------------------------------------------- Print a prompt and wait for the user to press a key, then erase prompt if possible. ---------------------------------------------------------------------------*/ if (!((Uz_Globs *)pG)->sol) fprintf(stderr, "\n"); /* numlines may or may not be used: */ fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines); fflush(stderr); if (flag & 1) { do { c = (uch)FGETCH(0); } while ( #ifdef THEOS c != 17 && /* standard QUIT key */ #endif c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q'); } else c = (uch)FGETCH(0); /* newline was not echoed, so cover up prompt line */ fprintf(stderr, LoadFarString(HidePrompt)); fflush(stderr); if ( #ifdef THEOS (c == 17) || /* standard QUIT key */ #endif (ToLower(c) == 'q')) { DESTROYGLOBALS(); EXIT(PK_COOL); } ((Uz_Globs *)pG)->sol = TRUE; #ifdef MORE /* space for another screen, enter for another line. */ if ((flag & 1) && c == ' ') ((Uz_Globs *)pG)->lines = 0; #endif /* MORE */ } /* end function UzpMorePause() */ #endif /* !WINDLL && !MACOS */ #ifndef WINDLL /**************************/ /* Function UzpPassword() */ /**************************/ int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn) zvoid *pG; /* pointer to UnZip's internal global vars */ int *rcnt; /* retry counter */ char *pwbuf; /* buffer for password */ int size; /* size of password buffer */ ZCONST char *zfn; /* name of zip archive */ ZCONST char *efn; /* name of archive entry being processed */ { #if CRYPT int r = IZ_PW_ENTERED; char *m; char *prompt; #ifndef REENTRANT /* tell picky compilers to shut up about "unused variable" warnings */ pG = pG; #endif if (*rcnt == 0) { /* First call for current entry */ *rcnt = 2; if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) { sprintf(prompt, LoadFarString(PasswPrompt), FnFilter1(zfn), FnFilter2(efn)); m = prompt; } else m = (char *)LoadFarString(PasswPrompt2); } else { /* Retry call, previous password was wrong */ (*rcnt)--; prompt = NULL; m = (char *)LoadFarString(PasswRetry); } m = getp(__G__ m, pwbuf, size); if (prompt != (char *)NULL) { free(prompt); } if (m == (char *)NULL) { r = IZ_PW_ERROR; } else if (*pwbuf == '\0') { r = IZ_PW_CANCELALL; } return r; #else /* !CRYPT */ /* tell picky compilers to shut up about "unused variable" warnings */ pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn; return IZ_PW_ERROR; /* internal error; function should never get called */ #endif /* ?CRYPT */ } /* end function UzpPassword() */ /**********************/ /* Function handler() */ /**********************/ void handler(signal) /* upon interrupt, turn on echo and exit cleanly */ int signal; { GETGLOBALS(); #if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */ (*G.message)((zvoid *)&G, slide, 0L, 0x41); /* start of line (to stderr; */ #endif /* slide[] should be safe) */ echon(); #ifdef SIGBUS if (signal == SIGBUS) { Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), "bus error")); DESTROYGLOBALS(); EXIT(PK_BADERR); } #endif /* SIGBUS */ #ifdef SIGILL if (signal == SIGILL) { Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), "illegal instruction")); DESTROYGLOBALS(); EXIT(PK_BADERR); } #endif /* SIGILL */ #ifdef SIGSEGV if (signal == SIGSEGV) { Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), "segmentation violation")); DESTROYGLOBALS(); EXIT(PK_BADERR); } #endif /* SIGSEGV */ /* probably ctrl-C */ DESTROYGLOBALS(); #if defined(AMIGA) && defined(__SASC) _abort(); #endif EXIT(IZ_CTRLC); /* was EXIT(0), then EXIT(PK_ERR) */ } #endif /* !WINDLL */ #if (!defined(VMS) && !defined(CMS_MVS)) #if (!defined(OS2) || defined(TIMESTAMP)) #if (!defined(HAVE_MKTIME) || defined(WIN32)) /* also used in amiga/filedate.c and win32/win32.c */ ZCONST ush ydays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; #endif /*******************************/ /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */ /*******************************/ time_t dos_to_unix_time(dosdatetime) ulg dosdatetime; { time_t m_time; #ifdef HAVE_MKTIME ZCONST time_t now = time(NULL); struct tm *tm; # define YRBASE 1900 tm = localtime(&now); tm->tm_isdst = -1; /* let mktime determine if DST is in effect */ /* dissect date */ tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE); tm->tm_mon = ((int)(dosdatetime >> 21) & 0x0f) - 1; tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f); /* dissect time */ tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f; tm->tm_min = (int)((unsigned)dosdatetime >> 5) & 0x3f; tm->tm_sec = (int)((unsigned)dosdatetime << 1) & 0x3e; m_time = mktime(tm); NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */ TTrace((stderr, " final m_time = %lu\n", (ulg)m_time)); #else /* !HAVE_MKTIME */ int yr, mo, dy, hh, mm, ss; #ifdef TOPS20 # define YRBASE 1900 struct tmx *tmx; char temp[20]; #else /* !TOPS20 */ # define YRBASE 1970 int leap; unsigned days; struct tm *tm; #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM)) #ifdef WIN32 TIME_ZONE_INFORMATION tzinfo; DWORD res; #else /* ! WIN32 */ #ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */ #if (defined(BSD) || defined(MTS) || defined(__GO32__)) struct timeb tbp; #else /* !(BSD || MTS || __GO32__) */ #ifdef DECLARE_TIMEZONE extern time_t timezone; #endif #endif /* ?(BSD || MTS || __GO32__) */ #endif /* !BSD4_4 */ #endif /* ?WIN32 */ #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */ #endif /* ?TOPS20 */ /* dissect date */ yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE); mo = ((int)(dosdatetime >> 21) & 0x0f) - 1; dy = ((int)(dosdatetime >> 16) & 0x1f) - 1; /* dissect time */ hh = (int)((unsigned)dosdatetime >> 11) & 0x1f; mm = (int)((unsigned)dosdatetime >> 5) & 0x3f; ss = (int)((unsigned)dosdatetime & 0x1f) * 2; #ifdef TOPS20 tmx = (struct tmx *)malloc(sizeof(struct tmx)); sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss); time_parse(temp, tmx, (char *)0); m_time = time_make(tmx); free(tmx); #else /* !TOPS20 */ /*--------------------------------------------------------------------------- Calculate the number of seconds since the epoch, usually 1 January 1970. ---------------------------------------------------------------------------*/ /* leap = # of leap yrs from YRBASE up to but not including current year */ leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */ /* calculate days from BASE to this year and add expired days this year */ days = (yr * 365) + (leap - 492) + ydays[mo]; /* if year is a leap year and month is after February, add another day */ if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100)) ++days; /* OK through 2199 */ /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */ m_time = (time_t)((unsigned long)(days + dy) * 86400L + (unsigned long)hh * 3600L + (unsigned long)(mm * 60 + ss)); /* - 1; MS-DOS times always rounded up to nearest even second */ TTrace((stderr, "dos_to_unix_time:\n")); TTrace((stderr, " m_time before timezone = %lu\n", (ulg)m_time)); /*--------------------------------------------------------------------------- Adjust for local standard timezone offset. ---------------------------------------------------------------------------*/ #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM)) #ifdef WIN32 /* account for timezone differences */ res = GetTimeZoneInformation(&tzinfo); if (res != TIME_ZONE_ID_INVALID) { m_time += 60*(tzinfo.Bias); #else /* !WIN32 */ #if (defined(BSD) || defined(MTS) || defined(__GO32__)) #ifdef BSD4_4 if ( (dosdatetime >= DOSTIME_2038_01_18) && (m_time < (time_t)0x70000000L) ) m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ if ((tm = localtime(&m_time)) != (struct tm *)NULL) m_time -= tm->tm_gmtoff; /* sec. EAST of GMT: subtr. */ #else /* !(BSD4_4 */ ftime(&tbp); /* get `timezone' */ m_time += tbp.timezone * 60L; /* seconds WEST of GMT: add */ #endif /* ?(BSD4_4 || __EMX__) */ #else /* !(BSD || MTS || __GO32__) */ /* tzset was already called at start of process_zipfiles() */ /* tzset(); */ /* set `timezone' variable */ #ifndef __BEOS__ /* BeOS DR8 has no timezones... */ m_time += timezone; /* seconds WEST of GMT: add */ #endif #endif /* ?(BSD || MTS || __GO32__) */ #endif /* ?WIN32 */ TTrace((stderr, " m_time after timezone = %lu\n", (ulg)m_time)); /*--------------------------------------------------------------------------- Adjust for local daylight savings (summer) time. ---------------------------------------------------------------------------*/ #ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */ if ( (dosdatetime >= DOSTIME_2038_01_18) && (m_time < (time_t)0x70000000L) ) m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ TIMET_TO_NATIVE(m_time) /* NOP unless MSC 7.0 or Macintosh */ if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst) #ifdef WIN32 m_time += 60L * tzinfo.DaylightBias; /* adjust with DST bias */ else m_time += 60L * tzinfo.StandardBias; /* add StdBias (normally 0) */ #else m_time -= 60L * 60L; /* adjust for daylight savings time */ #endif NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */ TTrace((stderr, " m_time after DST = %lu\n", (ulg)m_time)); #endif /* !BSD4_4 */ #ifdef WIN32 } #endif #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */ #endif /* ?TOPS20 */ #endif /* ?HAVE_MKTIME */ if ( (dosdatetime >= DOSTIME_2038_01_18) && (m_time < (time_t)0x70000000L) ) m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ return m_time; } /* end function dos_to_unix_time() */ #endif /* !OS2 || TIMESTAMP */ #endif /* !VMS && !CMS_MVS */ #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS)) /******************************/ /* Function check_for_newer() */ /* used for overwriting/freshening/updating */ /******************************/ int check_for_newer(__G__ filename) /* return 1 if existing file is newer */ __GDEF /* or equal; 0 if older; -1 if doesn't */ char *filename; /* exist yet */ { time_t existing, archive; #ifdef USE_EF_UT_TIME iztimes z_utime; #endif #ifdef AOS_VS long dyy, dmm, ddd, dhh, dmin, dss; dyy = (lrec.last_mod_dos_datetime >> 25) + 1980; dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f; ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f; dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f; dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f; dss = (lrec.last_mod_dos_datetime & 0x1f) * 2; /* under AOS/VS, file times can only be set at creation time, * with the info in a special DG format. Make sure we can create * it here - we delete it later & re-create it, whether or not * it exists now. */ if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) | (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1)) return DOES_NOT_EXIST; #endif /* AOS_VS */ Trace((stderr, "check_for_newer: doing stat(%s)\n", FnFilter1(filename))); if (SSTAT(filename, &G.statbuf)) { Trace((stderr, "check_for_newer: stat(%s) returns %d: file does not exist\n", FnFilter1(filename), SSTAT(filename, &G.statbuf))); #ifdef SYMLINKS Trace((stderr, "check_for_newer: doing lstat(%s)\n", FnFilter1(filename))); /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ if (lstat(filename, &G.statbuf) == 0) { Trace((stderr, "check_for_newer: lstat(%s) returns 0: symlink does exist\n", FnFilter1(filename))); if (QCOND2 && !IS_OVERWRT_ALL) Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), FnFilter1(filename), " with no real file")); return EXISTS_AND_OLDER; /* symlink dates are meaningless */ } #endif /* SYMLINKS */ return DOES_NOT_EXIST; } Trace((stderr, "check_for_newer: stat(%s) returns 0: file exists\n", FnFilter1(filename))); #ifdef SYMLINKS /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) { Trace((stderr, "check_for_newer: %s is a symbolic link\n", FnFilter1(filename))); if (QCOND2 && !IS_OVERWRT_ALL) Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), FnFilter1(filename), "")); return EXISTS_AND_OLDER; /* symlink dates are meaningless */ } #endif /* SYMLINKS */ NATIVE_TO_TIMET(G.statbuf.st_mtime) /* NOP unless MSC 7.0 or Macintosh */ #ifdef USE_EF_UT_TIME /* The `Unix extra field mtime' should be used for comparison with the * time stamp of the existing file >>>ONLY<<< when the EF info is also * used to set the modification time of the extracted file. */ if (G.extra_field && #ifdef IZ_CHECK_TZ G.tz_is_valid && #endif (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME)) { TTrace((stderr, "check_for_newer: using Unix extra field mtime\n")); existing = G.statbuf.st_mtime; archive = z_utime.mtime; } else { /* round up existing filetime to nearest 2 seconds for comparison, * but saturate in case of arithmetic overflow */ existing = ((G.statbuf.st_mtime & 1) && (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); } #else /* !USE_EF_UT_TIME */ /* round up existing filetime to nearest 2 seconds for comparison, * but saturate in case of arithmetic overflow */ existing = ((G.statbuf.st_mtime & 1) && (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); #endif /* ?USE_EF_UT_TIME */ TTrace((stderr, "check_for_newer: existing %lu, archive %lu, e-a %ld\n", (ulg)existing, (ulg)archive, (long)(existing-archive))); return (existing >= archive); } /* end function check_for_newer() */ #endif /* !VMS && !OS2 && !CMS_MVS */ /************************/ /* Function do_string() */ /************************/ int do_string(__G__ length, option) /* return PK-type error code */ __GDEF unsigned int length; /* without prototype, ush converted to this */ int option; { unsigned comment_bytes_left; unsigned int block_len; int error=PK_OK; #ifdef AMIGA char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */ #endif /*--------------------------------------------------------------------------- This function processes arbitrary-length (well, usually) strings. Four major options are allowed: SKIP, wherein the string is skipped (pretty logical, eh?); DISPLAY, wherein the string is printed to standard output after undergoing any necessary or unnecessary character conversions; DS_FN, wherein the string is put into the filename[] array after under- going appropriate conversions (including case-conversion, if that is indicated: see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the `string' is assumed to be an extra field and is copied to the (freshly malloced) buffer G.extra_field. The third option should be OK since filename is dimensioned at 1025, but we check anyway. The string, by the way, is assumed to start at the current file-pointer position; its length is given by 'length'. So start off by checking the length of the string: if zero, we're already done. ---------------------------------------------------------------------------*/ if (!length) return PK_COOL; switch (option) { #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) /* * Special case: See if the comment begins with an autorun command line. * Save that and display (or skip) the remainder. */ case CHECK_AUTORUN: case CHECK_AUTORUN_Q: comment_bytes_left = length; if (length >= 10) { block_len = readbuf(__G__ (char *)G.outbuf, 10); if (block_len == 0) return PK_EOF; comment_bytes_left -= block_len; G.outbuf[block_len] = '\0'; if (!strcmp((char *)G.outbuf, "$AUTORUN$>")) { char *eol; length -= 10; block_len = readbuf(__G__ G.autorun_command, MIN(length, sizeof(G.autorun_command)-1)); if (block_len == 0) return PK_EOF; comment_bytes_left -= block_len; G.autorun_command[block_len] = '\0'; A_TO_N(G.autorun_command); eol = strchr(G.autorun_command, '\n'); if (!eol) eol = G.autorun_command + strlen(G.autorun_command) - 1; length -= eol + 1 - G.autorun_command; while (eol >= G.autorun_command && isspace(*eol)) *eol-- = '\0'; #if (defined(WIN32) && !defined(_WIN32_WCE)) /* Win9x console always uses OEM character coding, and WinNT console is set to OEM charset by default, too */ INTERN_TO_OEM(G.autorun_command, G.autorun_command); #endif /* (WIN32 && !_WIN32_WCE) */ } } if (option == CHECK_AUTORUN_Q) /* don't display the remainder */ length = 0; /* seek to beginning of remaining part of comment -- rewind if */ /* displaying entire comment, or skip to end if discarding it */ seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr - G.inbuf) + comment_bytes_left - length); if (!length) break; /* FALL THROUGH... */ #endif /* SFX && CHEAP_SFX_AUTORUN */ /* * First normal case: print string on standard output. First set loop * variables, then loop through the comment in chunks of OUTBUFSIZ bytes, * converting formats and printing as we go. The second half of the * loop conditional was added because the file might be truncated, in * which case comment_bytes_left will remain at some non-zero value for * all time. outbuf and slide are used as scratch buffers because they * are available (we should be either before or in between any file pro- * cessing). */ case DISPLAY: case DISPL_8: comment_bytes_left = length; block_len = OUTBUFSIZ; /* for the while statement, first time */ while (comment_bytes_left > 0 && block_len > 0) { register uch *p = G.outbuf; register uch *q = G.outbuf; if ((block_len = readbuf(__G__ (char *)G.outbuf, MIN((unsigned)OUTBUFSIZ, comment_bytes_left))) == 0) return PK_EOF; comment_bytes_left -= block_len; /* this is why we allocated an extra byte for outbuf: terminate * with zero (ASCIIZ) */ G.outbuf[block_len] = '\0'; /* remove all ASCII carriage returns from comment before printing * (since used before A_TO_N(), check for CR instead of '\r') */ while (*p) { while (*p == CR) ++p; *q++ = *p++; } /* could check whether (p - outbuf) == block_len here */ *q = '\0'; if (option == DISPL_8) { /* translate the text coded in the entry's host-dependent "extended ASCII" charset into the compiler's (system's) internal text code page */ Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum, G.pInfo->hostver, G.pInfo->HasUxAtt, FALSE); #ifdef WINDLL /* translate to ANSI (RTL internal codepage may be OEM) */ INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf); #else /* !WINDLL */ #if (defined(WIN32) && !defined(_WIN32_WCE)) /* Win9x console always uses OEM character coding, and WinNT console is set to OEM charset by default, too */ INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf); #endif /* (WIN32 && !_WIN32_WCE) */ #endif /* ?WINDLL */ } else { A_TO_N(G.outbuf); /* translate string to native */ } #ifdef WINDLL /* ran out of local mem -- had to cheat */ win_fprintf((zvoid *)&G, stdout, (extent)(q-G.outbuf), (char *)G.outbuf); win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n"); #else /* !WINDLL */ #ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */ (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0); #else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */ p = G.outbuf - 1; q = slide; while (*++p) { int pause = FALSE; if (*p == 0x1B) { /* ASCII escape char */ *q++ = '^'; *q++ = '['; } else if (*p == 0x13) { /* ASCII ^S (pause) */ pause = TRUE; if (p[1] == LF) /* ASCII LF */ *q++ = *++p; else if (p[1] == CR && p[2] == LF) { /* ASCII CR LF */ *q++ = *++p; *q++ = *++p; } } else *q++ = *p; if ((unsigned)(q-slide) > WSIZE-3 || pause) { /* flush */ (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); q = slide; if (pause && G.extract_flag) /* don't pause for list/test */ (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0); } } (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); #endif /* ?NOANSIFILT */ #endif /* ?WINDLL */ } /* add '\n' if not at start of line */ (*G.message)((zvoid *)&G, slide, 0L, 0x40); break; /* * Second case: read string into filename[] array. The filename should * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check, * just to be sure. */ case DS_FN: case DS_FN_L: #ifdef UNICODE_SUPPORT /* get the whole filename as need it for Unicode checksum */ if (G.fnfull_bufsize <= length) { extent fnbufsiz = FILNAMSIZ; if (fnbufsiz <= length) fnbufsiz = length + 1; if (G.filename_full) free(G.filename_full); G.filename_full = malloc(fnbufsiz); if (G.filename_full == NULL) return PK_MEM; G.fnfull_bufsize = fnbufsiz; } if (readbuf(__G__ G.filename_full, length) == 0) return PK_EOF; G.filename_full[length] = '\0'; /* terminate w/zero: ASCIIZ */ /* if needed, chop off end so standard filename is a valid length */ if (length >= FILNAMSIZ) { Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameTooLongTrunc))); error = PK_WARN; length = FILNAMSIZ - 1; } /* no excess size */ block_len = 0; strncpy(G.filename, G.filename_full, length); G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */ #else /* !UNICODE_SUPPORT */ if (length >= FILNAMSIZ) { Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameTooLongTrunc))); error = PK_WARN; /* remember excess length in block_len */ block_len = length - (FILNAMSIZ - 1); length = FILNAMSIZ - 1; } else /* no excess size */ block_len = 0; if (readbuf(__G__ G.filename, length) == 0) return PK_EOF; G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */ #endif /* ?UNICODE_SUPPORT */ /* translate the Zip entry filename coded in host-dependent "extended ASCII" into the compiler's (system's) internal text code page */ Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum, G.pInfo->hostver, G.pInfo->HasUxAtt, (option == DS_FN_L)); if (G.pInfo->lcflag) /* replace with lowercase filename */ STRLOWER(G.filename, G.filename); if (G.pInfo->vollabel && length > 8 && G.filename[8] == '.') { char *p = G.filename+8; while (*p++) p[-1] = *p; /* disk label, and 8th char is dot: remove dot */ } if (!block_len) /* no overflow, we're done here */ break; /* * We truncated the filename, so print what's left and then fall * through to the SKIP routine. */ Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename))); length = block_len; /* SKIP the excess bytes... */ /* FALL THROUGH... */ /* * Third case: skip string, adjusting readbuf's internal variables * as necessary (and possibly skipping to and reading a new block of * data). */ case SKIP: /* cur_zipfile_bufstart already takes account of extra_bytes, so don't * correct for it twice: */ seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr-G.inbuf) + length); break; /* * Fourth case: assume we're at the start of an "extra field"; malloc * storage for it and read data into the allocated space. */ case EXTRA_FIELD: if (G.extra_field != (uch *)NULL) free(G.extra_field); if ((G.extra_field = (uch *)malloc(length)) == (uch *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong), length)); /* cur_zipfile_bufstart already takes account of extra_bytes, * so don't correct for it twice: */ seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr-G.inbuf) + length); } else { if (readbuf(__G__ (char *)G.extra_field, length) == 0) return PK_EOF; /* Looks like here is where extra fields are read */ getZip64Data(__G__ G.extra_field, length); #ifdef UNICODE_SUPPORT G.unipath_filename = NULL; if (G.UzO.U_flag < 2) { /* check if GPB11 (General Purpuse Bit 11) is set indicating the standard path and comment are UTF-8 */ if (G.pInfo->GPFIsUTF8) { /* if GPB11 set then filename_full is untruncated UTF-8 */ G.unipath_filename = G.filename_full; } else { /* Get the Unicode fields if exist */ getUnicodeData(__G__ G.extra_field, length); if (G.unipath_filename && strlen(G.unipath_filename) == 0) { /* the standard filename field is UTF-8 */ free(G.unipath_filename); G.unipath_filename = G.filename_full; } } if (G.unipath_filename) { # ifdef UTF8_MAYBE_NATIVE if (G.native_is_utf8 # ifdef UNICODE_WCHAR && (!G.unicode_escape_all) # endif ) { strncpy(G.filename, G.unipath_filename, FILNAMSIZ - 1); /* make sure filename is short enough */ if (strlen(G.unipath_filename) >= FILNAMSIZ) { G.filename[FILNAMSIZ - 1] = '\0'; Info(slide, 0x401, ((char *)slide, LoadFarString(UFilenameTooLongTrunc))); error = PK_WARN; } } # ifdef UNICODE_WCHAR else # endif # endif /* UTF8_MAYBE_NATIVE */ # ifdef UNICODE_WCHAR { char *fn; /* convert UTF-8 to local character set */ fn = utf8_to_local_string(G.unipath_filename, G.unicode_escape_all); /* make sure filename is short enough */ if (strlen(fn) >= FILNAMSIZ) { fn[FILNAMSIZ - 1] = '\0'; Info(slide, 0x401, ((char *)slide, LoadFarString(UFilenameTooLongTrunc))); error = PK_WARN; } /* replace filename with converted UTF-8 */ strcpy(G.filename, fn); free(fn); } # endif /* UNICODE_WCHAR */ if (G.unipath_filename != G.filename_full) free(G.unipath_filename); G.unipath_filename = NULL; } } #endif /* UNICODE_SUPPORT */ } break; #ifdef AMIGA /* * Fifth case, for the Amiga only: take the comment that would ordinarily * be skipped over, and turn it into a 79 character string that will be * attached to the file as a "filenote" after it is extracted. */ case FILENOTE: if ((block_len = readbuf(__G__ tmp_fnote, (unsigned) MIN(length, 2 * AMIGA_FILENOTELEN - 1))) == 0) return PK_EOF; if ((length -= block_len) > 0) /* treat remainder as in case SKIP: */ seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr - G.inbuf) + length); /* convert multi-line text into single line with no ctl-chars: */ tmp_fnote[block_len] = '\0'; while ((short int) --block_len >= 0) if ((unsigned) tmp_fnote[block_len] < ' ') if (tmp_fnote[block_len+1] == ' ') /* no excess */ strcpy(tmp_fnote+block_len, tmp_fnote+block_len+1); else tmp_fnote[block_len] = ' '; tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0'; if (G.filenotes[G.filenote_slot]) free(G.filenotes[G.filenote_slot]); /* should not happen */ G.filenotes[G.filenote_slot] = NULL; if (tmp_fnote[0]) { if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1))) return PK_MEM; strcpy(G.filenotes[G.filenote_slot], tmp_fnote); } break; #endif /* AMIGA */ } /* end switch (option) */ return error; } /* end function do_string() */ /***********************/ /* Function makeword() */ /***********************/ ush makeword(b) ZCONST uch *b; { /* * Convert Intel style 'short' integer to non-Intel non-16-bit * host format. This routine also takes care of byte-ordering. */ return (ush)((b[1] << 8) | b[0]); } /***********************/ /* Function makelong() */ /***********************/ ulg makelong(sig) ZCONST uch *sig; { /* * Convert intel style 'long' variable to non-Intel non-16-bit * host format. This routine also takes care of byte-ordering. */ return (((ulg)sig[3]) << 24) + (((ulg)sig[2]) << 16) + (ulg)((((unsigned)sig[1]) << 8) + ((unsigned)sig[0])); } /************************/ /* Function makeint64() */ /************************/ zusz_t makeint64(sig) ZCONST uch *sig; { #ifdef LARGE_FILE_SUPPORT /* * Convert intel style 'int64' variable to non-Intel non-16-bit * host format. This routine also takes care of byte-ordering. */ return (((zusz_t)sig[7]) << 56) + (((zusz_t)sig[6]) << 48) + (((zusz_t)sig[4]) << 32) + (zusz_t)((((ulg)sig[3]) << 24) + (((ulg)sig[2]) << 16) + (((unsigned)sig[1]) << 8) + (sig[0])); #else /* !LARGE_FILE_SUPPORT */ if ((sig[7] | sig[6] | sig[5] | sig[4]) != 0) return (zusz_t)0xffffffffL; else return (zusz_t)((((ulg)sig[3]) << 24) + (((ulg)sig[2]) << 16) + (((unsigned)sig[1]) << 8) + (sig[0])); #endif /* ?LARGE_FILE_SUPPORT */ } /*********************/ /* Function fzofft() */ /*********************/ /* Format a zoff_t value in a cylindrical buffer set. */ char *fzofft(__G__ val, pre, post) __GDEF zoff_t val; ZCONST char *pre; ZCONST char *post; { /* Storage cylinder. (now in globals.h) */ /*static char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN];*/ /*static int fzofft_index = 0;*/ /* Temporary format string storage. */ char fmt[16]; /* Assemble the format string. */ fmt[0] = '%'; fmt[1] = '\0'; /* Start after initial "%". */ if (pre == FZOFFT_HEX_WID) /* Special hex width. */ { strcat(fmt, FZOFFT_HEX_WID_VALUE); } else if (pre == FZOFFT_HEX_DOT_WID) /* Special hex ".width". */ { strcat(fmt, "."); strcat(fmt, FZOFFT_HEX_WID_VALUE); } else if (pre != NULL) /* Caller's prefix (width). */ { strcat(fmt, pre); } strcat(fmt, FZOFFT_FMT); /* Long or long-long or whatever. */ if (post == NULL) strcat(fmt, "d"); /* Default radix = decimal. */ else strcat(fmt, post); /* Caller's radix. */ /* Advance the cylinder. */ G.fzofft_index = (G.fzofft_index + 1) % FZOFFT_NUM; /* Write into the current chamber. */ sprintf(G.fzofft_buf[G.fzofft_index], fmt, val); /* Return a pointer to this chamber. */ return G.fzofft_buf[G.fzofft_index]; } #if CRYPT #ifdef NEED_STR2ISO /**********************/ /* Function str2iso() */ /**********************/ char *str2iso(dst, src) char *dst; /* destination buffer */ register ZCONST char *src; /* source string */ { #ifdef INTERN_TO_ISO INTERN_TO_ISO(src, dst); #else register uch c; register char *dstp = dst; do { c = (uch)foreign(*src++); *dstp++ = (char)ASCII2ISO(c); } while (c != '\0'); #endif return dst; } #endif /* NEED_STR2ISO */ #ifdef NEED_STR2OEM /**********************/ /* Function str2oem() */ /**********************/ char *str2oem(dst, src) char *dst; /* destination buffer */ register ZCONST char *src; /* source string */ { #ifdef INTERN_TO_OEM INTERN_TO_OEM(src, dst); #else register uch c; register char *dstp = dst; do { c = (uch)foreign(*src++); *dstp++ = (char)ASCII2OEM(c); } while (c != '\0'); #endif return dst; } #endif /* NEED_STR2OEM */ #endif /* CRYPT */ #ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */ /* bzero/bcmp/bcopy */ /* (no known systems as of 960211) */ /*********************/ /* Function memset() */ /*********************/ zvoid *memset(buf, init, len) register zvoid *buf; /* buffer location */ register int init; /* initializer character */ register unsigned int len; /* length of the buffer */ { zvoid *start; start = buf; while (len--) *((char *)buf++) = (char)init; return start; } /*********************/ /* Function memcmp() */ /*********************/ int memcmp(b1, b2, len) register ZCONST zvoid *b1; register ZCONST zvoid *b2; register unsigned int len; { register int c; if (len > 0) do { if ((c = (int)(*((ZCONST unsigned char *)b1)++) - (int)(*((ZCONST unsigned char *)b2)++)) != 0) return c; } while (--len > 0) return 0; } /*********************/ /* Function memcpy() */ /*********************/ zvoid *memcpy(dst, src, len) register zvoid *dst; register ZCONST zvoid *src; register unsigned int len; { zvoid *start; start = dst; while (len-- > 0) *((char *)dst)++ = *((ZCONST char *)src)++; return start; } #endif /* ZMEM */ #ifdef NO_STRNICMP /************************/ /* Function zstrnicmp() */ /************************/ int zstrnicmp(s1, s2, n) register ZCONST char *s1, *s2; register unsigned n; { for (; n > 0; --n, ++s1, ++s2) { if (ToLower(*s1) != ToLower(*s2)) /* test includes early termination of one string */ return ((uch)ToLower(*s1) < (uch)ToLower(*s2))? -1 : 1; if (*s1 == '\0') /* both strings terminate early */ return 0; } return 0; } #endif /* NO_STRNICMP */ #ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */ # undef stat /********************/ /* Function zstat() */ /********************/ int zstat(p, s) ZCONST char *p; struct stat *s; { return (stat((char *)p,s) >= 0? 0 : (-1)); } #endif /* REGULUS */ #ifdef _MBCS /* DBCS support for Info-ZIP's zip (mainly for japanese (-: ) * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp) * This code is public domain! Date: 1998/12/20 */ /************************/ /* Function plastchar() */ /************************/ char *plastchar(ptr, len) ZCONST char *ptr; extent len; { unsigned clen; ZCONST char *oldptr = ptr; while(*ptr != '\0' && len > 0){ oldptr = ptr; clen = CLEN(ptr); ptr += clen; len -= clen; } return (char *)oldptr; } #ifdef NEED_UZMBCLEN /***********************/ /* Function uzmbclen() */ /***********************/ extent uzmbclen(ptr) ZCONST unsigned char *ptr; { int mbl; mbl = mblen((ZCONST char *)ptr, MB_CUR_MAX); /* For use in code scanning through MBCS strings, we need a strictly positive "MB char bytes count". For our scanning purpose, it is not not relevant whether the MB character is valid or not. And, the NUL char '\0' has a byte count of 1, but mblen() returns 0. So, we make sure that the uzmbclen() return value is not less than 1. */ return (extent)(mbl > 0 ? mbl : 1); } #endif /* NEED_UZMBCLEN */ #ifdef NEED_UZMBSCHR /***********************/ /* Function uzmbschr() */ /***********************/ unsigned char *uzmbschr(str, c) ZCONST unsigned char *str; unsigned int c; { while(*str != '\0'){ if (*str == c) {return (unsigned char *)str;} INCSTR(str); } return NULL; } #endif /* NEED_UZMBSCHR */ #ifdef NEED_UZMBSRCHR /************************/ /* Function uzmbsrchr() */ /************************/ unsigned char *uzmbsrchr(str, c) ZCONST unsigned char *str; unsigned int c; { unsigned char *match = NULL; while(*str != '\0'){ if (*str == c) {match = (unsigned char *)str;} INCSTR(str); } return match; } #endif /* NEED_UZMBSRCHR */ #endif /* _MBCS */ #ifdef SMALL_MEM /*******************************/ /* Function fLoadFarString() */ /* (and friends...) */ /*******************************/ char *fLoadFarString(__GPRO__ const char Far *sz) { (void)zfstrcpy(G.rgchBigBuffer, sz); return G.rgchBigBuffer; } char *fLoadFarStringSmall(__GPRO__ const char Far *sz) { (void)zfstrcpy(G.rgchSmallBuffer, sz); return G.rgchSmallBuffer; } char *fLoadFarStringSmall2(__GPRO__ const char Far *sz) { (void)zfstrcpy(G.rgchSmallBuffer2, sz); return G.rgchSmallBuffer2; } #if (!defined(_MSC_VER) || (_MSC_VER < 600)) /*************************/ /* Function zfstrcpy() */ /* portable clone of _fstrcpy() */ /*************************/ char Far * Far zfstrcpy(char Far *s1, const char Far *s2) { char Far *p = s1; while ((*s1++ = *s2++) != '\0'); return p; } #if (!(defined(SFX) || defined(FUNZIP))) /*************************/ /* Function zfstrcmp() */ /* portable clone of _fstrcmp() */ /*************************/ int Far zfstrcmp(const char Far *s1, const char Far *s2) { int ret; while ((ret = (int)(uch)*s1 - (int)(uch)*s2) == 0 && *s2 != '\0') { ++s2; ++s1; } return ret; } #endif /* !(SFX || FUNZIP) */ #endif /* !_MSC_VER || (_MSC_VER < 600) */ #endif /* SMALL_MEM */ Carla-2.1/data/windows/unzipfx-carla-control/globals.c000066400000000000000000000145331364475620200230500ustar00rootroot00000000000000/* Copyright (c) 1990-2007 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2003-May-08 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- globals.c Routines to allocate and initialize globals, with or without threads. Contents: registerGlobalPointer() deregisterGlobalPointer() getGlobalPointer() globalsCtor() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #ifndef FUNZIP /* initialization of sigs is completed at runtime so unzip(sfx) executable * won't look like a zipfile */ char central_hdr_sig[4] = {0, 0, 0x01, 0x02}; char local_hdr_sig[4] = {0, 0, 0x03, 0x04}; char end_central_sig[4] = {0, 0, 0x05, 0x06}; char end_central64_sig[4] = {0, 0, 0x06, 0x06}; char end_centloc64_sig[4] = {0, 0, 0x06, 0x07}; /* extern char extd_local_sig[4] = {0, 0, 0x07, 0x08}; NOT USED YET */ ZCONST char *fnames[2] = {"*", NULL}; /* default filenames vector */ #endif #ifndef REENTRANT Uz_Globs G; #else /* REENTRANT */ # ifndef USETHREADID Uz_Globs *GG; # else /* USETHREADID */ # define THREADID_ENTRIES 0x40 int lastScan; Uz_Globs *threadPtrTable[THREADID_ENTRIES]; ulg threadIdTable [THREADID_ENTRIES] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* Make sure there are */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* THREADID_ENTRIES 0s */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; static ZCONST char Far TooManyThreads[] = "error: more than %d simultaneous threads.\n\ Some threads are probably not calling DESTROYTHREAD()\n"; static ZCONST char Far EntryNotFound[] = "error: couldn't find global pointer in table.\n\ Maybe somebody accidentally called DESTROYTHREAD() twice.\n"; static ZCONST char Far GlobalPointerMismatch[] = "error: global pointer in table does not match pointer passed as\ parameter\n"; static void registerGlobalPointer OF((__GPRO)); static void registerGlobalPointer(__G) __GDEF { int scan=0; ulg tid = GetThreadId(); while (threadIdTable[scan] && scan < THREADID_ENTRIES) scan++; if (scan == THREADID_ENTRIES) { ZCONST char *tooMany = LoadFarString(TooManyThreads); Info(slide, 0x421, ((char *)slide, tooMany, THREADID_ENTRIES)); free(pG); EXIT(PK_MEM); /* essentially memory error before we've started */ } threadIdTable [scan] = tid; threadPtrTable[scan] = pG; lastScan = scan; } void deregisterGlobalPointer(__G) __GDEF { int scan=0; ulg tid = GetThreadId(); while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES) scan++; /*--------------------------------------------------------------------------- There are two things we can do if we can't find the entry: ignore it or scream. The most likely reason for it not to be here is the user calling this routine twice. Since this could cause BIG problems if any globals are accessed after the first call, we'd better scream. ---------------------------------------------------------------------------*/ if (scan == THREADID_ENTRIES || threadPtrTable[scan] != pG) { ZCONST char *noEntry; if (scan == THREADID_ENTRIES) noEntry = LoadFarString(EntryNotFound); else noEntry = LoadFarString(GlobalPointerMismatch); Info(slide, 0x421, ((char *)slide, noEntry)); EXIT(PK_WARN); /* programming error, but after we're all done */ } threadIdTable [scan] = 0; lastScan = scan; free(threadPtrTable[scan]); } Uz_Globs *getGlobalPointer() { int scan=0; ulg tid = GetThreadId(); while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES) scan++; /*--------------------------------------------------------------------------- There are two things we can do if we can't find the entry: ignore it or scream. The most likely reason for it not to be here is the user calling this routine twice. Since this could cause BIG problems if any globals are accessed after the first call, we'd better scream. ---------------------------------------------------------------------------*/ if (scan == THREADID_ENTRIES) { ZCONST char *noEntry = LoadFarString(EntryNotFound); fprintf(stderr, noEntry); /* can't use Info w/o a global pointer */ EXIT(PK_ERR); /* programming error while still working */ } return threadPtrTable[scan]; } # endif /* ?USETHREADID */ #endif /* ?REENTRANT */ Uz_Globs *globalsCtor() { #ifdef REENTRANT Uz_Globs *pG = (Uz_Globs *)malloc(sizeof(Uz_Globs)); if (!pG) return (Uz_Globs *)NULL; #endif /* REENTRANT */ /* for REENTRANT version, G is defined as (*pG) */ memzero(&G, sizeof(Uz_Globs)); #ifndef FUNZIP #ifdef CMS_MVS uO.aflag=1; uO.C_flag=1; #endif #ifdef TANDEM uO.aflag=1; /* default to '-a' auto create Text Files as type 101 */ #endif #ifdef VMS # if (!defined(NO_TIMESTAMPS)) uO.D_flag=1; /* default to '-D', no restoration of dir timestamps */ # endif #endif uO.lflag=(-1); G.wildzipfn = ""; G.pfnames = (char **)fnames; G.pxnames = (char **)&fnames[1]; G.pInfo = G.info; G.sol = TRUE; /* at start of line */ G.message = UzpMessagePrnt; G.input = UzpInput; /* not used by anyone at the moment... */ #if defined(WINDLL) || defined(MACOS) G.mpause = NULL; /* has scrollbars: no need for pausing */ #else G.mpause = UzpMorePause; #endif G.decr_passwd = UzpPassword; #endif /* !FUNZIP */ #if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) #if (!defined(MACOS) && !defined(ATARI) && !defined(VMS)) G.echofd = -1; #endif /* !(MACOS || ATARI || VMS) */ #endif /* !(DOS_FLX_H68_NLM_OS2_W32 || AMIGA || RISCOS) */ #ifdef SYSTEM_SPECIFIC_CTOR SYSTEM_SPECIFIC_CTOR(__G); #endif #ifdef REENTRANT #ifdef USETHREADID registerGlobalPointer(__G); #else GG = &G; #endif /* ?USETHREADID */ #endif /* REENTRANT */ return &G; } Carla-2.1/data/windows/unzipfx-carla-control/globals.h000066400000000000000000000410711364475620200230520ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- globals.h There is usually no need to include this file since unzip.h includes it. This header file is used by all of the UnZip source files. It contains a struct definition that is used to "house" all of the global variables. This is done to allow for multithreaded environments (OS/2, NT, Win95, Unix) to call UnZip through an API without a semaphore. REENTRANT should be defined for all platforms that require this. GLOBAL CONSTRUCTOR AND DESTRUCTOR (API WRITERS READ THIS!!!) ------------------------------------------------------------ No, it's not C++, but it's as close as we can get with K&R. The main() of each process that uses these globals must include the CONSTRUCTGLOBALS; statement. This will malloc enough memory for the structure and initialize any variables that require it. This must also be done by any API function that jumps into the middle of the code. The DESTROYGLOBALS(); statement should be inserted before EVERY "EXIT(n)". Naturally, it also needs to be put before any API returns as well. In fact, it's much more important in API functions since the process will NOT end, and therefore the memory WON'T automatically be freed by the operating system. USING VARIABLES FROM THE STRUCTURE ---------------------------------- All global variables must now be prefixed with `G.' which is either a global struct (in which case it should be the only global variable) or a macro for the value of a local pointer variable that is passed from function to function. Yes, this is a pain. But it's the only way to allow full reentrancy. ADDING VARIABLES TO THE STRUCTURE --------------------------------- If you make the inclusion of any variables conditional, be sure to only check macros that are GUARANTEED to be included in every module. For instance, newzip and pwdarg are needed only if CRYPT is TRUE, but this is defined after unzip.h has been read. If you are not careful, some modules will expect your variable to be part of this struct while others won't. This will cause BIG problems. (Inexplicable crashes at strange times, car fires, etc.) When in doubt, always include it! Note also that UnZipSFX needs a few variables that UnZip doesn't. However, it also includes some object files from UnZip. If we were to conditionally include the extra variables that UnZipSFX needs, the object files from UnZip would not mesh with the UnZipSFX object files. Result: we just include the UnZipSFX variables every time. (It's only an extra 4 bytes so who cares!) ADDING FUNCTIONS ---------------- To support this new global struct, all functions must now conditionally pass the globals pointer (pG) to each other. This is supported by 5 macros: __GPRO, __GPRO__, __G, __G__ and __GDEF. A function that needs no other parameters would look like this: int extract_or_test_files(__G) __GDEF { ... stuff ... } A function with other parameters would look like: int memextract(__G__ tgt, tgtsize, src, srcsize) __GDEF uch *tgt, *src; ulg tgtsize, srcsize; { ... stuff ... } In the Function Prototypes section of unzpriv.h, you should use __GPRO and __GPRO__ instead: int uz_opts OF((__GPRO__ int *pargc, char ***pargv)); int process_zipfiles OF((__GPRO)); Note that there is NO comma after __G__ or __GPRO__ and no semi-colon after __GDEF. I wish there was another way but I don't think there is. TESTING THE CODE ----------------- Whether your platform requires reentrancy or not, you should always try building with REENTRANT defined if any functions have been added. It is pretty easy to forget a __G__ or a __GDEF and this mistake will only show up if REENTRANT is defined. All platforms should run with REENTRANT defined. Platforms that can't take advantage of it will just be paying a performance penalty needlessly. SIGNAL MADNESS -------------- This whole pointer passing scheme falls apart when it comes to SIGNALs. I handle this situation 2 ways right now. If you define USETHREADID, UnZip will include a 64-entry table. Each entry can hold a global pointer and thread ID for one thread. This should allow up to 64 threads to access UnZip simultaneously. Calling DESTROYGLOBALS() will free the global struct and zero the table entry. If somebody forgets to call DESTROYGLOBALS(), this table will eventually fill up and UnZip will exit with an error message. A good way to test your code to make sure you didn't forget a DESTROYGLOBALS() is to change THREADID_ENTRIES to 3 or 4 in globals.c, making the table real small. Then make a small test program that calls your API a dozen times. Those platforms that don't have threads still need to be able to compile with REENTRANT defined to test and see if new code is correctly written to work either way. For these platforms, I simply keep a global pointer called GG that points to the Globals structure. Good enough for testing. I believe that NT has thread level storage. This could probably be used to store a global pointer for the sake of the signal handler more cleanly than my table approach. ---------------------------------------------------------------------------*/ #ifndef __globals_h #define __globals_h #ifdef USE_ZLIB # include "zlib.h" # ifdef zlib_version /* This name is used internally in unzip */ # undef zlib_version /* and must not be defined as a macro. */ # endif #endif #ifdef USE_BZIP2 # include "bzlib.h" #endif /*************/ /* Globals */ /*************/ typedef struct Globals { #ifdef DLL zvoid *callerglobs; /* pointer to structure of pass-through global vars */ #endif /* command options of general use */ UzpOpts UzO; /* command options of general use */ #ifndef FUNZIP /* command options specific to the high level command line interface */ #ifdef MORE int M_flag; /* -M: built-in "more" function */ #endif /* internal flags and general globals */ #ifdef MORE int height; /* check for SIGWINCH, etc., eventually... */ int lines; /* count of lines displayed on current screen */ # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) int width; int chars; /* count of screen characters in current line */ # endif #endif /* MORE */ #if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) int tz_is_valid; /* indicates that timezone info can be used */ #endif int noargs; /* did true command line have *any* arguments? */ unsigned filespecs; /* number of real file specifications to be matched */ unsigned xfilespecs; /* number of excluded filespecs to be matched */ int process_all_files; int overwrite_mode; /* 0 - query, 1 - always, 2 - never */ int create_dirs; /* used by main(), mapname(), checkdir() */ int extract_flag; int newzip; /* reset in extract.c; used in crypt.c */ zoff_t real_ecrec_offset; zoff_t expect_ecrec_offset; zoff_t csize; /* used by decompr. (NEXTBYTE): must be signed */ zoff_t used_csize; /* used by extract_or_test_member(), explode() */ #ifdef DLL int fValidate; /* true if only validating an archive */ int filenotfound; int redirect_data; /* redirect data to memory buffer */ int redirect_text; /* redirect text output to buffer */ # ifndef NO_SLIDE_REDIR int redirect_slide; /* redirect decompression area to mem buffer */ # if (defined(USE_DEFLATE64) && defined(INT_16BIT)) ulg _wsize; /* size of sliding window exceeds "unsigned" range */ # else unsigned _wsize; /* sliding window size can be hold in unsigned */ # endif # endif ulg redirect_size; /* size of redirected output buffer */ uch *redirect_buffer; /* pointer to head of allocated buffer */ uch *redirect_pointer; /* pointer past end of written data */ # ifndef NO_SLIDE_REDIR uch *redirect_sldptr; /* head of decompression slide buffer */ # endif # ifdef OS2DLL cbList(processExternally); /* call-back list */ # endif #endif /* DLL */ char **pfnames; char **pxnames; char sig[4]; char answerbuf[10]; min_info info[DIR_BLKSIZ]; min_info *pInfo; #endif /* !FUNZIP */ union work area; /* see unzpriv.h for definition of work */ #if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) ZCONST ulg near *crc_32_tab; #else ZCONST ulg Far *crc_32_tab; #endif ulg crc32val; /* CRC shift reg. (was static in funzip) */ #ifdef FUNZIP FILE *in; /* file descriptor of compressed stream */ #endif uch *inbuf; /* input buffer (any size is OK) */ uch *inptr; /* pointer into input buffer */ int incnt; #ifndef FUNZIP ulg bitbuf; int bits_left; /* unreduce and unshrink only */ int zipeof; char *argv0; /* used for NT and EXE_EXTENSION */ char *wildzipfn; char *zipfn; /* GRR: WINDLL: must nuke any malloc'd zipfn... */ #ifdef USE_STRM_INPUT FILE *zipfd; /* zipfile file descriptor */ #else int zipfd; /* zipfile file handle */ #endif zoff_t ziplen; zoff_t cur_zipfile_bufstart; /* extract_or_test, readbuf, ReadByte */ zoff_t extra_bytes; /* used in unzip.c, misc.c */ uch *extra_field; /* Unix, VMS, Mac, OS/2, Acorn, ... */ uch *hold; local_file_hdr lrec; /* used in unzip.c, extract.c */ cdir_file_hdr crec; /* used in unzip.c, extract.c, misc.c */ ecdir_rec ecrec; /* used in unzip.c, extract.c */ z_stat statbuf; /* used by main, mapname, check_for_newer */ int mem_mode; uch *outbufptr; /* extract.c static */ ulg outsize; /* extract.c static */ int reported_backslash; /* extract.c static */ int disk_full; int newfile; int didCRlast; /* fileio static */ ulg numlines; /* fileio static: number of lines printed */ int sol; /* fileio static: at start of line */ int no_ecrec; /* process static */ #ifdef SYMLINKS int symlnk; slinkentry *slink_head; /* pointer to head of symlinks list */ slinkentry *slink_last; /* pointer to last entry in symlinks list */ #endif #ifdef NOVELL_BUG_FAILSAFE int dne; /* true if stat() says file doesn't exist */ #endif FILE *outfile; uch *outbuf; uch *realbuf; #ifndef VMS /* if SMALL_MEM, outbuf2 is initialized in */ uch *outbuf2; /* process_zipfiles() (never changes); */ #endif /* else malloc'd ONLY if unshrink and -a */ #endif /* !FUNZIP */ uch *outptr; ulg outcnt; /* number of chars stored in outbuf */ #ifndef FUNZIP char filename[FILNAMSIZ]; /* also used by NT for temporary SFX path */ #ifdef UNICODE_SUPPORT char *filename_full; /* the full path so Unicode checks work */ extent fnfull_bufsize; /* size of allocated filename buffer */ int unicode_escape_all; int unicode_mismatch; #ifdef UTF8_MAYBE_NATIVE int native_is_utf8; /* bool, TRUE => native charset == UTF-8 */ #endif int unipath_version; /* version of Unicode field */ ulg unipath_checksum; /* Unicode field checksum */ char *unipath_filename; /* UTF-8 path */ #endif /* UNICODE_SUPPORT */ #ifdef CMS_MVS char *tempfn; /* temp file used; erase on close */ #endif char *key; /* crypt static: decryption password or NULL */ int nopwd; /* crypt static */ #endif /* !FUNZIP */ z_uint4 keys[3]; /* crypt static: keys defining pseudo-random sequence */ #if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) #if (!defined(MACOS) && !defined(ATARI) && !defined(VMS)) int echofd; /* ttyio static: file descriptor whose echo is off */ #endif /* !(MACOS || ATARI || VMS) */ #endif /* !(DOS_FLX_H68_NLM_OS2_W32 || AMIGA || RISCOS) */ unsigned hufts; /* track memory usage */ #ifdef USE_ZLIB int inflInit; /* inflate static: zlib inflate() initialized */ z_stream dstrm; /* inflate global: decompression stream */ #else struct huft *fixed_tl; /* inflate static */ struct huft *fixed_td; /* inflate static */ unsigned fixed_bl, fixed_bd; /* inflate static */ #ifdef USE_DEFLATE64 struct huft *fixed_tl64; /* inflate static */ struct huft *fixed_td64; /* inflate static */ unsigned fixed_bl64, fixed_bd64; /* inflate static */ struct huft *fixed_tl32; /* inflate static */ struct huft *fixed_td32; /* inflate static */ unsigned fixed_bl32, fixed_bd32; /* inflate static */ ZCONST ush *cplens; /* inflate static */ ZCONST uch *cplext; /* inflate static */ ZCONST uch *cpdext; /* inflate static */ #endif unsigned wp; /* inflate static: current position in slide */ ulg bb; /* inflate static: bit buffer */ unsigned bk; /* inflate static: bits count in bit buffer */ #endif /* ?USE_ZLIB */ #ifndef FUNZIP /* cylindric buffer space for formatting zoff_t values (fileio static) */ char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN]; int fzofft_index; #ifdef SMALL_MEM char rgchBigBuffer[512]; char rgchSmallBuffer[96]; char rgchSmallBuffer2[160]; /* boosted to 160 for local3[] in unzip.c */ #endif MsgFn *message; InputFn *input; PauseFn *mpause; PasswdFn *decr_passwd; StatCBFn *statreportcb; #ifdef WINDLL LPUSERFUNCTIONS lpUserFunctions; #endif int incnt_leftover; /* so improved NEXTBYTE does not waste input */ uch *inptr_leftover; #ifdef VMS_TEXT_CONV unsigned VMS_line_length; /* so native VMS variable-length text files */ int VMS_line_state; /* are readable on other platforms */ int VMS_line_pad; #endif #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) char autorun_command[FILNAMSIZ]; #endif #endif /* !FUNZIP */ #ifdef SYSTEM_SPECIFIC_GLOBALS SYSTEM_SPECIFIC_GLOBALS #endif } Uz_Globs; /* end of struct Globals */ /***************************************************************************/ #define CRC_32_TAB G.crc_32_tab Uz_Globs *globalsCtor OF((void)); /* pseudo constant sigs; they are initialized at runtime so unzip executable * won't look like a zipfile */ extern char local_hdr_sig[4]; extern char central_hdr_sig[4]; extern char end_central_sig[4]; extern char end_central32_sig[4]; extern char end_central64_sig[4]; extern char end_centloc64_sig[4]; /* extern char extd_local_sig[4]; NOT USED YET */ #ifdef REENTRANT # define G (*(Uz_Globs *)pG) # define __G pG # define __G__ pG, # define __GPRO Uz_Globs *pG # define __GPRO__ Uz_Globs *pG, # define __GDEF Uz_Globs *pG; # ifdef USETHREADID extern int lastScan; void deregisterGlobalPointer OF((__GPRO)); Uz_Globs *getGlobalPointer OF((void)); # define GETGLOBALS() Uz_Globs *pG = getGlobalPointer() # define DESTROYGLOBALS() do {free_G_buffers(pG); \ deregisterGlobalPointer(pG);} while (0) # else extern Uz_Globs *GG; # define GETGLOBALS() Uz_Globs *pG = GG # define DESTROYGLOBALS() do {free_G_buffers(pG); free(pG);} while (0) # endif /* ?USETHREADID */ # define CONSTRUCTGLOBALS() Uz_Globs *pG = globalsCtor() #else /* !REENTRANT */ extern Uz_Globs G; # define __G # define __G__ # define __GPRO void # define __GPRO__ # define __GDEF # define GETGLOBALS() # define CONSTRUCTGLOBALS() globalsCtor() # define DESTROYGLOBALS() #endif /* ?REENTRANT */ #define uO G.UzO #endif /* __globals_h */ Carla-2.1/data/windows/unzipfx-carla-control/inflate.c000066400000000000000000001742151364475620200230530ustar00rootroot00000000000000/* Copyright (c) 1990-2008 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2007-Mar-04 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* inflate.c -- by Mark Adler version c17e, 30 Mar 2007 */ /* Copyright history: - Starting with UnZip 5.41 of 16-April-2000, this source file is covered by the Info-Zip LICENSE cited above. - Prior versions of this source file, found in UnZip source packages up to UnZip 5.40, were put in the public domain. The original copyright note by Mark Adler was: "You can do whatever you like with this source file, though I would prefer that if you modify it and redistribute it that you include comments to that effect with your name and the date. Thank you." History: vers date who what ---- --------- -------------- ------------------------------------ a ~~ Feb 92 M. Adler used full (large, one-step) lookup table b1 21 Mar 92 M. Adler first version with partial lookup tables b2 21 Mar 92 M. Adler fixed bug in fixed-code blocks b3 22 Mar 92 M. Adler sped up match copies, cleaned up some b4 25 Mar 92 M. Adler added prototypes; removed window[] (now is the responsibility of unzip.h--also changed name to slide[]), so needs diffs for unzip.c and unzip.h (this allows compiling in the small model on MSDOS); fixed cast of q in huft_build(); b5 26 Mar 92 M. Adler got rid of unintended macro recursion. b6 27 Mar 92 M. Adler got rid of nextbyte() routine. fixed bug in inflate_fixed(). c1 30 Mar 92 M. Adler removed lbits, dbits environment variables. changed BMAX to 16 for explode. Removed OUTB usage, and replaced it with flush()-- this was a 20% speed improvement! Added an explode.c (to replace unimplod.c) that uses the huft routines here. Removed register union. c2 4 Apr 92 M. Adler fixed bug for file sizes a multiple of 32k. c3 10 Apr 92 M. Adler reduced memory of code tables made by huft_build significantly (factor of two to three). c4 15 Apr 92 M. Adler added NOMEMCPY do kill use of memcpy(). worked around a Turbo C optimization bug. c5 21 Apr 92 M. Adler added the WSIZE #define to allow reducing the 32K window size for specialized applications. c6 31 May 92 M. Adler added some typecasts to eliminate warnings c7 27 Jun 92 G. Roelofs added some more typecasts (444: MSC bug). c8 5 Oct 92 J-l. Gailly added ifdef'd code to deal with PKZIP bug. c9 9 Oct 92 M. Adler removed a memory error message (~line 416). c10 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch, removed old inflate, renamed inflate_entry to inflate, added Mark's fix to a comment. c10.5 14 Dec 92 M. Adler fix up error messages for incomplete trees. c11 2 Jan 93 M. Adler fixed bug in detection of incomplete tables, and removed assumption that EOB is the longest code (bad assumption). c12 3 Jan 93 M. Adler make tables for fixed blocks only once. c13 5 Jan 93 M. Adler allow all zero length codes (pkzip 2.04c outputs one zero length code for an empty distance tree). c14 12 Mar 93 M. Adler made inflate.c standalone with the introduction of inflate.h. c14b 16 Jul 93 G. Roelofs added (unsigned) typecast to w at 470. c14c 19 Jul 93 J. Bush changed v[N_MAX], l[288], ll[28x+3x] arrays to static for Amiga. c14d 13 Aug 93 J-l. Gailly de-complicatified Mark's c[*p++]++ thing. c14e 8 Oct 93 G. Roelofs changed memset() to memzero(). c14f 22 Oct 93 G. Roelofs renamed quietflg to qflag; made Trace() conditional; added inflate_free(). c14g 28 Oct 93 G. Roelofs changed l/(lx+1) macro to pointer (Cray bug) c14h 7 Dec 93 C. Ghisler huft_build() optimizations. c14i 9 Jan 94 A. Verheijen set fixed_t{d,l} to NULL after freeing; G. Roelofs check NEXTBYTE macro for EOF. c14j 23 Jan 94 G. Roelofs removed Ghisler "optimizations"; ifdef'd EOF check. c14k 27 Feb 94 G. Roelofs added some typecasts to avoid warnings. c14l 9 Apr 94 G. Roelofs fixed split comments on preprocessor lines to avoid bug in Encore compiler. c14m 7 Jul 94 P. Kienitz modified to allow assembler version of inflate_codes() (define ASM_INFLATECODES) c14n 22 Jul 94 G. Roelofs changed fprintf to macro for DLL versions c14o 23 Aug 94 C. Spieler added a newline to a debug statement; G. Roelofs added another typecast to avoid MSC warning c14p 4 Oct 94 G. Roelofs added (voidp *) cast to free() argument c14q 30 Oct 94 G. Roelofs changed fprintf macro to MESSAGE() c14r 1 Nov 94 G. Roelofs fixed possible redefinition of CHECK_EOF c14s 7 May 95 S. Maxwell OS/2 DLL globals stuff incorporated; P. Kienitz "fixed" ASM_INFLATECODES macro/prototype c14t 18 Aug 95 G. Roelofs added UZinflate() to use zlib functions; changed voidp to zvoid; moved huft_build() and huft_free() to end of file c14u 1 Oct 95 G. Roelofs moved G into definition of MESSAGE macro c14v 8 Nov 95 P. Kienitz changed ASM_INFLATECODES to use a regular call with __G__ instead of a macro c15 3 Aug 96 M. Adler fixed bomb-bug on random input data (Adobe) c15b 24 Aug 96 M. Adler more fixes for random input data c15c 28 Mar 97 G. Roelofs changed USE_ZLIB fatal exit code from PK_MEM2 to PK_MEM3 c16 20 Apr 97 J. Altman added memzero(v[]) in huft_build() c16b 29 Mar 98 C. Spieler modified DLL code for slide redirection c16c 04 Apr 99 C. Spieler fixed memory leaks when processing gets stopped because of input data errors c16d 05 Jul 99 C. Spieler take care of FLUSH() return values and stop processing in case of errors c17 31 Dec 00 C. Spieler added preliminary support for Deflate64 c17a 04 Feb 01 C. Spieler complete integration of Deflate64 support c17b 16 Feb 02 C. Spieler changed type of "extra bits" arrays and corresponding huft_build() parameter e from ush into uch, to save space c17c 9 Mar 02 C. Spieler fixed NEEDBITS() "read beyond EOF" problem with CHECK_EOF enabled c17d 23 Jul 05 C. Spieler fixed memory leaks in inflate_dynamic() when processing invalid compressed literal/ distance table data c17e 30 Mar 07 C. Spieler in inflate_dynamic(), initialize tl and td to prevent freeing unallocated huft tables when processing invalid compressed data and hitting premature EOF, do not reuse td as temp work ptr during tables decoding */ /* Inflate deflated (PKZIP's method 8 compressed) data. The compression method searches for as much of the current string of bytes (up to a length of 258) in the previous 32K bytes. If it doesn't find any matches (of at least length 3), it codes the next byte. Otherwise, it codes the length of the matched string and its distance backwards from the current position. There is a single Huffman code that codes both single bytes (called "literals") and match lengths. A second Huffman code codes the distance information, which follows a length code. Each length or distance code actually represents a base value and a number of "extra" (sometimes zero) bits to get to add to the base value. At the end of each deflated block is a special end-of-block (EOB) literal/ length code. The decoding process is basically: get a literal/length code; if EOB then done; if a literal, emit the decoded byte; if a length then get the distance and emit the referred-to bytes from the sliding window of previously emitted data. There are (currently) three kinds of inflate blocks: stored, fixed, and dynamic. The compressor outputs a chunk of data at a time and decides which method to use on a chunk-by-chunk basis. A chunk might typically be 32K to 64K, uncompressed. If the chunk is uncompressible, then the "stored" method is used. In this case, the bytes are simply stored as is, eight bits per byte, with none of the above coding. The bytes are preceded by a count, since there is no longer an EOB code. If the data are compressible, then either the fixed or dynamic methods are used. In the dynamic method, the compressed data are preceded by an encoding of the literal/length and distance Huffman codes that are to be used to decode this block. The representation is itself Huffman coded, and so is preceded by a description of that code. These code descriptions take up a little space, and so for small blocks, there is a predefined set of codes, called the fixed codes. The fixed method is used if the block ends up smaller that way (usually for quite small chunks); otherwise the dynamic method is used. In the latter case, the codes are customized to the probabilities in the current block and so can code it much better than the pre-determined fixed codes can. The Huffman codes themselves are decoded using a multi-level table lookup, in order to maximize the speed of decoding plus the speed of building the decoding tables. See the comments below that precede the lbits and dbits tuning parameters. GRR: return values(?) 0 OK 1 incomplete table 2 bad input 3 not enough memory the following return codes are passed through from FLUSH() errors 50 (PK_DISK) "overflow of output space" 80 (IZ_CTRLC) "canceled by user's request" */ /* Notes beyond the 1.93a appnote.txt: 1. Distance pointers never point before the beginning of the output stream. 2. Distance pointers can point back across blocks, up to 32k away. 3. There is an implied maximum of 7 bits for the bit length table and 15 bits for the actual data. 4. If only one code exists, then it is encoded using one bit. (Zero would be more efficient, but perhaps a little confusing.) If two codes exist, they are coded using one bit each (0 and 1). 5. There is no way of sending zero distance codes--a dummy must be sent if there are none. (History: a pre 2.0 version of PKZIP would store blocks with no distance codes, but this was discovered to be too harsh a criterion.) Valid only for 1.93a. 2.04c does allow zero distance codes, which is sent as one code of zero bits in length. 6. There are up to 286 literal/length codes. Code 256 represents the end-of-block. Note however that the static length tree defines 288 codes just to fill out the Huffman codes. Codes 286 and 287 cannot be used though, since there is no length base or extra bits defined for them. Similarily, there are up to 30 distance codes. However, static trees define 32 codes (all 5 bits) to fill out the Huffman codes, but the last two had better not show up in the data. 7. Unzip can check dynamic Huffman blocks for complete code sets. The exception is that a single code would not be complete (see #4). 8. The five bits following the block type is really the number of literal codes sent minus 257. 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits (1+6+6). Therefore, to output three times the length, you output three codes (1+1+1), whereas to output four times the same length, you only need two codes (1+3). Hmm. 10. In the tree reconstruction algorithm, Code = Code + Increment only if BitLength(i) is not zero. (Pretty obvious.) 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) 12. Note: length code 284 can represent 227-258, but length code 285 really is 258. The last length deserves its own, short code since it gets used a lot in very redundant files. The length 258 is special since 258 - 3 (the min match length) is 255. 13. The literal/length and distance code bit lengths are read as a single stream of lengths. It is possible (and advantageous) for a repeat code (16, 17, or 18) to go across the boundary between the two sets of lengths. 14. The Deflate64 (PKZIP method 9) variant of the compression algorithm differs from "classic" deflate in the following 3 aspect: a) The size of the sliding history window is expanded to 64 kByte. b) The previously unused distance codes #30 and #31 code distances from 32769 to 49152 and 49153 to 65536. Both codes take 14 bits of extra data to determine the exact position in their 16 kByte range. c) The last lit/length code #285 gets a different meaning. Instead of coding a fixed maximum match length of 258, it is used as a "generic" match length code, capable of coding any length from 3 (min match length + 0) to 65538 (min match length + 65535). This means that the length code #285 takes 16 bits (!) of uncoded extra data, added to a fixed min length of 3. Changes a) and b) would have been transparent for valid deflated data, but change c) requires to switch decoder configurations between Deflate and Deflate64 modes. */ #define PKZIP_BUG_WORKAROUND /* PKZIP 1.93a problem--live with it */ /* inflate.h must supply the uch slide[WSIZE] array, the zvoid typedef (void if (void *) is accepted, else char) and the NEXTBYTE, FLUSH() and memzero macros. If the window size is not 32K, it should also define WSIZE. If INFMOD is defined, it can include compiled functions to support the NEXTBYTE and/or FLUSH() macros. There are defaults for NEXTBYTE and FLUSH() below for use as examples of what those functions need to do. Normally, you would also want FLUSH() to compute a crc on the data. inflate.h also needs to provide these typedefs: typedef unsigned char uch; typedef unsigned short ush; typedef unsigned long ulg; This module uses the external functions malloc() and free() (and probably memset() or bzero() in the memzero() macro). Their prototypes are normally found in and . */ #define __INFLATE_C /* identifies this source module */ /* #define DEBUG */ #define INFMOD /* tell inflate.h to include code to be compiled */ #include "inflate.h" /* marker for "unused" huft code, and corresponding check macro */ #define INVALID_CODE 99 #define IS_INVALID_CODE(c) ((c) == INVALID_CODE) #ifndef WSIZE /* default is 32K resp. 64K */ # ifdef USE_DEFLATE64 # define WSIZE 65536L /* window size--must be a power of two, and */ # else /* at least 64K for PKZip's deflate64 method */ # define WSIZE 0x8000 /* window size--must be a power of two, and */ # endif /* at least 32K for zip's deflate method */ #endif /* some buffer counters must be capable of holding 64k for Deflate64 */ #if (defined(USE_DEFLATE64) && defined(INT_16BIT)) # define UINT_D64 ulg #else # define UINT_D64 unsigned #endif #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) # define wsize G._wsize /* wsize is a variable */ #else # define wsize WSIZE /* wsize is a constant */ #endif #ifndef NEXTBYTE /* default is to simply get a byte from stdin */ # define NEXTBYTE getchar() #endif #ifndef MESSAGE /* only used twice, for fixed strings--NOT general-purpose */ # define MESSAGE(str,len,flag) fprintf(stderr,(char *)(str)) #endif #ifndef FLUSH /* default is to simply write the buffer to stdout */ # define FLUSH(n) \ (((extent)fwrite(redirSlide, 1, (extent)(n), stdout) == (extent)(n)) ? \ 0 : PKDISK) #endif /* Warning: the fwrite above might not work on 16-bit compilers, since 0x8000 might be interpreted as -32,768 by the library function. When support for Deflate64 is enabled, the window size is 64K and the simple fwrite statement is definitely broken for 16-bit compilers. */ #ifndef Trace # ifdef DEBUG # define Trace(x) fprintf x # else # define Trace(x) # endif #endif /*---------------------------------------------------------------------------*/ #ifdef USE_ZLIB /* Beginning with zlib version 1.2.0, a new inflate callback interface is provided that allows tighter integration of the zlib inflate service into unzip's extraction framework. The advantages are: - uses the windows buffer supplied by the unzip code; this saves one copy process between zlib's internal decompression buffer and unzip's post-decompression output buffer and improves performance. - does not pull in unused checksum code (adler32). The preprocessor flag NO_ZLIBCALLBCK can be set to force usage of the old zlib 1.1.x interface, for testing purpose. */ #ifdef USE_ZLIB_INFLATCB # undef USE_ZLIB_INFLATCB #endif #if (defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1200 && !defined(NO_ZLIBCALLBCK)) # define USE_ZLIB_INFLATCB 1 #else # define USE_ZLIB_INFLATCB 0 #endif /* Check for incompatible combinations of zlib and Deflate64 support. */ #if defined(USE_DEFLATE64) # if !USE_ZLIB_INFLATCB #error Deflate64 is incompatible with traditional (pre-1.2.x) zlib interface! # else /* The Deflate64 callback function in the framework of zlib 1.2.x requires the inclusion of the unsupported infback9 header file: */ # include "infback9.h" # endif #endif /* USE_DEFLATE64 */ #if USE_ZLIB_INFLATCB static unsigned zlib_inCB OF((void FAR *pG, unsigned char FAR * FAR * pInbuf)); static int zlib_outCB OF((void FAR *pG, unsigned char FAR *outbuf, unsigned outcnt)); static unsigned zlib_inCB(pG, pInbuf) void FAR *pG; unsigned char FAR * FAR * pInbuf; { *pInbuf = G.inbuf; return fillinbuf(__G); } static int zlib_outCB(pG, outbuf, outcnt) void FAR *pG; unsigned char FAR *outbuf; unsigned outcnt; { #ifdef FUNZIP return flush(__G__ (ulg)(outcnt)); #else return ((G.mem_mode) ? memflush(__G__ outbuf, (ulg)(outcnt)) : flush(__G__ outbuf, (ulg)(outcnt), 0)); #endif } #endif /* USE_ZLIB_INFLATCB */ /* GRR: return values for both original inflate() and UZinflate() 0 OK 1 incomplete table(?) 2 bad input 3 not enough memory */ /**************************/ /* Function UZinflate() */ /**************************/ int UZinflate(__G__ is_defl64) __GDEF int is_defl64; /* decompress an inflated entry using the zlib routines */ { int retval = 0; /* return code: 0 = "no error" */ int err=Z_OK; #if USE_ZLIB_INFLATCB #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) wsize = G.redirect_size, redirSlide = G.redirect_buffer; else wsize = WSIZE, redirSlide = slide; #endif if (!G.inflInit) { /* local buffer for efficiency */ ZCONST char *zlib_RtVersion = zlibVersion(); /* only need to test this stuff once */ if ((zlib_RtVersion[0] != ZLIB_VERSION[0]) || (zlib_RtVersion[2] != ZLIB_VERSION[2])) { Info(slide, 0x21, ((char *)slide, "error: incompatible zlib version (expected %s, found %s)\n", ZLIB_VERSION, zlib_RtVersion)); return 3; } else if (strcmp(zlib_RtVersion, ZLIB_VERSION) != 0) Info(slide, 0x21, ((char *)slide, "warning: different zlib version (expected %s, using %s)\n", ZLIB_VERSION, zlib_RtVersion)); G.dstrm.zalloc = (alloc_func)Z_NULL; G.dstrm.zfree = (free_func)Z_NULL; G.inflInit = 1; } #ifdef USE_DEFLATE64 if (is_defl64) { Trace((stderr, "initializing inflate9()\n")); err = inflateBack9Init(&G.dstrm, redirSlide); if (err == Z_MEM_ERROR) return 3; else if (err != Z_OK) { Trace((stderr, "oops! (inflateBack9Init() err = %d)\n", err)); return 2; } G.dstrm.next_in = G.inptr; G.dstrm.avail_in = G.incnt; err = inflateBack9(&G.dstrm, zlib_inCB, &G, zlib_outCB, &G); if (err != Z_STREAM_END) { if (err == Z_DATA_ERROR || err == Z_STREAM_ERROR) { Trace((stderr, "oops! (inflateBack9() err = %d)\n", err)); retval = 2; } else if (err == Z_MEM_ERROR) { retval = 3; } else if (err == Z_BUF_ERROR) { Trace((stderr, "oops! (inflateBack9() err = %d)\n", err)); if (G.dstrm.next_in == Z_NULL) { /* input failure */ Trace((stderr, " inflateBack9() input failure\n")); retval = 2; } else { /* output write failure */ retval = (G.disk_full != 0 ? PK_DISK : IZ_CTRLC); } } else { Trace((stderr, "oops! (inflateBack9() err = %d)\n", err)); retval = 2; } } if (G.dstrm.next_in != NULL) { G.inptr = (uch *)G.dstrm.next_in; G.incnt = G.dstrm.avail_in; } err = inflateBack9End(&G.dstrm); if (err != Z_OK) { Trace((stderr, "oops! (inflateBack9End() err = %d)\n", err)); if (retval == 0) retval = 2; } } else #endif /* USE_DEFLATE64 */ { /* For the callback interface, inflate initialization has to be called before each decompression call. */ { unsigned i; int windowBits; /* windowBits = log2(wsize) */ for (i = (unsigned)wsize, windowBits = 0; !(i & 1); i >>= 1, ++windowBits); if ((unsigned)windowBits > (unsigned)15) windowBits = 15; else if (windowBits < 8) windowBits = 8; Trace((stderr, "initializing inflate()\n")); err = inflateBackInit(&G.dstrm, windowBits, redirSlide); if (err == Z_MEM_ERROR) return 3; else if (err != Z_OK) { Trace((stderr, "oops! (inflateBackInit() err = %d)\n", err)); return 2; } } G.dstrm.next_in = G.inptr; G.dstrm.avail_in = G.incnt; err = inflateBack(&G.dstrm, zlib_inCB, &G, zlib_outCB, &G); if (err != Z_STREAM_END) { if (err == Z_DATA_ERROR || err == Z_STREAM_ERROR) { Trace((stderr, "oops! (inflateBack() err = %d)\n", err)); retval = 2; } else if (err == Z_MEM_ERROR) { retval = 3; } else if (err == Z_BUF_ERROR) { Trace((stderr, "oops! (inflateBack() err = %d)\n", err)); if (G.dstrm.next_in == Z_NULL) { /* input failure */ Trace((stderr, " inflateBack() input failure\n")); retval = 2; } else { /* output write failure */ retval = (G.disk_full != 0 ? PK_DISK : IZ_CTRLC); } } else { Trace((stderr, "oops! (inflateBack() err = %d)\n", err)); retval = 2; } } if (G.dstrm.next_in != NULL) { G.inptr = (uch *)G.dstrm.next_in; G.incnt = G.dstrm.avail_in; } err = inflateBackEnd(&G.dstrm); if (err != Z_OK) { Trace((stderr, "oops! (inflateBackEnd() err = %d)\n", err)); if (retval == 0) retval = 2; } } #else /* !USE_ZLIB_INFLATCB */ int repeated_buf_err; #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) wsize = G.redirect_size, redirSlide = G.redirect_buffer; else wsize = WSIZE, redirSlide = slide; #endif G.dstrm.next_out = redirSlide; G.dstrm.avail_out = wsize; G.dstrm.next_in = G.inptr; G.dstrm.avail_in = G.incnt; if (!G.inflInit) { unsigned i; int windowBits; /* local buffer for efficiency */ ZCONST char *zlib_RtVersion = zlibVersion(); /* only need to test this stuff once */ if (zlib_RtVersion[0] != ZLIB_VERSION[0]) { Info(slide, 0x21, ((char *)slide, "error: incompatible zlib version (expected %s, found %s)\n", ZLIB_VERSION, zlib_RtVersion)); return 3; } else if (strcmp(zlib_RtVersion, ZLIB_VERSION) != 0) Info(slide, 0x21, ((char *)slide, "warning: different zlib version (expected %s, using %s)\n", ZLIB_VERSION, zlib_RtVersion)); /* windowBits = log2(wsize) */ for (i = (unsigned)wsize, windowBits = 0; !(i & 1); i >>= 1, ++windowBits); if ((unsigned)windowBits > (unsigned)15) windowBits = 15; else if (windowBits < 8) windowBits = 8; G.dstrm.zalloc = (alloc_func)Z_NULL; G.dstrm.zfree = (free_func)Z_NULL; Trace((stderr, "initializing inflate()\n")); err = inflateInit2(&G.dstrm, -windowBits); if (err == Z_MEM_ERROR) return 3; else if (err != Z_OK) Trace((stderr, "oops! (inflateInit2() err = %d)\n", err)); G.inflInit = 1; } #ifdef FUNZIP while (err != Z_STREAM_END) { #else /* !FUNZIP */ while (G.csize > 0) { Trace((stderr, "first loop: G.csize = %ld\n", G.csize)); #endif /* ?FUNZIP */ while (G.dstrm.avail_out > 0) { err = inflate(&G.dstrm, Z_PARTIAL_FLUSH); if (err == Z_DATA_ERROR) { retval = 2; goto uzinflate_cleanup_exit; } else if (err == Z_MEM_ERROR) { retval = 3; goto uzinflate_cleanup_exit; } else if (err != Z_OK && err != Z_STREAM_END) Trace((stderr, "oops! (inflate(first loop) err = %d)\n", err)); #ifdef FUNZIP if (err == Z_STREAM_END) /* "END-of-entry-condition" ? */ #else /* !FUNZIP */ if (G.csize <= 0L) /* "END-of-entry-condition" ? */ #endif /* ?FUNZIP */ break; if (G.dstrm.avail_in == 0) { if (fillinbuf(__G) == 0) { /* no "END-condition" yet, but no more data */ retval = 2; goto uzinflate_cleanup_exit; } G.dstrm.next_in = G.inptr; G.dstrm.avail_in = G.incnt; } Trace((stderr, " avail_in = %u\n", G.dstrm.avail_in)); } /* flush slide[] */ if ((retval = FLUSH(wsize - G.dstrm.avail_out)) != 0) goto uzinflate_cleanup_exit; Trace((stderr, "inside loop: flushing %ld bytes (ptr diff = %ld)\n", (long)(wsize - G.dstrm.avail_out), (long)(G.dstrm.next_out-(Bytef *)redirSlide))); G.dstrm.next_out = redirSlide; G.dstrm.avail_out = wsize; } /* no more input, so loop until we have all output */ Trace((stderr, "beginning final loop: err = %d\n", err)); repeated_buf_err = FALSE; while (err != Z_STREAM_END) { err = inflate(&G.dstrm, Z_PARTIAL_FLUSH); if (err == Z_DATA_ERROR) { retval = 2; goto uzinflate_cleanup_exit; } else if (err == Z_MEM_ERROR) { retval = 3; goto uzinflate_cleanup_exit; } else if (err == Z_BUF_ERROR) { /* DEBUG */ #ifdef FUNZIP Trace((stderr, "zlib inflate() did not detect stream end\n")); #else Trace((stderr, "zlib inflate() did not detect stream end (%s, %s)\n", G.zipfn, G.filename)); #endif if ((!repeated_buf_err) && (G.dstrm.avail_in == 0)) { /* when detecting this problem for the first time, try to provide one fake byte beyond "EOF"... */ G.dstrm.next_in = ""; G.dstrm.avail_in = 1; repeated_buf_err = TRUE; } else break; } else if (err != Z_OK && err != Z_STREAM_END) { Trace((stderr, "oops! (inflate(final loop) err = %d)\n", err)); DESTROYGLOBALS(); EXIT(PK_MEM3); } /* final flush of slide[] */ if ((retval = FLUSH(wsize - G.dstrm.avail_out)) != 0) goto uzinflate_cleanup_exit; Trace((stderr, "final loop: flushing %ld bytes (ptr diff = %ld)\n", (long)(wsize - G.dstrm.avail_out), (long)(G.dstrm.next_out-(Bytef *)redirSlide))); G.dstrm.next_out = redirSlide; G.dstrm.avail_out = wsize; } Trace((stderr, "total in = %lu, total out = %lu\n", G.dstrm.total_in, G.dstrm.total_out)); G.inptr = (uch *)G.dstrm.next_in; G.incnt = (G.inbuf + INBUFSIZ) - G.inptr; /* reset for other routines */ uzinflate_cleanup_exit: err = inflateReset(&G.dstrm); if (err != Z_OK) Trace((stderr, "oops! (inflateReset() err = %d)\n", err)); #endif /* ?USE_ZLIB_INFLATCB */ return retval; } /*---------------------------------------------------------------------------*/ #else /* !USE_ZLIB */ /* Function prototypes */ #ifndef OF # ifdef __STDC__ # define OF(a) a # else # define OF(a) () # endif #endif /* !OF */ int inflate_codes OF((__GPRO__ struct huft *tl, struct huft *td, unsigned bl, unsigned bd)); static int inflate_stored OF((__GPRO)); static int inflate_fixed OF((__GPRO)); static int inflate_dynamic OF((__GPRO)); static int inflate_block OF((__GPRO__ int *e)); /* The inflate algorithm uses a sliding 32K byte window on the uncompressed stream to find repeated byte strings. This is implemented here as a circular buffer. The index is updated simply by incrementing and then and'ing with 0x7fff (32K-1). */ /* It is left to other modules to supply the 32K area. It is assumed to be usable as if it were declared "uch slide[32768];" or as just "uch *slide;" and then malloc'ed in the latter case. The definition must be in unzip.h, included above. */ /* unsigned wp; moved to globals.h */ /* current position in slide */ /* Tables for deflate from PKZIP's appnote.txt. */ /* - Order of the bit length code lengths */ static ZCONST unsigned border[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; /* - Copy lengths for literal codes 257..285 */ #ifdef USE_DEFLATE64 static ZCONST ush cplens64[] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 3, 0, 0}; /* For Deflate64, the code 285 is defined differently. */ #else # define cplens32 cplens #endif static ZCONST ush cplens32[] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; /* note: see note #13 above about the 258 in this list. */ /* - Extra bits for literal codes 257..285 */ #ifdef USE_DEFLATE64 static ZCONST uch cplext64[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16, INVALID_CODE, INVALID_CODE}; #else # define cplext32 cplext #endif static ZCONST uch cplext32[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, INVALID_CODE, INVALID_CODE}; /* - Copy offsets for distance codes 0..29 (0..31 for Deflate64) */ static ZCONST ush cpdist[] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, #if (defined(USE_DEFLATE64) || defined(PKZIP_BUG_WORKAROUND)) 8193, 12289, 16385, 24577, 32769, 49153}; #else 8193, 12289, 16385, 24577}; #endif /* - Extra bits for distance codes 0..29 (0..31 for Deflate64) */ #ifdef USE_DEFLATE64 static ZCONST uch cpdext64[] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14}; #else # define cpdext32 cpdext #endif static ZCONST uch cpdext32[] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, #ifdef PKZIP_BUG_WORKAROUND 12, 12, 13, 13, INVALID_CODE, INVALID_CODE}; #else 12, 12, 13, 13}; #endif #ifdef PKZIP_BUG_WORKAROUND # define MAXLITLENS 288 #else # define MAXLITLENS 286 #endif #if (defined(USE_DEFLATE64) || defined(PKZIP_BUG_WORKAROUND)) # define MAXDISTS 32 #else # define MAXDISTS 30 #endif /* moved to consts.h (included in unzip.c), resp. funzip.c */ #if 0 /* And'ing with mask_bits[n] masks the lower n bits */ ZCONST unsigned near mask_bits[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; #endif /* 0 */ /* Macros for inflate() bit peeking and grabbing. The usage is: NEEDBITS(j) x = b & mask_bits[j]; DUMPBITS(j) where NEEDBITS makes sure that b has at least j bits in it, and DUMPBITS removes the bits from b. The macros use the variable k for the number of bits in b. Normally, b and k are register variables for speed and are initialized at the beginning of a routine that uses these macros from a global bit buffer and count. In order to not ask for more bits than there are in the compressed stream, the Huffman tables are constructed to only ask for just enough bits to make up the end-of-block code (value 256). Then no bytes need to be "returned" to the buffer at the end of the last block. See the huft_build() routine. Actually, the precautions mentioned above are not sufficient to prevent fetches of bits beyound the end of the last block in every case. When the last code fetched before the end-of-block code was a very short distance code (shorter than "distance-prefetch-bits" - "end-of-block code bits"), this last distance code fetch already exausts the available data. To prevent failure of extraction in this case, the "read beyond EOF" check delays the raise of the "invalid data" error until an actual overflow of "used data" is detected. This error condition is only fulfilled when the "number of available bits" counter k is found to be negative in the NEEDBITS() macro. An alternate fix for that problem adjusts the size of the distance code base table so that it does not exceed the length of the end-of-block code plus the minimum length of a distance code. This alternate fix can be enabled by defining the preprocessor symbol FIX_PAST_EOB_BY_TABLEADJUST. */ /* These have been moved to globals.h */ #if 0 ulg bb; /* bit buffer */ unsigned bk; /* bits in bit buffer */ #endif #ifndef CHECK_EOF # define CHECK_EOF /* default as of 5.13/5.2 */ #endif #ifndef CHECK_EOF # define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<=0)break;retval=1;goto cleanup_and_exit;}\ b|=((ulg)c)<>=(n);k-=(n);} /* Huffman code decoding is performed using a multi-level table lookup. The fastest way to decode is to simply build a lookup table whose size is determined by the longest code. However, the time it takes to build this table can also be a factor if the data being decoded are not very long. The most common codes are necessarily the shortest codes, so those codes dominate the decoding time, and hence the speed. The idea is you can have a shorter table that decodes the shorter, more probable codes, and then point to subsidiary tables for the longer codes. The time it costs to decode the longer codes is then traded against the time it takes to make longer tables. This results of this trade are in the variables lbits and dbits below. lbits is the number of bits the first level table for literal/ length codes can decode in one step, and dbits is the same thing for the distance codes. Subsequent tables are also less than or equal to those sizes. These values may be adjusted either when all of the codes are shorter than that, in which case the longest code length in bits is used, or when the shortest code is *longer* than the requested table size, in which case the length of the shortest code in bits is used. There are two different values for the two tables, since they code a different number of possibilities each. The literal/length table codes 286 possible values, or in a flat code, a little over eight bits. The distance table codes 30 possible values, or a little less than five bits, flat. The optimum values for speed end up being about one bit more than those, so lbits is 8+1 and dbits is 5+1. The optimum values may differ though from machine to machine, and possibly even between compilers. Your mileage may vary. */ /* bits in base literal/length lookup table */ static ZCONST unsigned lbits = 9; /* bits in base distance lookup table */ static ZCONST unsigned dbits = 6; #ifndef ASM_INFLATECODES int inflate_codes(__G__ tl, td, bl, bd) __GDEF struct huft *tl, *td; /* literal/length and distance decoder tables */ unsigned bl, bd; /* number of bits decoded by tl[] and td[] */ /* inflate (decompress) the codes in a deflated (compressed) block. Return an error code or zero if it all goes ok. */ { register unsigned e; /* table entry flag/number of extra bits */ unsigned d; /* index for copy */ UINT_D64 n; /* length for copy (deflate64: might be 64k+2) */ UINT_D64 w; /* current window position (deflate64: up to 64k) */ struct huft *t; /* pointer to table entry */ unsigned ml, md; /* masks for bl and bd bits */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ int retval = 0; /* error code returned: initialized to "no error" */ /* make local copies of globals */ b = G.bb; /* initialize bit buffer */ k = G.bk; w = G.wp; /* initialize window position */ /* inflate the coded data */ ml = mask_bits[bl]; /* precompute masks for speed */ md = mask_bits[bd]; while (1) /* do until end of block */ { NEEDBITS(bl) t = tl + ((unsigned)b & ml); while (1) { DUMPBITS(t->b) if ((e = t->e) == 32) /* then it's a literal */ { redirSlide[w++] = (uch)t->v.n; if (w == wsize) { if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit; w = 0; } break; } if (e < 31) /* then it's a length */ { /* get length of block to copy */ NEEDBITS(e) n = t->v.n + ((unsigned)b & mask_bits[e]); DUMPBITS(e) /* decode distance of block to copy */ NEEDBITS(bd) t = td + ((unsigned)b & md); while (1) { DUMPBITS(t->b) if ((e = t->e) < 32) break; if (IS_INVALID_CODE(e)) return 1; e &= 31; NEEDBITS(e) t = t->v.t + ((unsigned)b & mask_bits[e]); } NEEDBITS(e) d = (unsigned)w - t->v.n - ((unsigned)b & mask_bits[e]); DUMPBITS(e) /* do the copy */ do { #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) { /* &= w/ wsize unnecessary & wrong if redirect */ if ((UINT_D64)d >= wsize) return 1; /* invalid compressed data */ e = (unsigned)(wsize - (d > (unsigned)w ? (UINT_D64)d : w)); } else #endif e = (unsigned)(wsize - ((d &= (unsigned)(wsize-1)) > (unsigned)w ? (UINT_D64)d : w)); if ((UINT_D64)e > n) e = (unsigned)n; n -= e; #ifndef NOMEMCPY if ((unsigned)w - d >= e) /* (this test assumes unsigned comparison) */ { memcpy(redirSlide + (unsigned)w, redirSlide + d, e); w += e; d += e; } else /* do it slowly to avoid memcpy() overlap */ #endif /* !NOMEMCPY */ do { redirSlide[w++] = redirSlide[d++]; } while (--e); if (w == wsize) { if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit; w = 0; } } while (n); break; } if (e == 31) /* it's the EOB signal */ { /* sorry for this goto, but we have to exit two loops at once */ goto cleanup_decode; } if (IS_INVALID_CODE(e)) return 1; e &= 31; NEEDBITS(e) t = t->v.t + ((unsigned)b & mask_bits[e]); } } cleanup_decode: /* restore the globals from the locals */ G.wp = (unsigned)w; /* restore global window pointer */ G.bb = b; /* restore global bit buffer */ G.bk = k; cleanup_and_exit: /* done */ return retval; } #endif /* ASM_INFLATECODES */ static int inflate_stored(__G) __GDEF /* "decompress" an inflated type 0 (stored) block. */ { UINT_D64 w; /* current window position (deflate64: up to 64k!) */ unsigned n; /* number of bytes in block */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ int retval = 0; /* error code returned: initialized to "no error" */ /* make local copies of globals */ Trace((stderr, "\nstored block")); b = G.bb; /* initialize bit buffer */ k = G.bk; w = G.wp; /* initialize window position */ /* go to byte boundary */ n = k & 7; DUMPBITS(n); /* get the length and its complement */ NEEDBITS(16) n = ((unsigned)b & 0xffff); DUMPBITS(16) NEEDBITS(16) if (n != (unsigned)((~b) & 0xffff)) return 1; /* error in compressed data */ DUMPBITS(16) /* read and output the compressed data */ while (n--) { NEEDBITS(8) redirSlide[w++] = (uch)b; if (w == wsize) { if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit; w = 0; } DUMPBITS(8) } /* restore the globals from the locals */ G.wp = (unsigned)w; /* restore global window pointer */ G.bb = b; /* restore global bit buffer */ G.bk = k; cleanup_and_exit: return retval; } /* Globals for literal tables (built once) */ /* Moved to globals.h */ #if 0 struct huft *fixed_tl = (struct huft *)NULL; struct huft *fixed_td; int fixed_bl, fixed_bd; #endif static int inflate_fixed(__G) __GDEF /* decompress an inflated type 1 (fixed Huffman codes) block. We should either replace this with a custom decoder, or at least precompute the Huffman tables. */ { /* if first time, set up tables for fixed blocks */ Trace((stderr, "\nliteral block")); if (G.fixed_tl == (struct huft *)NULL) { int i; /* temporary variable */ unsigned l[288]; /* length list for huft_build */ /* literal table */ for (i = 0; i < 144; i++) l[i] = 8; for (; i < 256; i++) l[i] = 9; for (; i < 280; i++) l[i] = 7; for (; i < 288; i++) /* make a complete, but wrong code set */ l[i] = 8; G.fixed_bl = 7; #ifdef USE_DEFLATE64 if ((i = huft_build(__G__ l, 288, 257, G.cplens, G.cplext, &G.fixed_tl, &G.fixed_bl)) != 0) #else if ((i = huft_build(__G__ l, 288, 257, cplens, cplext, &G.fixed_tl, &G.fixed_bl)) != 0) #endif { G.fixed_tl = (struct huft *)NULL; return i; } /* distance table */ for (i = 0; i < MAXDISTS; i++) /* make an incomplete code set */ l[i] = 5; G.fixed_bd = 5; #ifdef USE_DEFLATE64 if ((i = huft_build(__G__ l, MAXDISTS, 0, cpdist, G.cpdext, &G.fixed_td, &G.fixed_bd)) > 1) #else if ((i = huft_build(__G__ l, MAXDISTS, 0, cpdist, cpdext, &G.fixed_td, &G.fixed_bd)) > 1) #endif { huft_free(G.fixed_tl); G.fixed_td = G.fixed_tl = (struct huft *)NULL; return i; } } /* decompress until an end-of-block code */ return inflate_codes(__G__ G.fixed_tl, G.fixed_td, G.fixed_bl, G.fixed_bd); } static int inflate_dynamic(__G) __GDEF /* decompress an inflated type 2 (dynamic Huffman codes) block. */ { unsigned i; /* temporary variables */ unsigned j; unsigned l; /* last length */ unsigned m; /* mask for bit lengths table */ unsigned n; /* number of lengths to get */ struct huft *tl = (struct huft *)NULL; /* literal/length code table */ struct huft *td = (struct huft *)NULL; /* distance code table */ struct huft *th; /* temp huft table pointer used in tables decoding */ unsigned bl; /* lookup bits for tl */ unsigned bd; /* lookup bits for td */ unsigned nb; /* number of bit length codes */ unsigned nl; /* number of literal/length codes */ unsigned nd; /* number of distance codes */ unsigned ll[MAXLITLENS+MAXDISTS]; /* lit./length and distance code lengths */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ int retval = 0; /* error code returned: initialized to "no error" */ /* make local bit buffer */ Trace((stderr, "\ndynamic block")); b = G.bb; k = G.bk; /* read in table lengths */ NEEDBITS(5) nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */ DUMPBITS(5) NEEDBITS(5) nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */ DUMPBITS(5) NEEDBITS(4) nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */ DUMPBITS(4) if (nl > MAXLITLENS || nd > MAXDISTS) return 1; /* bad lengths */ /* read in bit-length-code lengths */ for (j = 0; j < nb; j++) { NEEDBITS(3) ll[border[j]] = (unsigned)b & 7; DUMPBITS(3) } for (; j < 19; j++) ll[border[j]] = 0; /* build decoding table for trees--single level, 7 bit lookup */ bl = 7; retval = huft_build(__G__ ll, 19, 19, NULL, NULL, &tl, &bl); if (bl == 0) /* no bit lengths */ retval = 1; if (retval) { if (retval == 1) huft_free(tl); return retval; /* incomplete code set */ } /* read in literal and distance code lengths */ n = nl + nd; m = mask_bits[bl]; i = l = 0; while (i < n) { NEEDBITS(bl) j = (th = tl + ((unsigned)b & m))->b; DUMPBITS(j) j = th->v.n; if (j < 16) /* length of code in bits (0..15) */ ll[i++] = l = j; /* save last length in l */ else if (j == 16) /* repeat last length 3 to 6 times */ { NEEDBITS(2) j = 3 + ((unsigned)b & 3); DUMPBITS(2) if ((unsigned)i + j > n) { huft_free(tl); return 1; } while (j--) ll[i++] = l; } else if (j == 17) /* 3 to 10 zero length codes */ { NEEDBITS(3) j = 3 + ((unsigned)b & 7); DUMPBITS(3) if ((unsigned)i + j > n) { huft_free(tl); return 1; } while (j--) ll[i++] = 0; l = 0; } else /* j == 18: 11 to 138 zero length codes */ { NEEDBITS(7) j = 11 + ((unsigned)b & 0x7f); DUMPBITS(7) if ((unsigned)i + j > n) { huft_free(tl); return 1; } while (j--) ll[i++] = 0; l = 0; } } /* free decoding table for trees */ huft_free(tl); /* restore the global bit buffer */ G.bb = b; G.bk = k; /* build the decoding tables for literal/length and distance codes */ bl = lbits; #ifdef USE_DEFLATE64 retval = huft_build(__G__ ll, nl, 257, G.cplens, G.cplext, &tl, &bl); #else retval = huft_build(__G__ ll, nl, 257, cplens, cplext, &tl, &bl); #endif if (bl == 0) /* no literals or lengths */ retval = 1; if (retval) { if (retval == 1) { if (!uO.qflag) MESSAGE((uch *)"(incomplete l-tree) ", 21L, 1); huft_free(tl); } return retval; /* incomplete code set */ } #ifdef FIX_PAST_EOB_BY_TABLEADJUST /* Adjust the requested distance base table size so that a distance code fetch never tries to get bits behind an immediatly following end-of-block code. */ bd = (dbits <= bl+1 ? dbits : bl+1); #else bd = dbits; #endif #ifdef USE_DEFLATE64 retval = huft_build(__G__ ll + nl, nd, 0, cpdist, G.cpdext, &td, &bd); #else retval = huft_build(__G__ ll + nl, nd, 0, cpdist, cpdext, &td, &bd); #endif #ifdef PKZIP_BUG_WORKAROUND if (retval == 1) retval = 0; #endif if (bd == 0 && nl > 257) /* lengths but no distances */ retval = 1; if (retval) { if (retval == 1) { if (!uO.qflag) MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1); huft_free(td); } huft_free(tl); return retval; } /* decompress until an end-of-block code */ retval = inflate_codes(__G__ tl, td, bl, bd); cleanup_and_exit: /* free the decoding tables, return */ if (tl != (struct huft *)NULL) huft_free(tl); if (td != (struct huft *)NULL) huft_free(td); return retval; } static int inflate_block(__G__ e) __GDEF int *e; /* last block flag */ /* decompress an inflated block */ { unsigned t; /* block type */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ int retval = 0; /* error code returned: initialized to "no error" */ /* make local bit buffer */ b = G.bb; k = G.bk; /* read in last block bit */ NEEDBITS(1) *e = (int)b & 1; DUMPBITS(1) /* read in block type */ NEEDBITS(2) t = (unsigned)b & 3; DUMPBITS(2) /* restore the global bit buffer */ G.bb = b; G.bk = k; /* inflate that block type */ if (t == 2) return inflate_dynamic(__G); if (t == 0) return inflate_stored(__G); if (t == 1) return inflate_fixed(__G); /* bad block type */ retval = 2; cleanup_and_exit: return retval; } int inflate(__G__ is_defl64) __GDEF int is_defl64; /* decompress an inflated entry */ { int e; /* last block flag */ int r; /* result code */ #ifdef DEBUG unsigned h = 0; /* maximum struct huft's malloc'ed */ #endif #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) wsize = G.redirect_size, redirSlide = G.redirect_buffer; else wsize = WSIZE, redirSlide = slide; /* how they're #defined if !DLL */ #endif /* initialize window, bit buffer */ G.wp = 0; G.bk = 0; G.bb = 0; #ifdef USE_DEFLATE64 if (is_defl64) { G.cplens = cplens64; G.cplext = cplext64; G.cpdext = cpdext64; G.fixed_tl = G.fixed_tl64; G.fixed_bl = G.fixed_bl64; G.fixed_td = G.fixed_td64; G.fixed_bd = G.fixed_bd64; } else { G.cplens = cplens32; G.cplext = cplext32; G.cpdext = cpdext32; G.fixed_tl = G.fixed_tl32; G.fixed_bl = G.fixed_bl32; G.fixed_td = G.fixed_td32; G.fixed_bd = G.fixed_bd32; } #else /* !USE_DEFLATE64 */ if (is_defl64) { /* This should not happen unless UnZip is built from object files * compiled with inconsistent option setting. Handle this by * returning with "bad input" error code. */ Trace((stderr, "\nThis inflate() cannot handle Deflate64!\n")); return 2; } #endif /* ?USE_DEFLATE64 */ /* decompress until the last block */ do { #ifdef DEBUG G.hufts = 0; #endif if ((r = inflate_block(__G__ &e)) != 0) return r; #ifdef DEBUG if (G.hufts > h) h = G.hufts; #endif } while (!e); Trace((stderr, "\n%u bytes in Huffman tables (%u/entry)\n", h * (unsigned)sizeof(struct huft), (unsigned)sizeof(struct huft))); #ifdef USE_DEFLATE64 if (is_defl64) { G.fixed_tl64 = G.fixed_tl; G.fixed_bl64 = G.fixed_bl; G.fixed_td64 = G.fixed_td; G.fixed_bd64 = G.fixed_bd; } else { G.fixed_tl32 = G.fixed_tl; G.fixed_bl32 = G.fixed_bl; G.fixed_td32 = G.fixed_td; G.fixed_bd32 = G.fixed_bd; } #endif /* flush out redirSlide and return (success, unless final FLUSH failed) */ return (FLUSH(G.wp)); } int inflate_free(__G) __GDEF { if (G.fixed_tl != (struct huft *)NULL) { huft_free(G.fixed_td); huft_free(G.fixed_tl); G.fixed_td = G.fixed_tl = (struct huft *)NULL; } return 0; } #endif /* ?USE_ZLIB */ /* * GRR: moved huft_build() and huft_free() down here; used by explode() * and fUnZip regardless of whether USE_ZLIB defined or not */ /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ #define BMAX 16 /* maximum bit length of any code (16 for explode) */ #define N_MAX 288 /* maximum number of codes in any set */ int huft_build(__G__ b, n, s, d, e, t, m) __GDEF ZCONST unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ unsigned n; /* number of codes (assumed <= N_MAX) */ unsigned s; /* number of simple-valued codes (0..s-1) */ ZCONST ush *d; /* list of base values for non-simple codes */ ZCONST uch *e; /* list of extra bits for non-simple codes */ struct huft **t; /* result: starting table */ unsigned *m; /* maximum lookup bits, returns actual */ /* Given a list of code lengths and a maximum table size, make a set of tables to decode that set of codes. Return zero on success, one if the given code set is incomplete (the tables are still built in this case), two if the input is invalid (all zero length codes or an oversubscribed set of lengths), and three if not enough memory. The code with value 256 is special, and the tables are constructed so that no bits beyond that code are fetched when that code is decoded. */ { unsigned a; /* counter for codes of length k */ unsigned c[BMAX+1]; /* bit length count table */ unsigned el; /* length of EOB code (value 256) */ unsigned f; /* i repeats in table every f entries */ int g; /* maximum code length */ int h; /* table level */ register unsigned i; /* counter, current code */ register unsigned j; /* counter */ register int k; /* number of bits in current code */ int lx[BMAX+1]; /* memory for l[-1..BMAX-1] */ int *l = lx+1; /* stack of bits per table */ register unsigned *p; /* pointer into c[], b[], or v[] */ register struct huft *q; /* points to current table */ struct huft r; /* table entry for structure assignment */ struct huft *u[BMAX]; /* table stack */ unsigned v[N_MAX]; /* values in order of bit length */ register int w; /* bits before this table == (l * h) */ unsigned x[BMAX+1]; /* bit offsets, then code stack */ unsigned *xp; /* pointer into x */ int y; /* number of dummy codes added */ unsigned z; /* number of entries in current table */ /* Generate counts for each bit length */ el = n > 256 ? b[256] : BMAX; /* set length of EOB code, if any */ memzero((char *)c, sizeof(c)); p = (unsigned *)b; i = n; do { c[*p]++; p++; /* assume all entries <= BMAX */ } while (--i); if (c[0] == n) /* null input--all zero length codes */ { *t = (struct huft *)NULL; *m = 0; return 0; } /* Find minimum and maximum length, bound *m by those */ for (j = 1; j <= BMAX; j++) if (c[j]) break; k = j; /* minimum code length */ if (*m < j) *m = j; for (i = BMAX; i; i--) if (c[i]) break; g = i; /* maximum code length */ if (*m > i) *m = i; /* Adjust last length count to fill out codes, if needed */ for (y = 1 << j; j < i; j++, y <<= 1) if ((y -= c[j]) < 0) return 2; /* bad input: more codes than bits */ if ((y -= c[i]) < 0) return 2; c[i] += y; /* Generate starting offsets into the value table for each length */ x[1] = j = 0; p = c + 1; xp = x + 2; while (--i) { /* note that i == g from above */ *xp++ = (j += *p++); } /* Make a table of values in order of bit lengths */ memzero((char *)v, sizeof(v)); p = (unsigned *)b; i = 0; do { if ((j = *p++) != 0) v[x[j]++] = i; } while (++i < n); n = x[g]; /* set n to length of v */ /* Generate the Huffman codes and for each, make the table entries */ x[0] = i = 0; /* first Huffman code is zero */ p = v; /* grab values in bit order */ h = -1; /* no tables yet--level -1 */ w = l[-1] = 0; /* no bits decoded yet */ u[0] = (struct huft *)NULL; /* just to keep compilers happy */ q = (struct huft *)NULL; /* ditto */ z = 0; /* ditto */ /* go through the bit lengths (k already is bits in shortest code) */ for (; k <= g; k++) { a = c[k]; while (a--) { /* here i is the Huffman code of length k bits for value *p */ /* make tables up to required level */ while (k > w + l[h]) { w += l[h++]; /* add bits already decoded */ /* compute minimum size table less than or equal to *m bits */ z = (z = g - w) > *m ? *m : z; /* upper limit */ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ { /* too few codes for k-w bit table */ f -= a + 1; /* deduct codes from patterns left */ xp = c + k; while (++j < z) /* try smaller tables up to z bits */ { if ((f <<= 1) <= *++xp) break; /* enough codes to use up j bits */ f -= *xp; /* else deduct codes from patterns */ } } if ((unsigned)w + j > el && (unsigned)w < el) j = el - w; /* make EOB code end at table */ z = 1 << j; /* table entries for j-bit table */ l[h] = j; /* set table size in stack */ /* allocate and link in new table */ if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) == (struct huft *)NULL) { if (h) huft_free(u[0]); return 3; /* not enough memory */ } #ifdef DEBUG G.hufts += z + 1; /* track memory usage */ #endif *t = q + 1; /* link to list for huft_free() */ *(t = &(q->v.t)) = (struct huft *)NULL; u[h] = ++q; /* table starts after link */ /* connect to last table, if there is one */ if (h) { x[h] = i; /* save pattern for backing up */ r.b = (uch)l[h-1]; /* bits to dump before this table */ r.e = (uch)(32 + j); /* bits in this table */ r.v.t = q; /* pointer to this table */ j = (i & ((1 << w) - 1)) >> (w - l[h-1]); u[h-1][j] = r; /* connect to last table */ } } /* set up table entry in r */ r.b = (uch)(k - w); if (p >= v + n) r.e = INVALID_CODE; /* out of values--invalid code */ else if (*p < s) { r.e = (uch)(*p < 256 ? 32 : 31); /* 256 is end-of-block code */ r.v.n = (ush)*p++; /* simple code is just the value */ } else { r.e = e[*p - s]; /* non-simple--look up in lists */ r.v.n = d[*p++ - s]; } /* fill code-like entries with r */ f = 1 << (k - w); for (j = i >> w; j < z; j += f) q[j] = r; /* backwards increment the k-bit code i */ for (j = 1 << (k - 1); i & j; j >>= 1) i ^= j; i ^= j; /* backup over finished tables */ while ((i & ((1 << w) - 1)) != x[h]) w -= l[--h]; /* don't need to update q */ } } /* return actual size of base table */ *m = l[0]; /* Return true (1) if we were given an incomplete table */ return y != 0 && g != 1; } int huft_free(t) struct huft *t; /* table to free */ /* Free the malloc'ed tables built by huft_build(), which makes a linked list of the tables it made, with the links in a dummy first entry of each table. */ { register struct huft *p, *q; /* Go through linked list, freeing from the malloced (t[-1]) address. */ p = t; while (p != (struct huft *)NULL) { q = (--p)->v.t; free((zvoid *)p); p = q; } return 0; } Carla-2.1/data/windows/unzipfx-carla-control/inflate.h000066400000000000000000000033051364475620200230470ustar00rootroot00000000000000/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* inflate.h for UnZip -- by Mark Adler version c14f, 23 November 1995 */ /* Copyright history: - Starting with UnZip 5.41 of 16-April-2000, this source file is covered by the Info-Zip LICENSE cited above. - Prior versions of this source file, found in UnZip source packages up to UnZip 5.40, were put in the public domain. The original copyright note by Mark Adler was: "You can do whatever you like with this source file, though I would prefer that if you modify it and redistribute it that you include comments to that effect with your name and the date. Thank you." History: vers date who what ---- --------- -------------- ------------------------------------ c14 12 Mar 93 M. Adler made inflate.c standalone with the introduction of inflate.h. c14d 28 Aug 93 G. Roelofs replaced flush/FlushOutput with new version c14e 29 Sep 93 G. Roelofs moved everything into unzip.h; added crypt.h c14f 23 Nov 95 G. Roelofs added UNZIP_INTERNAL to accommodate newly split unzip.h */ #define UNZIP_INTERNAL #include "unzip.h" /* provides slide[], typedefs and macros */ #ifdef FUNZIP # include "crypt.h" /* provides NEXTBYTE macro for crypt version of funzip */ #endif Carla-2.1/data/windows/unzipfx-carla-control/match.c000066400000000000000000000367721364475620200225320ustar00rootroot00000000000000/* Copyright (c) 1990-2005 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- match.c The match() routine recursively compares a string to a "pattern" (regular expression), returning TRUE if a match is found or FALSE if not. This version is specifically for use with unzip.c: as did the previous match() routines from SEA and J. Kercheval, it leaves the case (upper, lower, or mixed) of the string alone, but converts any uppercase characters in the pattern to lowercase if indicated by the global var pInfo->lcflag (which is to say, string is assumed to have been converted to lowercase already, if such was necessary). GRR: reversed order of text, pattern in matche() (now same as match()); added ignore_case/ic flags, Case() macro. PaulK: replaced matche() with recmatch() from Zip, modified to have an ignore_case argument; replaced test frame with simpler one. --------------------------------------------------------------------------- Copyright on recmatch() from Zip's util.c (although recmatch() was almost certainly written by Mark Adler...ask me how I can tell :-) ): Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly, Kai Uwe Rommel and Igor Mandrichenko. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as all of the original files are included unmodified, that it is not sold for profit, and that this copy- right notice is retained. --------------------------------------------------------------------------- Match the pattern (wildcard) against the string (fixed): match(string, pattern, ignore_case, sepc); returns TRUE if string matches pattern, FALSE otherwise. In the pattern: `*' matches any sequence of characters (zero or more) `?' matches any single character [SET] matches any character in the specified set, [!SET] or [^SET] matches any character not in the specified set. A set is composed of characters or ranges; a range looks like ``character hyphen character'' (as in 0-9 or A-Z). [0-9a-zA-Z_] is the minimal set of characters allowed in the [..] pattern construct. Other characters are allowed (i.e., 8-bit characters) if your system will support them. To suppress the special syntactic significance of any of ``[]*?!^-\'', in- side or outside a [..] construct, and match the character exactly, precede it with a ``\'' (backslash). Note that "*.*" and "*." are treated specially under MS-DOS if DOSWILD is defined. See the DOSWILD section below for an explanation. Note also that with VMSWILD defined, '%' is used instead of '?', and sets (ranges) are delimited by () instead of []. ---------------------------------------------------------------------------*/ #define __MATCH_C /* identifies this source module */ /* define ToLower() in here (for Unix, define ToLower to be macro (using * isupper()); otherwise just use tolower() */ #define UNZIP_INTERNAL #include "unzip.h" #ifndef THEOS /* the Theos port defines its own variant of match() */ #if 0 /* this is not useful until it matches Amiga names insensitively */ #ifdef AMIGA /* some other platforms might also want to use this */ # define ANSI_CHARSET /* MOVE INTO UNZIP.H EVENTUALLY */ #endif #endif /* 0 */ #ifdef ANSI_CHARSET # ifdef ToLower # undef ToLower # endif /* uppercase letters are values 41 thru 5A, C0 thru D6, and D8 thru DE */ # define IsUpper(c) (c>=0xC0 ? c<=0xDE && c!=0xD7 : c>=0x41 && c<=0x5A) # define ToLower(c) (IsUpper((uch) c) ? (unsigned) c | 0x20 : (unsigned) c) #endif #define Case(x) (ic? ToLower(x) : (x)) #ifdef VMSWILD # define WILDCHAR '%' # define BEG_RANGE '(' # define END_RANGE ')' #else # define WILDCHAR '?' # define BEG_RANGE '[' # define END_RANGE ']' #endif #if 0 /* GRR: add this to unzip.h someday... */ #if !(defined(MSDOS) && defined(DOSWILD)) #ifdef WILD_STOP_AT_DIR #define match(s,p,ic,sc) (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic,sc) == 1) #else #define match(s,p,ic) (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic) == 1) #endif int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, int ignore_case __WDLPRO)); #endif #endif /* 0 */ static int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, int ignore_case __WDLPRO)); static char *isshexp OF((ZCONST char *p)); static int namecmp OF((ZCONST char *s1, ZCONST char *s2)); /* match() is a shell to recmatch() to return only Boolean values. */ int match(string, pattern, ignore_case __WDL) ZCONST char *string, *pattern; int ignore_case; __WDLDEF { #if (defined(MSDOS) && defined(DOSWILD)) char *dospattern; int j = strlen(pattern); /*--------------------------------------------------------------------------- Optional MS-DOS preprocessing section: compare last three chars of the wildcard to "*.*" and translate to "*" if found; else compare the last two characters to "*." and, if found, scan the non-wild string for dots. If in the latter case a dot is found, return failure; else translate the "*." to "*". In either case, continue with the normal (Unix-like) match procedure after translation. (If not enough memory, default to normal match.) This causes "a*.*" and "a*." to behave as MS-DOS users expect. ---------------------------------------------------------------------------*/ if ((dospattern = (char *)malloc(j+1)) != NULL) { strcpy(dospattern, pattern); if (!strcmp(dospattern+j-3, "*.*")) { dospattern[j-2] = '\0'; /* nuke the ".*" */ } else if (!strcmp(dospattern+j-2, "*.")) { char *p = MBSCHR(string, '.'); if (p) { /* found a dot: match fails */ free(dospattern); return 0; } dospattern[j-1] = '\0'; /* nuke the end "." */ } j = recmatch((uch *)dospattern, (uch *)string, ignore_case __WDL); free(dospattern); return j == 1; } else #endif /* MSDOS && DOSWILD */ return recmatch((uch *)pattern, (uch *)string, ignore_case __WDL) == 1; } static int recmatch(p, s, ic __WDL) ZCONST uch *p; /* sh pattern to match */ ZCONST uch *s; /* string to which to match it */ int ic; /* true for case insensitivity */ __WDLDEF /* directory sepchar for WildStopAtDir mode, or 0 */ /* Recursively compare the sh pattern p with the string s and return 1 if * they match, and 0 or 2 if they don't or if there is a syntax error in the * pattern. This routine recurses on itself no more deeply than the number * of characters in the pattern. */ { unsigned int c; /* pattern char or start of range in [-] loop */ /* Get first character, the pattern for new recmatch calls follows */ c = *p; INCSTR(p); /* If that was the end of the pattern, match if string empty too */ if (c == 0) return *s == 0; /* '?' (or '%') matches any character (but not an empty string). */ if (c == WILDCHAR) #ifdef WILD_STOP_AT_DIR /* If uO.W_flag is non-zero, it won't match '/' */ return (*s && (!sepc || *s != (uch)sepc)) ? recmatch(p, s + CLEN(s), ic, sepc) : 0; #else return *s ? recmatch(p, s + CLEN(s), ic) : 0; #endif /* '*' matches any number of characters, including zero */ #ifdef AMIGA if (c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */ c = '*', p++; #endif /* AMIGA */ if (c == '*') { #ifdef WILD_STOP_AT_DIR if (sepc) { /* check for single "*" or double "**" */ # ifdef AMIGA if ((c = p[0]) == '#' && p[1] == '?') /* "#?" is Amiga-ese for "*" */ c = '*', p++; if (c != '*') { # else /* !AMIGA */ if (*p != '*') { # endif /* ?AMIGA */ /* single "*": this doesn't match the dirsep character */ for (; *s && *s != (uch)sepc; INCSTR(s)) if ((c = recmatch(p, s, ic, sepc)) != 0) return (int)c; /* end of pattern: matched if at end of string, else continue */ if (*p == '\0') return (*s == 0); /* continue to match if at sepc in pattern, else give up */ return (*p == (uch)sepc || (*p == '\\' && p[1] == (uch)sepc)) ? recmatch(p, s, ic, sepc) : 2; } /* "**": this matches slashes */ ++p; /* move p behind the second '*' */ /* and continue with the non-W_flag code variant */ } #endif /* WILD_STOP_AT_DIR */ if (*p == 0) return 1; if (isshexp((ZCONST char *)p) == NULL) { /* Optimization for rest of pattern being a literal string: * If there are no other shell expression chars in the rest * of the pattern behind the multi-char wildcard, then just * compare the literal string tail. */ ZCONST uch *srest; srest = s + (strlen((ZCONST char *)s) - strlen((ZCONST char *)p)); if (srest - s < 0) /* remaining literal string from pattern is longer than rest * of test string, there can't be a match */ return 0; else /* compare the remaining literal pattern string with the last * bytes of the test string to check for a match */ #ifdef _MBCS { ZCONST uch *q = s; /* MBCS-aware code must not scan backwards into a string from * the end. * So, we have to move forward by character from our well-known * character position s in the test string until we have * advanced to the srest position. */ while (q < srest) INCSTR(q); /* In case the byte *srest is a trailing byte of a multibyte * character in the test string s, we have actually advanced * past the position (srest). * For this case, the match has failed! */ if (q != srest) return 0; return ((ic ? namecmp((ZCONST char *)p, (ZCONST char *)q) : strcmp((ZCONST char *)p, (ZCONST char *)q) ) == 0); } #else /* !_MBCS */ return ((ic ? namecmp((ZCONST char *)p, (ZCONST char *)srest) : strcmp((ZCONST char *)p, (ZCONST char *)srest) ) == 0); #endif /* ?_MBCS */ } else { /* pattern contains more wildcards, continue with recursion... */ for (; *s; INCSTR(s)) if ((c = recmatch(p, s, ic __WDL)) != 0) return (int)c; return 2; /* 2 means give up--match will return false */ } } /* Parse and process the list of characters and ranges in brackets */ if (c == BEG_RANGE) { int e; /* flag true if next char to be taken literally */ ZCONST uch *q; /* pointer to end of [-] group */ int r; /* flag true to match anything but the range */ if (*s == 0) /* need a character to match */ return 0; p += (r = (*p == '!' || *p == '^')); /* see if reverse */ for (q = p, e = 0; *q; INCSTR(q)) /* find closing bracket */ if (e) e = 0; else if (*q == '\\') /* GRR: change to ^ for MS-DOS, OS/2? */ e = 1; else if (*q == END_RANGE) break; if (*q != END_RANGE) /* nothing matches if bad syntax */ return 0; for (c = 0, e = (*p == '-'); p < q; INCSTR(p)) { /* go through the list */ if (!e && *p == '\\') /* set escape flag if \ */ e = 1; else if (!e && *p == '-') /* set start of range if - */ c = *(p-1); else { unsigned int cc = Case(*s); if (*(p+1) != '-') for (c = c ? c : *p; c <= *p; c++) /* compare range */ if ((unsigned)Case(c) == cc) /* typecast for MSC bug */ return r ? 0 : recmatch(q + 1, s + 1, ic __WDL); c = e = 0; /* clear range, escape flags */ } } return r ? recmatch(q + CLEN(q), s + CLEN(s), ic __WDL) : 0; /* bracket match failed */ } /* if escape ('\\'), just compare next character */ if (c == '\\' && (c = *p++) == 0) /* if \ at end, then syntax error */ return 0; /* just a character--compare it */ #ifdef QDOS return QMatch(Case((uch)c), Case(*s)) ? recmatch(p, s + CLEN(s), ic __WDL) : 0; #else return Case((uch)c) == Case(*s) ? recmatch(p, s + CLEN(s), ic __WDL) : 0; #endif } /* end function recmatch() */ static char *isshexp(p) ZCONST char *p; /* If p is a sh expression, a pointer to the first special character is returned. Otherwise, NULL is returned. */ { for (; *p; INCSTR(p)) if (*p == '\\' && *(p+1)) p++; else if (*p == WILDCHAR || *p == '*' || *p == BEG_RANGE) return (char *)p; return NULL; } /* end function isshexp() */ static int namecmp(s1, s2) ZCONST char *s1, *s2; { int d; for (;;) { d = (int)ToLower((uch)*s1) - (int)ToLower((uch)*s2); if (d || *s1 == 0 || *s2 == 0) return d; s1++; s2++; } } /* end function namecmp() */ #endif /* !THEOS */ int iswild(p) /* originally only used for stat()-bug workaround in */ ZCONST char *p; /* VAX C, Turbo/Borland C, Watcom C, Atari MiNT libs; */ { /* now used in process_zipfiles() as well */ for (; *p; INCSTR(p)) if (*p == '\\' && *(p+1)) ++p; #ifdef THEOS else if (*p == '?' || *p == '*' || *p=='#'|| *p == '@') #else /* !THEOS */ #ifdef VMS else if (*p == '%' || *p == '*') #else /* !VMS */ #ifdef AMIGA else if (*p == '?' || *p == '*' || (*p=='#' && p[1]=='?') || *p == '[') #else /* !AMIGA */ else if (*p == '?' || *p == '*' || *p == '[') #endif /* ?AMIGA */ #endif /* ?VMS */ #endif /* ?THEOS */ #ifdef QDOS return (int)p; #else return TRUE; #endif return FALSE; } /* end function iswild() */ #ifdef TEST_MATCH #define put(s) {fputs(s,stdout); fflush(stdout);} #ifdef main # undef main #endif int main(int argc, char **argv) { char pat[256], str[256]; for (;;) { put("Pattern (return to exit): "); gets(pat); if (!pat[0]) break; for (;;) { put("String (return for new pattern): "); gets(str); if (!str[0]) break; printf("Case sensitive: %s insensitive: %s\n", match(str, pat, 0) ? "YES" : "NO", match(str, pat, 1) ? "YES" : "NO"); } } EXIT(0); } #endif /* TEST_MATCH */ Carla-2.1/data/windows/unzipfx-carla-control/process.c000066400000000000000000003250071364475620200231040ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- process.c This file contains the top-level routines for processing multiple zipfiles. Contains: process_zipfiles() free_G_buffers() do_seekable() file_size() rec_find() find_ecrec64() find_ecrec() process_zip_cmmnt() process_cdir_file_hdr() get_cdir_ent() process_local_file_hdr() getZip64Data() ef_scan_for_izux() getRISCOSexfield() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #ifdef WINDLL # ifdef POCKET_UNZIP # include "wince/intrface.h" # else # include "windll/windll.h" # endif #endif #if defined(DYNALLOC_CRCTAB) || defined(UNICODE_SUPPORT) # include "crc32.h" #endif #include "unzipfx/appDetails.h" static int do_seekable OF((__GPRO__ int lastchance)); #ifdef DO_SAFECHECK_2GB # ifdef USE_STRM_INPUT static zoff_t file_size OF((FILE *file)); # else static zoff_t file_size OF((int fh)); # endif #endif /* DO_SAFECHECK_2GB */ static int rec_find OF((__GPRO__ zoff_t, char *, int)); static int find_ecrec64 OF((__GPRO__ zoff_t searchlen)); static int find_ecrec OF((__GPRO__ zoff_t searchlen)); static int process_zip_cmmnt OF((__GPRO)); static int get_cdir_ent OF((__GPRO)); #ifdef IZ_HAVE_UXUIDGID static int read_ux3_value OF((ZCONST uch *dbuf, unsigned uidgid_sz, ulg *p_uidgid)); #endif /* IZ_HAVE_UXUIDGID */ static ZCONST char Far CannotAllocateBuffers[] = "error: cannot allocate unzip buffers\n"; #ifdef SFX static ZCONST char Far CannotFindMyself[] = "unzipsfx: cannot find myself! [%s]\n"; # ifdef CHEAP_SFX_AUTORUN static ZCONST char Far AutorunPrompt[] = "\nAuto-run command: %s\nExecute this command? [y/n] "; static ZCONST char Far NotAutoRunning[] = "Not executing auto-run command."; # endif #else /* !SFX */ /* process_zipfiles() strings */ # if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) static ZCONST char Far WarnInvalidTZ[] = "Warning: TZ environment variable not found, cannot use UTC times!!\n"; # endif # if !(defined(UNIX) || defined(AMIGA)) static ZCONST char Far CannotFindWildcardMatch[] = "%s: cannot find any matches for wildcard specification \"%s\".\n"; # endif /* !(UNIX || AMIGA) */ static ZCONST char Far FilesProcessOK[] = "%d archive%s successfully processed.\n"; static ZCONST char Far ArchiveWarning[] = "%d archive%s had warnings but no fatal errors.\n"; static ZCONST char Far ArchiveFatalError[] = "%d archive%s had fatal errors.\n"; static ZCONST char Far FileHadNoZipfileDir[] = "%d file%s had no zipfile directory.\n"; static ZCONST char Far ZipfileWasDir[] = "1 \"zipfile\" was a directory.\n"; static ZCONST char Far ManyZipfilesWereDir[] = "%d \"zipfiles\" were directories.\n"; static ZCONST char Far NoZipfileFound[] = "No zipfiles found.\n"; /* do_seekable() strings */ # ifdef UNIX static ZCONST char Far CannotFindZipfileDirMsg[] = "%s: cannot find zipfile directory in one of %s or\n\ %s%s.zip, and cannot find %s, period.\n"; static ZCONST char Far CannotFindEitherZipfile[] = "%s: cannot find or open %s, %s.zip or %s.\n"; # else /* !UNIX */ static ZCONST char Far CannotFindZipfileDirMsg[] = "%s: cannot find zipfile directory in %s,\n\ %sand cannot find %s, period.\n"; # ifdef VMS static ZCONST char Far CannotFindEitherZipfile[] = "%s: cannot find %s (%s).\n"; # else /* !VMS */ static ZCONST char Far CannotFindEitherZipfile[] = "%s: cannot find either %s or %s.\n"; # endif /* ?VMS */ # endif /* ?UNIX */ extern ZCONST char Far Zipnfo[]; /* in unzip.c */ #ifndef WINDLL static ZCONST char Far Unzip[] = "unzip"; #else static ZCONST char Far Unzip[] = "UnZip DLL"; #endif #ifdef DO_SAFECHECK_2GB static ZCONST char Far ZipfileTooBig[] = "Trying to read large file (> 2 GiB) without large file support\n"; #endif /* DO_SAFECHECK_2GB */ static ZCONST char Far MaybeExe[] = "note: %s may be a plain executable, not an archive\n"; static ZCONST char Far CentDirNotInZipMsg[] = "\n\ [%s]:\n\ Zipfile is disk %lu of a multi-disk archive, and this is not the disk on\n\ which the central zipfile directory begins (disk %lu).\n"; static ZCONST char Far EndCentDirBogus[] = "\nwarning [%s]: end-of-central-directory record claims this\n\ is disk %lu but that the central directory starts on disk %lu; this is a\n\ contradiction. Attempting to process anyway.\n"; # ifdef NO_MULTIPART static ZCONST char Far NoMultiDiskArcSupport[] = "\nerror [%s]: zipfile is part of multi-disk archive\n\ (sorry, not yet supported).\n"; static ZCONST char Far MaybePakBug[] = "warning [%s]:\ zipfile claims to be 2nd disk of a 2-part archive;\n\ attempting to process anyway. If no further errors occur, this archive\n\ was probably created by PAK v2.51 or earlier. This bug was reported to\n\ NoGate in March 1991 and was supposed to have been fixed by mid-1991; as\n\ of mid-1992 it still hadn't been. (If further errors do occur, archive\n\ was probably created by PKZIP 2.04c or later; UnZip does not yet support\n\ multi-part archives.)\n"; # else static ZCONST char Far MaybePakBug[] = "warning [%s]:\ zipfile claims to be last disk of a multi-part archive;\n\ attempting to process anyway, assuming all parts have been concatenated\n\ together in order. Expect \"errors\" and warnings...true multi-part support\ \n doesn't exist yet (coming soon).\n"; # endif static ZCONST char Far ExtraBytesAtStart[] = "warning [%s]: %s extra byte%s at beginning or within zipfile\n\ (attempting to process anyway)\n"; #endif /* ?SFX */ #if ((!defined(WINDLL) && !defined(SFX)) || !defined(NO_ZIPINFO)) static ZCONST char Far LogInitline[] = "Archive: %s\n"; #endif static ZCONST char Far MissingBytes[] = "error [%s]: missing %s bytes in zipfile\n\ (attempting to process anyway)\n"; static ZCONST char Far NullCentDirOffset[] = "error [%s]: NULL central directory offset\n\ (attempting to process anyway)\n"; static ZCONST char Far ZipfileEmpty[] = "warning [%s]: zipfile is empty\n"; static ZCONST char Far CentDirStartNotFound[] = "error [%s]: start of central directory not found;\n\ zipfile corrupt.\n%s"; static ZCONST char Far Cent64EndSigSearchErr[] = "fatal error: read failure while seeking for End-of-centdir-64 signature.\n\ This zipfile is corrupt.\n"; static ZCONST char Far Cent64EndSigSearchOff[] = "error: End-of-centdir-64 signature not where expected (prepended bytes?)\n\ (attempting to process anyway)\n"; #ifndef SFX static ZCONST char Far CentDirTooLong[] = "error [%s]: reported length of central directory is\n\ %s bytes too long (Atari STZip zipfile? J.H.Holm ZIPSPLIT 1.1\n\ zipfile?). Compensating...\n"; static ZCONST char Far CentDirEndSigNotFound[] = "\ End-of-central-directory signature not found. Either this file is not\n\ a zipfile, or it constitutes one disk of a multi-part archive. In the\n\ latter case the central directory and zipfile comment will be found on\n\ the last disk(s) of this archive.\n"; #else /* SFX */ static ZCONST char Far CentDirEndSigNotFound[] = " End-of-central-directory signature not found.\n"; #endif /* ?SFX */ #ifdef TIMESTAMP static ZCONST char Far ZipTimeStampFailed[] = "warning: cannot set time for %s\n"; static ZCONST char Far ZipTimeStampSuccess[] = "Updated time stamp for %s.\n"; #endif static ZCONST char Far ZipfileCommTrunc1[] = "\ncaution: zipfile comment truncated\n"; #ifndef NO_ZIPINFO static ZCONST char Far NoZipfileComment[] = "There is no zipfile comment.\n"; static ZCONST char Far ZipfileCommentDesc[] = "The zipfile comment is %u bytes long and contains the following text:\n"; static ZCONST char Far ZipfileCommBegin[] = "======================== zipfile comment begins\ ==========================\n"; static ZCONST char Far ZipfileCommEnd[] = "========================= zipfile comment ends\ ===========================\n"; static ZCONST char Far ZipfileCommTrunc2[] = "\n The zipfile comment is truncated.\n"; #endif /* !NO_ZIPINFO */ #ifdef UNICODE_SUPPORT static ZCONST char Far UnicodeVersionError[] = "\nwarning: Unicode Path version > 1\n"; static ZCONST char Far UnicodeMismatchError[] = "\nwarning: Unicode Path checksum invalid\n"; #endif /*******************************/ /* Function process_zipfiles() */ /*******************************/ int process_zipfiles(__G) /* return PK-type error code */ __GDEF { #ifndef SFX char *lastzipfn = (char *)NULL; int NumWinFiles, NumLoseFiles, NumWarnFiles; int NumMissDirs, NumMissFiles; #endif int error=0, error_in_archive=0; /*--------------------------------------------------------------------------- Start by allocating buffers and (re)constructing the various PK signature strings. ---------------------------------------------------------------------------*/ G.inbuf = (uch *)malloc(INBUFSIZ + 4); /* 4 extra for hold[] (below) */ G.outbuf = (uch *)malloc(OUTBUFSIZ + 1); /* 1 extra for string term. */ if ((G.inbuf == (uch *)NULL) || (G.outbuf == (uch *)NULL)) { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotAllocateBuffers))); return(PK_MEM); } G.hold = G.inbuf + INBUFSIZ; /* to check for boundary-spanning sigs */ #ifndef VMS /* VMS uses its own buffer scheme for textmode flush(). */ #ifdef SMALL_MEM G.outbuf2 = G.outbuf+RAWBUFSIZ; /* never changes */ #endif #endif /* !VMS */ #if 0 /* CRC_32_TAB has been NULLified by CONSTRUCTGLOBALS !!!! */ /* allocate the CRC table later when we know we can read zipfile data */ CRC_32_TAB = NULL; #endif /* 0 */ /* finish up initialization of magic signature strings */ local_hdr_sig[0] /* = extd_local_sig[0] */ = /* ASCII 'P', */ central_hdr_sig[0] = end_central_sig[0] = /* not EBCDIC */ end_centloc64_sig[0] = end_central64_sig[0] = 0x50; local_hdr_sig[1] /* = extd_local_sig[1] */ = /* ASCII 'K', */ central_hdr_sig[1] = end_central_sig[1] = /* not EBCDIC */ end_centloc64_sig[1] = end_central64_sig[1] = 0x4B; /*--------------------------------------------------------------------------- Make sure timezone info is set correctly; localtime() returns GMT on some OSes (e.g., Solaris 2.x) if this isn't done first. The ifdefs around tzset() were initially copied from dos_to_unix_time() in fileio.c. They may still be too strict; any listed OS that supplies tzset(), regardless of whether the function does anything, should be removed from the ifdefs. ---------------------------------------------------------------------------*/ #if (defined(WIN32) && defined(USE_EF_UT_TIME)) /* For the Win32 environment, we may have to "prepare" the environment prior to the tzset() call, to work around tzset() implementation bugs. */ iz_w32_prepareTZenv(); #endif #if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) # ifndef VALID_TIMEZONE # define VALID_TIMEZONE(tmp) \ (((tmp = getenv("TZ")) != NULL) && (*tmp != '\0')) # endif { char *p; G.tz_is_valid = VALID_TIMEZONE(p); # ifndef SFX if (!G.tz_is_valid) { Info(slide, 0x401, ((char *)slide, LoadFarString(WarnInvalidTZ))); error_in_archive = error = PK_WARN; } # endif /* !SFX */ } #endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */ /* For systems that do not have tzset() but supply this function using another name (_tzset() or something similar), an appropiate "#define tzset ..." should be added to the system specifc configuration section. */ #if (!defined(T20_VMS) && !defined(MACOS) && !defined(RISCOS) && !defined(QDOS)) #if (!defined(BSD) && !defined(MTS) && !defined(CMS_MVS) && !defined(TANDEM)) tzset(); #endif #endif /* Initialize UnZip's built-in pseudo hard-coded "ISO <--> OEM" translation, depending on the detected codepage setup. */ #ifdef NEED_ISO_OEM_INIT prepare_ISO_OEM_translat(__G); #endif /*--------------------------------------------------------------------------- Initialize the internal flag holding the mode of processing "overwrite existing file" cases. We do not use the calling interface flags directly because the overwrite mode may be changed by user interaction while processing archive files. Such a change should not affect the option settings as passed through the DLL calling interface. In case of conflicting options, the 'safer' flag uO.overwrite_none takes precedence. ---------------------------------------------------------------------------*/ G.overwrite_mode = (uO.overwrite_none ? OVERWRT_NEVER : (uO.overwrite_all ? OVERWRT_ALWAYS : OVERWRT_QUERY)); /*--------------------------------------------------------------------------- Match (possible) wildcard zipfile specification with existing files and attempt to process each. If no hits, try again after appending ".zip" suffix. If still no luck, give up. ---------------------------------------------------------------------------*/ #ifdef SFX if ((error = do_seekable(__G__ 0)) == PK_NOZIP) { #ifdef EXE_EXTENSION int len=strlen(G.argv0); /* append .exe if appropriate; also .sfx? */ if ( (G.zipfn = (char *)malloc(len+sizeof(EXE_EXTENSION))) != (char *)NULL ) { strcpy(G.zipfn, G.argv0); strcpy(G.zipfn+len, EXE_EXTENSION); error = do_seekable(__G__ 0); free(G.zipfn); G.zipfn = G.argv0; /* for "cannot find myself" message only */ } #endif /* EXE_EXTENSION */ #ifdef WIN32 G.zipfn = G.argv0; /* for "cannot find myself" message only */ #endif } if (error) { if (error == IZ_DIR) error_in_archive = PK_NOZIP; else error_in_archive = error; if (error == PK_NOZIP) Info(slide, 1, ((char *)slide, LoadFarString(CannotFindMyself), G.zipfn)); } #ifdef CHEAP_SFX_AUTORUN if (G.autorun_command[0] && !uO.qflag) { /* NO autorun without prompt! */ Info(slide, 0x81, ((char *)slide, LoadFarString(AutorunPrompt), FnFilter1(G.autorun_command))); if (fgets(G.answerbuf, 9, stdin) != (char *)NULL && toupper(*G.answerbuf) == 'Y') system(G.autorun_command); else Info(slide, 1, ((char *)slide, LoadFarString(NotAutoRunning))); } #endif /* CHEAP_SFX_AUTORUN */ int sfx_app_ret = sfx_app_autorun_now(); #else /* !SFX */ NumWinFiles = NumLoseFiles = NumWarnFiles = 0; NumMissDirs = NumMissFiles = 0; while ((G.zipfn = do_wild(__G__ G.wildzipfn)) != (char *)NULL) { Trace((stderr, "do_wild( %s ) returns %s\n", G.wildzipfn, G.zipfn)); lastzipfn = G.zipfn; /* print a blank line between the output of different zipfiles */ if (!uO.qflag && error != PK_NOZIP && error != IZ_DIR #ifdef TIMESTAMP && (!uO.T_flag || uO.zipinfo_mode) #endif && (NumWinFiles+NumLoseFiles+NumWarnFiles+NumMissFiles) > 0) (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); if ((error = do_seekable(__G__ 0)) == PK_WARN) ++NumWarnFiles; else if (error == IZ_DIR) ++NumMissDirs; else if (error == PK_NOZIP) ++NumMissFiles; else if (error != PK_OK) ++NumLoseFiles; else ++NumWinFiles; Trace((stderr, "do_seekable(0) returns %d\n", error)); if (error != IZ_DIR && error > error_in_archive) error_in_archive = error; #ifdef WINDLL if (error == IZ_CTRLC) { free_G_buffers(__G); return error; } #endif } /* end while-loop (wildcard zipfiles) */ if ((NumWinFiles + NumWarnFiles + NumLoseFiles) == 0 && (NumMissDirs + NumMissFiles) == 1 && lastzipfn != (char *)NULL) { #if (!defined(UNIX) && !defined(AMIGA)) /* filenames with wildcard characters */ if (iswild(G.wildzipfn)) { if (iswild(lastzipfn)) { NumMissDirs = NumMissFiles = 0; error_in_archive = PK_COOL; if (uO.qflag < 3) Info(slide, 0x401, ((char *)slide, LoadFarString(CannotFindWildcardMatch), LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), G.wildzipfn)); } } else #endif { #ifndef VMS /* 2004-11-24 SMS. * VMS has already tried a default file type of ".zip" in * do_wild(), so adding ZSUFX here only causes confusion by * corrupting some valid (though nonexistent) file names. * Complaining below about "fred;4.zip" is unlikely to be * helpful to the victim. */ /* 2005-08-14 Chr. Spieler * Although we already "know" the failure result, we call * do_seekable() again with the same zipfile name (and the * lastchance flag set), just to trigger the error report... */ #if defined(UNIX) || defined(QDOS) char *p = #endif strcpy(lastzipfn + strlen(lastzipfn), ZSUFX); #endif /* !VMS */ G.zipfn = lastzipfn; NumMissDirs = NumMissFiles = 0; error_in_archive = PK_COOL; #if defined(UNIX) || defined(QDOS) /* only Unix has case-sensitive filesystems */ /* Well FlexOS (sometimes) also has them, but support is per media */ /* and a pig to code for, so treat as case insensitive for now */ /* we do this under QDOS to check for .zip as well as _zip */ if ((error = do_seekable(__G__ 0)) == PK_NOZIP || error == IZ_DIR) { if (error == IZ_DIR) ++NumMissDirs; strcpy(p, ALT_ZSUFX); error = do_seekable(__G__ 1); } #else error = do_seekable(__G__ 1); #endif Trace((stderr, "do_seekable(1) returns %d\n", error)); switch (error) { case PK_WARN: ++NumWarnFiles; break; case IZ_DIR: ++NumMissDirs; error = PK_NOZIP; break; case PK_NOZIP: /* increment again => bug: "1 file had no zipfile directory." */ /* ++NumMissFiles */ ; break; default: if (error) ++NumLoseFiles; else ++NumWinFiles; break; } if (error > error_in_archive) error_in_archive = error; #ifdef WINDLL if (error == IZ_CTRLC) { free_G_buffers(__G); return error; } #endif } } #endif /* ?SFX */ /*--------------------------------------------------------------------------- Print summary of all zipfiles, assuming zipfile spec was a wildcard (no need for a summary if just one zipfile). ---------------------------------------------------------------------------*/ #ifndef SFX if (iswild(G.wildzipfn) && uO.qflag < 3 #ifdef TIMESTAMP && !(uO.T_flag && !uO.zipinfo_mode && uO.qflag > 1) #endif ) { if ((NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1) #ifdef TIMESTAMP && !(uO.T_flag && !uO.zipinfo_mode && uO.qflag) #endif && !(uO.tflag && uO.qflag > 1)) (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0x401); if ((NumWinFiles > 1) || (NumWinFiles == 1 && NumMissDirs + NumMissFiles + NumLoseFiles + NumWarnFiles > 0)) Info(slide, 0x401, ((char *)slide, LoadFarString(FilesProcessOK), NumWinFiles, (NumWinFiles == 1)? " was" : "s were")); if (NumWarnFiles > 0) Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveWarning), NumWarnFiles, (NumWarnFiles == 1)? "" : "s")); if (NumLoseFiles > 0) Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveFatalError), NumLoseFiles, (NumLoseFiles == 1)? "" : "s")); if (NumMissFiles > 0) Info(slide, 0x401, ((char *)slide, LoadFarString(FileHadNoZipfileDir), NumMissFiles, (NumMissFiles == 1)? "" : "s")); if (NumMissDirs == 1) Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileWasDir))); else if (NumMissDirs > 0) Info(slide, 0x401, ((char *)slide, LoadFarString(ManyZipfilesWereDir), NumMissDirs)); if (NumWinFiles + NumLoseFiles + NumWarnFiles == 0) Info(slide, 0x401, ((char *)slide, LoadFarString(NoZipfileFound))); } #endif /* !SFX */ /* free allocated memory */ free_G_buffers(__G); return sfx_app_ret; } /* end function process_zipfiles() */ /*****************************/ /* Function free_G_buffers() */ /*****************************/ void free_G_buffers(__G) /* releases all memory allocated in global vars */ __GDEF { #ifndef SFX unsigned i; #endif #ifdef SYSTEM_SPECIFIC_DTOR SYSTEM_SPECIFIC_DTOR(__G); #endif inflate_free(__G); checkdir(__G__ (char *)NULL, END); #ifdef DYNALLOC_CRCTAB if (CRC_32_TAB) { free_crc_table(); CRC_32_TAB = NULL; } #endif if (G.key != (char *)NULL) { free(G.key); G.key = (char *)NULL; } if (G.extra_field != (uch *)NULL) { free(G.extra_field); G.extra_field = (uch *)NULL; } #if (!defined(VMS) && !defined(SMALL_MEM)) /* VMS uses its own buffer scheme for textmode flush() */ if (G.outbuf2) { free(G.outbuf2); /* malloc'd ONLY if unshrink and -a */ G.outbuf2 = (uch *)NULL; } #endif if (G.outbuf) free(G.outbuf); if (G.inbuf) free(G.inbuf); G.inbuf = G.outbuf = (uch *)NULL; #ifdef UNICODE_SUPPORT if (G.filename_full) { free(G.filename_full); G.filename_full = (char *)NULL; G.fnfull_bufsize = 0; } #endif /* UNICODE_SUPPORT */ #ifndef SFX for (i = 0; i < DIR_BLKSIZ; i++) { if (G.info[i].cfilname != (char Far *)NULL) { zffree(G.info[i].cfilname); G.info[i].cfilname = (char Far *)NULL; } } #endif #ifdef MALLOC_WORK if (G.area.Slide) { free(G.area.Slide); G.area.Slide = (uch *)NULL; } #endif } /* end function free_G_buffers() */ /**************************/ /* Function do_seekable() */ /**************************/ static int do_seekable(__G__ lastchance) /* return PK-type error code */ __GDEF int lastchance; { #ifndef SFX /* static int no_ecrec = FALSE; SKM: moved to globals.h */ int maybe_exe=FALSE; int too_weird_to_continue=FALSE; #ifdef TIMESTAMP time_t uxstamp; ulg nmember = 0L; #endif #endif int error=0, error_in_archive; /*--------------------------------------------------------------------------- Open the zipfile for reading in BINARY mode to prevent CR/LF translation, which would corrupt the bit streams. ---------------------------------------------------------------------------*/ if (SSTAT(G.zipfn, &G.statbuf) || #ifdef THEOS (error = S_ISLIB(G.statbuf.st_mode)) != 0 || #endif (error = S_ISDIR(G.statbuf.st_mode)) != 0) { #ifndef SFX if (lastchance && (uO.qflag < 3)) { #if defined(UNIX) || defined(QDOS) if (G.no_ecrec) Info(slide, 1, ((char *)slide, LoadFarString(CannotFindZipfileDirMsg), LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), G.wildzipfn, uO.zipinfo_mode? " " : "", G.wildzipfn, G.zipfn)); else Info(slide, 1, ((char *)slide, LoadFarString(CannotFindEitherZipfile), LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), G.wildzipfn, G.wildzipfn, G.zipfn)); #else /* !(UNIX || QDOS) */ if (G.no_ecrec) Info(slide, 0x401, ((char *)slide, LoadFarString(CannotFindZipfileDirMsg), LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), G.wildzipfn, uO.zipinfo_mode? " " : "", G.zipfn)); else #ifdef VMS Info(slide, 0x401, ((char *)slide, LoadFarString(CannotFindEitherZipfile), LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), G.wildzipfn, (*G.zipfn ? G.zipfn : vms_msg_text()))); #else /* !VMS */ Info(slide, 0x401, ((char *)slide, LoadFarString(CannotFindEitherZipfile), LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), G.wildzipfn, G.zipfn)); #endif /* ?VMS */ #endif /* ?(UNIX || QDOS) */ } #endif /* !SFX */ return error? IZ_DIR : PK_NOZIP; } G.ziplen = G.statbuf.st_size; #ifndef SFX #if defined(UNIX) || defined(DOS_OS2_W32) || defined(THEOS) if (G.statbuf.st_mode & S_IEXEC) /* no extension on Unix exes: might */ maybe_exe = TRUE; /* find unzip, not unzip.zip; etc. */ #endif #endif /* !SFX */ #ifdef VMS if (check_format(__G)) /* check for variable-length format */ return PK_ERR; #endif if (open_input_file(__G)) /* this should never happen, given */ return PK_NOZIP; /* the stat() test above, but... */ #ifdef DO_SAFECHECK_2GB /* Need more care: Do not trust the size returned by stat() but determine it by reading beyond the end of the file. */ G.ziplen = file_size(G.zipfd); if (G.ziplen == EOF) { Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileTooBig))); /* printf( " We need a better error message for: 64-bit file, 32-bit program.\n"); */ CLOSE_INFILE(); return IZ_ERRBF; } #endif /* DO_SAFECHECK_2GB */ /*--------------------------------------------------------------------------- Find and process the end-of-central-directory header. UnZip need only check last 65557 bytes of zipfile: comment may be up to 65535, end-of- central-directory record is 18 bytes, and signature itself is 4 bytes; add some to allow for appended garbage. Since ZipInfo is often used as a debugging tool, search the whole zipfile if zipinfo_mode is true. ---------------------------------------------------------------------------*/ G.cur_zipfile_bufstart = 0; G.inptr = G.inbuf; #if ((!defined(WINDLL) && !defined(SFX)) || !defined(NO_ZIPINFO)) # if (!defined(WINDLL) && !defined(SFX)) if ( (!uO.zipinfo_mode && !uO.qflag # ifdef TIMESTAMP && !uO.T_flag # endif ) # ifndef NO_ZIPINFO || (uO.zipinfo_mode && uO.hflag) # endif ) # else /* not (!WINDLL && !SFX) ==> !NO_ZIPINFO !! */ if (uO.zipinfo_mode && uO.hflag) # endif /* if..else..: (!WINDLL && !SFX) */ # ifdef WIN32 /* Win32 console may require codepage conversion for G.zipfn */ Info(slide, 0, ((char *)slide, LoadFarString(LogInitline), FnFilter1(G.zipfn))); # else Info(slide, 0, ((char *)slide, LoadFarString(LogInitline), G.zipfn)); # endif #endif /* (!WINDLL && !SFX) || !NO_ZIPINFO */ if ( (error_in_archive = find_ecrec(__G__ #ifndef NO_ZIPINFO uO.zipinfo_mode ? G.ziplen : #endif MIN(G.ziplen, 66000L))) > PK_WARN ) { CLOSE_INFILE(); #ifdef SFX ++lastchance; /* avoid picky compiler warnings */ return error_in_archive; #else if (maybe_exe) Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeExe), G.zipfn)); if (lastchance) return error_in_archive; else { G.no_ecrec = TRUE; /* assume we found wrong file: e.g., */ return PK_NOZIP; /* unzip instead of unzip.zip */ } #endif /* ?SFX */ } if ((uO.zflag > 0) && !uO.zipinfo_mode) { /* unzip: zflag = comment ONLY */ CLOSE_INFILE(); return error_in_archive; } /*--------------------------------------------------------------------------- Test the end-of-central-directory info for incompatibilities (multi-disk archives) or inconsistencies (missing or extra bytes in zipfile). ---------------------------------------------------------------------------*/ #ifdef NO_MULTIPART error = !uO.zipinfo_mode && (G.ecrec.number_this_disk == 1) && (G.ecrec.num_disk_start_cdir == 1); #else error = !uO.zipinfo_mode && (G.ecrec.number_this_disk != 0); #endif #ifndef SFX if (uO.zipinfo_mode && G.ecrec.number_this_disk != G.ecrec.num_disk_start_cdir) { if (G.ecrec.number_this_disk > G.ecrec.num_disk_start_cdir) { Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirNotInZipMsg), G.zipfn, (ulg)G.ecrec.number_this_disk, (ulg)G.ecrec.num_disk_start_cdir)); error_in_archive = PK_FIND; too_weird_to_continue = TRUE; } else { Info(slide, 0x401, ((char *)slide, LoadFarString(EndCentDirBogus), G.zipfn, (ulg)G.ecrec.number_this_disk, (ulg)G.ecrec.num_disk_start_cdir)); error_in_archive = PK_WARN; } #ifdef NO_MULTIPART /* concatenation of multiple parts works in some cases */ } else if (!uO.zipinfo_mode && !error && G.ecrec.number_this_disk != 0) { Info(slide, 0x401, ((char *)slide, LoadFarString(NoMultiDiskArcSupport), G.zipfn)); error_in_archive = PK_FIND; too_weird_to_continue = TRUE; #endif } if (!too_weird_to_continue) { /* (relatively) normal zipfile: go for it */ if (error) { Info(slide, 0x401, ((char *)slide, LoadFarString(MaybePakBug), G.zipfn)); error_in_archive = PK_WARN; } #endif /* !SFX */ if ((G.extra_bytes = G.real_ecrec_offset-G.expect_ecrec_offset) < (zoff_t)0) { Info(slide, 0x401, ((char *)slide, LoadFarString(MissingBytes), G.zipfn, FmZofft((-G.extra_bytes), NULL, NULL))); error_in_archive = PK_ERR; } else if (G.extra_bytes > 0) { if ((G.ecrec.offset_start_central_directory == 0) && (G.ecrec.size_central_directory != 0)) /* zip 1.5 -go bug */ { Info(slide, 0x401, ((char *)slide, LoadFarString(NullCentDirOffset), G.zipfn)); G.ecrec.offset_start_central_directory = G.extra_bytes; G.extra_bytes = 0; error_in_archive = PK_ERR; } #ifndef SFX else { Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraBytesAtStart), G.zipfn, FmZofft(G.extra_bytes, NULL, NULL), (G.extra_bytes == 1)? "":"s")); error_in_archive = PK_WARN; } #endif /* !SFX */ } /*----------------------------------------------------------------------- Check for empty zipfile and exit now if so. -----------------------------------------------------------------------*/ if (G.expect_ecrec_offset==0L && G.ecrec.size_central_directory==0) { if (uO.zipinfo_mode) Info(slide, 0, ((char *)slide, "%sEmpty zipfile.\n", uO.lflag>9? "\n " : "")); else Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileEmpty), G.zipfn)); CLOSE_INFILE(); return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN; } /*----------------------------------------------------------------------- Compensate for missing or extra bytes, and seek to where the start of central directory should be. If header not found, uncompensate and try again (necessary for at least some Atari archives created with STZip, as well as archives created by J.H. Holm's ZIPSPLIT 1.1). -----------------------------------------------------------------------*/ error = seek_zipf(__G__ G.ecrec.offset_start_central_directory); if (error == PK_BADERR) { CLOSE_INFILE(); return PK_BADERR; } #ifdef OLD_SEEK_TEST if (error != PK_OK || readbuf(__G__ G.sig, 4) == 0) { CLOSE_INFILE(); return PK_ERR; /* file may be locked, or possibly disk error(?) */ } if (memcmp(G.sig, central_hdr_sig, 4)) #else if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) || memcmp(G.sig, central_hdr_sig, 4)) #endif { #ifndef SFX zoff_t tmp = G.extra_bytes; #endif G.extra_bytes = 0; error = seek_zipf(__G__ G.ecrec.offset_start_central_directory); if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) || memcmp(G.sig, central_hdr_sig, 4)) { if (error != PK_BADERR) Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirStartNotFound), G.zipfn, LoadFarStringSmall(ReportMsg))); CLOSE_INFILE(); return (error != PK_OK ? error : PK_BADERR); } #ifndef SFX Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong), G.zipfn, FmZofft((-tmp), NULL, NULL))); #endif error_in_archive = PK_ERR; } /*----------------------------------------------------------------------- Seek to the start of the central directory one last time, since we have just read the first entry's signature bytes; then list, extract or test member files as instructed, and close the zipfile. -----------------------------------------------------------------------*/ error = seek_zipf(__G__ G.ecrec.offset_start_central_directory); if (error != PK_OK) { CLOSE_INFILE(); return error; } Trace((stderr, "about to extract/list files (error = %d)\n", error_in_archive)); #ifdef DLL /* G.fValidate is used only to look at an archive to see if it appears to be a valid archive. There is no interest in what the archive contains, nor in validating that the entries in the archive are in good condition. This is currently used only in the Windows DLLs for purposes of checking archives within an archive to determine whether or not to display the inner archives. */ if (!G.fValidate) #endif { #ifndef NO_ZIPINFO if (uO.zipinfo_mode) error = zipinfo(__G); /* ZIPINFO 'EM */ else #endif #ifndef SFX #ifdef TIMESTAMP if (uO.T_flag) error = get_time_stamp(__G__ &uxstamp, &nmember); else #endif if (uO.vflag && !uO.tflag && !uO.cflag) error = list_files(__G); /* LIST 'EM */ else #endif /* !SFX */ error = extract_or_test_files(__G); /* EXTRACT OR TEST 'EM */ Trace((stderr, "done with extract/list files (error = %d)\n", error)); } if (error > error_in_archive) /* don't overwrite stronger error */ error_in_archive = error; /* with (for example) a warning */ #ifndef SFX } /* end if (!too_weird_to_continue) */ #endif CLOSE_INFILE(); #ifdef TIMESTAMP if (uO.T_flag && !uO.zipinfo_mode && (nmember > 0L)) { # ifdef WIN32 if (stamp_file(__G__ G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */ # else if (stamp_file(G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */ # endif if (uO.qflag < 3) Info(slide, 0x201, ((char *)slide, LoadFarString(ZipTimeStampFailed), G.zipfn)); if (error_in_archive < PK_WARN) error_in_archive = PK_WARN; } else { if (!uO.qflag) Info(slide, 0, ((char *)slide, LoadFarString(ZipTimeStampSuccess), G.zipfn)); } } #endif return error_in_archive; } /* end function do_seekable() */ #ifdef DO_SAFECHECK_2GB /************************/ /* Function file_size() */ /************************/ /* File size determination which does not mislead for large files in a small-file program. Probably should be somewhere else. The file has to be opened previously */ #ifdef USE_STRM_INPUT static zoff_t file_size(file) FILE *file; { int sts; size_t siz; #else /* !USE_STRM_INPUT */ static zoff_t file_size(fh) int fh; { int siz; #endif /* ?USE_STRM_INPUT */ zoff_t ofs; char waste[4]; #ifdef USE_STRM_INPUT /* Seek to actual EOF. */ sts = zfseeko(file, 0, SEEK_END); if (sts != 0) { /* fseeko() failed. (Unlikely.) */ ofs = EOF; } else { /* Get apparent offset at EOF. */ ofs = zftello(file); if (ofs < 0) { /* Offset negative (overflow). File too big. */ ofs = EOF; } else { /* Seek to apparent EOF offset. Won't be at actual EOF if offset was truncated. */ sts = zfseeko(file, ofs, SEEK_SET); if (sts != 0) { /* fseeko() failed. (Unlikely.) */ ofs = EOF; } else { /* Read a byte at apparent EOF. Should set EOF flag. */ siz = fread(waste, 1, 1, file); if (feof(file) == 0) { /* Not at EOF, but should be. File too big. */ ofs = EOF; } } } } #else /* !USE_STRM_INPUT */ /* Seek to actual EOF. */ ofs = zlseek(fh, 0, SEEK_END); if (ofs == (zoff_t) -1) { /* zlseek() failed. (Unlikely.) */ ofs = EOF; } else if (ofs < 0) { /* Offset negative (overflow). File too big. */ ofs = EOF; } else { /* Seek to apparent EOF offset. Won't be at actual EOF if offset was truncated. */ ofs = zlseek(fh, ofs, SEEK_SET); if (ofs == (zoff_t) -1) { /* zlseek() failed. (Unlikely.) */ ofs = EOF; } else { /* Read a byte at apparent EOF. Should set EOF flag. */ siz = read(fh, waste, 1); if (siz != 0) { /* Not at EOF, but should be. File too big. */ ofs = EOF; } } } #endif /* ?USE_STRM_INPUT */ return ofs; } /* end function file_size() */ #endif /* DO_SAFECHECK_2GB */ /***********************/ /* Function rec_find() */ /***********************/ static int rec_find(__G__ searchlen, signature, rec_size) /* return 0 when rec found, 1 when not found, 2 in case of read error */ __GDEF zoff_t searchlen; char* signature; int rec_size; { int i, numblks, found=FALSE; zoff_t tail_len; /*--------------------------------------------------------------------------- Zipfile is longer than INBUFSIZ: may need to loop. Start with short block at end of zipfile (if not TOO short). ---------------------------------------------------------------------------*/ if ((tail_len = G.ziplen % INBUFSIZ) > rec_size) { #ifdef USE_STRM_INPUT zfseeko(G.zipfd, G.ziplen-tail_len, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, G.ziplen-tail_len, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd, (char *)G.inbuf, (unsigned int)tail_len)) != (int)tail_len) return 2; /* it's expedient... */ /* 'P' must be at least (rec_size+4) bytes from end of zipfile */ for (G.inptr = G.inbuf+(int)tail_len-(rec_size+4); G.inptr >= G.inbuf; --G.inptr) { if ( (*G.inptr == (uch)0x50) && /* ASCII 'P' */ !memcmp((char *)G.inptr, signature, 4) ) { G.incnt -= (int)(G.inptr - G.inbuf); found = TRUE; break; } } /* sig may span block boundary: */ memcpy((char *)G.hold, (char *)G.inbuf, 3); } else G.cur_zipfile_bufstart = G.ziplen - tail_len; /*----------------------------------------------------------------------- Loop through blocks of zipfile data, starting at the end and going toward the beginning. In general, need not check whole zipfile for signature, but may want to do so if testing. -----------------------------------------------------------------------*/ numblks = (int)((searchlen - tail_len + (INBUFSIZ-1)) / INBUFSIZ); /* ==amount= ==done== ==rounding== =blksiz= */ for (i = 1; !found && (i <= numblks); ++i) { G.cur_zipfile_bufstart -= INBUFSIZ; #ifdef USE_STRM_INPUT zfseeko(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET); #else /* !USE_STRM_INPUT */ zlseek(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) != INBUFSIZ) return 2; /* read error is fatal failure */ for (G.inptr = G.inbuf+INBUFSIZ-1; G.inptr >= G.inbuf; --G.inptr) if ( (*G.inptr == (uch)0x50) && /* ASCII 'P' */ !memcmp((char *)G.inptr, signature, 4) ) { G.incnt -= (int)(G.inptr - G.inbuf); found = TRUE; break; } /* sig may span block boundary: */ memcpy((char *)G.hold, (char *)G.inbuf, 3); } return (found ? 0 : 1); } /* end function rec_find() */ #if 0 /********************************/ /* Function check_ecrec_zip64() */ /********************************/ static int check_ecrec_zip64(__G) __GDEF { return G.ecrec.offset_start_central_directory == 0xFFFFFFFFL || G.ecrec.size_central_directory == 0xFFFFFFFFL || G.ecrec.total_entries_central_dir == 0xFFFF || G.ecrec.num_entries_centrl_dir_ths_disk == 0xFFFF || G.ecrec.num_disk_start_cdir == 0xFFFF || G.ecrec.number_this_disk == 0xFFFF; } /* end function check_ecrec_zip64() */ #endif /* never */ /***************************/ /* Function find_ecrec64() */ /***************************/ static int find_ecrec64(__G__ searchlen) /* return PK-class error */ __GDEF zoff_t searchlen; { ec_byte_rec64 byterec; /* buf for ecrec64 */ ec_byte_loc64 byterecL; /* buf for ecrec64 locator */ zoff_t ecloc64_start_offset; /* start offset of ecrec64 locator */ zusz_t ecrec64_start_offset; /* start offset of ecrec64 */ zuvl_t ecrec64_start_disk; /* start disk of ecrec64 */ zuvl_t ecloc64_total_disks; /* total disks */ zuvl_t ecrec64_disk_cdstart; /* disk number of central dir start */ zucn_t ecrec64_this_entries; /* entries on disk with ecrec64 */ zucn_t ecrec64_tot_entries; /* total number of entries */ zusz_t ecrec64_cdirsize; /* length of central dir */ zusz_t ecrec64_offs_cdstart; /* offset of central dir start */ /* First, find the ecrec64 locator. By definition, this must be before ecrec with nothing in between. We back up the size of the ecrec64 locator and check. */ ecloc64_start_offset = G.real_ecrec_offset - (ECLOC64_SIZE+4); if (ecloc64_start_offset < 0) /* Seeking would go past beginning, so probably empty archive */ return PK_COOL; #ifdef USE_STRM_INPUT zfseeko(G.zipfd, ecloc64_start_offset, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, ecloc64_start_offset, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd, (char *)byterecL, ECLOC64_SIZE+4)) != (ECLOC64_SIZE+4)) { if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(Cent64EndSigSearchErr))); return PK_ERR; } if (memcmp((char *)byterecL, end_centloc64_sig, 4) ) { /* not found */ return PK_COOL; } /* Read the locator. */ ecrec64_start_disk = (zuvl_t)makelong(&byterecL[NUM_DISK_START_EOCDR64]); ecrec64_start_offset = (zusz_t)makeint64(&byterecL[OFFSET_START_EOCDR64]); ecloc64_total_disks = (zuvl_t)makelong(&byterecL[NUM_THIS_DISK_LOC64]); /* Check for consistency */ #ifdef TEST fprintf(stdout,"\nnumber of disks (ECR) %u, (ECLOC64) %lu\n", G.ecrec.number_this_disk, ecloc64_total_disks); fflush(stdout); #endif if ((G.ecrec.number_this_disk != 0xFFFF) && (G.ecrec.number_this_disk != ecloc64_total_disks - 1)) { /* Note: For some unknown reason, the developers at PKWARE decided to store the "zip64 total disks" value as a counter starting from 1, whereas all other "split/span volume" related fields use 0-based volume numbers. Sigh... */ /* When the total number of disks as found in the traditional ecrec is not 0xFFFF, the disk numbers in ecrec and ecloc64 must match. When this is not the case, the found ecrec64 locator cannot be valid. -> This is not a Zip64 archive. */ Trace((stderr, "\ninvalid ECLOC64, differing disk# (ECR %u, ECL64 %lu)\n", G.ecrec.number_this_disk, ecloc64_total_disks - 1)); return PK_COOL; } /* If found locator, look for ecrec64 where the locator says it is. */ /* For now assume that ecrec64 is on the same disk as ecloc64 and ecrec, which is usually the case and is how Zip writes it. To do this right, however, we should allow the ecrec64 to be on another disk since the AppNote allows it and the ecrec64 can be large, especially if Version 2 is used (AppNote uses 8 bytes for the size of this record). */ /* FIX BELOW IF ADD SUPPORT FOR MULTIPLE DISKS */ if (ecrec64_start_offset > (zusz_t)ecloc64_start_offset) { /* ecrec64 has to be before ecrec64 locator */ if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(Cent64EndSigSearchErr))); return PK_ERR; } #ifdef USE_STRM_INPUT zfseeko(G.zipfd, ecrec64_start_offset, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, ecrec64_start_offset, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd, (char *)byterec, ECREC64_SIZE+4)) != (ECREC64_SIZE+4)) { if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(Cent64EndSigSearchErr))); return PK_ERR; } if (memcmp((char *)byterec, end_central64_sig, 4) ) { /* Zip64 EOCD Record not found */ /* Since we already have seen the Zip64 EOCD Locator, it's possible we got here because there are bytes prepended to the archive, like the sfx prefix. */ /* Make a guess as to where the Zip64 EOCD Record might be */ ecrec64_start_offset = ecloc64_start_offset - ECREC64_SIZE - 4; #ifdef USE_STRM_INPUT zfseeko(G.zipfd, ecrec64_start_offset, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, ecrec64_start_offset, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd, (char *)byterec, ECREC64_SIZE+4)) != (ECREC64_SIZE+4)) { if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(Cent64EndSigSearchErr))); return PK_ERR; } if (memcmp((char *)byterec, end_central64_sig, 4) ) { /* Zip64 EOCD Record not found */ /* Probably something not so easy to handle so exit */ if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(Cent64EndSigSearchErr))); return PK_ERR; } if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(Cent64EndSigSearchOff))); } /* Check consistency of found ecrec64 with ecloc64 (and ecrec): */ if ( (zuvl_t)makelong(&byterec[NUMBER_THIS_DSK_REC64]) != ecrec64_start_disk ) /* found ecrec64 does not match ecloc64 info -> no Zip64 archive */ return PK_COOL; /* Read all relevant ecrec64 fields and compare them to the corresponding ecrec fields unless those are set to "all-ones". */ ecrec64_disk_cdstart = (zuvl_t)makelong(&byterec[NUM_DISK_START_CEN_DIR64]); if ( (G.ecrec.num_disk_start_cdir != 0xFFFF) && (G.ecrec.num_disk_start_cdir != ecrec64_disk_cdstart) ) return PK_COOL; ecrec64_this_entries = makeint64(&byterec[NUM_ENTRIES_CEN_DIR_THS_DISK64]); if ( (G.ecrec.num_entries_centrl_dir_ths_disk != 0xFFFF) && (G.ecrec.num_entries_centrl_dir_ths_disk != ecrec64_this_entries) ) return PK_COOL; ecrec64_tot_entries = makeint64(&byterec[TOTAL_ENTRIES_CENTRAL_DIR64]); if ( (G.ecrec.total_entries_central_dir != 0xFFFF) && (G.ecrec.total_entries_central_dir != ecrec64_tot_entries) ) return PK_COOL; ecrec64_cdirsize = makeint64(&byterec[SIZE_CENTRAL_DIRECTORY64]); if ( (G.ecrec.size_central_directory != 0xFFFFFFFFL) && (G.ecrec.size_central_directory != ecrec64_cdirsize) ) return PK_COOL; ecrec64_offs_cdstart = makeint64(&byterec[OFFSET_START_CENTRAL_DIRECT64]); if ( (G.ecrec.offset_start_central_directory != 0xFFFFFFFFL) && (G.ecrec.offset_start_central_directory != ecrec64_offs_cdstart) ) return PK_COOL; /* Now, we are (almost) sure that we have a Zip64 archive. */ G.ecrec.have_ecr64 = 1; /* Update the "end-of-central-dir offset" for later checks. */ G.real_ecrec_offset = ecrec64_start_offset; /* Update all ecdir_rec data that are flagged to be invalid in Zip64 mode. Set the ecrec64-mandatory flag when such a case is found. */ if (G.ecrec.number_this_disk == 0xFFFF) { G.ecrec.number_this_disk = ecrec64_start_disk; if (ecrec64_start_disk != 0xFFFF) G.ecrec.is_zip64_archive = TRUE; } if (G.ecrec.num_disk_start_cdir == 0xFFFF) { G.ecrec.num_disk_start_cdir = ecrec64_disk_cdstart; if (ecrec64_disk_cdstart != 0xFFFF) G.ecrec.is_zip64_archive = TRUE; } if (G.ecrec.num_entries_centrl_dir_ths_disk == 0xFFFF) { G.ecrec.num_entries_centrl_dir_ths_disk = ecrec64_this_entries; if (ecrec64_this_entries != 0xFFFF) G.ecrec.is_zip64_archive = TRUE; } if (G.ecrec.total_entries_central_dir == 0xFFFF) { G.ecrec.total_entries_central_dir = ecrec64_tot_entries; if (ecrec64_tot_entries != 0xFFFF) G.ecrec.is_zip64_archive = TRUE; } if (G.ecrec.size_central_directory == 0xFFFFFFFFL) { G.ecrec.size_central_directory = ecrec64_cdirsize; if (ecrec64_cdirsize != 0xFFFFFFFF) G.ecrec.is_zip64_archive = TRUE; } if (G.ecrec.offset_start_central_directory == 0xFFFFFFFFL) { G.ecrec.offset_start_central_directory = ecrec64_offs_cdstart; if (ecrec64_offs_cdstart != 0xFFFFFFFF) G.ecrec.is_zip64_archive = TRUE; } return PK_COOL; } /* end function find_ecrec64() */ /*************************/ /* Function find_ecrec() */ /*************************/ static int find_ecrec(__G__ searchlen) /* return PK-class error */ __GDEF zoff_t searchlen; { int found = FALSE; int error_in_archive; int result; ec_byte_rec byterec; /*--------------------------------------------------------------------------- Treat case of short zipfile separately. ---------------------------------------------------------------------------*/ if (G.ziplen <= INBUFSIZ) { #ifdef USE_STRM_INPUT zfseeko(G.zipfd, 0L, SEEK_SET); #else /* !USE_STRM_INPUT */ zlseek(G.zipfd, 0L, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd,(char *)G.inbuf,(unsigned int)G.ziplen)) == (int)G.ziplen) /* 'P' must be at least (ECREC_SIZE+4) bytes from end of zipfile */ for (G.inptr = G.inbuf+(int)G.ziplen-(ECREC_SIZE+4); G.inptr >= G.inbuf; --G.inptr) { if ( (*G.inptr == (uch)0x50) && /* ASCII 'P' */ !memcmp((char *)G.inptr, end_central_sig, 4)) { G.incnt -= (int)(G.inptr - G.inbuf); found = TRUE; break; } } /*--------------------------------------------------------------------------- Zipfile is longer than INBUFSIZ: MB - this next block of code moved to rec_find so that same code can be used to look for zip64 ec record. No need to include code above since a zip64 ec record will only be looked for if it is a BIG file. ---------------------------------------------------------------------------*/ } else { found = (rec_find(__G__ searchlen, end_central_sig, ECREC_SIZE) == 0 ? TRUE : FALSE); } /* end if (ziplen > INBUFSIZ) */ /*--------------------------------------------------------------------------- Searched through whole region where signature should be without finding it. Print informational message and die a horrible death. ---------------------------------------------------------------------------*/ if (!found) { if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirEndSigNotFound))); return PK_ERR; /* failed */ } /*--------------------------------------------------------------------------- Found the signature, so get the end-central data before returning. Do any necessary machine-type conversions (byte ordering, structure padding compensation) by reading data into character array and copying to struct. ---------------------------------------------------------------------------*/ G.real_ecrec_offset = G.cur_zipfile_bufstart + (G.inptr-G.inbuf); #ifdef TEST printf("\n found end-of-central-dir signature at offset %s (%sh)\n", FmZofft(G.real_ecrec_offset, NULL, NULL), FmZofft(G.real_ecrec_offset, FZOFFT_HEX_DOT_WID, "X")); printf(" from beginning of file; offset %d (%.4Xh) within block\n", G.inptr-G.inbuf, G.inptr-G.inbuf); #endif if (readbuf(__G__ (char *)byterec, ECREC_SIZE+4) == 0) return PK_EOF; G.ecrec.number_this_disk = makeword(&byterec[NUMBER_THIS_DISK]); G.ecrec.num_disk_start_cdir = makeword(&byterec[NUM_DISK_WITH_START_CEN_DIR]); G.ecrec.num_entries_centrl_dir_ths_disk = makeword(&byterec[NUM_ENTRIES_CEN_DIR_THS_DISK]); G.ecrec.total_entries_central_dir = makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]); G.ecrec.size_central_directory = makelong(&byterec[SIZE_CENTRAL_DIRECTORY]); G.ecrec.offset_start_central_directory = makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]); G.ecrec.zipfile_comment_length = makeword(&byterec[ZIPFILE_COMMENT_LENGTH]); /* Now, we have to read the archive comment, BEFORE the file pointer is moved away backwards to seek for a Zip64 ECLOC64 structure. */ if ( (error_in_archive = process_zip_cmmnt(__G)) > PK_WARN ) return error_in_archive; /* Next: Check for existence of Zip64 end-of-cent-dir locator ECLOC64. This structure must reside on the same volume as the classic ECREC, at exactly (ECLOC64_SIZE+4) bytes in front of the ECREC. The ECLOC64 structure directs to the longer ECREC64 structure A ECREC64 will ALWAYS exist for a proper Zip64 archive, as the "Version Needed To Extract" field is required to be set to 4.5 or higher whenever any Zip64 features are used anywhere in the archive, so just check for that to see if this is a Zip64 archive. */ result = find_ecrec64(__G__ searchlen+76); /* 76 bytes for zip64ec & zip64 locator */ if (result != PK_COOL) { if (error_in_archive < result) error_in_archive = result; return error_in_archive; } G.expect_ecrec_offset = G.ecrec.offset_start_central_directory + G.ecrec.size_central_directory; #ifndef NO_ZIPINFO if (uO.zipinfo_mode) { /* In ZipInfo mode, additional info about the data found in the end-of-central-directory areas is printed out. */ zi_end_central(__G); } #endif return error_in_archive; } /* end function find_ecrec() */ /********************************/ /* Function process_zip_cmmnt() */ /********************************/ static int process_zip_cmmnt(__G) /* return PK-type error code */ __GDEF { int error = PK_COOL; /*--------------------------------------------------------------------------- Get the zipfile comment (up to 64KB long), if any, and print it out. ---------------------------------------------------------------------------*/ #ifdef WINDLL /* for comment button: */ if ((!G.fValidate) && (G.lpUserFunctions != NULL)) G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length; #endif /* WINDLL */ #ifndef NO_ZIPINFO /* ZipInfo, verbose format */ if (uO.zipinfo_mode && uO.lflag > 9) { /*------------------------------------------------------------------- Get the zipfile comment, if any, and print it out. (Comment may be up to 64KB long. May the fleas of a thousand camels infest the arm-pits of anyone who actually takes advantage of this fact.) -------------------------------------------------------------------*/ if (!G.ecrec.zipfile_comment_length) Info(slide, 0, ((char *)slide, LoadFarString(NoZipfileComment))); else { Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommentDesc), G.ecrec.zipfile_comment_length)); Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommBegin))); if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) error = PK_WARN; Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommEnd))); if (error) Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommTrunc2))); } /* endif (comment exists) */ /* ZipInfo, non-verbose mode: print zipfile comment only if requested */ } else if (G.ecrec.zipfile_comment_length && (uO.zflag > 0) && uO.zipinfo_mode) { if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) { Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileCommTrunc1))); error = PK_WARN; } } else #endif /* !NO_ZIPINFO */ if ( G.ecrec.zipfile_comment_length && (uO.zflag > 0 #ifndef WINDLL || (uO.zflag == 0 # ifndef NO_ZIPINFO && !uO.zipinfo_mode # endif # ifdef TIMESTAMP && !uO.T_flag # endif && !uO.qflag) #endif /* !WINDLL */ ) ) { if (do_string(__G__ G.ecrec.zipfile_comment_length, #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) # ifndef NO_ZIPINFO (oU.zipinfo_mode ? DISPLAY : CHECK_AUTORUN) # else CHECK_AUTORUN # endif #else DISPLAY #endif )) { Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileCommTrunc1))); error = PK_WARN; } } #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) else if (G.ecrec.zipfile_comment_length) { if (do_string(__G__ G.ecrec.zipfile_comment_length, CHECK_AUTORUN_Q)) { Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileCommTrunc1))); error = PK_WARN; } } #endif return error; } /* end function process_zip_cmmnt() */ /************************************/ /* Function process_cdir_file_hdr() */ /************************************/ int process_cdir_file_hdr(__G) /* return PK-type error code */ __GDEF { int error; /*--------------------------------------------------------------------------- Get central directory info, save host and method numbers, and set flag for lowercase conversion of filename, depending on the OS from which the file is coming. ---------------------------------------------------------------------------*/ if ((error = get_cdir_ent(__G)) != 0) return error; G.pInfo->hostver = G.crec.version_made_by[0]; G.pInfo->hostnum = MIN(G.crec.version_made_by[1], NUM_HOSTS); /* extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */ G.pInfo->lcflag = 0; if (uO.L_flag == 1) /* name conversion for monocase systems */ switch (G.pInfo->hostnum) { case FS_FAT_: /* PKZIP and zip -k store in uppercase */ case CPM_: /* like MS-DOS, right? */ case VM_CMS_: /* all caps? */ case MVS_: /* all caps? */ case TANDEM_: case TOPS20_: case VMS_: /* our Zip uses lowercase, but ASi's doesn't */ /* case Z_SYSTEM_: ? */ /* case QDOS_: ? */ G.pInfo->lcflag = 1; /* convert filename to lowercase */ break; default: /* AMIGA_, FS_HPFS_, FS_NTFS_, MAC_, UNIX_, ATARI_, */ break; /* FS_VFAT_, ATHEOS_, BEOS_ (Z_SYSTEM_), THEOS_: */ /* no conversion */ } else if (uO.L_flag > 1) /* let -LL force lower case for all names */ G.pInfo->lcflag = 1; /* do Amigas (AMIGA_) also have volume labels? */ if (IS_VOLID(G.crec.external_file_attributes) && (G.pInfo->hostnum == FS_FAT_ || G.pInfo->hostnum == FS_HPFS_ || G.pInfo->hostnum == FS_NTFS_ || G.pInfo->hostnum == ATARI_)) { G.pInfo->vollabel = TRUE; G.pInfo->lcflag = 0; /* preserve case of volume labels */ } else G.pInfo->vollabel = FALSE; /* this flag is needed to detect archives made by "PKZIP for Unix" when deciding which kind of codepage conversion has to be applied to strings (see do_string() function in fileio.c) */ G.pInfo->HasUxAtt = (G.crec.external_file_attributes & 0xffff0000L) != 0L; #ifdef UNICODE_SUPPORT /* remember the state of GPB11 (General Purpuse Bit 11) which indicates that the standard path and comment are UTF-8. */ G.pInfo->GPFIsUTF8 = (G.crec.general_purpose_bit_flag & (1 << 11)) == (1 << 11); #endif return PK_COOL; } /* end function process_cdir_file_hdr() */ /***************************/ /* Function get_cdir_ent() */ /***************************/ static int get_cdir_ent(__G) /* return PK-type error code */ __GDEF { cdir_byte_hdr byterec; /*--------------------------------------------------------------------------- Read the next central directory entry and do any necessary machine-type conversions (byte ordering, structure padding compensation--do so by copying the data from the array into which it was read (byterec) to the usable struct (crec)). ---------------------------------------------------------------------------*/ if (readbuf(__G__ (char *)byterec, CREC_SIZE) == 0) return PK_EOF; G.crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0]; G.crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1]; G.crec.version_needed_to_extract[0] = byterec[C_VERSION_NEEDED_TO_EXTRACT_0]; G.crec.version_needed_to_extract[1] = byterec[C_VERSION_NEEDED_TO_EXTRACT_1]; G.crec.general_purpose_bit_flag = makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]); G.crec.compression_method = makeword(&byterec[C_COMPRESSION_METHOD]); G.crec.last_mod_dos_datetime = makelong(&byterec[C_LAST_MOD_DOS_DATETIME]); G.crec.crc32 = makelong(&byterec[C_CRC32]); G.crec.csize = makelong(&byterec[C_COMPRESSED_SIZE]); G.crec.ucsize = makelong(&byterec[C_UNCOMPRESSED_SIZE]); G.crec.filename_length = makeword(&byterec[C_FILENAME_LENGTH]); G.crec.extra_field_length = makeword(&byterec[C_EXTRA_FIELD_LENGTH]); G.crec.file_comment_length = makeword(&byterec[C_FILE_COMMENT_LENGTH]); G.crec.disk_number_start = makeword(&byterec[C_DISK_NUMBER_START]); G.crec.internal_file_attributes = makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]); G.crec.external_file_attributes = makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]); /* LONG, not word! */ G.crec.relative_offset_local_header = makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]); return PK_COOL; } /* end function get_cdir_ent() */ /*************************************/ /* Function process_local_file_hdr() */ /*************************************/ int process_local_file_hdr(__G) /* return PK-type error code */ __GDEF { local_byte_hdr byterec; /*--------------------------------------------------------------------------- Read the next local file header and do any necessary machine-type con- versions (byte ordering, structure padding compensation--do so by copy- ing the data from the array into which it was read (byterec) to the usable struct (lrec)). ---------------------------------------------------------------------------*/ if (readbuf(__G__ (char *)byterec, LREC_SIZE) == 0) return PK_EOF; G.lrec.version_needed_to_extract[0] = byterec[L_VERSION_NEEDED_TO_EXTRACT_0]; G.lrec.version_needed_to_extract[1] = byterec[L_VERSION_NEEDED_TO_EXTRACT_1]; G.lrec.general_purpose_bit_flag = makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]); G.lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]); G.lrec.last_mod_dos_datetime = makelong(&byterec[L_LAST_MOD_DOS_DATETIME]); G.lrec.crc32 = makelong(&byterec[L_CRC32]); G.lrec.csize = makelong(&byterec[L_COMPRESSED_SIZE]); G.lrec.ucsize = makelong(&byterec[L_UNCOMPRESSED_SIZE]); G.lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]); G.lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]); if ((G.lrec.general_purpose_bit_flag & 8) != 0) { /* can't trust local header, use central directory: */ G.lrec.crc32 = G.pInfo->crc; G.lrec.csize = G.pInfo->compr_size; G.lrec.ucsize = G.pInfo->uncompr_size; } G.csize = G.lrec.csize; return PK_COOL; } /* end function process_local_file_hdr() */ /*******************************/ /* Function getZip64Data() */ /*******************************/ int getZip64Data(__G__ ef_buf, ef_len) __GDEF ZCONST uch *ef_buf; /* buffer containing extra field */ unsigned ef_len; /* total length of extra field */ { unsigned eb_id; unsigned eb_len; /*--------------------------------------------------------------------------- This function scans the extra field for zip64 information, ie 8-byte versions of compressed file size, uncompressed file size, relative offset and a 4-byte version of disk start number. Sets both local header and central header fields. Not terribly clever, but it means that this procedure is only called in one place. ---------------------------------------------------------------------------*/ if (ef_len == 0 || ef_buf == NULL) return PK_COOL; Trace((stderr,"\ngetZip64Data: scanning extra field of length %u\n", ef_len)); while (ef_len >= EB_HEADSIZE) { eb_id = makeword(EB_ID + ef_buf); eb_len = makeword(EB_LEN + ef_buf); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ Trace((stderr, "getZip64Data: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } if (eb_id == EF_PKSZ64) { int offset = EB_HEADSIZE; if (G.crec.ucsize == 0xffffffff || G.lrec.ucsize == 0xffffffff){ G.lrec.ucsize = G.crec.ucsize = makeint64(offset + ef_buf); offset += sizeof(G.crec.ucsize); } if (G.crec.csize == 0xffffffff || G.lrec.csize == 0xffffffff){ G.csize = G.lrec.csize = G.crec.csize = makeint64(offset + ef_buf); offset += sizeof(G.crec.csize); } if (G.crec.relative_offset_local_header == 0xffffffff){ G.crec.relative_offset_local_header = makeint64(offset + ef_buf); offset += sizeof(G.crec.relative_offset_local_header); } if (G.crec.disk_number_start == 0xffff){ G.crec.disk_number_start = (zuvl_t)makelong(offset + ef_buf); offset += sizeof(G.crec.disk_number_start); } } /* Skip this extra field block */ ef_buf += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return PK_COOL; } /* end function getZip64Data() */ #ifdef UNICODE_SUPPORT /*******************************/ /* Function getUnicodeData() */ /*******************************/ int getUnicodeData(__G__ ef_buf, ef_len) __GDEF ZCONST uch *ef_buf; /* buffer containing extra field */ unsigned ef_len; /* total length of extra field */ { unsigned eb_id; unsigned eb_len; /*--------------------------------------------------------------------------- This function scans the extra field for Unicode information, ie UTF-8 path extra fields. On return, G.unipath_filename = NULL, if no Unicode path extra field or error "", if the standard path is UTF-8 (free when done) null-terminated UTF-8 path (free when done) Return PK_COOL if no error. ---------------------------------------------------------------------------*/ G.unipath_filename = NULL; if (ef_len == 0 || ef_buf == NULL) return PK_COOL; Trace((stderr,"\ngetUnicodeData: scanning extra field of length %u\n", ef_len)); while (ef_len >= EB_HEADSIZE) { eb_id = makeword(EB_ID + ef_buf); eb_len = makeword(EB_LEN + ef_buf); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ Trace((stderr, "getUnicodeData: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } if (eb_id == EF_UNIPATH) { int offset = EB_HEADSIZE; ush ULen = eb_len - 5; ulg chksum = CRCVAL_INITIAL; /* version */ G.unipath_version = (uch) *(offset + ef_buf); offset += 1; if (G.unipath_version > 1) { /* can do only version 1 */ Info(slide, 0x401, ((char *)slide, LoadFarString(UnicodeVersionError))); return PK_ERR; } /* filename CRC */ G.unipath_checksum = makelong(offset + ef_buf); offset += 4; /* * Compute 32-bit crc */ chksum = crc32(chksum, (uch *)(G.filename_full), strlen(G.filename_full)); /* If the checksums's don't match then likely filename has been * modified and the Unicode Path is no longer valid. */ if (chksum != G.unipath_checksum) { Info(slide, 0x401, ((char *)slide, LoadFarString(UnicodeMismatchError))); if (G.unicode_mismatch == 1) { /* warn and continue */ } else if (G.unicode_mismatch == 2) { /* ignore and continue */ } else if (G.unicode_mismatch == 0) { } return PK_ERR; } /* UTF-8 Path */ if ((G.unipath_filename = malloc(ULen + 1)) == NULL) { return PK_ERR; } if (ULen == 0) { /* standard path is UTF-8 so use that */ G.unipath_filename[0] = '\0'; } else { /* UTF-8 path */ strncpy(G.unipath_filename, (ZCONST char *)(offset + ef_buf), ULen); G.unipath_filename[ULen] = '\0'; } } /* Skip this extra field block */ ef_buf += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return PK_COOL; } /* end function getUnicodeData() */ #ifdef UNICODE_WCHAR /*--------------------------------------------- * Unicode conversion functions * * Based on functions provided by Paul Kienitz * *--------------------------------------------- */ /* NOTES APPLICABLE TO ALL STRING FUNCTIONS: All of the x_to_y functions take parameters for an output buffer and its available length, and return an int. The value returned is the length of the string that the input produces, which may be larger than the provided buffer length. If the returned value is less than the buffer length, then the contents of the buffer will be null-terminated; otherwise, it will not be terminated and may be invalid, possibly stopping in the middle of a multibyte sequence. In all cases you may pass NULL as the buffer and/or 0 as the length, if you just want to learn how much space the string is going to require. The functions will return -1 if the input is invalid UTF-8 or cannot be encoded as UTF-8. */ static int utf8_char_bytes OF((ZCONST char *utf8)); static ulg ucs4_char_from_utf8 OF((ZCONST char **utf8)); static int utf8_to_ucs4_string OF((ZCONST char *utf8, ulg *ucs4buf, int buflen)); /* utility functions for managing UTF-8 and UCS-4 strings */ /* utf8_char_bytes * * Returns the number of bytes used by the first character in a UTF-8 * string, or -1 if the UTF-8 is invalid or null. */ static int utf8_char_bytes(utf8) ZCONST char *utf8; { int t, r; unsigned lead; if (!utf8) return -1; /* no input */ lead = (unsigned char) *utf8; if (lead < 0x80) r = 1; /* an ascii-7 character */ else if (lead < 0xC0) return -1; /* error: trailing byte without lead byte */ else if (lead < 0xE0) r = 2; /* an 11 bit character */ else if (lead < 0xF0) r = 3; /* a 16 bit character */ else if (lead < 0xF8) r = 4; /* a 21 bit character (the most currently used) */ else if (lead < 0xFC) r = 5; /* a 26 bit character (shouldn't happen) */ else if (lead < 0xFE) r = 6; /* a 31 bit character (shouldn't happen) */ else return -1; /* error: invalid lead byte */ for (t = 1; t < r; t++) if ((unsigned char) utf8[t] < 0x80 || (unsigned char) utf8[t] >= 0xC0) return -1; /* error: not enough valid trailing bytes */ return r; } /* ucs4_char_from_utf8 * * Given a reference to a pointer into a UTF-8 string, returns the next * UCS-4 character and advances the pointer to the next character sequence. * Returns ~0 (= -1 in twos-complement notation) and does not advance the * pointer when input is ill-formed. */ static ulg ucs4_char_from_utf8(utf8) ZCONST char **utf8; { ulg ret; int t, bytes; if (!utf8) return ~0L; /* no input */ bytes = utf8_char_bytes(*utf8); if (bytes <= 0) return ~0L; /* invalid input */ if (bytes == 1) ret = **utf8; /* ascii-7 */ else ret = **utf8 & (0x7F >> bytes); /* lead byte of a multibyte sequence */ (*utf8)++; for (t = 1; t < bytes; t++) /* consume trailing bytes */ ret = (ret << 6) | (*((*utf8)++) & 0x3F); return (zwchar) ret; } #if 0 /* currently unused */ /* utf8_from_ucs4_char - Convert UCS char to UTF-8 * * Returns the number of bytes put into utf8buf to represent ch, from 1 to 6, * or -1 if ch is too large to represent. utf8buf must have room for 6 bytes. */ static int utf8_from_ucs4_char(utf8buf, ch) char *utf8buf; ulg ch; { int trailing = 0; int leadmask = 0x80; int leadbits = 0x3F; int tch = ch; int ret; if (ch > 0x7FFFFFFFL) return -1; /* UTF-8 can represent 31 bits */ if (ch < 0x7F) { *utf8buf++ = (char) ch; /* ascii-7 */ return 1; } do { trailing++; leadmask = (leadmask >> 1) | 0x80; leadbits >>= 1; tch >>= 6; } while (tch & ~leadbits); ret = trailing + 1; /* produce lead byte */ *utf8buf++ = (char) (leadmask | (ch >> (6 * trailing))); while (--trailing >= 0) /* produce trailing bytes */ *utf8buf++ = (char) (0x80 | ((ch >> (6 * trailing)) & 0x3F)); return ret; } #endif /* unused */ /*===================================================================*/ /* utf8_to_ucs4_string - convert UTF-8 string to UCS string * * Return UCS count. Now returns int so can return -1. */ static int utf8_to_ucs4_string(utf8, ucs4buf, buflen) ZCONST char *utf8; ulg *ucs4buf; int buflen; { int count = 0; for (;;) { ulg ch = ucs4_char_from_utf8(&utf8); if (ch == ~0L) return -1; else { if (ucs4buf && count < buflen) ucs4buf[count] = ch; if (ch == 0) return count; count++; } } } #if 0 /* currently unused */ /* ucs4_string_to_utf8 * * */ static int ucs4_string_to_utf8(ucs4, utf8buf, buflen) ZCONST ulg *ucs4; char *utf8buf; int buflen; { char mb[6]; int count = 0; if (!ucs4) return -1; for (;;) { int mbl = utf8_from_ucs4_char(mb, *ucs4++); int c; if (mbl <= 0) return -1; /* We could optimize this a bit by passing utf8buf + count */ /* directly to utf8_from_ucs4_char when buflen >= count + 6... */ c = buflen - count; if (mbl < c) c = mbl; if (utf8buf && count < buflen) strncpy(utf8buf + count, mb, c); if (mbl == 1 && !mb[0]) return count; /* terminating nul */ count += mbl; } } /* utf8_chars * * Wrapper: counts the actual unicode characters in a UTF-8 string. */ static int utf8_chars(utf8) ZCONST char *utf8; { return utf8_to_ucs4_string(utf8, NULL, 0); } #endif /* unused */ /* --------------------------------------------------- */ /* Unicode Support * * These functions common for all Unicode ports. * * These functions should allocate and return strings that can be * freed with free(). * * 8/27/05 EG * * Use zwchar for wide char which is unsigned long * in zip.h and 32 bits. This avoids problems with * different sizes of wchar_t. */ #if 0 /* currently unused */ /* is_ascii_string * Checks if a string is all ascii */ int is_ascii_string(mbstring) ZCONST char *mbstring; { char *p; uch c; for (p = mbstring; c = (uch)*p; p++) { if (c > 0x7F) { return 0; } } return 1; } /* local to UTF-8 */ char *local_to_utf8_string(local_string) ZCONST char *local_string; { return wide_to_utf8_string(local_to_wide_string(local_string)); } # endif /* unused */ /* wide_to_escape_string provides a string that represents a wide char not in local char set An initial try at an algorithm. Suggestions welcome. According to the standard, Unicode character points are restricted to the number range from 0 to 0x10FFFF, respective 21 bits. For a hexadecimal notation, 2 octets are sufficient for the mostly used characters from the "Basic Multilingual Plane", all other Unicode characters can be represented by 3 octets (= 6 hex digits). The Unicode standard suggests to write Unicode character points as 4 resp. 6 hex digits, preprended by "U+". (e.g.: U+10FFFF for the highest character point, or U+0030 for the ASCII digit "0") However, for the purpose of escaping non-ASCII chars in an ASCII character stream, the "U" is not a very good escape initializer. Therefore, we use the following convention within our Info-ZIP code: If not an ASCII char probably need 2 bytes at least. So if a 2-byte wide encode it as 4 hex digits with a leading #U. If needs 3 bytes then prefix the string with #L. So #U1234 is a 2-byte wide character with bytes 0x12 and 0x34 while #L123456 is a 3-byte wide character with bytes 0x12, 0x34, 0x56. On Windows, wide that need two wide characters need to be converted to a single number. */ /* set this to the max bytes an escape can be */ #define MAX_ESCAPE_BYTES 8 char *wide_to_escape_string(wide_char) zwchar wide_char; { int i; zwchar w = wide_char; uch b[sizeof(zwchar)]; char d[3]; char e[11]; int len; char *r; /* fill byte array with zeros */ memzero(b, sizeof(zwchar)); /* get bytes in right to left order */ for (len = 0; w; len++) { b[len] = (char)(w % 0x100); w /= 0x100; } strcpy(e, "#"); /* either 2 bytes or 3 bytes */ if (len <= 2) { len = 2; strcat(e, "U"); } else { strcat(e, "L"); } for (i = len - 1; i >= 0; i--) { sprintf(d, "%02x", b[i]); strcat(e, d); } if ((r = malloc(strlen(e) + 1)) == NULL) { return NULL; } strcpy(r, e); return r; } #if 0 /* currently unused */ /* returns the wide character represented by the escape string */ zwchar escape_string_to_wide(escape_string) ZCONST char *escape_string; { int i; zwchar w; char c; int len; ZCONST char *e = escape_string; if (e == NULL) { return 0; } if (e[0] != '#') { /* no leading # */ return 0; } len = strlen(e); /* either #U1234 or #L123456 format */ if (len != 6 && len != 8) { return 0; } w = 0; if (e[1] == 'L') { if (len != 8) { return 0; } /* 3 bytes */ for (i = 2; i < 8; i++) { c = e[i]; if (c < '0' || c > '9') { return 0; } w = w * 0x10 + (zwchar)(c - '0'); } } else if (e[1] == 'U') { /* 2 bytes */ for (i = 2; i < 6; i++) { c = e[i]; if (c < '0' || c > '9') { return 0; } w = w * 0x10 + (zwchar)(c - '0'); } } return w; } #endif /* unused */ #ifndef WIN32 /* WIN32 supplies a special variant of this function */ /* convert wide character string to multi-byte character string */ char *wide_to_local_string(wide_string, escape_all) ZCONST zwchar *wide_string; int escape_all; { int i; wchar_t wc; int b; int state_dependent; int wsize = 0; int max_bytes = MB_CUR_MAX; char buf[9]; char *buffer = NULL; char *local_string = NULL; for (wsize = 0; wide_string[wsize]; wsize++) ; if (max_bytes < MAX_ESCAPE_BYTES) max_bytes = MAX_ESCAPE_BYTES; if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) { return NULL; } /* convert it */ buffer[0] = '\0'; /* set initial state if state-dependent encoding */ wc = (wchar_t)'a'; b = wctomb(NULL, wc); if (b == 0) state_dependent = 0; else state_dependent = 1; for (i = 0; i < wsize; i++) { if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) { /* wchar_t probably 2 bytes */ /* could do surrogates if state_dependent and wctomb can do */ wc = zwchar_to_wchar_t_default_char; } else { wc = (wchar_t)wide_string[i]; } b = wctomb(buf, wc); if (escape_all) { if (b == 1 && (uch)buf[0] <= 0x7f) { /* ASCII */ strncat(buffer, buf, b); } else { /* use escape for wide character */ char *escape_string = wide_to_escape_string(wide_string[i]); strcat(buffer, escape_string); free(escape_string); } } else if (b > 0) { /* multi-byte char */ strncat(buffer, buf, b); } else { /* no MB for this wide */ /* use escape for wide character */ char *escape_string = wide_to_escape_string(wide_string[i]); strcat(buffer, escape_string); free(escape_string); } } if ((local_string = (char *)malloc(strlen(buffer) + 1)) != NULL) { strcpy(local_string, buffer); } free(buffer); return local_string; } #endif /* !WIN32 */ #if 0 /* currently unused */ /* convert local string to display character set string */ char *local_to_display_string(local_string) ZCONST char *local_string; { char *display_string; /* For Windows, OEM string should never be bigger than ANSI string, says CharToOem description. For all other ports, just make a copy of local_string. */ if ((display_string = (char *)malloc(strlen(local_string) + 1)) == NULL) { return NULL; } strcpy(display_string, local_string); #ifdef EBCDIC { char *ebc; if ((ebc = malloc(strlen(display_string) + 1)) == NULL) { return NULL; } strtoebc(ebc, display_string); free(display_string); display_string = ebc; } #endif return display_string; } #endif /* unused */ /* UTF-8 to local */ char *utf8_to_local_string(utf8_string, escape_all) ZCONST char *utf8_string; int escape_all; { zwchar *wide = utf8_to_wide_string(utf8_string); char *loc = wide_to_local_string(wide, escape_all); free(wide); return loc; } #if 0 /* currently unused */ /* convert multi-byte character string to wide character string */ zwchar *local_to_wide_string(local_string) ZCONST char *local_string; { int wsize; wchar_t *wc_string; zwchar *wide_string; /* for now try to convert as string - fails if a bad char in string */ wsize = mbstowcs(NULL, local_string, strlen(local_string) + 1); if (wsize == (size_t)-1) { /* could not convert */ return NULL; } /* convert it */ if ((wc_string = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t))) == NULL) { return NULL; } wsize = mbstowcs(wc_string, local_string, strlen(local_string) + 1); wc_string[wsize] = (wchar_t) 0; /* in case wchar_t is not zwchar */ if ((wide_string = (zwchar *)malloc((wsize + 1) * sizeof(zwchar))) == NULL) { return NULL; } for (wsize = 0; wide_string[wsize] = (zwchar)wc_string[wsize]; wsize++) ; wide_string[wsize] = (zwchar) 0; free(wc_string); return wide_string; } /* convert wide string to UTF-8 */ char *wide_to_utf8_string(wide_string) ZCONST zwchar *wide_string; { int mbcount; char *utf8_string; /* get size of utf8 string */ mbcount = ucs4_string_to_utf8(wide_string, NULL, 0); if (mbcount == -1) return NULL; if ((utf8_string = (char *) malloc(mbcount + 1)) == NULL) { return NULL; } mbcount = ucs4_string_to_utf8(wide_string, utf8_string, mbcount + 1); if (mbcount == -1) return NULL; return utf8_string; } #endif /* unused */ /* convert UTF-8 string to wide string */ zwchar *utf8_to_wide_string(utf8_string) ZCONST char *utf8_string; { int wcount; zwchar *wide_string; wcount = utf8_to_ucs4_string(utf8_string, NULL, 0); if (wcount == -1) return NULL; if ((wide_string = (zwchar *) malloc((wcount + 1) * sizeof(zwchar))) == NULL) { return NULL; } wcount = utf8_to_ucs4_string(utf8_string, wide_string, wcount + 1); return wide_string; } #endif /* UNICODE_WCHAR */ #endif /* UNICODE_SUPPORT */ #ifdef USE_EF_UT_TIME #ifdef IZ_HAVE_UXUIDGID static int read_ux3_value(dbuf, uidgid_sz, p_uidgid) ZCONST uch *dbuf; /* buffer a uid or gid value */ unsigned uidgid_sz; /* size of uid/gid value */ ulg *p_uidgid; /* return storage: uid or gid value */ { zusz_t uidgid64; switch (uidgid_sz) { case 2: *p_uidgid = (ulg)makeword(dbuf); break; case 4: *p_uidgid = (ulg)makelong(dbuf); break; case 8: uidgid64 = makeint64(dbuf); #ifndef LARGE_FILE_SUPPORT if (uidgid64 == (zusz_t)0xffffffffL) return FALSE; #endif *p_uidgid = (ulg)uidgid64; if ((zusz_t)(*p_uidgid) != uidgid64) return FALSE; break; } return TRUE; } #endif /* IZ_HAVE_UXUIDGID */ /*******************************/ /* Function ef_scan_for_izux() */ /*******************************/ unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime, z_utim, z_uidgid) ZCONST uch *ef_buf; /* buffer containing extra field */ unsigned ef_len; /* total length of extra field */ int ef_is_c; /* flag indicating "is central extra field" */ ulg dos_mdatetime; /* last_mod_file_date_time in DOS format */ iztimes *z_utim; /* return storage: atime, mtime, ctime */ ulg *z_uidgid; /* return storage: uid and gid */ { unsigned flags = 0; unsigned eb_id; unsigned eb_len; int have_new_type_eb = 0; long i_time; /* buffer for Unix style 32-bit integer time value */ #ifdef TIME_T_TYPE_DOUBLE int ut_in_archive_sgn = 0; #else int ut_zip_unzip_compatible = FALSE; #endif /*--------------------------------------------------------------------------- This function scans the extra field for EF_TIME, EF_IZUNIX2, EF_IZUNIX, or EF_PKUNIX blocks containing Unix-style time_t (GMT) values for the entry's access, creation, and modification time. If a valid block is found, the time stamps are copied to the iztimes structure (provided the z_utim pointer is not NULL). If a IZUNIX2 block is found or the IZUNIX block contains UID/GID fields, and the z_uidgid array pointer is valid (!= NULL), the owner info is transfered as well. The presence of an EF_TIME or EF_IZUNIX2 block results in ignoring all data from probably present obsolete EF_IZUNIX blocks. If multiple blocks of the same type are found, only the information from the last block is used. The return value is a combination of the EF_TIME Flags field with an additional flag bit indicating the presence of valid UID/GID info, or 0 in case of failure. ---------------------------------------------------------------------------*/ if (ef_len == 0 || ef_buf == NULL || (z_utim == 0 && z_uidgid == NULL)) return 0; TTrace((stderr,"\nef_scan_for_izux: scanning extra field of length %u\n", ef_len)); while (ef_len >= EB_HEADSIZE) { eb_id = makeword(EB_ID + ef_buf); eb_len = makeword(EB_LEN + ef_buf); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ TTrace((stderr, "ef_scan_for_izux: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } switch (eb_id) { case EF_TIME: flags &= ~0x0ff; /* ignore previous IZUNIX or EF_TIME fields */ have_new_type_eb = 1; if ( eb_len >= EB_UT_MINLEN && z_utim != NULL) { unsigned eb_idx = EB_UT_TIME1; TTrace((stderr,"ef_scan_for_izux: found TIME extra field\n")); flags |= (ef_buf[EB_HEADSIZE+EB_UT_FLAGS] & 0x0ff); if ((flags & EB_UT_FL_MTIME)) { if ((eb_idx+4) <= eb_len) { i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf); eb_idx += 4; TTrace((stderr," UT e.f. modification time = %ld\n", i_time)); #ifdef TIME_T_TYPE_DOUBLE if ((ulg)(i_time) & (ulg)(0x80000000L)) { if (dos_mdatetime == DOSTIME_MINIMUM) { ut_in_archive_sgn = -1; z_utim->mtime = (time_t)((long)i_time | (~(long)0x7fffffffL)); } else if (dos_mdatetime >= DOSTIME_2038_01_18) { ut_in_archive_sgn = 1; z_utim->mtime = (time_t)((ulg)i_time & (ulg)0xffffffffL); } else { ut_in_archive_sgn = 0; /* cannot determine sign of mtime; without modtime: ignore complete UT field */ flags &= ~0x0ff; /* no time_t times available */ TTrace((stderr, " UT modtime range error; ignore e.f.!\n")); break; /* stop scanning this field */ } } else { /* cannot determine, safe assumption is FALSE */ ut_in_archive_sgn = 0; z_utim->mtime = (time_t)i_time; } #else /* !TIME_T_TYPE_DOUBLE */ if ((ulg)(i_time) & (ulg)(0x80000000L)) { ut_zip_unzip_compatible = ((time_t)0x80000000L < (time_t)0L) ? (dos_mdatetime == DOSTIME_MINIMUM) : (dos_mdatetime >= DOSTIME_2038_01_18); if (!ut_zip_unzip_compatible) { /* UnZip interprets mtime differently than Zip; without modtime: ignore complete UT field */ flags &= ~0x0ff; /* no time_t times available */ TTrace((stderr, " UT modtime range error; ignore e.f.!\n")); break; /* stop scanning this field */ } } else { /* cannot determine, safe assumption is FALSE */ ut_zip_unzip_compatible = FALSE; } z_utim->mtime = (time_t)i_time; #endif /* ?TIME_T_TYPE_DOUBLE */ } else { flags &= ~EB_UT_FL_MTIME; TTrace((stderr," UT e.f. truncated; no modtime\n")); } } if (ef_is_c) { break; /* central version of TIME field ends here */ } if (flags & EB_UT_FL_ATIME) { if ((eb_idx+4) <= eb_len) { i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf); eb_idx += 4; TTrace((stderr," UT e.f. access time = %ld\n", i_time)); #ifdef TIME_T_TYPE_DOUBLE if ((ulg)(i_time) & (ulg)(0x80000000L)) { if (ut_in_archive_sgn == -1) z_utim->atime = (time_t)((long)i_time | (~(long)0x7fffffffL)); } else if (ut_in_archive_sgn == 1) { z_utim->atime = (time_t)((ulg)i_time & (ulg)0xffffffffL); } else { /* sign of 32-bit time is unknown -> ignore it */ flags &= ~EB_UT_FL_ATIME; TTrace((stderr, " UT access time range error: skip time!\n")); } } else { z_utim->atime = (time_t)i_time; } #else /* !TIME_T_TYPE_DOUBLE */ if (((ulg)(i_time) & (ulg)(0x80000000L)) && !ut_zip_unzip_compatible) { flags &= ~EB_UT_FL_ATIME; TTrace((stderr, " UT access time range error: skip time!\n")); } else { z_utim->atime = (time_t)i_time; } #endif /* ?TIME_T_TYPE_DOUBLE */ } else { flags &= ~EB_UT_FL_ATIME; } } if (flags & EB_UT_FL_CTIME) { if ((eb_idx+4) <= eb_len) { i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf); TTrace((stderr," UT e.f. creation time = %ld\n", i_time)); #ifdef TIME_T_TYPE_DOUBLE if ((ulg)(i_time) & (ulg)(0x80000000L)) { if (ut_in_archive_sgn == -1) z_utim->ctime = (time_t)((long)i_time | (~(long)0x7fffffffL)); } else if (ut_in_archive_sgn == 1) { z_utim->ctime = (time_t)((ulg)i_time & (ulg)0xffffffffL); } else { /* sign of 32-bit time is unknown -> ignore it */ flags &= ~EB_UT_FL_CTIME; TTrace((stderr, " UT creation time range error: skip time!\n")); } } else { z_utim->ctime = (time_t)i_time; } #else /* !TIME_T_TYPE_DOUBLE */ if (((ulg)(i_time) & (ulg)(0x80000000L)) && !ut_zip_unzip_compatible) { flags &= ~EB_UT_FL_CTIME; TTrace((stderr, " UT creation time range error: skip time!\n")); } else { z_utim->ctime = (time_t)i_time; } #endif /* ?TIME_T_TYPE_DOUBLE */ } else { flags &= ~EB_UT_FL_CTIME; } } } break; case EF_IZUNIX2: if (have_new_type_eb == 0) { flags &= ~0x0ff; /* ignore any previous IZUNIX field */ have_new_type_eb = 1; } #ifdef IZ_HAVE_UXUIDGID if (have_new_type_eb > 1) break; /* IZUNIX3 overrides IZUNIX2 e.f. block ! */ if (eb_len == EB_UX2_MINLEN && z_uidgid != NULL) { z_uidgid[0] = (ulg)makeword((EB_HEADSIZE+EB_UX2_UID) + ef_buf); z_uidgid[1] = (ulg)makeword((EB_HEADSIZE+EB_UX2_GID) + ef_buf); flags |= EB_UX2_VALID; /* signal success */ } #endif break; case EF_IZUNIX3: /* new 3rd generation Unix ef */ have_new_type_eb = 2; /* Version 1 byte version of this extra field, currently 1 UIDSize 1 byte Size of UID field UID Variable UID for this entry GIDSize 1 byte Size of GID field GID Variable GID for this entry */ #ifdef IZ_HAVE_UXUIDGID if (eb_len >= EB_UX3_MINLEN && z_uidgid != NULL && (*((EB_HEADSIZE + 0) + ef_buf) == 1) /* only know about version 1 */ { uch uid_size; uch gid_size; uid_size = *((EB_HEADSIZE + 1) + ef_buf); gid_size = *((EB_HEADSIZE + uid_size + 2) + ef_buf); flags &= ~0x0ff; /* ignore any previous UNIX field */ if ( read_ux3_value((EB_HEADSIZE + 2) + ef_buf, uid_size, z_uidgid[0]) && read_ux3_value((EB_HEADSIZE + uid_size + 3) + ef_buf, gid_size, z_uidgid[1]) ) { flags |= EB_UX2_VALID; /* signal success */ } } #endif /* IZ_HAVE_UXUIDGID */ break; case EF_IZUNIX: case EF_PKUNIX: /* PKUNIX e.f. layout is identical to IZUNIX */ if (eb_len >= EB_UX_MINLEN) { TTrace((stderr,"ef_scan_for_izux: found %s extra field\n", (eb_id == EF_IZUNIX ? "IZUNIX" : "PKUNIX"))); if (have_new_type_eb > 0) { break; /* Ignore IZUNIX extra field block ! */ } if (z_utim != NULL) { flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME); i_time = (long)makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf); TTrace((stderr," Unix EF modtime = %ld\n", i_time)); #ifdef TIME_T_TYPE_DOUBLE if ((ulg)(i_time) & (ulg)(0x80000000L)) { if (dos_mdatetime == DOSTIME_MINIMUM) { ut_in_archive_sgn = -1; z_utim->mtime = (time_t)((long)i_time | (~(long)0x7fffffffL)); } else if (dos_mdatetime >= DOSTIME_2038_01_18) { ut_in_archive_sgn = 1; z_utim->mtime = (time_t)((ulg)i_time & (ulg)0xffffffffL); } else { ut_in_archive_sgn = 0; /* cannot determine sign of mtime; without modtime: ignore complete UT field */ flags &= ~0x0ff; /* no time_t times available */ TTrace((stderr, " UX modtime range error: ignore e.f.!\n")); } } else { /* cannot determine, safe assumption is FALSE */ ut_in_archive_sgn = 0; z_utim->mtime = (time_t)i_time; } #else /* !TIME_T_TYPE_DOUBLE */ if ((ulg)(i_time) & (ulg)(0x80000000L)) { ut_zip_unzip_compatible = ((time_t)0x80000000L < (time_t)0L) ? (dos_mdatetime == DOSTIME_MINIMUM) : (dos_mdatetime >= DOSTIME_2038_01_18); if (!ut_zip_unzip_compatible) { /* UnZip interpretes mtime differently than Zip; without modtime: ignore complete UT field */ flags &= ~0x0ff; /* no time_t times available */ TTrace((stderr, " UX modtime range error: ignore e.f.!\n")); } } else { /* cannot determine, safe assumption is FALSE */ ut_zip_unzip_compatible = FALSE; } z_utim->mtime = (time_t)i_time; #endif /* ?TIME_T_TYPE_DOUBLE */ i_time = (long)makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf); TTrace((stderr," Unix EF actime = %ld\n", i_time)); #ifdef TIME_T_TYPE_DOUBLE if ((ulg)(i_time) & (ulg)(0x80000000L)) { if (ut_in_archive_sgn == -1) z_utim->atime = (time_t)((long)i_time | (~(long)0x7fffffffL)); } else if (ut_in_archive_sgn == 1) { z_utim->atime = (time_t)((ulg)i_time & (ulg)0xffffffffL); } else if (flags & 0x0ff) { /* sign of 32-bit time is unknown -> ignore it */ flags &= ~EB_UT_FL_ATIME; TTrace((stderr, " UX access time range error: skip time!\n")); } } else { z_utim->atime = (time_t)i_time; } #else /* !TIME_T_TYPE_DOUBLE */ if (((ulg)(i_time) & (ulg)(0x80000000L)) && !ut_zip_unzip_compatible && (flags & 0x0ff)) { /* atime not in range of UnZip's time_t */ flags &= ~EB_UT_FL_ATIME; TTrace((stderr, " UX access time range error: skip time!\n")); } else { z_utim->atime = (time_t)i_time; } #endif /* ?TIME_T_TYPE_DOUBLE */ } #ifdef IZ_HAVE_UXUIDGID if (eb_len >= EB_UX_FULLSIZE && z_uidgid != NULL) { z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX_UID) + ef_buf); z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX_GID) + ef_buf); flags |= EB_UX2_VALID; } #endif /* IZ_HAVE_UXUIDGID */ } break; default: break; } /* Skip this extra field block */ ef_buf += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return flags; } #endif /* USE_EF_UT_TIME */ #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS)) #define SPARKID_2 0x30435241 /* = "ARC0" */ /*******************************/ /* Function getRISCOSexfield() */ /*******************************/ zvoid *getRISCOSexfield(ef_buf, ef_len) ZCONST uch *ef_buf; /* buffer containing extra field */ unsigned ef_len; /* total length of extra field */ { unsigned eb_id; unsigned eb_len; /*--------------------------------------------------------------------------- This function scans the extra field for a Acorn SPARK filetype ef-block. If a valid block is found, the function returns a pointer to the start of the SPARK_EF block in the extra field buffer. Otherwise, a NULL pointer is returned. ---------------------------------------------------------------------------*/ if (ef_len == 0 || ef_buf == NULL) return NULL; Trace((stderr,"\ngetRISCOSexfield: scanning extra field of length %u\n", ef_len)); while (ef_len >= EB_HEADSIZE) { eb_id = makeword(EB_ID + ef_buf); eb_len = makeword(EB_LEN + ef_buf); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ Trace((stderr, "getRISCOSexfield: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } if (eb_id == EF_SPARK && (eb_len == 24 || eb_len == 20)) { if (makelong(EB_HEADSIZE + ef_buf) == SPARKID_2) { /* Return a pointer to the valid SPARK filetype ef block */ return (zvoid *)ef_buf; } } /* Skip this extra field block */ ef_buf += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return NULL; } #endif /* (RISCOS || ACORN_FTYPE_NFS) */ Carla-2.1/data/windows/unzipfx-carla-control/ttyio.c000066400000000000000000000510341364475620200225720ustar00rootroot00000000000000/* Copyright (c) 1990-2008 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- ttyio.c This file contains routines for doing console input/output, including code for non-echoing input. It is used by the encryption/decryption code but does not contain any restricted code itself. This file is shared between Info-ZIP's Zip and UnZip. Contains: echo() (VMS only) Echon() (Unix only) Echoff() (Unix only) screensize() (Unix only) zgetch() (Unix, VMS, and non-Unix/VMS versions) getp() ("PC," Unix/Atari/Be, VMS/VMCMS/MVS) ---------------------------------------------------------------------------*/ #define __TTYIO_C /* identifies this source module */ #include "zip.h" #include "crypt.h" #if (CRYPT || (defined(UNZIP) && !defined(FUNZIP))) /* Non-echo console/keyboard input is needed for (en/de)cryption's password * entry, and for UnZip(SFX)'s MORE and Pause features. * (The corresponding #endif is found at the end of this module.) */ #include "ttyio.h" #ifndef PUTC # define PUTC putc #endif #ifdef ZIP # ifdef GLOBAL /* used in Amiga system headers, maybe others too */ # undef GLOBAL # endif # define GLOBAL(g) g #else # define GLOBAL(g) G.g #endif #if (defined(__ATHEOS__) || defined(__BEOS__)) /* why yes, we do */ # define HAVE_TERMIOS_H #endif #ifdef _POSIX_VERSION # ifndef USE_POSIX_TERMIOS # define USE_POSIX_TERMIOS /* use POSIX style termio (termios) */ # endif # ifndef HAVE_TERMIOS_H # define HAVE_TERMIOS_H /* POSIX termios.h */ # endif #endif /* _POSIX_VERSION */ #ifdef UNZIP /* Zip handles this with the unix/configure script */ # ifndef _POSIX_VERSION # if (defined(SYSV) || defined(CRAY)) && !defined(__MINT__) # ifndef USE_SYSV_TERMIO # define USE_SYSV_TERMIO # endif # ifdef COHERENT # ifndef HAVE_TERMIO_H # define HAVE_TERMIO_H # endif # ifdef HAVE_SYS_TERMIO_H # undef HAVE_SYS_TERMIO_H # endif # else /* !COHERENT */ # ifdef HAVE_TERMIO_H # undef HAVE_TERMIO_H # endif # ifndef HAVE_SYS_TERMIO_H # define HAVE_SYS_TERMIO_H # endif # endif /* ?COHERENT */ # endif /* (SYSV || CRAY) && !__MINT__ */ # endif /* !_POSIX_VERSION */ # if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__)) # ifndef NO_FCNTL_H # define NO_FCNTL_H # endif # endif /* !(BSD4_4 || SYSV || __convexc__) */ #endif /* UNZIP */ #ifdef HAVE_TERMIOS_H # ifndef USE_POSIX_TERMIOS # define USE_POSIX_TERMIOS # endif #endif #if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H)) # ifndef USE_SYSV_TERMIO # define USE_SYSV_TERMIO # endif #endif #if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE)) # include # define GOT_IOCTL_H /* int ioctl OF((int, int, zvoid *)); GRR: may need for some systems */ #endif #ifndef HAVE_WORKING_GETCH /* include system support for switching of console echo */ # ifdef VMS # include # include # include /* Workaround for broken header files of older DECC distributions * that are incompatible with the /NAMES=AS_IS qualifier. */ # define sys$assign SYS$ASSIGN # define sys$dassgn SYS$DASSGN # define sys$qiow SYS$QIOW # include # include # else /* !VMS */ # ifdef HAVE_TERMIOS_H # include # define sgttyb termios # define sg_flags c_lflag # define GTTY(f, s) tcgetattr(f, (zvoid *) s) # define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s) # else /* !HAVE_TERMIOS_H */ # ifdef USE_SYSV_TERMIO /* Amdahl, Cray, all SysV? */ # ifdef HAVE_TERMIO_H # include # endif # ifdef HAVE_SYS_TERMIO_H # include # endif # ifdef NEED_PTEM # include # include # endif # define sgttyb termio # define sg_flags c_lflag # define GTTY(f,s) ioctl(f,TCGETA,(zvoid *)s) # define STTY(f,s) ioctl(f,TCSETAW,(zvoid *)s) # else /* !USE_SYSV_TERMIO */ # ifndef CMS_MVS # if (!defined(MINIX) && !defined(GOT_IOCTL_H)) # include # endif # include # define GTTY gtty # define STTY stty # ifdef UNZIP /* * XXX : Are these declarations needed at all ???? */ /* * GRR: let's find out... Hmmm, appears not... int gtty OF((int, struct sgttyb *)); int stty OF((int, struct sgttyb *)); */ # endif # endif /* !CMS_MVS */ # endif /* ?USE_SYSV_TERMIO */ # endif /* ?HAVE_TERMIOS_H */ # ifndef NO_FCNTL_H # ifndef UNZIP # include # endif # else char *ttyname OF((int)); # endif # endif /* ?VMS */ #endif /* !HAVE_WORKING_GETCH */ #ifndef HAVE_WORKING_GETCH #ifdef VMS static struct dsc$descriptor_s DevDesc = {11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND"}; /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */ /* * Turn keyboard echoing on or off (VMS). Loosely based on VMSmunch.c * and hence on Joe Meadows' file.c code. */ int echo(opt) int opt; { /* * For VMS v5.x: * IO$_SENSEMODE/SETMODE info: Programming, Vol. 7A, System Programming, * I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6 * sys$assign(), sys$qio() info: Programming, Vol. 4B, System Services, * System Services Reference Manual, pp. sys-23, sys-379 * fixed-length descriptor info: Programming, Vol. 3, System Services, * Intro to System Routines, sec. 2.9.2 * Greg Roelofs, 15 Aug 91 */ short DevChan, iosb[4]; long status; unsigned long ttmode[2]; /* space for 8 bytes */ /* assign a channel to standard input */ status = sys$assign(&DevDesc, &DevChan, 0, 0); if (!(status & 1)) return status; /* use sys$qio and the IO$_SENSEMODE function to determine the current * tty status (for password reading, could use IO$_READVBLK function * instead, but echo on/off will be more general) */ status = sys$qiow(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0, ttmode, 8, 0, 0, 0, 0); if (!(status & 1)) return status; status = iosb[0]; if (!(status & 1)) return status; /* modify mode buffer to be either NOECHO or ECHO * (depending on function argument opt) */ if (opt == 0) /* off */ ttmode[1] |= TT$M_NOECHO; /* set NOECHO bit */ else ttmode[1] &= ~((unsigned long) TT$M_NOECHO); /* clear NOECHO bit */ /* use the IO$_SETMODE function to change the tty status */ status = sys$qiow(0, DevChan, IO$_SETMODE, &iosb, 0, 0, ttmode, 8, 0, 0, 0, 0); if (!(status & 1)) return status; status = iosb[0]; if (!(status & 1)) return status; /* deassign the sys$input channel by way of clean-up */ status = sys$dassgn(DevChan); if (!(status & 1)) return status; return SS$_NORMAL; /* we be happy */ } /* end function echo() */ /* * Read a single character from keyboard in non-echoing mode (VMS). * (returns EOF in case of errors) */ int tt_getch() { short DevChan, iosb[4]; long status; char kbbuf[16]; /* input buffer with - some - excess length */ /* assign a channel to standard input */ status = sys$assign(&DevDesc, &DevChan, 0, 0); if (!(status & 1)) return EOF; /* read a single character from SYS$COMMAND (no-echo) and * wait for completion */ status = sys$qiow(0,DevChan, IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR, &iosb, 0, 0, &kbbuf, 1, 0, 0, 0, 0); if ((status&1) == 1) status = iosb[0]; /* deassign the sys$input channel by way of clean-up * (for this step, we do not need to check the completion status) */ sys$dassgn(DevChan); /* return the first char read, or EOF in case the read request failed */ return (int)(((status&1) == 1) ? (uch)kbbuf[0] : EOF); } /* end function tt_getch() */ #else /* !VMS: basically Unix */ /* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */ #ifndef CMS_MVS #ifdef ZIP /* moved to globals.h for UnZip */ static int echofd=(-1); /* file descriptor whose echo is off */ #endif /* * Turn echo off for file descriptor f. Assumes that f is a tty device. */ void Echoff(__G__ f) __GDEF int f; /* file descriptor for which to turn echo off */ { struct sgttyb sg; /* tty device structure */ GLOBAL(echofd) = f; GTTY(f, &sg); /* get settings */ sg.sg_flags &= ~ECHO; /* turn echo off */ STTY(f, &sg); } /* * Turn echo back on for file descriptor echofd. */ void Echon(__G) __GDEF { struct sgttyb sg; /* tty device structure */ if (GLOBAL(echofd) != -1) { GTTY(GLOBAL(echofd), &sg); /* get settings */ sg.sg_flags |= ECHO; /* turn echo on */ STTY(GLOBAL(echofd), &sg); GLOBAL(echofd) = -1; } } #endif /* !CMS_MVS */ #endif /* ?VMS */ #if (defined(UNZIP) && !defined(FUNZIP)) #ifdef ATH_BEO_UNX #ifdef MORE /* * Get the number of lines on the output terminal. SCO Unix apparently * defines TIOCGWINSZ but doesn't support it (!M_UNIX). * * GRR: will need to know width of terminal someday, too, to account for * line-wrapping. */ #if (defined(TIOCGWINSZ) && !defined(M_UNIX)) int screensize(tt_rows, tt_cols) int *tt_rows; int *tt_cols; { struct winsize wsz; #ifdef DEBUG_WINSZ static int firsttime = TRUE; #endif /* see termio(4) under, e.g., SunOS */ if (ioctl(1, TIOCGWINSZ, &wsz) == 0) { #ifdef DEBUG_WINSZ if (firsttime) { firsttime = FALSE; fprintf(stderr, "ttyio.c screensize(): ws_row = %d\n", wsz.ws_row); fprintf(stderr, "ttyio.c screensize(): ws_col = %d\n", wsz.ws_col); } #endif /* number of rows */ if (tt_rows != NULL) *tt_rows = (int)((wsz.ws_row > 0) ? wsz.ws_row : 24); /* number of columns */ if (tt_cols != NULL) *tt_cols = (int)((wsz.ws_col > 0) ? wsz.ws_col : 80); return 0; /* signal success */ } else { /* this happens when piping to more(1), for example */ #ifdef DEBUG_WINSZ if (firsttime) { firsttime = FALSE; fprintf(stderr, "ttyio.c screensize(): ioctl(TIOCGWINSZ) failed\n")); } #endif /* VT-100 assumed to be minimal hardware */ if (tt_rows != NULL) *tt_rows = 24; if (tt_cols != NULL) *tt_cols = 80; return 1; /* signal failure */ } } #else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */ int screensize(tt_rows, tt_cols) int *tt_rows; int *tt_cols; { char *envptr, *getenv(); int n; int errstat = 0; /* GRR: this is overly simplistic, but don't have access to stty/gtty * system anymore */ if (tt_rows != NULL) { envptr = getenv("LINES"); if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) { /* VT-100 assumed to be minimal hardware */ *tt_rows = 24; errstat = 1; /* signal failure */ } else { *tt_rows = n; } } if (tt_cols != NULL) { envptr = getenv("COLUMNS"); if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) { *tt_cols = 80; errstat = 1; /* signal failure */ } else { *tt_cols = n; } } return errstat; } #endif /* ?(TIOCGWINSZ && !M_UNIX) */ #endif /* MORE */ /* * Get a character from the given file descriptor without echo or newline. */ int zgetch(__G__ f) __GDEF int f; /* file descriptor from which to read */ { #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)) char oldmin, oldtim; #endif char c; struct sgttyb sg; /* tty device structure */ GTTY(f, &sg); /* get settings */ #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)) oldmin = sg.c_cc[VMIN]; /* save old values */ oldtim = sg.c_cc[VTIME]; sg.c_cc[VMIN] = 1; /* need only one char to return read() */ sg.c_cc[VTIME] = 0; /* no timeout */ sg.sg_flags &= ~ICANON; /* canonical mode off */ #else sg.sg_flags |= CBREAK; /* cbreak mode on */ #endif sg.sg_flags &= ~ECHO; /* turn echo off, too */ STTY(f, &sg); /* set cbreak mode */ GLOBAL(echofd) = f; /* in case ^C hit (not perfect: still CBREAK) */ read(f, &c, 1); /* read our character */ #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)) sg.c_cc[VMIN] = oldmin; /* restore old values */ sg.c_cc[VTIME] = oldtim; sg.sg_flags |= ICANON; /* canonical mode on */ #else sg.sg_flags &= ~CBREAK; /* cbreak mode off */ #endif sg.sg_flags |= ECHO; /* turn echo on */ STTY(f, &sg); /* restore canonical mode */ GLOBAL(echofd) = -1; return (int)(uch)c; } #else /* !ATH_BEO_UNX */ #ifndef VMS /* VMS supplies its own variant of getch() */ int zgetch(__G__ f) __GDEF int f; /* file descriptor from which to read (must be open already) */ { char c, c2; /*--------------------------------------------------------------------------- Get a character from the given file descriptor without echo; can't fake CBREAK mode (i.e., newline required), but can get rid of all chars up to and including newline. ---------------------------------------------------------------------------*/ echoff(f); read(f, &c, 1); if (c != '\n') do { read(f, &c2, 1); /* throw away all other chars up thru newline */ } while (c2 != '\n'); echon(); return (int)c; } #endif /* !VMS */ #endif /* ?ATH_BEO_UNX */ #endif /* UNZIP && !FUNZIP */ #endif /* !HAVE_WORKING_GETCH */ #if CRYPT /* getp() is only used with full encryption */ /* * Simple compile-time check for source compatibility between * zcrypt and ttyio: */ #if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7)) error: This Info-ZIP tool requires zcrypt 2.7 or later. #endif /* * Get a password of length n-1 or less into *p using the prompt *m. * The entered password is not echoed. */ #ifdef HAVE_WORKING_GETCH /* * For the AMIGA, getch() is defined as Agetch(), which is in * amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch() * uses the infrastructure that is already in place in filedate.c, it is * smaller. With this function, echoff() and echon() are not needed. * * For the MAC, a non-echo macgetch() function is defined in the MacOS * specific sources which uses the event handling mechanism of the * desktop window manager to get a character from the keyboard. * * For the other systems in this section, a non-echo getch() function * is either contained the C runtime library (conio package), or getch() * is defined as an alias for a similar system specific RTL function. */ #ifndef WINDLL /* WINDLL does not support a console interface */ #ifndef QDOS /* QDOS supplies a variant of this function */ /* This is the getp() function for all systems (with TTY type user interface) * that supply a working `non-echo' getch() function for "raw" console input. */ char *getp(__G__ m, p, n) __GDEF ZCONST char *m; /* prompt for password */ char *p; /* return value: line input */ int n; /* bytes available in p[] */ { char c; /* one-byte buffer for read() to use */ int i; /* number of characters input */ char *w; /* warning on retry */ /* get password */ w = ""; do { fputs(w, stderr); /* warning if back again */ fputs(m, stderr); /* display prompt and flush */ fflush(stderr); i = 0; do { /* read line, keeping first n characters */ if ((c = (char)getch()) == '\r') c = '\n'; /* until user hits CR */ if (c == 8 || c == 127) { if (i > 0) i--; /* the `backspace' and `del' keys works */ } else if (i < n) p[i++] = c; /* truncate past n */ } while (c != '\n'); PUTC('\n', stderr); fflush(stderr); w = "(line too long--try again)\n"; } while (p[i-1] != '\n'); p[i-1] = 0; /* terminate at newline */ return p; /* return pointer to password */ } /* end function getp() */ #endif /* !QDOS */ #endif /* !WINDLL */ #else /* !HAVE_WORKING_GETCH */ #if (defined(ATH_BEO_UNX) || defined(__MINT__)) #ifndef _PATH_TTY # ifdef __MINT__ # define _PATH_TTY ttyname(2) # else # define _PATH_TTY "/dev/tty" # endif #endif char *getp(__G__ m, p, n) __GDEF ZCONST char *m; /* prompt for password */ char *p; /* return value: line input */ int n; /* bytes available in p[] */ { char c; /* one-byte buffer for read() to use */ int i; /* number of characters input */ char *w; /* warning on retry */ int f; /* file descriptor for tty device */ #ifdef PASSWD_FROM_STDIN /* Read from stdin. This is unsafe if the password is stored on disk. */ f = 0; #else /* turn off echo on tty */ if ((f = open(_PATH_TTY, 0)) == -1) return NULL; #endif /* get password */ w = ""; do { fputs(w, stderr); /* warning if back again */ fputs(m, stderr); /* prompt */ fflush(stderr); i = 0; echoff(f); do { /* read line, keeping n */ read(f, &c, 1); if (i < n) p[i++] = c; } while (c != '\n'); echon(); PUTC('\n', stderr); fflush(stderr); w = "(line too long--try again)\n"; } while (p[i-1] != '\n'); p[i-1] = 0; /* terminate at newline */ #ifndef PASSWD_FROM_STDIN close(f); #endif return p; /* return pointer to password */ } /* end function getp() */ #endif /* ATH_BEO_UNX || __MINT__ */ #if (defined(VMS) || defined(CMS_MVS)) char *getp(__G__ m, p, n) __GDEF ZCONST char *m; /* prompt for password */ char *p; /* return value: line input */ int n; /* bytes available in p[] */ { char c; /* one-byte buffer for read() to use */ int i; /* number of characters input */ char *w; /* warning on retry */ FILE *f; /* file structure for SYS$COMMAND device */ #ifdef PASSWD_FROM_STDIN f = stdin; #else if ((f = fopen(ctermid(NULL), "r")) == NULL) return NULL; #endif /* get password */ fflush(stdout); w = ""; do { if (*w) /* bug: VMS apparently adds \n to NULL fputs */ fputs(w, stderr); /* warning if back again */ fputs(m, stderr); /* prompt */ fflush(stderr); i = 0; echoff(f); do { /* read line, keeping n */ if ((c = (char)getc(f)) == '\r') c = '\n'; if (i < n) p[i++] = c; } while (c != '\n'); echon(); PUTC('\n', stderr); fflush(stderr); w = "(line too long--try again)\n"; } while (p[i-1] != '\n'); p[i-1] = 0; /* terminate at newline */ #ifndef PASSWD_FROM_STDIN fclose(f); #endif return p; /* return pointer to password */ } /* end function getp() */ #endif /* VMS || CMS_MVS */ #endif /* ?HAVE_WORKING_GETCH */ #endif /* CRYPT */ #endif /* CRYPT || (UNZIP && !FUNZIP) */ Carla-2.1/data/windows/unzipfx-carla-control/ttyio.h000066400000000000000000000123441364475620200226000ustar00rootroot00000000000000/* Copyright (c) 1990-2004 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* ttyio.h */ #ifndef __ttyio_h /* don't include more than once */ #define __ttyio_h #ifndef __crypt_h # include "crypt.h" /* ensure that encryption header file has been seen */ #endif #if (CRYPT || (defined(UNZIP) && !defined(FUNZIP))) /* * Non-echo keyboard/console input support is needed and enabled. */ #ifndef __G /* UnZip only, for now (DLL stuff) */ # define __G # define __G__ # define __GDEF # define __GPRO void # define __GPRO__ #endif #ifndef ZCONST /* UnZip only (until have configure script like Zip) */ # define ZCONST const #endif #if (defined(MSDOS) || defined(OS2) || defined(WIN32)) # ifndef DOS_OS2_W32 # define DOS_OS2_W32 # endif #endif #if (defined(DOS_OS2_W32) || defined(__human68k__)) # ifndef DOS_H68_OS2_W32 # define DOS_H68_OS2_W32 # endif #endif #if (defined(DOS_OS2_W32) || defined(FLEXOS)) # ifndef DOS_FLX_OS2_W32 # define DOS_FLX_OS2_W32 # endif #endif #if (defined(DOS_H68_OS2_W32) || defined(FLEXOS)) # ifndef DOS_FLX_H68_OS2_W32 # define DOS_FLX_H68_OS2_W32 # endif #endif #if (defined(__ATHEOS__) || defined(__BEOS__) || defined(UNIX)) # ifndef ATH_BEO_UNX # define ATH_BEO_UNX # endif #endif #if (defined(VM_CMS) || defined(MVS)) # ifndef CMS_MVS # define CMS_MVS # endif #endif /* Function prototypes */ /* The following systems supply a `non-echo' character input function "getch()" * (or an alias) and do not need the echoff() / echon() function pair. */ #ifdef AMIGA # define echoff(f) # define echon() # define getch() Agetch() # define HAVE_WORKING_GETCH #endif /* AMIGA */ #ifdef ATARI # define echoff(f) # define echon() # include # define getch() (Cnecin() & 0x000000ff) # define HAVE_WORKING_GETCH #endif #ifdef MACOS # define echoff(f) # define echon() # define getch() macgetch() # define HAVE_WORKING_GETCH #endif #ifdef NLM # define echoff(f) # define echon() # define HAVE_WORKING_GETCH #endif #ifdef QDOS # define echoff(f) # define echon() # define HAVE_WORKING_GETCH #endif #ifdef RISCOS # define echoff(f) # define echon() # define getch() SWI_OS_ReadC() # define HAVE_WORKING_GETCH #endif #ifdef DOS_H68_OS2_W32 # define echoff(f) # define echon() # ifdef WIN32 # ifndef getch # define getch() getch_win32() # endif # else /* !WIN32 */ # ifdef __EMX__ # ifndef getch # define getch() _read_kbd(0, 1, 0) # endif # else /* !__EMX__ */ # ifdef __GO32__ # include # define getch() getkey() # else /* !__GO32__ */ # include # endif /* ?__GO32__ */ # endif /* ?__EMX__ */ # endif /* ?WIN32 */ # define HAVE_WORKING_GETCH #endif /* DOS_H68_OS2_W32 */ #ifdef FLEXOS # define echoff(f) # define echon() # define getch() getchar() /* not correct, but may not be on a console */ # define HAVE_WORKING_GETCH #endif /* For VM/CMS and MVS, we do not (yet) have any support to switch terminal * input echo on and off. The following "fake" definitions allow inclusion * of crypt support and UnZip's "pause prompting" features, but without * any echo suppression. */ #ifdef CMS_MVS # define echoff(f) # define echon() #endif #ifdef TANDEM # define echoff(f) # define echon() # define getch() zgetch() /* defined in TANDEMC */ # define HAVE_WORKING_GETCH #endif /* The THEOS C runtime library supplies the function conmask() to toggle * terminal input echo on (conmask("e")) and off (conmask("n")). But, * since THEOS C RTL also contains a working non-echo getch() function, * the echo toggles are not needed. */ #ifdef THEOS # define echoff(f) # define echon() # define HAVE_WORKING_GETCH #endif /* VMS has a single echo() function in ttyio.c to toggle terminal * input echo on and off. */ #ifdef VMS # define echoff(f) echo(0) # define echon() echo(1) # define getch() tt_getch() # define FGETCH(f) tt_getch() int echo OF((int)); int tt_getch OF((void)); #endif /* For all other systems, ttyio.c supplies the two functions Echoff() and * Echon() for suppressing and (re)enabling console input echo. */ #ifndef echoff # define echoff(f) Echoff(__G__ f) # define echon() Echon(__G) void Echoff OF((__GPRO__ int f)); void Echon OF((__GPRO)); #endif /* this stuff is used by MORE and also now by the ctrl-S code; fileio.c only */ #if (defined(UNZIP) && !defined(FUNZIP)) # ifdef HAVE_WORKING_GETCH # define FGETCH(f) getch() # endif # ifndef FGETCH /* default for all systems where no getch()-like function is available */ int zgetch OF((__GPRO__ int f)); # define FGETCH(f) zgetch(__G__ f) # endif #endif /* UNZIP && !FUNZIP */ #if (CRYPT && !defined(WINDLL)) char *getp OF((__GPRO__ ZCONST char *m, char *p, int n)); #endif #else /* !(CRYPT || (UNZIP && !FUNZIP)) */ /* * No need for non-echo keyboard/console input; provide dummy definitions. */ #define echoff(f) #define echon() #endif /* ?(CRYPT || (UNZIP && !FUNZIP)) */ #endif /* !__ttyio_h */ Carla-2.1/data/windows/unzipfx-carla-control/ubz2err.c000066400000000000000000000036551364475620200230230ustar00rootroot00000000000000/* Copyright (c) 1990-2008 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2007-Mar-04 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- ubz2err.c This file contains the "fatal error" callback routine required by the "minimal" (silent, non-stdio) setup of the bzip2 compression library. The fatal bzip2 error bail-out routine is provided in a separate code module, so that it can be easily overridden when the UnZip package is used as a static link library. One example is the WinDLL static library usage for building a monolythic binary of the Windows application "WiZ" that supports bzip2 both in compression and decompression operations. Contains: bz_internal_error() (USE_BZIP2 only) ---------------------------------------------------------------------------*/ #define __UBZ2ERR_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" #ifdef WINDLL # ifdef POCKET_UNZIP # include "wince/intrface.h" # else # include "windll/windll.h" # endif #endif #ifdef USE_BZIP2 /**********************************/ /* Function bz_internal_error() */ /**********************************/ /* Call-back function for the bzip2 decompression code (compiled with * BZ_NO_STDIO), required to handle fatal internal bug-type errors of * the bzip2 library. */ void bz_internal_error(bzerrcode) int bzerrcode; { GETGLOBALS(); Info(slide, 0x421, ((char *)slide, "error: internal fatal libbzip2 error number %d\n", bzerrcode)); #ifdef WINDLL longjmp(dll_error_return, 1); #else DESTROYGLOBALS(); EXIT(PK_BADERR); #endif } /* end function bz_internal_error() */ #endif /* USE_BZIP2 */ Carla-2.1/data/windows/unzipfx-carla-control/unix/000077500000000000000000000000001364475620200222365ustar00rootroot00000000000000Carla-2.1/data/windows/unzipfx-carla-control/unix/unix.c000066400000000000000000001711131364475620200233710ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- unix.c Unix-specific routines for use with Info-ZIP's UnZip 5.41 and later. Contains: readdir() do_wild() <-- generic enough to put in fileio.c? mapattr() mapname() checkdir() mkdir() close_outfile() defer_dir_attribs() set_direc_attribs() stamp_file() version() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #ifdef SCO_XENIX # define SYSNDIR #else /* SCO Unix, AIX, DNIX, TI SysV, Coherent 4.x, ... */ # if defined(__convexc__) || defined(SYSV) || defined(CRAY) || defined(BSD4_4) # define DIRENT # endif #endif #if defined(_AIX) || defined(__mpexl) # define DIRENT #endif #ifdef COHERENT # if defined(_I386) || (defined(__COHERENT__) && (__COHERENT__ >= 0x420)) # define DIRENT # endif #endif #ifdef _POSIX_VERSION # ifndef DIRENT # define DIRENT # endif #endif #ifdef DIRENT # include #else # ifdef SYSV # ifdef SYSNDIR # include # else # include # endif # else /* !SYSV */ # ifndef NO_SYSDIR # include # endif # endif /* ?SYSV */ # ifndef dirent # define dirent direct # endif #endif /* ?DIRENT */ #ifdef SET_DIR_ATTRIB typedef struct uxdirattr { /* struct for holding unix style directory */ struct uxdirattr *next; /* info until can be sorted and set at end */ char *fn; /* filename of directory */ union { iztimes t3; /* mtime, atime, ctime */ ztimbuf t2; /* modtime, actime */ } u; unsigned perms; /* same as min_info.file_attr */ int have_uidgid; /* flag */ ulg uidgid[2]; char fnbuf[1]; /* buffer stub for directory name */ } uxdirattr; #define UxAtt(d) ((uxdirattr *)d) /* typecast shortcut */ #endif /* SET_DIR_ATTRIB */ #ifdef ACORN_FTYPE_NFS /* Acorn bits for NFS filetyping */ typedef struct { uch ID[2]; uch size[2]; uch ID_2[4]; uch loadaddr[4]; uch execaddr[4]; uch attr[4]; } RO_extra_block; #endif /* ACORN_FTYPE_NFS */ /* static int created_dir; */ /* used in mapname(), checkdir() */ /* static int renamed_fullpath; */ /* ditto */ static unsigned filtattr OF((__GPRO__ unsigned perms)); /*****************************/ /* Strings used multiple */ /* times in unix.c */ /*****************************/ #ifndef MTS /* messages of code for setting file/directory attributes */ static ZCONST char CannotSetItemUidGid[] = "warning: cannot set UID %lu and/or GID %lu for %s\n %s\n"; static ZCONST char CannotSetUidGid[] = " (warning) cannot set UID %lu and/or GID %lu\n %s"; static ZCONST char CannotSetItemTimestamps[] = "warning: cannot set modif./access times for %s\n %s\n"; static ZCONST char CannotSetTimestamps[] = " (warning) cannot set modif./access times\n %s"; #endif /* !MTS */ #ifndef SFX #ifdef NO_DIR /* for AT&T 3B1 */ #define opendir(path) fopen(path,"r") #define closedir(dir) fclose(dir) typedef FILE DIR; typedef struct zdir { FILE *dirhandle; struct dirent *entry; } DIR DIR *opendir OF((ZCONST char *dirspec)); void closedir OF((DIR *dirp)); struct dirent *readdir OF((DIR *dirp)); DIR *opendir(dirspec) ZCONST char *dirspec; { DIR *dirp; if ((dirp = malloc(sizeof(DIR)) != NULL) { if ((dirp->dirhandle = fopen(dirspec, "r")) == NULL) { free(dirp); dirp = NULL; } } return dirp; } void closedir(dirp) DIR *dirp; { fclose(dirp->dirhandle); free(dirp); } /* * Apparently originally by Rich Salz. * Cleaned up and modified by James W. Birdsall. */ struct dirent *readdir(dirp) DIR *dirp; { if (dirp == NULL) return NULL; for (;;) if (fread(&(dirp->entry), sizeof (struct dirent), 1, dirp->dirhandle) == 0) return (struct dirent *)NULL; else if ((dirp->entry).d_ino) return &(dirp->entry); } /* end function readdir() */ #endif /* NO_DIR */ /**********************/ /* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ /**********************/ char *do_wild(__G__ wildspec) __GDEF ZCONST char *wildspec; /* only used first time on a given dir */ { /* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in unxcfg.h: static DIR *wild_dir = (DIR *)NULL; static ZCONST char *wildname; static char *dirname, matchname[FILNAMSIZ]; static int notfirstcall=FALSE, have_dirname, dirnamelen; */ struct dirent *file; /* Even when we're just returning wildspec, we *always* do so in * matchname[]--calling routine is allowed to append four characters * to the returned string, and wildspec may be a pointer to argv[]. */ if (!G.notfirstcall) { /* first call: must initialize everything */ G.notfirstcall = TRUE; if (!iswild(wildspec)) { strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; G.have_dirname = FALSE; G.wild_dir = NULL; return G.matchname; } /* break the wildspec into a directory part and a wildcard filename */ if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL) { G.dirname = "."; G.dirnamelen = 1; G.have_dirname = FALSE; G.wildname = wildspec; } else { ++G.wildname; /* point at character after '/' */ G.dirnamelen = G.wildname - wildspec; if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == (char *)NULL) { Info(slide, 0x201, ((char *)slide, "warning: cannot allocate wildcard buffers\n")); strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; return G.matchname; /* but maybe filespec was not a wildcard */ } strncpy(G.dirname, wildspec, G.dirnamelen); G.dirname[G.dirnamelen] = '\0'; /* terminate for strcpy below */ G.have_dirname = TRUE; } if ((G.wild_dir = (zvoid *)opendir(G.dirname)) != (zvoid *)NULL) { while ((file = readdir((DIR *)G.wild_dir)) != (struct dirent *)NULL) { Trace((stderr, "do_wild: readdir returns %s\n", FnFilter1(file->d_name))); if (file->d_name[0] == '.' && G.wildname[0] != '.') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, G.wildname, 0 WISEP) &&/*0=case sens.*/ /* skip "." and ".." directory entries */ strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { Trace((stderr, "do_wild: match() succeeds\n")); if (G.have_dirname) { strcpy(G.matchname, G.dirname); strcpy(G.matchname+G.dirnamelen, file->d_name); } else strcpy(G.matchname, file->d_name); return G.matchname; } } /* if we get to here directory is exhausted, so close it */ closedir((DIR *)G.wild_dir); G.wild_dir = (zvoid *)NULL; } Trace((stderr, "do_wild: opendir(%s) returns NULL\n", FnFilter1(G.dirname))); /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; return G.matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if ((DIR *)G.wild_dir == (DIR *)NULL) { G.notfirstcall = FALSE; /* nothing left--reset for new wildspec */ if (G.have_dirname) free(G.dirname); return (char *)NULL; } /* If we've gotten this far, we've read and matched at least one entry * successfully (in a previous call), so dirname has been copied into * matchname already. */ while ((file = readdir((DIR *)G.wild_dir)) != (struct dirent *)NULL) { Trace((stderr, "do_wild: readdir returns %s\n", FnFilter1(file->d_name))); if (file->d_name[0] == '.' && G.wildname[0] != '.') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, G.wildname, 0 WISEP)) { /* 0 == case sens. */ Trace((stderr, "do_wild: match() succeeds\n")); if (G.have_dirname) { /* strcpy(G.matchname, G.dirname); */ strcpy(G.matchname+G.dirnamelen, file->d_name); } else strcpy(G.matchname, file->d_name); return G.matchname; } } closedir((DIR *)G.wild_dir); /* at least one entry read; nothing left */ G.wild_dir = (zvoid *)NULL; G.notfirstcall = FALSE; /* reset for new wildspec */ if (G.have_dirname) free(G.dirname); return (char *)NULL; } /* end function do_wild() */ #endif /* !SFX */ #ifndef S_ISUID # define S_ISUID 0004000 /* set user id on execution */ #endif #ifndef S_ISGID # define S_ISGID 0002000 /* set group id on execution */ #endif #ifndef S_ISVTX # define S_ISVTX 0001000 /* save swapped text even after use */ #endif /************************/ /* Function filtattr() */ /************************/ /* This is used to clear or keep the SUID and SGID bits on file permissions. * It's possible that a file in an archive could have one of these bits set * and, unknown to the person unzipping, could allow others to execute the * file as the user or group. The new option -K bypasses this check. */ static unsigned filtattr(__G__ perms) __GDEF unsigned perms; { /* keep setuid/setgid/tacky perms? */ if (!uO.K_flag) perms &= ~(S_ISUID | S_ISGID | S_ISVTX); return (0xffff & perms); } /* end function filtattr() */ /**********************/ /* Function mapattr() */ /**********************/ int mapattr(__G) __GDEF { int r; ulg tmp = G.crec.external_file_attributes; G.pInfo->file_attr = 0; /* initialized to 0 for check in "default" branch below... */ switch (G.pInfo->hostnum) { case AMIGA_: tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); break; case THEOS_: tmp &= 0xF1FFFFFFL; if ((tmp & 0xF0000000L) != 0x40000000L) tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ else tmp &= 0x41FFFFFFL; /* leave directory bit as set */ /* fall through! */ case UNIX_: case VMS_: case ACORN_: case ATARI_: case ATHEOS_: case BEOS_: case QDOS_: case TANDEM_: r = FALSE; G.pInfo->file_attr = (unsigned)(tmp >> 16); if (G.pInfo->file_attr == 0 && G.extra_field) { /* Some (non-Info-ZIP) implementations of Zip for Unix and * VMS (and probably others ??) leave 0 in the upper 16-bit * part of the external_file_attributes field. Instead, they * store file permission attributes in some extra field. * As a work-around, we search for the presence of one of * these extra fields and fall back to the MSDOS compatible * part of external_file_attributes if one of the known * e.f. types has been detected. * Later, we might implement extraction of the permission * bits from the VMS extra field. But for now, the work-around * should be sufficient to provide "readable" extracted files. * (For ASI Unix e.f., an experimental remap of the e.f. * mode value IS already provided!) */ ush ebID; unsigned ebLen; uch *ef = G.extra_field; unsigned ef_len = G.crec.extra_field_length; while (!r && ef_len >= EB_HEADSIZE) { ebID = makeword(ef); ebLen = (unsigned)makeword(ef+EB_LEN); if (ebLen > (ef_len - EB_HEADSIZE)) /* discoverd some e.f. inconsistency! */ break; switch (ebID) { case EF_ASIUNIX: if (ebLen >= (EB_ASI_MODE+2)) { G.pInfo->file_attr = (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); /* force stop of loop: */ ef_len = (ebLen + EB_HEADSIZE); break; } /* else: fall through! */ case EF_PKVMS: /* "found nondecypherable e.f. with perm. attr" */ r = TRUE; default: break; } ef_len -= (ebLen + EB_HEADSIZE); ef += (ebLen + EB_HEADSIZE); } } if (!r) { #ifdef SYMLINKS /* Check if the file is a (POSIX-compatible) symbolic link. * We restrict symlink support to those "made-by" hosts that * are known to support symbolic links. */ G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && SYMLINK_HOST(G.pInfo->hostnum); #endif return 0; } /* fall through! */ /* all remaining cases: expand MSDOS read-only bit into write perms */ case FS_FAT_: /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the * Unix attributes in the upper 16 bits of the external attributes * field, just like Info-ZIP's Zip for Unix. We try to use that * value, after a check for consistency with the MSDOS attribute * bits (see below). */ G.pInfo->file_attr = (unsigned)(tmp >> 16); /* fall through! */ case FS_HPFS_: case FS_NTFS_: case MAC_: case TOPS20_: default: /* Ensure that DOS subdir bit is set when the entry's name ends * in a '/'. Some third-party Zip programs fail to set the subdir * bit for directory entries. */ if ((tmp & 0x10) == 0) { extent fnlen = strlen(G.filename); if (fnlen > 0 && G.filename[fnlen-1] == '/') tmp |= 0x10; } /* read-only bit --> write perms; subdir bit --> dir exec bit */ tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4; if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) { /* keep previous G.pInfo->file_attr setting, when its "owner" * part appears to be consistent with DOS attribute flags! */ #ifdef SYMLINKS /* Entries "made by FS_FAT_" could have been zipped on a * system that supports POSIX-style symbolic links. */ G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && (G.pInfo->hostnum == FS_FAT_); #endif return 0; } G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp); break; } /* end switch (host-OS-created-by) */ /* for originating systems with no concept of "group," "other," "system": */ umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */ G.pInfo->file_attr &= ~tmp; return 0; } /* end function mapattr() */ /************************/ /* Function mapname() */ /************************/ int mapname(__G__ renamed) __GDEF int renamed; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - caution (truncated filename) * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) * MPN_ERR_SKIP - error -> skip entry * MPN_ERR_TOOLONG - error -> path is too long * MPN_NOMEM - error (memory allocation failed) -> skip entry * [also MPN_VOL_LABEL, MPN_CREATED_DIR] */ { char pathcomp[FILNAMSIZ]; /* path-component buffer */ char *pp, *cp=(char *)NULL; /* character pointers */ char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ #ifdef ACORN_FTYPE_NFS char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ #endif int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ int error = MPN_OK; register unsigned workch; /* hold the character being tested */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return MPN_VOL_LABEL; /* can't set disk volume labels in Unix */ /* can create path as long as not just freshening, or if user told us */ G.create_dirs = (!uO.fflag || renamed); G.created_dir = FALSE; /* not yet */ /* user gave full pathname: don't prepend rootpath */ G.renamed_fullpath = (renamed && (*G.filename == '/')); if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM) return MPN_NOMEM; /* initialize path buffer, unless no memory */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (uO.jflag) /* junking directories */ cp = (char *)strrchr(G.filename, '/'); if (cp == (char *)NULL) /* no '/' or not junking dirs */ cp = G.filename; /* point to internal zipfile-member pathname */ else ++cp; /* point to start of last component of path */ /*--------------------------------------------------------------------------- Begin main loop through characters in filename. ---------------------------------------------------------------------------*/ while ((workch = (uch)*cp++) != 0) { switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if (strcmp(pathcomp, ".") == 0) { /* don't bother appending "./" to the path */ *pathcomp = '\0'; } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { /* "../" dir traversal detected, skip over it */ *pathcomp = '\0'; killed_ddot = TRUE; /* set "show message" flag */ } /* when path component is not empty, append it now */ if (*pathcomp != '\0' && ((error = checkdir(__G__ pathcomp, APPEND_DIR)) & MPN_MASK) > MPN_INF_TRUNC) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ break; #ifdef __CYGWIN__ /* Cygwin runs on Win32, apply FAT/NTFS filename rules */ case ':': /* drive spec not stored, so no colon allowed */ case '\\': /* '\\' may come as normal filename char (not */ case '<': /* dir sep char!) from unix-like file system */ case '>': /* no redirection symbols allowed either */ case '|': /* no pipe signs allowed */ case '"': /* no double quotes allowed */ case '?': /* no wildcards allowed */ case '*': *pp++ = '_'; /* these rules apply equally to FAT and NTFS */ break; #endif case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; *pp++ = ';'; /* keep for now; remove VMS ";##" */ break; /* later, if requested */ #ifdef ACORN_FTYPE_NFS case ',': /* NFS filetype extension */ lastcomma = pp; *pp++ = ','; /* keep for now; may need to remove */ break; /* later, if requested */ #endif #ifdef MTS case ' ': /* change spaces to underscore under */ *pp++ = '_'; /* MTS; leave as spaces under Unix */ break; #endif default: /* disable control character filter when requested, * else allow 8-bit characters (e.g. UTF-8) in filenames: */ if (uO.cflxflag || (isprint(workch) || (128 <= workch && workch <= 254))) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ /* Show warning when stripping insecure "parent dir" path components */ if (killed_ddot && QCOND2) { Info(slide, 0, ((char *)slide, "warning: skipped \"../\" path component(s) in %s\n", FnFilter1(G.filename))); if (!(error & ~MPN_MASK)) error = (error & MPN_MASK) | PK_WARN; } /*--------------------------------------------------------------------------- Report if directory was created (and no file to create: filename ended in '/'), check name to be sure it exists, and combine path and name be- fore exiting. ---------------------------------------------------------------------------*/ if (G.filename[strlen(G.filename) - 1] == '/') { checkdir(__G__ G.filename, GETPATH); if (G.created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %s\n", FnFilter1(G.filename))); } #ifndef NO_CHMOD /* Filter out security-relevant attributes bits. */ G.pInfo->file_attr = filtattr(__G__ G.pInfo->file_attr); /* When extracting non-UNIX directories or when extracting * without UID/GID restoration or SGID preservation, any * SGID flag inherited from the parent directory should be * maintained to allow files extracted into this new folder * to inherit the GID setting from the parent directory. */ if (G.pInfo->hostnum != UNIX_ || !(uO.X_flag || uO.K_flag)) { /* preserve SGID bit when inherited from parent dir */ if (!SSTAT(G.filename, &G.statbuf)) { G.pInfo->file_attr |= G.statbuf.st_mode & S_ISGID; } else { perror("Could not read directory attributes"); } } /* set approx. dir perms (make sure can still read/write in dir) */ if (chmod(G.filename, G.pInfo->file_attr | 0700)) perror("chmod (directory attributes) error"); #endif /* set dir time (note trailing '/') */ return (error & ~MPN_MASK) | MPN_CREATED_DIR; } /* dir existed already; don't look for data to extract */ return (error & ~MPN_MASK) | MPN_INF_SKIP; } *pp = '\0'; /* done with pathcomp: terminate it */ /* if not saving them, remove VMS version numbers (appended ";###") */ if (!uO.V_flag && lastsemi) { pp = lastsemi + 1; while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; } /* On UNIX (and compatible systems), "." and ".." are reserved for * directory navigation and cannot be used as regular file names. * These reserved one-dot and two-dot names are mapped to "_" and "__". */ if (strcmp(pathcomp, ".") == 0) *pathcomp = '_'; else if (strcmp(pathcomp, "..") == 0) strcpy(pathcomp, "__"); #ifdef ACORN_FTYPE_NFS /* translate Acorn filetype information if asked to do so */ if (uO.acorn_nfs_ext && (ef_spark = (RO_extra_block *) getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) != (RO_extra_block *)NULL) { /* file *must* have a RISC OS extra field */ long ft = (long)makelong(ef_spark->loadaddr); /*32-bit*/ if (lastcomma) { pp = lastcomma + 1; while (isxdigit((uch)(*pp))) ++pp; if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ } if ((ft & 1<<31)==0) ft=0x000FFD00; sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); } #endif /* ACORN_FTYPE_NFS */ if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", FnFilter1(G.filename))); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ checkdir(__G__ G.filename, GETPATH); return error; } /* end function mapname() */ #if 0 /*========== NOTES ==========*/ extract-to dir: a:path/ buildpath: path1/path2/ ... (NULL-terminated) pathcomp: filename mapname(): loop over chars in zipfile member name checkdir(path component, COMPONENT | CREATEDIR) --> map as required? (d:/tmp/unzip/) (disk:[tmp.unzip.) (d:/tmp/unzip/jj/) (disk:[tmp.unzip.jj.) (d:/tmp/unzip/jj/temp/) (disk:[tmp.unzip.jj.temp.) finally add filename itself and check for existence? (could use with rename) (d:/tmp/unzip/jj/temp/msg.outdir) (disk:[tmp.unzip.jj.temp]msg.outdir) checkdir(name, GETPATH) --> copy path to name and free space #endif /* 0 */ /***********************/ /* Function checkdir() */ /***********************/ int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename * MPN_INF_SKIP - path doesn't exist, not allowed to create * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path * exists and is not a directory, but is supposed to be * MPN_ERR_TOOLONG - path is too long * MPN_NOMEM - can't allocate memory for filename buffers */ { /* static int rootlen = 0; */ /* length of rootpath */ /* static char *rootpath; */ /* user's "extract-to" directory */ /* static char *buildpath; */ /* full path (so far) to extracted file */ /* static char *end; */ /* pointer to end of buildpath ('\0') */ # define FN_MASK 7 # define FUNCTION (flag & FN_MASK) /*--------------------------------------------------------------------------- APPEND_DIR: append the path component to the path being built and check for its existence. If doesn't exist and we are creating directories, do so for this one; else signal success or error as appropriate. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_DIR) { int too_long = FALSE; #ifdef SHORT_NAMES char *old_end = end; #endif Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); while ((*G.end = *pathcomp++) != '\0') ++G.end; #ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(G.end = old_end + FILENAME_MAX) = '\0'; #endif /* GRR: could do better check, see if overrunning buffer as we go: * check end-buildpath after each append, set warning variable if * within 20 of FILNAMSIZ; then if var set, do careful check when * appending. Clear variable when begin new path. */ /* next check: need to append '/', at least one-char name, '\0' */ if ((G.end-G.buildpath) > FILNAMSIZ-3) too_long = TRUE; /* check if extracting dir? */ if (SSTAT(G.buildpath, &G.statbuf)) { /* path doesn't exist */ if (!G.create_dirs) { /* told not to create (freshening) */ free(G.buildpath); return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); free(G.buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } if (mkdir(G.buildpath, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ %s\n\ unable to process %s.\n", FnFilter2(G.buildpath), strerror(errno), FnFilter1(G.filename))); free(G.buildpath); /* path didn't exist, tried to create, failed */ return MPN_ERR_SKIP; } G.created_dir = TRUE; } else if (!S_ISDIR(G.statbuf.st_mode)) { Info(slide, 1, ((char *)slide, "checkdir error: %s exists but is not directory\n\ unable to process %s.\n", FnFilter2(G.buildpath), FnFilter1(G.filename))); free(G.buildpath); /* path existed but wasn't dir */ return MPN_ERR_SKIP; } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); free(G.buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } *G.end++ = '/'; *G.end = '\0'; Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); return MPN_OK; } /* end if (FUNCTION == APPEND_DIR) */ /*--------------------------------------------------------------------------- GETPATH: copy full path to the string pointed at by pathcomp, and free G.buildpath. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { strcpy(pathcomp, G.buildpath); Trace((stderr, "getting and freeing path [%s]\n", FnFilter1(pathcomp))); free(G.buildpath); G.buildpath = G.end = (char *)NULL; return MPN_OK; } /*--------------------------------------------------------------------------- APPEND_NAME: assume the path component is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) { #ifdef SHORT_NAMES char *old_end = end; #endif Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); while ((*G.end = *pathcomp++) != '\0') { ++G.end; #ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(G.end = old_end + FILENAME_MAX) = '\0'; #endif if ((G.end-G.buildpath) >= FILNAMSIZ) { *--G.end = '\0'; Info(slide, 0x201, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", FnFilter1(G.filename), FnFilter2(G.buildpath))); return MPN_INF_TRUNC; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); /* could check for existence here, prompt for new name... */ return MPN_OK; } /*--------------------------------------------------------------------------- INIT: allocate and initialize buffer space for the file currently being extracted. If file was renamed with an absolute path, don't prepend the extract-to path. ---------------------------------------------------------------------------*/ /* GRR: for VMS and TOPS-20, add up to 13 to strlen */ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpath to ")); #ifdef ACORN_FTYPE_NFS if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+ (uO.acorn_nfs_ext ? 5 : 1))) #else if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1)) #endif == (char *)NULL) return MPN_NOMEM; if ((G.rootlen > 0) && !G.renamed_fullpath) { strcpy(G.buildpath, G.rootpath); G.end = G.buildpath + G.rootlen; } else { *G.buildpath = '\0'; G.end = G.buildpath; } Trace((stderr, "[%s]\n", FnFilter1(G.buildpath))); return MPN_OK; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in rootpath and create it if necessary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. ---------------------------------------------------------------------------*/ #if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", FnFilter1(pathcomp))); if (pathcomp == (char *)NULL) { G.rootlen = 0; return MPN_OK; } if (G.rootlen > 0) /* rootpath was already set, nothing to do */ return MPN_OK; if ((G.rootlen = strlen(pathcomp)) > 0) { char *tmproot; if ((tmproot = (char *)malloc(G.rootlen+2)) == (char *)NULL) { G.rootlen = 0; return MPN_NOMEM; } strcpy(tmproot, pathcomp); if (tmproot[G.rootlen-1] == '/') { tmproot[--G.rootlen] = '\0'; } if (G.rootlen > 0 && (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))) { /* path does not exist */ if (!G.create_dirs /* || iswild(tmproot) */ ) { free(tmproot); G.rootlen = 0; /* skip (or treat as stored file) */ return MPN_INF_SKIP; } /* create the directory (could add loop here scanning tmproot * to create more than one level, but why really necessary?) */ if (mkdir(tmproot, 0777) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory: %s\n\ %s\n", FnFilter1(tmproot), strerror(errno))); free(tmproot); G.rootlen = 0; /* path didn't exist, tried to create, and failed: */ /* file exists, or 2+ subdir levels required */ return MPN_ERR_SKIP; } } tmproot[G.rootlen++] = '/'; tmproot[G.rootlen] = '\0'; if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) { free(tmproot); G.rootlen = 0; return MPN_NOMEM; } Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath))); } return MPN_OK; } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (G.rootlen > 0) { free(G.rootpath); G.rootlen = 0; } return MPN_OK; } return MPN_INVALID; /* should never reach */ } /* end function checkdir() */ #ifdef NO_MKDIR /********************/ /* Function mkdir() */ /********************/ int mkdir(path, mode) ZCONST char *path; int mode; /* ignored */ /* * returns: 0 - successful * -1 - failed (errno not set, however) */ { char command[FILNAMSIZ+40]; /* buffer for system() call */ /* GRR 930416: added single quotes around path to avoid bug with * creating directories with ampersands in name; not yet tested */ sprintf(command, "IFS=\" \t\n\" /bin/mkdir '%s' 2>/dev/null", path); if (system(command)) return -1; return 0; } #endif /* NO_MKDIR */ #if (!defined(MTS) || defined(SET_DIR_ATTRIB)) static int get_extattribs OF((__GPRO__ iztimes *pzt, ulg z_uidgid[2])); static int get_extattribs(__G__ pzt, z_uidgid) __GDEF iztimes *pzt; ulg z_uidgid[2]; { /*--------------------------------------------------------------------------- Convert from MSDOS-format local time and date to Unix-format 32-bit GMT time: adjust base year from 1980 to 1970, do usual conversions from yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day- light savings time differences. If we have a Unix extra field, however, we're laughing: both mtime and atime are ours. On the other hand, we then have to check for restoration of UID/GID. ---------------------------------------------------------------------------*/ int have_uidgid_flg; unsigned eb_izux_flg; eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, #ifdef IZ_CHECK_TZ (G.tz_is_valid ? pzt : NULL), #else pzt, #endif z_uidgid) : 0); if (eb_izux_flg & EB_UT_FL_MTIME) { TTrace((stderr, "\nget_extattribs: Unix e.f. modif. time = %ld\n", pzt->mtime)); } else { pzt->mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); } if (eb_izux_flg & EB_UT_FL_ATIME) { TTrace((stderr, "get_extattribs: Unix e.f. access time = %ld\n", pzt->atime)); } else { pzt->atime = pzt->mtime; TTrace((stderr, "\nget_extattribs: modification/access times = %ld\n", pzt->mtime)); } /* if -X option was specified and we have UID/GID info, restore it */ have_uidgid_flg = #ifdef RESTORE_UIDGID (uO.X_flag && (eb_izux_flg & EB_UX2_VALID)); #else 0; #endif return have_uidgid_flg; } #endif /* !MTS || SET_DIR_ATTRIB */ #ifndef MTS /****************************/ /* Function close_outfile() */ /****************************/ void close_outfile(__G) /* GRR: change to return PK-style warning level */ __GDEF { union { iztimes t3; /* mtime, atime, ctime */ ztimbuf t2; /* modtime, actime */ } zt; ulg z_uidgid[2]; int have_uidgid_flg; have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid); /*--------------------------------------------------------------------------- If symbolic links are supported, allocate storage for a symlink control structure, put the uncompressed "data" and other required info in it, and add the structure to the "deferred symlinks" chain. Since we know it's a symbolic link to start with, we shouldn't have to worry about overflowing unsigned ints with unsigned longs. ---------------------------------------------------------------------------*/ #ifdef SYMLINKS if (G.symlnk) { extent ucsize = (extent)G.lrec.ucsize; # ifdef SET_SYMLINK_ATTRIBS extent attribsize = sizeof(unsigned) + (have_uidgid_flg ? sizeof(z_uidgid) : 0); # else extent attribsize = 0; # endif /* size of the symlink entry is the sum of * (struct size (includes 1st '\0') + 1 additional trailing '\0'), * system specific attribute data size (might be 0), * and the lengths of name and link target. */ extent slnk_entrysize = (sizeof(slinkentry) + 1) + attribsize + ucsize + strlen(G.filename); slinkentry *slnk_entry; if (slnk_entrysize < ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: mem alloc overflow\n", FnFilter1(G.filename))); fclose(G.outfile); return; } if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: no mem\n", FnFilter1(G.filename))); fclose(G.outfile); return; } slnk_entry->next = NULL; slnk_entry->targetlen = ucsize; slnk_entry->attriblen = attribsize; # ifdef SET_SYMLINK_ATTRIBS memcpy(slnk_entry->buf, &(G.pInfo->file_attr), sizeof(unsigned)); if (have_uidgid_flg) memcpy(slnk_entry->buf + 4, z_uidgid, sizeof(z_uidgid)); # endif slnk_entry->target = slnk_entry->buf + slnk_entry->attriblen; slnk_entry->fname = slnk_entry->target + ucsize + 1; strcpy(slnk_entry->fname, G.filename); /* move back to the start of the file to re-read the "link data" */ rewind(G.outfile); if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed\n", FnFilter1(G.filename))); free(slnk_entry); fclose(G.outfile); return; } fclose(G.outfile); /* close "link" file for good... */ slnk_entry->target[ucsize] = '\0'; if (QCOND2) Info(slide, 0, ((char *)slide, "-> %s ", FnFilter1(slnk_entry->target))); /* add this symlink record to the list of deferred symlinks */ if (G.slink_last != NULL) G.slink_last->next = slnk_entry; else G.slink_head = slnk_entry; G.slink_last = slnk_entry; return; } #endif /* SYMLINKS */ #ifdef QLZIP if (G.extra_field) { static void qlfix OF((__GPRO__ uch *ef_ptr, unsigned ef_len)); qlfix(__G__ G.extra_field, G.lrec.extra_field_length); } #endif #if (defined(NO_FCHOWN)) fclose(G.outfile); #endif /* if -X option was specified and we have UID/GID info, restore it */ if (have_uidgid_flg /* check that both uid and gid values fit into their data sizes */ && ((ulg)(uid_t)(z_uidgid[0]) == z_uidgid[0]) && ((ulg)(gid_t)(z_uidgid[1]) == z_uidgid[1])) { TTrace((stderr, "close_outfile: restoring Unix UID/GID info\n")); #if (defined(NO_FCHOWN)) if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1])) #else if (fchown(fileno(G.outfile), (uid_t)z_uidgid[0], (gid_t)z_uidgid[1])) #endif { if (uO.qflag) Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid, z_uidgid[0], z_uidgid[1], FnFilter1(G.filename), strerror(errno))); else Info(slide, 0x201, ((char *)slide, CannotSetUidGid, z_uidgid[0], z_uidgid[1], strerror(errno))); } } #if (!defined(NO_FCHOWN) && defined(NO_FCHMOD)) fclose(G.outfile); #endif #if (!defined(NO_FCHOWN) && !defined(NO_FCHMOD)) /*--------------------------------------------------------------------------- Change the file permissions from default ones to those stored in the zipfile. ---------------------------------------------------------------------------*/ if (fchmod(fileno(G.outfile), filtattr(__G__ G.pInfo->file_attr))) perror("fchmod (file attributes) error"); fclose(G.outfile); #endif /* !NO_FCHOWN && !NO_FCHMOD */ /* skip restoring time stamps on user's request */ if (uO.D_flag <= 1) { /* set the file's access and modification times */ if (utime(G.filename, &(zt.t2))) { if (uO.qflag) Info(slide, 0x201, ((char *)slide, CannotSetItemTimestamps, FnFilter1(G.filename), strerror(errno))); else Info(slide, 0x201, ((char *)slide, CannotSetTimestamps, strerror(errno))); } } #if (defined(NO_FCHOWN) || defined(NO_FCHMOD)) /*--------------------------------------------------------------------------- Change the file permissions from default ones to those stored in the zipfile. ---------------------------------------------------------------------------*/ #ifndef NO_CHMOD if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr))) perror("chmod (file attributes) error"); #endif #endif /* NO_FCHOWN || NO_FCHMOD */ } /* end function close_outfile() */ #endif /* !MTS */ #if (defined(SYMLINKS) && defined(SET_SYMLINK_ATTRIBS)) int set_symlnk_attribs(__G__ slnk_entry) __GDEF slinkentry *slnk_entry; { if (slnk_entry->attriblen > 0) { # if (!defined(NO_LCHOWN)) if (slnk_entry->attriblen > sizeof(unsigned)) { ulg *z_uidgid_p = (zvoid *)(slnk_entry->buf + sizeof(unsigned)); /* check that both uid and gid values fit into their data sizes */ if (((ulg)(uid_t)(z_uidgid_p[0]) == z_uidgid_p[0]) && ((ulg)(gid_t)(z_uidgid_p[1]) == z_uidgid_p[1])) { TTrace((stderr, "set_symlnk_attribs: restoring Unix UID/GID info for\n\ %s\n", FnFilter1(slnk_entry->fname))); if (lchown(slnk_entry->fname, (uid_t)z_uidgid_p[0], (gid_t)z_uidgid_p[1])) { Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid, z_uidgid_p[0], z_uidgid_p[1], FnFilter1(slnk_entry->fname), strerror(errno))); } } } # endif /* !NO_LCHOWN */ # if (!defined(NO_LCHMOD)) TTrace((stderr, "set_symlnk_attribs: restoring Unix attributes for\n %s\n", FnFilter1(slnk_entry->fname))); if (lchmod(slnk_entry->fname, filtattr(__G__ *(unsigned *)(zvoid *)slnk_entry->buf))) perror("lchmod (file attributes) error"); # endif /* !NO_LCHMOD */ } /* currently, no error propagation... */ return PK_OK; } /* end function set_symlnk_attribs() */ #endif /* SYMLINKS && SET_SYMLINK_ATTRIBS */ #ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */ # ifndef NO_CHMOD static ZCONST char DirlistChmodFailed[] = "warning: cannot set permissions for %s\n %s\n"; # endif int defer_dir_attribs(__G__ pd) __GDEF direntry **pd; { uxdirattr *d_entry; d_entry = (uxdirattr *)malloc(sizeof(uxdirattr) + strlen(G.filename)); *pd = (direntry *)d_entry; if (d_entry == (uxdirattr *)NULL) { return PK_MEM; } d_entry->fn = d_entry->fnbuf; strcpy(d_entry->fn, G.filename); d_entry->perms = G.pInfo->file_attr; d_entry->have_uidgid = get_extattribs(__G__ &(d_entry->u.t3), d_entry->uidgid); return PK_OK; } /* end function defer_dir_attribs() */ int set_direc_attribs(__G__ d) __GDEF direntry *d; { int errval = PK_OK; if (UxAtt(d)->have_uidgid && /* check that both uid and gid values fit into their data sizes */ ((ulg)(uid_t)(UxAtt(d)->uidgid[0]) == UxAtt(d)->uidgid[0]) && ((ulg)(gid_t)(UxAtt(d)->uidgid[1]) == UxAtt(d)->uidgid[1]) && chown(UxAtt(d)->fn, (uid_t)UxAtt(d)->uidgid[0], (gid_t)UxAtt(d)->uidgid[1])) { Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid, UxAtt(d)->uidgid[0], UxAtt(d)->uidgid[1], FnFilter1(d->fn), strerror(errno))); if (!errval) errval = PK_WARN; } /* Skip restoring directory time stamps on user' request. */ if (uO.D_flag <= 0) { /* restore directory timestamps */ if (utime(d->fn, &UxAtt(d)->u.t2)) { Info(slide, 0x201, ((char *)slide, CannotSetItemTimestamps, FnFilter1(d->fn), strerror(errno))); if (!errval) errval = PK_WARN; } } #ifndef NO_CHMOD if (chmod(d->fn, UxAtt(d)->perms)) { Info(slide, 0x201, ((char *)slide, DirlistChmodFailed, FnFilter1(d->fn), strerror(errno))); if (!errval) errval = PK_WARN; } #endif /* !NO_CHMOD */ return errval; } /* end function set_direc_attribs() */ #endif /* SET_DIR_ATTRIB */ #ifdef TIMESTAMP /***************************/ /* Function stamp_file() */ /***************************/ int stamp_file(fname, modtime) ZCONST char *fname; time_t modtime; { ztimbuf tp; tp.modtime = tp.actime = modtime; return (utime(fname, &tp)); } /* end function stamp_file() */ #endif /* TIMESTAMP */ #ifndef SFX /************************/ /* Function version() */ /************************/ void version(__G) __GDEF { #if (defined(__GNUC__) && defined(NX_CURRENT_COMPILER_RELEASE)) char cc_namebuf[40]; char cc_versbuf[40]; #else #if (defined(__SUNPRO_C)) char cc_versbuf[17]; #else #if (defined(__HP_cc) || defined(__IBMC__)) char cc_versbuf[25]; #else #if (defined(__DECC_VER)) char cc_versbuf[17]; int cc_verstyp; #else #if (defined(CRAY) && defined(_RELEASE)) char cc_versbuf[40]; #endif /* (CRAY && _RELEASE) */ #endif /* __DECC_VER */ #endif /* __HP_cc || __IBMC__ */ #endif /* __SUNPRO_C */ #endif /* (__GNUC__ && NX_CURRENT_COMPILER_RELEASE) */ #if ((defined(CRAY) || defined(cray)) && defined(_UNICOS)) char os_namebuf[40]; #else #if defined(__NetBSD__) char os_namebuf[40]; #endif #endif /* Pyramid, NeXT have problems with huge macro expansion, too: no Info() */ sprintf((char *)slide, LoadFarString(CompiledWith), #ifdef __GNUC__ # ifdef NX_CURRENT_COMPILER_RELEASE (sprintf(cc_namebuf, "NeXT DevKit %d.%02d ", NX_CURRENT_COMPILER_RELEASE/100, NX_CURRENT_COMPILER_RELEASE%100), cc_namebuf), (strlen(__VERSION__) > 8)? "(gcc)" : (sprintf(cc_versbuf, "(gcc %s)", __VERSION__), cc_versbuf), # else "gcc ", __VERSION__, # endif #else #if defined(__SUNPRO_C) "Sun C ", (sprintf(cc_versbuf, "version %x", __SUNPRO_C), cc_versbuf), #else #if (defined(__HP_cc)) "HP C ", (((__HP_cc% 100) == 0) ? (sprintf(cc_versbuf, "version A.%02d.%02d", (__HP_cc/ 10000), ((__HP_cc% 10000)/ 100))) : (sprintf(cc_versbuf, "version A.%02d.%02d.%02d", (__HP_cc/ 10000), ((__HP_cc% 10000)/ 100), (__HP_cc% 100))), cc_versbuf), #else #if (defined(__DECC_VER)) "DEC C ", (sprintf(cc_versbuf, "%c%d.%d-%03d", ((cc_verstyp = (__DECC_VER / 10000) % 10) == 6 ? 'T' : (cc_verstyp == 8 ? 'S' : 'V')), __DECC_VER / 10000000, (__DECC_VER % 10000000) / 100000, __DECC_VER % 1000), cc_versbuf), #else #if defined(CRAY) && defined(_RELEASE) "cc ", (sprintf(cc_versbuf, "version %d", _RELEASE), cc_versbuf), #else #ifdef __IBMC__ "IBM C ", (sprintf(cc_versbuf, "version %d.%d.%d", (__IBMC__ / 100), ((__IBMC__ / 10) % 10), (__IBMC__ % 10)), cc_versbuf), #else #ifdef __VERSION__ # ifndef IZ_CC_NAME # define IZ_CC_NAME "cc " # endif IZ_CC_NAME, __VERSION__ #else # ifndef IZ_CC_NAME # define IZ_CC_NAME "cc" # endif IZ_CC_NAME, "", #endif /* ?__VERSION__ */ #endif /* ?__IBMC__ */ #endif /* ?(CRAY && _RELEASE) */ #endif /* ?__DECC_VER */ #endif /* ?__HP_cc */ #endif /* ?__SUNPRO_C */ #endif /* ?__GNUC__ */ #ifndef IZ_OS_NAME # define IZ_OS_NAME "Unix" #endif IZ_OS_NAME, #if defined(sgi) || defined(__sgi) " (Silicon Graphics IRIX)", #else #ifdef sun # ifdef sparc # ifdef __SVR4 " (Sun SPARC/Solaris)", # else /* may or may not be SunOS */ " (Sun SPARC)", # endif # else # if defined(sun386) || defined(i386) " (Sun 386i)", # else # if defined(mc68020) || defined(__mc68020__) " (Sun 3)", # else /* mc68010 or mc68000: Sun 2 or earlier */ " (Sun 2)", # endif # endif # endif #else #ifdef __hpux " (HP-UX)", #else #ifdef __osf__ " (DEC OSF/1)", #else #ifdef _AIX " (IBM AIX)", #else #ifdef aiws " (IBM RT/AIX)", #else #if defined(CRAY) || defined(cray) # ifdef _UNICOS (sprintf(os_namebuf, " (Cray UNICOS release %d)", _UNICOS), os_namebuf), # else " (Cray UNICOS)", # endif #else #if defined(uts) || defined(UTS) " (Amdahl UTS)", #else #ifdef NeXT # ifdef mc68000 " (NeXTStep/black)", # else " (NeXTStep for Intel)", # endif #else /* the next dozen or so are somewhat order-dependent */ #ifdef LINUX # ifdef __ELF__ " (Linux ELF)", # else " (Linux a.out)", # endif #else #ifdef MINIX " (Minix)", #else #ifdef M_UNIX " (SCO Unix)", #else #ifdef M_XENIX " (SCO Xenix)", #else #ifdef __NetBSD__ # ifdef NetBSD0_8 (sprintf(os_namebuf, " (NetBSD 0.8%c)", (char)(NetBSD0_8 - 1 + 'A')), os_namebuf), # else # ifdef NetBSD0_9 (sprintf(os_namebuf, " (NetBSD 0.9%c)", (char)(NetBSD0_9 - 1 + 'A')), os_namebuf), # else # ifdef NetBSD1_0 (sprintf(os_namebuf, " (NetBSD 1.0%c)", (char)(NetBSD1_0 - 1 + 'A')), os_namebuf), # else (BSD4_4 == 0.5)? " (NetBSD before 0.9)" : " (NetBSD 1.1 or later)", # endif # endif # endif #else #ifdef __FreeBSD__ (BSD4_4 == 0.5)? " (FreeBSD 1.x)" : " (FreeBSD 2.0 or later)", #else #ifdef __bsdi__ (BSD4_4 == 0.5)? " (BSD/386 1.0)" : " (BSD/386 1.1 or later)", #else #ifdef __386BSD__ (BSD4_4 == 1)? " (386BSD, post-4.4 release)" : " (386BSD)", #else #ifdef __CYGWIN__ " (Cygwin)", #else #if defined(i686) || defined(__i686) || defined(__i686__) " (Intel 686)", #else #if defined(i586) || defined(__i586) || defined(__i586__) " (Intel 586)", #else #if defined(i486) || defined(__i486) || defined(__i486__) " (Intel 486)", #else #if defined(i386) || defined(__i386) || defined(__i386__) " (Intel 386)", #else #ifdef pyr " (Pyramid)", #else #ifdef ultrix # ifdef mips " (DEC/MIPS)", # else # ifdef vax " (DEC/VAX)", # else /* __alpha? */ " (DEC/Alpha)", # endif # endif #else #ifdef gould " (Gould)", #else #ifdef MTS " (MTS)", #else #ifdef __convexc__ " (Convex)", #else #ifdef __QNX__ " (QNX 4)", #else #ifdef __QNXNTO__ " (QNX Neutrino)", #else #ifdef Lynx " (LynxOS)", #else #ifdef __APPLE__ # ifdef __i386__ " Mac OS X Intel i32", # else # ifdef __ppc__ " Mac OS X PowerPC", # else # ifdef __ppc64__ " Mac OS X PowerPC64", # else " Mac OS X", # endif /* __ppc64__ */ # endif /* __ppc__ */ # endif /* __i386__ */ #else "", #endif /* Apple */ #endif /* Lynx */ #endif /* QNX Neutrino */ #endif /* QNX 4 */ #endif /* Convex */ #endif /* MTS */ #endif /* Gould */ #endif /* DEC */ #endif /* Pyramid */ #endif /* 386 */ #endif /* 486 */ #endif /* 586 */ #endif /* 686 */ #endif /* Cygwin */ #endif /* 386BSD */ #endif /* BSDI BSD/386 */ #endif /* NetBSD */ #endif /* FreeBSD */ #endif /* SCO Xenix */ #endif /* SCO Unix */ #endif /* Minix */ #endif /* Linux */ #endif /* NeXT */ #endif /* Amdahl */ #endif /* Cray */ #endif /* RT/AIX */ #endif /* AIX */ #endif /* OSF/1 */ #endif /* HP-UX */ #endif /* Sun */ #endif /* SGI */ #ifdef __DATE__ " on ", __DATE__ #else "", "" #endif ); (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); } /* end function version() */ #endif /* !SFX */ #ifdef QLZIP struct qdirect { long d_length __attribute__ ((packed)); /* file length */ unsigned char d_access __attribute__ ((packed)); /* file access type */ unsigned char d_type __attribute__ ((packed)); /* file type */ long d_datalen __attribute__ ((packed)); /* data length */ long d_reserved __attribute__ ((packed));/* Unused */ short d_szname __attribute__ ((packed)); /* size of name */ char d_name[36] __attribute__ ((packed));/* name area */ long d_update __attribute__ ((packed)); /* last update */ long d_refdate __attribute__ ((packed)); long d_backup __attribute__ ((packed)); /* EOD */ }; #define LONGID "QDOS02" #define EXTRALEN (sizeof(struct qdirect) + 8) #define JBLONGID "QZHD" #define JBEXTRALEN (sizeof(jbextra) - 4 * sizeof(char)) typedef struct { char eb_header[4] __attribute__ ((packed)); /* place_holder */ char longid[8] __attribute__ ((packed)); struct qdirect header __attribute__ ((packed)); } qdosextra; typedef struct { char eb_header[4]; /* place_holder */ char longid[4]; struct qdirect header; } jbextra; /* The following two functions SH() and LG() convert big-endian short * and long numbers into native byte order. They are some kind of * counterpart to the generic UnZip's makeword() and makelong() functions. */ static ush SH(ush val) { uch swapbuf[2]; swapbuf[1] = (uch)(val & 0xff); swapbuf[0] = (uch)(val >> 8); return (*(ush *)swapbuf); } static ulg LG(ulg val) { /* convert the big-endian unsigned long number `val' to the machine * dependent representation */ ush swapbuf[2]; swapbuf[1] = SH((ush)(val & 0xffff)); swapbuf[0] = SH((ush)(val >> 16)); return (*(ulg *)swapbuf); } static void qlfix(__G__ ef_ptr, ef_len) __GDEF uch *ef_ptr; unsigned ef_len; { while (ef_len >= EB_HEADSIZE) { unsigned eb_id = makeword(EB_ID + ef_ptr); unsigned eb_len = makeword(EB_LEN + ef_ptr); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ Trace((stderr, "qlfix: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } switch (eb_id) { case EF_QDOS: { struct _ntc_ { long id; long dlen; } ntc; long dlen = 0; qdosextra *extra = (qdosextra *)ef_ptr; jbextra *jbp = (jbextra *)ef_ptr; if (!strncmp(extra->longid, LONGID, strlen(LONGID))) { if (eb_len != EXTRALEN) if (uO.qflag) Info(slide, 0x201, ((char *)slide, "warning: invalid length in Qdos field for %s\n", FnFilter1(G.filename))); else Info(slide, 0x201, ((char *)slide, "warning: invalid length in Qdos field")); if (extra->header.d_type) { dlen = extra->header.d_datalen; } } if (!strncmp(jbp->longid, JBLONGID, strlen(JBLONGID))) { if (eb_len != JBEXTRALEN) if (uO.qflag) Info(slide, 0x201, ((char *)slide, "warning: invalid length in QZ field for %s\n", FnFilter1(G.filename))); else Info(slide, 0x201, ((char *)slide, "warning: invalid length in QZ field")); if (jbp->header.d_type) { dlen = jbp->header.d_datalen; } } if ((long)LG(dlen) > 0) { zfseeko(G.outfile, -8, SEEK_END); fread(&ntc, 8, 1, G.outfile); if (ntc.id != *(long *)"XTcc") { ntc.id = *(long *)"XTcc"; ntc.dlen = dlen; fwrite (&ntc, 8, 1, G.outfile); } Info(slide, 0x201, ((char *)slide, "QData = %d", LG(dlen))); } return; /* finished, cancel further extra field scanning */ } default: Trace((stderr,"qlfix: unknown extra field block, ID=%d\n", eb_id)); } /* Skip this extra field block */ ef_ptr += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } } #endif /* QLZIP */ Carla-2.1/data/windows/unzipfx-carla-control/unix/unxcfg.h000066400000000000000000000146171364475620200237120ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- Unix specific configuration section: ---------------------------------------------------------------------------*/ #ifndef __unxcfg_h #define __unxcfg_h /* LARGE FILE SUPPORT - 10/6/04 EG */ /* This needs to be set before the includes so they set the right sizes */ #if (defined(NO_LARGE_FILE_SUPPORT) && defined(LARGE_FILE_SUPPORT)) # undef LARGE_FILE_SUPPORT #endif /* Automatically set ZIP64_SUPPORT if LFS */ #ifdef LARGE_FILE_SUPPORT # if (!defined(NO_ZIP64_SUPPORT) && !defined(ZIP64_SUPPORT)) # define ZIP64_SUPPORT # endif #endif /* NO_ZIP64_SUPPORT takes preceedence over ZIP64_SUPPORT */ #if defined(NO_ZIP64_SUPPORT) && defined(ZIP64_SUPPORT) # undef ZIP64_SUPPORT #endif #ifdef LARGE_FILE_SUPPORT /* 64-bit Large File Support */ /* The following Large File Summit (LFS) defines turn on large file support on Linux (probably 2.4 or later kernel) and many other unixen */ /* These have to be before any include that sets types so the large file versions of the types are set in the includes */ # define _LARGEFILE_SOURCE /* some OSes need this for fseeko */ # define _LARGEFILE64_SOURCE # define _FILE_OFFSET_BITS 64 /* select default interface as 64 bit */ # define _LARGE_FILES /* some OSes need this for 64-bit off_t */ # define __USE_LARGEFILE64 #endif /* LARGE_FILE_SUPPORT */ #include /* off_t, time_t, dev_t, ... */ #include #ifdef NO_OFF_T typedef long zoff_t; #else typedef off_t zoff_t; #endif #define ZOFF_T_DEFINED typedef struct stat z_stat; #define Z_STAT_DEFINED #ifndef COHERENT # include /* O_BINARY for open() w/o CR/LF translation */ #else /* COHERENT */ # ifdef _I386 # include /* Coherent 4.0.x, Mark Williams C */ # else # include /* Coherent 3.10, Mark Williams C */ # endif # define SHORT_SYMS # ifndef __COHERENT__ /* Coherent 4.2 has tzset() */ # define tzset settz # endif #endif /* ?COHERENT */ #ifndef NO_PARAM_H # ifdef NGROUPS_MAX # undef NGROUPS_MAX /* SCO bug: defined again in */ # endif # ifdef BSD # define TEMP_BSD /* may be defined again in */ # undef BSD # endif # include /* conflict with , some systems? */ # ifdef TEMP_BSD # undef TEMP_BSD # ifndef BSD # define BSD # endif # endif #endif /* !NO_PARAM_H */ #ifdef __osf__ # define DIRENT # ifdef BSD # undef BSD # endif #endif /* __osf__ */ #ifdef __CYGWIN__ # include # define DIRENT # define HAVE_TERMIOS_H # ifndef timezone # define timezone _timezone # endif #endif #ifdef BSD # include # include # if (defined(_AIX) || defined(__GLIBC__) || defined(__GNU__)) # include # endif #else # include struct tm *gmtime(), *localtime(); #endif #if (defined(BSD4_4) || (defined(SYSV) && defined(MODERN))) # include /* this includes utime.h on SGIs */ # if (defined(BSD4_4) || defined(linux) || defined(__GLIBC__)) # include # define GOT_UTIMBUF # endif # if (!defined(GOT_UTIMBUF) && (defined(__hpux) || defined(__SUNPRO_C))) # include # define GOT_UTIMBUF # endif # if (!defined(GOT_UTIMBUF) && defined(__GNU__)) # include # define GOT_UTIMBUF # endif #endif #if (defined(__DGUX__) && !defined(GOT_UTIMBUF)) /* DG/UX requires this because of a non-standard struct utimebuf */ # include # define GOT_UTIMBUF #endif #if (defined(V7) || defined(pyr_bsd)) # define strchr index # define strrchr rindex #endif #ifdef V7 # define O_RDONLY 0 # define O_WRONLY 1 # define O_RDWR 2 #endif #if defined(NO_UNICODE_SUPPORT) && defined(UNICODE_SUPPORT) /* disable Unicode (UTF-8) support when requested */ # undef UNICODE_SUPPORT #endif #if (defined(_MBCS) && defined(NO_MBCS)) /* disable MBCS support when requested */ # undef _MBCS #endif #if (!defined(NO_SETLOCALE) && !defined(_MBCS)) # if (!defined(UNICODE_SUPPORT) || !defined(UTF8_MAYBE_NATIVE)) /* enable setlocale here, unless this happens later for UTF-8 and/or * MBCS support */ # include # ifndef SETLOCALE # define SETLOCALE(category, locale) setlocale(category, locale) # endif # endif #endif #ifndef NO_SETLOCALE # if (!defined(NO_WORKING_ISPRINT) && !defined(HAVE_WORKING_ISPRINT)) /* enable "enhanced" unprintable chars detection in fnfilter() */ # define HAVE_WORKING_ISPRINT # endif #endif #ifdef MINIX # include #endif #if (!defined(HAVE_STRNICMP) & !defined(NO_STRNICMP)) # define NO_STRNICMP #endif #ifndef DATE_FORMAT # define DATE_FORMAT DF_MDY /* GRR: customize with locale.h somehow? */ #endif #define lenEOL 1 #ifdef EBCDIC # define PutNativeEOL *q++ = '\n'; #else # define PutNativeEOL *q++ = native(LF); #endif #define SCREENSIZE(ttrows, ttcols) screensize(ttrows, ttcols) #define SCREENWIDTH 80 #define SCREENLWRAP 1 #define USE_EF_UT_TIME #if (!defined(NO_LCHOWN) || !defined(NO_LCHMOD)) # define SET_SYMLINK_ATTRIBS #endif #ifdef MTS # ifdef SET_DIR_ATTRIB # undef SET_DIR_ATTRIB # endif #else /* !MTS */ # define SET_DIR_ATTRIB # if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) /* GRR 970513 */ # define TIMESTAMP # endif # define RESTORE_UIDGID #endif /* ?MTS */ /* Static variables that we have to add to Uz_Globs: */ #define SYSTEM_SPECIFIC_GLOBALS \ int created_dir, renamed_fullpath;\ char *rootpath, *buildpath, *end;\ ZCONST char *wildname;\ char *dirname, matchname[FILNAMSIZ];\ int rootlen, have_dirname, dirnamelen, notfirstcall;\ zvoid *wild_dir; /* created_dir, and renamed_fullpath are used by both mapname() and */ /* checkdir(). */ /* rootlen, rootpath, buildpath and end are used by checkdir(). */ /* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */ /* and notfirstcall are used by do_wild(). */ #endif /* !__unxcfg_h */ Carla-2.1/data/windows/unzipfx-carla-control/unzip.c000066400000000000000000002757611364475620200226060ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- unzip.c UnZip - a zipfile extraction utility. See below for make instructions, or read the comments in Makefile and the various Contents files for more de- tailed explanations. To report a bug, submit a *complete* description via //www.info-zip.org/zip-bug.html; include machine type, operating system and version, compiler and version, and reasonably detailed error messages or problem report. To join Info-ZIP, see the instructions in README. UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x, which in turn was almost a complete rewrite of version 3.x. For a detailed revision history, see UnzpHist.zip at quest.jpl.nasa.gov. For a list of the many (near infinite) contributors, see "CONTRIBS" in the UnZip source distribution. UnZip 6.0 adds support for archives larger than 4 GiB using the Zip64 extensions as well as support for Unicode information embedded per the latest zip standard additions. --------------------------------------------------------------------------- [from original zipinfo.c] This program reads great gobs of totally nifty information, including the central directory stuff, from ZIP archives ("zipfiles" for short). It started as just a testbed for fooling with zipfiles, but at this point it is actually a useful utility. It also became the basis for the rewrite of UnZip (3.16 -> 4.0), using the central directory for processing rather than the individual (local) file headers. As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one. If the executable is named "unzip" (or "unzip.exe", depending), it behaves like UnZip by default; if it is named "zipinfo" or "ii", it behaves like ZipInfo. The ZipInfo behavior may also be triggered by use of unzip's -Z option; for example, "unzip -Z [zipinfo_options] archive.zip". Another dandy product from your buddies at Newtware! Author: Greg Roelofs, newt@pobox.com, http://pobox.com/~newt/ 23 August 1990 -> April 1997 --------------------------------------------------------------------------- Version: unzip5??.{tar.Z | tar.gz | zip} for Unix, VMS, OS/2, MS-DOS, Amiga, Atari, Windows 3.x/95/NT/CE, Macintosh, Human68K, Acorn RISC OS, AtheOS, BeOS, SMS/QDOS, VM/CMS, MVS, AOS/VS, Tandem NSK, Theos and TOPS-20. Copyrights: see accompanying file "LICENSE" in UnZip source distribution. (This software is free but NOT IN THE PUBLIC DOMAIN.) ---------------------------------------------------------------------------*/ #define __UNZIP_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" /* includes, typedefs, macros, prototypes, etc. */ #include "crypt.h" #include "unzvers.h" #include "unzipfx/appDetails.h" #ifndef WINDLL /* The WINDLL port uses windll/windll.c instead... */ /***************************/ /* Local type declarations */ /***************************/ #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS)) typedef struct _sign_info { struct _sign_info *previous; void (*sighandler)(int); int sigtype; } savsigs_info; #endif /*******************/ /* Local Functions */ /*******************/ #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS)) static int setsignalhandler OF((__GPRO__ savsigs_info **p_savedhandler_chain, int signal_type, void (*newhandler)(int))); #endif #ifndef SFX static void help_extended OF((__GPRO)); static void show_version_info OF((__GPRO)); #endif /*************/ /* Constants */ /*************/ #include "consts.h" /* all constant global variables are in here */ /* (non-constant globals were moved to globals.c) */ /* constant local variables: */ #ifndef SFX #ifndef _WIN32_WCE /* Win CE does not support environment variables */ static ZCONST char Far EnvUnZip[] = ENV_UNZIP; static ZCONST char Far EnvUnZip2[] = ENV_UNZIP2; static ZCONST char Far EnvZipInfo[] = ENV_ZIPINFO; static ZCONST char Far EnvZipInfo2[] = ENV_ZIPINFO2; #ifdef RISCOS static ZCONST char Far EnvUnZipExts[] = ENV_UNZIPEXTS; #endif /* RISCOS */ static ZCONST char Far NoMemEnvArguments[] = "envargs: cannot get memory for arguments"; #endif /* !_WIN32_WCE */ static ZCONST char Far CmdLineParamTooLong[] = "error: command line parameter #%d exceeds internal size limit\n"; #endif /* !SFX */ #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS)) static ZCONST char Far CantSaveSigHandler[] = "error: cannot save signal handler settings\n"; #endif #if (!defined(SFX) || defined(SFX_EXDIR)) static ZCONST char Far NotExtracting[] = "caution: not extracting; -d ignored\n"; static ZCONST char Far MustGiveExdir[] = "error: must specify directory to which to extract with -d option\n"; static ZCONST char Far OnlyOneExdir[] = "error: -d option used more than once (only one exdir allowed)\n"; #endif #if (defined(UNICODE_SUPPORT) && !defined(UNICODE_WCHAR)) static ZCONST char Far UTF8EscapeUnSupp[] = "warning: -U \"escape all non-ASCII UTF-8 chars\" is not supported\n"; #endif #if CRYPT static ZCONST char Far MustGivePasswd[] = "error: must give decryption password with -P option\n"; #endif #ifndef SFX static ZCONST char Far Zfirst[] = "error: -Z must be first option for ZipInfo mode (check UNZIP variable?)\n"; #endif static ZCONST char Far InvalidOptionsMsg[] = "error:\ -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n"; static ZCONST char Far IgnoreOOptionMsg[] = "caution: both -n and -o specified; ignoring -o\n"; /* usage() strings */ #ifndef SFX #ifdef VMS static ZCONST char Far Example3[] = "vms.c"; static ZCONST char Far Example2[] = " unzip \"-V\" foo \"Bar\"\ (Quote names to preserve case, unless SET PROC/PARS=EXT)\n"; #else /* !VMS */ static ZCONST char Far Example3[] = "ReadMe"; #ifdef RISCOS static ZCONST char Far Example2[] = " unzip foo -d RAM:$ => extract all files from foo into RAMDisc\n"; #else /* !RISCOS */ #if (defined(OS2) || (defined(DOS_FLX_OS2_W32) && defined(MORE))) static ZCONST char Far Example2[] = ""; /* no room: too many local3[] items */ #else /* !OS2 */ #ifdef MACOS static ZCONST char Far Example2[] = ""; /* not needed */ #else /* !MACOS */ static ZCONST char Far Example2[] = " \ unzip -p foo | more => send contents of foo.zip via pipe into program more\n"; #endif /* ?MACOS */ #endif /* ?OS2 */ #endif /* ?RISCOS */ #endif /* ?VMS */ /* local1[]: command options */ #if defined(TIMESTAMP) static ZCONST char Far local1[] = " -T timestamp archive to latest"; #else /* !TIMESTAMP */ static ZCONST char Far local1[] = ""; #endif /* ?TIMESTAMP */ /* local2[] and local3[]: modifier options */ #ifdef DOS_FLX_H68_OS2_W32 #ifdef FLEXOS static ZCONST char Far local2[] = ""; #else static ZCONST char Far local2[] = " -$ label removables (-$$ => fixed disks)"; #endif #ifdef OS2 #ifdef MORE static ZCONST char Far local3[] = "\ -X restore ACLs if supported -s spaces in filenames => '_'\n\ -M pipe through \"more\" pager\n"; #else static ZCONST char Far local3[] = " \ -X restore ACLs if supported -s spaces in filenames => '_'\n\n"; #endif /* ?MORE */ #else /* !OS2 */ #ifdef WIN32 #ifdef NTSD_EAS #ifdef MORE static ZCONST char Far local3[] = "\ -X restore ACLs (-XX => use privileges) -s spaces in filenames => '_'\n\ -M pipe through \"more\" pager\n"; #else static ZCONST char Far local3[] = " \ -X restore ACLs (-XX => use privileges) -s spaces in filenames => '_'\n\n"; #endif /* ?MORE */ #else /* !NTSD_EAS */ #ifdef MORE static ZCONST char Far local3[] = "\ -M pipe through \"more\" pager \ -s spaces in filenames => '_'\n\n"; #else static ZCONST char Far local3[] = " \ -s spaces in filenames => '_'\n\n"; #endif /* ?MORE */ #endif /* ?NTSD_EAS */ #else /* !WIN32 */ #ifdef MORE static ZCONST char Far local3[] = " -\ M pipe through \"more\" pager -s spaces in filenames => '_'\n\n"; #else static ZCONST char Far local3[] = "\ -s spaces in filenames => '_'\n"; #endif #endif /* ?WIN32 */ #endif /* ?OS2 || ?WIN32 */ #else /* !DOS_FLX_OS2_W32 */ #ifdef VMS static ZCONST char Far local2[] = " -X restore owner/ACL protection info"; #ifdef MORE static ZCONST char Far local3[] = "\ -Y treat \".nnn\" as \";nnn\" version -2 force ODS2 names\n\ --D restore dir (-D: no) timestamps -M pipe through \"more\" pager\n\ (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\ \n\n"; #else static ZCONST char Far local3[] = "\n\ -Y treat \".nnn\" as \";nnn\" version -2 force ODS2 names\n\ --D restore dir (-D: no) timestamps\n\ (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\ \n\n"; #endif #else /* !VMS */ #ifdef ATH_BEO_UNX static ZCONST char Far local2[] = " -X restore UID/GID info"; #ifdef MORE static ZCONST char Far local3[] = "\ -K keep setuid/setgid/tacky permissions -M pipe through \"more\" pager\n"; #else static ZCONST char Far local3[] = "\ -K keep setuid/setgid/tacky permissions\n"; #endif #else /* !ATH_BEO_UNX */ #ifdef TANDEM static ZCONST char Far local2[] = "\ -X restore Tandem User ID -r remove file extensions\n\ -b create 'C' (180) text files "; #ifdef MORE static ZCONST char Far local3[] = " \ -M pipe through \"more\" pager\n"; #else static ZCONST char Far local3[] = "\n"; #endif #else /* !TANDEM */ #ifdef AMIGA static ZCONST char Far local2[] = " -N restore comments as filenotes"; #ifdef MORE static ZCONST char Far local3[] = " \ -M pipe through \"more\" pager\n"; #else static ZCONST char Far local3[] = "\n"; #endif #else /* !AMIGA */ #ifdef MACOS static ZCONST char Far local2[] = " -E show Mac info during extraction"; static ZCONST char Far local3[] = " \ -i ignore filenames in mac extra info -J junk (ignore) Mac extra info\n\ \n"; #else /* !MACOS */ #ifdef MORE static ZCONST char Far local2[] = " -M pipe through \"more\" pager"; static ZCONST char Far local3[] = "\n"; #else static ZCONST char Far local2[] = ""; /* Atari, Mac, CMS/MVS etc. */ static ZCONST char Far local3[] = ""; #endif #endif /* ?MACOS */ #endif /* ?AMIGA */ #endif /* ?TANDEM */ #endif /* ?ATH_BEO_UNX */ #endif /* ?VMS */ #endif /* ?DOS_FLX_OS2_W32 */ #endif /* !SFX */ #ifndef NO_ZIPINFO #ifdef VMS static ZCONST char Far ZipInfoExample[] = "* or % (e.g., \"*font-%.zip\")"; #else static ZCONST char Far ZipInfoExample[] = "*, ?, [] (e.g., \"[a-j]*.zip\")"; #endif static ZCONST char Far ZipInfoUsageLine1[] = "\ ZipInfo %d.%d%d%s of %s, by Greg Roelofs and the Info-ZIP group.\n\ \n\ List name, date/time, attribute, size, compression method, etc., about files\n\ in list (excluding those in xlist) contained in the specified .zip archive(s).\ \n\"file[.zip]\" may be a wildcard name containing %s.\n\n\ usage: zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n\ or: unzip %s-Z%s [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n"; static ZCONST char Far ZipInfoUsageLine2[] = "\nmain\ listing-format options: -s short Unix \"ls -l\" format (def.)\n\ -1 filenames ONLY, one per line -m medium Unix \"ls -l\" format\n\ -2 just filenames but allow -h/-t/-z -l long Unix \"ls -l\" format\n\ -v verbose, multi-page format\n"; static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\ -h print header line -t print totals for listed files or for all\n\ -z print zipfile comment -T print file times in sortable decimal format\ \n -C be case-insensitive %s\ -x exclude filenames that follow from listing\n"; #ifdef MORE static ZCONST char Far ZipInfoUsageLine4[] = " -M page output through built-in \"more\"\n"; #else /* !MORE */ static ZCONST char Far ZipInfoUsageLine4[] = ""; #endif /* ?MORE */ #endif /* !NO_ZIPINFO */ #ifdef BETA # ifdef VMSCLI /* BetaVersion[] is also used in vms/cmdline.c: do not make it static */ ZCONST char Far BetaVersion[] = "%s\ THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n"; # else static ZCONST char Far BetaVersion[] = "%s\ THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n"; # endif #endif #ifdef SFX # ifdef VMSCLI /* UnzipSFXBanner[] is also used in vms/cmdline.c: do not make it static */ ZCONST char Far UnzipSFXBanner[] = # else static ZCONST char Far UnzipSFXBanner[] = # endif SFX_APP_BANNER "\n"; # ifdef SFX_EXDIR static ZCONST char Far UnzipSFXOpts[] = "Valid options are -tfupcz and -d ; modifiers are -abjnoqCL%sV%s.\n"; # else static ZCONST char Far UnzipSFXOpts[] = "Valid options are -tfupcz; modifiers are -abjnoqCL%sV%s.\n"; # endif #else /* !SFX */ static ZCONST char Far CompileOptions[] = "UnZip special compilation options:\n"; static ZCONST char Far CompileOptFormat[] = " %s\n"; #ifndef _WIN32_WCE /* Win CE does not support environment variables */ static ZCONST char Far EnvOptions[] = "\nUnZip and ZipInfo environment options:\n"; static ZCONST char Far EnvOptFormat[] = "%16s: %.1024s\n"; #endif static ZCONST char Far None[] = "[none]"; # ifdef ACORN_FTYPE_NFS static ZCONST char Far AcornFtypeNFS[] = "ACORN_FTYPE_NFS"; # endif # ifdef ASM_CRC static ZCONST char Far AsmCRC[] = "ASM_CRC"; # endif # ifdef ASM_INFLATECODES static ZCONST char Far AsmInflateCodes[] = "ASM_INFLATECODES"; # endif # ifdef CHECK_VERSIONS static ZCONST char Far Check_Versions[] = "CHECK_VERSIONS"; # endif # ifdef COPYRIGHT_CLEAN static ZCONST char Far Copyright_Clean[] = "COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported)"; # endif # ifdef DEBUG static ZCONST char Far UDebug[] = "DEBUG"; # endif # ifdef DEBUG_TIME static ZCONST char Far DebugTime[] = "DEBUG_TIME"; # endif # ifdef DLL static ZCONST char Far Dll[] = "DLL"; # endif # ifdef DOSWILD static ZCONST char Far DosWild[] = "DOSWILD"; # endif # ifdef LZW_CLEAN static ZCONST char Far LZW_Clean[] = "LZW_CLEAN (PKZIP/Zip 1.x unshrinking method not supported)"; # endif # ifndef MORE static ZCONST char Far No_More[] = "NO_MORE"; # endif # ifdef NO_ZIPINFO static ZCONST char Far No_ZipInfo[] = "NO_ZIPINFO"; # endif # ifdef NTSD_EAS static ZCONST char Far NTSDExtAttrib[] = "NTSD_EAS"; # endif # if defined(WIN32) && defined(NO_W32TIMES_IZFIX) static ZCONST char Far W32NoIZTimeFix[] = "NO_W32TIMES_IZFIX"; # endif # ifdef OLD_THEOS_EXTRA static ZCONST char Far OldTheosExtra[] = "OLD_THEOS_EXTRA (handle also old Theos port extra field)"; # endif # ifdef OS2_EAS static ZCONST char Far OS2ExtAttrib[] = "OS2_EAS"; # endif # ifdef QLZIP static ZCONST char Far SMSExFldOnUnix[] = "QLZIP"; # endif # ifdef REENTRANT static ZCONST char Far Reentrant[] = "REENTRANT"; # endif # ifdef REGARGS static ZCONST char Far RegArgs[] = "REGARGS"; # endif # ifdef RETURN_CODES static ZCONST char Far Return_Codes[] = "RETURN_CODES"; # endif # ifdef SET_DIR_ATTRIB static ZCONST char Far SetDirAttrib[] = "SET_DIR_ATTRIB"; # endif # ifdef SYMLINKS static ZCONST char Far SymLinkSupport[] = "SYMLINKS (symbolic links supported, if RTL and file system permit)"; # endif # ifdef TIMESTAMP static ZCONST char Far TimeStamp[] = "TIMESTAMP"; # endif # ifdef UNIXBACKUP static ZCONST char Far UnixBackup[] = "UNIXBACKUP"; # endif # ifdef USE_EF_UT_TIME static ZCONST char Far Use_EF_UT_time[] = "USE_EF_UT_TIME"; # endif # ifndef LZW_CLEAN static ZCONST char Far Use_Unshrink[] = "USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)"; # endif # ifndef COPYRIGHT_CLEAN static ZCONST char Far Use_Smith_Code[] = "USE_SMITH_CODE (PKZIP 0.9x unreducing method supported)"; # endif # ifdef USE_DEFLATE64 static ZCONST char Far Use_Deflate64[] = "USE_DEFLATE64 (PKZIP 4.x Deflate64(tm) supported)"; # endif # ifdef UNICODE_SUPPORT # ifdef UTF8_MAYBE_NATIVE # ifdef UNICODE_WCHAR /* direct native UTF-8 check AND charset transform via wchar_t */ static ZCONST char Far Use_Unicode[] = "UNICODE_SUPPORT [wide-chars, char coding: %s] (handle UTF-8 paths)"; # else /* direct native UTF-8 check, only */ static ZCONST char Far Use_Unicode[] = "UNICODE_SUPPORT [char coding: %s] (handle UTF-8 paths)"; # endif static ZCONST char Far SysChUTF8[] = "UTF-8"; static ZCONST char Far SysChOther[] = "other"; # else /* !UTF8_MAYBE_NATIVE */ /* charset transform via wchar_t, no native UTF-8 support */ static ZCONST char Far Use_Unicode[] = "UNICODE_SUPPORT [wide-chars] (handle UTF-8 paths)"; # endif /* ?UTF8_MAYBE_NATIVE */ # endif /* UNICODE_SUPPORT */ # ifdef _MBCS static ZCONST char Far Have_MBCS_Support[] = "MBCS-support (multibyte character support, MB_CUR_MAX = %u)"; # endif # ifdef MULT_VOLUME static ZCONST char Far Use_MultiVol[] = "MULT_VOLUME (multi-volume archives supported)"; # endif # ifdef LARGE_FILE_SUPPORT static ZCONST char Far Use_LFS[] = "LARGE_FILE_SUPPORT (large files over 2 GiB supported)"; # endif # ifdef ZIP64_SUPPORT static ZCONST char Far Use_Zip64[] = "ZIP64_SUPPORT (archives using Zip64 for large files supported)"; # endif # if (defined(__DJGPP__) && (__DJGPP__ >= 2)) # ifdef USE_DJGPP_ENV static ZCONST char Far Use_DJGPP_Env[] = "USE_DJGPP_ENV"; # endif # ifdef USE_DJGPP_GLOB static ZCONST char Far Use_DJGPP_Glob[] = "USE_DJGPP_GLOB"; # endif # endif /* __DJGPP__ && (__DJGPP__ >= 2) */ # ifdef USE_VFAT static ZCONST char Far Use_VFAT_support[] = "USE_VFAT"; # endif # ifdef USE_ZLIB static ZCONST char Far UseZlib[] = "USE_ZLIB (compiled with version %s; using version %s)"; # endif # ifdef USE_BZIP2 static ZCONST char Far UseBZip2[] = "USE_BZIP2 (PKZIP 4.6+, using bzip2 lib version %s)"; # endif # ifdef VMS_TEXT_CONV static ZCONST char Far VmsTextConv[] = "VMS_TEXT_CONV"; # endif # ifdef VMSCLI static ZCONST char Far VmsCLI[] = "VMSCLI"; # endif # ifdef VMSWILD static ZCONST char Far VmsWild[] = "VMSWILD"; # endif # ifdef WILD_STOP_AT_DIR static ZCONST char Far WildStopAtDir[] = "WILD_STOP_AT_DIR"; # endif # if CRYPT # ifdef PASSWD_FROM_STDIN static ZCONST char Far PasswdStdin[] = "PASSWD_FROM_STDIN"; # endif static ZCONST char Far Decryption[] = " [decryption, version %d.%d%s of %s]\n"; static ZCONST char Far CryptDate[] = CR_VERSION_DATE; # endif # ifndef __RSXNT__ # ifdef __EMX__ static ZCONST char Far EnvEMX[] = "EMX"; static ZCONST char Far EnvEMXOPT[] = "EMXOPT"; # endif # if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2))) static ZCONST char Far EnvGO32[] = "GO32"; static ZCONST char Far EnvGO32TMP[] = "GO32TMP"; # endif # endif /* !__RSXNT__ */ #ifdef VMS /* UnzipUsageLine1[] is also used in vms/cmdline.c: do not make it static */ ZCONST char Far UnzipUsageLine1[] = "\ UnZip %d.%d%d%s of %s, by Info-ZIP. For more details see: unzip -v.\n\n"; # ifdef COPYRIGHT_CLEAN static ZCONST char Far UnzipUsageLine1v[] = "\ UnZip %d.%d%d%s of %s, by Info-ZIP. Maintained by C. Spieler. Send\n\ bug reports using http://www.info-zip.org/zip-bug.html; see README for details.\ \n\n"; # else static ZCONST char Far UnzipUsageLine1v[] = "\ UnZip %d.%d%d%s of %s, by Info-ZIP. UnReduce (c) 1989 by S. H. Smith.\n\ Send bug reports using //www.info-zip.org/zip-bug.html; see README for details.\ \n\n"; # endif /* ?COPYRIGHT_CLEAN */ #else /* !VMS */ # ifdef COPYRIGHT_CLEAN static ZCONST char Far UnzipUsageLine1[] = "\ UnZip %d.%d%d%s of %s, by Info-ZIP. Maintained by C. Spieler. Send\n\ bug reports using http://www.info-zip.org/zip-bug.html; see README for details.\ \n\n"; # else static ZCONST char Far UnzipUsageLine1[] = "\ UnZip %d.%d%d%s of %s, by Info-ZIP. UnReduce (c) 1989 by S. H. Smith.\n\ Send bug reports using //www.info-zip.org/zip-bug.html; see README for details.\ \n\n"; # endif /* ?COPYRIGHT_CLEAN */ # define UnzipUsageLine1v UnzipUsageLine1 #endif /* ?VMS */ static ZCONST char Far UnzipUsageLine2v[] = "\ Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip/ ;\ \nsee ftp://ftp.info-zip.org/pub/infozip/UnZip.html for other sites.\ \n\n"; #ifdef MACOS static ZCONST char Far UnzipUsageLine2[] = "\ Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-d exdir]\n \ Default action is to extract files in list, to exdir;\n\ file[.zip] may be a wildcard. %s\n"; #else /* !MACOS */ #ifdef VM_CMS static ZCONST char Far UnzipUsageLine2[] = "\ Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d fm]\n \ Default action is to extract files in list, except those in xlist, to disk fm;\ \n file[.zip] may be a wildcard. %s\n"; #else /* !VM_CMS */ static ZCONST char Far UnzipUsageLine2[] = "\ Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \ Default action is to extract files in list, except those in xlist, to exdir;\n\ file[.zip] may be a wildcard. %s\n"; #endif /* ?VM_CMS */ #endif /* ?MACOS */ #ifdef NO_ZIPINFO # define ZIPINFO_MODE_OPTION "" static ZCONST char Far ZipInfoMode[] = "(ZipInfo mode is disabled in this version.)"; #else # define ZIPINFO_MODE_OPTION "[-Z] " static ZCONST char Far ZipInfoMode[] = "-Z => ZipInfo mode (\"unzip -Z\" for usage)."; #endif /* ?NO_ZIPINFO */ #ifdef VMS static ZCONST char Far VMSusageLine2b[] = "\ => define foreign command symbol in LOGIN.COM: $ unzip :== $dev:[dir]unzip.exe\ \n"; #endif #ifdef MACOS static ZCONST char Far UnzipUsageLine3[] = "\n\ -d extract files into exdir -l list files (short format)\n\ -f freshen existing files, create none -t test compressed archive data\n\ -u update files, create if necessary -z display archive comment only\n\ -v list verbosely/show version info %s\n"; #else /* !MACOS */ #ifdef VM_CMS static ZCONST char Far UnzipUsageLine3[] = "\n\ -p extract files to pipe, no messages -l list files (short format)\n\ -f freshen existing files, create none -t test compressed archive data\n\ -u update files, create if necessary -z display archive comment only\n\ -v list verbosely/show version info %s\n\ -x exclude files that follow (in xlist) -d extract files onto disk fm\n"; #else /* !VM_CMS */ static ZCONST char Far UnzipUsageLine3[] = "\n\ -p extract files to pipe, no messages -l list files (short format)\n\ -f freshen existing files, create none -t test compressed archive data\n\ -u update files, create if necessary -z display archive comment only\n\ -v list verbosely/show version info %s\n\ -x exclude files that follow (in xlist) -d extract files into exdir\n"; #endif /* ?VM_CMS */ #endif /* ?MACOS */ /* There is not enough space on a standard 80x25 Windows console screen for * the additional line advertising the UTF-8 debugging options. This may * eventually also be the case for other ports. Probably, the -U option need * not be shown on the introductory screen at all. [Chr. Spieler, 2008-02-09] * * Likely, other advanced options should be moved to an extended help page and * the option to list that page put here. [E. Gordon, 2008-3-16] */ #if (defined(UNICODE_SUPPORT) && !defined(WIN32)) #ifdef VMS static ZCONST char Far UnzipUsageLine4[] = "\ modifiers:\n\ -n never overwrite or make a new version of an existing file\n\ -o always make a new version (-oo: overwrite original) of an existing file\n\ -q quiet mode (-qq => quieter) -a auto-convert any text files\n\ -j junk paths (do not make directories) -aa treat ALL files as text\n\ -U use escapes for all non-ASCII Unicode -UU ignore any Unicode fields\n\ -C match filenames case-insensitively -L make (some) names \ lowercase\n %-42s -V retain VMS version numbers\n%s"; #else /* !VMS */ static ZCONST char Far UnzipUsageLine4[] = "\ modifiers:\n\ -n never overwrite existing files -q quiet mode (-qq => quieter)\n\ -o overwrite files WITHOUT prompting -a auto-convert any text files\n\ -j junk paths (do not make directories) -aa treat ALL files as text\n\ -U use escapes for all non-ASCII Unicode -UU ignore any Unicode fields\n\ -C match filenames case-insensitively -L make (some) names \ lowercase\n %-42s -V retain VMS version numbers\n%s"; #endif /* ?VMS */ #else /* !UNICODE_SUPPORT */ #ifdef VMS static ZCONST char Far UnzipUsageLine4[] = "\ modifiers:\n\ -n never overwrite or make a new version of an existing file\n\ -o always make a new version (-oo: overwrite original) of an existing file\n\ -q quiet mode (-qq => quieter) -a auto-convert any text files\n\ -j junk paths (do not make directories) -aa treat ALL files as text\n\ -C match filenames case-insensitively -L make (some) names \ lowercase\n %-42s -V retain VMS version numbers\n%s"; #else /* !VMS */ static ZCONST char Far UnzipUsageLine4[] = "\ modifiers:\n\ -n never overwrite existing files -q quiet mode (-qq => quieter)\n\ -o overwrite files WITHOUT prompting -a auto-convert any text files\n\ -j junk paths (do not make directories) -aa treat ALL files as text\n\ -C match filenames case-insensitively -L make (some) names \ lowercase\n %-42s -V retain VMS version numbers\n%s"; #endif /* ?VMS */ #endif /* ?UNICODE_SUPPORT */ static ZCONST char Far UnzipUsageLine5[] = "\ See \"unzip -hh\" or unzip.txt for more help. Examples:\n\ unzip data1 -x joe => extract all files except joe from zipfile data1.zip\n\ %s\ unzip -fo foo %-6s => quietly replace existing %s if archive file newer\n"; #endif /* ?SFX */ /*****************************/ /* main() / UzpMain() stub */ /*****************************/ int MAIN(argc, argv) /* return PK-type error code (except under VMS) */ int argc; char *argv[]; { int r; CONSTRUCTGLOBALS(); r = unzip(__G__ argc, argv); DESTROYGLOBALS(); RETURN(r); } /*******************************/ /* Primary UnZip entry point */ /*******************************/ int unzip(__G__ argc, argv) __GDEF int argc; char *argv[]; { #ifndef NO_ZIPINFO char *p; #endif #if (defined(DOS_FLX_H68_NLM_OS2_W32) || !defined(SFX)) int i; #endif int retcode, error=FALSE; #ifndef NO_EXCEPT_SIGNALS #ifdef REENTRANT savsigs_info *oldsighandlers = NULL; # define SET_SIGHANDLER(sigtype, newsighandler) \ if ((retcode = setsignalhandler(__G__ &oldsighandlers, (sigtype), \ (newsighandler))) > PK_WARN) \ goto cleanup_and_exit #else # define SET_SIGHANDLER(sigtype, newsighandler) \ signal((sigtype), (newsighandler)) #endif #endif /* NO_EXCEPT_SIGNALS */ /* initialize international char support to the current environment */ SETLOCALE(LC_CTYPE, "C"); #ifdef UNICODE_SUPPORT /* see if can use UTF-8 Unicode locale */ # ifdef UTF8_MAYBE_NATIVE { char *codeset; # if !(defined(NO_NL_LANGINFO) || defined(NO_LANGINFO_H)) /* get the codeset (character set encoding) currently used */ # include codeset = nl_langinfo(CODESET); # else /* NO_NL_LANGINFO || NO_LANGINFO_H */ /* query the current locale setting for character classification */ codeset = setlocale(LC_CTYPE, NULL); if (codeset != NULL) { /* extract the codeset portion of the locale name */ codeset = strchr(codeset, '.'); if (codeset != NULL) ++codeset; } # endif /* ?(NO_NL_LANGINFO || NO_LANGINFO_H) */ /* is the current codeset UTF-8 ? */ if ((codeset != NULL) && (strcmp(codeset, "UTF-8") == 0)) { /* successfully found UTF-8 char coding */ G.native_is_utf8 = TRUE; } else { /* Current codeset is not UTF-8 or cannot be determined. */ G.native_is_utf8 = FALSE; } /* Note: At least for UnZip, trying to change the process codeset to * UTF-8 does not work. For the example Linux setup of the * UnZip maintainer, a successful switch to "en-US.UTF-8" * resulted in garbage display of all non-basic ASCII characters. */ } # endif /* UTF8_MAYBE_NATIVE */ /* initialize Unicode */ G.unicode_escape_all = 0; G.unicode_mismatch = 0; G.unipath_version = 0; G.unipath_checksum = 0; G.unipath_filename = NULL; #endif /* UNICODE_SUPPORT */ #if (defined(__IBMC__) && defined(__DEBUG_ALLOC__)) extern void DebugMalloc(void); atexit(DebugMalloc); #endif #ifdef MALLOC_WORK /* The following (rather complex) expression determines the allocation size of the decompression work area. It simulates what the combined "union" and "struct" declaration of the "static" work area reservation achieves automatically at compile time. Any decent compiler should evaluate this expression completely at compile time and provide constants to the zcalloc() call. (For better readability, some subexpressions are encapsulated in temporarly defined macros.) */ # define UZ_SLIDE_CHUNK (sizeof(shrint)+sizeof(uch)+sizeof(uch)) # define UZ_NUMOF_CHUNKS \ (unsigned)(((WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK > HSIZE) ? \ (WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK : HSIZE) G.area.Slide = (uch *)zcalloc(UZ_NUMOF_CHUNKS, UZ_SLIDE_CHUNK); # undef UZ_SLIDE_CHUNK # undef UZ_NUMOF_CHUNKS G.area.shrink.Parent = (shrint *)G.area.Slide; G.area.shrink.value = G.area.Slide + (sizeof(shrint)*(HSIZE)); G.area.shrink.Stack = G.area.Slide + (sizeof(shrint) + sizeof(uch))*(HSIZE); #endif /*--------------------------------------------------------------------------- Set signal handler for restoring echo, warn of zipfile corruption, etc. ---------------------------------------------------------------------------*/ #ifndef NO_EXCEPT_SIGNALS #ifdef SIGINT SET_SIGHANDLER(SIGINT, handler); #endif #ifdef SIGTERM /* some systems really have no SIGTERM */ SET_SIGHANDLER(SIGTERM, handler); #endif #if defined(SIGABRT) && !(defined(AMIGA) && defined(__SASC)) SET_SIGHANDLER(SIGABRT, handler); #endif #ifdef SIGBREAK SET_SIGHANDLER(SIGBREAK, handler); #endif #ifdef SIGBUS SET_SIGHANDLER(SIGBUS, handler); #endif #ifdef SIGILL SET_SIGHANDLER(SIGILL, handler); #endif #ifdef SIGSEGV SET_SIGHANDLER(SIGSEGV, handler); #endif #endif /* NO_EXCEPT_SIGNALS */ #if (defined(WIN32) && defined(__RSXNT__)) for (i = 0 ; i < argc; i++) { _ISO_INTERN(argv[i]); } #endif /*--------------------------------------------------------------------------- Macintosh initialization code. ---------------------------------------------------------------------------*/ #ifdef MACOS { int a; for (a = 0; a < 4; ++a) G.rghCursor[a] = GetCursor(a+128); G.giCursor = 0; } #endif /*--------------------------------------------------------------------------- NetWare initialization code. ---------------------------------------------------------------------------*/ #ifdef NLM InitUnZipConsole(); #endif /*--------------------------------------------------------------------------- Acorn RISC OS initialization code. ---------------------------------------------------------------------------*/ #ifdef RISCOS set_prefix(); #endif /*--------------------------------------------------------------------------- Theos initialization code. ---------------------------------------------------------------------------*/ #ifdef THEOS /* The easiest way found to force creation of libraries when selected * members are to be unzipped. Explicitly add libraries names to the * arguments list before the first member of the library. */ if (! _setargv(&argc, &argv)) { Info(slide, 0x401, ((char *)slide, "cannot process argv\n")); retcode = PK_MEM; goto cleanup_and_exit; } #endif /*--------------------------------------------------------------------------- Sanity checks. Commentary by Otis B. Driftwood and Fiorello: D: It's all right. That's in every contract. That's what they call a sanity clause. F: Ha-ha-ha-ha-ha. You can't fool me. There ain't no Sanity Claus. ---------------------------------------------------------------------------*/ #ifdef DEBUG # ifdef LARGE_FILE_SUPPORT /* test if we can support large files - 10/6/04 EG */ if (sizeof(zoff_t) < 8) { Info(slide, 0x401, ((char *)slide, "LARGE_FILE_SUPPORT set but not supported\n")); retcode = PK_BADERR; goto cleanup_and_exit; } /* test if we can show 64-bit values */ { zoff_t z = ~(zoff_t)0; /* z should be all 1s now */ char *sz; sz = FmZofft(z, FZOFFT_HEX_DOT_WID, "X"); if ((sz[0] != 'F') || (strlen(sz) != 16)) { z = 0; } /* shift z so only MSB is set */ z <<= 63; sz = FmZofft(z, FZOFFT_HEX_DOT_WID, "X"); if ((sz[0] != '8') || (strlen(sz) != 16)) { Info(slide, 0x401, ((char *)slide, "Can't show 64-bit values correctly\n")); retcode = PK_BADERR; goto cleanup_and_exit; } } # endif /* LARGE_FILE_SUPPORT */ /* 2004-11-30 SMS. Test the NEXTBYTE macro for proper operation. */ { int test_char; static uch test_buf[2] = { 'a', 'b' }; G.inptr = test_buf; G.incnt = 1; test_char = NEXTBYTE; /* Should get 'a'. */ if (test_char == 'a') { test_char = NEXTBYTE; /* Should get EOF, not 'b'. */ } if (test_char != EOF) { Info(slide, 0x401, ((char *)slide, "NEXTBYTE macro failed. Try compiling with ALT_NEXTBYTE defined?")); retcode = PK_BADERR; goto cleanup_and_exit; } } #endif /* DEBUG */ /*--------------------------------------------------------------------------- First figure out if we're running in UnZip mode or ZipInfo mode, and put the appropriate environment-variable options into the queue. Then rip through any command-line options lurking about... ---------------------------------------------------------------------------*/ #ifdef SFX G.argv0 = argv[0]; #if (defined(OS2) || defined(WIN32)) G.zipfn = GetLoadPath(__G);/* non-MSC NT puts path into G.filename[] */ #else G.zipfn = G.argv0; #endif #ifdef VMSCLI { ulg status = vms_unzip_cmdline(&argc, &argv); if (!(status & 1)) { retcode = (int)status; goto cleanup_and_exit; } } #endif /* VMSCLI */ uO.zipinfo_mode = FALSE; error = uz_opts(__G__ &argc, &argv); /* UnZipSFX call only */ #else /* !SFX */ #ifdef RISCOS /* get the extensions to swap from environment */ getRISCOSexts(ENV_UNZIPEXTS); #endif #ifdef MSDOS /* extract MKS extended argument list from environment (before envargs!) */ mksargs(&argc, &argv); #endif #ifdef VMSCLI { ulg status = vms_unzip_cmdline(&argc, &argv); if (!(status & 1)) { retcode = (int)status; goto cleanup_and_exit; } } #endif /* VMSCLI */ G.noargs = (argc == 1); /* no options, no zipfile, no anything */ #ifndef NO_ZIPINFO for (p = argv[0] + strlen(argv[0]); p >= argv[0]; --p) { if (*p == DIR_END #ifdef DIR_END2 || *p == DIR_END2 #endif ) break; } ++p; #ifdef THEOS if (strncmp(p, "ZIPINFO.",8) == 0 || strstr(p, ".ZIPINFO:") != NULL || strncmp(p, "II.",3) == 0 || strstr(p, ".II:") != NULL || #else if (STRNICMP(p, LoadFarStringSmall(Zipnfo), 7) == 0 || STRNICMP(p, "ii", 2) == 0 || #endif (argc > 1 && strncmp(argv[1], "-Z", 2) == 0)) { uO.zipinfo_mode = TRUE; #ifndef _WIN32_WCE /* Win CE does not support environment variables */ if ((error = envargs(&argc, &argv, LoadFarStringSmall(EnvZipInfo), LoadFarStringSmall2(EnvZipInfo2))) != PK_OK) perror(LoadFarString(NoMemEnvArguments)); #endif } else #endif /* !NO_ZIPINFO */ { uO.zipinfo_mode = FALSE; #ifndef _WIN32_WCE /* Win CE does not support environment variables */ if ((error = envargs(&argc, &argv, LoadFarStringSmall(EnvUnZip), LoadFarStringSmall2(EnvUnZip2))) != PK_OK) perror(LoadFarString(NoMemEnvArguments)); #endif } if (!error) { /* Check the length of all passed command line parameters. * Command arguments might get sent through the Info() message * system, which uses the sliding window area as string buffer. * As arguments may additionally get fed through one of the FnFilter * macros, we require all command line arguments to be shorter than * WSIZE/4 (and ca. 2 standard line widths for fixed message text). */ for (i = 1 ; i < argc; i++) { if (strlen(argv[i]) > ((WSIZE>>2) - 160)) { Info(slide, 0x401, ((char *)slide, LoadFarString(CmdLineParamTooLong), i)); retcode = PK_PARAM; goto cleanup_and_exit; } } #ifndef NO_ZIPINFO if (uO.zipinfo_mode) error = zi_opts(__G__ &argc, &argv); else #endif /* !NO_ZIPINFO */ error = uz_opts(__G__ &argc, &argv); } #endif /* ?SFX */ if ((argc < 0) || error) { retcode = error; goto cleanup_and_exit; } /*--------------------------------------------------------------------------- Now get the zipfile name from the command line and then process any re- maining options and file specifications. ---------------------------------------------------------------------------*/ #ifdef DOS_FLX_H68_NLM_OS2_W32 /* convert MSDOS-style 'backward slash' directory separators to Unix-style * 'forward slashes' for user's convenience (include zipfile name itself) */ #ifdef SFX for (G.pfnames = argv, i = argc; i > 0; --i) { #else /* argc does not include the zipfile specification */ for (G.pfnames = argv, i = argc+1; i > 0; --i) { #endif #ifdef __human68k__ extern char *_toslash(char *); _toslash(*G.pfnames); #else /* !__human68k__ */ char *q = *G.pfnames; while (*q != '\0') { if (*q == '\\') *q = '/'; INCSTR(q); } #endif /* ?__human68k__ */ ++G.pfnames; } #endif /* DOS_FLX_H68_NLM_OS2_W32 */ #ifndef SFX G.wildzipfn = *argv++; #endif #if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */ G.filespecs = argc; G.xfilespecs = 0; if (argc > 0) { char **pp = argv-1; G.pfnames = argv; while (*++pp) if (strcmp(*pp, "-x") == 0) { if (pp > argv) { *pp = 0; /* terminate G.pfnames */ G.filespecs = pp - G.pfnames; } else { G.pfnames = (char **)fnames; /* defaults */ G.filespecs = 0; } G.pxnames = pp + 1; /* excluded-names ptr: _after_ -x */ G.xfilespecs = argc - G.filespecs - 1; break; /* skip rest of args */ } G.process_all_files = FALSE; } else G.process_all_files = TRUE; /* for speed */ #else /* !SFX || SFX_EXDIR */ /* check for -x or -d */ G.filespecs = argc; G.xfilespecs = 0; if (argc > 0) { int in_files=FALSE, in_xfiles=FALSE; char **pp = argv-1; G.process_all_files = FALSE; G.pfnames = argv; while (*++pp) { Trace((stderr, "pp - argv = %d\n", pp-argv)); #ifdef CMS_MVS if (!uO.exdir && STRNICMP(*pp, "-d", 2) == 0) { #else if (!uO.exdir && strncmp(*pp, "-d", 2) == 0) { #endif int firstarg = (pp == argv); uO.exdir = (*pp) + 2; if (in_files) { /* ... zipfile ... -d exdir ... */ *pp = (char *)NULL; /* terminate G.pfnames */ G.filespecs = pp - G.pfnames; in_files = FALSE; } else if (in_xfiles) { *pp = (char *)NULL; /* terminate G.pxnames */ G.xfilespecs = pp - G.pxnames; /* "... -x xlist -d exdir": nothing left */ } /* first check for "-dexdir", then for "-d exdir" */ if (*uO.exdir == '\0') { if (*++pp) uO.exdir = *pp; else { Info(slide, 0x401, ((char *)slide, LoadFarString(MustGiveExdir))); /* don't extract here by accident */ retcode = PK_PARAM; goto cleanup_and_exit; } } if (firstarg) { /* ... zipfile -d exdir ... */ if (pp[1]) { G.pfnames = pp + 1; /* argv+2 */ G.filespecs = argc - (G.pfnames-argv); /* for now... */ } else { G.process_all_files = TRUE; G.pfnames = (char **)fnames; /* GRR: necessary? */ G.filespecs = 0; /* GRR: necessary? */ break; } } } else if (!in_xfiles) { if (strcmp(*pp, "-x") == 0) { in_xfiles = TRUE; if (pp == G.pfnames) { G.pfnames = (char **)fnames; /* defaults */ G.filespecs = 0; } else if (in_files) { *pp = 0; /* terminate G.pfnames */ G.filespecs = pp - G.pfnames; /* adjust count */ in_files = FALSE; } G.pxnames = pp + 1; /* excluded-names ptr starts after -x */ G.xfilespecs = argc - (G.pxnames-argv); /* anything left */ } else in_files = TRUE; } } } else G.process_all_files = TRUE; /* for speed */ if (uO.exdir != (char *)NULL && !G.extract_flag) /* -d ignored */ Info(slide, 0x401, ((char *)slide, LoadFarString(NotExtracting))); #endif /* ?(SFX && !SFX_EXDIR) */ #ifdef UNICODE_SUPPORT /* set Unicode-escape-all if option -U used */ if (uO.U_flag == 1) # ifdef UNICODE_WCHAR G.unicode_escape_all = TRUE; # else Info(slide, 0x401, ((char *)slide, LoadFarString(UTF8EscapeUnSupp))); # endif #endif /*--------------------------------------------------------------------------- Okey dokey, we have everything we need to get started. Let's roll. ---------------------------------------------------------------------------*/ retcode = process_zipfiles(__G); cleanup_and_exit: #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS)) /* restore all signal handlers back to their state at function entry */ while (oldsighandlers != NULL) { savsigs_info *thissigsav = oldsighandlers; signal(thissigsav->sigtype, thissigsav->sighandler); oldsighandlers = thissigsav->previous; free(thissigsav); } #endif #if (defined(MALLOC_WORK) && !defined(REENTRANT)) if (G.area.Slide != (uch *)NULL) { free(G.area.Slide); G.area.Slide = (uch *)NULL; } #endif #if (defined(MSDOS) && !defined(SFX) && !defined(WINDLL)) if (retcode != PK_OK) check_for_windows("UnZip"); #endif return(retcode); } /* end main()/unzip() */ #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS)) /*******************************/ /* Function setsignalhandler() */ /*******************************/ static int setsignalhandler(__G__ p_savedhandler_chain, signal_type, newhandler) __GDEF savsigs_info **p_savedhandler_chain; int signal_type; void (*newhandler)(int); { savsigs_info *savsig; savsig = malloc(sizeof(savsigs_info)); if (savsig == NULL) { /* error message and break */ Info(slide, 0x401, ((char *)slide, LoadFarString(CantSaveSigHandler))); return PK_MEM; } savsig->sigtype = signal_type; savsig->sighandler = signal(SIGINT, newhandler); if (savsig->sighandler == SIG_ERR) { free(savsig); } else { savsig->previous = *p_savedhandler_chain; *p_savedhandler_chain = savsig; } return PK_OK; } /* end function setsignalhandler() */ #endif /* REENTRANT && !NO_EXCEPT_SIGNALS */ /**********************/ /* Function uz_opts() */ /**********************/ int uz_opts(__G__ pargc, pargv) __GDEF int *pargc; char ***pargv; { char **argv, *s; int argc, c, error=FALSE, negative=0, showhelp=0; argc = *pargc; argv = *pargv; uO.exdir = sfx_get_tmp_path(0); uO.overwrite_all = 1; sfx_app_set_args(argc-1, argv+1); while (++argv, (--argc > 0 && *argv != NULL /*&& **argv == '-'*/)) { #if 0 s = *argv + 1; while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */ #ifdef CMS_MVS switch (tolower(c)) #else switch (c) #endif { case ('-'): ++negative; break; #ifdef RISCOS case ('/'): if (negative) { /* negative not allowed with -/ swap */ Info(slide, 0x401, ((char *)slide, "error: must give extensions list")); return(PK_PARAM); /* don't extract here by accident */ } exts2swap = s; /* override Unzip$Exts */ s += strlen(s); break; #endif case ('a'): if (negative) { uO.aflag = MAX(uO.aflag-negative,0); negative = 0; } else ++uO.aflag; break; #if (defined(DLL) && defined(API_DOC)) case ('A'): /* extended help for API */ APIhelp(__G__ argc, argv); *pargc = -1; /* signal to exit successfully */ return 0; #endif case ('b'): if (negative) { #if (defined(TANDEM) || defined(VMS)) uO.bflag = MAX(uO.bflag-negative,0); #endif negative = 0; /* do nothing: "-b" is default */ } else { #ifdef VMS if (uO.aflag == 0) ++uO.bflag; #endif #ifdef TANDEM ++uO.bflag; #endif uO.aflag = 0; } break; #ifdef UNIXBACKUP case ('B'): /* -B: back up existing files */ if (negative) uO.B_flag = FALSE, negative = 0; else uO.B_flag = TRUE; break; #endif case ('c'): if (negative) { uO.cflag = FALSE, negative = 0; #ifdef NATIVE uO.aflag = 0; #endif } else { uO.cflag = TRUE; #ifdef NATIVE uO.aflag = 2; /* so you can read it on the screen */ #endif #ifdef DLL if (G.redirect_text) G.redirect_data = 2; #endif } break; #ifndef CMS_MVS case ('C'): /* -C: match filenames case-insensitively */ if (negative) uO.C_flag = FALSE, negative = 0; else uO.C_flag = TRUE; break; #endif /* !CMS_MVS */ #if (!defined(SFX) || defined(SFX_EXDIR)) case ('d'): if (negative) { /* negative not allowed with -d exdir */ Info(slide, 0x401, ((char *)slide, LoadFarString(MustGiveExdir))); return(PK_PARAM); /* don't extract here by accident */ } if (uO.exdir != (char *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(OnlyOneExdir))); return(PK_PARAM); /* GRR: stupid restriction? */ } else { /* first check for "-dexdir", then for "-d exdir" */ uO.exdir = s; if (*uO.exdir == '\0') { if (argc > 1) { --argc; uO.exdir = *++argv; if (*uO.exdir == '-') { Info(slide, 0x401, ((char *)slide, LoadFarString(MustGiveExdir))); return(PK_PARAM); } /* else uO.exdir points at extraction dir */ } else { Info(slide, 0x401, ((char *)slide, LoadFarString(MustGiveExdir))); return(PK_PARAM); } } /* uO.exdir now points at extraction dir (-dexdir or * -d exdir); point s at end of exdir to avoid mis- * interpretation of exdir characters as more options */ if (*s != 0) while (*++s != 0) ; } break; #endif /* !SFX || SFX_EXDIR */ #if (!defined(NO_TIMESTAMPS)) case ('D'): /* -D: Skip restoring dir (or any) timestamp. */ if (negative) { uO.D_flag = MAX(uO.D_flag-negative,0); negative = 0; } else uO.D_flag++; break; #endif /* (!NO_TIMESTAMPS) */ case ('e'): /* just ignore -e, -x options (extract) */ break; #ifdef MACOS case ('E'): /* -E [MacOS] display Mac e.f. when restoring */ if( negative ) { uO.E_flag = FALSE, negative = 0; } else { uO.E_flag = TRUE; } break; #endif /* MACOS */ case ('f'): /* "freshen" (extract only newer files) */ if (negative) uO.fflag = uO.uflag = FALSE, negative = 0; else uO.fflag = uO.uflag = TRUE; break; #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS)) case ('F'): /* Acorn filetype & NFS extension handling */ if (negative) uO.acorn_nfs_ext = FALSE, negative = 0; else uO.acorn_nfs_ext = TRUE; break; #endif /* RISCOS || ACORN_FTYPE_NFS */ case ('h'): /* just print help message and quit */ if (showhelp == 0) { #ifndef SFX if (*s == 'h') showhelp = 2; else #endif /* !SFX */ { showhelp = 1; } } break; #ifdef MACOS case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */ if( negative ) { uO.i_flag = FALSE, negative = 0; } else { uO.i_flag = TRUE; } break; #endif /* MACOS */ case ('j'): /* junk pathnames/directory structure */ if (negative) uO.jflag = FALSE, negative = 0; else uO.jflag = TRUE; break; #if (defined(ATH_BEO) || defined(MACOS)) case ('J'): /* Junk AtheOS, BeOS or MacOS file attributes */ if( negative ) { uO.J_flag = FALSE, negative = 0; } else { uO.J_flag = TRUE; } break; #endif /* ATH_BEO || MACOS */ #ifdef ATH_BEO_UNX case ('K'): if (negative) { uO.K_flag = FALSE, negative = 0; } else { uO.K_flag = TRUE; } break; #endif /* ATH_BEO_UNX */ #ifndef SFX case ('l'): if (negative) { uO.vflag = MAX(uO.vflag-negative,0); negative = 0; } else ++uO.vflag; break; #endif /* !SFX */ #ifndef CMS_MVS case ('L'): /* convert (some) filenames to lowercase */ if (negative) { uO.L_flag = MAX(uO.L_flag-negative,0); negative = 0; } else ++uO.L_flag; break; #endif /* !CMS_MVS */ #ifdef MORE #ifdef CMS_MVS case ('m'): #endif case ('M'): /* send all screen output through "more" fn. */ /* GRR: eventually check for numerical argument => height */ if (negative) G.M_flag = FALSE, negative = 0; else G.M_flag = TRUE; break; #endif /* MORE */ case ('n'): /* don't overwrite any files */ if (negative) uO.overwrite_none = FALSE, negative = 0; else uO.overwrite_none = TRUE; break; #ifdef AMIGA case ('N'): /* restore comments as filenotes */ if (negative) uO.N_flag = FALSE, negative = 0; else uO.N_flag = TRUE; break; #endif /* AMIGA */ case ('o'): /* OK to overwrite files without prompting */ if (negative) { uO.overwrite_all = MAX(uO.overwrite_all-negative,0); negative = 0; } else ++uO.overwrite_all; break; case ('p'): /* pipes: extract to stdout, no messages */ if (negative) { uO.cflag = FALSE; uO.qflag = MAX(uO.qflag-999,0); negative = 0; } else { uO.cflag = TRUE; uO.qflag += 999; } break; #if CRYPT /* GRR: yes, this is highly insecure, but dozens of people * have pestered us for this, so here we go... */ case ('P'): if (negative) { /* negative not allowed with -P passwd */ Info(slide, 0x401, ((char *)slide, LoadFarString(MustGivePasswd))); return(PK_PARAM); /* don't extract here by accident */ } if (uO.pwdarg != (char *)NULL) { /* GRR: eventually support multiple passwords? Info(slide, 0x401, ((char *)slide, LoadFarString(OnlyOnePasswd))); return(PK_PARAM); */ } else { /* first check for "-Ppasswd", then for "-P passwd" */ uO.pwdarg = s; if (*uO.pwdarg == '\0') { if (argc > 1) { --argc; uO.pwdarg = *++argv; if (*uO.pwdarg == '-') { Info(slide, 0x401, ((char *)slide, LoadFarString(MustGivePasswd))); return(PK_PARAM); } /* else pwdarg points at decryption password */ } else { Info(slide, 0x401, ((char *)slide, LoadFarString(MustGivePasswd))); return(PK_PARAM); } } /* pwdarg now points at decryption password (-Ppasswd or * -P passwd); point s at end of passwd to avoid mis- * interpretation of passwd characters as more options */ if (*s != 0) while (*++s != 0) ; } break; #endif /* CRYPT */ case ('q'): /* quiet: fewer comments/messages */ if (negative) { uO.qflag = MAX(uO.qflag-negative,0); negative = 0; } else ++uO.qflag; break; #ifdef QDOS case ('Q'): /* QDOS flags */ qlflag ^= strtol(s, &s, 10); break; /* we XOR this as we can config qlflags */ #endif #ifdef TANDEM case ('r'): /* remove file extensions */ if (negative) uO.rflag = FALSE, negative = 0; else uO.rflag = TRUE; break; #endif /* TANDEM */ #ifdef DOS_FLX_NLM_OS2_W32 case ('s'): /* spaces in filenames: allow by default */ if (negative) uO.sflag = FALSE, negative = 0; else uO.sflag = TRUE; break; #endif /* DOS_FLX_NLM_OS2_W32 */ #ifdef VMS /* VMS: extract "text" files in Stream_LF format (-a[a]) */ case ('S'): if (negative) uO.S_flag = FALSE, negative = 0; else uO.S_flag = TRUE; break; #endif /* VMS */ case ('t'): if (negative) uO.tflag = FALSE, negative = 0; else uO.tflag = TRUE; break; #ifdef TIMESTAMP case ('T'): if (negative) uO.T_flag = FALSE, negative = 0; else uO.T_flag = TRUE; break; #endif case ('u'): /* update (extract only new and newer files) */ if (negative) uO.uflag = FALSE, negative = 0; else uO.uflag = TRUE; break; #ifdef UNICODE_SUPPORT case ('U'): /* escape UTF-8, or disable UTF-8 support */ if (negative) { uO.U_flag = MAX(uO.U_flag-negative,0); negative = 0; } else uO.U_flag++; break; #else /* !UNICODE_SUPPORT */ #ifndef CMS_MVS case ('U'): /* obsolete; to be removed in version 6.0 */ if (negative) uO.L_flag = TRUE, negative = 0; else uO.L_flag = FALSE; break; #endif /* !CMS_MVS */ #endif /* ?UNICODE_SUPPORT */ #ifndef SFX case ('v'): /* verbose */ if (negative) { uO.vflag = MAX(uO.vflag-negative,0); negative = 0; } else if (uO.vflag) ++uO.vflag; else uO.vflag = 2; break; #endif /* !SFX */ #ifndef CMS_MVS case ('V'): /* Version (retain VMS/DEC-20 file versions) */ if (negative) uO.V_flag = FALSE, negative = 0; else uO.V_flag = TRUE; break; #endif /* !CMS_MVS */ #ifdef WILD_STOP_AT_DIR case ('W'): /* Wildcard interpretation (stop at '/'?) */ if (negative) uO.W_flag = FALSE, negative = 0; else uO.W_flag = TRUE; break; #endif /* WILD_STOP_AT_DIR */ case ('x'): /* extract: default */ #ifdef SFX /* when 'x' is the only option in this argument, and the * next arg is not an option, assume this initiates an * exclusion list (-x xlist): terminate option-scanning * and leave uz_opts with argv still pointing to "-x"; * the xlist is processed later */ if (s - argv[0] == 2 && *s == '\0' && argc > 1 && argv[1][0] != '-') { /* break out of nested loops without "++argv;--argc" */ goto opts_done; } #endif /* SFX */ break; #if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL)) case ('X'): /* restore owner/protection info (need privs?) */ if (negative) { uO.X_flag = MAX(uO.X_flag-negative,0); negative = 0; } else ++uO.X_flag; break; #endif /* RESTORE_UIDGID || RESTORE_ACL */ #ifdef VMS case ('Y'): /* Treat ".nnn" as ";nnn" version. */ if (negative) uO.Y_flag = FALSE, negative = 0; else uO.Y_flag = TRUE; break; #endif /* VMS */ case ('z'): /* display only the archive comment */ if (negative) { uO.zflag = MAX(uO.zflag-negative,0); negative = 0; } else ++uO.zflag; break; #ifndef SFX case ('Z'): /* should have been first option (ZipInfo) */ Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst))); error = TRUE; break; #endif /* !SFX */ #ifdef VMS case ('2'): /* Force ODS2-compliant names. */ if (negative) uO.ods2_flag = FALSE, negative = 0; else uO.ods2_flag = TRUE; break; #endif /* VMS */ #ifdef DOS_H68_OS2_W32 case ('$'): if (negative) { uO.volflag = MAX(uO.volflag-negative,0); negative = 0; } else ++uO.volflag; break; #endif /* DOS_H68_OS2_W32 */ #if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM)) case (':'): /* allow "parent dir" path components */ if (negative) { uO.ddotflag = MAX(uO.ddotflag-negative,0); negative = 0; } else ++uO.ddotflag; break; #endif /* !RISCOS && !CMS_MVS && !TANDEM */ #ifdef UNIX case ('^'): /* allow control chars in filenames */ if (negative) { uO.cflxflag = MAX(uO.cflxflag-negative,0); negative = 0; } else ++uO.cflxflag; break; #endif /* UNIX */ default: error = TRUE; break; } /* end switch */ } /* end while (not end of argument string) */ #endif } /* end while (not done with switches) */ /*--------------------------------------------------------------------------- Check for nonsensical combinations of options. ---------------------------------------------------------------------------*/ #if 0 #ifdef SFX opts_done: /* yes, very ugly...but only used by UnZipSFX with -x xlist */ #endif if (showhelp > 0) { /* just print help message and quit */ *pargc = -1; #ifndef SFX if (showhelp == 2) { help_extended(__G); return PK_OK; } else #endif /* !SFX */ { return USAGE(PK_OK); } } if ((uO.cflag && (uO.tflag || uO.uflag)) || (uO.tflag && uO.uflag) || (uO.fflag && uO.overwrite_none)) { Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg))); error = TRUE; } if (uO.aflag > 2) uO.aflag = 2; #ifdef VMS if (uO.bflag > 2) uO.bflag = 2; /* Clear -s flag when converting text files. */ if (uO.aflag <= 0) uO.S_flag = 0; #endif /* VMS */ if (uO.overwrite_all && uO.overwrite_none) { Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg))); uO.overwrite_all = FALSE; } #ifdef MORE if (G.M_flag && !isatty(1)) /* stdout redirected: "more" func. useless */ G.M_flag = 0; #endif #ifdef SFX if (error) #else if ((argc-- == 0) || error) #endif { *pargc = argc; *pargv = argv; #ifndef SFX if (uO.vflag >= 2 && argc == -1) { /* "unzip -v" */ show_version_info(__G); return PK_OK; } if (!G.noargs && !error) error = TRUE; /* had options (not -h or -v) but no zipfile */ #endif /* !SFX */ return USAGE(error); } #endif #ifdef SFX /* print our banner unless we're being fairly quiet */ if (uO.qflag < 2) Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner), UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, LoadFarStringSmall(VersionDate))); #ifdef BETA /* always print the beta warning: no unauthorized distribution!! */ Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n", "SFX")); #endif #endif /* SFX */ if (uO.cflag || uO.tflag || uO.vflag || uO.zflag #ifdef TIMESTAMP || uO.T_flag #endif ) G.extract_flag = FALSE; else G.extract_flag = TRUE; *pargc = argc; *pargv = argv; return PK_OK; } /* end function uz_opts() */ /********************/ /* Function usage() */ /********************/ #ifdef SFX # ifdef VMS # define LOCAL "X.\n\ (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)" # endif # ifdef UNIX # define LOCAL "X" # endif # ifdef DOS_OS2_W32 # define LOCAL "s$" # endif # if (defined(FLEXOS) || defined(NLM)) # define LOCAL "s" # endif # ifdef AMIGA # define LOCAL "N" # endif /* Default for all other systems: */ # ifndef LOCAL # define LOCAL "" # endif # ifndef NO_TIMESTAMP # ifdef MORE # define SFXOPT1 "DM" # else # define SFXOPT1 "D" # endif # else # ifdef MORE # define SFXOPT1 "M" # else # define SFXOPT1 "" # endif # endif int usage(__G__ error) /* return PK-type error code */ __GDEF int error; { Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner), UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, LoadFarStringSmall(VersionDate))); Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXOpts), SFXOPT1, LOCAL)); #ifdef BETA Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n", "SFX")); #endif if (error) return PK_PARAM; else return PK_COOL; /* just wanted usage screen: no error */ } /* end function usage() */ #else /* !SFX */ # ifdef VMS # define QUOT '\"' # define QUOTS "\"" # else # define QUOT ' ' # define QUOTS "" # endif int usage(__G__ error) /* return PK-type error code */ __GDEF int error; { int flag = (error? 1 : 0); /*--------------------------------------------------------------------------- Print either ZipInfo usage or UnZip usage, depending on incantation. (Strings must be no longer than 512 bytes for Turbo C, apparently.) ---------------------------------------------------------------------------*/ if (uO.zipinfo_mode) { #ifndef NO_ZIPINFO Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine1), ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, LoadFarStringSmall(VersionDate), LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS)); Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine2))); Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine3), LoadFarStringSmall(ZipInfoUsageLine4))); #ifdef VMS Info(slide, flag, ((char *)slide, "\n\ You must quote non-lowercase options and filespecs, unless SET PROC/PARSE=EXT.\ \n")); #endif #endif /* !NO_ZIPINFO */ } else { /* UnZip mode */ Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine1), UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, LoadFarStringSmall(VersionDate))); #ifdef BETA Info(slide, flag, ((char *)slide, LoadFarString(BetaVersion), "", "")); #endif Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine2), ZIPINFO_MODE_OPTION, LoadFarStringSmall(ZipInfoMode))); #ifdef VMS if (!error) /* maybe no command-line tail found; show extra help */ Info(slide, flag, ((char *)slide, LoadFarString(VMSusageLine2b))); #endif Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine3), LoadFarStringSmall(local1))); Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine4), LoadFarStringSmall(local2), LoadFarStringSmall2(local3))); /* This is extra work for SMALL_MEM, but it will work since * LoadFarStringSmall2 uses the same buffer. Remember, this * is a hack. */ Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine5), LoadFarStringSmall(Example2), LoadFarStringSmall2(Example3), LoadFarStringSmall2(Example3))); } /* end if (uO.zipinfo_mode) */ if (error) return PK_PARAM; else return PK_COOL; /* just wanted usage screen: no error */ } /* end function usage() */ #endif /* ?SFX */ #ifndef SFX /* Print extended help to stdout. */ static void help_extended(__G) __GDEF { extent i; /* counter for help array */ /* help array */ static ZCONST char *text[] = { "", "Extended Help for UnZip", "", "See the UnZip Manual for more detailed help", "", "", "UnZip lists and extracts files in zip archives. The default action is to", "extract zipfile entries to the current directory, creating directories as", "needed. With appropriate options, UnZip lists the contents of archives", "instead.", "", "Basic unzip command line:", " unzip [-Z] options archive[.zip] [file ...] [-x xfile ...] [-d exdir]", "", "Some examples:", " unzip -l foo.zip - list files in short format in archive foo.zip", "", " unzip -t foo - test the files in archive foo", "", " unzip -Z foo - list files using more detailed zipinfo format", "", " unzip foo - unzip the contents of foo in current dir", "", " unzip -a foo - unzip foo and convert text files to local OS", "", "If unzip is run in zipinfo mode, a more detailed list of archive contents", "is provided. The -Z option sets zipinfo mode and changes the available", "options.", "", "Basic zipinfo command line:", " zipinfo options archive[.zip] [file ...] [-x xfile ...]", " unzip -Z options archive[.zip] [file ...] [-x xfile ...]", "", "Below, Mac OS refers to Mac OS before Mac OS X. Mac OS X is a Unix based", "port and is referred to as Unix Apple.", "", "", "unzip options:", " -Z Switch to zipinfo mode. Must be first option.", " -hh Display extended help.", " -A [OS/2, Unix DLL] Print extended help for DLL.", " -c Extract files to stdout/screen. As -p but include names. Also,", " -a allowed and EBCDIC conversions done if needed.", " -f Freshen by extracting only if older file on disk.", " -l List files using short form.", " -p Extract files to pipe (stdout). Only file data is output and all", " files extracted in binary mode (as stored).", " -t Test archive files.", " -T Set timestamp on archive(s) to that of newest file. Similar to", " zip -o but faster.", " -u Update existing older files on disk as -f and extract new files.", " -v Use verbose list format. If given alone as unzip -v show version", " information. Also can be added to other list commands for more", " verbose output.", " -z Display only archive comment.", "", "unzip modifiers:", " -a Convert text files to local OS format. Convert line ends, EOF", " marker, and from or to EBCDIC character set as needed.", " -b Treat all files as binary. [Tandem] Force filecode 180 ('C').", " [VMS] Autoconvert binary files. -bb forces convert of all files.", " -B [UNIXBACKUP compile option enabled] Save a backup copy of each", " overwritten file in foo~ or foo~99999 format.", " -C Use case-insensitive matching.", " -D Skip restoration of timestamps for extracted directories. On VMS this", " is on by default and -D essentially becames -DD.", " -DD Skip restoration of timestamps for all entries.", " -E [MacOS (not Unix Apple)] Display contents of MacOS extra field during", " restore.", " -F [Acorn] Suppress removal of NFS filetype extension. [Non-Acorn if", " ACORN_FTYPE_NFS] Translate filetype and append to name.", " -i [MacOS] Ignore filenames in MacOS extra field. Instead, use name in", " standard header.", " -j Junk paths and deposit all files in extraction directory.", " -J [BeOS] Junk file attributes. [MacOS] Ignore MacOS specific info.", " -K [AtheOS, BeOS, Unix] Restore SUID/SGID/Tacky file attributes.", " -L Convert to lowercase any names from uppercase only file system.", " -LL Convert all files to lowercase.", " -M Pipe all output through internal pager similar to Unix more(1).", " -n Never overwrite existing files. Skip extracting that file, no prompt.", " -N [Amiga] Extract file comments as Amiga filenotes.", " -o Overwrite existing files without prompting. Useful with -f. Use with", " care.", " -P p Use password p to decrypt files. THIS IS INSECURE! Some OS show", " command line to other users.", " -q Perform operations quietly. The more q (as in -qq) the quieter.", " -s [OS/2, NT, MS-DOS] Convert spaces in filenames to underscores.", " -S [VMS] Convert text files (-a, -aa) into Stream_LF format.", " -U [UNICODE enabled] Show non-local characters as #Uxxxx or #Lxxxxxx ASCII", " text escapes where x is hex digit. [Old] -U used to leave names", " uppercase if created on MS-DOS, VMS, etc. See -L.", " -UU [UNICODE enabled] Disable use of stored UTF-8 paths. Note that UTF-8", " paths stored as native local paths are still processed as Unicode.", " -V Retain VMS file version numbers.", " -W [Only if WILD_STOP_AT_DIR] Modify pattern matching so ? and * do not", " match directory separator /, but ** does. Allows matching at specific", " directory levels.", " -X [VMS, Unix, OS/2, NT, Tandem] Restore UICs and ACL entries under VMS,", " or UIDs/GIDs under Unix, or ACLs under certain network-enabled", " versions of OS/2, or security ACLs under Windows NT. Can require", " user privileges.", " -XX [NT] Extract NT security ACLs after trying to enable additional", " system privileges.", " -Y [VMS] Treat archived name endings of .nnn as VMS version numbers.", " -$ [MS-DOS, OS/2, NT] Restore volume label if extraction medium is", " removable. -$$ allows fixed media (hard drives) to be labeled.", " -/ e [Acorn] Use e as extension list.", " -: [All but Acorn, VM/CMS, MVS, Tandem] Allow extract archive members into", " locations outside of current extraction root folder. This allows", " paths such as ../foo to be extracted above the current extraction", " directory, which can be a security problem.", " -^ [Unix] Allow control characters in names of extracted entries. Usually", " this is not a good thing and should be avoided.", " -2 [VMS] Force unconditional conversion of names to ODS-compatible names.", " Default is to exploit destination file system, preserving cases and", " extended name characters on ODS5 and applying ODS2 filtering on ODS2.", "", "", "Wildcards:", " Internally unzip supports the following wildcards:", " ? (or %% or #, depending on OS) matches any single character", " * matches any number of characters, including zero", " [list] matches char in list (regex), can do range [ac-f], all but [!bf]", " If port supports [], must escape [ as [[]", " For shells that expand wildcards, escape (\\* or \"*\") so unzip can recurse.", "", "Include and Exclude:", " -i pattern pattern ... include files that match a pattern", " -x pattern pattern ... exclude files that match a pattern", " Patterns are paths with optional wildcards and match paths as stored in", " archive. Exclude and include lists end at next option or end of line.", " unzip archive -x pattern pattern ...", "", "Multi-part (split) archives (archives created as a set of split files):", " Currently split archives are not readable by unzip. A workaround is", " to use zip to convert the split archive to a single-file archive and", " use unzip on that. See the manual page for Zip 3.0 or later.", "", "Streaming (piping into unzip):", " Currently unzip does not support streaming. The funzip utility can be", " used to process the first entry in a stream.", " cat archive | funzip", "", "Testing archives:", " -t test contents of archive", " This can be modified using -q for quieter operation, and -qq for even", " quieter operation.", "", "Unicode:", " If compiled with Unicode support, unzip automatically handles archives", " with Unicode entries. Currently Unicode on Win32 systems is limited.", " Characters not in the current character set are shown as ASCII escapes", " in the form #Uxxxx where the Unicode character number fits in 16 bits,", " or #Lxxxxxx where it doesn't, where x is the ASCII character for a hex", " digit.", "", "", "zipinfo options (these are used in zipinfo mode (unzip -Z ...)):", " -1 List names only, one per line. No headers/trailers. Good for scripts.", " -2 List names only as -1, but include headers, trailers, and comments.", " -s List archive entries in short Unix ls -l format. Default list format.", " -m List in long Unix ls -l format. As -s, but includes compression %.", " -l List in long Unix ls -l format. As -m, but compression in bytes.", " -v List zipfile information in verbose, multi-page format.", " -h List header line. Includes archive name, actual size, total files.", " -M Pipe all output through internal pager similar to Unix more(1) command.", " -t List totals for files listed or for all files. Includes uncompressed", " and compressed sizes, and compression factors.", " -T Print file dates and times in a sortable decimal format (yymmdd.hhmmss)", " Default date and time format is a more human-readable version.", " -U [UNICODE] If entry has a UTF-8 Unicode path, display any characters", " not in current character set as text #Uxxxx and #Lxxxxxx escapes", " representing the Unicode character number of the character in hex.", " -UU [UNICODE] Disable use of any UTF-8 path information.", " -z Include archive comment if any in listing.", "", "", "funzip stream extractor:", " funzip extracts the first member in an archive to stdout. Typically", " used to unzip the first member of a stream or pipe. If a file argument", " is given, read from that file instead of stdin.", "", "funzip command line:", " funzip [-password] [input[.zip|.gz]]", "", "", "unzipsfx self extractor:", " Self-extracting archives made with unzipsfx are no more (or less)", " portable across different operating systems than unzip executables.", " In general, a self-extracting archive made on a particular Unix system,", " for example, will only self-extract under the same flavor of Unix.", " Regular unzip may still be used to extract embedded archive however.", "", "unzipsfx command line:", " [-options] [file(s) ... [-x xfile(s) ...]]", "", "unzipsfx options:", " -c, -p - Output to pipe. (See above for unzip.)", " -f, -u - Freshen and Update, as for unzip.", " -t - Test embedded archive. (Can be used to list contents.)", " -z - Print archive comment. (See unzip above.)", "", "unzipsfx modifiers:", " Most unzip modifiers are supported. These include", " -a - Convert text files.", " -n - Never overwrite.", " -o - Overwrite without prompting.", " -q - Quiet operation.", " -C - Match names case-insensitively.", " -j - Junk paths.", " -V - Keep version numbers.", " -s - Convert spaces to underscores.", " -$ - Restore volume label.", "", "If unzipsfx compiled with SFX_EXDIR defined, -d option also available:", " -d exd - Extract to directory exd.", "By default, all files extracted to current directory. This option", "forces extraction to specified directory.", "", "See unzipsfx manual page for more information.", "" }; for (i = 0; i < sizeof(text)/sizeof(char *); i++) { Info(slide, 0, ((char *)slide, "%s\n", text[i])); } } /* end function help_extended() */ #ifndef _WIN32_WCE /* Win CE does not support environment variables */ #if (!defined(MODERN) || defined(NO_STDLIB_H)) /* Declare getenv() to be sure (might be missing in some environments) */ extern char *getenv(); #endif #endif /********************************/ /* Function show_version_info() */ /********************************/ static void show_version_info(__G) __GDEF { if (uO.qflag > 3) /* "unzip -vqqqq" */ Info(slide, 0, ((char *)slide, "%d\n", (UZ_MAJORVER*100 + UZ_MINORVER*10 + UZ_PATCHLEVEL))); else { #ifndef _WIN32_WCE /* Win CE does not support environment variables */ char *envptr; #endif int numopts = 0; Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine1v), UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, LoadFarStringSmall(VersionDate))); Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine2v))); version(__G); Info(slide, 0, ((char *)slide, LoadFarString(CompileOptions))); #ifdef ACORN_FTYPE_NFS Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(AcornFtypeNFS))); ++numopts; #endif #ifdef ASM_CRC Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(AsmCRC))); ++numopts; #endif #ifdef ASM_INFLATECODES Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(AsmInflateCodes))); ++numopts; #endif #ifdef CHECK_VERSIONS Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Check_Versions))); ++numopts; #endif #ifdef COPYRIGHT_CLEAN Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Copyright_Clean))); ++numopts; #endif #ifdef DEBUG Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(UDebug))); ++numopts; #endif #ifdef DEBUG_TIME Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(DebugTime))); ++numopts; #endif #ifdef DLL Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Dll))); ++numopts; #endif #ifdef DOSWILD Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(DosWild))); ++numopts; #endif #ifdef LZW_CLEAN Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(LZW_Clean))); ++numopts; #endif #ifndef MORE Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(No_More))); ++numopts; #endif #ifdef NO_ZIPINFO Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(No_ZipInfo))); ++numopts; #endif #ifdef NTSD_EAS Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(NTSDExtAttrib))); ++numopts; #endif #if defined(WIN32) && defined(NO_W32TIMES_IZFIX) Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(W32NoIZTimeFix))); ++numopts; #endif #ifdef OLD_THEOS_EXTRA Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(OldTheosExtra))); ++numopts; #endif #ifdef OS2_EAS Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(OS2ExtAttrib))); ++numopts; #endif #ifdef QLZIP Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(SMSExFldOnUnix))); ++numopts; #endif #ifdef REENTRANT Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Reentrant))); ++numopts; #endif #ifdef REGARGS Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(RegArgs))); ++numopts; #endif #ifdef RETURN_CODES Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Return_Codes))); ++numopts; #endif #ifdef SET_DIR_ATTRIB Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(SetDirAttrib))); ++numopts; #endif #ifdef SYMLINKS Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(SymLinkSupport))); ++numopts; #endif #ifdef TIMESTAMP Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(TimeStamp))); ++numopts; #endif #ifdef UNIXBACKUP Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(UnixBackup))); ++numopts; #endif #ifdef USE_EF_UT_TIME Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_EF_UT_time))); ++numopts; #endif #ifndef COPYRIGHT_CLEAN Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_Smith_Code))); ++numopts; #endif #ifndef LZW_CLEAN Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_Unshrink))); ++numopts; #endif #ifdef USE_DEFLATE64 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_Deflate64))); ++numopts; #endif #ifdef UNICODE_SUPPORT # ifdef UTF8_MAYBE_NATIVE sprintf((char *)(slide+256), LoadFarStringSmall(Use_Unicode), LoadFarStringSmall2(G.native_is_utf8 ? SysChUTF8 : SysChOther)); Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), (char *)(slide+256))); # else Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_Unicode))); # endif ++numopts; #endif #ifdef _MBCS sprintf((char *)(slide+256), LoadFarStringSmall(Have_MBCS_Support), (unsigned int)MB_CUR_MAX); Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), (char *)(slide+256))); ++numopts; #endif #ifdef MULT_VOLUME Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_MultiVol))); ++numopts; #endif #ifdef LARGE_FILE_SUPPORT Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_LFS))); ++numopts; #endif #ifdef ZIP64_SUPPORT Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_Zip64))); ++numopts; #endif #if (defined(__DJGPP__) && (__DJGPP__ >= 2)) # ifdef USE_DJGPP_ENV Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_DJGPP_Env))); ++numopts; # endif # ifdef USE_DJGPP_GLOB Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_DJGPP_Glob))); ++numopts; # endif #endif /* __DJGPP__ && (__DJGPP__ >= 2) */ #ifdef USE_VFAT Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_VFAT_support))); ++numopts; #endif #ifdef USE_ZLIB sprintf((char *)(slide+256), LoadFarStringSmall(UseZlib), ZLIB_VERSION, zlibVersion()); Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), (char *)(slide+256))); ++numopts; #endif #ifdef USE_BZIP2 sprintf((char *)(slide+256), LoadFarStringSmall(UseBZip2), BZ2_bzlibVersion()); Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), (char *)(slide+256))); ++numopts; #endif #ifdef VMS_TEXT_CONV Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(VmsTextConv))); ++numopts; #endif #ifdef VMSCLI Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(VmsCLI))); ++numopts; #endif #ifdef VMSWILD Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(VmsWild))); ++numopts; #endif #ifdef WILD_STOP_AT_DIR Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(WildStopAtDir))); ++numopts; #endif #if CRYPT # ifdef PASSWD_FROM_STDIN Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(PasswdStdin))); # endif Info(slide, 0, ((char *)slide, LoadFarString(Decryption), CR_MAJORVER, CR_MINORVER, CR_BETA_VER, LoadFarStringSmall(CryptDate))); ++numopts; #endif /* CRYPT */ if (numopts == 0) Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(None))); #ifndef _WIN32_WCE /* Win CE does not support environment variables */ Info(slide, 0, ((char *)slide, LoadFarString(EnvOptions))); envptr = getenv(LoadFarStringSmall(EnvUnZip)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvUnZip), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); envptr = getenv(LoadFarStringSmall(EnvUnZip2)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvUnZip2), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); envptr = getenv(LoadFarStringSmall(EnvZipInfo)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvZipInfo), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); envptr = getenv(LoadFarStringSmall(EnvZipInfo2)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvZipInfo2), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); #ifndef __RSXNT__ #ifdef __EMX__ envptr = getenv(LoadFarStringSmall(EnvEMX)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvEMX), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); envptr = getenv(LoadFarStringSmall(EnvEMXOPT)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvEMXOPT), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); #endif /* __EMX__ */ #if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2))) envptr = getenv(LoadFarStringSmall(EnvGO32)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvGO32), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); envptr = getenv(LoadFarStringSmall(EnvGO32TMP)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvGO32TMP), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); #endif /* __GO32__ && !(__DJGPP__ >= 2) */ #endif /* !__RSXNT__ */ #ifdef RISCOS envptr = getenv(LoadFarStringSmall(EnvUnZipExts)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvUnZipExts), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); #endif /* RISCOS */ #endif /* !_WIN32_WCE */ } } /* end function show_version() */ #endif /* !SFX */ #endif /* !WINDLL */ Carla-2.1/data/windows/unzipfx-carla-control/unzip.h000066400000000000000000000630401364475620200225740ustar00rootroot00000000000000/*--------------------------------------------------------------------------- unzip.h (new) Copyright (c) 1990-2009 Info-ZIP. All rights reserved. This header file contains the public macros and typedefs required by both the UnZip sources and by any application using the UnZip API. If UNZIP_INTERNAL is defined, it includes unzpriv.h (containing includes, prototypes and extern variables used by the actual UnZip sources). ---------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- This is version 2009-Jan-02 of the Info-ZIP license. The definitive version of this document should be available at ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and a copy at http://www.info-zip.org/pub/infozip/license.html. Copyright (c) 1990-2009 Info-ZIP. All rights reserved. For the purposes of this copyright and license, "Info-ZIP" is defined as the following set of individuals: Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois, Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth, Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko, Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs, Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda, Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren, Rich Wales, Mike White. This software is provided "as is," without warranty of any kind, express or implied. In no event shall Info-ZIP or its contributors be held liable for any direct, indirect, incidental, special or consequential damages arising out of the use of or inability to use this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the above disclaimer and the following restrictions: 1. Redistributions of source code (in whole or in part) must retain the above copyright notice, definition, disclaimer, and this list of conditions. 2. Redistributions in binary form (compiled executables and libraries) must reproduce the above copyright notice, definition, disclaimer, and this list of conditions in documentation and/or other materials provided with the distribution. Additional documentation is not needed for executables where a command line license option provides these and a note regarding this option is in the executable's startup banner. The sole exception to this condition is redistribution of a standard UnZipSFX binary (including SFXWiz) as part of a self-extracting archive; that is permitted without inclusion of this license, as long as the normal SFX banner has not been removed from the binary or disabled. 3. Altered versions--including, but not limited to, ports to new operating systems, existing ports with new graphical interfaces, versions with modified or added functionality, and dynamic, shared, or static library versions not from Info-ZIP--must be plainly marked as such and must not be misrepresented as being the original source or, if binaries, compiled from the original source. Such altered versions also must not be misrepresented as being Info-ZIP releases--including, but not limited to, labeling of the altered versions with the names "Info-ZIP" (or any variation thereof, including, but not limited to, different capitalizations), "Pocket UnZip," "WiZ" or "MacZip" without the explicit permission of Info-ZIP. Such altered versions are further prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP will provide support for the altered versions. 4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip," "UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its own source and binary releases. ---------------------------------------------------------------------------*/ #ifndef __unzip_h /* prevent multiple inclusions */ #define __unzip_h /*--------------------------------------------------------------------------- Predefined, machine-specific macros. ---------------------------------------------------------------------------*/ #ifdef __GO32__ /* MS-DOS extender: NOT Unix */ # ifdef unix # undef unix # endif # ifdef _unix # undef _unix # endif # ifdef __unix # undef __unix # endif # ifdef __unix__ # undef __unix__ # endif #endif #if ((defined(__convex__) || defined(__convexc__)) && !defined(CONVEX)) # define CONVEX #endif #if (defined(unix) || defined(_unix) || defined(__unix) || defined(__unix__)) # ifndef UNIX # define UNIX # endif #endif /* unix || _unix || __unix || __unix__ */ #if (defined(M_XENIX) || defined(COHERENT) || defined(__hpux)) # ifndef UNIX # define UNIX # endif #endif /* M_XENIX || COHERENT || __hpux */ #if (defined(__NetBSD__) || defined(__FreeBSD__)) # ifndef UNIX # define UNIX # endif #endif /* __NetBSD__ || __FreeBSD__ */ #if (defined(CONVEX) || defined(MINIX) || defined(_AIX) || defined(__QNX__)) # ifndef UNIX # define UNIX # endif #endif /* CONVEX || MINIX || _AIX || __QNX__ */ #if (defined(VM_CMS) || defined(MVS)) # define CMS_MVS #endif #if (defined(__OS2__) && !defined(OS2)) # define OS2 #endif #if (defined(__TANDEM) && !defined(TANDEM)) # define TANDEM #endif #if (defined(__VMS) && !defined(VMS)) # define VMS #endif #if ((defined(__WIN32__) || defined(_WIN32)) && !defined(WIN32)) # define WIN32 #endif #if ((defined(__WINNT__) || defined(__WINNT)) && !defined(WIN32)) # define WIN32 #endif #if defined(_WIN32_WCE) # ifndef WIN32 /* WinCE is treated as a variant of the Win32 API */ # define WIN32 # endif # ifndef UNICODE /* WinCE requires UNICODE wide character support */ # define UNICODE # endif #endif #ifdef __COMPILER_KCC__ # include # ifdef SYS_T20 # define TOPS20 # endif #endif /* __COMPILER_KCC__ */ /* Borland C does not define __TURBOC__ if compiling for a 32-bit platform */ #ifdef __BORLANDC__ # ifndef __TURBOC__ # define __TURBOC__ # endif # if (!defined(__MSDOS__) && !defined(OS2) && !defined(WIN32)) # define __MSDOS__ # endif #endif /* define MSDOS for Turbo C (unless OS/2) and Power C as well as Microsoft C */ #ifdef __POWERC # define __TURBOC__ # define MSDOS #endif /* __POWERC */ #if (defined(__MSDOS__) && !defined(MSDOS)) /* just to make sure */ # define MSDOS #endif /* RSXNTDJ (at least up to v1.3) compiles for WIN32 (RSXNT) using a derivate of the EMX environment, but defines MSDOS and __GO32__. ARG !!! */ #if (defined(MSDOS) && defined(WIN32)) # undef MSDOS /* WIN32 is >>>not<<< MSDOS */ #endif #if (defined(__GO32__) && defined(__EMX__) && defined(__RSXNT__)) # undef __GO32__ #endif #if (defined(linux) && !defined(LINUX)) # define LINUX #endif #ifdef __riscos # define RISCOS #endif #if (defined(THINK_C) || defined(MPW)) # define MACOS #endif #if (defined(__MWERKS__) && defined(macintosh)) # define MACOS #endif /* use prototypes and ANSI libraries if __STDC__, or MS-DOS, or OS/2, or Win32, * or IBM C Set/2, or Borland C, or Watcom C, or GNU gcc (emx or Cygwin), * or Macintosh, or Sequent, or Atari, or IBM RS/6000, or Silicon Graphics, * or Convex?, or AtheOS, or BeOS. */ #if (defined(__STDC__) || defined(MSDOS) || defined(OS2) || defined(WIN32)) # ifndef PROTO # define PROTO # endif # ifndef MODERN # define MODERN # endif #endif #if (defined(__IBMC__) || defined(__BORLANDC__) || defined(__WATCOMC__)) # ifndef PROTO # define PROTO # endif # ifndef MODERN # define MODERN # endif #endif #if (defined(__EMX__) || defined(__CYGWIN__)) # ifndef PROTO # define PROTO # endif # ifndef MODERN # define MODERN # endif #endif #if (defined(MACOS) || defined(ATARI_ST) || defined(RISCOS) || defined(THEOS)) # ifndef PROTO # define PROTO # endif # ifndef MODERN # define MODERN # endif #endif /* Sequent running Dynix/ptx: non-modern compiler */ #if (defined(_AIX) || defined(sgi) || (defined(_SEQUENT_) && !defined(PTX))) # ifndef PROTO # define PROTO # endif # ifndef MODERN # define MODERN # endif #endif #if (defined(CMS_MVS) || defined(__ATHEOS__) || defined(__BEOS__)) /* || defined(CONVEX) ? */ # ifndef PROTO # define PROTO # endif # ifndef MODERN # define MODERN # endif #endif /* Bundled C compiler on HP-UX needs this. Others shouldn't care. */ #if (defined(__hpux)) # ifndef MODERN # define MODERN # endif #endif /* turn off prototypes if requested */ #if (defined(NOPROTO) && defined(PROTO)) # undef PROTO #endif /* used to remove arguments in function prototypes for non-ANSI C */ #ifdef PROTO # define OF(a) a #else # define OF(a) () #endif /* enable the "const" keyword only if MODERN and if not otherwise instructed */ #ifdef MODERN # if (!defined(ZCONST) && (defined(USE_CONST) || !defined(NO_CONST))) # define ZCONST const # endif #endif #ifndef ZCONST # define ZCONST #endif /* Tell Microsoft Visual C++ 2005 (and newer) to leave us alone * and let us use standard C functions the way we're supposed to. * (These preprocessor symbols must appear before the first system * header include. They are located here, because for WINDLL the * first system header includes follow just below.) */ #if defined(_MSC_VER) && (_MSC_VER >= 1400) # ifndef _CRT_SECURE_NO_WARNINGS # define _CRT_SECURE_NO_WARNINGS # endif # ifndef _CRT_NONSTDC_NO_WARNINGS # define _CRT_NONSTDC_NO_WARNINGS # endif # if defined(POCKET_UNZIP) && !defined(_CRT_NON_CONFORMING_SWPRINTFS) # define _CRT_NON_CONFORMING_SWPRINTFS # endif #endif /* NO_UNIXBACKUP overrides UNIXBACKUP */ #if defined(NO_UNIXBACKUP) && defined(UNIXBACKUP) # undef UNIXBACKUP #endif /*--------------------------------------------------------------------------- Grab system-specific public include headers. ---------------------------------------------------------------------------*/ #ifdef POCKET_UNZIP /* WinCE port */ # include "wince/punzip.h" /* must appear before windows.h */ #endif #ifdef WINDLL /* for UnZip, the "basic" part of the win32 api is sufficient */ # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # define IZ_HASDEFINED_WIN32LEAN # endif # include # include "windll/structs.h" # ifdef IZ_HASDEFINED_WIN32LEAN # undef WIN32_LEAN_AND_MEAN # undef IZ_HASDEFINED_WIN32LEAN # endif #endif /*--------------------------------------------------------------------------- Grab system-dependent definition of EXPENTRY for prototypes below. ---------------------------------------------------------------------------*/ #if 0 #if (defined(OS2) && !defined(FUNZIP)) # ifdef UNZIP_INTERNAL # define INCL_NOPM # define INCL_DOSNLS # define INCL_DOSPROCESS # define INCL_DOSDEVICES # define INCL_DOSDEVIOCTL # define INCL_DOSERRORS # define INCL_DOSMISC # ifdef OS2DLL # define INCL_REXXSAA # include # endif # endif /* UNZIP_INTERNAL */ # include # define UZ_EXP EXPENTRY #endif /* OS2 && !FUNZIP */ #endif /* 0 */ #if (defined(OS2) && !defined(FUNZIP)) # if (defined(__IBMC__) || defined(__WATCOMC__)) # define UZ_EXP _System /* compiler keyword */ # else # define UZ_EXP # endif #endif /* OS2 && !FUNZIP */ #if (defined(WINDLL) || defined(USE_UNZIP_LIB)) # ifndef EXPENTRY # define UZ_EXP WINAPI # else # define UZ_EXP EXPENTRY # endif #endif #ifndef UZ_EXP # define UZ_EXP #endif #ifdef __cplusplus extern "C" { #endif /*--------------------------------------------------------------------------- Public typedefs. ---------------------------------------------------------------------------*/ #ifndef _IZ_TYPES_DEFINED #ifdef MODERN typedef void zvoid; #else /* !MODERN */ # ifndef AOS_VS /* mostly modern? */ # ifndef VAXC /* not fully modern, but has knows 'void' */ # define void int # endif /* !VAXC */ # endif /* !AOS_VS */ typedef char zvoid; #endif /* ?MODERN */ typedef unsigned char uch; /* code assumes unsigned bytes; these type- */ typedef unsigned short ush; /* defs replace byte/UWORD/ULONG (which are */ typedef unsigned long ulg; /* predefined on some systems) & match zip */ #define _IZ_TYPES_DEFINED #endif /* !_IZ_TYPES_DEFINED */ /* InputFn is not yet used and is likely to change: */ #ifdef PROTO typedef int (UZ_EXP MsgFn) (zvoid *pG, uch *buf, ulg size, int flag); typedef int (UZ_EXP InputFn) (zvoid *pG, uch *buf, int *size, int flag); typedef void (UZ_EXP PauseFn) (zvoid *pG, ZCONST char *prompt, int flag); typedef int (UZ_EXP PasswdFn) (zvoid *pG, int *rcnt, char *pwbuf, int size, ZCONST char *zfn, ZCONST char *efn); typedef int (UZ_EXP StatCBFn) (zvoid *pG, int fnflag, ZCONST char *zfn, ZCONST char *efn, ZCONST zvoid *details); typedef void (UZ_EXP UsrIniFn) (void); #else /* !PROTO */ typedef int (UZ_EXP MsgFn) (); typedef int (UZ_EXP InputFn) (); typedef void (UZ_EXP PauseFn) (); typedef int (UZ_EXP PasswdFn) (); typedef int (UZ_EXP StatCBFn) (); typedef void (UZ_EXP UsrIniFn) (); #endif /* ?PROTO */ typedef struct _UzpBuffer { /* rxstr */ ulg strlength; /* length of string */ char *strptr; /* pointer to string */ } UzpBuffer; typedef struct _UzpInit { ulg structlen; /* length of the struct being passed */ /* GRR: can we assume that each of these is a 32-bit pointer? if not, * does it matter? add "far" keyword to make sure? */ MsgFn *msgfn; InputFn *inputfn; PauseFn *pausefn; UsrIniFn *userfn; /* user init function to be called after */ /* globals constructed and initialized */ /* pointer to program's environment area or something? */ /* hooks for performance testing? */ /* hooks for extra unzip -v output? (detect CPU or other hardware?) */ /* anything else? let me (Greg) know... */ } UzpInit; typedef struct _UzpCB { ulg structlen; /* length of the struct being passed */ /* GRR: can we assume that each of these is a 32-bit pointer? if not, * does it matter? add "far" keyword to make sure? */ MsgFn *msgfn; InputFn *inputfn; PauseFn *pausefn; PasswdFn *passwdfn; StatCBFn *statrepfn; } UzpCB; /* the collection of general UnZip option flags and option arguments */ typedef struct _UzpOpts { #ifndef FUNZIP char *exdir; /* pointer to extraction root directory (-d option) */ char *pwdarg; /* pointer to command-line password (-P option) */ int zipinfo_mode; /* behave like ZipInfo or like normal UnZip? */ int aflag; /* -a: do ASCII-EBCDIC and/or end-of-line translation */ #ifdef VMS int bflag; /* -b: force fixed record format for binary files */ #endif #ifdef TANDEM int bflag; /* -b: create text files in 'C' format (180)*/ #endif #if defined(UNIX) || defined(OS2) || defined(WIN32) int B_flag; /* -B: back up existing files by renaming to *~##### */ #else #ifdef UNIXBACKUP int B_flag; /* -B: back up existing files by renaming to *~##### */ #endif #endif int cflag; /* -c: output to stdout */ int C_flag; /* -C: match filenames case-insensitively */ int D_flag; /* -D: don't restore directory (-DD: any) timestamps */ #ifdef MACOS int E_flag; /* -E: [MacOS] show Mac extra field during restoring */ #endif int fflag; /* -f: "freshen" (extract only newer files) */ #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS)) int acorn_nfs_ext; /* -F: RISC OS types & NFS filetype extensions */ #endif int hflag; /* -h: header line (zipinfo) */ #ifdef MACOS int i_flag; /* -i: [MacOS] ignore filenames stored in Mac e.f. */ #endif #ifdef RISCOS int scanimage; /* -I: scan image files */ #endif int jflag; /* -j: junk pathnames (unzip) */ #if (defined(__ATHEOS__) || defined(__BEOS__) || defined(MACOS)) int J_flag; /* -J: ignore AtheOS/BeOS/MacOS e. f. info (unzip) */ #endif #if (defined(__ATHEOS__) || defined(__BEOS__) || defined(UNIX)) int K_flag; /* -K: keep setuid/setgid/tacky permissions */ #endif int lflag; /* -12slmv: listing format (zipinfo) */ int L_flag; /* -L: convert filenames from some OSes to lowercase */ int overwrite_none; /* -n: never overwrite files (no prompting) */ #ifdef AMIGA int N_flag; /* -N: restore comments as AmigaDOS filenotes */ #endif int overwrite_all; /* -o: OK to overwrite files without prompting */ #endif /* !FUNZIP */ int qflag; /* -q: produce a lot less output */ #ifdef TANDEM int rflag; /* -r: remove file extensions */ #endif #ifndef FUNZIP #if (defined(MSDOS) || defined(FLEXOS) || defined(OS2) || defined(WIN32)) int sflag; /* -s: convert spaces in filenames to underscores */ #endif #if (defined(NLM)) int sflag; /* -s: convert spaces in filenames to underscores */ #endif #ifdef VMS int S_flag; /* -S: use Stream_LF for text files (-a[a]) */ #endif #if (defined(MSDOS) || defined(__human68k__) || defined(OS2) || defined(WIN32)) int volflag; /* -$: extract volume labels */ #endif int tflag; /* -t: test (unzip) or totals line (zipinfo) */ int T_flag; /* -T: timestamps (unzip) or dec. time fmt (zipinfo) */ int uflag; /* -u: "update" (extract only newer/brand-new files) */ #if defined(UNIX) || defined(VMS) || defined(WIN32) int U_flag; /* -U: escape non-ASCII, -UU No Unicode paths */ #endif int vflag; /* -v: (verbosely) list directory */ int V_flag; /* -V: don't strip VMS version numbers */ int W_flag; /* -W: wildcard '*' won't match '/' dir separator */ #if (defined (__ATHEOS__) || defined(__BEOS__) || defined(UNIX)) int X_flag; /* -X: restore owner/protection or UID/GID or ACLs */ #else #if (defined(TANDEM) || defined(THEOS)) int X_flag; /* -X: restore owner/protection or UID/GID or ACLs */ #else #if (defined(OS2) || defined(VMS) || defined(WIN32)) int X_flag; /* -X: restore owner/protection or UID/GID or ACLs */ #endif #endif #endif #ifdef VMS int Y_flag; /* -Y: treat ".nnn" as ";nnn" version */ #endif int zflag; /* -z: display the zipfile comment (only, for unzip) */ #ifdef VMS int ods2_flag; /* -2: force names to conform to ODS2 */ #endif #if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM)) int ddotflag; /* -:: don't skip over "../" path elements */ #endif #ifdef UNIX int cflxflag; /* -^: allow control chars in extracted filenames */ #endif #endif /* !FUNZIP */ } UzpOpts; /* intended to be a private struct: */ typedef struct _ver { uch major; /* e.g., integer 5 */ uch minor; /* e.g., 2 */ uch patchlevel; /* e.g., 0 */ uch not_used; } _version_type; typedef struct _UzpVer { ulg structlen; /* length of the struct being passed */ ulg flag; /* bit 0: is_beta bit 1: uses_zlib */ ZCONST char *betalevel; /* e.g. "g BETA" or "" */ ZCONST char *date; /* e.g. "9 Oct 08" (beta) or "9 October 2008" */ ZCONST char *zlib_version;/* e.g. "1.2.3" or NULL */ _version_type unzip; /* current UnZip version */ _version_type zipinfo; /* current ZipInfo version */ _version_type os2dll; /* OS2DLL version (retained for compatibility */ _version_type windll; /* WinDLL version (retained for compatibility */ _version_type dllapimin; /* last incompatible change of library API */ } UzpVer; /* for Visual BASIC access to Windows DLLs: */ typedef struct _UzpVer2 { ulg structlen; /* length of the struct being passed */ ulg flag; /* bit 0: is_beta bit 1: uses_zlib */ char betalevel[10]; /* e.g. "g BETA" or "" */ char date[20]; /* e.g. "9 Oct 08" (beta) or "9 October 2008" */ char zlib_version[10]; /* e.g. "1.2.3" or NULL */ _version_type unzip; /* current UnZip version */ _version_type zipinfo; /* current ZipInfo version */ _version_type os2dll; /* OS2DLL version (retained for compatibility */ _version_type windll; /* WinDLL version (retained for compatibility */ _version_type dllapimin; /* last incompatible change of library API */ } UzpVer2; typedef struct _Uzp_Siz64 { unsigned long lo32; unsigned long hi32; } Uzp_Siz64; typedef struct _Uzp_cdir_Rec { uch version_made_by[2]; uch version_needed_to_extract[2]; ush general_purpose_bit_flag; ush compression_method; ulg last_mod_dos_datetime; ulg crc32; Uzp_Siz64 csize; Uzp_Siz64 ucsize; ush filename_length; ush extra_field_length; ush file_comment_length; ush disk_number_start; ush internal_file_attributes; ulg external_file_attributes; Uzp_Siz64 relative_offset_local_header; } Uzp_cdir_Rec; #define UZPINIT_LEN sizeof(UzpInit) #define UZPVER_LEN sizeof(UzpVer) #define cbList(func) int (* UZ_EXP func)(char *filename, Uzp_cdir_Rec *crec) /*--------------------------------------------------------------------------- Return (and exit) values of the public UnZip API functions. ---------------------------------------------------------------------------*/ /* external return codes */ #define PK_OK 0 /* no error */ #define PK_COOL 0 /* no error */ #define PK_WARN 1 /* warning error */ #define PK_ERR 2 /* error in zipfile */ #define PK_BADERR 3 /* severe error in zipfile */ #define PK_MEM 4 /* insufficient memory (during initialization) */ #define PK_MEM2 5 /* insufficient memory (password failure) */ #define PK_MEM3 6 /* insufficient memory (file decompression) */ #define PK_MEM4 7 /* insufficient memory (memory decompression) */ #define PK_MEM5 8 /* insufficient memory (not yet used) */ #define PK_NOZIP 9 /* zipfile not found */ #define PK_PARAM 10 /* bad or illegal parameters specified */ #define PK_FIND 11 /* no files found */ #define PK_DISK 50 /* disk full */ #define PK_EOF 51 /* unexpected EOF */ #define IZ_CTRLC 80 /* user hit ^C to terminate */ #define IZ_UNSUP 81 /* no files found: all unsup. compr/encrypt. */ #define IZ_BADPWD 82 /* no files found: all had bad password */ #define IZ_ERRBF 83 /* big-file archive, small-file program */ /* return codes of password fetches (negative = user abort; positive = error) */ #define IZ_PW_ENTERED 0 /* got some password string; use/try it */ #define IZ_PW_CANCEL -1 /* no password available (for this entry) */ #define IZ_PW_CANCELALL -2 /* no password, skip any further pwd. request */ #define IZ_PW_ERROR 5 /* = PK_MEM2 : failure (no mem, no tty, ...) */ /* flag values for status callback function */ #define UZ_ST_START_EXTRACT 1 /* no details */ #define UZ_ST_IN_PROGRESS 2 /* no details */ #define UZ_ST_FINISH_MEMBER 3 /* 'details': extracted size */ /* return values of status callback function */ #define UZ_ST_CONTINUE 0 #define UZ_ST_BREAK 1 /*--------------------------------------------------------------------------- Prototypes for public UnZip API (DLL) functions. ---------------------------------------------------------------------------*/ #define UzpMatch match int UZ_EXP UzpMain OF((int argc, char **argv)); int UZ_EXP UzpAltMain OF((int argc, char **argv, UzpInit *init)); ZCONST UzpVer * UZ_EXP UzpVersion OF((void)); void UZ_EXP UzpFreeMemBuffer OF((UzpBuffer *retstr)); #ifndef WINDLL int UZ_EXP UzpUnzipToMemory OF((char *zip, char *file, UzpOpts *optflgs, UzpCB *UsrFunc, UzpBuffer *retstr)); int UZ_EXP UzpGrep OF((char *archive, char *file, char *pattern, int cmd, int SkipBin, UzpCB *UsrFunc)); #endif #ifdef OS2 int UZ_EXP UzpFileTree OF((char *name, cbList(callBack), char *cpInclude[], char *cpExclude[])); #endif unsigned UZ_EXP UzpVersion2 OF((UzpVer2 *version)); int UZ_EXP UzpValidate OF((char *archive, int AllCodes)); /* default I/O functions (can be swapped out via UzpAltMain() entry point): */ int UZ_EXP UzpMessagePrnt OF((zvoid *pG, uch *buf, ulg size, int flag)); int UZ_EXP UzpMessageNull OF((zvoid *pG, uch *buf, ulg size, int flag)); int UZ_EXP UzpInput OF((zvoid *pG, uch *buf, int *size, int flag)); void UZ_EXP UzpMorePause OF((zvoid *pG, ZCONST char *prompt, int flag)); int UZ_EXP UzpPassword OF((zvoid *pG, int *rcnt, char *pwbuf, int size, ZCONST char *zfn, ZCONST char *efn)); #ifdef __cplusplus } #endif /*--------------------------------------------------------------------------- Remaining private stuff for UnZip compilation. ---------------------------------------------------------------------------*/ #ifdef UNZIP_INTERNAL # include "unzpriv.h" #endif #endif /* !__unzip_h */ Carla-2.1/data/windows/unzipfx-carla-control/unzipfx/000077500000000000000000000000001364475620200227565ustar00rootroot00000000000000Carla-2.1/data/windows/unzipfx-carla-control/unzipfx/appDetails.c000066400000000000000000000032201364475620200252050ustar00rootroot00000000000000 #include #include #include #ifdef WIN32 # include #endif #include "appDetails.h" #define CMD_BUF_LEN 1024 static int sfx_app_argc = 0; static char** sfx_app_argv = NULL; static char sfx_tmp_path[512] = { 0 }; void sfx_app_set_args(int argc, char** argv) { sfx_app_argc = argc; sfx_app_argv = argv; } int sfx_app_autorun_now() { int i, cmdBufLen = 0; char cmdBuf[CMD_BUF_LEN]; const char* const path = sfx_get_tmp_path(1); chdir(path); strcpy(cmdBuf, path); strcat(cmdBuf, SFX_AUTORUN_CMD); cmdBufLen = strlen(cmdBuf); for (i=0; i < sfx_app_argc; i++) { if (! sfx_app_argv[i]) continue; cmdBufLen += strlen(sfx_app_argv[i]) + 1; if (cmdBufLen >= CMD_BUF_LEN-1) break; strcat(cmdBuf, " "); strcat(cmdBuf, sfx_app_argv[i]); } puts(SFX_APP_BANNER); printf("Launching: '%s'\n", cmdBuf); #ifdef WIN32 ShellExecute(NULL, "open", cmdBuf, NULL, NULL, SW_SHOWNORMAL); return 0; #else const int ret = system(cmdBuf); exit(ret); return ret; #endif } char* sfx_get_tmp_path(int withAppName) { #ifdef WIN32 { GetTempPathA(512 - strlen(SFX_APP_MININAME_TITLE), sfx_tmp_path); if (withAppName == 1) strcat(sfx_tmp_path, SFX_APP_MININAME_TITLE "-2.1"); } #else { char* tmp = getenv("TMP"); if (tmp) strcpy(sfx_tmp_path, tmp); else strcpy(sfx_tmp_path, "/tmp"); if (withAppName == 1) strcat(sfx_tmp_path, "/" SFX_APP_MININAME_LCASE "-2.1"); } #endif return sfx_tmp_path; } Carla-2.1/data/windows/unzipfx-carla-control/unzipfx/appDetails.h000066400000000000000000000011671364475620200252220ustar00rootroot00000000000000 #ifndef __APP_DETAILS_H__ #define __APP_DETAILS_H__ #define REAL_BUILD #include "../../../../source/includes/CarlaDefines.h" #define SFX_APP_MININAME_TITLE "CarlaControl" #define SFX_APP_MININAME_LCASE "carla-control" #define SFX_APP_BANNER SFX_APP_MININAME_TITLE " self-contained executable " CARLA_VERSION_STRING ", based on UnZipSFX." #ifdef WIN32 # define SFX_AUTORUN_CMD "\\" SFX_APP_MININAME_TITLE ".exe" #else # define SFX_AUTORUN_CMD "/" SFX_APP_MININAME_LCASE #endif void sfx_app_set_args(int argc, char** argv); int sfx_app_autorun_now(); char* sfx_get_tmp_path(int withAppName); #endif // __APP_DETAILS_H__ Carla-2.1/data/windows/unzipfx-carla-control/unzpriv.h000066400000000000000000003251651364475620200231550ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- unzpriv.h This header file contains private (internal) macros, typedefs, prototypes and global-variable declarations used by all of the UnZip source files. In a prior life it was part of the main unzip.h header, but now it is only included by that header if UNZIP_INTERNAL is defined. ---------------------------------------------------------------------------*/ #ifndef __unzpriv_h /* prevent multiple inclusions */ #define __unzpriv_h /* First thing: Signal all following code that we compile UnZip utilities! */ #ifndef UNZIP # define UNZIP #endif /* GRR 960204: MORE defined here in preparation for removal altogether */ #ifndef MORE # ifndef RISCOS # define MORE # endif #endif /* fUnZip should never need to be reentrant */ #ifdef FUNZIP # ifdef REENTRANT # undef REENTRANT # endif # ifdef DLL # undef DLL # endif # ifdef SFX /* fUnZip is NOT the sfx stub! */ # undef SFX # endif # ifdef USE_BZIP2 /* fUnZip does not support bzip2 decompression */ # undef USE_BZIP2 # endif #endif #if (defined(USE_ZLIB) && !defined(HAVE_ZL_INFLAT64) && !defined(NO_DEFLATE64)) /* zlib does not (yet?) provide Deflate64(tm) support */ # define NO_DEFLATE64 #endif #ifdef NO_DEFLATE64 /* disable support for Deflate64(tm) */ # ifdef USE_DEFLATE64 # undef USE_DEFLATE64 # endif #else /* enable Deflate64(tm) support unless compiling for SFX stub */ # if (!defined(USE_DEFLATE64) && !defined(SFX)) # define USE_DEFLATE64 # endif #endif /* disable bzip2 support for SFX stub, unless explicitly requested */ #if (defined(SFX) && !defined(BZIP2_SFX) && defined(USE_BZIP2)) # undef USE_BZIP2 #endif #if (defined(NO_VMS_TEXT_CONV) || defined(VMS)) # ifdef VMS_TEXT_CONV # undef VMS_TEXT_CONV # endif #else # if (!defined(VMS_TEXT_CONV) && !defined(SFX)) # define VMS_TEXT_CONV # endif #endif /* Enable -B option per default on specific systems, to allow backing up * files that would be overwritten. * (This list of systems must be kept in sync with the list of systems * that add the B_flag to the UzpOpts structure, see unzip.h.) */ #if (!defined(NO_UNIXBACKUP) && !defined(UNIXBACKUP)) # if defined(UNIX) || defined(OS2) || defined(WIN32) # define UNIXBACKUP # endif #endif #if (defined(DLL) && !defined(REENTRANT)) # define REENTRANT #endif #if (!defined(DYNAMIC_CRC_TABLE) && !defined(FUNZIP)) # define DYNAMIC_CRC_TABLE #endif #if (defined(DYNAMIC_CRC_TABLE) && !defined(REENTRANT)) # ifndef DYNALLOC_CRCTAB # define DYNALLOC_CRCTAB # endif #endif /*--------------------------------------------------------------------------- OS-dependent configuration for UnZip internals ---------------------------------------------------------------------------*/ /* Some compiler distributions for Win32/i386 systems try to emulate * a Unix (POSIX-compatible) environment. */ #if (defined(WIN32) && defined(UNIX)) /* UnZip does not support merging both ports in a single executable. */ # if (defined(FORCE_WIN32_OVER_UNIX) && defined(FORCE_UNIX_OVER_WIN32)) /* conflicting choice requests -> we prefer the Win32 environment */ # undef FORCE_UNIX_OVER_WIN32 # endif # ifdef FORCE_WIN32_OVER_UNIX /* native Win32 support was explicitly requested... */ # undef UNIX # else /* use the POSIX (Unix) emulation features by default... */ # undef WIN32 # endif #endif /* bad or (occasionally?) missing stddef.h: */ #if (defined(M_XENIX) || defined(DNIX)) # define NO_STDDEF_H #endif #if (defined(M_XENIX) && !defined(M_UNIX)) /* SCO Xenix only, not SCO Unix */ # define SCO_XENIX # define NO_LIMITS_H /* no limits.h, but MODERN defined */ # define NO_UID_GID /* no uid_t/gid_t */ # define size_t int #endif #ifdef realix /* Modcomp Real/IX, real-time SysV.3 variant */ # define SYSV # define NO_UID_GID /* no uid_t/gid_t */ #endif #if (defined(_AIX) && !defined(_ALL_SOURCE)) # define _ALL_SOURCE #endif #if defined(apollo) /* defines __STDC__ */ # define NO_STDLIB_H #endif #ifdef DNIX # define SYSV # define SHORT_NAMES /* 14-char limitation on path components */ /* # define FILENAME_MAX 14 */ # define FILENAME_MAX NAME_MAX /* GRR: experiment */ #endif #if (defined(SYSTEM_FIVE) || defined(__SYSTEM_FIVE)) # ifndef SYSV # define SYSV # endif #endif /* SYSTEM_FIVE || __SYSTEM_FIVE */ #if (defined(M_SYSV) || defined(M_SYS5)) # ifndef SYSV # define SYSV # endif #endif /* M_SYSV || M_SYS5 */ /* __SVR4 and __svr4__ catch Solaris on at least some combos of compiler+OS */ #if (defined(__SVR4) || defined(__svr4__) || defined(sgi) || defined(__hpux)) # ifndef SYSV # define SYSV # endif #endif /* __SVR4 || __svr4__ || sgi || __hpux */ #if (defined(LINUX) || defined(__QNX__)) # ifndef SYSV # define SYSV # endif #endif /* LINUX || __QNX__ */ #if (defined(ultrix) || defined(__ultrix) || defined(bsd4_2)) # if (!defined(BSD) && !defined(SYSV)) # define BSD # endif #endif /* ultrix || __ultrix || bsd4_2 */ #if (defined(sun) || defined(pyr) || defined(CONVEX)) # if (!defined(BSD) && !defined(SYSV)) # define BSD # endif #endif /* sun || pyr || CONVEX */ #ifdef pyr /* Pyramid: has BSD and AT&T "universes" */ # ifdef BSD # define pyr_bsd # define USE_STRINGS_H /* instead of more common string.h */ # define ZMEM /* ZMEM now uses bcopy/bzero: not in AT&T universe */ # endif /* (AT&T memcpy claimed to be very slow, though) */ # define DECLARE_ERRNO #endif /* pyr */ /* stat() bug for Borland, VAX C RTL, and Atari ST MiNT on TOS * filesystems: returns 0 for wildcards! (returns 0xffffffff on Minix * filesystem or `U:' drive under Atari MiNT.) Watcom C was previously * included on this list; it would be good to know what version the problem * was fixed at, if it did exist. */ #if (defined(__TURBOC__) && !defined(WIN32)) /*# define WILD_STAT_BUG*/ #endif #if (defined(VMS) || defined(__MINT__)) # define WILD_STAT_BUG #endif /*--------------------------------------------------------------------------- OS-dependent includes ---------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- API (DLL) section: ---------------------------------------------------------------------------*/ #ifdef DLL # define MAIN UZ_EXP UzpMain /* was UzpUnzip */ # ifdef OS2DLL # undef Info # define REDIRECTC(c) varputchar(__G__ c) # define REDIRECTPRINT(buf,size) varmessage(__G__ buf, size) # define FINISH_REDIRECT() finish_REXX_redirect(__G) # else # define REDIRECTC(c) # define REDIRECTPRINT(buf,size) 0 # define FINISH_REDIRECT() close_redirect(__G) # endif #endif /*--------------------------------------------------------------------------- Acorn RISCOS section: ---------------------------------------------------------------------------*/ #ifdef RISCOS # include "acorn/riscos.h" #endif /*--------------------------------------------------------------------------- Amiga section: ---------------------------------------------------------------------------*/ #ifdef AMIGA # include "amiga/amiga.h" #endif /*--------------------------------------------------------------------------- AOS/VS section (somewhat similar to Unix, apparently): ---------------------------------------------------------------------------*/ #ifdef AOS_VS # ifdef __FILEIO_C # include "aosvs/aosvs.h" # endif #endif /*--------------------------------------------------------------------------- Atari ST section: ---------------------------------------------------------------------------*/ #ifdef ATARI # include # include # include # include # define SYMLINKS # define EXE_EXTENSION ".tos" # ifndef DATE_FORMAT # define DATE_FORMAT DF_DMY # endif # define DIR_END '/' # define INT_SPRINTF # define timezone _timezone # define lenEOL 2 # define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);} # undef SHORT_NAMES # if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) # define TIMESTAMP # endif #endif /*--------------------------------------------------------------------------- AtheOS section: ---------------------------------------------------------------------------*/ #ifdef __ATHEOS__ # include "atheos/athcfg.h" #endif /*--------------------------------------------------------------------------- BeOS section: ---------------------------------------------------------------------------*/ #ifdef __BEOS__ # include "beos/beocfg.h" #endif /*--------------------------------------------------------------------------- Human68k/X680x0 section: ---------------------------------------------------------------------------*/ #ifdef __human68k__ /* DO NOT DEFINE DOS_OS2 HERE! If Human68k is so much */ /* like MS-DOS and/or OS/2, create DOS_H68_OS2 macro. */ # if (!defined(_MBCS) && !defined(NO_MBCS)) /* enable MBCS support by default for this system */ # define _MBCS # endif # if (defined(_MBCS) && defined(NO_MBCS)) /* disable MBCS support when explicitely requested */ # undef _MBCS # endif # include # include # include # include # include # ifdef HAVE_MBSTRING_H # include # endif # ifdef HAVE_MBCTYPE_H # include # else # ifndef _ismbblead # define _ismbblead(c) (0x80 <= (c) && ((c) < 0xa0 || 0xe0 <= (c))) # endif # endif # ifndef DATE_FORMAT # define DATE_FORMAT DF_YMD /* Japanese standard */ # endif # define lenEOL 1 # define PutNativeEOL *q++ = native(LF); # define INT_SPRINTF # define SYMLINKS # ifdef SFX # define MAIN main_sfx # endif #endif /*--------------------------------------------------------------------------- Mac section: ---------------------------------------------------------------------------*/ #ifdef MACOS # include "maccfg.h" #endif /* MACOS */ /*--------------------------------------------------------------------------- MS-DOS, OS/2, FLEXOS section: ---------------------------------------------------------------------------*/ #ifdef WINDLL # ifdef MORE # undef MORE # endif # ifdef OS2_EAS # undef OS2_EAS # endif #endif #if (defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__))) # ifndef MSC # define MSC /* This should work for older MSC, too! */ # endif #endif #if (defined(MSDOS) || defined(OS2) || defined(FLEXOS)) # include /* off_t, time_t, dev_t, ... */ # include # include /* lseek(), open(), setftime(), dup(), creat() */ # include /* localtime() */ # include /* O_BINARY for open() w/o CR/LF translation */ # ifdef OS2 /* defined for all OS/2 compilers */ # include "os2/os2cfg.h" # else # ifdef FLEXOS # include "flexos/flxcfg.h" # else # include "msdos/doscfg.h" # endif # endif # if (defined(_MSC_VER) && (_MSC_VER == 700) && !defined(GRR)) /* * ARGH. MSC 7.0 libraries think times are based on 1899 Dec 31 00:00, not * 1970 Jan 1 00:00. So we have to diddle time_t's appropriately: add or * subtract 70 years' worth of seconds; i.e., number of days times 86400; * i.e., (70*365 regular days + 17 leap days + 1 1899 day) * 86400 == * (25550 + 17 + 1) * 86400 == 2209075200 seconds. We know time_t is an * unsigned long (ulg) on the only system with this bug. */ # define TIMET_TO_NATIVE(x) (x) += (ulg)2209075200L; # define NATIVE_TO_TIMET(x) (x) -= (ulg)2209075200L; # endif # if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0450)) # define timezone _timezone # endif # if (defined(__GO32__) || defined(FLEXOS)) # define DIR_END '/' # else # define DIR_END '\\' /* OS uses '\\' as directory separator */ # define DIR_END2 '/' /* also check for '/' (RTL may convert) */ # endif # ifdef DATE_FORMAT # undef DATE_FORMAT # endif # define DATE_FORMAT dateformat() # define lenEOL 2 # define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);} # if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)) # define USE_EF_UT_TIME # endif #endif /* MSDOS || OS2 || FLEXOS */ /*--------------------------------------------------------------------------- MTS section (piggybacks UNIX, I think): ---------------------------------------------------------------------------*/ #ifdef MTS # include /* off_t, time_t, dev_t, ... */ # include # include /* MTS uses this instead of fcntl.h */ # include # include # include /* some important non-ANSI routines */ # define mkdir(s,n) (-1) /* no "make directory" capability */ # define EBCDIC /* set EBCDIC conversion on */ # define NO_STRNICMP /* unzip's is as good the one in MTS */ # define USE_FWRITE # define close_outfile() fclose(G.outfile) /* can't set time on files */ # define umask(n) /* don't have umask() on MTS */ # define FOPWT "w" /* open file for writing in TEXT mode */ # ifndef DATE_FORMAT # define DATE_FORMAT DF_MDY # endif # define lenEOL 1 # define PutNativeEOL *q++ = native(LF); #endif /* MTS */ /*--------------------------------------------------------------------------- Novell Netware NLM section ---------------------------------------------------------------------------*/ #ifdef NLM # include "netware/nlmcfg.h" #endif /*--------------------------------------------------------------------------- QDOS section ---------------------------------------------------------------------------*/ #ifdef QDOS # define DIRENT # include # include # include # include # include "qdos/izqdos.h" # ifndef DATE_FORMAT # define DATE_FORMAT DF_MDY # endif # define lenEOL 1 # define PutNativeEOL *q++ = native(LF); # define DIR_END '_' # define RETURN QReturn # undef PATH_MAX # define PATH_MAX 36 # if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) # define TIMESTAMP # endif # define SCREENSIZE(ttrows, ttcols) screensize(ttrows, ttcols) # define SCREENWIDTH 80 #endif /*--------------------------------------------------------------------------- Tandem NSK section: ---------------------------------------------------------------------------*/ #ifdef TANDEM # include "tandem.h" # include # ifndef __INT32 /* We are compiling with non-WIDE memory model, int = 16 bits */ # ifndef INT_16BIT # define INT_16BIT /* report "int" size is 16-bit to inflate setup */ # endif # ifdef USE_DEFLATE64 /* Following required for 64k WSIZE of Deflate64 support */ # define MED_MEM /* else OUTBUFSIZ is 64K and fails in do_string */ # define INBUFSIZ 8192 /* but larger buffer for real OSes */ # endif # endif /* use a single LF delimiter so that writes to 101 text files work */ # define PutNativeEOL *q++ = native(LF); # define lenEOL 1 # ifndef DATE_FORMAT # define DATE_FORMAT DF_DMY # endif # define SCREENLINES 25 /* USE_EF_UT_TIME is set in tandem.h */ # define RESTORE_UIDGID # define NO_STRNICMP #endif /*--------------------------------------------------------------------------- THEOS section: ---------------------------------------------------------------------------*/ #ifdef THEOS # include "theos/thscfg.h" #endif /*--------------------------------------------------------------------------- TOPS-20 section: ---------------------------------------------------------------------------*/ #ifdef TOPS20 # include /* off_t, time_t, dev_t, ... */ # include # include # include # include # include # include # include /* get amazing monsym() macro */ extern int open(), close(), read(); extern int stat(), unlink(), jsys(), fcntl(); extern long lseek(), dup(), creat(); # define strchr index /* GRR: necessary? */ # define strrchr rindex # define REALLY_SHORT_SYMS # define NO_MKDIR # ifndef HAVE_STRNICMP # define NO_STRNICMP /* probably not provided by TOPS20 C RTL */ # endif # define DIR_BEG '<' # define DIR_END '>' # define DIR_EXT ".directory" # ifndef DATE_FORMAT # define DATE_FORMAT DF_MDY # endif # define EXE_EXTENSION ".exe" /* just a guess... */ #endif /* TOPS20 */ /*--------------------------------------------------------------------------- Unix section: ---------------------------------------------------------------------------*/ #ifdef UNIX # include "unix/unxcfg.h" #endif /* UNIX */ /*--------------------------------------------------------------------------- VM/CMS and MVS section: ---------------------------------------------------------------------------*/ #ifdef CMS_MVS # include "vmmvs.h" # define CLOSE_INFILE() close_infile(__G) #endif /*--------------------------------------------------------------------------- VMS section: ---------------------------------------------------------------------------*/ #ifdef VMS # include "vms/vmscfg.h" #endif /* VMS */ /*--------------------------------------------------------------------------- Win32 (Windows 95/NT) section: ---------------------------------------------------------------------------*/ #if (defined(WIN32) && !defined(POCKET_UNZIP) && !defined(_WIN32_WCE)) # include "win32/w32cfg.h" #endif /*--------------------------------------------------------------------------- Win32 Windows CE section (also POCKET_UNZIP) ---------------------------------------------------------------------------*/ #if (defined(_WIN32_WCE) || defined(POCKET_UNZIP)) # include "wince/wcecfg.h" #endif /* ---------------------------------------------------------------------------- MUST BE AFTER LARGE FILE INCLUDES ---------------------------------------------------------------------------- */ /* This stuff calls in types and messes up large file includes. It needs to go after large file defines in local includes. I am guessing that moving them here probably broke some ports, but hey. 10/31/2004 EG */ /* ---------------------------------------------------------------------------- Common includes ---------------------------------------------------------------------------- */ /* Some ports apply specific adjustments which must be in effect before reading the "standard" include headers. */ #ifdef EFT # define Z_OFF_T off_t /* Amdahl UTS nonsense ("extended file types") */ #else #if (defined(UNIX) && defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)) # define Z_OFF_T off_t /* 64bit offsets to support 2GB < zipfile size < 4GB */ #else # define Z_OFF_T long long #endif #endif #ifndef ZOFF_T_DEFINED typedef Z_OFF_T zoff_t; # define ZOFF_T_DEFINED #endif #ifndef Z_STAT_DEFINED typedef struct stat z_stat; # define Z_STAT_DEFINED #endif #ifndef MINIX /* Minix needs it after all the other includes (?) */ # include #endif #include /* skip for VMS, to use tolower() function? */ #include /* used in mapname() */ #ifdef USE_STRINGS_H # include /* strcpy, strcmp, memcpy, index/rindex, etc. */ #else # include /* strcpy, strcmp, memcpy, strchr/strrchr, etc. */ #endif #if (defined(MODERN) && !defined(NO_LIMITS_H)) # include /* MAX/MIN constant symbols for system types... */ #endif /* this include must be down here for SysV.4, for some reason... */ #include /* used in unzip.c, fileio.c */ #ifdef MODERN # ifndef NO_STDDEF_H # include # endif # ifndef NO_STDLIB_H # include /* standard library prototypes, malloc(), etc. */ # endif typedef size_t extent; #else /* !MODERN */ # ifndef AOS_VS /* mostly modern? */ Z_OFF_T lseek(); # ifdef VAXC /* not fully modern, but has stdlib.h and void */ # include # else char *malloc(); # endif /* ?VAXC */ # endif /* !AOS_VS */ typedef unsigned int extent; #endif /* ?MODERN */ /*************/ /* Defines */ /*************/ #define UNZIP_BZ2VERS 46 #ifdef ZIP64_SUPPORT # ifdef USE_BZIP2 # define UNZIP_VERSION UNZIP_BZ2VERS # else # define UNZIP_VERSION 45 # endif #else #ifdef USE_DEFLATE64 # define UNZIP_VERSION 21 /* compatible with PKUNZIP 4.0 */ #else # define UNZIP_VERSION 20 /* compatible with PKUNZIP 2.0 */ #endif #endif #define VMS_UNZIP_VERSION 42 /* if OS-needed-to-extract is VMS: can do */ #if (defined(MSDOS) || defined(OS2)) # define DOS_OS2 #endif #if (defined(OS2) || defined(WIN32)) # define OS2_W32 #endif #if (defined(DOS_OS2) || defined(WIN32)) # define DOS_OS2_W32 # define DOS_W32_OS2 /* historical: don't use */ #endif #if (defined(DOS_OS2_W32) || defined(__human68k__)) # define DOS_H68_OS2_W32 #endif #if (defined(DOS_OS2) || defined(FLEXOS)) # define DOS_FLX_OS2 #endif #if (defined(DOS_OS2_W32) || defined(FLEXOS)) # define DOS_FLX_OS2_W32 #endif #if (defined(DOS_H68_OS2_W32) || defined(FLEXOS)) # define DOS_FLX_H68_OS2_W32 #endif #if (defined(DOS_FLX_OS2) || defined(NLM)) # define DOS_FLX_NLM_OS2 #endif #if (defined(DOS_FLX_OS2_W32) || defined(NLM)) # define DOS_FLX_NLM_OS2_W32 #endif #if (defined(DOS_FLX_H68_OS2_W32) || defined(NLM)) # define DOS_FLX_H68_NLM_OS2_W32 #endif #if (defined(TOPS20) || defined(VMS)) # define T20_VMS #endif #if (defined(MSDOS) || defined(T20_VMS)) # define DOS_T20_VMS #endif #if (defined(__ATHEOS__) || defined(__BEOS__)) # define ATH_BEO #endif #if (defined(ATH_BEO) || defined(UNIX)) # define ATH_BEO_UNX #endif #if (defined(ATH_BEO_UNX) || defined(THEOS)) # define ATH_BEO_THS_UNX #endif /* clean up with a few defaults */ #ifndef DIR_END # define DIR_END '/' /* last char before program name or filename */ #endif #ifndef DATE_FORMAT # ifdef DATEFMT_ISO_DEFAULT # define DATE_FORMAT DF_YMD /* defaults to invariant ISO-style */ # else # define DATE_FORMAT DF_MDY /* defaults to US convention */ # endif #endif #ifndef DATE_SEPCHAR # define DATE_SEPCHAR '-' #endif #ifndef CLOSE_INFILE # define CLOSE_INFILE() close(G.zipfd) #endif #ifndef RETURN # define RETURN return /* only used in main() */ #endif #ifndef EXIT # define EXIT exit #endif #ifndef USAGE # define USAGE(ret) usage(__G__ (ret)) /* used in unzip.c, zipinfo.c */ #endif #ifndef TIMET_TO_NATIVE /* everybody but MSC 7.0 and Macintosh */ # define TIMET_TO_NATIVE(x) # define NATIVE_TO_TIMET(x) #endif #ifndef STRNICMP # ifdef NO_STRNICMP # define STRNICMP zstrnicmp # else # define STRNICMP strnicmp # endif #endif #if (defined(DOS_FLX_NLM_OS2_W32) || defined(ATH_BEO_UNX) || defined(RISCOS)) # ifndef HAVE_UNLINK # define HAVE_UNLINK # endif #endif #if (defined(AOS_VS) || defined(ATARI)) /* GRR: others? */ # ifndef HAVE_UNLINK # define HAVE_UNLINK # endif #endif /* OS-specific exceptions to the "ANSI <--> INT_SPRINTF" rule */ #if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF)) # if (defined(SYSV) || defined(CONVEX) || defined(NeXT) || defined(BSD4_4)) # define INT_SPRINTF /* sprintf() returns int: SysVish/Posix */ # endif # if (defined(DOS_FLX_NLM_OS2_W32) || defined(VMS) || defined(AMIGA)) # define INT_SPRINTF /* sprintf() returns int: ANSI */ # endif # if (defined(ultrix) || defined(__ultrix)) /* Ultrix 4.3 and newer */ # if (defined(POSIX) || defined(__POSIX)) # define INT_SPRINTF /* sprintf() returns int: ANSI/Posix */ # endif # ifdef __GNUC__ # define PCHAR_SPRINTF /* undetermined actual return value */ # endif # endif # if (defined(__osf__) || defined(_AIX) || defined(CMS_MVS) || defined(THEOS)) # define INT_SPRINTF /* sprintf() returns int: ANSI/Posix */ # endif # if defined(sun) # define PCHAR_SPRINTF /* sprintf() returns char *: SunOS cc *and* gcc */ # endif #endif /* defaults that we hope will take care of most machines in the future */ #if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF)) # ifdef __STDC__ # define INT_SPRINTF /* sprintf() returns int: ANSI */ # endif # ifndef INT_SPRINTF # define PCHAR_SPRINTF /* sprintf() returns char *: BSDish */ # endif #endif #define MSG_STDERR(f) (f & 1) /* bit 0: 0 = stdout, 1 = stderr */ #define MSG_INFO(f) ((f & 6) == 0) /* bits 1 and 2: 0 = info */ #define MSG_WARN(f) ((f & 6) == 2) /* bits 1 and 2: 1 = warning */ #define MSG_ERROR(f) ((f & 6) == 4) /* bits 1 and 2: 2 = error */ #define MSG_FATAL(f) ((f & 6) == 6) /* bits 1 and 2: (3 = fatal error) */ #define MSG_ZFN(f) (f & 0x0008) /* bit 3: 1 = print zipfile name */ #define MSG_FN(f) (f & 0x0010) /* bit 4: 1 = print filename */ #define MSG_LNEWLN(f) (f & 0x0020) /* bit 5: 1 = leading newline if !SOL */ #define MSG_TNEWLN(f) (f & 0x0040) /* bit 6: 1 = trailing newline if !SOL */ #define MSG_MNEWLN(f) (f & 0x0080) /* bit 7: 1 = trailing NL for prompts */ /* the following are subject to change */ #define MSG_NO_WGUI(f) (f & 0x0100) /* bit 8: 1 = skip if Windows GUI */ #define MSG_NO_AGUI(f) (f & 0x0200) /* bit 9: 1 = skip if Acorn GUI */ #define MSG_NO_DLL2(f) (f & 0x0400) /* bit 10: 1 = skip if OS/2 DLL */ #define MSG_NO_NDLL(f) (f & 0x0800) /* bit 11: 1 = skip if WIN32 DLL */ #define MSG_NO_WDLL(f) (f & 0x1000) /* bit 12: 1 = skip if Windows DLL */ #if (defined(MORE) && !defined(SCREENLINES)) # ifdef DOS_FLX_NLM_OS2_W32 # define SCREENLINES 25 /* can be (should be) a function instead */ # else # define SCREENLINES 24 /* VT-100s are assumed to be minimal hardware */ # endif #endif #if (defined(MORE) && !defined(SCREENSIZE)) # ifndef SCREENWIDTH # define SCREENSIZE(scrrows, scrcols) { \ if ((scrrows) != NULL) *(scrrows) = SCREENLINES; } # else # define SCREENSIZE(scrrows, scrcols) { \ if ((scrrows) != NULL) *(scrrows) = SCREENLINES; \ if ((scrcols) != NULL) *(scrcols) = SCREENWIDTH; } # endif #endif #if (defined(__16BIT__) || defined(MED_MEM) || defined(SMALL_MEM)) # define DIR_BLKSIZ 64 /* number of directory entries per block * (should fit in 4096 bytes, usually) */ #else # define DIR_BLKSIZ 16384 /* use more memory, to reduce long-range seeks */ #endif #ifndef WSIZE # ifdef USE_DEFLATE64 # define WSIZE 65536L /* window size--must be a power of two, and */ # else /* at least 64K for PKZip's deflate64 method */ # define WSIZE 0x8000 /* window size--must be a power of two, and */ # endif /* at least 32K for zip's deflate method */ #endif #ifdef __16BIT__ # ifndef INT_16BIT # define INT_16BIT /* on 16-bit systems int size is 16 bits */ # endif #else # define nearmalloc malloc # define nearfree free # if (!defined(__IBMC__) || !defined(OS2)) # ifndef near # define near # endif # ifndef far # define far # endif # endif #endif #if (defined(DYNALLOC_CRCTAB) && !defined(DYNAMIC_CRC_TABLE)) # undef DYNALLOC_CRCTAB #endif #if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT)) # undef DYNALLOC_CRCTAB /* not safe with reentrant code */ #endif #if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB)) # ifdef DYNALLOC_CRCTAB # undef DYNALLOC_CRCTAB # endif #endif #if (defined(USE_ZLIB) && defined(ASM_CRC)) # undef ASM_CRC #endif #ifdef USE_ZLIB # ifdef IZ_CRC_BE_OPTIMIZ # undef IZ_CRC_BE_OPTIMIZ # endif # ifdef IZ_CRC_LE_OPTIMIZ # undef IZ_CRC_LE_OPTIMIZ # endif #endif #if (!defined(IZ_CRC_BE_OPTIMIZ) && !defined(IZ_CRC_LE_OPTIMIZ)) # ifdef IZ_CRCOPTIM_UNFOLDTBL # undef IZ_CRCOPTIM_UNFOLDTBL # endif #endif #ifndef INBUFSIZ # if (defined(MED_MEM) || defined(SMALL_MEM)) # define INBUFSIZ 2048 /* works for MS-DOS small model */ # else # define INBUFSIZ 8192 /* larger buffers for real OSes */ # endif #endif #if (defined(INT_16BIT) && (defined(USE_DEFLATE64) || lenEOL > 1)) /* For environments using 16-bit integers OUTBUFSIZ must be limited to * less than 64k (do_string() uses "unsigned" in calculations involving * OUTBUFSIZ). This is achieved by defining MED_MEM when WSIZE = 64k (aka * Deflate64 support enabled) or EOL markers contain multiple characters. * (The rule gets applied AFTER the default rule for INBUFSIZ because it * is not neccessary to reduce INBUFSIZE in this case.) */ # if (!defined(SMALL_MEM) && !defined(MED_MEM)) # define MED_MEM # endif #endif /* Logic for case of small memory, length of EOL > 1: if OUTBUFSIZ == 2048, * OUTBUFSIZ>>1 == 1024 and OUTBUFSIZ>>7 == 16; therefore rawbuf is 1008 bytes * and transbuf 1040 bytes. Have room for 32 extra EOL chars; 1008/32 == 31.5 * chars/line, smaller than estimated 35-70 characters per line for C source * and normal text. Hence difference is sufficient for most "average" files. * (Argument scales for larger OUTBUFSIZ.) */ #ifdef SMALL_MEM /* i.e., 16-bit OSes: MS-DOS, OS/2 1.x, etc. */ # define LoadFarString(x) fLoadFarString(__G__ (x)) # define LoadFarStringSmall(x) fLoadFarStringSmall(__G__ (x)) # define LoadFarStringSmall2(x) fLoadFarStringSmall2(__G__ (x)) # if (defined(_MSC_VER) && (_MSC_VER >= 600)) # define zfstrcpy(dest, src) _fstrcpy((dest), (src)) # define zfstrcmp(s1, s2) _fstrcmp((s1), (s2)) # endif # if !(defined(SFX) || defined(FUNZIP)) # if (defined(_MSC_VER)) # define zfmalloc(sz) _fmalloc((sz)) # define zffree(x) _ffree(x) # endif # if (defined(__TURBOC__)) # include # define zfmalloc(sz) farmalloc((unsigned long)(sz)) # define zffree(x) farfree(x) # endif # endif /* !(SFX || FUNZIP) */ # ifndef Far # define Far far /* __far only works for MSC 6.00, not 6.0a or Borland */ # endif # define OUTBUFSIZ INBUFSIZ # if (lenEOL == 1) # define RAWBUFSIZ (OUTBUFSIZ>>1) # else # define RAWBUFSIZ ((OUTBUFSIZ>>1) - (OUTBUFSIZ>>7)) # endif # define TRANSBUFSIZ (OUTBUFSIZ-RAWBUFSIZ) typedef short shrint; /* short/int or "shrink int" (unshrink) */ #else # define zfstrcpy(dest, src) strcpy((dest), (src)) # define zfstrcmp(s1, s2) strcmp((s1), (s2)) # define zfmalloc malloc # define zffree(x) free(x) # ifdef QDOS # define LoadFarString(x) Qstrfix(x) /* fix up _ for '.' */ # define LoadFarStringSmall(x) Qstrfix(x) # define LoadFarStringSmall2(x) Qstrfix(x) # else # define LoadFarString(x) (char *)(x) # define LoadFarStringSmall(x) (char *)(x) # define LoadFarStringSmall2(x) (char *)(x) # endif # ifdef MED_MEM # define OUTBUFSIZ 0xFF80 /* can't malloc arrays of 0xFFE8 or more */ # define TRANSBUFSIZ 0xFF80 typedef short shrint; # else # define OUTBUFSIZ (lenEOL*WSIZE) /* more efficient text conversion */ # define TRANSBUFSIZ (lenEOL*OUTBUFSIZ) # ifdef AMIGA typedef short shrint; # else typedef int shrint; /* for efficiency/speed, we hope... */ # endif # endif /* ?MED_MEM */ # define RAWBUFSIZ OUTBUFSIZ #endif /* ?SMALL_MEM */ #ifndef Far # define Far #endif #ifndef Cdecl # define Cdecl #endif #ifndef MAIN # define MAIN main #endif #ifdef SFX /* disable some unused features for SFX executables */ # ifndef NO_ZIPINFO # define NO_ZIPINFO # endif # ifdef TIMESTAMP # undef TIMESTAMP # endif #endif #ifdef SFX # ifdef CHEAP_SFX_AUTORUN # ifndef NO_SFX_EXDIR # define NO_SFX_EXDIR # endif # endif # ifndef NO_SFX_EXDIR # ifndef SFX_EXDIR # define SFX_EXDIR # endif # else # ifdef SFX_EXDIR # undef SFX_EXDIR # endif # endif #endif /* user may have defined both by accident... NOTIMESTAMP takes precedence */ #if (defined(TIMESTAMP) && defined(NOTIMESTAMP)) # undef TIMESTAMP #endif #if (!defined(COPYRIGHT_CLEAN) && !defined(USE_SMITH_CODE)) # define COPYRIGHT_CLEAN #endif /* The LZW patent is expired worldwide since 2004-Jul-07, so USE_UNSHRINK * is now enabled by default. See unshrink.c. */ #if (!defined(LZW_CLEAN) && !defined(USE_UNSHRINK)) # define USE_UNSHRINK #endif #ifndef O_BINARY # define O_BINARY 0 #endif #ifndef PIPE_ERROR # ifndef EPIPE # define EPIPE -1 # endif # define PIPE_ERROR (errno == EPIPE) #endif /* File operations--use "b" for binary if allowed or fixed length 512 on VMS */ #ifdef VMS # define FOPR "r","ctx=stm" # define FOPM "r+","ctx=stm","rfm=fix","mrs=512" # define FOPW "w","ctx=stm","rfm=fix","mrs=512" # define FOPWR "w+","ctx=stm","rfm=fix","mrs=512" #endif /* VMS */ #ifdef CMS_MVS /* Binary files must be RECFM=F,LRECL=1 for ftell() to get correct pos */ /* ...unless byteseek is used. Let's try that for a while. */ # define FOPR "rb,byteseek" # define FOPM "r+b,byteseek" # ifdef MVS # define FOPW "wb,recfm=u,lrecl=32760,byteseek" /* New binary files */ # define FOPWE "wb" /* Existing binary files */ # define FOPWT "w,lrecl=133" /* New text files */ # define FOPWTE "w" /* Existing text files */ # else # define FOPW "wb,recfm=v,lrecl=32760" # define FOPWT "w" # endif #endif /* CMS_MVS */ #ifdef TOPS20 /* TOPS-20 MODERN? You kidding? */ # define FOPW "w8" #endif /* TOPS20 */ /* Defaults when nothing special has been defined previously. */ #ifdef MODERN # ifndef FOPR # define FOPR "rb" # endif # ifndef FOPM # define FOPM "r+b" # endif # ifndef FOPW # define FOPW "wb" # endif # ifndef FOPWT # define FOPWT "wt" # endif # ifndef FOPWR # define FOPWR "w+b" # endif #else /* !MODERN */ # ifndef FOPR # define FOPR "r" # endif # ifndef FOPM # define FOPM "r+" # endif # ifndef FOPW # define FOPW "w" # endif # ifndef FOPWT # define FOPWT "w" # endif # ifndef FOPWR # define FOPWR "w+" # endif #endif /* ?MODERN */ /* * If exists on most systems, should include that, since it may * define some or all of the following: NAME_MAX, PATH_MAX, _POSIX_NAME_MAX, * _POSIX_PATH_MAX. */ #ifdef DOS_FLX_NLM_OS2_W32 # include #endif /* 2008-07-22 SMS. * Unfortunately, on VMS, exists, and is included by * (so it's pretty much unavoidable), and it defines PATH_MAX to a fixed * short value (256, correct only for older systems without ODS-5 support), * rather than one based on the real RMS NAM[L] situation. So, we * artificially undefine it here, to allow our better-defined _MAX_PATH * (see vms/vmscfg.h) to be used. */ #ifdef VMS # undef PATH_MAX #endif #ifndef PATH_MAX # ifdef MAXPATHLEN # define PATH_MAX MAXPATHLEN /* in on some systems */ # else # ifdef _MAX_PATH # define PATH_MAX _MAX_PATH # else # if FILENAME_MAX > 255 # define PATH_MAX FILENAME_MAX /* used like PATH_MAX on some systems */ # else # define PATH_MAX 1024 # endif # endif /* ?_MAX_PATH */ # endif /* ?MAXPATHLEN */ #endif /* !PATH_MAX */ /* * buffer size required to hold the longest legal local filepath * (including the trailing '\0') */ #define FILNAMSIZ PATH_MAX #ifdef UNICODE_SUPPORT # if !(defined(UTF8_MAYBE_NATIVE) || defined(UNICODE_WCHAR)) # undef UNICODE_SUPPORT # endif #endif /* 2007-09-18 SMS. * Include here if it will be needed later for Unicode. * Otherwise, SETLOCALE may be defined here, and then defined again * (differently) when is read later. */ #ifdef UNICODE_SUPPORT # ifdef UNICODE_WCHAR # if !(defined(_WIN32_WCE) || defined(POCKET_UNZIP)) # include # endif # endif # ifndef _MBCS /* no need to include twice, see below */ # include # ifndef SETLOCALE # define SETLOCALE(category, locale) setlocale(category, locale) # endif # endif #endif /* UNICODE_SUPPORT */ /* DBCS support for Info-ZIP (mainly for japanese (-: ) * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp) */ #ifdef _MBCS # include /* Multi Byte Character Set */ # define ___MBS_TMP_DEF char *___tmp_ptr; # define ___TMP_PTR ___tmp_ptr # ifndef CLEN # define NEED_UZMBCLEN # define CLEN(ptr) (int)uzmbclen((ZCONST unsigned char *)(ptr)) # endif # ifndef PREINCSTR # define PREINCSTR(ptr) (ptr += CLEN(ptr)) # endif # define POSTINCSTR(ptr) (___TMP_PTR=(char *)(ptr), PREINCSTR(ptr),___TMP_PTR) char *plastchar OF((ZCONST char *ptr, extent len)); # define lastchar(ptr, len) ((int)(unsigned)*plastchar(ptr, len)) # ifndef MBSCHR # define NEED_UZMBSCHR # define MBSCHR(str,c) (char *)uzmbschr((ZCONST unsigned char *)(str), c) # endif # ifndef MBSRCHR # define NEED_UZMBSRCHR # define MBSRCHR(str,c) (char *)uzmbsrchr((ZCONST unsigned char *)(str), c) # endif # ifndef SETLOCALE # define SETLOCALE(category, locale) setlocale(category, locale) # endif #else /* !_MBCS */ # define ___MBS_TMP_DEF # define ___TMP_PTR # define CLEN(ptr) 1 # define PREINCSTR(ptr) (++(ptr)) # define POSTINCSTR(ptr) ((ptr)++) # define plastchar(ptr, len) (&ptr[(len)-1]) # define lastchar(ptr, len) (ptr[(len)-1]) # define MBSCHR(str, c) strchr(str, c) # define MBSRCHR(str, c) strrchr(str, c) # ifndef SETLOCALE # define SETLOCALE(category, locale) # endif #endif /* ?_MBCS */ #define INCSTR(ptr) PREINCSTR(ptr) #if (defined(MALLOC_WORK) && !defined(MY_ZCALLOC)) /* Any system without a special calloc function */ # ifndef zcalloc # define zcalloc(items, size) \ (zvoid far *)calloc((unsigned)(items), (unsigned)(size)) # endif # ifndef zcfree # define zcfree free # endif #endif /* MALLOC_WORK && !MY_ZCALLOC */ #if (defined(CRAY) && defined(ZMEM)) # undef ZMEM #endif #ifdef ZMEM # undef ZMEM # define memcmp(b1,b2,len) bcmp(b2,b1,len) # define memcpy(dest,src,len) bcopy(src,dest,len) # define memzero bzero #else # define memzero(dest,len) memset(dest,0,len) #endif #ifndef TRUE # define TRUE 1 /* sort of obvious */ #endif #ifndef FALSE # define FALSE 0 #endif #ifndef SEEK_SET # define SEEK_SET 0 # define SEEK_CUR 1 # define SEEK_END 2 #endif #if (!defined(S_IEXEC) && defined(S_IXUSR)) # define S_IEXEC S_IXUSR #endif #if (defined(UNIX) && defined(S_IFLNK) && !defined(MTS)) # define SYMLINKS # ifndef S_ISLNK # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) # endif #endif /* UNIX && S_IFLNK && !MTS */ #ifndef S_ISDIR # ifdef CMS_MVS # define S_ISDIR(m) (FALSE) # else # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) # endif #endif #ifndef IS_VOLID # define IS_VOLID(m) ((m) & 0x08) #endif /***********************************/ /* LARGE_FILE_SUPPORT */ /***********************************/ /* This whole section lifted from Zip 3b tailor.h * Types are in OS dependent headers (eg, w32cfg.h) * * LARGE_FILE_SUPPORT and ZIP64_SUPPORT are automatically * set in OS dependent headers (for some ports) based on the port and compiler. * * Function prototypes are below as OF is defined earlier in this file * but after OS dependent header is included. * * E. Gordon 9/21/2003 * Updated 1/28/2004 * Lifted and placed here 6/7/2004 - Myles Bennett */ #ifdef LARGE_FILE_SUPPORT /* 64-bit Large File Support */ /* ---------------------------- */ # if defined(UNIX) || defined(VMS) /* 64-bit stat functions */ # define zstat stat # define zfstat fstat /* 64-bit fseeko */ # define zlseek lseek # define zfseeko fseeko /* 64-bit ftello */ # define zftello ftello /* 64-bit fopen */ # define zfopen fopen # define zfdopen fdopen # endif /* UNIX || VMS */ /* ---------------------------- */ # ifdef WIN32 # if defined(_MSC_VER) || defined(__MINGW32__) || defined(__LCC__) /* MS C (VC), MinGW GCC port and LCC-32 use the MS C Runtime lib */ /* 64-bit stat functions */ # define zstat _stati64 # define zfstat _fstati64 /* 64-bit lseek */ # define zlseek _lseeki64 # if defined(_MSC_VER) && (_MSC_VER >= 1400) /* Beginning with VS 8.0 (Visual Studio 2005, MSC 14), the Microsoft C rtl publishes its (previously internal) implmentations of "fseeko" and "ftello" for 64-bit file offsets. */ /* 64-bit fseeko */ # define zfseeko _fseeki64 /* 64-bit ftello */ # define zftello _ftelli64 # else /* not (defined(_MSC_VER) && (_MSC_VER >= 1400)) */ # if defined(__MSVCRT_VERSION__) && (__MSVCRT_VERSION__ >= 0x800) /* Up-to-date versions of MinGW define the macro __MSVCRT_VERSION__ to denote the version of the MS C rtl dll used for linking. When configured to link against the runtime of MS Visual Studio 8 (or newer), the built-in 64-bit fseek/ftell functions are available. */ /* 64-bit fseeko */ # define zfseeko _fseeki64 /* 64-bit ftello */ # define zftello _ftelli64 # else /* !(defined(__MSVCRT_VERSION__) && (__MSVCRT_VERSION__>=0x800)) */ /* The version of the C runtime is lower than MSC 14 or unknown. */ /* The newest MinGW port contains built-in extensions to the MSC rtl that provide fseeko and ftello, but our implementations will do for now. */ /* 64-bit fseeko */ int zfseeko OF((FILE *, zoff_t, int)); /* 64-bit ftello */ zoff_t zftello OF((FILE *)); # endif /* ? (__MSVCRT_VERSION__ >= 0x800) */ # endif /* ? (_MSC_VER >= 1400) */ /* 64-bit fopen */ # define zfopen fopen # define zfdopen fdopen # endif /* _MSC_VER || __MINGW__ || __LCC__ */ # ifdef __CYGWIN__ /* CYGWIN GCC Posix emulator on Windows (configuration not yet finished/tested) */ /* 64-bit stat functions */ # define zstat _stati64 # define zfstat _fstati64 /* 64-bit lseek */ # define zlseek _lseeki64 /* 64-bit fseeko */ # define zfseeko fseeko /* 64-bit ftello */ # define zftello ftello /* 64-bit fopen */ # define zfopen fopen # define zfdopen fdopen # endif # if defined(__WATCOMC__) || defined(__BORLANDC__) /* WATCOM C and Borland C provide their own C runtime libraries, but they are sufficiently compatible with MS CRTL. */ /* 64-bit stat functions */ # define zstat _stati64 # define zfstat _fstati64 # ifdef __WATCOMC__ /* 64-bit lseek */ # define zlseek _lseeki64 # endif /* 64-bit fseeko */ int zfseeko OF((FILE *, zoff_t, int)); /* 64-bit ftello */ zoff_t zftello OF((FILE *)); /* 64-bit fopen */ # define zfopen fopen # define zfdopen fdopen # endif # ifdef __IBMC__ /* IBM C */ /* 64-bit stat functions */ /* 64-bit fseeko */ /* 64-bit ftello */ /* 64-bit fopen */ # endif # endif /* WIN32 */ #else /* No Large File Support */ # ifndef REGULUS /* returns the inode number on success(!)...argh argh argh */ # define zstat stat # endif # define zfstat fstat # define zlseek lseek # define zfseeko fseek # define zftello ftell # define zfopen fopen # define zfdopen fdopen # if defined(UNIX) || defined(VMS) || defined(WIN32) /* For these systems, implement "64bit file vs. 32bit prog" check */ # ifndef DO_SAFECHECK_2GB # define DO_SAFECHECK_2GB # endif # endif #endif /* No "64bit file vs. 32bit prog" check for SFX stub, to save space */ #if (defined(DO_SAFECHECK_2GB) && defined(SFX)) # undef DO_SAFECHECK_2GB #endif #ifndef SSTAT # ifdef WILD_STAT_BUG # define SSTAT(path,pbuf) (iswild(path) || zstat(path,pbuf)) # else # define SSTAT zstat # endif #endif /* Default fzofft() format selection. */ #ifndef FZOFFT_FMT # ifdef LARGE_FILE_SUPPORT # define FZOFFT_FMT "ll" # define FZOFFT_HEX_WID_VALUE "16" # else /* def LARGE_FILE_SUPPORT */ # define FZOFFT_FMT "l" # define FZOFFT_HEX_WID_VALUE "8" # endif /* def LARGE_FILE_SUPPORT */ #endif /* ndef FZOFFT_FMT */ #define FZOFFT_HEX_WID ((char *) -1) #define FZOFFT_HEX_DOT_WID ((char *) -2) #define FZOFFT_NUM 4 /* Number of chambers. */ #define FZOFFT_LEN 24 /* Number of characters/chamber. */ #ifdef SHORT_SYMS /* Mark Williams C, ...? */ # define extract_or_test_files xtr_or_tst_files # define extract_or_test_member xtr_or_tst_member #endif #ifdef REALLY_SHORT_SYMS /* TOPS-20 linker: first 6 chars */ # define process_cdir_file_hdr XXpcdfh # define process_local_file_hdr XXplfh # define extract_or_test_files XXxotf /* necessary? */ # define extract_or_test_member XXxotm /* necessary? */ # define check_for_newer XXcfn # define overwrite_all XXoa # define process_all_files XXpaf # define extra_field XXef # define explode_lit8 XXel8 # define explode_lit4 XXel4 # define explode_nolit8 XXnl8 # define explode_nolit4 XXnl4 # define cpdist8 XXcpdist8 # define inflate_codes XXic # define inflate_stored XXis # define inflate_fixed XXif # define inflate_dynamic XXid # define inflate_block XXib # define maxcodemax XXmax #endif #ifndef S_TIME_T_MAX /* max value of signed (>= 32-bit) time_t */ # define S_TIME_T_MAX ((time_t)(ulg)0x7fffffffL) #endif #ifndef U_TIME_T_MAX /* max value of unsigned (>= 32-bit) time_t */ # define U_TIME_T_MAX ((time_t)(ulg)0xffffffffL) #endif #ifdef DOSTIME_MINIMUM /* min DOSTIME value (1980-01-01) */ # undef DOSTIME_MINIMUM #endif #define DOSTIME_MINIMUM ((ulg)0x00210000L) #ifdef DOSTIME_2038_01_18 /* approximate DOSTIME equivalent of */ # undef DOSTIME_2038_01_18 /* the signed-32-bit time_t limit */ #endif #define DOSTIME_2038_01_18 ((ulg)0x74320000L) #ifdef QDOS # define ZSUFX "_zip" # define ALT_ZSUFX ".zip" #else # ifdef RISCOS # define ZSUFX "/zip" # else # define ZSUFX ".zip" # endif # define ALT_ZSUFX ".ZIP" /* Unix-only so far (only case-sensitive fs) */ #endif #define CENTRAL_HDR_SIG "\001\002" /* the infamous "PK" signature bytes, */ #define LOCAL_HDR_SIG "\003\004" /* w/o "PK" (so unzip executable not */ #define END_CENTRAL_SIG "\005\006" /* mistaken for zipfile itself) */ #define EXTD_LOCAL_SIG "\007\010" /* [ASCII "\113" == EBCDIC "\080" ??] */ /** internal-only return codes **/ #define IZ_DIR 76 /* potential zipfile is a directory */ /* special return codes for mapname() */ #define MPN_OK 0 /* mapname successful */ #define MPN_INF_TRUNC (1<<8) /* caution - filename truncated */ #define MPN_INF_SKIP (2<<8) /* info - skipped because nothing to do */ #define MPN_ERR_SKIP (3<<8) /* error - entry skipped */ #define MPN_ERR_TOOLONG (4<<8) /* error - path too long */ #define MPN_NOMEM (10<<8) /* error - out of memory, file skipped */ #define MPN_CREATED_DIR (16<<8) /* directory created: set time & permission */ #define MPN_VOL_LABEL (17<<8) /* volume label, but can't set on hard disk */ #define MPN_INVALID (99<<8) /* internal logic error, should never reach */ /* mask for internal mapname&checkdir return codes */ #define MPN_MASK 0x7F00 /* error code for extracting/testing extra field blocks */ #define IZ_EF_TRUNC 79 /* local extra field truncated (PKZIP'd) */ /* choice of activities for do_string() */ #define SKIP 0 /* skip header block */ #define DISPLAY 1 /* display archive comment (ASCII) */ #define DISPL_8 5 /* display file comment (ext. ASCII) */ #define DS_FN 2 /* read filename (ext. ASCII, chead) */ #define DS_FN_C 2 /* read filename from central header */ #define DS_FN_L 6 /* read filename from local header */ #define EXTRA_FIELD 3 /* copy extra field into buffer */ #define DS_EF 3 #ifdef AMIGA # define FILENOTE 4 /* convert file comment to filenote */ #endif #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) # define CHECK_AUTORUN 7 /* copy command, display remainder */ # define CHECK_AUTORUN_Q 8 /* copy command, skip remainder */ #endif #define DOES_NOT_EXIST -1 /* return values for check_for_newer() */ #define EXISTS_AND_OLDER 0 #define EXISTS_AND_NEWER 1 #define OVERWRT_QUERY 0 /* status values for G.overwrite_mode */ #define OVERWRT_ALWAYS 1 #define OVERWRT_NEVER 2 #define IS_OVERWRT_ALL (G.overwrite_mode == OVERWRT_ALWAYS) #define IS_OVERWRT_NONE (G.overwrite_mode == OVERWRT_NEVER) #ifdef VMS /* return codes for VMS-specific open_outfile() function */ # define OPENOUT_OK 0 /* file openend normally */ # define OPENOUT_FAILED 1 /* file open failed */ # define OPENOUT_SKIPOK 2 /* file not opened, skip at error level OK */ # define OPENOUT_SKIPWARN 3 /* file not opened, skip at error level WARN */ #endif /* VMS */ #define ROOT 0 /* checkdir() extract-to path: called once */ #define INIT 1 /* allocate buildpath: called once per member */ #define APPEND_DIR 2 /* append a dir comp.: many times per member */ #define APPEND_NAME 3 /* append actual filename: once per member */ #define GETPATH 4 /* retrieve the complete path and free it */ #define END 5 /* free root path prior to exiting program */ /* version_made_by codes (central dir): make sure these */ /* are not defined on their respective systems!! */ #define FS_FAT_ 0 /* filesystem used by MS-DOS, OS/2, Win32 */ #define AMIGA_ 1 #define VMS_ 2 #define UNIX_ 3 #define VM_CMS_ 4 #define ATARI_ 5 /* what if it's a minix filesystem? [cjh] */ #define FS_HPFS_ 6 /* filesystem used by OS/2 (and NT 3.x) */ #define MAC_ 7 /* HFS filesystem used by MacOS */ #define Z_SYSTEM_ 8 #define CPM_ 9 #define TOPS20_ 10 #define FS_NTFS_ 11 /* filesystem used by Windows NT */ #define QDOS_ 12 #define ACORN_ 13 /* Archimedes Acorn RISC OS */ #define FS_VFAT_ 14 /* filesystem used by Windows 95, NT */ #define MVS_ 15 #define BEOS_ 16 /* hybrid POSIX/database filesystem */ #define TANDEM_ 17 /* Tandem NSK */ #define THEOS_ 18 /* THEOS */ #define MAC_OSX_ 19 /* Mac OS/X (Darwin) */ #define ATHEOS_ 30 /* AtheOS */ #define NUM_HOSTS 31 /* index of last system + 1 */ /* don't forget to update zipinfo.c appropiately if NUM_HOSTS changes! */ #define STORED 0 /* compression methods */ #define SHRUNK 1 #define REDUCED1 2 #define REDUCED2 3 #define REDUCED3 4 #define REDUCED4 5 #define IMPLODED 6 #define TOKENIZED 7 #define DEFLATED 8 #define ENHDEFLATED 9 #define DCLIMPLODED 10 #define BZIPPED 12 #define LZMAED 14 #define IBMTERSED 18 #define IBMLZ77ED 19 #define WAVPACKED 97 #define PPMDED 98 #define NUM_METHODS 17 /* number of known method IDs */ /* don't forget to update list.c (list_files()), extract.c and zipinfo.c * appropriately if NUM_METHODS changes */ /* (the PK-class error codes are public and have been moved into unzip.h) */ #define DF_MDY 0 /* date format 10/26/91 (USA only) */ #define DF_DMY 1 /* date format 26/10/91 (most of the world) */ #define DF_YMD 2 /* date format 91/10/26 (a few countries) */ /*--------------------------------------------------------------------------- Extra-field block ID values and offset info. ---------------------------------------------------------------------------*/ /* extra-field ID values, all little-endian: */ #define EF_PKSZ64 0x0001 /* PKWARE's 64-bit filesize extensions */ #define EF_AV 0x0007 /* PKWARE's authenticity verification */ #define EF_EFS 0x0008 /* PKWARE's extended language encoding */ #define EF_OS2 0x0009 /* OS/2 extended attributes */ #define EF_PKW32 0x000a /* PKWARE's Win95/98/WinNT filetimes */ #define EF_PKVMS 0x000c /* PKWARE's VMS */ #define EF_PKUNIX 0x000d /* PKWARE's Unix */ #define EF_PKFORK 0x000e /* PKWARE's future stream/fork descriptors */ #define EF_PKPATCH 0x000f /* PKWARE's patch descriptor */ #define EF_PKPKCS7 0x0014 /* PKWARE's PKCS#7 store for X.509 Certs */ #define EF_PKFX509 0x0015 /* PKWARE's file X.509 Cert&Signature ID */ #define EF_PKCX509 0x0016 /* PKWARE's central dir X.509 Cert ID */ #define EF_PKENCRHD 0x0017 /* PKWARE's Strong Encryption header */ #define EF_PKRMCTL 0x0018 /* PKWARE's Record Management Controls*/ #define EF_PKLSTCS7 0x0019 /* PKWARE's PKCS#7 Encr. Recipient Cert List */ #define EF_PKIBM 0x0065 /* PKWARE's IBM S/390 & AS/400 attributes */ #define EF_PKIBM2 0x0066 /* PKWARE's IBM S/390 & AS/400 compr. attribs */ #define EF_IZVMS 0x4d49 /* Info-ZIP's VMS ("IM") */ #define EF_IZUNIX 0x5855 /* Info-ZIP's first Unix[1] ("UX") */ #define EF_IZUNIX2 0x7855 /* Info-ZIP's second Unix[2] ("Ux") */ #define EF_IZUNIX3 0x7875 /* Info-ZIP's newest Unix[3] ("ux") */ #define EF_TIME 0x5455 /* universal timestamp ("UT") */ #define EF_UNIPATH 0x7075 /* Info-ZIP Unicode Path ("up") */ #define EF_UNICOMNT 0x6375 /* Info-ZIP Unicode Comment ("uc") */ #define EF_MAC3 0x334d /* Info-ZIP's new Macintosh (= "M3") */ #define EF_JLMAC 0x07c8 /* Johnny Lee's old Macintosh (= 1992) */ #define EF_ZIPIT 0x2605 /* Thomas Brown's Macintosh (ZipIt) */ #define EF_ZIPIT2 0x2705 /* T. Brown's Mac (ZipIt) v 1.3.8 and newer ? */ #define EF_SMARTZIP 0x4d63 /* Mac SmartZip by Marco Bambini */ #define EF_VMCMS 0x4704 /* Info-ZIP's VM/CMS ("\004G") */ #define EF_MVS 0x470f /* Info-ZIP's MVS ("\017G") */ #define EF_ACL 0x4c41 /* (OS/2) access control list ("AL") */ #define EF_NTSD 0x4453 /* NT security descriptor ("SD") */ #define EF_ATHEOS 0x7441 /* AtheOS ("At") */ #define EF_BEOS 0x6542 /* BeOS ("Be") */ #define EF_QDOS 0xfb4a /* SMS/QDOS ("J\373") */ #define EF_AOSVS 0x5356 /* AOS/VS ("VS") */ #define EF_SPARK 0x4341 /* David Pilling's Acorn/SparkFS ("AC") */ #define EF_TANDEM 0x4154 /* Tandem NSK ("TA") */ #define EF_THEOS 0x6854 /* Jean-Michel Dubois' Theos "Th" */ #define EF_THEOSO 0x4854 /* old Theos port */ #define EF_MD5 0x4b46 /* Fred Kantor's MD5 ("FK") */ #define EF_ASIUNIX 0x756e /* ASi's Unix ("nu") */ #define EB_HEADSIZE 4 /* length of extra field block header */ #define EB_ID 0 /* offset of block ID in header */ #define EB_LEN 2 /* offset of data length field in header */ #define EB_UCSIZE_P 0 /* offset of ucsize field in compr. data */ #define EB_CMPRHEADLEN 6 /* lenght of compression header */ #define EB_UX_MINLEN 8 /* minimal "UX" field contains atime, mtime */ #define EB_UX_FULLSIZE 12 /* full "UX" field (atime, mtime, uid, gid) */ #define EB_UX_ATIME 0 /* offset of atime in "UX" extra field data */ #define EB_UX_MTIME 4 /* offset of mtime in "UX" extra field data */ #define EB_UX_UID 8 /* byte offset of UID in "UX" field data */ #define EB_UX_GID 10 /* byte offset of GID in "UX" field data */ #define EB_UX2_MINLEN 4 /* minimal "Ux" field contains UID/GID */ #define EB_UX2_UID 0 /* byte offset of UID in "Ux" field data */ #define EB_UX2_GID 2 /* byte offset of GID in "Ux" field data */ #define EB_UX2_VALID (1 << 8) /* UID/GID present */ #define EB_UX3_MINLEN 7 /* minimal "ux" field size (2-byte UID/GID) */ #define EB_UT_MINLEN 1 /* minimal UT field contains Flags byte */ #define EB_UT_FLAGS 0 /* byte offset of Flags field */ #define EB_UT_TIME1 1 /* byte offset of 1st time value */ #define EB_UT_FL_MTIME (1 << 0) /* mtime present */ #define EB_UT_FL_ATIME (1 << 1) /* atime present */ #define EB_UT_FL_CTIME (1 << 2) /* ctime present */ #define EB_FLGS_OFFS 4 /* offset of flags area in generic compressed extra field blocks (BEOS, MAC, and others) */ #define EB_OS2_HLEN 4 /* size of OS2/ACL compressed data header */ #define EB_BEOS_HLEN 5 /* length of BeOS&AtheOS e.f attribute header */ #define EB_BE_FL_UNCMPR 0x01 /* "BeOS&AtheOS attribs uncompr." bit flag */ #define EB_MAC3_HLEN 14 /* length of Mac3 attribute block header */ #define EB_SMARTZIP_HLEN 64 /* fixed length of the SmartZip extra field */ #define EB_M3_FL_DATFRK 0x01 /* "this entry is data fork" flag */ #define EB_M3_FL_UNCMPR 0x04 /* "Mac3 attributes uncompressed" bit flag */ #define EB_M3_FL_TIME64 0x08 /* "Mac3 time fields are 64 bit wide" flag */ #define EB_M3_FL_NOUTC 0x10 /* "Mac3 timezone offset fields missing" flag */ #define EB_NTSD_C_LEN 4 /* length of central NT security data */ #define EB_NTSD_L_LEN 5 /* length of minimal local NT security data */ #define EB_NTSD_VERSION 4 /* offset of NTSD version byte */ #define EB_NTSD_MAX_VER (0) /* maximum version # we know how to handle */ #define EB_ASI_CRC32 0 /* offset of ASI Unix field's crc32 checksum */ #define EB_ASI_MODE 4 /* offset of ASI Unix permission mode field */ #define EB_IZVMS_HLEN 12 /* length of IZVMS attribute block header */ #define EB_IZVMS_FLGS 4 /* offset of compression type flag */ #define EB_IZVMS_UCSIZ 6 /* offset of ucsize field in IZVMS header */ #define EB_IZVMS_BCMASK 07 /* 3 bits for compression type */ #define EB_IZVMS_BCSTOR 0 /* Stored */ #define EB_IZVMS_BC00 1 /* 0byte -> 0bit compression */ #define EB_IZVMS_BCDEFL 2 /* Deflated */ /*--------------------------------------------------------------------------- True sizes of the various headers (excluding their 4-byte signatures), as defined by PKWARE--so it is not likely that these will ever change. But if they do, make sure both these defines AND the typedefs below get updated accordingly. 12/27/2006 The Zip64 End Of Central Directory record is variable size and now comes in two flavors, version 1 and the new version 2 that supports central directory encryption. We only use the old fields at the top of the Zip64 EOCDR, and this block is a fixed size still, but need to be aware of the stuff following. ---------------------------------------------------------------------------*/ #define LREC_SIZE 26 /* lengths of local file headers, central */ #define CREC_SIZE 42 /* directory headers, end-of-central-dir */ #define ECREC_SIZE 18 /* record, zip64 end-of-cent-dir locator */ #define ECLOC64_SIZE 16 /* and zip64 end-of-central-dir record, */ #define ECREC64_SIZE 52 /* respectively */ #define MAX_BITS 13 /* used in unshrink() */ #define HSIZE (1 << MAX_BITS) /* size of global work area */ #define LF 10 /* '\n' on ASCII machines; must be 10 due to EBCDIC */ #define CR 13 /* '\r' on ASCII machines; must be 13 due to EBCDIC */ #define CTRLZ 26 /* DOS & OS/2 EOF marker (used in fileio.c, vms.c) */ #ifdef EBCDIC # define foreign(c) ascii[(uch)(c)] # define native(c) ebcdic[(uch)(c)] # define NATIVE "EBCDIC" # define NOANSIFILT #endif #ifdef VMS # define ENV_UNZIP "UNZIP_OPTS" /* names of environment variables */ # define ENV_ZIPINFO "ZIPINFO_OPTS" #endif /* VMS */ #ifdef RISCOS # define ENV_UNZIP "Unzip$Options" # define ENV_ZIPINFO "Zipinfo$Options" # define ENV_UNZIPEXTS "Unzip$Exts" #endif /* RISCOS */ #ifndef ENV_UNZIP # define ENV_UNZIP "UNZIP" /* the standard names */ # define ENV_ZIPINFO "ZIPINFO" #endif #define ENV_UNZIP2 "UNZIPOPT" /* alternate names, for zip compat. */ #define ENV_ZIPINFO2 "ZIPINFOOPT" #if (!defined(QQ) && !defined(NOQQ)) # define QQ #endif #ifdef QQ /* Newtware version: no file */ # define QCOND (!uO.qflag) /* comments with -vq or -vqq */ #else /* Bill Davidsen version: no way to */ # define QCOND (longhdr) /* kill file comments when listing */ #endif #ifdef OLD_QQ # define QCOND2 (uO.qflag < 2) #else # define QCOND2 (!uO.qflag) #endif #ifdef WILD_STOP_AT_DIR # define __WDLPRO , int sepc # define __WDL , sepc # define __WDLDEF int sepc; # define WISEP , (uO.W_flag ? '/' : '\0') #else # define __WDLPRO # define __WDL # define __WDLDEF # define WISEP #endif /**************/ /* Typedefs */ /**************/ #ifdef ZIP64_SUPPORT # ifndef Z_UINT8_DEFINED # if (defined(__GNUC__) || defined(__hpux) || defined(__SUNPRO_C)) typedef unsigned long long z_uint8; # else typedef unsigned __int64 z_uint8; # endif # define Z_UINT8_DEFINED # endif #endif #ifndef Z_UINT4_DEFINED # if (defined(MODERN) && !defined(NO_LIMITS_H)) # if (defined(UINT_MAX) && (UINT_MAX == 0xffffffffUL)) typedef unsigned int z_uint4; # define Z_UINT4_DEFINED # else # if (defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL)) typedef unsigned long z_uint4; # define Z_UINT4_DEFINED # else # if (defined(USHRT_MAX) && (USHRT_MAX == 0xffffffffUL)) typedef unsigned short z_uint4; # define Z_UINT4_DEFINED # endif # endif # endif # endif /* MODERN && !NO_LIMITS_H */ #endif /* !Z_UINT4_DEFINED */ #ifndef Z_UINT4_DEFINED typedef ulg z_uint4; # define Z_UINT4_DEFINED #endif /* The following three user-defined unsigned integer types are used for holding zipfile entities (required widths without / with Zip64 support): a) sizes and offset of zipfile entries (4 bytes / 8 bytes) b) enumeration and counts of zipfile entries (2 bytes / 8 bytes) Remark: internally, we use 4 bytes for archive member counting in the No-Zip64 case, because UnZip supports more than 64k entries for classic Zip archives without Zip64 extensions. c) enumeration and counts of zipfile volumes of multivolume archives (2 bytes / 4 bytes) */ #ifdef ZIP64_SUPPORT typedef z_uint8 zusz_t; /* zipentry sizes & offsets */ typedef z_uint8 zucn_t; /* archive entry counts */ typedef z_uint4 zuvl_t; /* multivolume numbers */ # define MASK_ZUCN64 (~(zucn_t)0) /* In case we ever get to support an environment where z_uint8 may be WIDER than 64 bit wide, we will have to apply a construct similar to #define MASK_ZUCN64 (~(zucn_t)0 & (zucn_t)0xffffffffffffffffULL) for the 64-bit mask. */ #else typedef ulg zusz_t; /* zipentry sizes & offsets */ typedef unsigned int zucn_t; /* archive entry counts */ typedef unsigned short zuvl_t; /* multivolume numbers */ # define MASK_ZUCN64 (~(zucn_t)0) #endif #define MASK_ZUCN16 ((zucn_t)0xFFFF) #ifdef NO_UID_GID # ifdef UID_USHORT typedef unsigned short uid_t; /* TI SysV.3 */ typedef unsigned short gid_t; # else typedef unsigned int uid_t; /* SCO Xenix */ typedef unsigned int gid_t; # endif #endif #if (defined(GOT_UTIMBUF) || defined(sgi) || defined(ATARI)) typedef struct utimbuf ztimbuf; #else typedef struct ztimbuf { time_t actime; /* new access time */ time_t modtime; /* new modification time */ } ztimbuf; #endif typedef struct iztimes { time_t atime; /* new access time */ time_t mtime; /* new modification time */ time_t ctime; /* used for creation time; NOT same as st_ctime */ } iztimes; #ifdef SET_DIR_ATTRIB typedef struct direntry { /* head of system-specific struct holding */ struct direntry *next; /* defered directory attributes info */ char *fn; /* filename of directory */ char buf[1]; /* start of system-specific internal data */ } direntry; #endif /* SET_DIR_ATTRIB */ #ifdef SYMLINKS typedef struct slinkentry { /* info for deferred symlink creation */ struct slinkentry *next; /* pointer to next entry in chain */ extent targetlen; /* length of target filespec */ extent attriblen; /* length of system-specific attrib data */ char *target; /* pointer to target filespec */ char *fname; /* pointer to name of link */ char buf[1]; /* data/name/link buffer */ } slinkentry; #endif /* SYMLINKS */ typedef struct min_info { zoff_t offset; zusz_t compr_size; /* compressed size (needed if extended header) */ zusz_t uncompr_size; /* uncompressed size (needed if extended header) */ ulg crc; /* crc (needed if extended header) */ zuvl_t diskstart; /* no of volume where this entry starts */ uch hostver; uch hostnum; unsigned file_attr; /* local flavor, as used by creat(), chmod()... */ unsigned encrypted : 1; /* file encrypted: decrypt before uncompressing */ unsigned ExtLocHdr : 1; /* use time instead of CRC for decrypt check */ unsigned textfile : 1; /* file is text (according to zip) */ unsigned textmode : 1; /* file is to be extracted as text */ unsigned lcflag : 1; /* convert filename to lowercase */ unsigned vollabel : 1; /* "file" is an MS-DOS volume (disk) label */ #ifdef SYMLINKS unsigned symlink : 1; /* file is a symbolic link */ #endif unsigned HasUxAtt : 1; /* crec ext_file_attr has Unix style mode bits */ #ifdef UNICODE_SUPPORT unsigned GPFIsUTF8: 1; /* crec gen_purpose_flag UTF-8 bit 11 is set */ #endif #ifndef SFX char Far *cfilname; /* central header version of filename */ #endif } min_info; typedef struct VMStimbuf { char *revdate; /* (both roughly correspond to Unix modtime/st_mtime) */ char *credate; } VMStimbuf; /*--------------------------------------------------------------------------- Zipfile work area declarations. ---------------------------------------------------------------------------*/ #ifdef MALLOC_WORK union work { struct { /* unshrink(): */ shrint *Parent; /* pointer to (8192 * sizeof(shrint)) */ uch *value; /* pointer to 8KB char buffer */ uch *Stack; /* pointer to another 8KB char buffer */ } shrink; uch *Slide; /* explode(), inflate(), unreduce() */ }; #else /* !MALLOC_WORK */ union work { struct { /* unshrink(): */ shrint Parent[HSIZE]; /* (8192 * sizeof(shrint)) == 16KB minimum */ uch value[HSIZE]; /* 8KB */ uch Stack[HSIZE]; /* 8KB */ } shrink; /* total = 32KB minimum; 80KB on Cray/Alpha */ uch Slide[WSIZE]; /* explode(), inflate(), unreduce() */ }; #endif /* ?MALLOC_WORK */ #define slide G.area.Slide #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) # define redirSlide G.redirect_sldptr #else # define redirSlide G.area.Slide #endif /*--------------------------------------------------------------------------- Zipfile layout declarations. If these headers ever change, make sure the xxREC_SIZE defines (above) change with them! ---------------------------------------------------------------------------*/ typedef uch local_byte_hdr[ LREC_SIZE ]; # define L_VERSION_NEEDED_TO_EXTRACT_0 0 # define L_VERSION_NEEDED_TO_EXTRACT_1 1 # define L_GENERAL_PURPOSE_BIT_FLAG 2 # define L_COMPRESSION_METHOD 4 # define L_LAST_MOD_DOS_DATETIME 6 # define L_CRC32 10 # define L_COMPRESSED_SIZE 14 # define L_UNCOMPRESSED_SIZE 18 # define L_FILENAME_LENGTH 22 # define L_EXTRA_FIELD_LENGTH 24 typedef uch cdir_byte_hdr[ CREC_SIZE ]; # define C_VERSION_MADE_BY_0 0 # define C_VERSION_MADE_BY_1 1 # define C_VERSION_NEEDED_TO_EXTRACT_0 2 # define C_VERSION_NEEDED_TO_EXTRACT_1 3 # define C_GENERAL_PURPOSE_BIT_FLAG 4 # define C_COMPRESSION_METHOD 6 # define C_LAST_MOD_DOS_DATETIME 8 # define C_CRC32 12 # define C_COMPRESSED_SIZE 16 # define C_UNCOMPRESSED_SIZE 20 # define C_FILENAME_LENGTH 24 # define C_EXTRA_FIELD_LENGTH 26 # define C_FILE_COMMENT_LENGTH 28 # define C_DISK_NUMBER_START 30 # define C_INTERNAL_FILE_ATTRIBUTES 32 # define C_EXTERNAL_FILE_ATTRIBUTES 34 # define C_RELATIVE_OFFSET_LOCAL_HEADER 38 typedef uch ec_byte_rec[ ECREC_SIZE+4 ]; /* define SIGNATURE 0 space-holder only */ # define NUMBER_THIS_DISK 4 # define NUM_DISK_WITH_START_CEN_DIR 6 # define NUM_ENTRIES_CEN_DIR_THS_DISK 8 # define TOTAL_ENTRIES_CENTRAL_DIR 10 # define SIZE_CENTRAL_DIRECTORY 12 # define OFFSET_START_CENTRAL_DIRECTORY 16 # define ZIPFILE_COMMENT_LENGTH 20 typedef uch ec_byte_loc64[ ECLOC64_SIZE+4 ]; # define NUM_DISK_START_EOCDR64 4 # define OFFSET_START_EOCDR64 8 # define NUM_THIS_DISK_LOC64 16 typedef uch ec_byte_rec64[ ECREC64_SIZE+4 ]; # define ECREC64_LENGTH 4 # define EC_VERSION_MADE_BY_0 12 # define EC_VERSION_NEEDED_0 14 # define NUMBER_THIS_DSK_REC64 16 # define NUM_DISK_START_CEN_DIR64 20 # define NUM_ENTRIES_CEN_DIR_THS_DISK64 24 # define TOTAL_ENTRIES_CENTRAL_DIR64 32 # define SIZE_CENTRAL_DIRECTORY64 40 # define OFFSET_START_CENTRAL_DIRECT64 48 /* The following structs are used to hold all header data of a zip entry. Traditionally, the structs' layouts followed the data layout of the corresponding zipfile header structures. However, the zipfile header layouts were designed in the old ages of 16-bit CPUs, they are subject to structure padding and/or alignment issues on newer systems with a "natural word width" of more than 2 bytes. Please note that the structure members are now reordered by size (top-down), to prevent internal padding and optimize memory usage! */ typedef struct local_file_header { /* LOCAL */ zusz_t csize; zusz_t ucsize; ulg last_mod_dos_datetime; ulg crc32; uch version_needed_to_extract[2]; ush general_purpose_bit_flag; ush compression_method; ush filename_length; ush extra_field_length; } local_file_hdr; typedef struct central_directory_file_header { /* CENTRAL */ zusz_t csize; zusz_t ucsize; zusz_t relative_offset_local_header; ulg last_mod_dos_datetime; ulg crc32; ulg external_file_attributes; zuvl_t disk_number_start; ush internal_file_attributes; uch version_made_by[2]; uch version_needed_to_extract[2]; ush general_purpose_bit_flag; ush compression_method; ush filename_length; ush extra_field_length; ush file_comment_length; } cdir_file_hdr; typedef struct end_central_dir_record { /* END CENTRAL */ zusz_t size_central_directory; zusz_t offset_start_central_directory; zucn_t num_entries_centrl_dir_ths_disk; zucn_t total_entries_central_dir; zuvl_t number_this_disk; zuvl_t num_disk_start_cdir; int have_ecr64; /* valid Zip64 ecdir-record exists */ int is_zip64_archive; /* Zip64 ecdir-record is mandatory */ ush zipfile_comment_length; } ecdir_rec; /* Huffman code lookup table entry--this entry is four bytes for machines that have 16-bit pointers (e.g. PC's in the small or medium model). Valid extra bits are 0..16. e == 31 is EOB (end of block), e == 32 means that v is a literal, 32 < e < 64 means that v is a pointer to the next table, which codes (e & 31) bits, and lastly e == 99 indicates an unused code. If a code with e == 99 is looked up, this implies an error in the data. */ struct huft { uch e; /* number of extra bits or operation */ uch b; /* number of bits in this code or subcode */ union { ush n; /* literal, length base, or distance base */ struct huft *t; /* pointer to next level of table */ } v; }; typedef struct _APIDocStruct { char *compare; char *function; char *syntax; char *purpose; } APIDocStruct; /*************/ /* Globals */ /*************/ #if (defined(OS2) && !defined(FUNZIP)) # include "os2/os2data.h" #endif #include "globals.h" /*************************/ /* Function Prototypes */ /*************************/ /*--------------------------------------------------------------------------- Functions in unzip.c (initialization routines): ---------------------------------------------------------------------------*/ #ifndef WINDLL int MAIN OF((int argc, char **argv)); int unzip OF((__GPRO__ int argc, char **argv)); int uz_opts OF((__GPRO__ int *pargc, char ***pargv)); int usage OF((__GPRO__ int error)); #endif /* !WINDLL */ /*--------------------------------------------------------------------------- Functions in process.c (main driver routines): ---------------------------------------------------------------------------*/ int process_zipfiles OF((__GPRO)); void free_G_buffers OF((__GPRO)); /* static int do_seekable OF((__GPRO__ int lastchance)); */ /* static int find_ecrec OF((__GPRO__ long searchlen)); */ /* static int process_central_comment OF((__GPRO)); */ int process_cdir_file_hdr OF((__GPRO)); int process_local_file_hdr OF((__GPRO)); int getZip64Data OF((__GPRO__ ZCONST uch *ef_buf, unsigned ef_len)); #ifdef UNICODE_SUPPORT int getUnicodeData OF((__GPRO__ ZCONST uch *ef_buf, unsigned ef_len)); #endif unsigned ef_scan_for_izux OF((ZCONST uch *ef_buf, unsigned ef_len, int ef_is_c, ulg dos_mdatetime, iztimes *z_utim, ulg *z_uidgid)); #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS)) zvoid *getRISCOSexfield OF((ZCONST uch *ef_buf, unsigned ef_len)); #endif #ifndef SFX /*--------------------------------------------------------------------------- Functions in zipinfo.c (`zipinfo-style' listing routines): ---------------------------------------------------------------------------*/ #ifndef NO_ZIPINFO #ifndef WINDLL int zi_opts OF((__GPRO__ int *pargc, char ***pargv)); #endif void zi_end_central OF((__GPRO)); int zipinfo OF((__GPRO)); /* static int zi_long OF((__GPRO__ zusz_t *pEndprev)); */ /* static int zi_short OF((__GPRO)); */ /* static char *zi_time OF((__GPRO__ ZCONST ulg *datetimez, ZCONST time_t *modtimez, char *d_t_str));*/ #endif /* !NO_ZIPINFO */ /*--------------------------------------------------------------------------- Functions in list.c (generic zipfile-listing routines): ---------------------------------------------------------------------------*/ int list_files OF((__GPRO)); #ifdef TIMESTAMP int get_time_stamp OF((__GPRO__ time_t *last_modtime, ulg *nmember)); #endif int ratio OF((zusz_t uc, zusz_t c)); void fnprint OF((__GPRO)); #endif /* !SFX */ /*--------------------------------------------------------------------------- Functions in fileio.c: ---------------------------------------------------------------------------*/ int open_input_file OF((__GPRO)); int open_outfile OF((__GPRO)); /* also vms.c */ void undefer_input OF((__GPRO)); void defer_leftover_input OF((__GPRO)); unsigned readbuf OF((__GPRO__ char *buf, register unsigned len)); int readbyte OF((__GPRO)); int fillinbuf OF((__GPRO)); int seek_zipf OF((__GPRO__ zoff_t abs_offset)); #ifdef FUNZIP int flush OF((__GPRO__ ulg size)); /* actually funzip.c */ #else int flush OF((__GPRO__ uch *buf, ulg size, int unshrink)); #endif /* static int disk_error OF((__GPRO)); */ void handler OF((int signal)); time_t dos_to_unix_time OF((ulg dos_datetime)); int check_for_newer OF((__GPRO__ char *filename)); /* os2,vmcms,vms */ int do_string OF((__GPRO__ unsigned int length, int option)); ush makeword OF((ZCONST uch *b)); ulg makelong OF((ZCONST uch *sig)); zusz_t makeint64 OF((ZCONST uch *sig)); char *fzofft OF((__GPRO__ zoff_t val, ZCONST char *pre, ZCONST char *post)); #if (!defined(STR_TO_ISO) || defined(NEED_STR2ISO)) char *str2iso OF((char *dst, ZCONST char *src)); #endif #if (!defined(STR_TO_OEM) || defined(NEED_STR2OEM)) char *str2oem OF((char *dst, ZCONST char *src)); #endif #ifdef NO_STRNICMP int zstrnicmp OF((register ZCONST char *s1, register ZCONST char *s2, register unsigned n)); #endif #ifdef REGULUS int zstat OF((ZCONST char *p, struct stat *s)); #endif #ifdef ZMEM /* MUST be ifdef'd because of conflicts with the standard def. */ zvoid *memset OF((register zvoid *, register int, register unsigned int)); int memcmp OF((register ZCONST zvoid*, register ZCONST zvoid *, register unsigned int)); zvoid *memcpy OF((register zvoid *, register ZCONST zvoid *, register unsigned int)); #endif #ifdef NEED_UZMBCLEN extent uzmbclen OF((ZCONST unsigned char *ptr)); #endif #ifdef NEED_UZMBSCHR unsigned char *uzmbschr OF((ZCONST unsigned char *str, unsigned int c)); #endif #ifdef NEED_UZMBSRCHR unsigned char *uzmbsrchr OF((ZCONST unsigned char *str, unsigned int c)); #endif #ifdef SMALL_MEM char *fLoadFarString OF((__GPRO__ const char Far *sz)); char *fLoadFarStringSmall OF((__GPRO__ const char Far *sz)); char *fLoadFarStringSmall2 OF((__GPRO__ const char Far *sz)); #ifndef zfstrcpy char Far * Far zfstrcpy OF((char Far *s1, const char Far *s2)); #endif #if (!defined(SFX) && !defined(zfstrcmp)) int Far zfstrcmp OF((const char Far *s1, const char Far *s2)); #endif #endif /*--------------------------------------------------------------------------- Functions in extract.c: ---------------------------------------------------------------------------*/ int extract_or_test_files OF((__GPRO)); /* static int store_info OF((void)); */ /* static int extract_or_test_member OF((__GPRO)); */ /* static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len)); */ /* static int test_OS2 OF((__GPRO__ uch *eb, unsigned eb_size)); */ /* static int test_NT OF((__GPRO__ uch *eb, unsigned eb_size)); */ #ifndef SFX unsigned find_compr_idx OF((unsigned compr_methodnum)); #endif int memextract OF((__GPRO__ uch *tgt, ulg tgtsize, ZCONST uch *src, ulg srcsize)); int memflush OF((__GPRO__ ZCONST uch *rawbuf, ulg size)); #if (defined(VMS) || defined(VMS_TEXT_CONV)) uch *extract_izvms_block OF((__GPRO__ ZCONST uch *ebdata, unsigned size, unsigned *retlen, ZCONST uch *init, unsigned needlen)); #endif char *fnfilter OF((ZCONST char *raw, uch *space, extent size)); /*--------------------------------------------------------------------------- Decompression functions: ---------------------------------------------------------------------------*/ #if (!defined(SFX) && !defined(FUNZIP)) int explode OF((__GPRO)); /* explode.c */ #endif int huft_free OF((struct huft *t)); /* inflate.c */ int huft_build OF((__GPRO__ ZCONST unsigned *b, unsigned n, unsigned s, ZCONST ush *d, ZCONST uch *e, struct huft **t, unsigned *m)); #ifdef USE_ZLIB int UZinflate OF((__GPRO__ int is_defl64)); /* inflate.c */ # define inflate_free(x) inflateEnd(&((Uz_Globs *)(&G))->dstrm) #else int inflate OF((__GPRO__ int is_defl64)); /* inflate.c */ int inflate_free OF((__GPRO)); /* inflate.c */ #endif /* ?USE_ZLIB */ #if (!defined(SFX) && !defined(FUNZIP)) #ifndef COPYRIGHT_CLEAN int unreduce OF((__GPRO)); /* unreduce.c */ /* static void LoadFollowers OF((__GPRO__ f_array *follower, uch *Slen)); * unreduce.c */ #endif /* !COPYRIGHT_CLEAN */ #ifndef LZW_CLEAN int unshrink OF((__GPRO)); /* unshrink.c */ /* static void partial_clear OF((__GPRO)); * unshrink.c */ #endif /* !LZW_CLEAN */ #endif /* !SFX && !FUNZIP */ #ifdef USE_BZIP2 int UZbunzip2 OF((__GPRO)); /* extract.c */ void bz_internal_error OF((int bzerrcode)); /* ubz2err.c */ #endif /*--------------------------------------------------------------------------- Internal API functions (only included in DLL versions): ---------------------------------------------------------------------------*/ #ifdef DLL void setFileNotFound OF((__GPRO)); /* api.c */ int unzipToMemory OF((__GPRO__ char *zip, char *file, UzpBuffer *retstr)); /* api.c */ int redirect_outfile OF((__GPRO)); /* api.c */ int writeToMemory OF((__GPRO__ ZCONST uch *rawbuf, extent size)); /* api.c */ int close_redirect OF((__GPRO)); /* api.c */ /* this obsolescent entry point kept for compatibility: */ int UzpUnzip OF((int argc, char **argv));/* use UzpMain */ #ifdef OS2DLL int varmessage OF((__GPRO__ ZCONST uch *buf, ulg size)); int varputchar OF((__GPRO__ int c)); /* rexxapi.c */ int finish_REXX_redirect OF((__GPRO)); /* rexxapi.c */ #endif #ifdef API_DOC void APIhelp OF((__GPRO__ int argc, char **argv)); #endif /* apihelp.c */ #endif /* DLL */ /*--------------------------------------------------------------------------- MSDOS-only functions: ---------------------------------------------------------------------------*/ #ifdef MSDOS #if (!defined(FUNZIP) && !defined(SFX) && !defined(WINDLL)) void check_for_windows OF((ZCONST char *app)); /* msdos.c */ #endif #if (defined(__GO32__) || defined(__EMX__)) unsigned _dos_getcountryinfo(void *); /* msdos.c */ #if (!defined(__DJGPP__) || (__DJGPP__ < 2)) unsigned _dos_setftime(int, unsigned, unsigned); /* msdos.c */ unsigned _dos_setfileattr(const char *, unsigned); /* msdos.c */ unsigned _dos_creat(const char *, unsigned, int *); /* msdos.c */ void _dos_getdrive(unsigned *); /* msdos.c */ unsigned _dos_close(int); /* msdos.c */ #endif /* !__DJGPP__ || (__DJGPP__ < 2) */ #endif /* __GO32__ || __EMX__ */ #endif /*--------------------------------------------------------------------------- OS/2-only functions: ---------------------------------------------------------------------------*/ #ifdef OS2 /* GetFileTime conflicts with something in Win32 header files */ #if (defined(REENTRANT) && defined(USETHREADID)) ulg GetThreadId OF((void)); #endif int GetCountryInfo OF((void)); /* os2.c */ long GetFileTime OF((ZCONST char *name)); /* os2.c */ /* static void SetPathAttrTimes OF((__GPRO__ int flags, int dir)); os2.c */ /* static int SetEAs OF((__GPRO__ const char *path, void *eablock)); os2.c */ /* static int SetACL OF((__GPRO__ const char *path, void *eablock)); os2.c */ /* static int IsFileNameValid OF((const char *name)); os2.c */ /* static void map2fat OF((char *pathcomp, char **pEndFAT)); os2.c */ /* static int SetLongNameEA OF((char *name, char *longname)); os2.c */ /* static void InitNLS OF((void)); os2.c */ int IsUpperNLS OF((int nChr)); /* os2.c */ int ToLowerNLS OF((int nChr)); /* os2.c */ void DebugMalloc OF((void)); /* os2.c */ #endif /*--------------------------------------------------------------------------- QDOS-only functions: ---------------------------------------------------------------------------*/ #ifdef QDOS int QMatch (uch, uch); void QFilename (__GPRO__ char *); char *Qstrfix (char *); int QReturn (int zip_error); #endif /*--------------------------------------------------------------------------- TOPS20-only functions: ---------------------------------------------------------------------------*/ #ifdef TOPS20 int upper OF((char *s)); /* tops20.c */ int enquote OF((char *s)); /* tops20.c */ int dequote OF((char *s)); /* tops20.c */ int fnlegal OF(()); /* error if prototyped? */ /* tops20.c */ #endif /*--------------------------------------------------------------------------- VM/CMS- and MVS-only functions: ---------------------------------------------------------------------------*/ #ifdef CMS_MVS extent getVMMVSexfield OF((char *type, uch *ef_block, unsigned datalen)); FILE *vmmvs_open_infile OF((__GPRO)); /* vmmvs.c */ void close_infile OF((__GPRO)); /* vmmvs.c */ #endif /*--------------------------------------------------------------------------- VMS-only functions: ---------------------------------------------------------------------------*/ #ifdef VMS int check_format OF((__GPRO)); /* vms.c */ /* int open_outfile OF((__GPRO)); * (see fileio.c) vms.c */ /* int flush OF((__GPRO__ uch *rawbuf, unsigned size, int final_flag)); * (see fileio.c) vms.c */ char *vms_msg_text OF((void)); /* vms.c */ #ifdef RETURN_CODES void return_VMS OF((__GPRO__ int zip_error)); /* vms.c */ #else void return_VMS OF((int zip_error)); /* vms.c */ #endif #ifdef VMSCLI ulg vms_unzip_cmdline OF((int *, char ***)); /* cmdline.c */ int VMSCLI_usage OF((__GPRO__ int error)); /* cmdline.c */ #endif #endif /*--------------------------------------------------------------------------- WIN32-only functions: ---------------------------------------------------------------------------*/ #ifdef WIN32 int IsWinNT OF((void)); /* win32.c */ #ifdef NTSD_EAS void process_defer_NT OF((__GPRO)); /* win32.c */ int test_NTSD OF((__GPRO__ uch *eb, unsigned eb_size, uch *eb_ucptr, ulg eb_ucsize)); /* win32.c */ # define TEST_NTSD test_NTSD #endif #ifdef W32_STAT_BANDAID int zstat_win32 OF((__W32STAT_GLOBALS__ const char *path, z_stat *buf)); /* win32.c */ #endif #endif /*--------------------------------------------------------------------------- Miscellaneous/shared functions: ---------------------------------------------------------------------------*/ Uz_Globs *globalsCtor OF((void)); /* globals.c */ int envargs OF((int *Pargc, char ***Pargv, ZCONST char *envstr, ZCONST char *envstr2)); /* envargs.c */ void mksargs OF((int *argcp, char ***argvp)); /* envargs.c */ int match OF((ZCONST char *s, ZCONST char *p, int ic __WDLPRO)); /* match.c */ int iswild OF((ZCONST char *p)); /* match.c */ /* declarations of public CRC-32 functions have been moved into crc32.h (free_crc_table(), get_crc_table(), crc32()) crc32.c */ int dateformat OF((void)); /* local */ char dateseparator OF((void)); /* local */ #ifndef WINDLL void version OF((__GPRO)); /* local */ #endif int mapattr OF((__GPRO)); /* local */ int mapname OF((__GPRO__ int renamed)); /* local */ int checkdir OF((__GPRO__ char *pathcomp, int flag)); /* local */ char *do_wild OF((__GPRO__ ZCONST char *wildzipfn)); /* local */ char *GetLoadPath OF((__GPRO)); /* local */ #if (defined(MORE) && (defined(ATH_BEO_UNX) || defined(QDOS) || defined(VMS))) int screensize OF((int *tt_rows, int *tt_cols)); /* local */ # if defined(VMS) int screenlinewrap OF((void)); /* local */ # endif #endif /* MORE && (ATH_BEO_UNX || QDOS || VMS) */ #ifdef OS2_W32 int SetFileSize OF((FILE *file, zusz_t filesize)); /* local */ #endif #ifndef MTS /* macro in MTS */ void close_outfile OF((__GPRO)); /* local */ #endif #ifdef SET_SYMLINK_ATTRIBS int set_symlnk_attribs OF((__GPRO__ slinkentry *slnk_entry)); /* local */ #endif #ifdef SET_DIR_ATTRIB int defer_dir_attribs OF((__GPRO__ direntry **pd)); /* local */ int set_direc_attribs OF((__GPRO__ direntry *d)); /* local */ #endif #ifdef TIMESTAMP # ifdef WIN32 int stamp_file OF((__GPRO__ ZCONST char *fname, time_t modtime)); /* local */ # else int stamp_file OF((ZCONST char *fname, time_t modtime)); /* local */ # endif #endif #ifdef NEED_ISO_OEM_INIT void prepare_ISO_OEM_translat OF((__GPRO)); /* local */ #endif #if (defined(MALLOC_WORK) && defined(MY_ZCALLOC)) zvoid far *zcalloc OF((unsigned int, unsigned int)); zvoid zcfree OF((zvoid far *)); #endif /* MALLOC_WORK && MY_ZCALLOC */ #ifdef SYSTEM_SPECIFIC_CTOR void SYSTEM_SPECIFIC_CTOR OF((__GPRO)); /* local */ #endif #ifdef SYSTEM_SPECIFIC_DTOR void SYSTEM_SPECIFIC_DTOR OF((__GPRO)); /* local */ #endif /************/ /* Macros */ /************/ #ifndef MAX # define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif #ifndef MIN # define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif #ifdef DEBUG # if (defined(THEOS) && defined(NO_BOGUS_SPC)) # define NO_DEBUG_IN_MACROS # define Trace(x) _fprintf x # else # define Trace(x) fprintf x # endif #else # define Trace(x) #endif #ifdef DEBUG_TIME # define TTrace(x) fprintf x #else # define TTrace(x) #endif #ifdef NO_DEBUG_IN_MACROS # define MTrace(x) #else # define MTrace(x) Trace(x) #endif #if (defined(UNIX) || defined(T20_VMS)) /* generally old systems */ # define ToLower(x) ((char)(isupper((int)x)? tolower((int)x) : x)) #else # define ToLower tolower /* assumed "smart"; used in match() */ #endif #ifdef USE_STRM_INPUT /* ``Replace'' the unbuffered UNIX style I/O function with similar * standard C functions from . */ # define read(fd,buf,n) fread((buf),1,(n),(FILE *)(fd)) # ifdef zlseek # undef zlseek # endif # define zlseek(fd,o,w) zfseeko((FILE *)(fd),(o),(w)) # define close(fd) fclose((FILE *)(fd)) #endif /* USE_STRM_INPUT */ /* The return value of the Info() "macro function" is never checked in * UnZip. Otherwise, to get the same behaviour as for (*G.message)(), the * Info() definition for "FUNZIP" would have to be corrected: * #define Info(buf,flag,sprf_arg) \ * (fputs((char *)(sprintf sprf_arg, (buf)), \ * (flag)&1? stderr : stdout) < 0) */ static inline void noop(void) {} #define Info(...) noop() #ifndef Info /* may already have been defined for redirection */ # ifdef FUNZIP # define Info(buf,flag,sprf_arg) \ fputs((char *)(sprintf sprf_arg, (buf)), (flag)&1? stderr : stdout) # else # ifdef INT_SPRINTF /* optimized version for "int sprintf()" flavour */ # define Info(buf,flag,sprf_arg) \ (*G.message)((zvoid *)&G, (uch *)(buf), (ulg)sprintf sprf_arg, (flag)) # else /* generic version, does not use sprintf() return value */ # define Info(buf,flag,sprf_arg) \ (*G.message)((zvoid *)&G, (uch *)(buf), \ (ulg)(sprintf sprf_arg, strlen((char *)(buf))), (flag)) # endif # endif #endif /* !Info */ /* This wrapper macro around fzofft() is just defined to "hide" the * argument needed to reference the global storage buffers. */ #define FmZofft(val, pre, post) fzofft(__G__ val, pre, post) /* The following macro wrappers around the fnfilter function are used many * times to prepare archive entry names or name components for displaying * listings and (warning/error) messages. They use sections in the upper half * of 'slide' as buffer, since their output is normally fed through the * Info() macro with 'slide' (the start of this area) as message buffer. */ #define FnFilter1(fname) \ fnfilter((fname), slide + (extent)(WSIZE>>1), (extent)(WSIZE>>2)) #define FnFilter2(fname) \ fnfilter((fname), slide + (extent)((WSIZE>>1) + (WSIZE>>2)),\ (extent)(WSIZE>>2)) #ifndef FUNZIP /* used only in inflate.c */ # define MESSAGE(str,len,flag) (*G.message)((zvoid *)&G,(str),(len),(flag)) #endif #if 0 /* Optimization: use the (const) result of crc32(0L,NULL,0) */ # define CRCVAL_INITIAL crc32(0L, NULL, 0) #else # define CRCVAL_INITIAL 0L #endif #ifdef SYMLINKS /* This macro defines the Zip "made by" hosts that are considered to support storing symbolic link entries. */ # define SYMLINK_HOST(hn) ((hn) == UNIX_ || (hn) == ATARI_ || \ (hn) == ATHEOS_ || (hn) == BEOS_ || (hn) == VMS_) #endif #ifndef TEST_NTSD /* "NTSD valid?" checking function */ # define TEST_NTSD NULL /* ... is not available */ #endif #define SKIP_(length) if(length&&((error=do_string(__G__ length,SKIP))!=0))\ {error_in_archive=error; if(error>1) return error;} /* * Skip a variable-length field, and report any errors. Used in zipinfo.c * and unzip.c in several functions. * * macro SKIP_(length) * ush length; * { * if (length && ((error = do_string(length, SKIP)) != 0)) { * error_in_archive = error; /-* might be warning *-/ * if (error > 1) /-* fatal *-/ * return (error); * } * } * */ #ifdef FUNZIP # define FLUSH(w) flush(__G__ (ulg)(w)) # define NEXTBYTE getc(G.in) /* redefined in crypt.h if full version */ #else # define FLUSH(w) ((G.mem_mode) ? memflush(__G__ redirSlide,(ulg)(w)) \ : flush(__G__ redirSlide,(ulg)(w),0)) # define NEXTBYTE (G.incnt-- > 0 ? (int)(*G.inptr++) : readbyte(__G)) #endif #define READBITS(nbits,zdest) {if(nbits>G.bits_left) {int temp; G.zipeof=1;\ while (G.bits_left<=8*(int)(sizeof(G.bitbuf)-1) && (temp=NEXTBYTE)!=EOF) {\ G.bitbuf|=(ulg)temp<>=nbits;\ G.bits_left-=nbits;} /* * macro READBITS(nbits,zdest) * only used by unreduce and unshrink * * { * if (nbits > G.bits_left) { * fill G.bitbuf, 8*sizeof(ulg) bits * * int temp; * * G.zipeof = 1; * while (G.bits_left <= 8*(int)(sizeof(G.bitbuf)-1) && * (temp = NEXTBYTE) != EOF) { * G.bitbuf |= (ulg)temp << G.bits_left; * G.bits_left += 8; * G.zipeof = 0; * } * } * zdest = (shrint)((unsigned)G.bitbuf & mask_bits[nbits]); * G.bitbuf >>= nbits; * G.bits_left -= nbits; * } * */ /* GRR: should use StringLower for STRLOWER macro if possible */ /* * Copy the zero-terminated string in str1 into str2, converting any * uppercase letters to lowercase as we go. str2 gets zero-terminated * as well, of course. str1 and str2 may be the same character array. */ #ifdef _MBCS # define STRLOWER(str1, str2) \ { \ char *p, *q, c; unsigned i; \ p = (char *)(str1); \ q = (char *)(str2); \ while ((c = *p) != '\0') { \ if ((i = CLEN(p)) > 1) { \ while (i--) *q++ = *p++; \ } else { \ *q++ = (char)(isupper((int)(c))? tolower((int)(c)) : c); \ p++; \ } \ } \ *q = '\0'; \ } #else # define STRLOWER(str1, str2) \ { \ char *p, *q; \ p = (char *)(str1) - 1; \ q = (char *)(str2); \ while (*++p) \ *q++ = (char)(isupper((int)(*p))? tolower((int)(*p)) : *p); \ *q = '\0'; \ } #endif /* * NOTES: This macro makes no assumptions about the characteristics of * the tolower() function or macro (beyond its existence), nor does it * make assumptions about the structure of the character set (i.e., it * should work on EBCDIC machines, too). The fact that either or both * of isupper() and tolower() may be macros has been taken into account; * watch out for "side effects" (in the C sense) when modifying this * macro. */ #ifndef foreign # define foreign(c) (c) #endif #ifndef native # define native(c) (c) # define A_TO_N(str1) #else # ifndef NATIVE # define NATIVE "native chars" # endif # define A_TO_N(str1) {register uch *p;\ for (p=(uch *)(str1); *p; p++) *p=native(*p);} #endif /* * Translate the zero-terminated string in str1 from ASCII to the native * character set. The translation is performed in-place and uses the * "native" macro to translate each character. * * NOTE: Using the "native" macro means that is it the only part of unzip * which knows which translation table (if any) is actually in use to * produce the native character set. This makes adding new character set * translation tables easy, insofar as all that is needed is an appropriate * "native" macro definition and the translation table itself. Currently, * the only non-ASCII native character set implemented is EBCDIC, but this * may not always be so. */ /* default setup for internal codepage: assume ISO 8859-1 compatibility!! */ #if (!defined(NATIVE) && !defined(CRTL_CP_IS_ISO) && !defined(CRTL_CP_IS_OEM)) # define CRTL_CP_IS_ISO #endif /* Translate "extended ASCII" chars (OEM coding for DOS and OS/2; else * ISO-8859-1 [ISO Latin 1, Win Ansi,...]) into the internal "native" * code page. As with A_TO_N(), conversion is done in place. */ #ifndef _ISO_INTERN # ifdef CRTL_CP_IS_OEM # ifndef IZ_ISO2OEM_ARRAY # define IZ_ISO2OEM_ARRAY # endif # define _ISO_INTERN(str1) if (iso2oem) {register uch *p;\ for (p=(uch *)(str1); *p; p++)\ *p = native((*p & 0x80) ? iso2oem[*p & 0x7f] : *p);} # else # define _ISO_INTERN(str1) A_TO_N(str1) # endif #endif #ifndef _OEM_INTERN # ifdef CRTL_CP_IS_OEM # define _OEM_INTERN(str1) A_TO_N(str1) # else # ifndef IZ_OEM2ISO_ARRAY # define IZ_OEM2ISO_ARRAY # endif # define _OEM_INTERN(str1) if (oem2iso) {register uch *p;\ for (p=(uch *)(str1); *p; p++)\ *p = native((*p & 0x80) ? oem2iso[*p & 0x7f] : *p);} # endif #endif #ifndef STR_TO_ISO # ifdef CRTL_CP_IS_ISO # define STR_TO_ISO strcpy # else # define STR_TO_ISO str2iso # define NEED_STR2ISO # endif #endif #ifndef STR_TO_OEM # ifdef CRTL_CP_IS_OEM # define STR_TO_OEM strcpy # else # define STR_TO_OEM str2oem # define NEED_STR2OEM # endif #endif #if (!defined(INTERN_TO_ISO) && !defined(ASCII2ISO)) # ifdef CRTL_CP_IS_OEM /* know: "ASCII" is "OEM" */ # define ASCII2ISO(c) \ ((((c) & 0x80) && oem2iso) ? oem2iso[(c) & 0x7f] : (c)) # if (defined(NEED_STR2ISO) && !defined(CRYP_USES_OEM2ISO)) # define CRYP_USES_OEM2ISO # endif # else /* assume: "ASCII" is "ISO-ANSI" */ # define ASCII2ISO(c) (c) # endif #endif #if (!defined(INTERN_TO_OEM) && !defined(ASCII2OEM)) # ifdef CRTL_CP_IS_OEM /* know: "ASCII" is "OEM" */ # define ASCII2OEM(c) (c) # else /* assume: "ASCII" is "ISO-ANSI" */ # define ASCII2OEM(c) \ ((((c) & 0x80) && iso2oem) ? iso2oem[(c) & 0x7f] : (c)) # if (defined(NEED_STR2OEM) && !defined(CRYP_USES_ISO2OEM)) # define CRYP_USES_ISO2OEM # endif # endif #endif /* codepage conversion setup for testp() in crypt.c */ #ifdef CRTL_CP_IS_ISO # ifndef STR_TO_CP2 # define STR_TO_CP2 STR_TO_OEM # endif #else # ifdef CRTL_CP_IS_OEM # ifndef STR_TO_CP2 # define STR_TO_CP2 STR_TO_ISO # endif # else /* native internal CP is neither ISO nor OEM */ # ifndef STR_TO_CP1 # define STR_TO_CP1 STR_TO_ISO # endif # ifndef STR_TO_CP2 # define STR_TO_CP2 STR_TO_OEM # endif # endif #endif /* Convert filename (and file comment string) into "internal" charset. * This macro assumes that Zip entry filenames are coded in OEM (IBM DOS) * codepage when made on * -> DOS (this includes 16-bit Windows 3.1) (FS_FAT_) * -> OS/2 (FS_HPFS_) * -> Win95/WinNT with Nico Mak's WinZip (FS_NTFS_ && hostver == "5.0") * EXCEPTIONS: * PKZIP for Windows 2.5, 2.6, and 4.0 flag their entries as "FS_FAT_", but * the filename stored in the local header is coded in Windows ANSI (CP 1252 * resp. ISO 8859-1 on US and western Europe locale settings). * Likewise, PKZIP for UNIX 2.51 flags its entries as "FS_FAT_", but the * filenames stored in BOTH the local and the central header are coded * in the local system's codepage (usually ANSI codings like ISO 8859-1). * * All other ports are assumed to code zip entry filenames in ISO 8859-1. */ #ifndef Ext_ASCII_TO_Native # define Ext_ASCII_TO_Native(string, hostnum, hostver, isuxatt, islochdr) \ if (((hostnum) == FS_FAT_ && \ !(((islochdr) || (isuxatt)) && \ ((hostver) == 25 || (hostver) == 26 || (hostver) == 40))) || \ (hostnum) == FS_HPFS_ || \ ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \ _OEM_INTERN((string)); \ } else { \ _ISO_INTERN((string)); \ } #endif /**********************/ /* Global constants */ /**********************/ extern ZCONST unsigned near mask_bits[17]; extern ZCONST char *fnames[2]; #ifdef EBCDIC extern ZCONST uch ebcdic[]; #endif #ifdef IZ_ISO2OEM_ARRAY extern ZCONST uch Far *iso2oem; extern ZCONST uch Far iso2oem_850[]; #endif #ifdef IZ_OEM2ISO_ARRAY extern ZCONST uch Far *oem2iso; extern ZCONST uch Far oem2iso_850[]; #endif extern ZCONST char Far VersionDate[]; extern ZCONST char Far CentSigMsg[]; #ifndef SFX extern ZCONST char Far EndSigMsg[]; #endif extern ZCONST char Far SeekMsg[]; extern ZCONST char Far FilenameNotMatched[]; extern ZCONST char Far ExclFilenameNotMatched[]; extern ZCONST char Far ReportMsg[]; #ifndef SFX extern ZCONST char Far Zipnfo[]; extern ZCONST char Far CompiledWith[]; #endif /* !SFX */ /***********************************/ /* Global (shared?) RTL variables */ /***********************************/ #ifdef DECLARE_ERRNO extern int errno; #endif /*--------------------------------------------------------------------- Unicode Support 28 August 2005 ---------------------------------------------------------------------*/ #if (defined(UNICODE_SUPPORT) && defined(UNICODE_WCHAR)) /* Default character when a zwchar too big for wchar_t */ # define zwchar_to_wchar_t_default_char '_' /* Default character string when wchar_t does not convert to mb */ # define wide_to_mb_default_string "_" /* wide character type */ typedef unsigned long zwchar; /* UTF-8 related conversion functions, currently found in process.c */ # if 0 /* currently unused */ /* check if string is all ASCII */ int is_ascii_string OF((ZCONST char *mbstring)); # endif /* unused */ /* convert UTF-8 string to multi-byte string */ char *utf8_to_local_string OF((ZCONST char *utf8_string, int escape_all)); /* convert UTF-8 string to wide string */ zwchar *utf8_to_wide_string OF((ZCONST char *utf8_string)); /* convert wide string to multi-byte string */ char *wide_to_local_string OF((ZCONST zwchar *wide_string, int escape_all)); # if 0 /* currently unused */ /* convert local string to multi-byte display string */ char *local_to_display_string OF((ZCONST char *local_string)); # endif /* unused */ /* convert wide character to escape string */ char *wide_to_escape_string OF((unsigned long)); # define utf8_to_escaped_string(utf8_string) \ utf8_to_local_string(utf8_string, TRUE) # if 0 /* currently unused */ /* convert escape string to wide character */ unsigned long escape_string_to_wide OF((ZCONST char *escape_string)); /* convert local to UTF-8 */ char *local_to_utf8_string OF ((ZCONST char *local_string)); /* convert local to wide string */ zwchar *local_to_wide_string OF ((ZCONST char *local_string)); /* convert wide string to UTF-8 */ char *wide_to_utf8_string OF((ZCONST zwchar *wide_string)); # endif /* unused */ #endif /* UNICODE_SUPPORT && UNICODE_WCHAR */ #endif /* !__unzpriv_h */ Carla-2.1/data/windows/unzipfx-carla-control/unzvers.h000066400000000000000000000060411364475620200231410ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* unzvers.h (for UnZip) by Info-ZIP. */ #ifndef __unzvers_h /* don't include more than once */ #define __unzvers_h #ifdef BETA # undef BETA /* undefine BETA for public releases */ #endif #ifdef BETA # define UZ_BETALEVEL "h03 BETA" # define UZ_VERSION_DATE "17 Apr 09" /* internal beta version */ #else # define UZ_BETALEVEL "" # define UZ_VERSION_DATE "20 April 2009" /* official release version */ # define RELEASE #endif #define UZ_MAJORVER 6 /* UnZip */ #define UZ_MINORVER 0 #define ZI_MAJORVER 3 /* ZipInfo */ #define ZI_MINORVER 0 #define UZ_PATCHLEVEL 0 #define UZ_VER_STRING "6.0" /* keep in sync with Version numbers! */ #ifndef IZ_COMPANY_NAME /* might be already defined... */ # define IZ_COMPANY_NAME "Info-ZIP" #endif /* these are obsolete but remain for backward compatibility: */ #if (defined(OS2) || defined(__OS2__)) # define D2_MAJORVER UZ_MAJORVER /* DLL for OS/2 */ # define D2_MINORVER UZ_MINORVER # define D2_PATCHLEVEL UZ_PATCHLEVEL #endif #define DW_MAJORVER UZ_MAJORVER /* DLL for MS Windows */ #define DW_MINORVER UZ_MINORVER #define DW_PATCHLEVEL UZ_PATCHLEVEL #define WIN_VERSION_DATE UZ_VERSION_DATE #define UNZ_DLL_VERSION UZ_VER_STRING /* The following version constants specify the UnZip version that introduced * the most recent incompatible change (means: change that breaks backward * compatibility) of a DLL/Library binary API definition. * * Currently, UnZip supports three distinct DLL/Library APIs, which each * carry their own "compatibility level": * a) The "generic" (console-mode oriented) API has been used on UNIX, * for example. This API provides a "callable" interface similar to the * interactive command line of the normal program executables. * b) The OS/2-only API provides (additional) functions specially tailored * for interfacing with the REXX shell. * c) The Win32 DLL API with a pure binary interface which can be used to * build GUI mode as well as Console mode applications. * * Whenever a change that breaks backward compatibility gets applied to * any of the DLL/Library APIs, the corresponding compatibility level should * be synchronized with the current UnZip version numbers. */ /* generic DLL API minimum compatible version*/ #define UZ_GENAPI_COMP_MAJOR 6 #define UZ_GENAPI_COMP_MINOR 0 #define UZ_GENAPI_COMP_REVIS 0 /* os2dll API minimum compatible version*/ #define UZ_OS2API_COMP_MAJOR 6 #define UZ_OS2API_COMP_MINOR 0 #define UZ_OS2API_COMP_REVIS 0 /* windll API minimum compatible version*/ #define UZ_WINAPI_COMP_MAJOR 6 #define UZ_WINAPI_COMP_MINOR 0 #define UZ_WINAPI_COMP_REVIS 0 #endif /* !__unzvers_h */ Carla-2.1/data/windows/unzipfx-carla-control/win32/000077500000000000000000000000001364475620200222155ustar00rootroot00000000000000Carla-2.1/data/windows/unzipfx-carla-control/win32/nt.c000066400000000000000000000405051364475620200230060ustar00rootroot00000000000000/* Copyright (c) 1990-2007 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* Copyright (c) 1996 Scott Field (dedicated to Info-Zip group) Module Name: nt.c Abstract: This module implements WinNT security descriptor operations for the Win32 Info-ZIP project. Operation such as setting file security, using/querying local and remote privileges, and queuing of operations is performed here. The contents of this module are only relevant when the code is running on Windows NT, and the target volume supports persistent Acl storage. User privileges that allow accessing certain privileged aspects of the security descriptor (such as the Sacl) are only used if the user specified to do so. Author: Scott Field (sfield@microsoft.com) Last revised: 18 Jan 97 */ #define WIN32_LEAN_AND_MEAN #define UNZIP_INTERNAL #include #include "../unzip.h" #ifdef __RSXNT__ # include "../win32/rsxntwin.h" #endif #include "../win32/nt.h" #ifdef NTSD_EAS /* This file is only needed for NTSD handling */ /* Borland C++ does not define FILE_SHARE_DELETE. Others also? */ #ifndef FILE_SHARE_DELETE # define FILE_SHARE_DELETE 0x00000004 #endif /* This macro definition is missing in old versions of MS' winbase.h. */ #ifndef InterlockedExchangePointer # define InterlockedExchangePointer(Target, Value) \ (PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value)) #endif /* private prototypes */ static BOOL Initialize(VOID); static VOID GetRemotePrivilegesSet(CHAR *FileName, PDWORD dwRemotePrivileges); static VOID InitLocalPrivileges(VOID); volatile BOOL bInitialized = FALSE; /* module level stuff initialized? */ HANDLE hInitMutex = NULL; /* prevent multiple initialization */ BOOL g_bRestorePrivilege = FALSE; /* for local set file security override */ BOOL g_bSaclPrivilege = FALSE; /* for local set sacl operations, only when restore privilege not present */ /* our single cached volume capabilities structure that describes the last volume root we encountered. A single entry like this works well in the zip/unzip scenario for a number of reasons: 1. typically one extraction path during unzip. 2. typically process one volume at a time during zip, and then move on to the next. 3. no cleanup code required and no memory leaks. 4. simple code. This approach should be reworked to a linked list approach if we expect to be called by many threads which are processing a variety of input/output volumes, since lock contention and stale data may become a bottleneck. */ VOLUMECAPS g_VolumeCaps; CRITICAL_SECTION VolumeCapsLock; static BOOL Initialize(VOID) { HANDLE hMutex; HANDLE hOldMutex; if (bInitialized) return TRUE; hMutex = CreateMutex(NULL, TRUE, NULL); if(hMutex == NULL) return FALSE; hOldMutex = (HANDLE)InterlockedExchangePointer((void *)&hInitMutex, hMutex); if (hOldMutex != NULL) { /* somebody setup the mutex already */ InterlockedExchangePointer((void *)&hInitMutex, hOldMutex); CloseHandle(hMutex); /* close new, un-needed mutex */ /* wait for initialization to complete and return status */ WaitForSingleObject(hOldMutex, INFINITE); ReleaseMutex(hOldMutex); return bInitialized; } if (!bInitialized) { /* initialize module level resources */ InitializeCriticalSection( &VolumeCapsLock ); memset(&g_VolumeCaps, 0, sizeof(VOLUMECAPS)); InitLocalPrivileges(); bInitialized = TRUE; } InterlockedExchangePointer((void *)&hInitMutex, NULL); ReleaseMutex(hMutex); /* release correct mutex */ CloseHandle(hMutex); /* free the no longer needed handle resource */ return TRUE; } BOOL ValidateSecurity(uch *securitydata) { PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata; PACL pAcl; PSID pSid; BOOL bAclPresent; BOOL bDefaulted; if(!IsWinNT()) return TRUE; /* don't do anything if not on WinNT */ if(!IsValidSecurityDescriptor(sd)) return FALSE; /* verify Dacl integrity */ if(!GetSecurityDescriptorDacl(sd, &bAclPresent, &pAcl, &bDefaulted)) return FALSE; if(bAclPresent && pAcl!=NULL) { if(!IsValidAcl(pAcl)) return FALSE; } /* verify Sacl integrity */ if(!GetSecurityDescriptorSacl(sd, &bAclPresent, &pAcl, &bDefaulted)) return FALSE; if(bAclPresent && pAcl!=NULL) { if(!IsValidAcl(pAcl)) return FALSE; } /* verify owner integrity */ if(!GetSecurityDescriptorOwner(sd, &pSid, &bDefaulted)) return FALSE; if(pSid != NULL) { if(!IsValidSid(pSid)) return FALSE; } /* verify group integrity */ if(!GetSecurityDescriptorGroup(sd, &pSid, &bDefaulted)) return FALSE; if(pSid != NULL) { if(!IsValidSid(pSid)) return FALSE; } return TRUE; } static VOID GetRemotePrivilegesSet(char *FileName, PDWORD dwRemotePrivileges) { HANDLE hFile; *dwRemotePrivileges = 0; /* see if we have the SeRestorePrivilege */ hFile = CreateFileA( FileName, ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER | READ_CONTROL, FILE_SHARE_READ | FILE_SHARE_DELETE, /* no sd updating allowed here */ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL ); if(hFile != INVALID_HANDLE_VALUE) { /* no remote way to determine SeRestorePrivilege -- just try a read/write to simulate it */ SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION; PSECURITY_DESCRIPTOR sd; DWORD cbBuf = 0; GetKernelObjectSecurity(hFile, si, NULL, cbBuf, &cbBuf); if(ERROR_INSUFFICIENT_BUFFER == GetLastError()) { if((sd = HeapAlloc(GetProcessHeap(), 0, cbBuf)) != NULL) { if(GetKernelObjectSecurity(hFile, si, sd, cbBuf, &cbBuf)) { if(SetKernelObjectSecurity(hFile, si, sd)) *dwRemotePrivileges |= OVERRIDE_RESTORE; } HeapFree(GetProcessHeap(), 0, sd); } } CloseHandle(hFile); } else { /* see if we have the SeSecurityPrivilege */ /* note we don't need this if we have SeRestorePrivilege */ hFile = CreateFileA( FileName, ACCESS_SYSTEM_SECURITY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* max */ NULL, OPEN_EXISTING, 0, NULL ); if(hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); *dwRemotePrivileges |= OVERRIDE_SACL; } } } BOOL GetVolumeCaps( char *rootpath, /* filepath, or NULL */ char *name, /* filename associated with rootpath */ PVOLUMECAPS VolumeCaps /* result structure describing capabilities */ ) { char TempRootPath[MAX_PATH + 1]; DWORD cchTempRootPath = 0; BOOL bSuccess = TRUE; /* assume success until told otherwise */ if(!bInitialized) if(!Initialize()) return FALSE; /* process the input path to produce a consistent path suitable for compare operations and also suitable for certain picky Win32 API that don't like forward slashes */ if(rootpath != NULL && rootpath[0] != '\0') { DWORD i; cchTempRootPath = lstrlenA(rootpath); if(cchTempRootPath > MAX_PATH) return FALSE; /* copy input, converting forward slashes to back slashes as we go */ for(i = 0 ; i <= cchTempRootPath ; i++) { if(rootpath[i] == '/') TempRootPath[i] = '\\'; else TempRootPath[i] = rootpath[i]; } /* check for UNC and Null terminate or append trailing \ as appropriate */ /* possible valid UNCs we are passed follow: \\machine\foo\bar (path is \\machine\foo\) \\machine\foo (path is \\machine\foo\) \\machine\foo\ \\.\c$\ (FIXFIX: Win32API doesn't like this - GetComputerName()) LATERLATER: handling mounted DFS drives in the future will require slightly different logic which isn't available today. This is required because directories can point at different servers which have differing capabilities. */ if(TempRootPath[0] == '\\' && TempRootPath[1] == '\\') { DWORD slash = 0; for(i = 2 ; i < cchTempRootPath ; i++) { if(TempRootPath[i] == '\\') { slash++; if(slash == 2) { i++; TempRootPath[i] = '\0'; cchTempRootPath = i; break; } } } /* if there was only one slash found, just tack another onto the end */ if(slash == 1 && TempRootPath[cchTempRootPath] != '\\') { TempRootPath[cchTempRootPath] = TempRootPath[0]; /* '\\' */ TempRootPath[cchTempRootPath+1] = '\0'; cchTempRootPath++; } } else { if(TempRootPath[1] == ':') { /* drive letter specified, truncate to root */ TempRootPath[2] = '\\'; TempRootPath[3] = '\0'; cchTempRootPath = 3; } else { /* must be file on current drive */ TempRootPath[0] = '\0'; cchTempRootPath = 0; } } } /* if path != NULL */ /* grab lock protecting cached entry */ EnterCriticalSection( &VolumeCapsLock ); if(!g_VolumeCaps.bValid || lstrcmpiA(g_VolumeCaps.RootPath, TempRootPath) != 0) { /* no match found, build up new entry */ DWORD dwFileSystemFlags; DWORD dwRemotePrivileges = 0; BOOL bRemote = FALSE; /* release lock during expensive operations */ LeaveCriticalSection( &VolumeCapsLock ); bSuccess = GetVolumeInformationA( (TempRootPath[0] == '\0') ? NULL : TempRootPath, NULL, 0, NULL, NULL, &dwFileSystemFlags, NULL, 0); /* only if target volume supports Acls, and we were told to use privileges do we need to go out and test for the remote case */ if(bSuccess && (dwFileSystemFlags & FS_PERSISTENT_ACLS) && VolumeCaps->bUsePrivileges) { if(GetDriveTypeA( (TempRootPath[0] == '\0') ? NULL : TempRootPath ) == DRIVE_REMOTE) { bRemote = TRUE; /* make a determination about our remote capabilities */ GetRemotePrivilegesSet(name, &dwRemotePrivileges); } } /* always take the lock again, since we release it below */ EnterCriticalSection( &VolumeCapsLock ); /* replace the existing data if successful */ if(bSuccess) { lstrcpynA(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1); g_VolumeCaps.dwFileSystemFlags = dwFileSystemFlags; g_VolumeCaps.bRemote = bRemote; g_VolumeCaps.dwRemotePrivileges = dwRemotePrivileges; g_VolumeCaps.bValid = TRUE; } } if(bSuccess) { /* copy input elements */ g_VolumeCaps.bUsePrivileges = VolumeCaps->bUsePrivileges; g_VolumeCaps.dwFileAttributes = VolumeCaps->dwFileAttributes; /* give caller results */ memcpy(VolumeCaps, &g_VolumeCaps, sizeof(VOLUMECAPS)); } else { g_VolumeCaps.bValid = FALSE; } LeaveCriticalSection( &VolumeCapsLock ); /* release lock */ return bSuccess; } BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata) { HANDLE hFile; DWORD dwDesiredAccess = 0; DWORD dwFlags = 0; PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata; SECURITY_DESCRIPTOR_CONTROL sdc; SECURITY_INFORMATION RequestedInfo = 0; DWORD dwRev; BOOL bRestorePrivilege = FALSE; BOOL bSaclPrivilege = FALSE; BOOL bSuccess; if(!bInitialized) if(!Initialize()) return FALSE; /* defer directory processing */ if(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* opening a directory requires FILE_FLAG_BACKUP_SEMANTICS */ dwFlags |= FILE_FLAG_BACKUP_SEMANTICS; } /* evaluate the input security descriptor and act accordingly */ if(!IsValidSecurityDescriptor(sd)) return FALSE; if(!GetSecurityDescriptorControl(sd, &sdc, &dwRev)) return FALSE; /* setup privilege usage based on if told we can use privileges, and if so, what privileges we have */ if(VolumeCaps->bUsePrivileges) { if(VolumeCaps->bRemote) { /* use remotely determined privileges */ if(VolumeCaps->dwRemotePrivileges & OVERRIDE_RESTORE) bRestorePrivilege = TRUE; if(VolumeCaps->dwRemotePrivileges & OVERRIDE_SACL) bSaclPrivilege = TRUE; } else { /* use local privileges */ bRestorePrivilege = g_bRestorePrivilege; bSaclPrivilege = g_bSaclPrivilege; } } /* if a Dacl is present write Dacl out */ /* if we have SeRestorePrivilege, write owner and group info out */ if(sdc & SE_DACL_PRESENT) { dwDesiredAccess |= WRITE_DAC; RequestedInfo |= DACL_SECURITY_INFORMATION; if(bRestorePrivilege) { dwDesiredAccess |= WRITE_OWNER; RequestedInfo |= (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION); } } /* if a Sacl is present and we have either SeRestorePrivilege or SeSystemSecurityPrivilege try to write Sacl out */ if((sdc & SE_SACL_PRESENT) && (bRestorePrivilege || bSaclPrivilege)) { dwDesiredAccess |= ACCESS_SYSTEM_SECURITY; RequestedInfo |= SACL_SECURITY_INFORMATION; } if(RequestedInfo == 0) /* nothing to do */ return FALSE; if(bRestorePrivilege) dwFlags |= FILE_FLAG_BACKUP_SEMANTICS; hFile = CreateFileA( resource, dwDesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,/* max sharing */ NULL, OPEN_EXISTING, dwFlags, NULL ); if(hFile == INVALID_HANDLE_VALUE) return FALSE; bSuccess = SetKernelObjectSecurity(hFile, RequestedInfo, sd); CloseHandle(hFile); return bSuccess; } static VOID InitLocalPrivileges(VOID) { HANDLE hToken; TOKEN_PRIVILEGES tp; /* try to enable some interesting privileges that give us the ability to get some security information that we normally cannot. note that enabling privileges is only relevant on the local machine; when accessing files that are on a remote machine, any privileges that are present on the remote machine get enabled by default. */ if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) return; tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if(LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid)) { /* try to enable SeRestorePrivilege; if this succeeds, we can write all aspects of the security descriptor */ if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) && GetLastError() == ERROR_SUCCESS) g_bRestorePrivilege = TRUE; } /* try to enable SeSystemSecurityPrivilege, if SeRestorePrivilege not present; if this succeeds, we can write the Sacl */ if(!g_bRestorePrivilege && LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) { if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) && GetLastError() == ERROR_SUCCESS) g_bSaclPrivilege = TRUE; } CloseHandle(hToken); } #endif /* NTSD_EAS */ Carla-2.1/data/windows/unzipfx-carla-control/win32/nt.h000066400000000000000000000026141364475620200230120ustar00rootroot00000000000000/* Copyright (c) 1990-2005 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* nt.h: central header for EF_NTSD "SD" extra field */ #ifndef _NT_H #define _NT_H #define NTSD_BUFFERSIZE (1024) /* threshold to cause malloc() */ #define OVERRIDE_BACKUP 1 /* we have SeBackupPrivilege on remote */ #define OVERRIDE_RESTORE 2 /* we have SeRestorePrivilege on remote */ #define OVERRIDE_SACL 4 /* we have SeSystemSecurityPrivilege on remote */ typedef struct { BOOL bValid; /* are our contents valid? */ BOOL bUsePrivileges; /* use privilege overrides? */ DWORD dwFileSystemFlags; /* describes target file system */ BOOL bRemote; /* is volume remote? */ DWORD dwRemotePrivileges; /* relevant only on remote volumes */ DWORD dwFileAttributes; char RootPath[MAX_PATH+1]; /* path to network / filesystem */ } VOLUMECAPS, *PVOLUMECAPS, *LPVOLUMECAPS; BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata); BOOL GetVolumeCaps(char *rootpath, char *name, PVOLUMECAPS VolumeCaps); BOOL ValidateSecurity(uch *securitydata); #endif /* _NT_H */ Carla-2.1/data/windows/unzipfx-carla-control/win32/w32cfg.h000066400000000000000000000443251364475620200234710ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- Win32 specific configuration section: ---------------------------------------------------------------------------*/ #ifndef __w32cfg_h #define __w32cfg_h #ifdef __MINGW32__ # define USE_STRM_INPUT #endif #ifdef __CYGWIN__ /* We treat the file system underneath the Cygwin Unix emulator environment * as "native VFAT/NTFS" and use the WIN32 API for its special attributes... */ # ifdef UNIX # undef UNIX # endif #endif #if (defined(_MSC_VER) && !defined(MSC)) # define MSC #endif /* enable multibyte character set support by default */ #if (!defined(_MBCS) && !defined(NO_MBCS)) # define _MBCS #endif #if (defined(_MBCS) && defined(NO_MBCS)) # undef _MBCS #endif #if (defined(__CYGWIN__) && defined(_MBCS)) # undef _MBCS /* Cygwin RTL lacks support for __mb_cur_max */ #endif #if (defined(__DJGPP__) && !defined(__EMX__) && defined(_MBCS)) # undef _MBCS /* __mb_cur_max missing for RSXNTdj 1.6 beta */ #endif #include /* off_t, time_t, dev_t, ... */ #include #include /* read(), open(), etc. */ #include #if ((defined(__RSXNT__) || defined(__EMX__)) && !defined(tzset)) # define tzset _tzset #endif #if (defined(__LCC__) && !defined(tzset)) # define tzset _tzset #endif #ifdef W32_USE_IZ_TIMEZONE # ifdef __BORLANDC__ # define tzname tzname # define IZTZ_DEFINESTDGLOBALS # endif # ifdef __WATCOMC__ # define IZTZ_DEFINESTDGLOBALS # endif # ifndef tzset # define tzset _tzset # endif # ifndef timezone # define timezone _timezone # endif # ifndef daylight # define daylight _daylight # endif # ifndef tzname # define tzname _tzname # endif # if (!defined(NEED__ISINDST) && !defined(__BORLANDC__)) # define NEED__ISINDST # endif # ifdef IZTZ_GETLOCALETZINFO # undef IZTZ_GETLOCALETZINFO # endif # define IZTZ_GETLOCALETZINFO GetPlatformLocalTimezone #endif /* W32_USE_IZ_TIMEZONE */ #include #if (!defined(__RSXNT__) && !defined(__CYGWIN__)) # include /* mkdir() */ #endif #include #ifdef __CYGWIN__ # include extern int setmode(int, int); /* this is missing in */ #endif #if (defined(MSC) || defined(__WATCOMC__) || defined(__MINGW32__)) # include #else # include #endif #define GOT_UTIMBUF #ifdef _MBCS # if (!defined(__EMX__) && !defined(__DJGPP__) && !defined(__CYGWIN__)) # if (!defined(__MINGW32__) || defined(__MSVCRT__)) # include # include /* for MSC (and compatible compilers), use routines supplied by RTL */ # define CLEN(ptr) _mbclen((const uch *)(ptr)) # define PREINCSTR(ptr) (ptr = (char *)_mbsinc((const uch *)(ptr))) # define MBSCHR(str, c) (char *)_mbschr((const uch *)(str), (c)) # define MBSRCHR(str, c) (char *)_mbsrchr((const uch *)(str), (c)) # endif # endif # if (defined(__MINGW32__) && !defined(MB_CUR_MAX)) # ifdef __MSVCRT__ extern int *__p___mb_cur_max(void); # define MB_CUR_MAX (*__p___mb_cur_max()) # else extern int *_imp____mb_cur_max_dll; # define MB_CUR_MAX (*_imp____mb_cur_max_dll) # endif # endif # if (defined(__LCC__) && !defined(MB_CUR_MAX)) extern int *_imp____mb_cur_max; # define MB_CUR_MAX (*_imp____mb_cur_max) # endif # if (defined(__DJGPP__) && !defined(__EMX__) && !defined(MB_CUR_MAX)) extern int *_imp____mb_cur_max; # define MB_CUR_MAX (*_imp____mb_cur_max) # endif #endif /* for UnZip, the "basic" part of the win32 api is sufficient */ #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif #if defined(__FILEIO_C) # ifndef __CYGWIN__ # include # endif # include # ifdef __RSXNT__ # include "../win32/rsxntwin.h" # endif # ifndef TIME_ZONE_ID_INVALID # define TIME_ZONE_ID_INVALID (DWORD)0xFFFFFFFFL # endif #endif #if (defined(__ENVARGS_C) || defined(__EXTRACT_C) || defined(__UNZIP_C) || \ defined(ZCRYPT_INTERNAL)) # include # ifdef __RSXNT__ # include "../win32/rsxntwin.h" # endif # ifndef TIME_ZONE_ID_INVALID # define TIME_ZONE_ID_INVALID (DWORD)0xFFFFFFFFL # endif #endif #ifndef Cdecl # define Cdecl __cdecl #endif /* the following definitions are considered as "obsolete" by Microsoft and * might be missing in some versions of */ #ifndef AnsiToOem # define AnsiToOem CharToOemA #endif #ifndef OemToAnsi # define OemToAnsi OemToCharA #endif #define DIR_END '\\' /* OS uses '\\' as directory separator */ #define DIR_END2 '/' /* also check for '/' (RTL may convert) */ #ifdef DATE_FORMAT # undef DATE_FORMAT #endif #define DATE_FORMAT dateformat() #ifdef DATE_SEPCHAR # undef DATE_SEPCHAR #endif #define DATE_SEPCHAR dateseparator() #define lenEOL 2 #define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);} #if (defined(__RSXNT__) && !defined(HAVE_MKTIME)) # define HAVE_MKTIME /* use mktime() in time conversion routines */ #endif #if (defined(MSC) && !defined(HAVE_MKTIME)) # define HAVE_MKTIME /* use mktime() in time conversion routines */ #endif #if (defined(__CYGWIN__) && defined(HAVE_MKTIME)) # undef HAVE_MKTIME /* Cygnus' mktime() implementation is buggy */ #endif #if (defined(W32_USE_IZ_TIMEZONE) && !defined(HAVE_MKTIME)) # define HAVE_MKTIME /* use mktime() in time conversion routines */ #endif #if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)) # define USE_EF_UT_TIME #endif #if (!defined(NO_DIR_ATTRIB) && !defined(SET_DIR_ATTRIB)) # define SET_DIR_ATTRIB #endif #if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) # define TIMESTAMP #endif #if (!defined(NO_NTSD_EAS) && !defined(NTSD_EAS)) # define NTSD_EAS /* enable NTSD support unless explicitly suppressed */ #endif #if (defined(NTSD_EAS) && !defined(RESTORE_ACL)) # define RESTORE_ACL /* "restore ACLs" only needed when NTSD_EAS active */ #endif #if (!defined(NO_UNICODE_SUPPORT) && !defined(UNICODE_SUPPORT)) # define UNICODE_SUPPORT /* enable UTF-8 filename support by default */ #endif #if (defined(UNICODE_SUPPORT) && !defined(UNICODE_WCHAR)) # define UNICODE_WCHAR /* wchar_t is UTF-16 encoded on WIN32 */ #endif #ifdef UTF8_MAYBE_NATIVE # undef UTF8_MAYBE_NATIVE /* UTF-8 cannot be system charset on WIN32 */ #endif /* The following compiler systems provide or use a runtime library with a * locale-aware isprint() implementation. For these systems, the "enhanced" * unprintable charcode detection in fnfilter() gets enabled. */ #if (!defined(HAVE_WORKING_ISPRINT) && !defined(NO_WORKING_ISPRINT)) # if defined(MSC) || defined(__BORLANDC__) # define HAVE_WORKING_ISPRINT # endif # if defined(__MINGW32__) && defined(__MSVCRT__) # define HAVE_WORKING_ISPRINT # endif #endif /* WIN32 runs solely on little-endian processors; enable support * for the 32-bit optimized CRC-32 C code by default. */ #ifdef IZ_CRC_BE_OPTIMIZ # undef IZ_CRC_BE_OPTIMIZ #endif #if !defined(IZ_CRC_LE_OPTIMIZ) && !defined(NO_CRC_OPTIMIZ) # define IZ_CRC_LE_OPTIMIZ #endif /* handlers for OEM <--> ANSI string conversions */ #ifdef __RSXNT__ /* RSXNT uses OEM coded strings in functions supplied by C RTL */ # ifdef CRTL_CP_IS_ISO # undef CRTL_CP_IS_ISO # endif # ifndef CRTL_CP_IS_OEM # define CRTL_CP_IS_OEM # endif #else /* "real" native WIN32 compilers use ANSI coded strings in C RTL calls */ # ifndef CRTL_CP_IS_ISO # define CRTL_CP_IS_ISO # endif # ifdef CRTL_CP_IS_OEM # undef CRTL_CP_IS_OEM # endif #endif #ifdef CRTL_CP_IS_ISO /* C RTL's file system support assumes ANSI coded strings */ # define ISO_TO_INTERN(src, dst) {if ((src) != (dst)) strcpy((dst), (src));} # define OEM_TO_INTERN(src, dst) OemToAnsi(src, dst) # define INTERN_TO_ISO(src, dst) {if ((src) != (dst)) strcpy((dst), (src));} # define INTERN_TO_OEM(src, dst) AnsiToOem(src, dst) #endif /* CRTL_CP_IS_ISO */ #ifdef CRTL_CP_IS_OEM /* C RTL's file system support assumes OEM coded strings */ # define ISO_TO_INTERN(src, dst) AnsiToOem(src, dst) # define OEM_TO_INTERN(src, dst) {if ((src) != (dst)) strcpy((dst), (src));} # define INTERN_TO_ISO(src, dst) OemToAnsi(src, dst) # define INTERN_TO_OEM(src, dst) {if ((src) != (dst)) strcpy((dst), (src));} #endif /* CRTL_CP_IS_OEM */ #define _OEM_INTERN(str1) OEM_TO_INTERN(str1, str1) #define _ISO_INTERN(str1) ISO_TO_INTERN(str1, str1) #ifndef WINDLL /* Despite best intentions, for the command-line version UzpPassword() * could return either character set, depending on whether running under * Win95 (DOS-session) or WinNT (native WinNT command interpreter)! */ # define STR_TO_CP2(dst, src) (AnsiToOem(src, dst), dst) # define STR_TO_CP3(dst, src) (OemToAnsi(src, dst), dst) #else /* The WINDLL front end is known to supply ISO/ANSI-coded passwords! */ # define STR_TO_CP2(dst, src) (AnsiToOem(src, dst), dst) #endif /* dummy defines to disable these functions, they are not needed */ #define STR_TO_OEM #define STR_TO_ISO /* Static variables that we have to add to Uz_Globs: */ #define SYSTEM_SPECIFIC_GLOBALS \ int created_dir, renamed_fullpath, fnlen;\ unsigned nLabelDrive;\ char lastRootPath[4];\ int lastVolOldFAT, lastVolLocTim;\ char *rootpath, *buildpathHPFS, *buildpathFAT, *endHPFS, *endFAT;\ ZCONST char *wildname;\ char *dirname, matchname[FILNAMSIZ];\ int rootlen, have_dirname, dirnamelen, notfirstcall;\ zvoid *wild_dir; /* created_dir, renamed_fullpath, fnlen, and nLabelDrive are used by */ /* both mapname() and checkdir(). */ /* lastRootPath, lastVolOldFAT and lastVolLocTim are used by */ /* IsVolumeOldFAT() and NTQueryVolInfo(). */ /* rootlen, rootpath, buildpathHPFS, buildpathFAT, endHPFS, and endFAT */ /* are used by checkdir(). */ /* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */ /* and notfirstcall are used by do_wild(). */ /* This replacement for C-RTL-supplied getch() (or similar) functionality * avoids leaving unabsorbed LFs in the keyboard buffer under Windows95, * and supports the +[0] feature. */ int getch_win32 OF((void)); /* Up to now, all versions of Microsoft C runtime libraries lack the support * for customized (non-US) switching rules between daylight saving time and * standard time in the TZ environment variable string. * But non-US timezone rules are correctly supported when timezone information * is read from the OS system settings in the Win32 registry. * The following work-around deletes any TZ environment setting from * the process environment. This results in a fallback of the RTL time * handling code to the (correctly interpretable) OS system settings, read * from the registry. */ #ifdef USE_EF_UT_TIME # if (defined(__WATCOMC__) || defined(__CYGWIN__) || \ defined(W32_USE_IZ_TIMEZONE)) # define iz_w32_prepareTZenv() # else # define iz_w32_prepareTZenv() putenv("TZ=") # endif #endif /* This patch of stat() is useful for at least two compilers. It is */ /* difficult to take a stat() of a root directory under Windows95, so */ /* zstat_win32() detects that case and fills in suitable values. */ #ifndef __RSXNT__ # ifndef W32_STATROOT_FIX # define W32_STATROOT_FIX # endif #endif /* !__RSXNT__ */ #define W32_STAT_BANDAID #if defined(REENTRANT) # define __W32STAT_GLOBALS__ Uz_Globs *pG, # define __W32STAT_G__ pG, #else # define __W32STAT_GLOBALS__ # define __W32STAT_G__ #endif #ifdef SSTAT # undef SSTAT #endif #ifdef WILD_STAT_BUG # define SSTAT(path, pbuf) (iswild(path) || zstat_win32(__W32STAT_G__ path, pbuf)) #else # define SSTAT(path, pbuf) zstat_win32(__W32STAT_G__ path, pbuf) #endif #ifdef __WATCOMC__ # ifdef __386__ # ifndef WATCOMC_386 # define WATCOMC_386 # endif # define __32BIT__ # undef far # define far # undef near # define near # undef Cdecl # define Cdecl /* gaah -- Watcom's docs claim that _get_osfhandle exists, but it doesn't. */ # define _get_osfhandle _os_handle /* Get asm routines to link properly without using "__cdecl": */ # ifndef USE_ZLIB # pragma aux crc32 "_*" parm caller [] value [eax] modify [eax] # pragma aux get_crc_table "_*" parm caller [] value [eax] \ modify [eax ecx edx] # endif /* !USE_ZLIB */ # endif /* __386__ */ #endif /* __WATCOMC__ */ #define SCREENWIDTH 80 #define SCREENSIZE(scrrows, scrcols) screensize(scrrows, scrcols) int screensize(int *tt_rows, int *tt_cols); /* on the DOS or NT console screen, line-wraps are always enabled */ #define SCREENLWRAP 1 #define TABSIZE 8 /* 64-bit-Integers & Large File Support * (pasted here from Zip 3b, osdep.h - Myles Bennett 7-jun-2004) * (updated from Zip 3.0d - Ed Gordon 6-oct-2004) * * If this is set it is assumed that the port * supports 64-bit file calls. The types are * defined here. Any local implementations are * in w32i64.c and the prototypes for the calls are * in unzip.h. Note that a port must support * these calls fully or should not set * LARGE_FILE_SUPPORT. */ /* Automatically set ZIP64_SUPPORT if supported */ #ifndef NO_ZIP64_SUPPORT # ifndef ZIP64_SUPPORT # if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) # define ZIP64_SUPPORT # elif defined(__LCC__) /* LCC links against crtdll.dll -> no support of 64-bit offsets :( */ # elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100)) # define ZIP64_SUPPORT # elif (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0520)) /* Borland C RTL lacks any support to get/set 64-bit file pointer :( */ # endif # endif #endif #ifdef ZIP64_SUPPORT /* base type for file offsets and file sizes */ # if (defined(__GNUC__) || defined(ULONG_LONG_MAX)) typedef long long zoff_t; # else /* all other compilers use this as intrinsic 64-bit type */ typedef __int64 zoff_t; # endif # define ZOFF_T_DEFINED /* user-defined types and format strings for 64-bit numbers and * file pointer functions (these depend on the rtl library and library * headers used; they are NOT compiler-specific) */ # if defined(_MSC_VER) || defined(__MINGW32__) || defined(__LCC__) /* MS C and VC, MinGW32, lcc32 */ /* these systems use the Microsoft C RTL */ /* 64-bit stat struct */ typedef struct _stati64 z_stat; # define Z_STAT_DEFINED # ifdef __LCC__ /* The LCC headers lack these declarations of MSC rtl functions in sys/stat.h. */ struct _stati64 { unsigned int st_dev; unsigned short st_ino; unsigned short st_mode; short st_nlink; short st_uid; short st_gid; unsigned int st_rdev; __int64 st_size; time_t st_atime; time_t st_mtime; time_t st_ctime; }; int _stati64(const char *, struct _stati64 *); int _fstati64(int, struct _stati64 *); __int64 _lseeki64(int, __int64, int); # endif /* __LCC__ */ /* printf format size prefix for zoff_t values */ # define FZOFFT_FMT "I64" # define FZOFFT_HEX_WID_VALUE "16" # define SHORTHDRSTATS "%9I64u %02u%c%02u%c%02u %02u:%02u %c" # define SHORTFILETRAILER " -------- -------\n%9I64u %9lu file%s\n" # elif (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0520)) /* Borland C 5.2 or newer */ /* 64-bit stat struct */ typedef struct stati64 z_stat; # define Z_STAT_DEFINED /* Borland C does not provide a 64-bit-capable _lseeki64(), so we need to use the stdio.h stream functions instead. */ # ifndef USE_STRM_INPUT # define USE_STRM_INPUT # endif /* printf format size prefix for zoff_t values */ # define FZOFFT_FMT "L" # define FZOFFT_HEX_WID_VALUE "16" # define SHORTHDRSTATS "%9Lu %02u%c%02u%c%02u %02u:%02u %c" # define SHORTFILETRAILER " -------- -------\n%9Lu %9lu file%s\n" # elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100)) /* WATCOM C */ /* 64-bit stat struct */ typedef struct _stati64 z_stat; # define Z_STAT_DEFINED /* printf format size prefix for zoff_t values */ # define FZOFFT_FMT "ll" # define FZOFFT_HEX_WID_VALUE "16" # define SHORTHDRSTATS "%9llu %02u%c%02u%c%02u %02u:%02u %c" # define SHORTFILETRAILER " -------- -------\n%9llu %9lu file%s\n" # elif (defined(__IBMC__) && (__IBMC__ >= 350)) /* IBM C */ /* 64-bit stat struct */ /* printf format size prefix for zoff_t values */ # define FZOFFT_FMT "I64" # define FZOFFT_HEX_WID_VALUE "16" # define SHORTHDRSTATS "%9I64u %02u%c%02u%c%02u %02u:%02u %c" # define SHORTFILETRAILER " -------- -------\n%9I64u %9lu file%s\n" # endif #endif /* If port has LARGE_FILE_SUPPORT then define here to make automatic unless overridden */ #ifndef LARGE_FILE_SUPPORT # ifndef NO_LARGE_FILE_SUPPORT # if defined(_MSC_VER) || defined(__MINGW32__) # define LARGE_FILE_SUPPORT # elif defined(__LCC__) /* LCC links against crtdll.dll -> no support of 64-bit offsets :( */ # elif defined(__CYGWIN__) # define LARGE_FILE_SUPPORT # elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100)) # define LARGE_FILE_SUPPORT # elif (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0520)) /* Borland C RTL lacks any support to get/set 64-bit file pointer :( */ # endif # endif #endif #ifndef LARGE_FILE_SUPPORT /* No Large File Support */ /* base type for file offsets and file sizes */ typedef long zoff_t; # define ZOFF_T_DEFINED /* stat struct */ typedef struct stat z_stat; # define Z_STAT_DEFINED # define FZOFFT_FMT "l" # define FZOFFT_HEX_WID_VALUE "8" # define SHORTHDRSTATS "%9lu %02u%c%02u%c%02u %02u:%02u %c" # define SHORTFILETRAILER " -------- -------\n%9lu %9lu file%s\n" #endif /* LARGE_FILE_SUPPORT */ #endif /* !__w32cfg_h */ Carla-2.1/data/windows/unzipfx-carla-control/win32/win32.c000066400000000000000000003275571364475620200233460ustar00rootroot00000000000000/* Copyright (c) 1990-2008 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2007-Mar-04 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- win32.c 32-bit Windows-specific (NT/9x) routines for use with Info-ZIP's UnZip 5.3 and later. Contains: GetLoadPath() Opendir() Readdir() Closedir() SetSD() set security descriptor on file FindSDExtraField() extract SD e.f. block from extra field IsWinNT() indicate type of WIN32 platform test_NTSD() test integrity of NT security data utime2NtfsFileTime() utime2VFatFileTime() FStampIsLocTime() NtfsFileTime2utime() VFatFileTime2utime() getNTfiletime() SetFileSize() close_outfile() defer_dir_attribs() set_direc_attribs() stamp_file() isfloppy() NTQueryVolInfo() IsVolumeOldFAT() do_wild() mapattr() mapname() maskDOSdevice() map2fat() checkdir() dateformat() dateseparator() version() screensize() zstat_win32() conv_to_rule() GetPlatformLocalTimezone() getch_win32() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include #include "../unzip.h" #ifdef __RSXNT__ # include "../win32/rsxntwin.h" #endif #include "../win32/nt.h" #ifndef FUNZIP /* most of this file is not used with fUnZip */ /* some non-MS runtime headers (e.g. lcc) may miss this definition */ #ifndef FILE_WRITE_ATTRIBUTES # define FILE_WRITE_ATTRIBUTES 0x0100 #endif #if (defined(__EMX__) || defined(__CYGWIN__)) # define MKDIR(path,mode) mkdir(path,mode) #else # define MKDIR(path,mode) mkdir(path) #endif #ifdef HAVE_WORKING_DIRENT_H # undef HAVE_WORKING_DIRENT_H #endif /* The emxrtl dirent support of (__GO32__ || __EMX__) converts to lowercase! */ #if defined(__CYGWIN__) # define HAVE_WORKING_DIRENT_H #endif #ifndef SFX # ifdef HAVE_WORKING_DIRENT_H # include /* use readdir() */ # define zdirent dirent # define zDIR DIR # define Opendir opendir # define Readdir readdir # define Closedir closedir # else /* !HAVE_WORKING_DIRENT_H */ typedef struct zdirent { char reserved [21]; char ff_attrib; short ff_ftime; short ff_fdate; long size; char d_name[MAX_PATH]; int d_first; HANDLE d_hFindFile; } zDIR; static zDIR *Opendir (const char *n); static struct zdirent *Readdir (zDIR *d); static void Closedir (zDIR *d); # endif /* ?HAVE_WORKING_DIRENT_H */ #endif /* !SFX */ #ifdef SET_DIR_ATTRIB typedef struct NTdirattr { /* struct for holding unix style directory */ struct NTdirattr *next; /* info until can be sorted and set at end */ char *fn; /* filename of directory */ FILETIME Modft; /* File time type defined in NT, `last modified' time */ FILETIME Accft; /* NT file time type, `last access' time */ FILETIME Creft; /* NT file time type, `file creation' time */ int gotTime; unsigned perms; /* same as min_info.file_attr */ #ifdef NTSD_EAS unsigned SDlen; /* length of SD data in buf */ #endif char buf[1]; /* buffer stub for directory SD and name */ } NTdirattr; #define NtAtt(d) ((NTdirattr *)d) /* typecast shortcut */ #endif /* SET_DIR_ATTRIB */ /* Function prototypes */ #ifdef NTSD_EAS static int SetSD(__GPRO__ char *path, unsigned fperms, uch *eb_ptr, unsigned eb_len); static int FindSDExtraField(__GPRO__ uch *ef_ptr, unsigned ef_len, uch **p_ebSD_ptr, unsigned *p_ebSD_len); #endif #ifndef NO_W32TIMES_IZFIX static void utime2NtfsFileTime(time_t ut, FILETIME *pft); #endif static void utime2VFatFileTime(time_t ut, FILETIME *pft, int clipDosMin); #if (defined(W32_STAT_BANDAID) && !defined(NO_W32TIMES_IZFIX)) static int NtfsFileTime2utime(const FILETIME *pft, time_t *ut); #endif #ifdef W32_STAT_BANDAID static int VFatFileTime2utime(const FILETIME *pft, time_t *ut); #endif static int FStampIsLocTime(__GPRO__ const char *path); static int getNTfiletime (__GPRO__ FILETIME *pModFT, FILETIME *pAccFT, FILETIME *pCreFT); static int isfloppy (int nDrive); static int NTQueryVolInfo (__GPRO__ const char *name); static int IsVolumeOldFAT (__GPRO__ const char *name); static void maskDOSdevice (__GPRO__ char *pathcomp); static void map2fat (char *pathcomp, char **pEndFAT); #if (defined(__MINGW32__) && !defined(USE_MINGW_GLOBBING)) int _CRT_glob = 0; /* suppress command line globbing by C RTL */ #endif #ifdef ACORN_FTYPE_NFS /* Acorn bits for NFS filetyping */ typedef struct { uch ID[2]; uch size[2]; uch ID_2[4]; uch loadaddr[4]; uch execaddr[4]; uch attr[4]; } RO_extra_block; #endif /* ACORN_FTYPE_NFS */ /* static int created_dir; */ /* used by mapname(), checkdir() */ /* static int renamed_fullpath; */ /* ditto */ /* static int fnlen; */ /* ditto */ /* static unsigned nLabelDrive; */ /* ditto */ extern char Far TruncNTSD[]; /* in extract.c */ #ifdef SFX /**************************/ /* Function GetLoadPath() */ /**************************/ char *GetLoadPath(__GPRO) { #ifdef MSC extern char *_pgmptr; return _pgmptr; #else /* use generic API call */ GetModuleFileName(NULL, G.filename, FILNAMSIZ); _ISO_INTERN(G.filename); /* translate to codepage of C rtl's stdio */ return G.filename; #endif } /* end function GetLoadPath() */ #else /* !SFX */ #ifndef HAVE_WORKING_DIRENT_H /**********************/ /* Borrowed from ZIP 2.0 sources */ /* Function Opendir() */ /* Difference: no special handling for */ /**********************/ /* hidden or system files. */ static zDIR *Opendir(n) const char *n; /* directory to open */ { zDIR *d; /* malloc'd return value */ char *p; /* malloc'd temporary string */ WIN32_FIND_DATAA fd; extent len = strlen(n); /* Start searching for files in directory n */ if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL || (p = malloc(strlen(n) + 5)) == NULL) { if (d != (zDIR *)NULL) free((void *)d); return (zDIR *)NULL; } INTERN_TO_ISO(n, p); if (len > 0) { if (p[len-1] == ':') p[len++] = '.'; /* x: => x:. */ else if (p[len-1] == '/' || p[len-1] == '\\') --len; /* foo/ => foo */ } strcpy(p+len, "/*"); if (INVALID_HANDLE_VALUE == (d->d_hFindFile = FindFirstFileA(p, &fd))) { free((zvoid *)d); free((zvoid *)p); return NULL; } strcpy(d->d_name, fd.cFileName); free((zvoid *)p); d->d_first = 1; return d; } /* end of function Opendir() */ /**********************/ /* Borrowed from ZIP 2.0 sources */ /* Function Readdir() */ /* Difference: no special handling for */ /**********************/ /* hidden or system files. */ static struct zdirent *Readdir(d) zDIR *d; /* directory stream from which to read */ { /* Return pointer to first or next directory entry, or NULL if end. */ if ( d->d_first ) d->d_first = 0; else { WIN32_FIND_DATAA fd; if ( !FindNextFileA(d->d_hFindFile, &fd) ) return NULL; ISO_TO_INTERN(fd.cFileName, d->d_name); } return (struct zdirent *)d; } /* end of function Readdir() */ /***********************/ /* Function Closedir() */ /* Borrowed from ZIP 2.0 sources */ /***********************/ static void Closedir(d) zDIR *d; /* directory stream to close */ { FindClose(d->d_hFindFile); free(d); } #endif /* !HAVE_WORKING_DIRENT_H */ #endif /* ?SFX */ #ifdef NTSD_EAS /**********************/ /* Function SetSD() */ /* return almost-PK errors */ /**********************/ static int SetSD(__G__ path, fperms, eb_ptr, eb_len) __GDEF char *path; unsigned fperms; uch *eb_ptr; unsigned eb_len; { ulg ntsd_ucSize; VOLUMECAPS VolumeCaps; uch *security_data; int error; ntsd_ucSize = makelong(eb_ptr + (EB_HEADSIZE+EB_UCSIZE_P)); if (ntsd_ucSize > 0L && eb_len <= (EB_NTSD_L_LEN + EB_CMPRHEADLEN)) return IZ_EF_TRUNC; /* no compressed data! */ /* provide useful input */ VolumeCaps.dwFileAttributes = fperms; VolumeCaps.bUsePrivileges = (uO.X_flag > 1); /* check target volume capabilities - just fall through * and try if fail */ if (GetVolumeCaps(G.rootpath, path, &VolumeCaps) && !(VolumeCaps.dwFileSystemFlags & FS_PERSISTENT_ACLS)) return PK_OK; /* allocate storage for uncompressed data */ security_data = (uch *)malloc((extent)ntsd_ucSize); if (security_data == (uch *)NULL) return PK_MEM4; error = memextract(__G__ security_data, ntsd_ucSize, (eb_ptr + (EB_HEADSIZE+EB_NTSD_L_LEN)), (ulg)(eb_len - EB_NTSD_L_LEN)); if (error == PK_OK) { if (SecuritySet(path, &VolumeCaps, security_data)) { error = PK_COOL; if (!uO.tflag && QCOND2) Info(slide, 0, ((char *)slide, " (%ld bytes security)", ntsd_ucSize)); } } free(security_data); return error; } /********************************/ /* scan extra fields for something */ /* Function FindSDExtraField() */ /* we happen to know */ /********************************/ /* Returns TRUE when a valid NTFS SD block is found. * Address and size of the NTSD e.f. block are passed up to the caller. * In case of more than one valid NTSD block in the e.f., the last block * found is passed up. * Returns FALSE and leaves the content of the ebSD_ptr and ebSD_len * parameters untouched when no valid NTFS SD block is found. */ static int FindSDExtraField(__GPRO__ uch *ef_ptr, unsigned ef_len, uch **p_ebSD_ptr, unsigned *p_ebSD_len) { int rc = FALSE; if (!uO.X_flag) return FALSE; /* user said don't process ACLs; for now, no other extra block types are handled here */ while (ef_len >= EB_HEADSIZE) { unsigned eb_id = makeword(EB_ID + ef_ptr); unsigned eb_len = makeword(EB_LEN + ef_ptr); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ Trace((stderr, "FindSDExtraField: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } switch (eb_id) { /* process security descriptor extra data if: Caller is WinNT AND Target local/remote drive supports acls AND Target file is not a directory (else we defer processing until later) */ case EF_NTSD: if (!IsWinNT()) break; /* OS not capable of handling NTFS attributes */ if (eb_len < EB_NTSD_L_LEN) break; /* not a valid NTSD extra field */ /* check if we know how to handle this version */ if (*(ef_ptr + (EB_HEADSIZE+EB_NTSD_VERSION)) > (uch)EB_NTSD_MAX_VER) break; *p_ebSD_ptr = ef_ptr; *p_ebSD_len = eb_len; rc = TRUE; break; #ifdef DEBUG case EF_OS2: case EF_AV: case EF_PKVMS: case EF_PKW32: case EF_PKUNIX: case EF_IZVMS: case EF_IZUNIX: case EF_IZUNIX2: case EF_TIME: case EF_MAC3: case EF_JLMAC: case EF_ZIPIT: case EF_VMCMS: case EF_MVS: case EF_ACL: case EF_ATHEOS: case EF_BEOS: case EF_QDOS: case EF_AOSVS: case EF_SPARK: case EF_MD5: case EF_ASIUNIX: break; /* shut up for other known e.f. blocks */ #endif /* DEBUG */ default: Trace((stderr, "FindSDExtraField: unknown extra field block, ID=%u\n", eb_id)); break; } ef_ptr += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return rc; } #ifndef SFX /**************************/ /* Function test_NTSD() */ /* returns PK_WARN when NTSD data is invalid */ /**************************/ #ifdef __BORLANDC__ /* Turn off warning about not using all parameters for this function only */ #pragma argsused #endif int test_NTSD(__G__ eb, eb_size, eb_ucptr, eb_ucsize) __GDEF uch *eb; unsigned eb_size; uch *eb_ucptr; ulg eb_ucsize; { return (ValidateSecurity(eb_ucptr) ? PK_OK : PK_WARN); } /* end function test_NTSD() */ #endif /* !SFX */ #endif /* NTSD_EAS */ /**********************/ /* Function IsWinNT() */ /**********************/ int IsWinNT(void) /* returns TRUE if real NT, FALSE if Win9x or Win32s */ { static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */ if (g_PlatformId == 0xFFFFFFFF) { /* note: GetVersionEx() doesn't exist on WinNT 3.1 */ if (GetVersion() < 0x80000000) g_PlatformId = TRUE; else g_PlatformId = FALSE; } return (int)g_PlatformId; } /* DEBUG_TIME insertion: */ #ifdef DEBUG_TIME static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft); static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft) { SYSTEMTIME w32tm; int rval; rval = FileTimeToSystemTime(pft, &w32tm); if (!rval) { fprintf(hdo, "%s\n %08lX,%08lX (%s) -> Conversion failed !!!\n", TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime), (isloc ? "local" : "UTC")); } else { fprintf(hdo, "%s\n %08lx,%08lx -> %04u-%02u-%02u, %02u:%02u:%02u %s\n", TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime), w32tm.wYear, w32tm.wMonth, w32tm.wDay, w32tm.wHour, w32tm.wMinute, w32tm.wSecond, (isloc ? "local" : "UTC")); } return rval; } #define FTTrace(x) show_NTFileTime x #else #define FTTrace(x) #endif /* DEBUG_TIME */ /* end of DEBUG_TIME insertion */ #ifndef IZ_USE_INT64 # if (defined(__GNUC__) || defined(ULONG_LONG_MAX)) typedef long long LLONG64; typedef unsigned long long ULLNG64; # define IZ_USE_INT64 # elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100)) typedef __int64 LLONG64; typedef unsigned __int64 ULLNG64; # define IZ_USE_INT64 # elif (defined(_MSC_VER) && (_MSC_VER >= 1100)) typedef __int64 LLONG64; typedef unsigned __int64 ULLNG64; # define IZ_USE_INT64 # elif (defined(__IBMC__) && (__IBMC__ >= 350)) typedef __int64 LLONG64; typedef unsigned __int64 ULLNG64; # define IZ_USE_INT64 # elif defined(HAVE_INT64) typedef __int64 LLONG64; typedef unsigned __int64 ULLNG64; # define IZ_USE_INT64 # endif #endif /* scale factor and offset for conversion time_t -> FILETIME */ #define NT_QUANTA_PER_UNIX 10000000L #define UNIX_TIME_ZERO_HI 0x019DB1DEUL #define UNIX_TIME_ZERO_LO 0xD53E8000UL /* special FILETIME values for bound-checks */ #define UNIX_TIME_UMAX_HI 0x0236485EUL #define UNIX_TIME_UMAX_LO 0xD4A5E980UL #define UNIX_TIME_SMIN_HI 0x0151669EUL #define UNIX_TIME_SMIN_LO 0xD53E8000UL #define UNIX_TIME_SMAX_HI 0x01E9FD1EUL #define UNIX_TIME_SMAX_LO 0xD4A5E980UL #define DOSTIME_MIN_FT_HI 0x01A8E79FUL #define DOSTIME_MIN_FT_LO 0xE1D58000UL /* time_t equivalent of DOSTIME_MINIMUM */ #define UTIME_1980_JAN_01_00_00 315532800L #ifndef NO_W32TIMES_IZFIX /*********************************/ /* Function utime2NtfsFileTime() */ /* convert Unix time_t format into the */ /*********************************/ /* form used by SetFileTime() in NT/9x */ static void utime2NtfsFileTime(time_t ut, FILETIME *pft) { #ifdef IZ_USE_INT64 ULLNG64 NTtime; /* NT_QUANTA_PER_UNIX is small enough so that "ut * NT_QUANTA_PER_UNIX" * cannot overflow in 64-bit signed calculation, regardless whether "ut" * is signed or unsigned. */ NTtime = ((LLONG64)ut * NT_QUANTA_PER_UNIX) + ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32)); pft->dwLowDateTime = (DWORD)NTtime; pft->dwHighDateTime = (DWORD)(NTtime >> 32); #else /* !IZ_USE_INT64 (64-bit integer arithmetics may not be supported) */ unsigned int b1, b2, carry = 0; unsigned long r0, r1, r2, r3; long r4; /* signed, to catch environments with signed time_t */ b1 = ut & 0xFFFF; b2 = (ut >> 16) & 0xFFFF; /* if ut is over 32 bits, too bad */ r1 = b1 * (NT_QUANTA_PER_UNIX & 0xFFFF); r2 = b1 * (NT_QUANTA_PER_UNIX >> 16); r3 = b2 * (NT_QUANTA_PER_UNIX & 0xFFFF); r4 = b2 * (NT_QUANTA_PER_UNIX >> 16); r0 = (r1 + (r2 << 16)) & 0xFFFFFFFFL; if (r0 < r1) carry++; r1 = r0; r0 = (r0 + (r3 << 16)) & 0xFFFFFFFFL; if (r0 < r1) carry++; pft->dwLowDateTime = r0 + UNIX_TIME_ZERO_LO; if (pft->dwLowDateTime < r0) carry++; pft->dwHighDateTime = r4 + (r2 >> 16) + (r3 >> 16) + UNIX_TIME_ZERO_HI + carry; #endif /* ?IZ_USE_INT64 */ } /* end function utime2NtfsFileTime() */ #endif /* !NO_W32TIMES_IZFIX */ /*********************************/ /* Function utime2VFatFileTime() */ /* convert Unix time_t format into the */ /*********************************/ /* form used by SetFileTime() in NT/9x */ static void utime2VFatFileTime(time_t ut, FILETIME *pft, int clipDosMin) { time_t utc = ut; struct tm *ltm; SYSTEMTIME w32tm; FILETIME lft; /* The milliseconds field gets always initialized to 0. */ w32tm.wMilliseconds = 0; #ifdef __BORLANDC__ /* Borland C++ 5.x crashes when trying to reference tm */ if (utc < UTIME_1980_JAN_01_00_00) utc = UTIME_1980_JAN_01_00_00; #endif ltm = localtime(&utc); if (ltm == (struct tm *)NULL) /* localtime() did not accept given utc time value; try to use the UTC value */ ltm = gmtime(&utc); if (ltm == (struct tm *)NULL) { if (ut <= (UTIME_1980_JAN_01_00_00 + 86400)) { /* use DOSTIME_MINIMUM date instead of "early" failure dates */ w32tm.wYear = 1980; w32tm.wMonth = 1; w32tm.wDay = 1; w32tm.wHour = 0; w32tm.wMinute = 0; w32tm.wSecond = 0; } else { /* as a last resort, use the current system time */ GetLocalTime(&w32tm); } } else if (clipDosMin && (ltm->tm_year < 80)) { w32tm.wYear = 1980; w32tm.wMonth = 1; w32tm.wDay = 1; w32tm.wHour = 0; w32tm.wMinute = 0; w32tm.wSecond = 0; } else { w32tm.wYear = ltm->tm_year + 1900; /* year + 1900 -> year */ w32tm.wMonth = ltm->tm_mon + 1; /* 0..11 -> 1..12 */ w32tm.wDay = ltm->tm_mday; /* 1..31 */ w32tm.wHour = ltm->tm_hour; /* 0..23 */ w32tm.wMinute = ltm->tm_min; /* 0..59 */ w32tm.wSecond = ltm->tm_sec; /* 0..61 in ANSI C */ } SystemTimeToFileTime(&w32tm, &lft); LocalFileTimeToFileTime(&lft, pft); } /* end function utime2VFatFileTime() */ /* nonzero if `y' is a leap year, else zero */ #define leap(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0) /* number of leap years from 1970 to `y' (not including `y' itself) */ #define nleap(y) (((y)-1969)/4 - ((y)-1901)/100 + ((y)-1601)/400) extern ZCONST ush ydays[]; /* defined in fileio.c */ #if (defined(W32_STAT_BANDAID) && !defined(NO_W32TIMES_IZFIX)) /*********************************/ /* Function NtfsFileTime2utime() */ /*********************************/ static int NtfsFileTime2utime(const FILETIME *pft, time_t *ut) { #ifdef IZ_USE_INT64 ULLNG64 NTtime; NTtime = ((ULLNG64)pft->dwLowDateTime + ((ULLNG64)pft->dwHighDateTime << 32)); #ifndef TIME_T_TYPE_DOUBLE /* underflow and overflow handling */ #ifdef CHECK_UTIME_SIGNED_UNSIGNED if ((time_t)0x80000000L < (time_t)0L) { if (NTtime < ((ULLNG64)UNIX_TIME_SMIN_LO + ((ULLNG64)UNIX_TIME_SMIN_HI << 32))) { *ut = (time_t)LONG_MIN; return FALSE; } if (NTtime > ((ULLNG64)UNIX_TIME_SMAX_LO + ((ULLNG64)UNIX_TIME_SMAX_HI << 32))) { *ut = (time_t)LONG_MAX; return FALSE; } } else #endif /* CHECK_UTIME_SIGNED_UNSIGNED */ { if (NTtime < ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32))) { *ut = (time_t)0; return FALSE; } if (NTtime > ((ULLNG64)UNIX_TIME_UMAX_LO + ((ULLNG64)UNIX_TIME_UMAX_HI << 32))) { *ut = (time_t)ULONG_MAX; return FALSE; } } #endif /* !TIME_T_TYPE_DOUBLE */ NTtime -= ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32)); *ut = (time_t)(NTtime / (unsigned long)NT_QUANTA_PER_UNIX); return TRUE; #else /* !IZ_USE_INT64 (64-bit integer arithmetics may not be supported) */ time_t days; SYSTEMTIME w32tm; #ifndef TIME_T_TYPE_DOUBLE /* underflow and overflow handling */ #ifdef CHECK_UTIME_SIGNED_UNSIGNED if ((time_t)0x80000000L < (time_t)0L) { if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) || ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) && (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) { *ut = (time_t)LONG_MIN; return FALSE; if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) || ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) && (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) { *ut = (time_t)LONG_MAX; return FALSE; } } else #endif /* CHECK_UTIME_SIGNED_UNSIGNED */ { if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) || ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) && (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) { *ut = (time_t)0; return FALSE; } if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) || ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) && (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) { *ut = (time_t)ULONG_MAX; return FALSE; } } #endif /* !TIME_T_TYPE_DOUBLE */ FileTimeToSystemTime(pft, &w32tm); /* set `days' to the number of days into the year */ days = w32tm.wDay - 1 + ydays[w32tm.wMonth-1] + (w32tm.wMonth > 2 && leap (w32tm.wYear)); /* now set `days' to the number of days since 1 Jan 1970 */ days += 365 * (time_t)(w32tm.wYear - 1970) + (time_t)(nleap(w32tm.wYear)); *ut = (time_t)(86400L * days + 3600L * (time_t)w32tm.wHour + (time_t)(60 * w32tm.wMinute + w32tm.wSecond)); return TRUE; #endif /* ?IZ_USE_INT64 */ } /* end function NtfsFileTime2utime() */ #endif /* W32_STAT_BANDAID && !NO_W32TIMES_IZFIX */ #ifdef W32_STAT_BANDAID /*********************************/ /* Function VFatFileTime2utime() */ /*********************************/ static int VFatFileTime2utime(const FILETIME *pft, time_t *ut) { FILETIME lft; #ifndef HAVE_MKTIME WORD wDOSDate, wDOSTime; #else SYSTEMTIME w32tm; struct tm ltm; #endif if (!FileTimeToLocalFileTime(pft, &lft)) { /* if pft cannot be converted to local time, set ut to current time */ time(ut); return FALSE; } FTTrace((stdout, "VFatFT2utime, feed for mktime()", 1, &lft)); #ifndef HAVE_MKTIME /* This version of the FILETIME-to-UNIXTIME conversion function * uses DOS-DATE-TIME format as intermediate stage. For modification * and access times, this is no problem. But, the extra fine resolution * of the VFAT-stored creation time gets lost. */ if (!FileTimeToDosDateTime(&lft, &wDOSDate, &wDOSTime)) { static const FILETIME dosmin_ft = {DOSTIME_MIN_FT_LO, DOSTIME_MIN_FT_HI}; if (CompareFileTime(&lft, &dosmin_ft) <= 0) { /* underflow -> set to minimum DOS time */ wDOSDate = (WORD)((DWORD)DOSTIME_MINIMUM >> 16); wDOSTime = (WORD)DOSTIME_MINIMUM; } else { /* overflow -> set to maximum DOS time */ wDOSDate = (WORD)0xFF9F; /* 2107-12-31 */ wDOSTime = (WORD)0xBF7D; /* 23:59:58 */ } } TTrace((stdout,"DosDateTime is %04u-%02u-%02u %02u:%02u:%02u\n", (unsigned)((wDOSDate>>9)&0x7f)+1980,(unsigned)((wDOSDate>>5)&0x0f), (unsigned)(wDOSDate&0x1f),(unsigned)((wDOSTime>>11)&0x1f), (unsigned)((wDOSTime>>5)&0x3f),(unsigned)((wDOSTime<<1)&0x3e))); *ut = dos_to_unix_time(((ulg)wDOSDate << 16) | (ulg)wDOSTime); /* a cheap error check: dos_to_unix_time() only returns an odd time * when clipping at maximum time_t value. DOS_DATE_TIME values have * a resolution of 2 seconds and are therefore even numbers. */ return (((*ut)&1) == (time_t)0); #else /* HAVE_MKTIME */ FileTimeToSystemTime(&lft, &w32tm); #ifndef TIME_T_TYPE_DOUBLE /* underflow and overflow handling */ /* TODO: The range checks are not accurate, the actual limits may * be off by one daylight-saving-time shift (typically 1 hour), * depending on the current state of "is_dst". */ #ifdef CHECK_UTIME_SIGNED_UNSIGNED if ((time_t)0x80000000L < (time_t)0L) { if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) || ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) && (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) { *ut = (time_t)LONG_MIN; return FALSE; if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) || ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) && (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) { *ut = (time_t)LONG_MAX; return FALSE; } } else #endif /* CHECK_UTIME_SIGNED_UNSIGNED */ { if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) || ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) && (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) { *ut = (time_t)0; return FALSE; } if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) || ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) && (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) { *ut = (time_t)ULONG_MAX; return FALSE; } } #endif /* !TIME_T_TYPE_DOUBLE */ ltm.tm_year = w32tm.wYear - 1900; ltm.tm_mon = w32tm.wMonth - 1; ltm.tm_mday = w32tm.wDay; ltm.tm_hour = w32tm.wHour; ltm.tm_min = w32tm.wMinute; ltm.tm_sec = w32tm.wSecond; ltm.tm_isdst = -1; /* let mktime determine if DST is in effect */ *ut = mktime(<m); /* a cheap error check: mktime returns "(time_t)-1L" on conversion errors. * Normally, we would have to apply a consistency check because "-1" * could also be a valid time. But, it is quite unlikely to read back odd * time numbers from file systems that store time stamps in DOS format. * (The only known exception is creation time on VFAT partitions.) */ return (*ut != (time_t)-1L); #endif /* ?HAVE_MKTIME */ } /* end function VFatFileTime2utime() */ #endif /* W32_STAT_BANDAID */ /******************************/ /* Function FStampIsLocTime() */ /******************************/ static int FStampIsLocTime(__GPRO__ const char *path) { return (NTQueryVolInfo(__G__ path) ? G.lastVolLocTim : FALSE); } #ifndef NO_W32TIMES_IZFIX # define UTIME_2_IZFILETIME(ut, pft) \ if (fs_uses_loctime) {utime2VFatFileTime(ut, pft, TRUE);} \ else {utime2NtfsFileTime(ut, pft);} #else # define UTIME_2_IZFILETIME(ut, pft) \ utime2VFatFileTime(ut, pft, fs_uses_loctime); #endif /****************************/ /* Get the file time in a format that */ /* Function getNTfiletime() */ /* can be used by SetFileTime() in NT */ /****************************/ static int getNTfiletime(__G__ pModFT, pAccFT, pCreFT) __GDEF FILETIME *pModFT; FILETIME *pAccFT; FILETIME *pCreFT; { #ifdef USE_EF_UT_TIME unsigned eb_izux_flg; iztimes z_utime; /* struct for Unix-style actime & modtime, + creatime */ #endif int fs_uses_loctime = FStampIsLocTime(__G__ G.filename); /* Copy and/or convert time and date variables, if necessary; * return a flag indicating which time stamps are available. */ #ifdef USE_EF_UT_TIME if (G.extra_field && #ifdef IZ_CHECK_TZ G.tz_is_valid && #endif ((eb_izux_flg = ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, &z_utime, NULL)) & EB_UT_FL_MTIME)) { TTrace((stderr, "getNTfiletime: Unix e.f. modif. time = %lu\n", z_utime.mtime)); UTIME_2_IZFILETIME(z_utime.mtime, pModFT) if (eb_izux_flg & EB_UT_FL_ATIME) { UTIME_2_IZFILETIME(z_utime.atime, pAccFT) } if (eb_izux_flg & EB_UT_FL_CTIME) { UTIME_2_IZFILETIME(z_utime.ctime, pCreFT) } return (int)eb_izux_flg; } #endif /* USE_EF_UT_TIME */ #ifndef NO_W32TIMES_IZFIX if (!fs_uses_loctime) { time_t ux_modtime; ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); utime2NtfsFileTime(ux_modtime, pModFT); } else #endif /* NO_W32TIMES_IZFIX */ { FILETIME lft; DosDateTimeToFileTime((WORD)(G.lrec.last_mod_dos_datetime >> 16), (WORD)(G.lrec.last_mod_dos_datetime & 0xFFFFL), &lft); LocalFileTimeToFileTime(&lft, pModFT); } *pAccFT = *pModFT; return (EB_UT_FL_MTIME | EB_UT_FL_ATIME); } /* end function getNTfiletime() */ /**************************/ /* Function SetFileSize() */ /**************************/ int SetFileSize(FILE *file, zusz_t filesize) { #ifdef __RSXNT__ /* RSXNT environment lacks a translation function from C file pointer to Win32-API file handle. So, simply do nothing. */ return 0; #else /* !__RSXNT__ */ /* not yet verified, if that really creates an unfragmented file rommel@ars.de */ HANDLE os_fh; #ifdef Z_UINT8_DEFINED LARGE_INTEGER fsbuf; #endif /* Win9x supports FAT file system, only; presetting file size does not help to prevent fragmentation. */ if (!IsWinNT()) return 0; /* Win32-API calls require access to the Win32 file handle. The interface function used to retrieve the Win32 handle for a file opened by the C rtl is non-standard and may not be available for every Win32 compiler environment. (see also win32/win32.c of the Zip distribution) */ os_fh = (HANDLE)_get_osfhandle(fileno(file)); /* move file pointer behind the last byte of the expected file size */ #ifdef Z_UINT8_DEFINED fsbuf.QuadPart = filesize; if ((SetFilePointer(os_fh, fsbuf.LowPart, &fsbuf.HighPart, FILE_BEGIN) == 0xFFFFFFFF) && GetLastError() != NO_ERROR) #else if (SetFilePointer(os_fh, (ulg)filesize, 0, FILE_BEGIN) == 0xFFFFFFFF) #endif return -1; /* extend/truncate file to the current position */ if (SetEndOfFile(os_fh) == 0) return -1; /* move file position pointer back to the start of the file! */ return (SetFilePointer(os_fh, 0, 0, FILE_BEGIN) == 0xFFFFFFFF) ? -1 : 0; #endif /* ?__RSXNT__ */ } /* end function SetFileSize() */ /****************************/ /* Function close_outfile() */ /****************************/ void close_outfile(__G) __GDEF { FILETIME Modft; /* File time type defined in NT, `last modified' time */ FILETIME Accft; /* NT file time type, `last access' time */ FILETIME Creft; /* NT file time type, `file creation' time */ HANDLE hFile = INVALID_HANDLE_VALUE; /* File handle defined in NT */ int gotTime; #ifdef NTSD_EAS uch *ebSDptr; unsigned ebSDlen; #endif #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(G.filename) + 1); INTERN_TO_ISO(G.filename, ansi_name); # define Ansi_Fname ansi_name #else # define Ansi_Fname G.filename #endif #ifndef __RSXNT__ if (IsWinNT()) { /* Truncate the file to the current position. * This is needed to remove excess allocation in case the * extraction has failed or stopped prematurely. */ SetEndOfFile((HANDLE)_get_osfhandle(fileno(G.outfile))); } #endif /* Close the file and then re-open it using the Win32 * CreateFile call, so that the file can be created * with GENERIC_WRITE access, otherwise the SetFileTime * call will fail. */ fclose(G.outfile); /* don't set the time stamp and attributes on standard output */ if (uO.cflag) return; /* skip restoring time stamps on user's request */ if (uO.D_flag <= 1) { gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft); /* open a handle to the file before processing extra fields; we do this in case new security on file prevents us from updating time stamps */ hFile = CreateFileA(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } else { gotTime = 0; } /* sfield@microsoft.com: set attributes before time in case we decide to support other filetime members later. This also allows us to apply attributes before the security is changed, which may prevent this from succeeding otherwise. Also, since most files don't have any interesting attributes, only change them if something other than FILE_ATTRIBUTE_ARCHIVE appears in the attributes. This works well as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the file anyway, when it's created new. */ if ((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) { if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F)) Info(slide, 1, ((char *)slide, "\nwarning (%d): could not set file attributes\n", (int)GetLastError())); } #ifdef NTSD_EAS /* set NTFS SD extra fields */ if (G.extra_field && /* zipfile extra field may have extended attribs */ FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length, &ebSDptr, &ebSDlen)) { int err = SetSD(__G__ Ansi_Fname, G.pInfo->file_attr, ebSDptr, ebSDlen); if (err == IZ_EF_TRUNC) { if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD), ebSDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), uO.qflag? "\n":"")); } } #endif /* NTSD_EAS */ /* skip restoring time stamps on user's request */ if (uO.D_flag <= 1) { if ( hFile == INVALID_HANDLE_VALUE ) Info(slide, 1, ((char *)slide, "\nCreateFile() error %d when trying set file time\n", (int)GetLastError())); else { if (gotTime) { FILETIME *pModft = (gotTime & EB_UT_FL_MTIME) ? &Modft : NULL; FILETIME *pAccft = (gotTime & EB_UT_FL_ATIME) ? &Accft : NULL; FILETIME *pCreft = (gotTime & EB_UT_FL_CTIME) ? &Creft : NULL; if (!SetFileTime(hFile, pCreft, pAccft, pModft)) Info(slide, 0, ((char *)slide, "\nSetFileTime failed: %d\n", (int)GetLastError())); } CloseHandle(hFile); } } return; #undef Ansi_Fname } /* end function close_outfile() */ #ifdef SET_DIR_ATTRIB int defer_dir_attribs(__G__ pd) __GDEF direntry **pd; { NTdirattr *d_entry; #ifdef NTSD_EAS uch *ebSDptr; unsigned ebSDlen; #endif /* Win9x does not support setting directory time stamps. */ if (!IsWinNT()) { *pd = (direntry *)NULL; return PK_OK; } #ifdef NTSD_EAS /* set extended attributes from extra fields */ if (G.extra_field && /* zipfile e.f. may have extended attribs */ FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length, &ebSDptr, &ebSDlen)) { /* ebSDlen contains the payload size of the e.f. block, but we store it including the e.b. header. */ ebSDlen += EB_HEADSIZE; } else { /* no NTSD e.f. block -> no space needed to allocate */ ebSDlen = 0; } #endif /* NTSD_EAS */ d_entry = (NTdirattr *)malloc(sizeof(NTdirattr) #ifdef NTSD_EAS + ebSDlen #endif + strlen(G.filename)); *pd = (direntry *)d_entry; if (d_entry == (NTdirattr *)NULL) { return PK_MEM; } #ifdef NTSD_EAS if (ebSDlen > 0) memcpy(d_entry->buf, ebSDptr, ebSDlen); d_entry->SDlen = ebSDlen; d_entry->fn = d_entry->buf + ebSDlen; #else d_entry->fn = d_entry->buf; #endif strcpy(d_entry->fn, G.filename); d_entry->perms = G.pInfo->file_attr; d_entry->gotTime = (uO.D_flag <= 0 ? getNTfiletime(__G__ &(d_entry->Modft), &(d_entry->Accft), &(d_entry->Creft)) : 0); return PK_OK; } /* end function defer_dir_attribs() */ int set_direc_attribs(__G__ d) __GDEF direntry *d; { int errval; HANDLE hFile = INVALID_HANDLE_VALUE; /* File handle defined in NT */ #ifdef __RSXNT__ char *ansi_name; #endif /* Win9x does not support setting directory time stamps. */ if (!IsWinNT()) return PK_OK; errval = PK_OK; #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ ansi_name = (char *)alloca(strlen(d->fn) + 1); INTERN_TO_ISO(d->fn, ansi_name); # define Ansi_Dirname ansi_name #else # define Ansi_Dirname d->fn #endif /* Skip restoring directory time stamps on user' request. */ if (uO.D_flag <= 0) { /* Open a handle to the directory before processing extra fields; we do this in case new security on file prevents us from updating time stamps. Although the WIN32 documentation recommends to use GENERIC_WRITE access flag to create the handle for SetFileTime(), this is too demanding for directories with the "read-only" attribute bit set. So we use the more specific flag FILE_WRITE_ATTRIBUTES here to request the minimum required access rights. (This problem is a Windows bug that has been silently fixed in Windows XP SP2.) */ hFile = CreateFileA(Ansi_Dirname, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #ifdef NTSD_EAS if (NtAtt(d)->SDlen > 0) { int err; if (QCOND2) { Info(slide, 1, ((char *)slide, " set attrib: %-22s ", FnFilter1(d->fn))); } /* set NTFS SD extra fields */ err = SetSD(__G__ Ansi_Dirname, NtAtt(d)->perms, NtAtt(d)->buf, NtAtt(d)->SDlen - EB_HEADSIZE); if (err == IZ_EF_TRUNC) { if (!QCOND2) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(d->fn))); Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD), NtAtt(d)->SDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n")); } else if (QCOND2) { Info(slide, 0, ((char *)slide, "\n")); } if (errval < err) errval = err; } #endif /* NTSD_EAS */ /* Skip restoring directory time stamps on user' request. */ if (uO.D_flag <= 0) { if (hFile == INVALID_HANDLE_VALUE) { Info(slide, 1, ((char *)slide, "warning: CreateFile() error %d (set file times for %s)\n", (int)GetLastError(), FnFilter1(d->fn))); if (!errval) errval = PK_WARN; } else { if (NtAtt(d)->gotTime) { FILETIME *pModft = (NtAtt(d)->gotTime & EB_UT_FL_MTIME) ? &(NtAtt(d)->Modft) : NULL; FILETIME *pAccft = (NtAtt(d)->gotTime & EB_UT_FL_ATIME) ? &(NtAtt(d)->Accft) : NULL; FILETIME *pCreft = (NtAtt(d)->gotTime & EB_UT_FL_CTIME) ? &(NtAtt(d)->Creft) : NULL; if (!SetFileTime(hFile, pCreft, pAccft, pModft)) { Info(slide, 0, ((char *)slide, "warning: SetFileTime() for %s error %d\n", FnFilter1(d->fn), (int)GetLastError())); if (!errval) errval = PK_WARN; } } CloseHandle(hFile); } } return errval; } /* end function set_direc_attribs() */ #endif /* SET_DIR_ATTRIB */ #ifdef TIMESTAMP /*************************/ /* Function stamp_file() */ /*************************/ int stamp_file(__GPRO__ ZCONST char *fname, time_t modtime) { FILETIME Modft; /* File time type defined in NT, `last modified' time */ HANDLE hFile; /* File handle defined in NT */ int errstat = 0; /* return status: 0 == "OK", -1 == "Failure" */ int fs_uses_loctime = FStampIsLocTime(__G__ fname); #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(fname) + 1); INTERN_TO_ISO(fname, ansi_name); # define Ansi_Fname ansi_name #else # define Ansi_Fname fname #endif /* open a handle to the file to prepare setting the mod-time stamp */ hFile = CreateFileA(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if ( hFile == INVALID_HANDLE_VALUE ) { errstat = -1; } else { /* convert time_t modtime into WIN32 native 64bit format */ UTIME_2_IZFILETIME(modtime, &Modft) /* set Access and Modification times of the file to modtime */ if (!SetFileTime(hFile, NULL, &Modft, &Modft)) { errstat = -1; } CloseHandle(hFile); } return errstat; #undef Ansi_Fname } /* end function stamp_file() */ #endif /* TIMESTAMP */ /***********************/ /* Function isfloppy() */ /* more precisely, is it removable? */ /***********************/ static int isfloppy(int nDrive) /* 1 == A:, 2 == B:, etc. */ { char rootPathName[4]; rootPathName[0] = (char)('A' + nDrive - 1); /* build the root path */ rootPathName[1] = ':'; /* name, e.g. "A:/" */ rootPathName[2] = '/'; rootPathName[3] = '\0'; return (GetDriveTypeA(rootPathName) == DRIVE_REMOVABLE); } /* end function isfloppy() */ /*****************************/ /* Function NTQueryVolInfo() */ /*****************************/ /* * Note: 8.3 limits on filenames apply only to old-style FAT filesystems. * More recent versions of Windows (Windows NT 3.5 / Windows 4.0) * can support long filenames (LFN) on FAT filesystems. Check the * filesystem maximum component length field to detect LFN support. */ static int NTQueryVolInfo(__GPRO__ const char *name) { /* static char lastRootPath[4] = ""; */ /* static int lastVolOldFAT; */ /* static int lastVolLocTim; */ char *tmp0; char tmp1[MAX_PATH], tmp2[MAX_PATH]; DWORD volSerNo, maxCompLen, fileSysFlags; #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(name) + 1); INTERN_TO_ISO(name, ansi_name); name = ansi_name; #endif if ((!strncmp(name, "//", 2) || !strncmp(name, "\\\\", 2)) && (name[2] != '\0' && name[2] != '/' && name[2] != '\\')) { /* GetFullPathname() and GetVolumeInformation() do not work * on UNC names. For now, we return "error". * **FIXME**: check if UNC name is mapped to a drive letter * and use mapped drive for volume info query. */ return FALSE; } if (isalpha((uch)name[0]) && (name[1] == ':')) tmp0 = (char *)name; else { if (!GetFullPathNameA(name, MAX_PATH, tmp1, &tmp0)) return FALSE; tmp0 = &tmp1[0]; } if (strncmp(G.lastRootPath, tmp0, 2) != 0) { /* For speed, we skip repeated queries for the same device */ strncpy(G.lastRootPath, tmp0, 2); /* Build the root path name, */ G.lastRootPath[2] = '/'; /* e.g. "A:/" */ G.lastRootPath[3] = '\0'; if (!GetVolumeInformationA((LPCSTR)G.lastRootPath, (LPSTR)tmp1, (DWORD)MAX_PATH, &volSerNo, &maxCompLen, &fileSysFlags, (LPSTR)tmp2, (DWORD)MAX_PATH)) { G.lastRootPath[0] = '\0'; return FALSE; } /* LFNs are available if the component length is > 12 */ G.lastVolOldFAT = (maxCompLen <= 12); /* G.lastVolOldFAT = !strncmp(strupr(tmp2), "FAT", 3); old version */ /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in * local time! */ G.lastVolLocTim = !strncmp(strupr(tmp2), "VFAT", 4) || !strncmp(tmp2, "HPFS", 4) || !strncmp(tmp2, "FAT", 3); } return TRUE; } /* end function NTQueryVolInfo() */ /*****************************/ /* Function IsVolumeOldFAT() */ /*****************************/ static int IsVolumeOldFAT(__GPRO__ const char *name) { return (NTQueryVolInfo(__G__ name) ? G.lastVolOldFAT : FALSE); } #ifndef SFX /************************/ /* Function do_wild() */ /* identical to OS/2 version */ /************************/ char *do_wild(__G__ wildspec) __GDEF ZCONST char *wildspec; /* only used first time on a given dir */ { /* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in w32cfg.h: static zDIR *wild_dir = NULL; static ZCONST char *wildname; static char *dirname, matchname[FILNAMSIZ]; static int notfirstcall=FALSE, have_dirname, dirnamelen; */ char *fnamestart; struct zdirent *file; /* Even when we're just returning wildspec, we *always* do so in * matchname[]--calling routine is allowed to append four characters * to the returned string, and wildspec may be a pointer to argv[]. */ if (!G.notfirstcall) { /* first call: must initialize everything */ G.notfirstcall = TRUE; if (!iswild(wildspec)) { strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; G.have_dirname = FALSE; G.wild_dir = NULL; return G.matchname; } /* break the wildspec into a directory part and a wildcard filename */ if ((G.wildname = MBSRCHR(wildspec, '/')) == (ZCONST char *)NULL && (G.wildname = MBSRCHR(wildspec, ':')) == (ZCONST char *)NULL) { G.dirname = "."; G.dirnamelen = 1; G.have_dirname = FALSE; G.wildname = wildspec; } else { ++G.wildname; /* point at character after '/' or ':' */ G.dirnamelen = G.wildname - wildspec; if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == NULL) { Info(slide, 1, ((char *)slide, "warning: cannot allocate wildcard buffers\n")); strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; return G.matchname; /* but maybe filespec was not a wildcard */ } strncpy(G.dirname, wildspec, G.dirnamelen); G.dirname[G.dirnamelen] = '\0'; /* terminate for strcpy below */ G.have_dirname = TRUE; } Trace((stderr, "do_wild: dirname = [%s]\n", FnFilter1(G.dirname))); if ((G.wild_dir = (zvoid *)Opendir(G.dirname)) != NULL) { if (G.have_dirname) { strcpy(G.matchname, G.dirname); fnamestart = G.matchname + G.dirnamelen; } else fnamestart = G.matchname; while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) { Trace((stderr, "do_wild: Readdir returns %s\n", FnFilter1(file->d_name))); strcpy(fnamestart, file->d_name); if (MBSRCHR(fnamestart, '.') == (char *)NULL) strcat(fnamestart, "."); if (match(fnamestart, G.wildname, TRUE WISEP) && /* skip "." and ".." directory entries */ strcmp(fnamestart, ".") && strcmp(fnamestart, "..")) { Trace((stderr, "do_wild: match() succeeds\n")); /* remove trailing dot */ fnamestart = plastchar(fnamestart, strlen(fnamestart)); if (*fnamestart == '.') *fnamestart = '\0'; return G.matchname; } } /* if we get to here directory is exhausted, so close it */ Closedir((zDIR *)G.wild_dir); G.wild_dir = NULL; } Trace((stderr, "do_wild: Opendir(%s) returns NULL\n", FnFilter1(G.dirname))); /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; return G.matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if (G.wild_dir == NULL) { G.notfirstcall = FALSE; /* reset for new wildspec */ if (G.have_dirname) free(G.dirname); return (char *)NULL; } /* If we've gotten this far, we've read and matched at least one entry * successfully (in a previous call), so dirname has been copied into * matchname already. */ if (G.have_dirname) { /* strcpy(G.matchname, G.dirname); */ fnamestart = G.matchname + G.dirnamelen; } else fnamestart = G.matchname; while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) { Trace((stderr, "do_wild: readdir returns %s\n", FnFilter1(file->d_name))); strcpy(fnamestart, file->d_name); if (MBSRCHR(fnamestart, '.') == (char *)NULL) strcat(fnamestart, "."); if (match(fnamestart, G.wildname, TRUE WISEP)) { Trace((stderr, "do_wild: match() succeeds\n")); /* remove trailing dot */ fnamestart = plastchar(fnamestart, strlen(fnamestart)); if (*fnamestart == '.') *fnamestart = '\0'; return G.matchname; } } Closedir((zDIR *)G.wild_dir); /* at least one entry read; nothing left */ G.wild_dir = NULL; G.notfirstcall = FALSE; /* reset for new wildspec */ if (G.have_dirname) free(G.dirname); return (char *)NULL; } /* end function do_wild() */ #endif /* !SFX */ /**********************/ /* Function mapattr() */ /**********************/ /* Identical to MS-DOS, OS/2 versions. However, NT has a lot of extra * permission stuff, so this function should probably be extended in the * future. */ int mapattr(__G) __GDEF { /* set archive bit for file entries (file is not backed up): */ G.pInfo->file_attr = ((unsigned)G.crec.external_file_attributes | (G.crec.external_file_attributes & FILE_ATTRIBUTE_DIRECTORY ? 0 : FILE_ATTRIBUTE_ARCHIVE)) & 0xff; return 0; } /* end function mapattr() */ /************************/ /* Function mapname() */ /************************/ int mapname(__G__ renamed) __GDEF int renamed; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - caution (truncated filename) * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) * MPN_ERR_SKIP - error -> skip entry * MPN_ERR_TOOLONG - error -> path is too long * MPN_NOMEM - error (memory allocation failed) -> skip entry * [also MPN_VOL_LABEL, MPN_CREATED_DIR] */ { char pathcomp[FILNAMSIZ]; /* path-component buffer */ char *pp, *cp=NULL; /* character pointers */ char *lastsemi = NULL; /* pointer to last semi-colon in pathcomp */ #ifdef ACORN_FTYPE_NFS char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ #endif int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ int error; register unsigned workch; /* hold the character being tested */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ /* can create path as long as not just freshening, or if user told us */ G.create_dirs = (!uO.fflag || renamed); G.created_dir = FALSE; /* not yet */ G.renamed_fullpath = FALSE; G.fnlen = strlen(G.filename); if (renamed) { cp = G.filename; /* point to beginning of renamed name... */ if (*cp) do { if (*cp == '\\') /* convert backslashes to forward */ *cp = '/'; } while (*PREINCSTR(cp)); cp = G.filename; /* use temporary rootpath if user gave full pathname */ if (G.filename[0] == '/') { G.renamed_fullpath = TRUE; pathcomp[0] = '/'; /* copy the '/' and terminate */ pathcomp[1] = '\0'; ++cp; } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') { G.renamed_fullpath = TRUE; pp = pathcomp; *pp++ = *cp++; /* copy the "d:" (+ '/', possibly) */ *pp++ = *cp++; if (*cp == '/') *pp++ = *cp++; /* otherwise add "./"? */ *pp = '\0'; } } /* pathcomp is ignored unless renamed_fullpath is TRUE: */ if ((error = checkdir(__G__ pathcomp, INIT)) != 0) /* init path buffer */ return error; /* ...unless no mem or vol label on hard disk */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (!renamed) { /* cp already set if renamed */ if (uO.jflag) /* junking directories */ cp = (char *)MBSRCHR(G.filename, '/'); if (cp == NULL) /* no '/' or not junking dirs */ cp = G.filename; /* point to internal zipfile-member pathname */ else ++cp; /* point to start of last component of path */ } /*--------------------------------------------------------------------------- Begin main loop through characters in filename. ---------------------------------------------------------------------------*/ for (; (workch = (uch)*cp) != 0; INCSTR(cp)) { switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; maskDOSdevice(__G__ pathcomp); if (strcmp(pathcomp, ".") == 0) { /* don't bother appending "./" to the path */ *pathcomp = '\0'; } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { /* "../" dir traversal detected, skip over it */ *pathcomp = '\0'; killed_ddot = TRUE; /* set "show message" flag */ } /* when path component is not empty, append it now */ if (*pathcomp != '\0' && ((error = checkdir(__G__ pathcomp, APPEND_DIR)) & MPN_MASK) > MPN_INF_TRUNC) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ break; case ':': /* drive spec not stored, so no colon allowed */ case '\\': /* '\\' may come as normal filename char (not */ case '<': /* dir sep char!) from unix-like file system */ case '>': /* no redirection symbols allowed either */ case '|': /* no pipe signs allowed */ case '"': /* no double quotes allowed */ case '?': /* no wildcards allowed */ case '*': *pp++ = '_'; /* these rules apply equally to FAT and NTFS */ break; case ';': /* start of VMS version? */ lastsemi = pp; /* remove VMS version later... */ *pp++ = ';'; /* but keep semicolon for now */ break; #ifdef ACORN_FTYPE_NFS case ',': /* NFS filetype extension */ lastcomma = pp; *pp++ = ','; /* keep for now; may need to remove */ break; /* later, if requested */ #endif case ' ': /* keep spaces unless specifically */ /* NT cannot create filenames with spaces on FAT volumes */ if (uO.sflag || IsVolumeOldFAT(__G__ G.filename)) *pp++ = '_'; else *pp++ = ' '; break; default: /* allow European characters in filenames: */ if (isprint(workch) || workch >= 127) #ifdef _MBCS { memcpy(pp, cp, CLEN(cp)); INCSTR(pp); } #else *pp++ = (char)workch; #endif } /* end switch */ } /* end while loop */ /* Show warning when stripping insecure "parent dir" path components */ if (killed_ddot && QCOND2) { Info(slide, 0, ((char *)slide, "warning: skipped \"../\" path component(s) in %s\n", FnFilter1(G.filename))); if (!(error & ~MPN_MASK)) error = (error & MPN_MASK) | PK_WARN; } /*--------------------------------------------------------------------------- Report if directory was created (and no file to create: filename ended in '/'), check name to be sure it exists, and combine path and name be- fore exiting. ---------------------------------------------------------------------------*/ if (lastchar(G.filename, G.fnlen) == '/') { #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(G.filename) + 1); INTERN_TO_ISO(G.filename, ansi_name); # define Ansi_Fname ansi_name #else # define Ansi_Fname G.filename #endif checkdir(__G__ G.filename, GETPATH); if (G.created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %-22s\n", FnFilter1(G.filename))); } /* set file attributes: The default for newly created directories is "DIR attribute flags set", so there is no need to change attributes unless one of the DOS style attribute flags is set. The readonly attribute need not be masked, since it does not prevent modifications in the new directory. */ if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) { if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F)) Info(slide, 1, ((char *)slide, "\nwarning (%d): could not set file attributes for %s\n", (int)GetLastError(), FnFilter1(G.filename))); } /* set dir time (note trailing '/') */ return (error & ~MPN_MASK) | MPN_CREATED_DIR; } else if (IS_OVERWRT_ALL) { /* overwrite attributes of existing directory on user's request */ /* set file attributes: */ if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) { if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F)) Info(slide, 1, ((char *)slide, "\nwarning (%d): could not set file attributes for %s\n", (int)GetLastError(), FnFilter1(G.filename))); } } /* dir existed already; don't look for data to extract */ return (error & ~MPN_MASK) | MPN_INF_SKIP; } *pp = '\0'; /* done with pathcomp: terminate it */ /* if not saving them, remove VMS version numbers (appended "###") */ if (!uO.V_flag && lastsemi) { pp = lastsemi + 1; /* semi-colon was kept: expect #'s after */ while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; } #ifdef ACORN_FTYPE_NFS /* translate Acorn filetype information if asked to do so */ if (uO.acorn_nfs_ext && (ef_spark = (RO_extra_block *) getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) != (RO_extra_block *)NULL) { /* file *must* have a RISC OS extra field */ long ft = (long)makelong(ef_spark->loadaddr); /*32-bit*/ if (lastcomma) { pp = lastcomma + 1; while (isxdigit((uch)(*pp))) ++pp; if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ } if ((ft & 1<<31)==0) ft=0x000FFD00; sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); } #endif /* ACORN_FTYPE_NFS */ maskDOSdevice(__G__ pathcomp); if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", FnFilter1(G.filename))); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ checkdir(__G__ G.filename, GETPATH); if (G.pInfo->vollabel) { /* set the volume label now */ char drive[4]; #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(G.filename) + 1); INTERN_TO_ISO(G.filename, ansi_name); # define Ansi_Fname ansi_name #else # define Ansi_Fname G.filename #endif /* Build a drive string, e.g. "b:" */ drive[0] = (char)('a' + G.nLabelDrive - 1); strcpy(drive + 1, ":\\"); if (QCOND2) Info(slide, 0, ((char *)slide, "labelling %s %-22s\n", drive, FnFilter1(G.filename))); if (!SetVolumeLabelA(drive, Ansi_Fname)) { Info(slide, 1, ((char *)slide, "mapname: error setting volume label\n")); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } /* success: skip the "extraction" quietly */ return (error & ~MPN_MASK) | MPN_INF_SKIP; #undef Ansi_Fname } Trace((stderr, "mapname returns with filename = [%s] (error = %d)\n\n", FnFilter1(G.filename), error)); return error; } /* end function mapname() */ /****************************/ /* Function maskDOSdevice() */ /****************************/ static void maskDOSdevice(__G__ pathcomp) __GDEF char *pathcomp; { /*--------------------------------------------------------------------------- Put an underscore in front of the file name if the file name is a DOS/WINDOWS device name like CON.*, AUX.*, PRN.*, etc. Trying to extract such a file would fail at best and wedge us at worst. ---------------------------------------------------------------------------*/ #if !defined(S_IFCHR) && defined(_S_IFCHR) # define S_IFCHR _S_IFCHR #endif #if !defined(S_ISCHR) # if defined(_S_ISCHR) # define S_ISCHR(m) _S_ISCHR(m) # elif defined(S_IFCHR) # define S_ISCHR(m) ((m) & S_IFCHR) # endif #endif #ifdef DEBUG if (zstat(pathcomp, &G.statbuf) == 0) { Trace((stderr, "maskDOSdevice() stat(\"%s\", buf) st_mode result: %X, %o\n", FnFilter1(pathcomp), G.statbuf.st_mode, G.statbuf.st_mode)); } else { Trace((stderr, "maskDOSdevice() stat(\"%s\", buf) failed\n", FnFilter1(pathcomp))); } #endif if (zstat(pathcomp, &G.statbuf) == 0 && S_ISCHR(G.statbuf.st_mode)) { extent i; /* pathcomp contains a name of a DOS character device (builtin or * installed device driver). * Prepend a '_' to allow creation of the item in the file system. */ for (i = strlen(pathcomp) + 1; i > 0; --i) pathcomp[i] = pathcomp[i - 1]; pathcomp[0] = '_'; } } /* end function maskDOSdevice() */ /**********************/ /* Function map2fat() */ /* Not quite identical to OS/2 version */ /**********************/ static void map2fat(pathcomp, pEndFAT) char *pathcomp, **pEndFAT; { char *ppc = pathcomp; /* variable pointer to pathcomp */ char *pEnd = *pEndFAT; /* variable pointer to buildpathFAT */ char *pBegin = *pEndFAT; /* constant pointer to start of this comp. */ char *last_dot = NULL; /* last dot not converted to underscore */ register unsigned workch; /* hold the character being tested */ /* Only need check those characters which are legal in NTFS but not * in FAT: to get here, must already have passed through mapname. * Also must truncate path component to ensure 8.3 compliance. */ while ((workch = (uch)*ppc++) != 0) { switch (workch) { case '[': case ']': case '+': case ',': case ';': case '=': *pEnd++ = '_'; /* convert brackets to underscores */ break; case '.': if (pEnd == *pEndFAT) { /* nothing appended yet... */ if (*ppc == '\0') /* don't bother appending a */ break; /* "./" component to the path */ else if (*ppc == '.' && ppc[1] == '\0') { /* "../" */ *pEnd++ = '.'; /* add first dot, */ *pEnd++ = '.'; /* add second dot, and */ ++ppc; /* skip over to pathcomp's end */ } else { /* FAT doesn't allow null filename */ *pEnd++ = '_'; /* bodies, so map .exrc -> _exrc */ } /* (_.exr would keep max 3 chars) */ } else { /* found dot within path component */ last_dot = pEnd; /* point at last dot so far... */ *pEnd++ = '_'; /* convert to underscore for now */ } break; default: *pEnd++ = (char)workch; } /* end switch */ } /* end while loop */ *pEnd = '\0'; /* terminate buildpathFAT */ /* NOTE: keep in mind that pEnd points to the end of the path * component, and *pEndFAT still points to the *beginning* of it... * Also note that the algorithm does not try to get too fancy: * if there are no dots already, the name either gets truncated * at 8 characters or the last underscore is converted to a dot * (only if more characters are saved that way). In no case is * a dot inserted between existing characters. */ if (last_dot == NULL) { /* no dots: check for underscores... */ char *plu = MBSRCHR(pBegin, '_'); /* pointer to last underscore */ if ((plu != NULL) && /* found underscore: convert to dot? */ (MIN(plu - pBegin, 8) + MIN(pEnd - plu - 1, 3) > 8)) { last_dot = plu; /* be lazy: drop through to next if-blk */ } else if ((pEnd - *pEndFAT) > 8) { /* no underscore; or converting underscore to dot would save less chars than leaving everything in the basename */ *pEndFAT += 8; /* truncate at 8 chars */ **pEndFAT = '\0'; } else *pEndFAT = pEnd; /* whole thing fits into 8 chars or less */ } if (last_dot != NULL) { /* one dot is OK: */ *last_dot = '.'; /* put it back in */ if ((last_dot - pBegin) > 8) { char *p, *q; int i; p = last_dot; q = last_dot = pBegin + 8; for (i = 0; (i < 4) && *p; ++i) /* too many chars in basename: */ *q++ = *p++; /* shift .ext left and trun- */ *q = '\0'; /* cate/terminate it */ *pEndFAT = q; } else if ((pEnd - last_dot) > 4) { /* too many chars in extension */ *pEndFAT = last_dot + 4; **pEndFAT = '\0'; } else *pEndFAT = pEnd; /* filename is fine; point at terminating zero */ if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ') last_dot[-1] = '_'; /* NO blank in front of '.'! */ } } /* end function map2fat() */ /***********************/ /* Borrowed from os2.c for UnZip 5.1. */ /* Function checkdir() */ /* Difference: no EA stuff */ /***********************/ /* HPFS stuff works on NTFS too */ int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename * MPN_INF_SKIP - path doesn't exist, not allowed to create * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path * exists and is not a directory, but is supposed to be * MPN_ERR_TOOLONG - path is too long * MPN_NOMEM - can't allocate memory for filename buffers */ { /* static int rootlen = 0; */ /* length of rootpath */ /* static char *rootpath; */ /* user's "extract-to" directory */ /* static char *buildpathHPFS; */ /* full path (so far) to extracted file, */ /* static char *buildpathFAT; */ /* both HPFS/EA (main) and FAT versions */ /* static char *endHPFS; */ /* corresponding pointers to end of */ /* static char *endFAT; */ /* buildpath ('\0') */ # define FN_MASK 7 # define FUNCTION (flag & FN_MASK) /*--------------------------------------------------------------------------- APPEND_DIR: append the path component to the path being built and check for its existence. If doesn't exist and we are creating directories, do so for this one; else signal success or error as appropriate. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_DIR) { char *p = pathcomp; int too_long = FALSE; Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); while ((*G.endHPFS = *p++) != '\0') /* copy to HPFS filename */ ++G.endHPFS; if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) { p = pathcomp; while ((*G.endFAT = *p++) != '\0') /* copy to FAT filename, too */ ++G.endFAT; } else map2fat(pathcomp, &G.endFAT); /* map into FAT fn, update endFAT */ /* GRR: could do better check, see if overrunning buffer as we go: * check endHPFS-buildpathHPFS after each append, set warning variable * if within 20 of FILNAMSIZ; then if var set, do careful check when * appending. Clear variable when begin new path. */ /* next check: need to append '/', at least one-char name, '\0' */ if ((G.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3) too_long = TRUE; /* check if extracting dir? */ #ifdef FIX_STAT_BUG /* Borland C++ 5.0 does not handle a call to stat() well if the * directory does not exist (it tends to crash in strange places.) * This is apparently a problem only when compiling for GUI rather * than console. The code below attempts to work around this problem. */ if (access(G.buildpathFAT, 0) != 0) { if (!G.create_dirs) { /* told not to create (freshening) */ free(G.buildpathHPFS); free(G.buildpathFAT); /* path doesn't exist: nothing to do */ return MPN_INF_SKIP; } if (too_long) { /* GRR: should allow FAT extraction w/o EAs */ Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpathHPFS))); free(G.buildpathHPFS); free(G.buildpathFAT); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ %s\n\ unable to process %s.\n", FnFilter2(G.buildpathFAT), strerror(errno), FnFilter1(G.filename))); free(G.buildpathHPFS); free(G.buildpathFAT); /* path didn't exist, tried to create, failed */ return MPN_ERR_SKIP; } G.created_dir = TRUE; } #endif /* FIX_STAT_BUG */ if (SSTAT(G.buildpathFAT, &G.statbuf)) /* path doesn't exist */ { if (!G.create_dirs) { /* told not to create (freshening) */ free(G.buildpathHPFS); free(G.buildpathFAT); /* path doesn't exist: nothing to do */ return MPN_INF_SKIP; } if (too_long) { /* GRR: should allow FAT extraction w/o EAs */ Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpathHPFS))); free(G.buildpathHPFS); free(G.buildpathFAT); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ %s\n\ unable to process %s.\n", FnFilter2(G.buildpathFAT), strerror(errno), FnFilter1(G.filename))); free(G.buildpathHPFS); free(G.buildpathFAT); /* path didn't exist, tried to create, failed */ return MPN_ERR_SKIP; } G.created_dir = TRUE; } else if (!S_ISDIR(G.statbuf.st_mode)) { Info(slide, 1, ((char *)slide, "checkdir error: %s exists but is not directory\n\ unable to process %s.\n", FnFilter2(G.buildpathFAT), FnFilter1(G.filename))); free(G.buildpathHPFS); free(G.buildpathFAT); /* path existed but wasn't dir */ return MPN_ERR_SKIP; } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpathHPFS))); free(G.buildpathHPFS); free(G.buildpathFAT); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } *G.endHPFS++ = '/'; *G.endFAT++ = '/'; *G.endHPFS = *G.endFAT = '\0'; Trace((stderr, "buildpathHPFS now = [%s]\nbuildpathFAT now = [%s]\n", FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT))); return MPN_OK; } /* end if (FUNCTION == APPEND_DIR) */ /*--------------------------------------------------------------------------- GETPATH: copy full FAT path to the string pointed at by pathcomp (want filename to reflect name used on disk, not EAs; if full path is HPFS, buildpathFAT and buildpathHPFS will be identical). Also free both paths. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { Trace((stderr, "getting and freeing FAT path [%s]\n", FnFilter1(G.buildpathFAT))); Trace((stderr, "freeing HPFS path [%s]\n", FnFilter1(G.buildpathHPFS))); strcpy(pathcomp, G.buildpathFAT); free(G.buildpathFAT); free(G.buildpathHPFS); G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL; return MPN_OK; } /*--------------------------------------------------------------------------- APPEND_NAME: assume the path component is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) { char *p = pathcomp; int error = MPN_OK; Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); /* The buildpathHPFS buffer has been allocated large enough to * hold the complete combined name, so there is no need to check * for OS filename size limit overflow within the copy loop. */ while ((*G.endHPFS = *p++) != '\0') { /* copy to HPFS filename */ ++G.endHPFS; } /* Now, check for OS filename size overflow. When detected, the * mapped HPFS name is truncated and a warning message is shown. */ if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) { G.buildpathHPFS[FILNAMSIZ-1] = '\0'; Info(slide, 1, ((char *)slide, "checkdir warning: path too long; truncating\n \ %s\n -> %s\n", FnFilter1(G.filename), FnFilter2(G.buildpathHPFS))); error = MPN_INF_TRUNC; /* filename truncated */ } /* The buildpathFAT buffer has the same allocated size as the * buildpathHPFS buffer, so there is no need for an overflow check * within the following copy loop, either. */ if (G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) { /* copy to FAT filename, too */ p = pathcomp; while ((*G.endFAT = *p++) != '\0') ++G.endFAT; } else /* map into FAT fn, update endFAT */ map2fat(pathcomp, &G.endFAT); /* Check that the FAT path does not exceed the FILNAMSIZ limit, and * truncate when neccessary. * Note that truncation can only happen when the HPFS path (which is * never shorter than the FAT path) has been already truncated. * So, emission of the warning message and setting the error code * has already happened. */ if ((G.endFAT-G.buildpathFAT) >= FILNAMSIZ) G.buildpathFAT[FILNAMSIZ-1] = '\0'; Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n", FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT))); return error; /* could check for existence, prompt for new name... */ } /* end if (FUNCTION == APPEND_NAME) */ /*--------------------------------------------------------------------------- INIT: allocate and initialize buffer space for the file currently being extracted. If file was renamed with an absolute path, don't prepend the extract-to path. ---------------------------------------------------------------------------*/ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpathHPFS and buildpathFAT to ")); #ifdef ACORN_FTYPE_NFS if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+ (uO.acorn_nfs_ext ? 5 : 1))) #else if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1)) #endif == NULL) return MPN_NOMEM; #ifdef ACORN_FTYPE_NFS if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+ (uO.acorn_nfs_ext ? 5 : 1))) #else if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1)) #endif == NULL) { free(G.buildpathHPFS); return MPN_NOMEM; } if (G.pInfo->vollabel) { /* use root or renamed path, but don't store */ /* GRR: for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */ if (G.renamed_fullpath && pathcomp[1] == ':') *G.buildpathHPFS = (char)ToLower(*pathcomp); else if (!G.renamed_fullpath && G.rootlen > 1 && G.rootpath[1] == ':') *G.buildpathHPFS = (char)ToLower(*G.rootpath); else { char tmpN[MAX_PATH], *tmpP; if (GetFullPathNameA(".", MAX_PATH, tmpN, &tmpP) > MAX_PATH) { /* by definition of MAX_PATH we should never get here */ Info(slide, 1, ((char *)slide, "checkdir warning: current dir path too long\n")); return MPN_INF_TRUNC; /* can't get drive letter */ } G.nLabelDrive = *tmpN - 'a' + 1; *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a'); } G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */ if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */ || (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */ free(G.buildpathHPFS); free(G.buildpathFAT); return MPN_VOL_LABEL; /* skipping with message */ } *G.buildpathHPFS = '\0'; } else if (G.renamed_fullpath) /* pathcomp = valid data */ strcpy(G.buildpathHPFS, pathcomp); else if (G.rootlen > 0) strcpy(G.buildpathHPFS, G.rootpath); else *G.buildpathHPFS = '\0'; G.endHPFS = G.buildpathHPFS; G.endFAT = G.buildpathFAT; while ((*G.endFAT = *G.endHPFS) != '\0') { ++G.endFAT; ++G.endHPFS; } Trace((stderr, "[%s]\n", FnFilter1(G.buildpathHPFS))); return MPN_OK; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in rootpath and create it if neces- sary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. Note that under OS/2 and MS-DOS, if a candidate extract-to directory specification includes a drive letter (leading "x:"), it is treated just as if it had a trailing '/'--that is, one directory level will be created if the path doesn't exist, unless this is otherwise pro- hibited (e.g., freshening). ---------------------------------------------------------------------------*/ #if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", FnFilter1(pathcomp))); if (pathcomp == NULL) { G.rootlen = 0; return MPN_OK; } if (G.rootlen > 0) /* rootpath was already set, nothing to do */ return MPN_OK; if ((G.rootlen = strlen(pathcomp)) > 0) { int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE; char *tmproot; if ((tmproot = (char *)malloc(G.rootlen+3)) == (char *)NULL) { G.rootlen = 0; return MPN_NOMEM; } strcpy(tmproot, pathcomp); if (isalpha((uch)tmproot[0]) && tmproot[1] == ':') has_drive = TRUE; /* drive designator */ if (tmproot[G.rootlen-1] == '/' || tmproot[G.rootlen-1] == '\\') { tmproot[--G.rootlen] = '\0'; had_trailing_pathsep = TRUE; } if (has_drive && (G.rootlen == 2)) { if (!had_trailing_pathsep) /* i.e., original wasn't "x:/" */ add_dot = TRUE; /* relative path: add '.' before '/' */ } else if (G.rootlen > 0) { /* need not check "x:." and "x:/" */ if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) { /* path does not exist */ if (!G.create_dirs /* || iswild(tmproot) */ ) { free(tmproot); G.rootlen = 0; /* treat as stored file */ return MPN_INF_SKIP; } /* create directory (could add loop here scanning tmproot * to create more than one level, but really necessary?) */ if (MKDIR(tmproot, 0777) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory: %s\n", FnFilter1(tmproot))); free(tmproot); G.rootlen = 0; /* path didn't exist, tried to create, failed: */ /* file exists, or need 2+ subdir levels */ return MPN_ERR_SKIP; } } } if (add_dot) /* had just "x:", make "x:." */ tmproot[G.rootlen++] = '.'; tmproot[G.rootlen++] = '/'; tmproot[G.rootlen] = '\0'; if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) { free(tmproot); G.rootlen = 0; return MPN_NOMEM; } Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath))); } return MPN_OK; } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (G.rootlen > 0) { free(G.rootpath); G.rootlen = 0; } return MPN_OK; } return MPN_INVALID; /* should never reach */ } /* end function checkdir() */ #ifndef SFX /*************************/ /* Function dateformat() */ /*************************/ int dateformat() { char df[2]; /* LOCALE_IDATE has a maximum value of 2 */ if (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IDATE, df, 2) != 0) { switch (df[0]) { case '0': return DF_MDY; case '1': return DF_DMY; case '2': return DF_YMD; } } return DF_MDY; } /****************************/ /* Function dateseparator() */ /****************************/ char dateseparator() { char df[2]; /* use only if it is one character */ if ((GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDATE, df, 2) != 0) && (df[0] != '\0')) return df[0]; else return '-'; } #ifndef WINDLL /************************/ /* Function version() */ /************************/ void version(__G) __GDEF { int len; #if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DJGPP__)) char buf[80]; #if (defined(_MSC_VER) && (_MSC_VER > 900)) char buf2[80]; #endif #endif len = sprintf((char *)slide, CompiledWith, #if defined(_MSC_VER) /* MSC == VC++, but what about SDK compiler? */ (sprintf(buf, "Microsoft C %d.%02d ", _MSC_VER/100, _MSC_VER%100), buf), # if (_MSC_VER == 800) "(Visual C++ v1.1)", # elif (_MSC_VER == 850) "(Windows NT v3.5 SDK)", # elif (_MSC_VER == 900) "(Visual C++ v2.x)", # elif (_MSC_VER > 900) (sprintf(buf2, "(Visual C++ %d.%d)", _MSC_VER/100 - 6, _MSC_VER%100/10), buf2), # else "(bad version)", # endif #elif defined(__WATCOMC__) # if (__WATCOMC__ % 10 > 0) (sprintf(buf, "Watcom C/C++ %d.%02d", __WATCOMC__ / 100, __WATCOMC__ % 100), buf), "", # else (sprintf(buf, "Watcom C/C++ %d.%d", __WATCOMC__ / 100, (__WATCOMC__ % 100) / 10), buf), "", # endif #elif defined(__BORLANDC__) "Borland C++", # if (__BORLANDC__ < 0x0200) " 1.0", # elif (__BORLANDC__ == 0x0200) " 2.0", # elif (__BORLANDC__ == 0x0400) " 3.0", # elif (__BORLANDC__ == 0x0410) /* __TURBOC__ = 0x0310 */ " 3.1", # elif (__BORLANDC__ == 0x0452) /* __TURBOC__ = 0x0320 */ " 4.0 or 4.02", # elif (__BORLANDC__ == 0x0460) /* __TURBOC__ = 0x0340 */ " 4.5", # elif (__BORLANDC__ == 0x0500) /* __TURBOC__ = 0x0340 */ " 5.0", # elif (__BORLANDC__ == 0x0520) /* __TURBOC__ = 0x0520 */ " 5.2 (C++ Builder 1.0)", # elif (__BORLANDC__ == 0x0530) /* __TURBOC__ = 0x0530 */ " 5.3 (C++ Builder 3.0)", # elif (__BORLANDC__ == 0x0540) /* __TURBOC__ = 0x0540 */ " 5.4 (C++ Builder 4.0)", # elif (__BORLANDC__ == 0x0550) /* __TURBOC__ = 0x0550 */ " 5.5 (C++ Builder 5.0)", # elif (__BORLANDC__ == 0x0551) /* __TURBOC__ = 0x0551 */ " 5.5.1 (C++ Builder 5.0.1)", # elif (__BORLANDC__ == 0x0560) /* __TURBOC__ = 0x0560 */ " 6.0 (C++ Builder 6.0)", # else " later than 6.0", # endif #elif defined(__LCC__) "LCC-Win32", "", #elif defined(__GNUC__) # if defined(__RSXNT__) # if (defined(__DJGPP__) && !defined(__EMX__)) (sprintf(buf, "rsxnt(djgpp v%d.%02d) / gcc ", __DJGPP__, __DJGPP_MINOR__), buf), # elif defined(__DJGPP__) (sprintf(buf, "rsxnt(emx+djgpp v%d.%02d) / gcc ", __DJGPP__, __DJGPP_MINOR__), buf), # elif (defined(__GO32__) && !defined(__EMX__)) "rsxnt(djgpp v1.x) / gcc ", # elif defined(__GO32__) "rsxnt(emx + djgpp v1.x) / gcc ", # elif defined(__EMX__) "rsxnt(emx)+gcc ", # else "rsxnt(unknown) / gcc ", # endif # elif defined(__CYGWIN__) "cygnus win32 / gcc ", # elif defined(__MINGW32__) "mingw32 / gcc ", # else "gcc ", # endif __VERSION__, #else /* !_MSC_VER, !__WATCOMC__, !__BORLANDC__, !__LCC__, !__GNUC__ */ "unknown compiler (SDK?)", "", #endif /* ?compilers */ "\nWindows 9x / Windows NT/2K/XP/2K3", " (32-bit)", #ifdef __DATE__ " on ", __DATE__ #else "", "" #endif ); (*G.message)((zvoid *)&G, slide, (ulg)len, 0); return; } /* end function version() */ #endif /* !WINDLL */ #endif /* !SFX */ #ifdef MORE int screensize(int *tt_rows, int *tt_cols) { HANDLE hstdout; CONSOLE_SCREEN_BUFFER_INFO scr; hstdout = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(hstdout, &scr); if (tt_rows != NULL) *tt_rows = scr.srWindow.Bottom - scr.srWindow.Top + 1; if (tt_cols != NULL) *tt_cols = scr.srWindow.Right - scr.srWindow.Left + 1; return 0; /* signal success */ } #endif /* MORE */ #ifdef W32_STAT_BANDAID /* All currently known variants of WIN32 operating systems (Windows 95/98, * WinNT 3.x, 4.0, 5.x) have a nasty bug in the OS kernel concerning * conversions between UTC and local time: In the time conversion functions * of the Win32 API, the timezone offset (including seasonal daylight saving * shift) between UTC and local time evaluation is erratically based on the * current system time. The correct evaluation must determine the offset * value as it {was/is/will be} for the actual time to be converted. * * Newer versions of MS C runtime lib's stat() returns utc time-stamps so * that localtime(timestamp) corresponds to the (potentially false) local * time shown by the OS' system programs (Explorer, command shell dir, etc.) * The RSXNT port follows the same strategy, but fails to recognize the * access-time attribute. * * For the NTFS file system (and other filesystems that store time-stamps * as UTC values), this results in st_mtime (, st_{c|a}time) fields which * are not stable but vary according to the seasonal change of "daylight * saving time in effect / not in effect". * * Other C runtime libs (CygWin), or the crtdll.dll supplied with Win9x/NT * return the unix-time equivalent of the UTC FILETIME values as got back * from the Win32 API call. This time, return values from NTFS are correct * whereas utimes from files on (V)FAT volumes vary according to the DST * switches. * * To achieve timestamp consistency of UTC (UT extra field) values in * Zip archives, the Info-ZIP programs require work-around code for * proper time handling in stat() (and other time handling routines). * * However, nowadays most other programs on Windows systems use the * time conversion strategy of Microsofts C runtime lib "msvcrt.dll". * To improve interoperability in environments where a "consistent" (but * false) "UTC<-->LocalTime" conversion is preferred over "stable" time * stamps, the Info-ZIP specific time conversion handling can be * deactivated by defining the preprocessor flag NO_W32TIMES_IZFIX. */ /* stat() functions under Windows95 tend to fail for root directories. * * Watcom and Borland, at least, are affected by this bug. Watcom made * * a partial fix for 11.0 but still missed some cases. This substitute * * detects the case and fills in reasonable values. Otherwise we get * * effects like failure to extract to a root dir because it's not found. */ int zstat_win32(__W32STAT_GLOBALS__ const char *path, z_stat *buf) { if (!zstat(path, buf)) { /* stat was successful, now redo the time-stamp fetches */ #ifndef NO_W32TIMES_IZFIX int fs_uses_loctime = FStampIsLocTime(__G__ path); #endif HANDLE h; FILETIME Modft, Accft, Creft; #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_path = (char *)alloca(strlen(path) + 1); INTERN_TO_ISO(path, ansi_path); # define Ansi_Path ansi_path #else # define Ansi_Path path #endif TTrace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime)); h = CreateFileA(Ansi_Path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h != INVALID_HANDLE_VALUE) { BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft); CloseHandle(h); if (ftOK) { FTTrace((stdout, "GetFileTime returned Modft", 0, &Modft)); FTTrace((stdout, "GetFileTime returned Creft", 0, &Creft)); #ifndef NO_W32TIMES_IZFIX if (!fs_uses_loctime) { /* On a filesystem that stores UTC timestamps, we refill * the time fields of the struct stat buffer by directly * using the UTC values as returned by the Win32 * GetFileTime() API call. */ NtfsFileTime2utime(&Modft, &(buf->st_mtime)); if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0) NtfsFileTime2utime(&Accft, &(buf->st_atime)); else buf->st_atime = buf->st_mtime; if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0) NtfsFileTime2utime(&Creft, &(buf->st_ctime)); else buf->st_ctime = buf->st_mtime; TTrace((stdout,"NTFS, recalculated modtime %08lx\n", buf->st_mtime)); } else #endif /* NO_W32TIMES_IZFIX */ { /* On VFAT and FAT-like filesystems, the FILETIME values * are converted back to the stable local time before * converting them to UTC unix time-stamps. */ VFatFileTime2utime(&Modft, &(buf->st_mtime)); if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0) VFatFileTime2utime(&Accft, &(buf->st_atime)); else buf->st_atime = buf->st_mtime; if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0) VFatFileTime2utime(&Creft, &(buf->st_ctime)); else buf->st_ctime = buf->st_mtime; TTrace((stdout, "VFAT, recalculated modtime %08lx\n", buf->st_mtime)); } } } # undef Ansi_Path return 0; } #ifdef W32_STATROOT_FIX else { DWORD flags; #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_path = (char *)alloca(strlen(path) + 1); INTERN_TO_ISO(path, ansi_path); # define Ansi_Path ansi_path #else # define Ansi_Path path #endif flags = GetFileAttributesA(Ansi_Path); if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) { Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n", FnFilter1(path))); memset(buf, 0, sizeof(z_stat)); buf->st_atime = buf->st_ctime = buf->st_mtime = dos_to_unix_time(DOSTIME_MINIMUM); /* 1-1-80 */ buf->st_mode = S_IFDIR | S_IREAD | ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE); return 0; } /* assumes: stat() won't fail on non-dirs without good reason */ # undef Ansi_Path } #endif /* W32_STATROOT_FIX */ return -1; } #endif /* W32_STAT_BANDAID */ #ifdef W32_USE_IZ_TIMEZONE #include "timezone.h" #define SECSPERMIN 60 #define MINSPERHOUR 60 #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) static void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule); static void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule) { if (lpw32tm->wYear != 0) { ptrule->r_type = JULIAN_DAY; ptrule->r_day = ydays[lpw32tm->wMonth - 1] + lpw32tm->wDay; } else { ptrule->r_type = MONTH_NTH_DAY_OF_WEEK; ptrule->r_mon = lpw32tm->wMonth; ptrule->r_day = lpw32tm->wDayOfWeek; ptrule->r_week = lpw32tm->wDay; } ptrule->r_time = (long)lpw32tm->wHour * SECSPERHOUR + (long)(lpw32tm->wMinute * SECSPERMIN) + (long)lpw32tm->wSecond; } int GetPlatformLocalTimezone(register struct state * ZCONST sp, void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res, ZCONST struct rule * ZCONST start, ZCONST struct rule * ZCONST end)) { TIME_ZONE_INFORMATION tzinfo; DWORD res; /* read current timezone settings from registry if TZ envvar missing */ res = GetTimeZoneInformation(&tzinfo); if (res != TIME_ZONE_ID_INVALID) { struct rule startrule, stoprule; conv_to_rule(&(tzinfo.StandardDate), &stoprule); conv_to_rule(&(tzinfo.DaylightDate), &startrule); sp->timecnt = 0; sp->ttis[0].tt_abbrind = 0; if ((sp->charcnt = WideCharToMultiByte(CP_ACP, 0, tzinfo.StandardName, -1, sp->chars, sizeof(sp->chars), NULL, NULL)) == 0) sp->chars[sp->charcnt++] = '\0'; sp->ttis[1].tt_abbrind = sp->charcnt; sp->charcnt += WideCharToMultiByte(CP_ACP, 0, tzinfo.DaylightName, -1, sp->chars + sp->charcnt, sizeof(sp->chars) - sp->charcnt, NULL, NULL); if ((sp->charcnt - sp->ttis[1].tt_abbrind) == 0) sp->chars[sp->charcnt++] = '\0'; sp->ttis[0].tt_gmtoff = - (tzinfo.Bias + tzinfo.StandardBias) * MINSPERHOUR; sp->ttis[1].tt_gmtoff = - (tzinfo.Bias + tzinfo.DaylightBias) * MINSPERHOUR; sp->ttis[0].tt_isdst = 0; sp->ttis[1].tt_isdst = 1; sp->typecnt = (startrule.r_mon == 0 && stoprule.r_mon == 0) ? 1 : 2; if (sp->typecnt > 1) (*fill_tzstate_from_rules)(sp, &startrule, &stoprule); return TRUE; } return FALSE; } #endif /* W32_USE_IZ_TIMEZONE */ #endif /* !FUNZIP */ #ifndef WINDLL /* This replacement getch() function was originally created for Watcom C * and then additionally used with CYGWIN. Since UnZip 5.4, all other Win32 * ports apply this replacement rather that their supplied getch() (or * alike) function. There are problems with unabsorbed LF characters left * over in the keyboard buffer under Win95 (and 98) when ENTER was pressed. * (Under Win95, ENTER returns two(!!) characters: CR-LF.) This problem * does not appear when run on a WinNT console prompt! */ /* Watcom 10.6's getch() does not handle Alt+. */ /* Note that if PASSWD_FROM_STDIN is defined, the file containing */ /* the password must have a carriage return after the word, not a */ /* Unix-style newline (linefeed only). This discards linefeeds. */ int getch_win32(void) { HANDLE stin; DWORD rc; unsigned char buf[2]; int ret = -1; DWORD odemode = ~(DWORD)0; # ifdef PASSWD_FROM_STDIN stin = GetStdHandle(STD_INPUT_HANDLE); # else stin = CreateFileA("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (stin == INVALID_HANDLE_VALUE) return -1; # endif if (GetConsoleMode(stin, &odemode)) SetConsoleMode(stin, ENABLE_PROCESSED_INPUT); /* raw except ^C noticed */ if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1) ret = buf[0]; /* when the user hits return we get CR LF. We discard the LF, not the CR, * because when we call this for the first time after a previous input * such as the one for "replace foo? [y]es, ..." the LF may still be in * the input stream before whatever the user types at our prompt. */ if (ret == '\n') if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1) ret = buf[0]; if (odemode != ~(DWORD)0) SetConsoleMode(stin, odemode); # ifndef PASSWD_FROM_STDIN CloseHandle(stin); # endif return ret; } #endif /* !WINDLL */ #if (defined(UNICODE_SUPPORT) && !defined(FUNZIP)) /* convert wide character string to multi-byte character string */ char *wide_to_local_string(wide_string, escape_all) ZCONST zwchar *wide_string; int escape_all; { int i; wchar_t wc; int bytes_char; int default_used; int wsize = 0; int max_bytes = 9; char buf[9]; char *buffer = NULL; char *local_string = NULL; for (wsize = 0; wide_string[wsize]; wsize++) ; if (max_bytes < MB_CUR_MAX) max_bytes = MB_CUR_MAX; if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) { return NULL; } /* convert it */ buffer[0] = '\0'; for (i = 0; i < wsize; i++) { if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) { /* wchar_t probably 2 bytes */ /* could do surrogates if state_dependent and wctomb can do */ wc = zwchar_to_wchar_t_default_char; } else { wc = (wchar_t)wide_string[i]; } /* Unter some vendor's C-RTL, the Wide-to-MultiByte conversion functions * (like wctomb() et. al.) do not use the same codepage as the other * string arguments I/O functions (fopen, mkdir, rmdir etc.). * Therefore, we have to fall back to the underlying Win32-API call to * achieve a consistent behaviour for all supported compiler environments. * Failing RTLs are for example: * Borland (locale uses OEM-CP as default, but I/O functions expect ANSI * names) * Watcom (only "C" locale, wctomb() always uses OEM CP) * (in other words: all supported environments except the Microsoft RTLs) */ bytes_char = WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK, &wc, 1, (LPSTR)buf, sizeof(buf), NULL, &default_used); if (default_used) bytes_char = -1; if (escape_all) { if (bytes_char == 1 && (uch)buf[0] <= 0x7f) { /* ASCII */ strncat(buffer, buf, 1); } else { /* use escape for wide character */ char *escape_string = wide_to_escape_string(wide_string[i]); strcat(buffer, escape_string); free(escape_string); } } else if (bytes_char > 0) { /* multi-byte char */ strncat(buffer, buf, bytes_char); } else { /* no MB for this wide */ /* use escape for wide character */ char *escape_string = wide_to_escape_string(wide_string[i]); strcat(buffer, escape_string); free(escape_string); } } if ((local_string = (char *)realloc(buffer, strlen(buffer) + 1)) == NULL) { free(buffer); return NULL; } return local_string; } #if 0 wchar_t *utf8_to_wchar_string(utf8_string) char *utf8_string; /* path to get utf-8 name for */ { wchar_t *qw; int ulen; int ulenw; if (utf8_string == NULL) return NULL; /* get length */ ulenw = MultiByteToWideChar( CP_UTF8, /* UTF-8 code page */ 0, /* flags for character-type options */ utf8_string, /* string to convert */ -1, /* string length (-1 = NULL terminated) */ NULL, /* buffer */ 0 ); /* buffer length (0 = return length) */ if (ulenw == 0) { /* failed */ return NULL; } ulenw++; /* get length in bytes */ ulen = sizeof(wchar_t) * (ulenw + 1); if ((qw = (wchar_t *)malloc(ulen + 1)) == NULL) { return NULL; } /* convert multibyte to wide */ ulen = MultiByteToWideChar( CP_UTF8, /* UTF-8 code page */ 0, /* flags for character-type options */ utf8_string, /* string to convert */ -1, /* string length (-1 = NULL terminated) */ qw, /* buffer */ ulenw); /* buffer length (0 = return length) */ if (ulen == 0) { /* failed */ free(qw); return NULL; } return qw; } wchar_t *local_to_wchar_string(local_string) char *local_string; /* path of local name */ { wchar_t *qw; int ulen; int ulenw; if (local_string == NULL) return NULL; /* get length */ ulenw = MultiByteToWideChar( CP_ACP, /* ANSI code page */ 0, /* flags for character-type options */ local_string, /* string to convert */ -1, /* string length (-1 = NULL terminated) */ NULL, /* buffer */ 0 ); /* buffer length (0 = return length) */ if (ulenw == 0) { /* failed */ return NULL; } ulenw++; /* get length in bytes */ ulen = sizeof(wchar_t) * (ulenw + 1); if ((qw = (wchar_t *)malloc(ulen + 1)) == NULL) { return NULL; } /* convert multibyte to wide */ ulen = MultiByteToWideChar( CP_ACP, /* ANSI code page */ 0, /* flags for character-type options */ local_string, /* string to convert */ -1, /* string length (-1 = NULL terminated) */ qw, /* buffer */ ulenw); /* buffer length (0 = return length) */ if (ulen == 0) { /* failed */ free(qw); return NULL; } return qw; } #endif /* 0 */ #endif /* UNICODE_SUPPORT && !FUNZIP */ /* --------------------------------------------------- */ /* Large File Support * * Initial functions by E. Gordon and R. Nausedat * 9/10/2003 * Lifted from Zip 3b, win32.c and place here by Myles Bennett * 7/6/2004 * * These implement 64-bit file support for Windows. The * defines and headers are in win32/w32cfg.h. * * Moved to win32i64.c by Mike White to avoid conflicts in * same name functions in WiZ using UnZip and Zip libraries. * 9/25/2003 */ Carla-2.1/data/windows/unzipfx-carla-control/win32/win32i64.c000066400000000000000000000067741364475620200236640ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- win32/win32i64.c - UnZip 6 64-bit filesize support for WIN32 Zip and UnZip. ---------------------------------------------------------------------------*/ #include "../zip.h" /* --------------------------------------------------- */ /* Large File Support * * Initial functions by E. Gordon and R. Nausedat * 9/10/2003 * * These implement 64-bit file support for Windows. The * defines and headers are in win32/osdep.h. * * These moved from win32.c by Mike White to avoid conflicts * in WiZ of same name functions in UnZip and Zip libraries. * 9/25/04 EG */ #if defined(LARGE_FILE_SUPPORT) && !defined(__CYGWIN__) # ifdef USE_STRM_INPUT # ifndef zftello /* 64-bit buffered ftello * * Win32 does not provide a 64-bit buffered * ftell (in the published api anyway) so below provides * hopefully close version. * We have not gotten _telli64 to work with buffered * streams. Below cheats by using fgetpos improperly and * may not work on other ports. */ zoff_t zftello(stream) FILE *stream; { fpos_t fpos = 0; if (fgetpos(stream, &fpos) != 0) { return -1L; } else { return fpos; } } # endif /* ndef zftello */ # ifndef zfseeko /* 64-bit buffered fseeko * * Win32 does not provide a 64-bit buffered * fseeko, so use _lseeki64 and fflush. Note * that SEEK_CUR can lose track of location * if fflush is done between the last buffered * io and this call. */ int zfseeko(stream, offset, origin) FILE *stream; zoff_t offset; int origin; { /* fseek() or its replacements are supposed to clear the eof status of the stream. fflush() and _lseeki64() do not touch the stream's eof flag, so we have to do it manually. */ #if ((defined(_MSC_VER) && (_MSC_VER >= 1200)) || \ (defined(__MINGW32__) && defined(__MSVCRT_VERSION__))) /* For the MSC environment (VS 6 or higher), and for recent releases of the MinGW environment, we "know" the internals of the FILE structure. So, we can clear just the EOF bit of the status flag. */ stream->_flag &= ~_IOEOF; #else /* Unfortunately, there is no standard "cleareof()" function, so we have to use clearerr(). This has the unwanted side effect of clearing the ferror() state as well. */ clearerr(stream); #endif if (origin == SEEK_CUR) { /* instead of synching up lseek easier just to figure and use an absolute offset */ offset += zftello(stream); origin = SEEK_SET; } fflush(stream); if (_lseeki64(fileno(stream), offset, origin) == (zoff_t)-1L) { return -1; } else { return 0; } } # endif /* ndef fseeko */ # endif /* USE_STRM_INPUT */ #endif /* Win32 LARGE_FILE_SUPPORT */ #if 0 FILE* zfopen(filename, mode) const char *filename; const char *mode; { FILE* fTemp; fTemp = fopen(filename, mode); if( fTemp == NULL ) return NULL; /* sorry, could not make VC60 and its rtl work properly without setting the * file buffer to NULL. the problem seems to be _telli64 which seems to * return the max stream position, comments are welcome */ setbuf(fTemp, NULL); return fTemp; } #endif /* --------------------------------------------------- */ Carla-2.1/data/windows/unzipfx-carla-control/zip.h000066400000000000000000000014431364475620200222300ustar00rootroot00000000000000/* Copyright (c) 1990-2005 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2003-May-08 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* This is a dummy zip.h to allow the source files shared with Zip (crypt.c, crc32.c, ttyio.c, win32/win32i64.c) to compile for UnZip. (In case you are looking for the Info-ZIP license, please follow the pointers above.) */ #ifndef __zip_h /* don't include more than once */ #define __zip_h #define UNZIP_INTERNAL #include "unzip.h" #define local static #define ZE_MEM PK_MEM #define ziperr(c, h) return #endif /* !__zip_h */ Carla-2.1/data/windows/unzipfx-carla-control/zipinfo.c000066400000000000000000002761221364475620200231070ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- zipinfo.c Greg Roelofs et al. This file contains all of the ZipInfo-specific listing routines for UnZip. Contains: zi_opts() zi_end_central() zipinfo() zi_long() zi_short() zi_time() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #ifndef NO_ZIPINFO /* strings use up too much space in small-memory systems */ /* Define OS-specific attributes for use on ALL platforms--the S_xxxx * versions of these are defined differently (or not defined) by different * compilers and operating systems. */ #define UNX_IFMT 0170000 /* Unix file type mask */ #define UNX_IFREG 0100000 /* Unix regular file */ #define UNX_IFSOCK 0140000 /* Unix socket (BSD, not SysV or Amiga) */ #define UNX_IFLNK 0120000 /* Unix symbolic link (not SysV, Amiga) */ #define UNX_IFBLK 0060000 /* Unix block special (not Amiga) */ #define UNX_IFDIR 0040000 /* Unix directory */ #define UNX_IFCHR 0020000 /* Unix character special (not Amiga) */ #define UNX_IFIFO 0010000 /* Unix fifo (BCC, not MSC or Amiga) */ #define UNX_ISUID 04000 /* Unix set user id on execution */ #define UNX_ISGID 02000 /* Unix set group id on execution */ #define UNX_ISVTX 01000 /* Unix directory permissions control */ #define UNX_ENFMT UNX_ISGID /* Unix record locking enforcement flag */ #define UNX_IRWXU 00700 /* Unix read, write, execute: owner */ #define UNX_IRUSR 00400 /* Unix read permission: owner */ #define UNX_IWUSR 00200 /* Unix write permission: owner */ #define UNX_IXUSR 00100 /* Unix execute permission: owner */ #define UNX_IRWXG 00070 /* Unix read, write, execute: group */ #define UNX_IRGRP 00040 /* Unix read permission: group */ #define UNX_IWGRP 00020 /* Unix write permission: group */ #define UNX_IXGRP 00010 /* Unix execute permission: group */ #define UNX_IRWXO 00007 /* Unix read, write, execute: other */ #define UNX_IROTH 00004 /* Unix read permission: other */ #define UNX_IWOTH 00002 /* Unix write permission: other */ #define UNX_IXOTH 00001 /* Unix execute permission: other */ #define VMS_IRUSR UNX_IRUSR /* VMS read/owner */ #define VMS_IWUSR UNX_IWUSR /* VMS write/owner */ #define VMS_IXUSR UNX_IXUSR /* VMS execute/owner */ #define VMS_IRGRP UNX_IRGRP /* VMS read/group */ #define VMS_IWGRP UNX_IWGRP /* VMS write/group */ #define VMS_IXGRP UNX_IXGRP /* VMS execute/group */ #define VMS_IROTH UNX_IROTH /* VMS read/other */ #define VMS_IWOTH UNX_IWOTH /* VMS write/other */ #define VMS_IXOTH UNX_IXOTH /* VMS execute/other */ #define AMI_IFMT 06000 /* Amiga file type mask */ #define AMI_IFDIR 04000 /* Amiga directory */ #define AMI_IFREG 02000 /* Amiga regular file */ #define AMI_IHIDDEN 00200 /* to be supported in AmigaDOS 3.x */ #define AMI_ISCRIPT 00100 /* executable script (text command file) */ #define AMI_IPURE 00040 /* allow loading into resident memory */ #define AMI_IARCHIVE 00020 /* not modified since bit was last set */ #define AMI_IREAD 00010 /* can be opened for reading */ #define AMI_IWRITE 00004 /* can be opened for writing */ #define AMI_IEXECUTE 00002 /* executable image, a loadable runfile */ #define AMI_IDELETE 00001 /* can be deleted */ #define THS_IFMT 0xF000 /* Theos file type mask */ #define THS_IFIFO 0x1000 /* pipe */ #define THS_IFCHR 0x2000 /* char device */ #define THS_IFSOCK 0x3000 /* socket */ #define THS_IFDIR 0x4000 /* directory */ #define THS_IFLIB 0x5000 /* library */ #define THS_IFBLK 0x6000 /* block device */ #define THS_IFREG 0x8000 /* regular file */ #define THS_IFREL 0x9000 /* relative (direct) */ #define THS_IFKEY 0xA000 /* keyed */ #define THS_IFIND 0xB000 /* indexed */ #define THS_IFRND 0xC000 /* ???? */ #define THS_IFR16 0xD000 /* 16 bit real mode program */ #define THS_IFP16 0xE000 /* 16 bit protected mode prog */ #define THS_IFP32 0xF000 /* 32 bit protected mode prog */ #define THS_IMODF 0x0800 /* modified */ #define THS_INHID 0x0400 /* not hidden */ #define THS_IEUSR 0x0200 /* erase permission: owner */ #define THS_IRUSR 0x0100 /* read permission: owner */ #define THS_IWUSR 0x0080 /* write permission: owner */ #define THS_IXUSR 0x0040 /* execute permission: owner */ #define THS_IROTH 0x0004 /* read permission: other */ #define THS_IWOTH 0x0002 /* write permission: other */ #define THS_IXOTH 0x0001 /* execute permission: other */ #ifdef OLD_THEOS_EXTRA # include "theos/oldstat.h" #endif #ifndef NSK_UNSTRUCTURED # define NSK_UNSTRUCTURED 0 #endif #ifndef NSK_OBJECTFILECODE # define NSK_OBJECTFILECODE 100 #endif #ifndef NSK_EDITFILECODE # define NSK_EDITFILECODE 101 #endif #define LFLAG 3 /* short "ls -l" type listing */ static int zi_long OF((__GPRO__ zusz_t *pEndprev, int error_in_archive)); static int zi_short OF((__GPRO)); static void zi_showMacTypeCreator OF((__GPRO__ uch *ebfield)); static char *zi_time OF((__GPRO__ ZCONST ulg *datetimez, ZCONST time_t *modtimez, char *d_t_str)); /**********************************************/ /* Strings used in zipinfo.c (ZipInfo half) */ /**********************************************/ static ZCONST char nullStr[] = ""; static ZCONST char PlurSufx[] = "s"; static ZCONST char Far ZipInfHeader2[] = "Zip file size: %s bytes, number of entries: %s\n"; static ZCONST char Far EndCentDirRec[] = "\nEnd-of-central-directory record:\n"; static ZCONST char Far LineSeparators[] = "-------------------------------\n\n"; static ZCONST char Far ZipFSizeVerbose[] = "\ Zip archive file size: %s (%sh)\n"; static ZCONST char Far ActOffsetCentDir[] = "\ Actual end-cent-dir record offset: %s (%sh)\n\ Expected end-cent-dir record offset: %s (%sh)\n\ (based on the length of the central directory and its expected offset)\n\n"; static ZCONST char Far SinglePartArchive1[] = "\ This zipfile constitutes the sole disk of a single-part archive; its\n\ central directory contains %s %s.\n\ The central directory is %s (%sh) bytes long,\n"; static ZCONST char Far SinglePartArchive2[] = "\ and its (expected) offset in bytes from the beginning of the zipfile\n\ is %s (%sh).\n\n"; static ZCONST char Far MultiPartArchive1[] = "\ This zipfile constitutes disk %lu of a multi-part archive. The central\n\ directory starts on disk %lu at an offset within that archive part\n"; static ZCONST char Far MultiPartArchive2[] = "\ of %s (%sh) bytes. The entire\n\ central directory is %s (%sh) bytes long.\n"; static ZCONST char Far MultiPartArchive3[] = "\ %s of the archive entries %s contained within this zipfile volume,\n\ out of a total of %s %s.\n\n"; static ZCONST char Far CentralDirEntry[] = "\nCentral directory entry #%lu:\n---------------------------\n\n"; static ZCONST char Far ZipfileStats[] = "%lu file%s, %s bytes uncompressed, %s bytes compressed: %s%d.%d%%\n"; /* zi_long() strings */ static ZCONST char Far OS_FAT[] = "MS-DOS, OS/2 or NT FAT"; static ZCONST char Far OS_Amiga[] = "Amiga"; static ZCONST char Far OS_VMS[] = "VMS"; static ZCONST char Far OS_Unix[] = "Unix"; static ZCONST char Far OS_VMCMS[] = "VM/CMS"; static ZCONST char Far OS_AtariST[] = "Atari ST"; static ZCONST char Far OS_HPFS[] = "OS/2 or NT HPFS"; static ZCONST char Far OS_Macintosh[] = "Macintosh HFS"; static ZCONST char Far OS_ZSystem[] = "Z-System"; static ZCONST char Far OS_CPM[] = "CP/M"; static ZCONST char Far OS_TOPS20[] = "TOPS-20"; static ZCONST char Far OS_NTFS[] = "NTFS"; static ZCONST char Far OS_QDOS[] = "SMS/QDOS"; static ZCONST char Far OS_Acorn[] = "Acorn RISC OS"; static ZCONST char Far OS_MVS[] = "MVS"; static ZCONST char Far OS_VFAT[] = "Win32 VFAT"; static ZCONST char Far OS_AtheOS[] = "AtheOS"; static ZCONST char Far OS_BeOS[] = "BeOS"; static ZCONST char Far OS_Tandem[] = "Tandem NSK"; static ZCONST char Far OS_Theos[] = "Theos"; static ZCONST char Far OS_MacDarwin[] = "Mac OS/X (Darwin)"; #ifdef OLD_THEOS_EXTRA static ZCONST char Far OS_TheosOld[] = "Theos (Old)"; #endif /* OLD_THEOS_EXTRA */ static ZCONST char Far MthdNone[] = "none (stored)"; static ZCONST char Far MthdShrunk[] = "shrunk"; static ZCONST char Far MthdRedF1[] = "reduced (factor 1)"; static ZCONST char Far MthdRedF2[] = "reduced (factor 2)"; static ZCONST char Far MthdRedF3[] = "reduced (factor 3)"; static ZCONST char Far MthdRedF4[] = "reduced (factor 4)"; static ZCONST char Far MthdImplode[] = "imploded"; static ZCONST char Far MthdToken[] = "tokenized"; static ZCONST char Far MthdDeflate[] = "deflated"; static ZCONST char Far MthdDeflat64[] = "deflated (enhanced-64k)"; static ZCONST char Far MthdDCLImplode[] = "imploded (PK DCL)"; static ZCONST char Far MthdBZip2[] = "bzipped"; static ZCONST char Far MthdLZMA[] = "LZMA-ed"; static ZCONST char Far MthdTerse[] = "tersed (IBM)"; static ZCONST char Far MthdLZ77[] = "LZ77-compressed (IBM)"; static ZCONST char Far MthdWavPack[] = "WavPacked"; static ZCONST char Far MthdPPMd[] = "PPMd-ed"; static ZCONST char Far DeflNorm[] = "normal"; static ZCONST char Far DeflMax[] = "maximum"; static ZCONST char Far DeflFast[] = "fast"; static ZCONST char Far DeflSFast[] = "superfast"; static ZCONST char Far ExtraBytesPreceding[] = " There are an extra %s bytes preceding this file.\n\n"; static ZCONST char Far UnknownNo[] = "unknown (%d)"; #ifdef ZIP64_SUPPORT static ZCONST char Far LocalHeaderOffset[] = "\n offset of local header from start of archive: %s\n\ (%sh) bytes\n"; #else static ZCONST char Far LocalHeaderOffset[] = "\n offset of local header from start of archive: %s (%sh) bytes\n"; #endif static ZCONST char Far HostOS[] = " file system or operating system of origin: %s\n"; static ZCONST char Far EncodeSWVer[] = " version of encoding software: %u.%u\n"; static ZCONST char Far MinOSCompReq[] = " minimum file system compatibility required: %s\n"; static ZCONST char Far MinSWVerReq[] = " minimum software version required to extract: %u.%u\n"; static ZCONST char Far CompressMethod[] = " compression method: %s\n"; static ZCONST char Far SlideWindowSizeImplode[] = " size of sliding dictionary (implosion): %cK\n"; static ZCONST char Far ShannonFanoTrees[] = " number of Shannon-Fano trees (implosion): %c\n"; static ZCONST char Far CompressSubtype[] = " compression sub-type (deflation): %s\n"; static ZCONST char Far FileSecurity[] = " file security status: %sencrypted\n"; static ZCONST char Far ExtendedLocalHdr[] = " extended local header: %s\n"; static ZCONST char Far FileModDate[] = " file last modified on (DOS date/time): %s\n"; #ifdef USE_EF_UT_TIME static ZCONST char Far UT_FileModDate[] = " file last modified on (UT extra field modtime): %s %s\n"; static ZCONST char Far LocalTime[] = "local"; #ifndef NO_GMTIME static ZCONST char Far GMTime[] = "UTC"; #endif #endif /* USE_EF_UT_TIME */ static ZCONST char Far CRC32Value[] = " 32-bit CRC value (hex): %.8lx\n"; static ZCONST char Far CompressedFileSize[] = " compressed size: %s bytes\n"; static ZCONST char Far UncompressedFileSize[] = " uncompressed size: %s bytes\n"; static ZCONST char Far FilenameLength[] = " length of filename: %u characters\n"; static ZCONST char Far ExtraFieldLength[] = " length of extra field: %u bytes\n"; static ZCONST char Far FileCommentLength[] = " length of file comment: %u characters\n"; static ZCONST char Far FileDiskNum[] = " disk number on which file begins: disk %lu\n"; static ZCONST char Far ApparentFileType[] = " apparent file type: %s\n"; static ZCONST char Far VMSFileAttributes[] = " VMS file attributes (%06o octal): %s\n"; static ZCONST char Far AmigaFileAttributes[] = " Amiga file attributes (%06o octal): %s\n"; static ZCONST char Far UnixFileAttributes[] = " Unix file attributes (%06o octal): %s\n"; static ZCONST char Far NonMSDOSFileAttributes[] = " non-MSDOS external file attributes: %06lX hex\n"; static ZCONST char Far MSDOSFileAttributes[] = " MS-DOS file attributes (%02X hex): none\n"; static ZCONST char Far MSDOSFileAttributesRO[] = " MS-DOS file attributes (%02X hex): read-only\n"; static ZCONST char Far MSDOSFileAttributesAlpha[] = " MS-DOS file attributes (%02X hex): %s%s%s%s%s%s%s%s\n"; static ZCONST char Far TheosFileAttributes[] = " Theos file attributes (%04X hex): %s\n"; static ZCONST char Far TheosFTypLib[] = "Library "; static ZCONST char Far TheosFTypDir[] = "Directory "; static ZCONST char Far TheosFTypReg[] = "Sequential "; static ZCONST char Far TheosFTypRel[] = "Direct "; static ZCONST char Far TheosFTypKey[] = "Keyed "; static ZCONST char Far TheosFTypInd[] = "Indexed "; static ZCONST char Far TheosFTypR16[] = " 86 program "; static ZCONST char Far TheosFTypP16[] = "286 program "; static ZCONST char Far TheosFTypP32[] = "386 program "; static ZCONST char Far TheosFTypUkn[] = "??? "; static ZCONST char Far ExtraFieldTrunc[] = "\n\ error: EF data block (type 0x%04x) size %u exceeds remaining extra field\n\ space %u; block length has been truncated.\n"; static ZCONST char Far ExtraFields[] = "\n\ The central-directory extra field contains:"; static ZCONST char Far ExtraFieldType[] = "\n\ - A subfield with ID 0x%04x (%s) and %u data bytes"; static ZCONST char Far efPKSZ64[] = "PKWARE 64-bit sizes"; static ZCONST char Far efAV[] = "PKWARE AV"; static ZCONST char Far efOS2[] = "OS/2"; static ZCONST char Far efPKVMS[] = "PKWARE VMS"; static ZCONST char Far efPKWin32[] = "PKWARE Win32"; static ZCONST char Far efPKUnix[] = "PKWARE Unix"; static ZCONST char Far efIZVMS[] = "Info-ZIP VMS"; static ZCONST char Far efIZUnix[] = "old Info-ZIP Unix/OS2/NT"; static ZCONST char Far efIZUnix2[] = "Unix UID/GID (16-bit)"; static ZCONST char Far efIZUnix3[] = "Unix UID/GID (any size)"; static ZCONST char Far efTime[] = "universal time"; static ZCONST char Far efU8Path[] = "UTF8 path name"; static ZCONST char Far efU8Commnt[] = "UTF8 entry comment"; static ZCONST char Far efJLMac[] = "old Info-ZIP Macintosh"; static ZCONST char Far efMac3[] = "new Info-ZIP Macintosh"; static ZCONST char Far efZipIt[] = "ZipIt Macintosh"; static ZCONST char Far efSmartZip[] = "SmartZip Macintosh"; static ZCONST char Far efZipIt2[] = "ZipIt Macintosh (short)"; static ZCONST char Far efVMCMS[] = "VM/CMS"; static ZCONST char Far efMVS[] = "MVS"; static ZCONST char Far efACL[] = "OS/2 ACL"; static ZCONST char Far efNTSD[] = "Security Descriptor"; static ZCONST char Far efAtheOS[] = "AtheOS"; static ZCONST char Far efBeOS[] = "BeOS"; static ZCONST char Far efQDOS[] = "SMS/QDOS"; static ZCONST char Far efAOSVS[] = "AOS/VS"; static ZCONST char Far efSpark[] = "Acorn SparkFS"; static ZCONST char Far efMD5[] = "Fred Kantor MD5"; static ZCONST char Far efASiUnix[] = "ASi Unix"; static ZCONST char Far efTandem[] = "Tandem NSK"; static ZCONST char Far efTheos[] = "Theos"; static ZCONST char Far efUnknown[] = "unknown"; static ZCONST char Far OS2EAs[] = ".\n\ The local extra field has %lu bytes of OS/2 extended attributes.\n\ (May not match OS/2 \"dir\" amount due to storage method)"; static ZCONST char Far izVMSdata[] = ". The extra\n\ field is %s and has %u bytes of VMS %s information%s"; static ZCONST char Far izVMSstored[] = "stored"; static ZCONST char Far izVMSrleenc[] = "run-length encoded"; static ZCONST char Far izVMSdeflat[] = "deflated"; static ZCONST char Far izVMScunknw[] = "compressed(?)"; static ZCONST char Far *izVMScomp[4] = {izVMSstored, izVMSrleenc, izVMSdeflat, izVMScunknw}; static ZCONST char Far ACLdata[] = ".\n\ The local extra field has %lu bytes of access control list information"; static ZCONST char Far NTSDData[] = ".\n\ The local extra field has %lu bytes of NT security descriptor data"; static ZCONST char Far UTdata[] = ".\n\ The local extra field has UTC/GMT %s time%s"; static ZCONST char Far UTmodification[] = "modification"; static ZCONST char Far UTaccess[] = "access"; static ZCONST char Far UTcreation[] = "creation"; static ZCONST char Far U8PthCmnComplete[] = ".\n\ The UTF8 data of the extra field (V%u, ASCII name CRC `%.8lx') are:\n "; static ZCONST char Far U8PthCmnF24[] = ". The first\n\ 24 UTF8 bytes in the extra field (V%u, ASCII name CRC `%.8lx') are:\n "; static ZCONST char Far ZipItFname[] = ".\n\ The Mac long filename is %s"; static ZCONST char Far Mac3data[] = ".\n\ The local extra field has %lu bytes of %scompressed Macintosh\n\ finder attributes"; /* MacOSdata[] is used by EF_MAC3, EF_ZIPIT, EF_ZIPIT2 and EF_JLEE e. f. */ static ZCONST char Far MacOSdata[] = ".\n\ The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'"; static ZCONST char Far MacOSdata1[] = ".\n\ The associated file has type code `0x%lx' and creator code `0x%lx'"; static ZCONST char Far MacOSJLEEflags[] = ".\n File is marked as %s"; static ZCONST char Far MacOS_RF[] = "Resource-fork"; static ZCONST char Far MacOS_DF[] = "Data-fork"; static ZCONST char Far MacOSMAC3flags[] = ".\n\ File is marked as %s, File Dates are in %d Bit"; static ZCONST char Far AtheOSdata[] = ".\n\ The local extra field has %lu bytes of %scompressed AtheOS file attributes"; static ZCONST char Far BeOSdata[] = ".\n\ The local extra field has %lu bytes of %scompressed BeOS file attributes"; /* The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'" */ static ZCONST char Far QDOSdata[] = ".\n\ The QDOS extra field subtype is `%c%c%c%c'"; static ZCONST char Far AOSVSdata[] = ".\n\ The AOS/VS extra field revision is %d.%d"; static ZCONST char Far TandemUnstr[] = "Unstructured"; static ZCONST char Far TandemRel[] = "Relative"; static ZCONST char Far TandemEntry[] = "Entry Sequenced"; static ZCONST char Far TandemKey[] = "Key Sequenced"; static ZCONST char Far TandemEdit[] = "Edit"; static ZCONST char Far TandemObj[] = "Object"; static ZCONST char Far *TandemFileformat[6] = {TandemUnstr, TandemRel, TandemEntry, TandemKey, TandemEdit, TandemObj}; static ZCONST char Far Tandemdata[] = ".\n\ The file was originally a Tandem %s file, with file code %u"; static ZCONST char Far MD5data[] = ".\n\ The 128-bit MD5 signature is %s"; #ifdef CMS_MVS static ZCONST char Far VmMvsExtraField[] = ".\n\ The stored file open mode (FLDATA TYPE) is \"%s\""; static ZCONST char Far VmMvsInvalid[] = "[invalid]"; #endif /* CMS_MVS */ static ZCONST char Far First20[] = ". The first\n 20 are: "; static ZCONST char Far ColonIndent[] = ":\n "; static ZCONST char Far efFormat[] = " %02x"; static ZCONST char Far lExtraFieldType[] = "\n\ There %s a local extra field with ID 0x%04x (%s) and\n\ %u data bytes (%s).\n"; static ZCONST char Far efIZuid[] = "GMT modification/access times and Unix UID/GID"; static ZCONST char Far efIZnouid[] = "GMT modification/access times only"; static ZCONST char Far NoFileComment[] = "\n There is no file comment.\n"; static ZCONST char Far FileCommBegin[] = "\n\ ------------------------- file comment begins ----------------------------\n"; static ZCONST char Far FileCommEnd[] = "\ -------------------------- file comment ends -----------------------------\n"; /* zi_time() strings */ static ZCONST char Far BogusFmt[] = "%03d"; static ZCONST char Far shtYMDHMTime[] = "%02u-%s-%02u %02u:%02u"; static ZCONST char Far lngYMDHMSTime[] = "%u %s %u %02u:%02u:%02u"; static ZCONST char Far DecimalTime[] = "%04u%02u%02u.%02u%02u%02u"; #ifdef USE_EF_UT_TIME static ZCONST char Far lngYMDHMSTimeError[] = "???? ??? ?? ??:??:??"; #endif #ifndef WINDLL /************************/ /* Function zi_opts() */ /************************/ int zi_opts(__G__ pargc, pargv) int *pargc; char ***pargv; __GDEF { char **argv, *s; int argc, c, error=FALSE, negative=0; int hflag_slmv=TRUE, hflag_2=FALSE; /* diff options => diff defaults */ int tflag_slm=TRUE, tflag_2v=FALSE; int explicit_h=FALSE, explicit_t=FALSE; #ifdef MACOS uO.lflag = LFLAG; /* reset default on each call */ #endif G.extract_flag = FALSE; /* zipinfo does not extract to disk */ argc = *pargc; argv = *pargv; while (--argc > 0 && (*++argv)[0] == '-') { s = argv[0] + 1; while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */ switch (c) { case '-': ++negative; break; case '1': /* shortest listing: JUST filenames */ if (negative) uO.lflag = -2, negative = 0; else uO.lflag = 1; break; case '2': /* just filenames, plus headers if specified */ if (negative) uO.lflag = -2, negative = 0; else uO.lflag = 2; break; #ifndef CMS_MVS case ('C'): /* -C: match filenames case-insensitively */ if (negative) uO.C_flag = FALSE, negative = 0; else uO.C_flag = TRUE; break; #endif /* !CMS_MVS */ case 'h': /* header line */ if (negative) hflag_2 = hflag_slmv = FALSE, negative = 0; else { hflag_2 = hflag_slmv = explicit_h = TRUE; if (uO.lflag == -1) uO.lflag = 0; } break; case 'l': /* longer form of "ls -l" type listing */ if (negative) uO.lflag = -2, negative = 0; else uO.lflag = 5; break; case 'm': /* medium form of "ls -l" type listing */ if (negative) uO.lflag = -2, negative = 0; else uO.lflag = 4; break; #ifdef MORE case 'M': /* send output through built-in "more" */ if (negative) G.M_flag = FALSE, negative = 0; else G.M_flag = TRUE; break; #endif case 's': /* default: shorter "ls -l" type listing */ if (negative) uO.lflag = -2, negative = 0; else uO.lflag = 3; break; case 't': /* totals line */ if (negative) tflag_2v = tflag_slm = FALSE, negative = 0; else { tflag_2v = tflag_slm = explicit_t = TRUE; if (uO.lflag == -1) uO.lflag = 0; } break; case ('T'): /* use (sortable) decimal time format */ if (negative) uO.T_flag = FALSE, negative = 0; else uO.T_flag = TRUE; break; #ifdef UNICODE_SUPPORT case ('U'): /* escape UTF-8, or disable UTF-8 support */ if (negative) { uO.U_flag = MAX(uO.U_flag-negative,0); negative = 0; } else uO.U_flag++; break; #endif /* UNICODE_SUPPORT */ case 'v': /* turbo-verbose listing */ if (negative) uO.lflag = -2, negative = 0; else uO.lflag = 10; break; #ifdef WILD_STOP_AT_DIR case ('W'): /* Wildcard interpretation (stop at '/'?) */ if (negative) uO.W_flag = FALSE, negative = 0; else uO.W_flag = TRUE; break; #endif /* WILD_STOP_AT_DIR */ case 'z': /* print zipfile comment */ if (negative) uO.zflag = negative = 0; else uO.zflag = 1; break; case 'Z': /* ZipInfo mode: ignore */ break; default: error = TRUE; break; } } } if ((argc-- == 0) || error) { *pargc = argc; *pargv = argv; return USAGE(error); } #ifdef MORE if (G.M_flag && !isatty(1)) /* stdout redirected: "more" func useless */ G.M_flag = 0; #endif /* if no listing options given (or all negated), or if only -h/-t given * with individual files specified, use default listing format */ if ((uO.lflag < 0) || ((argc > 0) && (uO.lflag == 0))) uO.lflag = LFLAG; /* set header and totals flags to default or specified values */ switch (uO.lflag) { case 0: /* 0: can only occur if either -t or -h explicitly given; */ case 2: /* therefore set both flags equal to normally false value */ uO.hflag = hflag_2; uO.tflag = tflag_2v; break; case 1: /* only filenames, *always* */ uO.hflag = FALSE; uO.tflag = FALSE; uO.zflag = FALSE; break; case 3: case 4: case 5: uO.hflag = ((argc > 0) && !explicit_h)? FALSE : hflag_slmv; uO.tflag = ((argc > 0) && !explicit_t)? FALSE : tflag_slm; break; case 10: uO.hflag = hflag_slmv; uO.tflag = tflag_2v; break; } *pargc = argc; *pargv = argv; return 0; } /* end function zi_opts() */ #endif /* !WINDLL */ /*******************************/ /* Function zi_end_central() */ /*******************************/ void zi_end_central(__G) __GDEF { /*--------------------------------------------------------------------------- Print out various interesting things about the zipfile. ---------------------------------------------------------------------------*/ if (uO.lflag > 9) { /* verbose format */ Info(slide, 0, ((char *)slide, LoadFarString(EndCentDirRec))); Info(slide, 0, ((char *)slide, LoadFarString(LineSeparators))); Info(slide, 0, ((char *)slide, LoadFarString(ZipFSizeVerbose), FmZofft(G.ziplen, "11", NULL), FmZofft(G.ziplen, FZOFFT_HEX_DOT_WID, "X"))); Info(slide, 0, ((char *)slide, LoadFarString(ActOffsetCentDir), FmZofft(G.real_ecrec_offset, "11", "u"), FmZofft(G.real_ecrec_offset, FZOFFT_HEX_DOT_WID, "X"), FmZofft(G.expect_ecrec_offset, "11", "u"), FmZofft(G.expect_ecrec_offset, FZOFFT_HEX_DOT_WID, "X"))); if (G.ecrec.number_this_disk == 0) { Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive1), FmZofft(G.ecrec.total_entries_central_dir, NULL, "u"), (G.ecrec.total_entries_central_dir == 1)? "entry" : "entries", FmZofft(G.ecrec.size_central_directory, NULL, "u"), FmZofft(G.ecrec.size_central_directory, FZOFFT_HEX_DOT_WID, "X"))); Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive2), FmZofft(G.ecrec.offset_start_central_directory, NULL, "u"), FmZofft(G.ecrec.offset_start_central_directory, FZOFFT_HEX_DOT_WID, "X"))); } else { Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive1), (ulg)(G.ecrec.number_this_disk + 1), (ulg)(G.ecrec.num_disk_start_cdir + 1))); Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive2), FmZofft(G.ecrec.offset_start_central_directory, NULL, "u"), FmZofft(G.ecrec.offset_start_central_directory, FZOFFT_HEX_DOT_WID, "X"), FmZofft(G.ecrec.size_central_directory, NULL, "u"), FmZofft(G.ecrec.size_central_directory, FZOFFT_HEX_DOT_WID, "X"))); Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive3), FmZofft(G.ecrec.num_entries_centrl_dir_ths_disk, NULL, "u"), (G.ecrec.num_entries_centrl_dir_ths_disk == 1)? "is" : "are", FmZofft(G.ecrec.total_entries_central_dir, NULL, "u"), (G.ecrec.total_entries_central_dir == 1) ? "entry" : "entries")); } } else if (uO.hflag) { /* print zip file size and number of contained entries: */ Info(slide, 0, ((char *)slide, LoadFarString(ZipInfHeader2), FmZofft(G.ziplen, NULL, NULL), FmZofft(G.ecrec.total_entries_central_dir, NULL, "u"))); } } /* end function zi_end_central() */ /************************/ /* Function zipinfo() */ /************************/ int zipinfo(__G) /* return PK-type error code */ __GDEF { int do_this_file=FALSE, error, error_in_archive=PK_COOL; int *fn_matched=NULL, *xn_matched=NULL; ulg j, members=0L; zusz_t tot_csize=0L, tot_ucsize=0L; zusz_t endprev; /* buffers end of previous entry for zi_long()'s check * of extra bytes */ /*--------------------------------------------------------------------------- Malloc space for check on unmatched filespecs (no big deal if one or both are NULL). ---------------------------------------------------------------------------*/ if (G.filespecs > 0 && (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != NULL) for (j = 0; j < G.filespecs; ++j) fn_matched[j] = FALSE; if (G.xfilespecs > 0 && (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != NULL) for (j = 0; j < G.xfilespecs; ++j) xn_matched[j] = FALSE; /*--------------------------------------------------------------------------- Set file pointer to start of central directory, then loop through cen- tral directory entries. Check that directory-entry signature bytes are actually there (just a precaution), then process the entry. We know the entire central directory is on this disk: we wouldn't have any of this information unless the end-of-central-directory record was on this disk, and we wouldn't have gotten to this routine unless this is also the disk on which the central directory starts. In practice, this had better be the *only* disk in the archive, but maybe someday we'll add multi-disk support. ---------------------------------------------------------------------------*/ uO.L_flag = FALSE; /* zipinfo mode: never convert name to lowercase */ G.pInfo = G.info; /* (re-)initialize, (just to make sure) */ G.pInfo->textmode = 0; /* so one can read on screen (is this ever used?) */ /* reset endprev for new zipfile; account for multi-part archives (?) */ endprev = (G.crec.relative_offset_local_header == 4L)? 4L : 0L; for (j = 1L;; j++) { if (readbuf(__G__ G.sig, 4) == 0) { error_in_archive = PK_EOF; break; } if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a CentDir entry? */ /* no new central directory entry * -> is the number of processed entries compatible with the * number of entries as stored in the end_central record? */ if (((j - 1) & (ulg)(G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16)) == (ulg)G.ecrec.total_entries_central_dir) { /* "j modulus 4T/64k" matches the reported 64/16-bit-unsigned * number of directory entries -> probably, the regular * end of the central directory has been reached */ break; } else { Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j)); Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); error_in_archive = PK_BADERR; /* sig not found */ break; } } /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */ if ((error = process_cdir_file_hdr(__G)) != PK_COOL) { error_in_archive = error; /* only PK_EOF defined */ break; } if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) /* fatal */ break; } if (!G.process_all_files) { /* check if specified on command line */ unsigned i; if (G.filespecs == 0) do_this_file = TRUE; else { /* check if this entry matches an `include' argument */ do_this_file = FALSE; for (i = 0; i < G.filespecs; i++) if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) { do_this_file = TRUE; if (fn_matched) fn_matched[i] = TRUE; break; /* found match, so stop looping */ } } if (do_this_file) { /* check if this is an excluded file */ for (i = 0; i < G.xfilespecs; i++) if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) { do_this_file = FALSE; /* ^-- ignore case in match */ if (xn_matched) xn_matched[i] = TRUE; break; } } } /*----------------------------------------------------------------------- If current file was specified on command line, or if no names were specified, do the listing for this file. Otherwise, get rid of the file comment and go back for the next file. -----------------------------------------------------------------------*/ if (G.process_all_files || do_this_file) { /* Read the extra field, if any. The extra field info is required * for resolving the Zip64 sizes/offsets and may be used in more * analysis of the entry below. */ if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0) { if (G.extra_field != NULL) { free(G.extra_field); G.extra_field = NULL; } error_in_archive = error; /* The premature return in case of a "fatal" error (PK_EOF) is * delayed until we analyze the extra field contents. * This allows us to display all the other info that has been * successfully read in. */ } switch (uO.lflag) { case 1: case 2: fnprint(__G); SKIP_(G.crec.file_comment_length) break; case 3: case 4: case 5: if ((error = zi_short(__G)) != PK_COOL) { error_in_archive = error; /* might be warning */ } break; case 10: Info(slide, 0, ((char *)slide, LoadFarString(CentralDirEntry), j)); if ((error = zi_long(__G__ &endprev, error_in_archive)) != PK_COOL) { error_in_archive = error; /* might be warning */ } break; default: SKIP_(G.crec.file_comment_length) break; } /* end switch (lflag) */ if (error > PK_WARN) /* fatal */ break; tot_csize += G.crec.csize; tot_ucsize += G.crec.ucsize; if (G.crec.general_purpose_bit_flag & 1) tot_csize -= 12; /* don't count encryption header */ ++members; #ifdef DLL if ((G.statreportcb != NULL) && (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn, G.filename, (zvoid *)&G.crec.ucsize)) { /* cancel operation by user request */ error_in_archive = IZ_CTRLC; break; } #endif #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ UserStop(); #endif } else { /* not listing this file */ SKIP_(G.crec.extra_field_length) SKIP_(G.crec.file_comment_length) if (endprev != 0) endprev = 0; } /* end if (list member?) */ } /* end for-loop (j: member files) */ /*--------------------------------------------------------------------------- Check that we actually found requested files; if so, print totals. ---------------------------------------------------------------------------*/ if ((error_in_archive <= PK_WARN) && uO.tflag) { char *sgn = ""; int cfactor = ratio(tot_ucsize, tot_csize); if (cfactor < 0) { sgn = "-"; cfactor = -cfactor; } Info(slide, 0, ((char *)slide, LoadFarString(ZipfileStats), members, (members==1L)? nullStr:PlurSufx, FmZofft(tot_ucsize, NULL, "u"), FmZofft(tot_csize, NULL, "u"), sgn, cfactor/10, cfactor%10)); } /*--------------------------------------------------------------------------- Check for unmatched filespecs on command line and print warning if any found. ---------------------------------------------------------------------------*/ if (fn_matched) { if (error_in_archive <= PK_WARN) for (j = 0; j < G.filespecs; ++j) if (!fn_matched[j]) Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameNotMatched), G.pfnames[j])); free((zvoid *)fn_matched); } if (xn_matched) { if (error_in_archive <= PK_WARN) for (j = 0; j < G.xfilespecs; ++j) if (!xn_matched[j]) Info(slide, 0x401, ((char *)slide, LoadFarString(ExclFilenameNotMatched), G.pxnames[j])); free((zvoid *)xn_matched); } /* Skip the following checks in case of a premature listing break. */ if (error_in_archive <= PK_WARN) { /*--------------------------------------------------------------------------- Double check that we're back at the end-of-central-directory record. ---------------------------------------------------------------------------*/ if ( (memcmp(G.sig, (G.ecrec.have_ecr64 ? end_central64_sig : end_central_sig), 4) != 0) && (!G.ecrec.is_zip64_archive) && (memcmp(G.sig, end_central_sig, 4) != 0) ) { /* just to make sure again */ Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); error_in_archive = PK_WARN; /* didn't find sig */ } /* Set specific return code when no files have been found. */ if (members == 0L && error_in_archive <= PK_WARN) error_in_archive = PK_FIND; if (uO.lflag >= 10) (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); } return error_in_archive; } /* end function zipinfo() */ /************************/ /* Function zi_long() */ /************************/ static int zi_long(__G__ pEndprev, error_in_archive) /* return PK-type error code */ __GDEF zusz_t *pEndprev; /* for zi_long() check of extra bytes */ int error_in_archive; /* may signal premature return */ { #ifdef USE_EF_UT_TIME iztimes z_utime; #endif int error; unsigned hostnum, hostver, extnum, extver, methid, methnum, xattr; char workspace[12], attribs[22]; ZCONST char *varmsg_str; char unkn[16]; static ZCONST char Far *os[NUM_HOSTS] = { OS_FAT, OS_Amiga, OS_VMS, OS_Unix, OS_VMCMS, OS_AtariST, OS_HPFS, OS_Macintosh, OS_ZSystem, OS_CPM, OS_TOPS20, OS_NTFS, OS_QDOS, OS_Acorn, OS_VFAT, OS_MVS, OS_BeOS, OS_Tandem, OS_Theos, OS_MacDarwin, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, OS_AtheOS }; static ZCONST char Far *method[NUM_METHODS] = { MthdNone, MthdShrunk, MthdRedF1, MthdRedF2, MthdRedF3, MthdRedF4, MthdImplode, MthdToken, MthdDeflate, MthdDeflat64, MthdDCLImplode, MthdBZip2, MthdLZMA, MthdTerse, MthdLZ77, MthdWavPack, MthdPPMd }; static ZCONST char Far *dtypelng[4] = { DeflNorm, DeflMax, DeflFast, DeflSFast }; /*--------------------------------------------------------------------------- Check whether there's any extra space inside the zipfile. If *pEndprev is zero, it's probably a signal that OS/2 extra fields are involved (with unknown compressed size). We won't worry about prepended junk here... ---------------------------------------------------------------------------*/ if (G.crec.relative_offset_local_header != *pEndprev && *pEndprev > 0L) { /* GRR DEBUG Info(slide, 0, ((char *)slide, " [crec.relative_offset_local_header = %lu, endprev = %lu]\n", G.crec.relative_offset_local_header, *pEndprev)); */ Info(slide, 0, ((char *)slide, LoadFarString(ExtraBytesPreceding), FmZofft((G.crec.relative_offset_local_header - (*pEndprev)), NULL, NULL))); } /* calculate endprev for next time around (problem: extra fields may * differ in length between local and central-directory records) */ *pEndprev = G.crec.relative_offset_local_header + (4L + LREC_SIZE) + G.crec.filename_length + G.crec.extra_field_length + G.crec.csize; /*--------------------------------------------------------------------------- Print out various interesting things about the compressed file. ---------------------------------------------------------------------------*/ hostnum = (unsigned)(G.pInfo->hostnum); hostver = (unsigned)(G.pInfo->hostver); extnum = (unsigned)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS); extver = (unsigned)G.crec.version_needed_to_extract[0]; methid = (unsigned)G.crec.compression_method; methnum = find_compr_idx(G.crec.compression_method); (*G.message)((zvoid *)&G, (uch *)" ", 2L, 0); fnprint(__G); Info(slide, 0, ((char *)slide, LoadFarString(LocalHeaderOffset), FmZofft(G.crec.relative_offset_local_header, NULL, "u"), FmZofft(G.crec.relative_offset_local_header, FZOFFT_HEX_DOT_WID, "X"))); if (hostnum >= NUM_HOSTS) { sprintf(unkn, LoadFarString(UnknownNo), (int)G.crec.version_made_by[1]); varmsg_str = unkn; } else { varmsg_str = LoadFarStringSmall(os[hostnum]); #ifdef OLD_THEOS_EXTRA if (hostnum == FS_VFAT_ && hostver == 20) { /* entry made by old non-official THEOS port zip archive */ varmsg_str = LoadFarStringSmall(OS_TheosOld); } #endif /* OLD_THEOS_EXTRA */ } Info(slide, 0, ((char *)slide, LoadFarString(HostOS), varmsg_str)); Info(slide, 0, ((char *)slide, LoadFarString(EncodeSWVer), hostver/10, hostver%10)); if ((extnum >= NUM_HOSTS) || (os[extnum] == NULL)) { sprintf(unkn, LoadFarString(UnknownNo), (int)G.crec.version_needed_to_extract[1]); varmsg_str = unkn; } else { varmsg_str = LoadFarStringSmall(os[extnum]); } Info(slide, 0, ((char *)slide, LoadFarString(MinOSCompReq), varmsg_str)); Info(slide, 0, ((char *)slide, LoadFarString(MinSWVerReq), extver/10, extver%10)); if (methnum >= NUM_METHODS) { sprintf(unkn, LoadFarString(UnknownNo), G.crec.compression_method); varmsg_str = unkn; } else { varmsg_str = LoadFarStringSmall(method[methnum]); } Info(slide, 0, ((char *)slide, LoadFarString(CompressMethod), varmsg_str)); if (methid == IMPLODED) { Info(slide, 0, ((char *)slide, LoadFarString(SlideWindowSizeImplode), (G.crec.general_purpose_bit_flag & 2)? '8' : '4')); Info(slide, 0, ((char *)slide, LoadFarString(ShannonFanoTrees), (G.crec.general_purpose_bit_flag & 4)? '3' : '2')); } else if (methid == DEFLATED || methid == ENHDEFLATED) { ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3); Info(slide, 0, ((char *)slide, LoadFarString(CompressSubtype), LoadFarStringSmall(dtypelng[dnum]))); } Info(slide, 0, ((char *)slide, LoadFarString(FileSecurity), (G.crec.general_purpose_bit_flag & 1) ? nullStr : "not ")); Info(slide, 0, ((char *)slide, LoadFarString(ExtendedLocalHdr), (G.crec.general_purpose_bit_flag & 8) ? "yes" : "no")); /* print upper 3 bits for amusement? */ /* For printing of date & time, a "char d_t_buf[21]" is required. * To save stack space, we reuse the "char attribs[22]" buffer which * is not used yet. */ # define d_t_buf attribs zi_time(__G__ &G.crec.last_mod_dos_datetime, NULL, d_t_buf); Info(slide, 0, ((char *)slide, LoadFarString(FileModDate), d_t_buf)); #ifdef USE_EF_UT_TIME if (G.extra_field && #ifdef IZ_CHECK_TZ G.tz_is_valid && #endif (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1, G.crec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME)) { TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7.0 or Macintosh */ d_t_buf[0] = (char)0; /* signal "show local time" */ zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf); Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate), d_t_buf, LoadFarStringSmall(LocalTime))); #ifndef NO_GMTIME d_t_buf[0] = (char)1; /* signal "show UTC (GMT) time" */ zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf); Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate), d_t_buf, LoadFarStringSmall(GMTime))); #endif /* !NO_GMTIME */ } #endif /* USE_EF_UT_TIME */ Info(slide, 0, ((char *)slide, LoadFarString(CRC32Value), G.crec.crc32)); Info(slide, 0, ((char *)slide, LoadFarString(CompressedFileSize), FmZofft(G.crec.csize, NULL, "u"))); Info(slide, 0, ((char *)slide, LoadFarString(UncompressedFileSize), FmZofft(G.crec.ucsize, NULL, "u"))); Info(slide, 0, ((char *)slide, LoadFarString(FilenameLength), G.crec.filename_length)); Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldLength), G.crec.extra_field_length)); Info(slide, 0, ((char *)slide, LoadFarString(FileCommentLength), G.crec.file_comment_length)); Info(slide, 0, ((char *)slide, LoadFarString(FileDiskNum), (ulg)(G.crec.disk_number_start + 1))); Info(slide, 0, ((char *)slide, LoadFarString(ApparentFileType), (G.crec.internal_file_attributes & 1)? "text" : (G.crec.internal_file_attributes & 2)? "ebcdic" : "binary")); /* changed to accept EBCDIC */ #ifdef ATARI printf(" external file attributes (hex): %.8lx\n", G.crec.external_file_attributes); #endif xattr = (unsigned)((G.crec.external_file_attributes >> 16) & 0xFFFF); if (hostnum == VMS_) { char *p=attribs, *q=attribs+1; int i, j, k; for (k = 0; k < 12; ++k) workspace[k] = 0; if (xattr & VMS_IRUSR) workspace[0] = 'R'; if (xattr & VMS_IWUSR) { workspace[1] = 'W'; workspace[3] = 'D'; } if (xattr & VMS_IXUSR) workspace[2] = 'E'; if (xattr & VMS_IRGRP) workspace[4] = 'R'; if (xattr & VMS_IWGRP) { workspace[5] = 'W'; workspace[7] = 'D'; } if (xattr & VMS_IXGRP) workspace[6] = 'E'; if (xattr & VMS_IROTH) workspace[8] = 'R'; if (xattr & VMS_IWOTH) { workspace[9] = 'W'; workspace[11] = 'D'; } if (xattr & VMS_IXOTH) workspace[10] = 'E'; *p++ = '('; for (k = j = 0; j < 3; ++j) { /* loop over groups of permissions */ for (i = 0; i < 4; ++i, ++k) /* loop over perms within a group */ if (workspace[k]) *p++ = workspace[k]; *p++ = ','; /* group separator */ if (j == 0) while ((*p++ = *q++) != ',') ; /* system, owner perms are same */ } *p-- = '\0'; *p = ')'; /* overwrite last comma */ Info(slide, 0, ((char *)slide, LoadFarString(VMSFileAttributes), xattr, attribs)); } else if (hostnum == AMIGA_) { switch (xattr & AMI_IFMT) { case AMI_IFDIR: attribs[0] = 'd'; break; case AMI_IFREG: attribs[0] = '-'; break; default: attribs[0] = '?'; break; } attribs[1] = (xattr & AMI_IHIDDEN)? 'h' : '-'; attribs[2] = (xattr & AMI_ISCRIPT)? 's' : '-'; attribs[3] = (xattr & AMI_IPURE)? 'p' : '-'; attribs[4] = (xattr & AMI_IARCHIVE)? 'a' : '-'; attribs[5] = (xattr & AMI_IREAD)? 'r' : '-'; attribs[6] = (xattr & AMI_IWRITE)? 'w' : '-'; attribs[7] = (xattr & AMI_IEXECUTE)? 'e' : '-'; attribs[8] = (xattr & AMI_IDELETE)? 'd' : '-'; attribs[9] = 0; /* better dlm the string */ Info(slide, 0, ((char *)slide, LoadFarString(AmigaFileAttributes), xattr, attribs)); } else if (hostnum == THEOS_) { ZCONST char Far *fpFtyp; switch (xattr & THS_IFMT) { case THS_IFLIB: fpFtyp = TheosFTypLib; break; case THS_IFDIR: fpFtyp = TheosFTypDir; break; case THS_IFREG: fpFtyp = TheosFTypReg; break; case THS_IFREL: fpFtyp = TheosFTypRel; break; case THS_IFKEY: fpFtyp = TheosFTypKey; break; case THS_IFIND: fpFtyp = TheosFTypInd; break; case THS_IFR16: fpFtyp = TheosFTypR16; break; case THS_IFP16: fpFtyp = TheosFTypP16; break; case THS_IFP32: fpFtyp = TheosFTypP32; break; default: fpFtyp = TheosFTypUkn; break; } strcpy(attribs, LoadFarStringSmall(fpFtyp)); attribs[12] = (xattr & THS_INHID) ? '.' : 'H'; attribs[13] = (xattr & THS_IMODF) ? '.' : 'M'; attribs[14] = (xattr & THS_IWOTH) ? '.' : 'W'; attribs[15] = (xattr & THS_IROTH) ? '.' : 'R'; attribs[16] = (xattr & THS_IEUSR) ? '.' : 'E'; attribs[17] = (xattr & THS_IXUSR) ? '.' : 'X'; attribs[18] = (xattr & THS_IWUSR) ? '.' : 'W'; attribs[19] = (xattr & THS_IRUSR) ? '.' : 'R'; attribs[20] = 0; Info(slide, 0, ((char *)slide, LoadFarString(TheosFileAttributes), xattr, attribs)); #ifdef OLD_THEOS_EXTRA } else if (hostnum == FS_VFAT_ && hostver == 20) { /* process old non-official THEOS port zip archive */ ZCONST char Far *fpFtyp; switch (xattr & _THS_IFMT) { case _THS_IFLIB: fpFtyp = TheosFTypLib; break; case _THS_IFDIR: fpFtyp = TheosFTypDir; break; case _THS_IFREG: fpFtyp = TheosFTypReg; break; case _THS_IODRC: fpFtyp = TheosFTypRel; break; case _THS_IOKEY: fpFtyp = TheosFTypKey; break; case _THS_IOIND: fpFtyp = TheosFTypInd; break; case _THS_IOPRG: fpFtyp = TheosFTypR16; break; case _THS_IO286: fpFtyp = TheosFTypP16; break; case _THS_IO386: fpFtyp = TheosFTypP32; break; default: fpFtyp = TheosFTypUkn; break; } strcpy(attribs, LoadFarStringSmall(fpFtyp)); attribs[12] = (xattr & _THS_HIDDN) ? 'H' : '.'; attribs[13] = (xattr & _THS_IXOTH) ? '.' : 'X'; attribs[14] = (xattr & _THS_IWOTH) ? '.' : 'W'; attribs[15] = (xattr & _THS_IROTH) ? '.' : 'R'; attribs[16] = (xattr & _THS_IEUSR) ? '.' : 'E'; attribs[17] = (xattr & _THS_IXUSR) ? '.' : 'X'; attribs[18] = (xattr & _THS_IWUSR) ? '.' : 'W'; attribs[19] = (xattr & _THS_IRUSR) ? '.' : 'R'; attribs[20] = 0; Info(slide, 0, ((char *)slide, LoadFarString(TheosFileAttributes), xattr, attribs)); #endif /* OLD_THEOS_EXTRA */ } else if ((hostnum != FS_FAT_) && (hostnum != FS_HPFS_) && (hostnum != FS_NTFS_) && (hostnum != FS_VFAT_) && (hostnum != ACORN_) && (hostnum != VM_CMS_) && (hostnum != MVS_)) { /* assume Unix-like */ switch ((unsigned)(xattr & UNX_IFMT)) { case (unsigned)UNX_IFDIR: attribs[0] = 'd'; break; case (unsigned)UNX_IFREG: attribs[0] = '-'; break; case (unsigned)UNX_IFLNK: attribs[0] = 'l'; break; case (unsigned)UNX_IFBLK: attribs[0] = 'b'; break; case (unsigned)UNX_IFCHR: attribs[0] = 'c'; break; case (unsigned)UNX_IFIFO: attribs[0] = 'p'; break; case (unsigned)UNX_IFSOCK: attribs[0] = 's'; break; default: attribs[0] = '?'; break; } attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-'; attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-'; attribs[7] = (xattr & UNX_IROTH)? 'r' : '-'; attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-'; attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-'; attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-'; if (xattr & UNX_IXUSR) attribs[3] = (xattr & UNX_ISUID)? 's' : 'x'; else attribs[3] = (xattr & UNX_ISUID)? 'S' : '-'; /* S = undefined */ if (xattr & UNX_IXGRP) attribs[6] = (xattr & UNX_ISGID)? 's' : 'x'; /* == UNX_ENFMT */ else attribs[6] = (xattr & UNX_ISGID)? 'l' : '-'; if (xattr & UNX_IXOTH) attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x'; /* "sticky bit" */ else attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-'; /* T = undefined */ attribs[10] = 0; Info(slide, 0, ((char *)slide, LoadFarString(UnixFileAttributes), xattr, attribs)); } else { Info(slide, 0, ((char *)slide, LoadFarString(NonMSDOSFileAttributes), G.crec.external_file_attributes >> 8)); } /* endif (hostnum: external attributes format) */ if ((xattr=(unsigned)(G.crec.external_file_attributes & 0xFF)) == 0) Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributes), xattr)); else if (xattr == 1) Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesRO), xattr)); else Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesAlpha), xattr, (xattr&1)? "rdo " : nullStr, (xattr&2)? "hid " : nullStr, (xattr&4)? "sys " : nullStr, (xattr&8)? "lab " : nullStr, (xattr&16)? "dir " : nullStr, (xattr&32)? "arc " : nullStr, (xattr&64)? "lnk " : nullStr, (xattr&128)? "exe" : nullStr)); /*--------------------------------------------------------------------------- Analyze the extra field, if any, and print the file comment, if any (the filename has already been printed, above). That finishes up this file entry... ---------------------------------------------------------------------------*/ if (G.crec.extra_field_length > 0) { uch *ef_ptr = G.extra_field; ush ef_len = G.crec.extra_field_length; ush eb_id, eb_datalen; ZCONST char Far *ef_fieldname; if (error_in_archive > PK_WARN) /* fatal: can't continue */ /* delayed "fatal error" return from extra field reading */ return error_in_archive; if (G.extra_field == (uch *)NULL) return PK_ERR; /* not consistent with crec length */ Info(slide, 0, ((char *)slide, LoadFarString(ExtraFields))); while (ef_len >= EB_HEADSIZE) { eb_id = makeword(&ef_ptr[EB_ID]); eb_datalen = makeword(&ef_ptr[EB_LEN]); ef_ptr += EB_HEADSIZE; ef_len -= EB_HEADSIZE; if (eb_datalen > (ush)ef_len) { Info(slide, 0x421, ((char *)slide, LoadFarString(ExtraFieldTrunc), eb_id, eb_datalen, ef_len)); eb_datalen = ef_len; } switch (eb_id) { case EF_PKSZ64: ef_fieldname = efPKSZ64; if ((G.crec.relative_offset_local_header & (~(zusz_t)0xFFFFFFFFL)) != 0) { /* Subtract the size of the 64bit local offset from the local e.f. size, local Z64 e.f. block has no offset; when only local offset present, the entire local PKSZ64 block is missing. */ *pEndprev -= (eb_datalen == 8 ? 12 : 8); } break; case EF_AV: ef_fieldname = efAV; break; case EF_OS2: ef_fieldname = efOS2; break; case EF_ACL: ef_fieldname = efACL; break; case EF_NTSD: ef_fieldname = efNTSD; break; case EF_PKVMS: ef_fieldname = efPKVMS; break; case EF_IZVMS: ef_fieldname = efIZVMS; break; case EF_PKW32: ef_fieldname = efPKWin32; break; case EF_PKUNIX: ef_fieldname = efPKUnix; break; case EF_IZUNIX: ef_fieldname = efIZUnix; if (hostnum == UNIX_ && *pEndprev > 0L) *pEndprev += 4L; /* also have UID/GID in local copy */ break; case EF_IZUNIX2: ef_fieldname = efIZUnix2; if (*pEndprev > 0L) *pEndprev += 4L; /* 4 byte UID/GID in local copy */ break; case EF_IZUNIX3: ef_fieldname = efIZUnix3; #if 0 if (*pEndprev > 0L) *pEndprev += 4L; /* 4 byte UID/GID in local copy */ #endif break; case EF_TIME: ef_fieldname = efTime; break; case EF_UNIPATH: ef_fieldname = efU8Path; break; case EF_UNICOMNT: ef_fieldname = efU8Commnt; break; case EF_MAC3: ef_fieldname = efMac3; break; case EF_JLMAC: ef_fieldname = efJLMac; break; case EF_ZIPIT: ef_fieldname = efZipIt; break; case EF_ZIPIT2: ef_fieldname = efZipIt2; break; case EF_VMCMS: ef_fieldname = efVMCMS; break; case EF_MVS: ef_fieldname = efMVS; break; case EF_ATHEOS: ef_fieldname = efAtheOS; break; case EF_BEOS: ef_fieldname = efBeOS; break; case EF_QDOS: ef_fieldname = efQDOS; break; case EF_AOSVS: ef_fieldname = efAOSVS; break; case EF_SPARK: /* from RISC OS */ ef_fieldname = efSpark; break; case EF_MD5: ef_fieldname = efMD5; break; case EF_ASIUNIX: ef_fieldname = efASiUnix; break; case EF_TANDEM: ef_fieldname = efTandem; break; case EF_SMARTZIP: ef_fieldname = efSmartZip; break; case EF_THEOS: #ifdef OLD_THEOS_EXTRA case EF_THEOSO: #endif ef_fieldname = efTheos; break; default: ef_fieldname = efUnknown; break; } Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldType), eb_id, LoadFarStringSmall(ef_fieldname), eb_datalen)); /* additional, field-specific information: */ switch (eb_id) { case EF_OS2: case EF_ACL: if (eb_datalen >= EB_OS2_HLEN) { if (eb_id == EF_OS2) ef_fieldname = OS2EAs; else ef_fieldname = ACLdata; Info(slide, 0, ((char *)slide, LoadFarString(ef_fieldname), makelong(ef_ptr))); *pEndprev = 0L; /* no clue about csize of local */ } else { goto ef_default_display; } break; case EF_NTSD: if (eb_datalen >= EB_NTSD_C_LEN) { Info(slide, 0, ((char *)slide, LoadFarString(NTSDData), makelong(ef_ptr))); *pEndprev = 0L; /* no clue about csize of local */ } else { goto ef_default_display; } break; case EF_IZVMS: if (eb_datalen >= 8) { char *p, q[8]; unsigned compr = makeword(ef_ptr+EB_IZVMS_FLGS) & EB_IZVMS_BCMASK; *q = '\0'; if (compr > 3) compr = 3; switch (makelong(ef_ptr)) { case 0x42414656: /* "VFAB" */ p = "FAB"; break; case 0x4C4C4156: /* "VALL" */ p = "XABALL"; break; case 0x43484656: /* "VFHC" */ p = "XABFHC"; break; case 0x54414456: /* "VDAT" */ p = "XABDAT"; break; case 0x54445256: /* "VRDT" */ p = "XABRDT"; break; case 0x4F525056: /* "VPRO" */ p = "XABPRO"; break; case 0x59454B56: /* "VKEY" */ p = "XABKEY"; break; case 0x56534D56: /* "VMSV" */ p = "version"; if (eb_datalen >= 16) { /* put termitation first, for A_TO_N() */ q[7] = '\0'; q[0] = ' '; q[1] = '('; strncpy(q+2, (char *)ef_ptr+EB_IZVMS_HLEN, 4); A_TO_N(q+2); q[6] = ')'; } break; default: p = "unknown"; } Info(slide, 0, ((char *)slide, LoadFarString(izVMSdata), LoadFarStringSmall(izVMScomp[compr]), makeword(ef_ptr+EB_IZVMS_UCSIZ), p, q)); } else { goto ef_default_display; } break; case EF_TIME: if (eb_datalen > 0) { char types[80]; int num = 0, len; *types = '\0'; if (*ef_ptr & 1) { strcpy(types, LoadFarString(UTmodification)); ++num; } if (*ef_ptr & 2) { len = strlen(types); if (num) types[len++] = '/'; strcpy(types+len, LoadFarString(UTaccess)); ++num; if (*pEndprev > 0L) *pEndprev += 4L; } if (*ef_ptr & 4) { len = strlen(types); if (num) types[len++] = '/'; strcpy(types+len, LoadFarString(UTcreation)); ++num; if (*pEndprev > 0L) *pEndprev += 4L; } if (num > 0) Info(slide, 0, ((char *)slide, LoadFarString(UTdata), types, num == 1? nullStr : PlurSufx)); } break; case EF_UNIPATH: case EF_UNICOMNT: if (eb_datalen >= 5) { unsigned i, n; ulg name_crc = makelong(ef_ptr+1); if (eb_datalen <= 29) { Info(slide, 0, ((char *)slide, LoadFarString(U8PthCmnComplete), (unsigned)ef_ptr[0], name_crc)); n = eb_datalen; } else { Info(slide, 0, ((char *)slide, LoadFarString(U8PthCmnF24), (unsigned)ef_ptr[0], name_crc)); n = 29; } for (i = 5; i < n; ++i) Info(slide, 0, ((char *)slide, LoadFarString(efFormat), ef_ptr[i])); } else { goto ef_default_display; } break; case EF_MAC3: if (eb_datalen >= EB_MAC3_HLEN) { ulg eb_uc = makelong(ef_ptr); unsigned mac3_flgs = makeword(ef_ptr+EB_FLGS_OFFS); unsigned eb_is_uc = mac3_flgs & EB_M3_FL_UNCMPR; Info(slide, 0, ((char *)slide, LoadFarString(Mac3data), eb_uc, eb_is_uc ? "un" : nullStr)); if (eb_is_uc) { if (*pEndprev > 0L) *pEndprev += makelong(ef_ptr); } else { *pEndprev = 0L; /* no clue about csize of local */ } Info(slide, 0, ((char *)slide, LoadFarString(MacOSMAC3flags), LoadFarStringSmall(mac3_flgs & EB_M3_FL_DATFRK ? MacOS_DF : MacOS_RF), (mac3_flgs & EB_M3_FL_TIME64 ? 64 : 32))); zi_showMacTypeCreator(__G__ &ef_ptr[6]); } else { goto ef_default_display; } break; case EF_ZIPIT2: if (eb_datalen >= 5 && makelong(ef_ptr) == 0x5449505A /* "ZPIT" */) { if (eb_datalen >= 12) { zi_showMacTypeCreator(__G__ &ef_ptr[4]); } } else { goto ef_default_display; } break; case EF_ZIPIT: if (eb_datalen >= 5 && makelong(ef_ptr) == 0x5449505A /* "ZPIT" */) { unsigned fnlen = ef_ptr[4]; if ((unsigned)eb_datalen >= fnlen + (5 + 8)) { uch nullchar = ef_ptr[fnlen+5]; ef_ptr[fnlen+5] = '\0'; /* terminate filename */ A_TO_N(ef_ptr+5); Info(slide, 0, ((char *)slide, LoadFarString(ZipItFname), (char *)ef_ptr+5)); ef_ptr[fnlen+5] = nullchar; zi_showMacTypeCreator(__G__ &ef_ptr[fnlen+5]); } } else { goto ef_default_display; } break; case EF_JLMAC: if (eb_datalen >= 40 && makelong(ef_ptr) == 0x45454C4A /* "JLEE" */) { zi_showMacTypeCreator(__G__ &ef_ptr[4]); Info(slide, 0, ((char *)slide, LoadFarString(MacOSJLEEflags), LoadFarStringSmall(ef_ptr[31] & 1 ? MacOS_DF : MacOS_RF))); } else { goto ef_default_display; } break; case EF_SMARTZIP: if ((eb_datalen == EB_SMARTZIP_HLEN) && makelong(ef_ptr) == 0x70695A64 /* "dZip" */) { char filenameBuf[32]; zi_showMacTypeCreator(__G__ &ef_ptr[4]); memcpy(filenameBuf, &ef_ptr[33], 31); filenameBuf[ef_ptr[32]] = '\0'; A_TO_N(filenameBuf); Info(slide, 0, ((char *)slide, LoadFarString(ZipItFname), filenameBuf)); } else { goto ef_default_display; } break; #ifdef CMS_MVS case EF_VMCMS: case EF_MVS: { char type[100]; Info(slide, 0, ((char *)slide, LoadFarString(VmMvsExtraField), (getVMMVSexfield(type, ef_ptr-EB_HEADSIZE, (unsigned)eb_datalen) > 0)? type : LoadFarStringSmall(VmMvsInvalid))); } break; #endif /* CMS_MVS */ case EF_ATHEOS: case EF_BEOS: if (eb_datalen >= EB_BEOS_HLEN) { ulg eb_uc = makelong(ef_ptr); unsigned eb_is_uc = *(ef_ptr+EB_FLGS_OFFS) & EB_BE_FL_UNCMPR; if (eb_id == EF_ATHEOS) ef_fieldname = AtheOSdata; else ef_fieldname = BeOSdata; Info(slide, 0, ((char *)slide, LoadFarString(ef_fieldname), eb_uc, eb_is_uc ? "un" : nullStr)); if (eb_is_uc) { if (*pEndprev > 0L) *pEndprev += makelong(ef_ptr); } else { *pEndprev = 0L; /* no clue about csize of local */ } } else { goto ef_default_display; } break; case EF_QDOS: if (eb_datalen >= 4) { Info(slide, 0, ((char *)slide, LoadFarString(QDOSdata), ef_ptr[0], ef_ptr[1], ef_ptr[2], ef_ptr[3])); } else { goto ef_default_display; } break; case EF_AOSVS: if (eb_datalen >= 5) { Info(slide, 0, ((char *)slide, LoadFarString(AOSVSdata), ((int)(uch)ef_ptr[4])/10, ((int)(uch)ef_ptr[4])%10)); } else { goto ef_default_display; } break; case EF_TANDEM: if (eb_datalen == 20) { unsigned type, code; type = (ef_ptr[18] & 0x60) >> 5; code = makeword(ef_ptr); /* Arrg..., Tandem e.f. uses BigEndian byte-order */ code = ((code << 8) & 0xff00) | ((code >> 8) & 0x00ff); if (type == NSK_UNSTRUCTURED) { if (code == NSK_EDITFILECODE) type = 4; else if (code == NSK_OBJECTFILECODE) type = 5; } Info(slide, 0, ((char *)slide, LoadFarString(Tandemdata), LoadFarStringSmall(TandemFileformat[type]), code)); } else { goto ef_default_display; } break; case EF_MD5: if (eb_datalen >= 19) { char md5[33]; int i; for (i = 0; i < 16; ++i) sprintf(&md5[i<<1], "%02x", ef_ptr[15-i]); md5[32] = '\0'; Info(slide, 0, ((char *)slide, LoadFarString(MD5data), md5)); break; } /* else: fall through !! */ default: ef_default_display: if (eb_datalen > 0) { unsigned i, n; if (eb_datalen <= 24) { Info(slide, 0, ((char *)slide, LoadFarString(ColonIndent))); n = eb_datalen; } else { Info(slide, 0, ((char *)slide, LoadFarString(First20))); n = 20; } for (i = 0; i < n; ++i) Info(slide, 0, ((char *)slide, LoadFarString(efFormat), ef_ptr[i])); } break; } (*G.message)((zvoid *)&G, (uch *)".", 1L, 0); ef_ptr += eb_datalen; ef_len -= eb_datalen; } (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); } /* high bit == Unix/OS2/NT GMT times (mtime, atime); next bit == UID/GID */ if ((xattr = (unsigned)((G.crec.external_file_attributes & 0xC000) >> 12)) & 8) { if (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_) { Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType), "is", EF_IZUNIX, LoadFarStringSmall(efIZUnix), (unsigned)(xattr&12), (xattr&4)? efIZuid : efIZnouid)); if (*pEndprev > 0L) *pEndprev += (ulg)(xattr&12); } else if (hostnum == FS_FAT_ && !(xattr&4)) Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType), "may be", EF_IZUNIX, LoadFarStringSmall(efIZUnix), 8, efIZnouid)); } if (!G.crec.file_comment_length) Info(slide, 0, ((char *)slide, LoadFarString(NoFileComment))); else { Info(slide, 0, ((char *)slide, LoadFarString(FileCommBegin))); if ((error = do_string(__G__ G.crec.file_comment_length, DISPL_8)) != PK_COOL) { error_in_archive = error; /* might be warning */ if (error > PK_WARN) /* fatal */ return error; } Info(slide, 0, ((char *)slide, LoadFarString(FileCommEnd))); } return error_in_archive; } /* end function zi_long() */ /*************************/ /* Function zi_short() */ /*************************/ static int zi_short(__G) /* return PK-type error code */ __GDEF { #ifdef USE_EF_UT_TIME iztimes z_utime; time_t *z_modtim; #endif int k, error, error_in_archive=PK_COOL; unsigned hostnum, hostver, methid, methnum, xattr; char *p, workspace[12], attribs[16]; char methbuf[5]; static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */ static ZCONST char Far os[NUM_HOSTS+1][4] = { "fat", "ami", "vms", "unx", "cms", "atr", "hpf", "mac", "zzz", "cpm", "t20", "ntf", "qds", "aco", "vft", "mvs", "be ", "nsk", "ths", "osx", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "ath", "???" }; #ifdef OLD_THEOS_EXTRA static ZCONST char Far os_TheosOld[] = "tho"; #endif static ZCONST char Far method[NUM_METHODS+1][5] = { "stor", "shrk", "re:1", "re:2", "re:3", "re:4", "i#:#", "tokn", "def#", "d64#", "dcli", "bzp2", "lzma", "ters", "lz77", "wavp", "ppmd", "u###" }; /*--------------------------------------------------------------------------- Print out various interesting things about the compressed file. ---------------------------------------------------------------------------*/ methid = (unsigned)(G.crec.compression_method); methnum = find_compr_idx(G.crec.compression_method); hostnum = (unsigned)(G.pInfo->hostnum); hostver = (unsigned)(G.pInfo->hostver); /* extnum = (unsigned)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS); extver = (unsigned)G.crec.version_needed_to_extract[0]; */ zfstrcpy(methbuf, method[methnum]); if (methid == IMPLODED) { methbuf[1] = (char)((G.crec.general_purpose_bit_flag & 2)? '8' : '4'); methbuf[3] = (char)((G.crec.general_purpose_bit_flag & 4)? '3' : '2'); } else if (methid == DEFLATED || methid == ENHDEFLATED) { ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3); methbuf[3] = dtype[dnum]; } else if (methnum >= NUM_METHODS) { /* unknown */ sprintf(&methbuf[1], "%03u", G.crec.compression_method); } for (k = 0; k < 15; ++k) attribs[k] = ' '; attribs[15] = 0; xattr = (unsigned)((G.crec.external_file_attributes >> 16) & 0xFFFF); switch (hostnum) { case VMS_: { int i, j; for (k = 0; k < 12; ++k) workspace[k] = 0; if (xattr & VMS_IRUSR) workspace[0] = 'R'; if (xattr & VMS_IWUSR) { workspace[1] = 'W'; workspace[3] = 'D'; } if (xattr & VMS_IXUSR) workspace[2] = 'E'; if (xattr & VMS_IRGRP) workspace[4] = 'R'; if (xattr & VMS_IWGRP) { workspace[5] = 'W'; workspace[7] = 'D'; } if (xattr & VMS_IXGRP) workspace[6] = 'E'; if (xattr & VMS_IROTH) workspace[8] = 'R'; if (xattr & VMS_IWOTH) { workspace[9] = 'W'; workspace[11] = 'D'; } if (xattr & VMS_IXOTH) workspace[10] = 'E'; p = attribs; for (k = j = 0; j < 3; ++j) { /* groups of permissions */ for (i = 0; i < 4; ++i, ++k) /* perms within a group */ if (workspace[k]) *p++ = workspace[k]; *p++ = ','; /* group separator */ } *--p = ' '; /* overwrite last comma */ if ((p - attribs) < 12) sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10); } break; case AMIGA_: switch (xattr & AMI_IFMT) { case AMI_IFDIR: attribs[0] = 'd'; break; case AMI_IFREG: attribs[0] = '-'; break; default: attribs[0] = '?'; break; } attribs[1] = (xattr & AMI_IHIDDEN)? 'h' : '-'; attribs[2] = (xattr & AMI_ISCRIPT)? 's' : '-'; attribs[3] = (xattr & AMI_IPURE)? 'p' : '-'; attribs[4] = (xattr & AMI_IARCHIVE)? 'a' : '-'; attribs[5] = (xattr & AMI_IREAD)? 'r' : '-'; attribs[6] = (xattr & AMI_IWRITE)? 'w' : '-'; attribs[7] = (xattr & AMI_IEXECUTE)? 'e' : '-'; attribs[8] = (xattr & AMI_IDELETE)? 'd' : '-'; sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10); break; case THEOS_: switch (xattr & THS_IFMT) { case THS_IFLIB: *attribs = 'L'; break; case THS_IFDIR: *attribs = 'D'; break; case THS_IFCHR: *attribs = 'C'; break; case THS_IFREG: *attribs = 'S'; break; case THS_IFREL: *attribs = 'R'; break; case THS_IFKEY: *attribs = 'K'; break; case THS_IFIND: *attribs = 'I'; break; case THS_IFR16: *attribs = 'P'; break; case THS_IFP16: *attribs = '2'; break; case THS_IFP32: *attribs = '3'; break; default: *attribs = '?'; break; } attribs[1] = (xattr & THS_INHID) ? '.' : 'H'; attribs[2] = (xattr & THS_IMODF) ? '.' : 'M'; attribs[3] = (xattr & THS_IWOTH) ? '.' : 'W'; attribs[4] = (xattr & THS_IROTH) ? '.' : 'R'; attribs[5] = (xattr & THS_IEUSR) ? '.' : 'E'; attribs[6] = (xattr & THS_IXUSR) ? '.' : 'X'; attribs[7] = (xattr & THS_IWUSR) ? '.' : 'W'; attribs[8] = (xattr & THS_IRUSR) ? '.' : 'R'; sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10); break; case FS_VFAT_: #ifdef OLD_THEOS_EXTRA if (hostver == 20) { switch (xattr & _THS_IFMT) { case _THS_IFLIB: *attribs = 'L'; break; case _THS_IFDIR: *attribs = 'd'; break; case _THS_IFCHR: *attribs = 'c'; break; case _THS_IFREG: *attribs = 'S'; break; case _THS_IODRC: *attribs = 'D'; break; case _THS_IOKEY: *attribs = 'K'; break; case _THS_IOIND: *attribs = 'I'; break; case _THS_IOPRG: *attribs = 'P'; break; case _THS_IO286: *attribs = '2'; break; case _THS_IO386: *attribs = '3'; break; default: *attribs = '?'; break; } attribs[1] = (xattr & _THS_HIDDN) ? 'H' : '.'; attribs[2] = (xattr & _THS_IXOTH) ? '.' : 'X'; attribs[3] = (xattr & _THS_IWOTH) ? '.' : 'W'; attribs[4] = (xattr & _THS_IROTH) ? '.' : 'R'; attribs[5] = (xattr & _THS_IEUSR) ? '.' : 'E'; attribs[6] = (xattr & _THS_IXUSR) ? '.' : 'X'; attribs[7] = (xattr & _THS_IWUSR) ? '.' : 'W'; attribs[8] = (xattr & _THS_IRUSR) ? '.' : 'R'; sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10); break; } /* else: fall through! */ #endif /* OLD_THEOS_EXTRA */ case FS_FAT_: case FS_HPFS_: case FS_NTFS_: case VM_CMS_: case MVS_: case ACORN_: if (hostnum != FS_FAT_ || (unsigned)(xattr & 0700) != ((unsigned)0400 | ((unsigned)!(G.crec.external_file_attributes & 1) << 7) | ((unsigned)(G.crec.external_file_attributes & 0x10) << 2)) ) { xattr = (unsigned)(G.crec.external_file_attributes & 0xFF); sprintf(attribs, ".r.-... %u.%u", hostver/10, hostver%10); attribs[2] = (xattr & 0x01)? '-' : 'w'; attribs[5] = (xattr & 0x02)? 'h' : '-'; attribs[6] = (xattr & 0x04)? 's' : '-'; attribs[4] = (xattr & 0x20)? 'a' : '-'; if (xattr & 0x10) { attribs[0] = 'd'; attribs[3] = 'x'; } else attribs[0] = '-'; if (IS_VOLID(xattr)) attribs[0] = 'V'; else if ((p = MBSRCHR(G.filename, '.')) != (char *)NULL) { ++p; if (STRNICMP(p, "com", 3) == 0 || STRNICMP(p, "exe", 3) == 0 || STRNICMP(p, "btm", 3) == 0 || STRNICMP(p, "cmd", 3) == 0 || STRNICMP(p, "bat", 3) == 0) attribs[3] = 'x'; } break; } /* else: fall through! */ default: /* assume Unix-like */ switch ((unsigned)(xattr & UNX_IFMT)) { case (unsigned)UNX_IFDIR: attribs[0] = 'd'; break; case (unsigned)UNX_IFREG: attribs[0] = '-'; break; case (unsigned)UNX_IFLNK: attribs[0] = 'l'; break; case (unsigned)UNX_IFBLK: attribs[0] = 'b'; break; case (unsigned)UNX_IFCHR: attribs[0] = 'c'; break; case (unsigned)UNX_IFIFO: attribs[0] = 'p'; break; case (unsigned)UNX_IFSOCK: attribs[0] = 's'; break; default: attribs[0] = '?'; break; } attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-'; attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-'; attribs[7] = (xattr & UNX_IROTH)? 'r' : '-'; attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-'; attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-'; attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-'; if (xattr & UNX_IXUSR) attribs[3] = (xattr & UNX_ISUID)? 's' : 'x'; else attribs[3] = (xattr & UNX_ISUID)? 'S' : '-'; /* S==undefined */ if (xattr & UNX_IXGRP) attribs[6] = (xattr & UNX_ISGID)? 's' : 'x'; /* == UNX_ENFMT */ else /* attribs[6] = (xattr & UNX_ISGID)? 'l' : '-'; real 4.3BSD */ attribs[6] = (xattr & UNX_ISGID)? 'S' : '-'; /* SunOS 4.1.x */ if (xattr & UNX_IXOTH) attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x'; /* "sticky bit" */ else attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-'; /* T==undefined */ sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10); break; } /* end switch (hostnum: external attributes format) */ #ifdef OLD_THEOS_EXTRA Info(slide, 0, ((char *)slide, "%s %s %s ", attribs, LoadFarStringSmall(((hostnum == FS_VFAT_ && hostver == 20) ? os_TheosOld : os[hostnum])), FmZofft(G.crec.ucsize, "8", "u"))); #else Info(slide, 0, ((char *)slide, "%s %s %s ", attribs, LoadFarStringSmall(os[hostnum]), FmZofft(G.crec.ucsize, "8", "u"))); #endif Info(slide, 0, ((char *)slide, "%c", (G.crec.general_purpose_bit_flag & 1)? ((G.crec.internal_file_attributes & 1)? 'T' : 'B') : /* encrypted */ ((G.crec.internal_file_attributes & 1)? 't' : 'b'))); /* plaintext */ k = (G.crec.extra_field_length || /* a local-only "UX" (old Unix/OS2/NT GMT times "IZUNIX") e.f.? */ ((G.crec.external_file_attributes & 0x8000) && (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_))); Info(slide, 0, ((char *)slide, "%c", k? ((G.crec.general_purpose_bit_flag & 8)? 'X' : 'x') : /* extra field */ ((G.crec.general_purpose_bit_flag & 8)? 'l' : '-'))); /* no extra field */ /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ extended local header or not */ if (uO.lflag == 4) { zusz_t csiz = G.crec.csize; if (G.crec.general_purpose_bit_flag & 1) csiz -= 12; /* if encrypted, don't count encryption header */ Info(slide, 0, ((char *)slide, "%3d%%", (ratio(G.crec.ucsize,csiz)+5)/10)); } else if (uO.lflag == 5) Info(slide, 0, ((char *)slide, " %s", FmZofft(G.crec.csize, "8", "u"))); /* For printing of date & time, a "char d_t_buf[16]" is required. * To save stack space, we reuse the "char attribs[16]" buffer whose * content is no longer needed. */ # define d_t_buf attribs #ifdef USE_EF_UT_TIME z_modtim = G.extra_field && #ifdef IZ_CHECK_TZ G.tz_is_valid && #endif (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1, G.crec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME) ? &z_utime.mtime : NULL; TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7.0 or Macintosh */ d_t_buf[0] = (char)0; /* signal "show local time" */ #else # define z_modtim NULL #endif Info(slide, 0, ((char *)slide, " %s %s ", methbuf, zi_time(__G__ &G.crec.last_mod_dos_datetime, z_modtim, d_t_buf))); fnprint(__G); /*--------------------------------------------------------------------------- Skip the file comment, if any (the filename has already been printed, above). That finishes up this file entry... ---------------------------------------------------------------------------*/ SKIP_(G.crec.file_comment_length) return error_in_archive; } /* end function zi_short() */ /**************************************/ /* Function zi_showMacTypeCreator() */ /**************************************/ static void zi_showMacTypeCreator(__G__ ebfield) __GDEF uch *ebfield; { /* not every Type / Creator character is printable */ if (isprint(native(ebfield[0])) && isprint(native(ebfield[1])) && isprint(native(ebfield[2])) && isprint(native(ebfield[3])) && isprint(native(ebfield[4])) && isprint(native(ebfield[5])) && isprint(native(ebfield[6])) && isprint(native(ebfield[7]))) { Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata), native(ebfield[0]), native(ebfield[1]), native(ebfield[2]), native(ebfield[3]), native(ebfield[4]), native(ebfield[5]), native(ebfield[6]), native(ebfield[7]))); } else { Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata1), (((ulg)ebfield[0]) << 24) + (((ulg)ebfield[1]) << 16) + (((ulg)ebfield[2]) << 8) + ((ulg)ebfield[3]), (((ulg)ebfield[4]) << 24) + (((ulg)ebfield[5]) << 16) + (((ulg)ebfield[6]) << 8) + ((ulg)ebfield[7]))); } } /* end function zi_showMacTypeCreator() */ /************************/ /* Function zi_time() */ /************************/ static char *zi_time(__G__ datetimez, modtimez, d_t_str) __GDEF ZCONST ulg *datetimez; ZCONST time_t *modtimez; char *d_t_str; { unsigned yr, mo, dy, hh, mm, ss; char monthbuf[4]; ZCONST char *monthstr; static ZCONST char Far month[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; #ifdef USE_EF_UT_TIME struct tm *t; #endif /*--------------------------------------------------------------------------- Convert the file-modification date and time info to a string of the form "1991 Feb 23 17:15:00", "23-Feb-91 17:15" or "19910223.171500", depending on values of lflag and T_flag. If using Unix-time extra fields, convert to local time or not, depending on value of first character in d_t_str[]. ---------------------------------------------------------------------------*/ #ifdef USE_EF_UT_TIME if (modtimez != NULL) { #ifndef NO_GMTIME /* check for our secret message from above... */ t = (d_t_str[0] == (char)1)? gmtime(modtimez) : localtime(modtimez); #else t = localtime(modtimez); #endif if (uO.lflag > 9 && t == (struct tm *)NULL) /* time conversion error in verbose listing format, * return string with '?' instead of data */ return (strcpy(d_t_str, LoadFarString(lngYMDHMSTimeError))); } else t = (struct tm *)NULL; if (t != (struct tm *)NULL) { mo = (unsigned)(t->tm_mon + 1); dy = (unsigned)(t->tm_mday); yr = (unsigned)(t->tm_year); hh = (unsigned)(t->tm_hour); mm = (unsigned)(t->tm_min); ss = (unsigned)(t->tm_sec); } else #endif /* USE_EF_UT_TIME */ { yr = ((unsigned)(*datetimez >> 25) & 0x7f) + 80; mo = ((unsigned)(*datetimez >> 21) & 0x0f); dy = ((unsigned)(*datetimez >> 16) & 0x1f); hh = (((unsigned)*datetimez >> 11) & 0x1f); mm = (((unsigned)*datetimez >> 5) & 0x3f); ss = (((unsigned)*datetimez << 1) & 0x3e); } if (mo == 0 || mo > 12) { sprintf(monthbuf, LoadFarString(BogusFmt), mo); monthstr = monthbuf; } else monthstr = LoadFarStringSmall(month[mo-1]); if (uO.lflag > 9) /* verbose listing format */ sprintf(d_t_str, LoadFarString(lngYMDHMSTime), yr+1900, monthstr, dy, hh, mm, ss); else if (uO.T_flag) sprintf(d_t_str, LoadFarString(DecimalTime), yr+1900, mo, dy, hh, mm, ss); else /* was: if ((uO.lflag >= 3) && (uO.lflag <= 5)) */ sprintf(d_t_str, LoadFarString(shtYMDHMTime), yr%100, monthstr, dy, hh, mm); return d_t_str; } /* end function zi_time() */ #endif /* !NO_ZIPINFO */ Carla-2.1/data/windows/unzipfx-carla/000077500000000000000000000000001364475620200175755ustar00rootroot00000000000000Carla-2.1/data/windows/unzipfx-carla/.gitignore000066400000000000000000000000411364475620200215600ustar00rootroot00000000000000 *~ *.o *.exe *.zip unzipfx2cat Carla-2.1/data/windows/unzipfx-carla/Makefile.linux000066400000000000000000000012051364475620200223710ustar00rootroot00000000000000#!/usr/bin/Makefile -f CC ?= gcc BUILD_FLAGS = -DSFX -DLINUX -I. -I.. $(CFLAGS) -O2 BUILD_FLAGS += -DLARGE_FILE_SUPPORT -DUNICODE_SUPPORT -DUNICODE_WCHAR -DUTF8_MAYBE_NATIVE BUILD_FLAGS += -DNO_LCHMOD -DHAVE_DIRENT_H -DHAVE_TERMIOS_H -D_MBCS LINK_FLAGS = -static $(LDFLAGS) OBJ = crc32.o crypt.o extract.o fileio.o globals.o inflate.o match.o process.o ttyio.o ubz2err.o unzip.o zipinfo.o OBJ += unix/unix.o OBJ += unzipfx/appDetails.o # ----------------------------- all: unzipfx2cat unzipfx2cat: $(OBJ) $(CC) $^ $(LINK_FLAGS) -o $@ clean: rm -f *~ $(OBJ) # ----------------------------- .c.o: $(CC) $< $(BUILD_FLAGS) -c -o $@ Carla-2.1/data/windows/unzipfx-carla/Makefile.win32000066400000000000000000000015261364475620200222020ustar00rootroot00000000000000#!/usr/bin/Makefile -f CC ?= gcc WINDRES ?= windres BUILD_FLAGS = -DSFX -DWIN32 -DWINDOWS -DFORCE_UNIX_OVER_WIN32 -I. -I.. $(CFLAGS) -O2 BUILD_FLAGS += -DLARGE_FILE_SUPPORT -DUNICODE_SUPPORT -DUNICODE_WCHAR -DUTF8_MAYBE_NATIVE BUILD_FLAGS += -DNO_LCHMOD -DHAVE_DIRENT_H -DHAVE_TERMIOS_H -D_MBCS LINK_FLAGS = -static -mwindows -lkernel32 -lshell32 $(LDFLAGS) OBJ = crc32.o crypt.o extract.o fileio.o globals.o inflate.o match.o process.o ttyio.o ubz2err.o unzip.o zipinfo.o OBJ += win32/nt.o win32/win32.o win32/win32i64.o OBJ += unzipfx/appDetails.o OBJ += icon.o # ----------------------------- all: unzipfx2cat.exe unzipfx2cat.exe: $(OBJ) $(CC) $^ $(LINK_FLAGS) -o $@ icon.o: ../../../resources/ico/carla.rc $(WINDRES) -i $< -o $@ -O coff clean: rm -f *~ $(OBJ) # ----------------------------- .c.o: $(CC) $< $(BUILD_FLAGS) -c -o $@ Carla-2.1/data/windows/unzipfx-carla/README000066400000000000000000000016061364475620200204600ustar00rootroot00000000000000This is a special build of unzip's unzipfx tool, modified to allow full application bundles. You get a static linked binary that extracts your files into a temporary location, then executes the main program (defined by you). Currently working under Linux only, but should be fairly easy to get it into other OSes (unzip itself is already available in many, including Windows, MacOS, Linux and BeOS). To get a static unzipfx application, you do: 1 - create a zip file of your application bundle, with a single parent/root directory (this directory and the main app-name must match) 2 - edit unzipfx/appDetails.h and set SFX_APP_MININAME as the directory name set in step 1 3 - compile this tool using the appropriate makefile (eg: make -f Makefile.linux). That will give you 'unzipfx2cat' binary 4 - concatenate your zip file over the 'unzipfx2cat' binary (eg: cat unzipfx2cat myapp.zip > myapp) Carla-2.1/data/windows/unzipfx-carla/consts.h000066400000000000000000000037341364475620200212660ustar00rootroot00000000000000/* Copyright (c) 1990-2001 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- consts.h This file contains global, initialized variables that never change. It is included by unzip.c and windll/windll.c. ---------------------------------------------------------------------------*/ /* And'ing with mask_bits[n] masks the lower n bits */ ZCONST unsigned near mask_bits[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; ZCONST char Far VersionDate[] = UZ_VERSION_DATE; /* now defined in unzvers.h */ #ifndef SFX ZCONST char Far EndSigMsg[] = "\nnote: didn't find end-of-central-dir signature at end of central dir.\n"; #endif ZCONST char Far CentSigMsg[] = "error: expected central file header signature not found (file #%lu).\n"; ZCONST char Far SeekMsg[] = "error [%s]: attempt to seek before beginning of zipfile\n%s"; ZCONST char Far FilenameNotMatched[] = "caution: filename not matched: %s\n"; ZCONST char Far ExclFilenameNotMatched[] = "caution: excluded filename not matched: %s\n"; #ifdef VMS ZCONST char Far ReportMsg[] = "\ (please check that you have transferred or created the zipfile in the\n\ appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\n"; #else ZCONST char Far ReportMsg[] = "\ (please check that you have transferred or created the zipfile in the\n\ appropriate BINARY mode and that you have compiled UnZip properly)\n"; #endif #ifndef SFX ZCONST char Far Zipnfo[] = "zipinfo"; ZCONST char Far CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n"; #endif Carla-2.1/data/windows/unzipfx-carla/crc32.c000066400000000000000000001133561364475620200206660ustar00rootroot00000000000000/* Copyright (c) 1990-2007 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2005-Feb-10 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crc32.c -- compute the CRC-32 of a data stream * Copyright (C) 1995 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing * tables for updating the shift register in one step with three exclusive-ors * instead of four steps with four exclusive-ors. This results about a factor * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. */ /* $Id: crc32.c,v 2.0 2007/01/07 05:20:36 spc Exp $ */ #define __CRC32_C /* identifies this source module */ #include "zip.h" #if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) #ifndef ZCONST # define ZCONST const #endif #include "crc32.h" /* When only the table of precomputed CRC values is needed, only the basic system-independent table containing 256 entries is created; any support for "unfolding" optimization is disabled. */ #if (defined(USE_ZLIB) || defined(CRC_TABLE_ONLY)) # ifdef IZ_CRCOPTIM_UNFOLDTBL # undef IZ_CRCOPTIM_UNFOLDTBL # endif #endif /* (USE_ZLIB || CRC_TABLE_ONLY) */ #if defined(IZ_CRCOPTIM_UNFOLDTBL) # define CRC_TBLS 4 #else # define CRC_TBLS 1 #endif /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. Polynomials over GF(2) are represented in binary, one bit per coefficient, with the lowest powers in the most significant bit. Then adding polynomials is just exclusive-or, and multiplying a polynomial by x is a right shift by one. If we call the above polynomial p, and represent a byte as the polynomial q, also with the lowest power in the most significant bit (so the byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, where a mod b means the remainder after dividing a by b. This calculation is done using the shift-register method of multiplying and taking the remainder. The register is initialized to zero, and for each incoming bit, x^32 is added mod p to the register if the bit is a one (where x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x (which is shifting right by one and adding x^32 mod p if the bit shifted out is a one). We start with the highest power (least significant bit) of q and repeat for all eight bits of q. The first (or only) table is simply the CRC of all possible eight bit values. This is all the information needed to generate CRC's on data a byte-at-a-time for all combinations of CRC register values and incoming bytes. The remaining 3 tables (if IZ_CRCOPTIM_UNFOLDTBL is enabled) allow for word-at-a-time CRC calculation, where a word is four bytes. */ #ifdef DYNAMIC_CRC_TABLE /* ========================================================================= * Make the crc table. This function is needed only if you want to compute * the table dynamically. */ local void make_crc_table OF((void)); #if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT)) error: Dynamic allocation of CRC table not safe with reentrant code. #endif /* DYNALLOC_CRCTAB && REENTRANT */ #ifdef DYNALLOC_CRCTAB local ulg near *crc_table = NULL; # if 0 /* not used, since sizeof("near *") <= sizeof(int) */ /* Use this section when access to a "local int" is faster than access to a "local pointer" (e.g.: i86 16bit code with far pointers). */ local int crc_table_empty = 1; # define CRC_TABLE_IS_EMPTY (crc_table_empty != 0) # define MARK_CRCTAB_FILLED crc_table_empty = 0 # define MARK_CRCTAB_EMPTY crc_table_empty = 1 # else /* Use this section on systems where the size of pointers and ints is equal (e.g.: all 32bit systems). */ # define CRC_TABLE_IS_EMPTY (crc_table == NULL) # define MARK_CRCTAB_FILLED crc_table = crctab_p # define MARK_CRCTAB_EMPTY crc_table = NULL # endif #else /* !DYNALLOC_CRCTAB */ local ulg near crc_table[CRC_TBLS*256]; local int crc_table_empty = 1; # define CRC_TABLE_IS_EMPTY (crc_table_empty != 0) # define MARK_CRCTAB_FILLED crc_table_empty = 0 #endif /* ?DYNALLOC_CRCTAB */ local void make_crc_table() { ulg c; /* crc shift register */ int n; /* counter for all possible eight bit values */ int k; /* byte being shifted into crc apparatus */ #ifdef DYNALLOC_CRCTAB ulg near *crctab_p; /* temporary pointer to allocated crc_table area */ #else /* !DYNALLOC_CRCTAB */ # define crctab_p crc_table #endif /* DYNALLOC_CRCTAB */ #ifdef COMPUTE_XOR_PATTERN /* This piece of code has been left here to explain how the XOR pattern * used in the creation of the crc_table values can be recomputed. * For production versions of this function, it is more efficient to * supply the resultant pattern at compile time. */ ulg xor; /* polynomial exclusive-or pattern */ /* terms of polynomial defining this crc (except x^32): */ static ZCONST uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; /* make exclusive-or pattern from polynomial (0xedb88320L) */ xor = 0L; for (n = 0; n < sizeof(p)/sizeof(uch); n++) xor |= 1L << (31 - p[n]); #else # define xor 0xedb88320L #endif #ifdef DYNALLOC_CRCTAB crctab_p = (ulg near *) nearmalloc (CRC_TBLS*256*sizeof(ulg)); if (crctab_p == NULL) { ziperr(ZE_MEM, "crc_table allocation"); } #endif /* DYNALLOC_CRCTAB */ /* generate a crc for every 8-bit value */ for (n = 0; n < 256; n++) { c = (ulg)n; for (k = 8; k; k--) c = c & 1 ? xor ^ (c >> 1) : c >> 1; crctab_p[n] = REV_BE(c); } #ifdef IZ_CRCOPTIM_UNFOLDTBL /* generate crc for each value followed by one, two, and three zeros */ for (n = 0; n < 256; n++) { c = crctab_p[n]; for (k = 1; k < 4; k++) { c = CRC32(c, 0, crctab_p); crctab_p[k*256+n] = c; } } #endif /* IZ_CRCOPTIM_UNFOLDTBL */ MARK_CRCTAB_FILLED; } #else /* !DYNAMIC_CRC_TABLE */ #ifdef DYNALLOC_CRCTAB error: Inconsistent flags, DYNALLOC_CRCTAB without DYNAMIC_CRC_TABLE. #endif /* ======================================================================== * Table of CRC-32's of all single-byte values (made by make_crc_table) */ local ZCONST ulg near crc_table[CRC_TBLS*256] = { # ifdef IZ_CRC_BE_OPTIMIZ 0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L, 0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L, 0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L, 0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L, 0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L, 0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L, 0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L, 0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L, 0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L, 0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L, 0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL, 0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L, 0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L, 0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L, 0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L, 0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L, 0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL, 0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L, 0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL, 0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L, 0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L, 0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L, 0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL, 0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL, 0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L, 0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL, 0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L, 0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL, 0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L, 0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L, 0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L, 0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L, 0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L, 0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL, 0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L, 0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L, 0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L, 0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L, 0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L, 0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L, 0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L, 0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L, 0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL, 0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L, 0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L, 0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L, 0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L, 0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L, 0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL, 0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L, 0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL, 0x8def022dL # ifdef IZ_CRCOPTIM_UNFOLDTBL , 0x00000000L, 0x41311b19L, 0x82623632L, 0xc3532d2bL, 0x04c56c64L, 0x45f4777dL, 0x86a75a56L, 0xc796414fL, 0x088ad9c8L, 0x49bbc2d1L, 0x8ae8effaL, 0xcbd9f4e3L, 0x0c4fb5acL, 0x4d7eaeb5L, 0x8e2d839eL, 0xcf1c9887L, 0x5112c24aL, 0x1023d953L, 0xd370f478L, 0x9241ef61L, 0x55d7ae2eL, 0x14e6b537L, 0xd7b5981cL, 0x96848305L, 0x59981b82L, 0x18a9009bL, 0xdbfa2db0L, 0x9acb36a9L, 0x5d5d77e6L, 0x1c6c6cffL, 0xdf3f41d4L, 0x9e0e5acdL, 0xa2248495L, 0xe3159f8cL, 0x2046b2a7L, 0x6177a9beL, 0xa6e1e8f1L, 0xe7d0f3e8L, 0x2483dec3L, 0x65b2c5daL, 0xaaae5d5dL, 0xeb9f4644L, 0x28cc6b6fL, 0x69fd7076L, 0xae6b3139L, 0xef5a2a20L, 0x2c09070bL, 0x6d381c12L, 0xf33646dfL, 0xb2075dc6L, 0x715470edL, 0x30656bf4L, 0xf7f32abbL, 0xb6c231a2L, 0x75911c89L, 0x34a00790L, 0xfbbc9f17L, 0xba8d840eL, 0x79dea925L, 0x38efb23cL, 0xff79f373L, 0xbe48e86aL, 0x7d1bc541L, 0x3c2ade58L, 0x054f79f0L, 0x447e62e9L, 0x872d4fc2L, 0xc61c54dbL, 0x018a1594L, 0x40bb0e8dL, 0x83e823a6L, 0xc2d938bfL, 0x0dc5a038L, 0x4cf4bb21L, 0x8fa7960aL, 0xce968d13L, 0x0900cc5cL, 0x4831d745L, 0x8b62fa6eL, 0xca53e177L, 0x545dbbbaL, 0x156ca0a3L, 0xd63f8d88L, 0x970e9691L, 0x5098d7deL, 0x11a9ccc7L, 0xd2fae1ecL, 0x93cbfaf5L, 0x5cd76272L, 0x1de6796bL, 0xdeb55440L, 0x9f844f59L, 0x58120e16L, 0x1923150fL, 0xda703824L, 0x9b41233dL, 0xa76bfd65L, 0xe65ae67cL, 0x2509cb57L, 0x6438d04eL, 0xa3ae9101L, 0xe29f8a18L, 0x21cca733L, 0x60fdbc2aL, 0xafe124adL, 0xeed03fb4L, 0x2d83129fL, 0x6cb20986L, 0xab2448c9L, 0xea1553d0L, 0x29467efbL, 0x687765e2L, 0xf6793f2fL, 0xb7482436L, 0x741b091dL, 0x352a1204L, 0xf2bc534bL, 0xb38d4852L, 0x70de6579L, 0x31ef7e60L, 0xfef3e6e7L, 0xbfc2fdfeL, 0x7c91d0d5L, 0x3da0cbccL, 0xfa368a83L, 0xbb07919aL, 0x7854bcb1L, 0x3965a7a8L, 0x4b98833bL, 0x0aa99822L, 0xc9fab509L, 0x88cbae10L, 0x4f5def5fL, 0x0e6cf446L, 0xcd3fd96dL, 0x8c0ec274L, 0x43125af3L, 0x022341eaL, 0xc1706cc1L, 0x804177d8L, 0x47d73697L, 0x06e62d8eL, 0xc5b500a5L, 0x84841bbcL, 0x1a8a4171L, 0x5bbb5a68L, 0x98e87743L, 0xd9d96c5aL, 0x1e4f2d15L, 0x5f7e360cL, 0x9c2d1b27L, 0xdd1c003eL, 0x120098b9L, 0x533183a0L, 0x9062ae8bL, 0xd153b592L, 0x16c5f4ddL, 0x57f4efc4L, 0x94a7c2efL, 0xd596d9f6L, 0xe9bc07aeL, 0xa88d1cb7L, 0x6bde319cL, 0x2aef2a85L, 0xed796bcaL, 0xac4870d3L, 0x6f1b5df8L, 0x2e2a46e1L, 0xe136de66L, 0xa007c57fL, 0x6354e854L, 0x2265f34dL, 0xe5f3b202L, 0xa4c2a91bL, 0x67918430L, 0x26a09f29L, 0xb8aec5e4L, 0xf99fdefdL, 0x3accf3d6L, 0x7bfde8cfL, 0xbc6ba980L, 0xfd5ab299L, 0x3e099fb2L, 0x7f3884abL, 0xb0241c2cL, 0xf1150735L, 0x32462a1eL, 0x73773107L, 0xb4e17048L, 0xf5d06b51L, 0x3683467aL, 0x77b25d63L, 0x4ed7facbL, 0x0fe6e1d2L, 0xccb5ccf9L, 0x8d84d7e0L, 0x4a1296afL, 0x0b238db6L, 0xc870a09dL, 0x8941bb84L, 0x465d2303L, 0x076c381aL, 0xc43f1531L, 0x850e0e28L, 0x42984f67L, 0x03a9547eL, 0xc0fa7955L, 0x81cb624cL, 0x1fc53881L, 0x5ef42398L, 0x9da70eb3L, 0xdc9615aaL, 0x1b0054e5L, 0x5a314ffcL, 0x996262d7L, 0xd85379ceL, 0x174fe149L, 0x567efa50L, 0x952dd77bL, 0xd41ccc62L, 0x138a8d2dL, 0x52bb9634L, 0x91e8bb1fL, 0xd0d9a006L, 0xecf37e5eL, 0xadc26547L, 0x6e91486cL, 0x2fa05375L, 0xe836123aL, 0xa9070923L, 0x6a542408L, 0x2b653f11L, 0xe479a796L, 0xa548bc8fL, 0x661b91a4L, 0x272a8abdL, 0xe0bccbf2L, 0xa18dd0ebL, 0x62defdc0L, 0x23efe6d9L, 0xbde1bc14L, 0xfcd0a70dL, 0x3f838a26L, 0x7eb2913fL, 0xb924d070L, 0xf815cb69L, 0x3b46e642L, 0x7a77fd5bL, 0xb56b65dcL, 0xf45a7ec5L, 0x370953eeL, 0x763848f7L, 0xb1ae09b8L, 0xf09f12a1L, 0x33cc3f8aL, 0x72fd2493L , 0x00000000L, 0x376ac201L, 0x6ed48403L, 0x59be4602L, 0xdca80907L, 0xebc2cb06L, 0xb27c8d04L, 0x85164f05L, 0xb851130eL, 0x8f3bd10fL, 0xd685970dL, 0xe1ef550cL, 0x64f91a09L, 0x5393d808L, 0x0a2d9e0aL, 0x3d475c0bL, 0x70a3261cL, 0x47c9e41dL, 0x1e77a21fL, 0x291d601eL, 0xac0b2f1bL, 0x9b61ed1aL, 0xc2dfab18L, 0xf5b56919L, 0xc8f23512L, 0xff98f713L, 0xa626b111L, 0x914c7310L, 0x145a3c15L, 0x2330fe14L, 0x7a8eb816L, 0x4de47a17L, 0xe0464d38L, 0xd72c8f39L, 0x8e92c93bL, 0xb9f80b3aL, 0x3cee443fL, 0x0b84863eL, 0x523ac03cL, 0x6550023dL, 0x58175e36L, 0x6f7d9c37L, 0x36c3da35L, 0x01a91834L, 0x84bf5731L, 0xb3d59530L, 0xea6bd332L, 0xdd011133L, 0x90e56b24L, 0xa78fa925L, 0xfe31ef27L, 0xc95b2d26L, 0x4c4d6223L, 0x7b27a022L, 0x2299e620L, 0x15f32421L, 0x28b4782aL, 0x1fdeba2bL, 0x4660fc29L, 0x710a3e28L, 0xf41c712dL, 0xc376b32cL, 0x9ac8f52eL, 0xada2372fL, 0xc08d9a70L, 0xf7e75871L, 0xae591e73L, 0x9933dc72L, 0x1c259377L, 0x2b4f5176L, 0x72f11774L, 0x459bd575L, 0x78dc897eL, 0x4fb64b7fL, 0x16080d7dL, 0x2162cf7cL, 0xa4748079L, 0x931e4278L, 0xcaa0047aL, 0xfdcac67bL, 0xb02ebc6cL, 0x87447e6dL, 0xdefa386fL, 0xe990fa6eL, 0x6c86b56bL, 0x5bec776aL, 0x02523168L, 0x3538f369L, 0x087faf62L, 0x3f156d63L, 0x66ab2b61L, 0x51c1e960L, 0xd4d7a665L, 0xe3bd6464L, 0xba032266L, 0x8d69e067L, 0x20cbd748L, 0x17a11549L, 0x4e1f534bL, 0x7975914aL, 0xfc63de4fL, 0xcb091c4eL, 0x92b75a4cL, 0xa5dd984dL, 0x989ac446L, 0xaff00647L, 0xf64e4045L, 0xc1248244L, 0x4432cd41L, 0x73580f40L, 0x2ae64942L, 0x1d8c8b43L, 0x5068f154L, 0x67023355L, 0x3ebc7557L, 0x09d6b756L, 0x8cc0f853L, 0xbbaa3a52L, 0xe2147c50L, 0xd57ebe51L, 0xe839e25aL, 0xdf53205bL, 0x86ed6659L, 0xb187a458L, 0x3491eb5dL, 0x03fb295cL, 0x5a456f5eL, 0x6d2fad5fL, 0x801b35e1L, 0xb771f7e0L, 0xeecfb1e2L, 0xd9a573e3L, 0x5cb33ce6L, 0x6bd9fee7L, 0x3267b8e5L, 0x050d7ae4L, 0x384a26efL, 0x0f20e4eeL, 0x569ea2ecL, 0x61f460edL, 0xe4e22fe8L, 0xd388ede9L, 0x8a36abebL, 0xbd5c69eaL, 0xf0b813fdL, 0xc7d2d1fcL, 0x9e6c97feL, 0xa90655ffL, 0x2c101afaL, 0x1b7ad8fbL, 0x42c49ef9L, 0x75ae5cf8L, 0x48e900f3L, 0x7f83c2f2L, 0x263d84f0L, 0x115746f1L, 0x944109f4L, 0xa32bcbf5L, 0xfa958df7L, 0xcdff4ff6L, 0x605d78d9L, 0x5737bad8L, 0x0e89fcdaL, 0x39e33edbL, 0xbcf571deL, 0x8b9fb3dfL, 0xd221f5ddL, 0xe54b37dcL, 0xd80c6bd7L, 0xef66a9d6L, 0xb6d8efd4L, 0x81b22dd5L, 0x04a462d0L, 0x33cea0d1L, 0x6a70e6d3L, 0x5d1a24d2L, 0x10fe5ec5L, 0x27949cc4L, 0x7e2adac6L, 0x494018c7L, 0xcc5657c2L, 0xfb3c95c3L, 0xa282d3c1L, 0x95e811c0L, 0xa8af4dcbL, 0x9fc58fcaL, 0xc67bc9c8L, 0xf1110bc9L, 0x740744ccL, 0x436d86cdL, 0x1ad3c0cfL, 0x2db902ceL, 0x4096af91L, 0x77fc6d90L, 0x2e422b92L, 0x1928e993L, 0x9c3ea696L, 0xab546497L, 0xf2ea2295L, 0xc580e094L, 0xf8c7bc9fL, 0xcfad7e9eL, 0x9613389cL, 0xa179fa9dL, 0x246fb598L, 0x13057799L, 0x4abb319bL, 0x7dd1f39aL, 0x3035898dL, 0x075f4b8cL, 0x5ee10d8eL, 0x698bcf8fL, 0xec9d808aL, 0xdbf7428bL, 0x82490489L, 0xb523c688L, 0x88649a83L, 0xbf0e5882L, 0xe6b01e80L, 0xd1dadc81L, 0x54cc9384L, 0x63a65185L, 0x3a181787L, 0x0d72d586L, 0xa0d0e2a9L, 0x97ba20a8L, 0xce0466aaL, 0xf96ea4abL, 0x7c78ebaeL, 0x4b1229afL, 0x12ac6fadL, 0x25c6adacL, 0x1881f1a7L, 0x2feb33a6L, 0x765575a4L, 0x413fb7a5L, 0xc429f8a0L, 0xf3433aa1L, 0xaafd7ca3L, 0x9d97bea2L, 0xd073c4b5L, 0xe71906b4L, 0xbea740b6L, 0x89cd82b7L, 0x0cdbcdb2L, 0x3bb10fb3L, 0x620f49b1L, 0x55658bb0L, 0x6822d7bbL, 0x5f4815baL, 0x06f653b8L, 0x319c91b9L, 0xb48adebcL, 0x83e01cbdL, 0xda5e5abfL, 0xed3498beL , 0x00000000L, 0x6567bcb8L, 0x8bc809aaL, 0xeeafb512L, 0x5797628fL, 0x32f0de37L, 0xdc5f6b25L, 0xb938d79dL, 0xef28b4c5L, 0x8a4f087dL, 0x64e0bd6fL, 0x018701d7L, 0xb8bfd64aL, 0xddd86af2L, 0x3377dfe0L, 0x56106358L, 0x9f571950L, 0xfa30a5e8L, 0x149f10faL, 0x71f8ac42L, 0xc8c07bdfL, 0xada7c767L, 0x43087275L, 0x266fcecdL, 0x707fad95L, 0x1518112dL, 0xfbb7a43fL, 0x9ed01887L, 0x27e8cf1aL, 0x428f73a2L, 0xac20c6b0L, 0xc9477a08L, 0x3eaf32a0L, 0x5bc88e18L, 0xb5673b0aL, 0xd00087b2L, 0x6938502fL, 0x0c5fec97L, 0xe2f05985L, 0x8797e53dL, 0xd1878665L, 0xb4e03addL, 0x5a4f8fcfL, 0x3f283377L, 0x8610e4eaL, 0xe3775852L, 0x0dd8ed40L, 0x68bf51f8L, 0xa1f82bf0L, 0xc49f9748L, 0x2a30225aL, 0x4f579ee2L, 0xf66f497fL, 0x9308f5c7L, 0x7da740d5L, 0x18c0fc6dL, 0x4ed09f35L, 0x2bb7238dL, 0xc518969fL, 0xa07f2a27L, 0x1947fdbaL, 0x7c204102L, 0x928ff410L, 0xf7e848a8L, 0x3d58149bL, 0x583fa823L, 0xb6901d31L, 0xd3f7a189L, 0x6acf7614L, 0x0fa8caacL, 0xe1077fbeL, 0x8460c306L, 0xd270a05eL, 0xb7171ce6L, 0x59b8a9f4L, 0x3cdf154cL, 0x85e7c2d1L, 0xe0807e69L, 0x0e2fcb7bL, 0x6b4877c3L, 0xa20f0dcbL, 0xc768b173L, 0x29c70461L, 0x4ca0b8d9L, 0xf5986f44L, 0x90ffd3fcL, 0x7e5066eeL, 0x1b37da56L, 0x4d27b90eL, 0x284005b6L, 0xc6efb0a4L, 0xa3880c1cL, 0x1ab0db81L, 0x7fd76739L, 0x9178d22bL, 0xf41f6e93L, 0x03f7263bL, 0x66909a83L, 0x883f2f91L, 0xed589329L, 0x546044b4L, 0x3107f80cL, 0xdfa84d1eL, 0xbacff1a6L, 0xecdf92feL, 0x89b82e46L, 0x67179b54L, 0x027027ecL, 0xbb48f071L, 0xde2f4cc9L, 0x3080f9dbL, 0x55e74563L, 0x9ca03f6bL, 0xf9c783d3L, 0x176836c1L, 0x720f8a79L, 0xcb375de4L, 0xae50e15cL, 0x40ff544eL, 0x2598e8f6L, 0x73888baeL, 0x16ef3716L, 0xf8408204L, 0x9d273ebcL, 0x241fe921L, 0x41785599L, 0xafd7e08bL, 0xcab05c33L, 0x3bb659edL, 0x5ed1e555L, 0xb07e5047L, 0xd519ecffL, 0x6c213b62L, 0x094687daL, 0xe7e932c8L, 0x828e8e70L, 0xd49eed28L, 0xb1f95190L, 0x5f56e482L, 0x3a31583aL, 0x83098fa7L, 0xe66e331fL, 0x08c1860dL, 0x6da63ab5L, 0xa4e140bdL, 0xc186fc05L, 0x2f294917L, 0x4a4ef5afL, 0xf3762232L, 0x96119e8aL, 0x78be2b98L, 0x1dd99720L, 0x4bc9f478L, 0x2eae48c0L, 0xc001fdd2L, 0xa566416aL, 0x1c5e96f7L, 0x79392a4fL, 0x97969f5dL, 0xf2f123e5L, 0x05196b4dL, 0x607ed7f5L, 0x8ed162e7L, 0xebb6de5fL, 0x528e09c2L, 0x37e9b57aL, 0xd9460068L, 0xbc21bcd0L, 0xea31df88L, 0x8f566330L, 0x61f9d622L, 0x049e6a9aL, 0xbda6bd07L, 0xd8c101bfL, 0x366eb4adL, 0x53090815L, 0x9a4e721dL, 0xff29cea5L, 0x11867bb7L, 0x74e1c70fL, 0xcdd91092L, 0xa8beac2aL, 0x46111938L, 0x2376a580L, 0x7566c6d8L, 0x10017a60L, 0xfeaecf72L, 0x9bc973caL, 0x22f1a457L, 0x479618efL, 0xa939adfdL, 0xcc5e1145L, 0x06ee4d76L, 0x6389f1ceL, 0x8d2644dcL, 0xe841f864L, 0x51792ff9L, 0x341e9341L, 0xdab12653L, 0xbfd69aebL, 0xe9c6f9b3L, 0x8ca1450bL, 0x620ef019L, 0x07694ca1L, 0xbe519b3cL, 0xdb362784L, 0x35999296L, 0x50fe2e2eL, 0x99b95426L, 0xfcdee89eL, 0x12715d8cL, 0x7716e134L, 0xce2e36a9L, 0xab498a11L, 0x45e63f03L, 0x208183bbL, 0x7691e0e3L, 0x13f65c5bL, 0xfd59e949L, 0x983e55f1L, 0x2106826cL, 0x44613ed4L, 0xaace8bc6L, 0xcfa9377eL, 0x38417fd6L, 0x5d26c36eL, 0xb389767cL, 0xd6eecac4L, 0x6fd61d59L, 0x0ab1a1e1L, 0xe41e14f3L, 0x8179a84bL, 0xd769cb13L, 0xb20e77abL, 0x5ca1c2b9L, 0x39c67e01L, 0x80fea99cL, 0xe5991524L, 0x0b36a036L, 0x6e511c8eL, 0xa7166686L, 0xc271da3eL, 0x2cde6f2cL, 0x49b9d394L, 0xf0810409L, 0x95e6b8b1L, 0x7b490da3L, 0x1e2eb11bL, 0x483ed243L, 0x2d596efbL, 0xc3f6dbe9L, 0xa6916751L, 0x1fa9b0ccL, 0x7ace0c74L, 0x9461b966L, 0xf10605deL # endif /* IZ_CRCOPTIM_UNFOLDTBL */ # else /* !IZ_CRC_BE_OPTIMIZ */ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL # ifdef IZ_CRCOPTIM_UNFOLDTBL , 0x00000000L, 0x191b3141L, 0x32366282L, 0x2b2d53c3L, 0x646cc504L, 0x7d77f445L, 0x565aa786L, 0x4f4196c7L, 0xc8d98a08L, 0xd1c2bb49L, 0xfaefe88aL, 0xe3f4d9cbL, 0xacb54f0cL, 0xb5ae7e4dL, 0x9e832d8eL, 0x87981ccfL, 0x4ac21251L, 0x53d92310L, 0x78f470d3L, 0x61ef4192L, 0x2eaed755L, 0x37b5e614L, 0x1c98b5d7L, 0x05838496L, 0x821b9859L, 0x9b00a918L, 0xb02dfadbL, 0xa936cb9aL, 0xe6775d5dL, 0xff6c6c1cL, 0xd4413fdfL, 0xcd5a0e9eL, 0x958424a2L, 0x8c9f15e3L, 0xa7b24620L, 0xbea97761L, 0xf1e8e1a6L, 0xe8f3d0e7L, 0xc3de8324L, 0xdac5b265L, 0x5d5daeaaL, 0x44469febL, 0x6f6bcc28L, 0x7670fd69L, 0x39316baeL, 0x202a5aefL, 0x0b07092cL, 0x121c386dL, 0xdf4636f3L, 0xc65d07b2L, 0xed705471L, 0xf46b6530L, 0xbb2af3f7L, 0xa231c2b6L, 0x891c9175L, 0x9007a034L, 0x179fbcfbL, 0x0e848dbaL, 0x25a9de79L, 0x3cb2ef38L, 0x73f379ffL, 0x6ae848beL, 0x41c51b7dL, 0x58de2a3cL, 0xf0794f05L, 0xe9627e44L, 0xc24f2d87L, 0xdb541cc6L, 0x94158a01L, 0x8d0ebb40L, 0xa623e883L, 0xbf38d9c2L, 0x38a0c50dL, 0x21bbf44cL, 0x0a96a78fL, 0x138d96ceL, 0x5ccc0009L, 0x45d73148L, 0x6efa628bL, 0x77e153caL, 0xbabb5d54L, 0xa3a06c15L, 0x888d3fd6L, 0x91960e97L, 0xded79850L, 0xc7cca911L, 0xece1fad2L, 0xf5facb93L, 0x7262d75cL, 0x6b79e61dL, 0x4054b5deL, 0x594f849fL, 0x160e1258L, 0x0f152319L, 0x243870daL, 0x3d23419bL, 0x65fd6ba7L, 0x7ce65ae6L, 0x57cb0925L, 0x4ed03864L, 0x0191aea3L, 0x188a9fe2L, 0x33a7cc21L, 0x2abcfd60L, 0xad24e1afL, 0xb43fd0eeL, 0x9f12832dL, 0x8609b26cL, 0xc94824abL, 0xd05315eaL, 0xfb7e4629L, 0xe2657768L, 0x2f3f79f6L, 0x362448b7L, 0x1d091b74L, 0x04122a35L, 0x4b53bcf2L, 0x52488db3L, 0x7965de70L, 0x607eef31L, 0xe7e6f3feL, 0xfefdc2bfL, 0xd5d0917cL, 0xcccba03dL, 0x838a36faL, 0x9a9107bbL, 0xb1bc5478L, 0xa8a76539L, 0x3b83984bL, 0x2298a90aL, 0x09b5fac9L, 0x10aecb88L, 0x5fef5d4fL, 0x46f46c0eL, 0x6dd93fcdL, 0x74c20e8cL, 0xf35a1243L, 0xea412302L, 0xc16c70c1L, 0xd8774180L, 0x9736d747L, 0x8e2de606L, 0xa500b5c5L, 0xbc1b8484L, 0x71418a1aL, 0x685abb5bL, 0x4377e898L, 0x5a6cd9d9L, 0x152d4f1eL, 0x0c367e5fL, 0x271b2d9cL, 0x3e001cddL, 0xb9980012L, 0xa0833153L, 0x8bae6290L, 0x92b553d1L, 0xddf4c516L, 0xc4eff457L, 0xefc2a794L, 0xf6d996d5L, 0xae07bce9L, 0xb71c8da8L, 0x9c31de6bL, 0x852aef2aL, 0xca6b79edL, 0xd37048acL, 0xf85d1b6fL, 0xe1462a2eL, 0x66de36e1L, 0x7fc507a0L, 0x54e85463L, 0x4df36522L, 0x02b2f3e5L, 0x1ba9c2a4L, 0x30849167L, 0x299fa026L, 0xe4c5aeb8L, 0xfdde9ff9L, 0xd6f3cc3aL, 0xcfe8fd7bL, 0x80a96bbcL, 0x99b25afdL, 0xb29f093eL, 0xab84387fL, 0x2c1c24b0L, 0x350715f1L, 0x1e2a4632L, 0x07317773L, 0x4870e1b4L, 0x516bd0f5L, 0x7a468336L, 0x635db277L, 0xcbfad74eL, 0xd2e1e60fL, 0xf9ccb5ccL, 0xe0d7848dL, 0xaf96124aL, 0xb68d230bL, 0x9da070c8L, 0x84bb4189L, 0x03235d46L, 0x1a386c07L, 0x31153fc4L, 0x280e0e85L, 0x674f9842L, 0x7e54a903L, 0x5579fac0L, 0x4c62cb81L, 0x8138c51fL, 0x9823f45eL, 0xb30ea79dL, 0xaa1596dcL, 0xe554001bL, 0xfc4f315aL, 0xd7626299L, 0xce7953d8L, 0x49e14f17L, 0x50fa7e56L, 0x7bd72d95L, 0x62cc1cd4L, 0x2d8d8a13L, 0x3496bb52L, 0x1fbbe891L, 0x06a0d9d0L, 0x5e7ef3ecL, 0x4765c2adL, 0x6c48916eL, 0x7553a02fL, 0x3a1236e8L, 0x230907a9L, 0x0824546aL, 0x113f652bL, 0x96a779e4L, 0x8fbc48a5L, 0xa4911b66L, 0xbd8a2a27L, 0xf2cbbce0L, 0xebd08da1L, 0xc0fdde62L, 0xd9e6ef23L, 0x14bce1bdL, 0x0da7d0fcL, 0x268a833fL, 0x3f91b27eL, 0x70d024b9L, 0x69cb15f8L, 0x42e6463bL, 0x5bfd777aL, 0xdc656bb5L, 0xc57e5af4L, 0xee530937L, 0xf7483876L, 0xb809aeb1L, 0xa1129ff0L, 0x8a3fcc33L, 0x9324fd72L , 0x00000000L, 0x01c26a37L, 0x0384d46eL, 0x0246be59L, 0x0709a8dcL, 0x06cbc2ebL, 0x048d7cb2L, 0x054f1685L, 0x0e1351b8L, 0x0fd13b8fL, 0x0d9785d6L, 0x0c55efe1L, 0x091af964L, 0x08d89353L, 0x0a9e2d0aL, 0x0b5c473dL, 0x1c26a370L, 0x1de4c947L, 0x1fa2771eL, 0x1e601d29L, 0x1b2f0bacL, 0x1aed619bL, 0x18abdfc2L, 0x1969b5f5L, 0x1235f2c8L, 0x13f798ffL, 0x11b126a6L, 0x10734c91L, 0x153c5a14L, 0x14fe3023L, 0x16b88e7aL, 0x177ae44dL, 0x384d46e0L, 0x398f2cd7L, 0x3bc9928eL, 0x3a0bf8b9L, 0x3f44ee3cL, 0x3e86840bL, 0x3cc03a52L, 0x3d025065L, 0x365e1758L, 0x379c7d6fL, 0x35dac336L, 0x3418a901L, 0x3157bf84L, 0x3095d5b3L, 0x32d36beaL, 0x331101ddL, 0x246be590L, 0x25a98fa7L, 0x27ef31feL, 0x262d5bc9L, 0x23624d4cL, 0x22a0277bL, 0x20e69922L, 0x2124f315L, 0x2a78b428L, 0x2bbade1fL, 0x29fc6046L, 0x283e0a71L, 0x2d711cf4L, 0x2cb376c3L, 0x2ef5c89aL, 0x2f37a2adL, 0x709a8dc0L, 0x7158e7f7L, 0x731e59aeL, 0x72dc3399L, 0x7793251cL, 0x76514f2bL, 0x7417f172L, 0x75d59b45L, 0x7e89dc78L, 0x7f4bb64fL, 0x7d0d0816L, 0x7ccf6221L, 0x798074a4L, 0x78421e93L, 0x7a04a0caL, 0x7bc6cafdL, 0x6cbc2eb0L, 0x6d7e4487L, 0x6f38fadeL, 0x6efa90e9L, 0x6bb5866cL, 0x6a77ec5bL, 0x68315202L, 0x69f33835L, 0x62af7f08L, 0x636d153fL, 0x612bab66L, 0x60e9c151L, 0x65a6d7d4L, 0x6464bde3L, 0x662203baL, 0x67e0698dL, 0x48d7cb20L, 0x4915a117L, 0x4b531f4eL, 0x4a917579L, 0x4fde63fcL, 0x4e1c09cbL, 0x4c5ab792L, 0x4d98dda5L, 0x46c49a98L, 0x4706f0afL, 0x45404ef6L, 0x448224c1L, 0x41cd3244L, 0x400f5873L, 0x4249e62aL, 0x438b8c1dL, 0x54f16850L, 0x55330267L, 0x5775bc3eL, 0x56b7d609L, 0x53f8c08cL, 0x523aaabbL, 0x507c14e2L, 0x51be7ed5L, 0x5ae239e8L, 0x5b2053dfL, 0x5966ed86L, 0x58a487b1L, 0x5deb9134L, 0x5c29fb03L, 0x5e6f455aL, 0x5fad2f6dL, 0xe1351b80L, 0xe0f771b7L, 0xe2b1cfeeL, 0xe373a5d9L, 0xe63cb35cL, 0xe7fed96bL, 0xe5b86732L, 0xe47a0d05L, 0xef264a38L, 0xeee4200fL, 0xeca29e56L, 0xed60f461L, 0xe82fe2e4L, 0xe9ed88d3L, 0xebab368aL, 0xea695cbdL, 0xfd13b8f0L, 0xfcd1d2c7L, 0xfe976c9eL, 0xff5506a9L, 0xfa1a102cL, 0xfbd87a1bL, 0xf99ec442L, 0xf85cae75L, 0xf300e948L, 0xf2c2837fL, 0xf0843d26L, 0xf1465711L, 0xf4094194L, 0xf5cb2ba3L, 0xf78d95faL, 0xf64fffcdL, 0xd9785d60L, 0xd8ba3757L, 0xdafc890eL, 0xdb3ee339L, 0xde71f5bcL, 0xdfb39f8bL, 0xddf521d2L, 0xdc374be5L, 0xd76b0cd8L, 0xd6a966efL, 0xd4efd8b6L, 0xd52db281L, 0xd062a404L, 0xd1a0ce33L, 0xd3e6706aL, 0xd2241a5dL, 0xc55efe10L, 0xc49c9427L, 0xc6da2a7eL, 0xc7184049L, 0xc25756ccL, 0xc3953cfbL, 0xc1d382a2L, 0xc011e895L, 0xcb4dafa8L, 0xca8fc59fL, 0xc8c97bc6L, 0xc90b11f1L, 0xcc440774L, 0xcd866d43L, 0xcfc0d31aL, 0xce02b92dL, 0x91af9640L, 0x906dfc77L, 0x922b422eL, 0x93e92819L, 0x96a63e9cL, 0x976454abL, 0x9522eaf2L, 0x94e080c5L, 0x9fbcc7f8L, 0x9e7eadcfL, 0x9c381396L, 0x9dfa79a1L, 0x98b56f24L, 0x99770513L, 0x9b31bb4aL, 0x9af3d17dL, 0x8d893530L, 0x8c4b5f07L, 0x8e0de15eL, 0x8fcf8b69L, 0x8a809decL, 0x8b42f7dbL, 0x89044982L, 0x88c623b5L, 0x839a6488L, 0x82580ebfL, 0x801eb0e6L, 0x81dcdad1L, 0x8493cc54L, 0x8551a663L, 0x8717183aL, 0x86d5720dL, 0xa9e2d0a0L, 0xa820ba97L, 0xaa6604ceL, 0xaba46ef9L, 0xaeeb787cL, 0xaf29124bL, 0xad6fac12L, 0xacadc625L, 0xa7f18118L, 0xa633eb2fL, 0xa4755576L, 0xa5b73f41L, 0xa0f829c4L, 0xa13a43f3L, 0xa37cfdaaL, 0xa2be979dL, 0xb5c473d0L, 0xb40619e7L, 0xb640a7beL, 0xb782cd89L, 0xb2cddb0cL, 0xb30fb13bL, 0xb1490f62L, 0xb08b6555L, 0xbbd72268L, 0xba15485fL, 0xb853f606L, 0xb9919c31L, 0xbcde8ab4L, 0xbd1ce083L, 0xbf5a5edaL, 0xbe9834edL , 0x00000000L, 0xb8bc6765L, 0xaa09c88bL, 0x12b5afeeL, 0x8f629757L, 0x37def032L, 0x256b5fdcL, 0x9dd738b9L, 0xc5b428efL, 0x7d084f8aL, 0x6fbde064L, 0xd7018701L, 0x4ad6bfb8L, 0xf26ad8ddL, 0xe0df7733L, 0x58631056L, 0x5019579fL, 0xe8a530faL, 0xfa109f14L, 0x42acf871L, 0xdf7bc0c8L, 0x67c7a7adL, 0x75720843L, 0xcdce6f26L, 0x95ad7f70L, 0x2d111815L, 0x3fa4b7fbL, 0x8718d09eL, 0x1acfe827L, 0xa2738f42L, 0xb0c620acL, 0x087a47c9L, 0xa032af3eL, 0x188ec85bL, 0x0a3b67b5L, 0xb28700d0L, 0x2f503869L, 0x97ec5f0cL, 0x8559f0e2L, 0x3de59787L, 0x658687d1L, 0xdd3ae0b4L, 0xcf8f4f5aL, 0x7733283fL, 0xeae41086L, 0x525877e3L, 0x40edd80dL, 0xf851bf68L, 0xf02bf8a1L, 0x48979fc4L, 0x5a22302aL, 0xe29e574fL, 0x7f496ff6L, 0xc7f50893L, 0xd540a77dL, 0x6dfcc018L, 0x359fd04eL, 0x8d23b72bL, 0x9f9618c5L, 0x272a7fa0L, 0xbafd4719L, 0x0241207cL, 0x10f48f92L, 0xa848e8f7L, 0x9b14583dL, 0x23a83f58L, 0x311d90b6L, 0x89a1f7d3L, 0x1476cf6aL, 0xaccaa80fL, 0xbe7f07e1L, 0x06c36084L, 0x5ea070d2L, 0xe61c17b7L, 0xf4a9b859L, 0x4c15df3cL, 0xd1c2e785L, 0x697e80e0L, 0x7bcb2f0eL, 0xc377486bL, 0xcb0d0fa2L, 0x73b168c7L, 0x6104c729L, 0xd9b8a04cL, 0x446f98f5L, 0xfcd3ff90L, 0xee66507eL, 0x56da371bL, 0x0eb9274dL, 0xb6054028L, 0xa4b0efc6L, 0x1c0c88a3L, 0x81dbb01aL, 0x3967d77fL, 0x2bd27891L, 0x936e1ff4L, 0x3b26f703L, 0x839a9066L, 0x912f3f88L, 0x299358edL, 0xb4446054L, 0x0cf80731L, 0x1e4da8dfL, 0xa6f1cfbaL, 0xfe92dfecL, 0x462eb889L, 0x549b1767L, 0xec277002L, 0x71f048bbL, 0xc94c2fdeL, 0xdbf98030L, 0x6345e755L, 0x6b3fa09cL, 0xd383c7f9L, 0xc1366817L, 0x798a0f72L, 0xe45d37cbL, 0x5ce150aeL, 0x4e54ff40L, 0xf6e89825L, 0xae8b8873L, 0x1637ef16L, 0x048240f8L, 0xbc3e279dL, 0x21e91f24L, 0x99557841L, 0x8be0d7afL, 0x335cb0caL, 0xed59b63bL, 0x55e5d15eL, 0x47507eb0L, 0xffec19d5L, 0x623b216cL, 0xda874609L, 0xc832e9e7L, 0x708e8e82L, 0x28ed9ed4L, 0x9051f9b1L, 0x82e4565fL, 0x3a58313aL, 0xa78f0983L, 0x1f336ee6L, 0x0d86c108L, 0xb53aa66dL, 0xbd40e1a4L, 0x05fc86c1L, 0x1749292fL, 0xaff54e4aL, 0x322276f3L, 0x8a9e1196L, 0x982bbe78L, 0x2097d91dL, 0x78f4c94bL, 0xc048ae2eL, 0xd2fd01c0L, 0x6a4166a5L, 0xf7965e1cL, 0x4f2a3979L, 0x5d9f9697L, 0xe523f1f2L, 0x4d6b1905L, 0xf5d77e60L, 0xe762d18eL, 0x5fdeb6ebL, 0xc2098e52L, 0x7ab5e937L, 0x680046d9L, 0xd0bc21bcL, 0x88df31eaL, 0x3063568fL, 0x22d6f961L, 0x9a6a9e04L, 0x07bda6bdL, 0xbf01c1d8L, 0xadb46e36L, 0x15080953L, 0x1d724e9aL, 0xa5ce29ffL, 0xb77b8611L, 0x0fc7e174L, 0x9210d9cdL, 0x2aacbea8L, 0x38191146L, 0x80a57623L, 0xd8c66675L, 0x607a0110L, 0x72cfaefeL, 0xca73c99bL, 0x57a4f122L, 0xef189647L, 0xfdad39a9L, 0x45115eccL, 0x764dee06L, 0xcef18963L, 0xdc44268dL, 0x64f841e8L, 0xf92f7951L, 0x41931e34L, 0x5326b1daL, 0xeb9ad6bfL, 0xb3f9c6e9L, 0x0b45a18cL, 0x19f00e62L, 0xa14c6907L, 0x3c9b51beL, 0x842736dbL, 0x96929935L, 0x2e2efe50L, 0x2654b999L, 0x9ee8defcL, 0x8c5d7112L, 0x34e11677L, 0xa9362eceL, 0x118a49abL, 0x033fe645L, 0xbb838120L, 0xe3e09176L, 0x5b5cf613L, 0x49e959fdL, 0xf1553e98L, 0x6c820621L, 0xd43e6144L, 0xc68bceaaL, 0x7e37a9cfL, 0xd67f4138L, 0x6ec3265dL, 0x7c7689b3L, 0xc4caeed6L, 0x591dd66fL, 0xe1a1b10aL, 0xf3141ee4L, 0x4ba87981L, 0x13cb69d7L, 0xab770eb2L, 0xb9c2a15cL, 0x017ec639L, 0x9ca9fe80L, 0x241599e5L, 0x36a0360bL, 0x8e1c516eL, 0x866616a7L, 0x3eda71c2L, 0x2c6fde2cL, 0x94d3b949L, 0x090481f0L, 0xb1b8e695L, 0xa30d497bL, 0x1bb12e1eL, 0x43d23e48L, 0xfb6e592dL, 0xe9dbf6c3L, 0x516791a6L, 0xccb0a91fL, 0x740cce7aL, 0x66b96194L, 0xde0506f1L # endif /* IZ_CRCOPTIM_UNFOLDTBL */ # endif /* ? IZ_CRC_BE_OPTIMIZ */ }; #endif /* ?DYNAMIC_CRC_TABLE */ /* use "OF((void))" here to work around a Borland TC++ 1.0 problem */ #ifdef USE_ZLIB ZCONST uLongf *get_crc_table OF((void)) #else ZCONST ulg near *get_crc_table OF((void)) #endif { #ifdef DYNAMIC_CRC_TABLE if (CRC_TABLE_IS_EMPTY) make_crc_table(); #endif #ifdef USE_ZLIB return (ZCONST uLongf *)crc_table; #else return crc_table; #endif } #ifdef DYNALLOC_CRCTAB void free_crc_table() { if (!CRC_TABLE_IS_EMPTY) { nearfree((ulg near *)crc_table); MARK_CRCTAB_EMPTY; } } #endif #ifndef USE_ZLIB #ifndef CRC_TABLE_ONLY #ifndef ASM_CRC #define DO1(crc, buf) crc = CRC32(crc, *buf++, crc_32_tab) #define DO2(crc, buf) DO1(crc, buf); DO1(crc, buf) #define DO4(crc, buf) DO2(crc, buf); DO2(crc, buf) #define DO8(crc, buf) DO4(crc, buf); DO4(crc, buf) #if (defined(IZ_CRC_BE_OPTIMIZ) || defined(IZ_CRC_LE_OPTIMIZ)) # ifdef IZ_CRCOPTIM_UNFOLDTBL # ifdef IZ_CRC_BE_OPTIMIZ # define DO_OPT4(c, buf4) c ^= *(buf4)++; \ c = crc_32_tab[c & 0xff] ^ crc_32_tab[256+((c>>8) & 0xff)] ^ \ crc_32_tab[2*256+((c>>16) & 0xff)] ^ crc_32_tab[3*256+(c>>24)] # else /* !IZ_CRC_BE_OPTIMIZ */ # define DO_OPT4(c, buf4) c ^= *(buf4)++; \ c = crc_32_tab[3*256+(c & 0xff)] ^ crc_32_tab[2*256+((c>>8) & 0xff)] \ ^ crc_32_tab[256+((c>>16) & 0xff)] ^ crc_32_tab[c>>24] # endif /* ?IZ_CRC_BE_OPTIMIZ */ # else /* !IZ_CRCOPTIM_UNFOLDTBL */ # define DO_OPT4(c, buf4) c ^= *(buf4)++; \ c = CRC32UPD(c, crc_32_tab); \ c = CRC32UPD(c, crc_32_tab); \ c = CRC32UPD(c, crc_32_tab); \ c = CRC32UPD(c, crc_32_tab) # endif /* ?IZ_CRCOPTIM_UNFOLDTBL */ # define DO_OPT16(crc, buf4) DO_OPT4(crc, buf4); DO_OPT4(crc, buf4); \ DO_OPT4(crc, buf4); DO_OPT4(crc, buf4); #endif /* (IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */ /* ========================================================================= */ ulg crc32(crc, buf, len) ulg crc; /* crc shift register */ register ZCONST uch *buf; /* pointer to bytes to pump through */ extent len; /* number of bytes in buf[] */ /* Run a set of bytes through the crc shift register. If buf is a NULL pointer, then initialize the crc shift register contents instead. Return the current crc in either case. */ { register z_uint4 c; register ZCONST ulg near *crc_32_tab; if (buf == NULL) return 0L; crc_32_tab = get_crc_table(); c = (REV_BE((z_uint4)crc) ^ 0xffffffffL); #if (defined(IZ_CRC_BE_OPTIMIZ) || defined(IZ_CRC_LE_OPTIMIZ)) /* Align buf pointer to next DWORD boundary. */ while (len && ((ptrdiff_t)buf & 3)) { DO1(c, buf); len--; } { ZCONST z_uint4 *buf4 = (ZCONST z_uint4 *)buf; while (len >= 16) { DO_OPT16(c, buf4); len -= 16; } while (len >= 4) { DO_OPT4(c, buf4); len -= 4; } buf = (ZCONST uch *)buf4; } #else /* !(IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */ #ifndef NO_UNROLLED_LOOPS while (len >= 8) { DO8(c, buf); len -= 8; } #endif /* !NO_UNROLLED_LOOPS */ #endif /* ?(IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */ if (len) do { DO1(c, buf); } while (--len); return REV_BE(c) ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ } #endif /* !ASM_CRC */ #endif /* !CRC_TABLE_ONLY */ #endif /* !USE_ZLIB */ #endif /* !USE_ZLIB || USE_OWN_CRCTAB */ Carla-2.1/data/windows/unzipfx-carla/crc32.h000066400000000000000000000033611364475620200206650ustar00rootroot00000000000000/* Copyright (c) 1990-2008 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crc32.h -- compute the CRC-32 of a data stream * Copyright (C) 1995 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #ifndef __crc32_h #define __crc32_h /* identifies this source module */ /* This header should be read AFTER zip.h resp. unzip.h * (the latter with UNZIP_INTERNAL defined...). */ #ifndef OF # define OF(a) a #endif #ifndef ZCONST # define ZCONST const #endif #ifdef DYNALLOC_CRCTAB void free_crc_table OF((void)); #endif #ifndef USE_ZLIB ZCONST ulg near *get_crc_table OF((void)); #endif #if (defined(USE_ZLIB) || defined(CRC_TABLE_ONLY)) # ifdef IZ_CRC_BE_OPTIMIZ # undef IZ_CRC_BE_OPTIMIZ # endif #else /* !(USE_ZLIB || CRC_TABLE_ONLY) */ ulg crc32 OF((ulg crc, ZCONST uch *buf, extent len)); #endif /* ?(USE_ZLIB || CRC_TABLE_ONLY) */ #ifndef CRC_32_TAB # define CRC_32_TAB crc_32_tab #endif #ifdef CRC32 # undef CRC32 #endif #ifdef IZ_CRC_BE_OPTIMIZ # define CRC32UPD(c, crctab) (crctab[((c) >> 24)] ^ ((c) << 8)) # define CRC32(c, b, crctab) (crctab[(((int)(c) >> 24) ^ (b))] ^ ((c) << 8)) # define REV_BE(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ (((w)&0xff00)<<8)+(((w)&0xff)<<24)) #else # define CRC32UPD(c, crctab) (crctab[((int)(c)) & 0xff] ^ ((c) >> 8)) # define CRC32(c, b, crctab) (crctab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) # define REV_BE(w) w #endif #endif /* !__crc32_h */ Carla-2.1/data/windows/unzipfx-carla/crypt.c000066400000000000000000000533761364475620200211200ustar00rootroot00000000000000/* Copyright (c) 1990-2007 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2005-Feb-10 or later (the contents of which are also included in (un)zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] The main encryption/decryption source code for Info-Zip software was originally written in Europe. To the best of our knowledge, it can be freely distributed in both source and object forms from any country, including the USA under License Exception TSU of the U.S. Export Administration Regulations (section 740.13(e)) of 6 June 2002. NOTE on copyright history: Previous versions of this source package (up to version 2.8) were not copyrighted and put in the public domain. If you cannot comply with the Info-Zip LICENSE, you may want to look for one of those public domain versions. */ /* This encryption code is a direct transcription of the algorithm from Roger Schlafly, described by Phil Katz in the file appnote.txt. This file (appnote.txt) is distributed with the PKZIP program (even in the version without encryption capabilities). */ #define ZCRYPT_INTERNAL #include "zip.h" #include "crypt.h" #include "ttyio.h" #if CRYPT #ifndef FALSE # define FALSE 0 #endif #ifdef ZIP /* For the encoding task used in Zip (and ZipCloak), we want to initialize the crypt algorithm with some reasonably unpredictable bytes, see the crypthead() function. The standard rand() library function is used to supply these `random' bytes, which in turn is initialized by a srand() call. The srand() function takes an "unsigned" (at least 16bit) seed value as argument to determine the starting point of the rand() pseudo-random number generator. This seed number is constructed as "Seed = Seed1 .XOR. Seed2" with Seed1 supplied by the current time (= "(unsigned)time()") and Seed2 as some (hopefully) nondeterministic bitmask. On many (most) systems, we use some "process specific" number, as the PID or something similar, but when nothing unpredictable is available, a fixed number may be sufficient. NOTE: 1.) This implementation requires the availability of the following standard UNIX C runtime library functions: time(), rand(), srand(). On systems where some of them are missing, the environment that incorporates the crypt routines must supply suitable replacement functions. 2.) It is a very bad idea to use a second call to time() to set the "Seed2" number! In this case, both "Seed1" and "Seed2" would be (almost) identical, resulting in a (mostly) "zero" constant seed number passed to srand(). The implementation environment defined in the "zip.h" header should supply a reasonable definition for ZCR_SEED2 (an unsigned number; for most implementations of rand() and srand(), only the lower 16 bits are significant!). An example that works on many systems would be "#define ZCR_SEED2 (unsigned)getpid()". The default definition for ZCR_SEED2 supplied below should be regarded as a fallback to allow successful compilation in "beta state" environments. */ # include /* time() function supplies first part of crypt seed */ /* "last resort" source for second part of crypt seed pattern */ # ifndef ZCR_SEED2 # define ZCR_SEED2 (unsigned)3141592654L /* use PI as default pattern */ # endif # ifdef GLOBAL /* used in Amiga system headers, maybe others too */ # undef GLOBAL # endif # define GLOBAL(g) g #else /* !ZIP */ # define GLOBAL(g) G.g #endif /* ?ZIP */ #ifdef UNZIP /* char *key = (char *)NULL; moved to globals.h */ # ifndef FUNZIP local int testp OF((__GPRO__ ZCONST uch *h)); local int testkey OF((__GPRO__ ZCONST uch *h, ZCONST char *key)); # endif #endif /* UNZIP */ #ifndef UNZIP /* moved to globals.h for UnZip */ # ifndef Z_UINT4_DEFINED # if !defined(NO_LIMITS_H) # if (defined(UINT_MAX) && (UINT_MAX == 0xffffffffUL)) typedef unsigned int z_uint4; # define Z_UINT4_DEFINED # else # if (defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL)) typedef unsigned long z_uint4; # define Z_UINT4_DEFINED # else # if (defined(USHRT_MAX) && (USHRT_MAX == 0xffffffffUL)) typedef unsigned short z_uint4; # define Z_UINT4_DEFINED # endif # endif # endif # endif /* !NO_LIMITS_H */ # endif /* !Z_UINT4_DEFINED */ # ifndef Z_UINT4_DEFINED typedef ulg z_uint4; # define Z_UINT4_DEFINED # endif local z_uint4 keys[3]; /* keys defining the pseudo-random sequence */ #endif /* !UNZIP */ #ifndef Trace # ifdef CRYPT_DEBUG # define Trace(x) fprintf x # else # define Trace(x) # endif #endif #include "crc32.h" #ifdef IZ_CRC_BE_OPTIMIZ local z_uint4 near crycrctab[256]; local z_uint4 near *cry_crctb_p = NULL; local z_uint4 near *crytab_init OF((__GPRO)); # define CRY_CRC_TAB cry_crctb_p # undef CRC32 # define CRC32(c, b, crctab) (crctab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) #else # define CRY_CRC_TAB CRC_32_TAB #endif /* ?IZ_CRC_BE_OPTIMIZ */ /*********************************************************************** * Return the next byte in the pseudo-random sequence */ int decrypt_byte(__G) __GDEF { unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an * unpredictable manner on 16-bit systems; not a problem * with any known compiler so far, though */ temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2; return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); } /*********************************************************************** * Update the encryption keys with the next byte of plain text */ int update_keys(__G__ c) __GDEF int c; /* byte of plain text */ { GLOBAL(keys[0]) = CRC32(GLOBAL(keys[0]), c, CRY_CRC_TAB); GLOBAL(keys[1]) = (GLOBAL(keys[1]) + (GLOBAL(keys[0]) & 0xff)) * 134775813L + 1; { register int keyshift = (int)(GLOBAL(keys[1]) >> 24); GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift, CRY_CRC_TAB); } return c; } /*********************************************************************** * Initialize the encryption keys and the random header according to * the given password. */ void init_keys(__G__ passwd) __GDEF ZCONST char *passwd; /* password string with which to modify keys */ { #ifdef IZ_CRC_BE_OPTIMIZ if (cry_crctb_p == NULL) { cry_crctb_p = crytab_init(__G); } #endif GLOBAL(keys[0]) = 305419896L; GLOBAL(keys[1]) = 591751049L; GLOBAL(keys[2]) = 878082192L; while (*passwd != '\0') { update_keys(__G__ (int)*passwd); passwd++; } } /*********************************************************************** * Initialize the local copy of the table of precomputed crc32 values. * Whereas the public crc32-table is optimized for crc32 calculations * on arrays of bytes, the crypt code needs the crc32 values in an * byte-order-independent form as 32-bit unsigned numbers. On systems * with Big-Endian byte order using the optimized crc32 code, this * requires inverting the byte-order of the values in the * crypt-crc32-table. */ #ifdef IZ_CRC_BE_OPTIMIZ local z_uint4 near *crytab_init(__G) __GDEF { int i; for (i = 0; i < 256; i++) { crycrctab[i] = REV_BE(CRC_32_TAB[i]); } return crycrctab; } #endif #ifdef ZIP /*********************************************************************** * Write encryption header to file zfile using the password passwd * and the cyclic redundancy check crc. */ void crypthead(passwd, crc, zfile) ZCONST char *passwd; /* password string */ ulg crc; /* crc of file being encrypted */ FILE *zfile; /* where to write header */ { int n; /* index in random header */ int t; /* temporary */ int c; /* random byte */ uch header[RAND_HEAD_LEN]; /* random header */ static unsigned calls = 0; /* ensure different random header each time */ /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the * output of rand() to get less predictability, since rand() is * often poorly implemented. */ if (++calls == 1) { srand((unsigned)time(NULL) ^ ZCR_SEED2); } init_keys(passwd); for (n = 0; n < RAND_HEAD_LEN-2; n++) { c = (rand() >> 7) & 0xff; header[n] = (uch)zencode(c, t); } /* Encrypt random header (last two bytes is high word of crc) */ init_keys(passwd); for (n = 0; n < RAND_HEAD_LEN-2; n++) { header[n] = (uch)zencode(header[n], t); } header[RAND_HEAD_LEN-2] = (uch)zencode((int)(crc >> 16) & 0xff, t); header[RAND_HEAD_LEN-1] = (uch)zencode((int)(crc >> 24) & 0xff, t); fwrite(header, 1, RAND_HEAD_LEN, f); } #ifdef UTIL /*********************************************************************** * Encrypt the zip entry described by z from file source to file dest * using the password passwd. Return an error code in the ZE_ class. */ int zipcloak(z, source, dest, passwd) struct zlist far *z; /* zip entry to encrypt */ FILE *source, *dest; /* source and destination files */ ZCONST char *passwd; /* password string */ { int c; /* input byte */ int res; /* result code */ ulg n; /* holds offset and counts size */ ush flag; /* previous flags */ int t; /* temporary */ int ztemp; /* temporary storage for zencode value */ /* Set encrypted bit, clear extended local header bit and write local header to output file */ if ((n = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; z->off = n; flag = z->flg; z->flg |= 1, z->flg &= ~8; z->lflg |= 1, z->lflg &= ~8; z->siz += RAND_HEAD_LEN; if ((res = putlocal(z, dest)) != ZE_OK) return res; /* Initialize keys with password and write random header */ crypthead(passwd, z->crc, dest); /* Skip local header in input file */ if (fseek(source, (long)((4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext), SEEK_CUR)) { return ferror(source) ? ZE_READ : ZE_EOF; } /* Encrypt data */ for (n = z->siz - RAND_HEAD_LEN; n; n--) { if ((c = getc(source)) == EOF) { return ferror(source) ? ZE_READ : ZE_EOF; } ztemp = zencode(c, t); putc(ztemp, dest); } /* Skip extended local header in input file if there is one */ if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { return ferror(source) ? ZE_READ : ZE_EOF; } if (fflush(dest) == EOF) return ZE_TEMP; /* Update number of bytes written to output file */ tempzn += (4 + LOCHEAD) + z->nam + z->ext + z->siz; return ZE_OK; } /*********************************************************************** * Decrypt the zip entry described by z from file source to file dest * using the password passwd. Return an error code in the ZE_ class. */ int zipbare(z, source, dest, passwd) struct zlist far *z; /* zip entry to encrypt */ FILE *source, *dest; /* source and destination files */ ZCONST char *passwd; /* password string */ { #ifdef ZIP10 int c0 /* byte preceding the last input byte */ #endif int c1; /* last input byte */ ulg offset; /* used for file offsets */ ulg size; /* size of input data */ int r; /* size of encryption header */ int res; /* return code */ ush flag; /* previous flags */ /* Save position and skip local header in input file */ if ((offset = (ulg)ftell(source)) == (ulg)-1L || fseek(source, (long)((4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext), SEEK_CUR)) { return ferror(source) ? ZE_READ : ZE_EOF; } /* Initialize keys with password */ init_keys(passwd); /* Decrypt encryption header, save last two bytes */ c1 = 0; for (r = RAND_HEAD_LEN; r; r--) { #ifdef ZIP10 c0 = c1; #endif if ((c1 = getc(source)) == EOF) { return ferror(source) ? ZE_READ : ZE_EOF; } Trace((stdout, " (%02x)", c1)); zdecode(c1); Trace((stdout, " %02x", c1)); } Trace((stdout, "\n")); /* If last two bytes of header don't match crc (or file time in the * case of an extended local header), back up and just copy. For * pkzip 2.0, the check has been reduced to one byte only. */ #ifdef ZIP10 if ((ush)(c0 | (c1<<8)) != (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) { #else if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) { #endif if (fseek(source, offset, SEEK_SET)) { return ferror(source) ? ZE_READ : ZE_EOF; } if ((res = zipcopy(z, source, dest)) != ZE_OK) return res; return ZE_MISS; } /* Clear encrypted bit and local header bit, and write local header to output file */ if ((offset = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; z->off = offset; flag = z->flg; z->flg &= ~9; z->lflg &= ~9; z->siz -= RAND_HEAD_LEN; if ((res = putlocal(z, dest)) != ZE_OK) return res; /* Decrypt data */ for (size = z->siz; size; size--) { if ((c1 = getc(source)) == EOF) { return ferror(source) ? ZE_READ : ZE_EOF; } zdecode(c1); putc(c1, dest); } /* Skip extended local header in input file if there is one */ if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { return ferror(source) ? ZE_READ : ZE_EOF; } if (fflush(dest) == EOF) return ZE_TEMP; /* Update number of bytes written to output file */ tempzn += (4 + LOCHEAD) + z->nam + z->ext + z->siz; return ZE_OK; } #else /* !UTIL */ /*********************************************************************** * If requested, encrypt the data in buf, and in any case call fwrite() * with the arguments to zfwrite(). Return what fwrite() returns. * * A bug has been found when encrypting large files. See trees.c * for details and the fix. */ unsigned zfwrite(buf, item_size, nb, f) zvoid *buf; /* data buffer */ extent item_size; /* size of each item in bytes */ extent nb; /* number of items */ FILE *f; /* file to write to */ { int t; /* temporary */ if (key != (char *)NULL) { /* key is the global password pointer */ ulg size; /* buffer size */ char *p = (char*)buf; /* steps through buffer */ /* Encrypt data in buffer */ for (size = item_size*(ulg)nb; size != 0; p++, size--) { *p = (char)zencode(*p, t); } } /* Write the buffer out */ return fwrite(buf, item_size, nb, f); } #endif /* ?UTIL */ #endif /* ZIP */ #if (defined(UNZIP) && !defined(FUNZIP)) /*********************************************************************** * Get the password and set up keys for current zipfile member. * Return PK_ class error. */ int decrypt(__G__ passwrd) __GDEF ZCONST char *passwrd; { ush b; int n, r; uch h[RAND_HEAD_LEN]; Trace((stdout, "\n[incnt = %d]: ", GLOBAL(incnt))); /* get header once (turn off "encrypted" flag temporarily so we don't * try to decrypt the same data twice) */ GLOBAL(pInfo->encrypted) = FALSE; defer_leftover_input(__G); for (n = 0; n < RAND_HEAD_LEN; n++) { b = NEXTBYTE; h[n] = (uch)b; Trace((stdout, " (%02x)", h[n])); } undefer_input(__G); GLOBAL(pInfo->encrypted) = TRUE; if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */ GLOBAL(newzip) = FALSE; if (passwrd != (char *)NULL) { /* user gave password on command line */ if (!GLOBAL(key)) { if ((GLOBAL(key) = (char *)malloc(strlen(passwrd)+1)) == (char *)NULL) return PK_MEM2; strcpy(GLOBAL(key), passwrd); GLOBAL(nopwd) = TRUE; /* inhibit password prompting! */ } } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */ free(GLOBAL(key)); GLOBAL(key) = (char *)NULL; } } /* if have key already, test it; else allocate memory for it */ if (GLOBAL(key)) { if (!testp(__G__ h)) return PK_COOL; /* existing password OK (else prompt for new) */ else if (GLOBAL(nopwd)) return PK_WARN; /* user indicated no more prompting */ } else if ((GLOBAL(key) = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL) return PK_MEM2; /* try a few keys */ n = 0; do { r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), IZ_PWLEN+1, GLOBAL(zipfn), GLOBAL(filename)); if (r == IZ_PW_ERROR) { /* internal error in fetch of PW */ free (GLOBAL(key)); GLOBAL(key) = NULL; return PK_MEM2; } if (r != IZ_PW_ENTERED) { /* user replied "skip" or "skip all" */ *GLOBAL(key) = '\0'; /* We try the NIL password, ... */ n = 0; /* and cancel fetch for this item. */ } if (!testp(__G__ h)) return PK_COOL; if (r == IZ_PW_CANCELALL) /* User replied "Skip all" */ GLOBAL(nopwd) = TRUE; /* inhibit any further PW prompt! */ } while (n > 0); return PK_WARN; } /* end function decrypt() */ /*********************************************************************** * Test the password. Return -1 if bad, 0 if OK. */ local int testp(__G__ h) __GDEF ZCONST uch *h; { int r; char *key_translated; /* On systems with "obscure" native character coding (e.g., EBCDIC), * the first test translates the password to the "main standard" * character coding. */ #ifdef STR_TO_CP1 /* allocate buffer for translated password */ if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) return -1; /* first try, test password translated "standard" charset */ r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key))); #else /* !STR_TO_CP1 */ /* first try, test password as supplied on the extractor's host */ r = testkey(__G__ h, GLOBAL(key)); #endif /* ?STR_TO_CP1 */ #ifdef STR_TO_CP2 if (r != 0) { #ifndef STR_TO_CP1 /* now prepare for second (and maybe third) test with translated pwd */ if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) return -1; #endif /* second try, password translated to alternate ("standard") charset */ r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key))); #ifdef STR_TO_CP3 if (r != 0) /* third try, password translated to another "standard" charset */ r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key))); #endif #ifndef STR_TO_CP1 free(key_translated); #endif } #endif /* STR_TO_CP2 */ #ifdef STR_TO_CP1 free(key_translated); if (r != 0) { /* last resort, test password as supplied on the extractor's host */ r = testkey(__G__ h, GLOBAL(key)); } #endif /* STR_TO_CP1 */ return r; } /* end function testp() */ local int testkey(__G__ h, key) __GDEF ZCONST uch *h; /* decrypted header */ ZCONST char *key; /* decryption password to test */ { ush b; #ifdef ZIP10 ush c; #endif int n; uch *p; uch hh[RAND_HEAD_LEN]; /* decrypted header */ /* set keys and save the encrypted header */ init_keys(__G__ key); memcpy(hh, h, RAND_HEAD_LEN); /* check password */ for (n = 0; n < RAND_HEAD_LEN; n++) { zdecode(hh[n]); Trace((stdout, " %02x", hh[n])); } Trace((stdout, "\n lrec.crc= %08lx crec.crc= %08lx pInfo->ExtLocHdr= %s\n", GLOBAL(lrec.crc32), GLOBAL(pInfo->crc), GLOBAL(pInfo->ExtLocHdr) ? "true":"false")); Trace((stdout, " incnt = %d unzip offset into zipfile = %ld\n", GLOBAL(incnt), GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf)))); /* same test as in zipbare(): */ #ifdef ZIP10 /* check two bytes */ c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1]; Trace((stdout, " (c | (b<<8)) = %04x (crc >> 16) = %04x lrec.time = %04x\n", (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16), ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff)))); if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ? ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff) : (ush)(GLOBAL(lrec.crc32) >> 16))) return -1; /* bad */ #else b = hh[RAND_HEAD_LEN-1]; Trace((stdout, " b = %02x (crc >> 24) = %02x (lrec.time >> 8) = %02x\n", b, (ush)(GLOBAL(lrec.crc32) >> 24), ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff)); if (b != (GLOBAL(pInfo->ExtLocHdr) ? ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff : (ush)(GLOBAL(lrec.crc32) >> 24))) return -1; /* bad */ #endif /* password OK: decrypt current buffer contents before leaving */ for (n = (long)GLOBAL(incnt) > GLOBAL(csize) ? (int)GLOBAL(csize) : GLOBAL(incnt), p = GLOBAL(inptr); n--; p++) zdecode(*p); return 0; /* OK */ } /* end function testkey() */ #endif /* UNZIP && !FUNZIP */ #else /* !CRYPT */ /* something "externally visible" to shut up compiler/linker warnings */ int zcr_dummy; #endif /* ?CRYPT */ Carla-2.1/data/windows/unzipfx-carla/crypt.h000066400000000000000000000112251364475620200211100ustar00rootroot00000000000000/* Copyright (c) 1990-2007 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2005-Feb-10 or later (the contents of which are also included in (un)zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crypt.h (full version) by Info-ZIP. Last revised: [see CR_VERSION_DATE] The main encryption/decryption source code for Info-Zip software was originally written in Europe. To the best of our knowledge, it can be freely distributed in both source and object forms from any country, including the USA under License Exception TSU of the U.S. Export Administration Regulations (section 740.13(e)) of 6 June 2002. NOTE on copyright history: Previous versions of this source package (up to version 2.8) were not copyrighted and put in the public domain. If you cannot comply with the Info-Zip LICENSE, you may want to look for one of those public domain versions. */ #ifndef __crypt_h /* don't include more than once */ #define __crypt_h #ifdef CRYPT # undef CRYPT #endif /* Logic of selecting "full crypt" code: a) default behaviour: - dummy crypt code when compiling UnZipSFX stub, to minimize size - full crypt code when used to compile Zip, UnZip and fUnZip b) USE_CRYPT defined: - always full crypt code c) NO_CRYPT defined: - never full crypt code NO_CRYPT takes precedence over USE_CRYPT */ #if defined(NO_CRYPT) # define CRYPT 0 /* dummy version */ #else #if defined(USE_CRYPT) # define CRYPT 1 /* full version */ #else #if !defined(SFX) # define CRYPT 1 /* full version for zip and main unzip */ #else # define CRYPT 0 /* dummy version for unzip sfx */ #endif #endif /* ?USE_CRYPT */ #endif /* ?NO_CRYPT */ #if CRYPT /* full version */ #ifdef CR_BETA # undef CR_BETA /* this is not a beta release */ #endif #define CR_MAJORVER 2 #define CR_MINORVER 11 #ifdef CR_BETA # define CR_BETA_VER "c BETA" # define CR_VERSION_DATE "05 Jan 2007" /* last real code change */ #else # define CR_BETA_VER "" # define CR_VERSION_DATE "05 Jan 2007" /* last public release date */ # define CR_RELEASE #endif #ifndef __G /* UnZip only, for now (DLL stuff) */ # define __G # define __G__ # define __GDEF # define __GPRO void # define __GPRO__ #endif #if defined(MSDOS) || defined(OS2) || defined(WIN32) # ifndef DOS_OS2_W32 # define DOS_OS2_W32 # endif #endif #if defined(DOS_OS2_W32) || defined(__human68k__) # ifndef DOS_H68_OS2_W32 # define DOS_H68_OS2_W32 # endif #endif #if defined(VM_CMS) || defined(MVS) # ifndef CMS_MVS # define CMS_MVS # endif #endif /* To allow combining of Zip and UnZip static libraries in a single binary, * the Zip and UnZip versions of the crypt core functions have to be named * differently. */ #ifdef ZIP # ifdef REALLY_SHORT_SYMS # define decrypt_byte zdcrby # else # define decrypt_byte zp_decrypt_byte # endif # define update_keys zp_update_keys # define init_keys zp_init_keys #else /* !ZIP */ # ifdef REALLY_SHORT_SYMS # define decrypt_byte dcrbyt # endif #endif /* ?ZIP */ #define IZ_PWLEN 80 /* input buffer size for reading encryption key */ #ifndef PWLEN /* for compatibility with previous zcrypt release... */ # define PWLEN IZ_PWLEN #endif #define RAND_HEAD_LEN 12 /* length of encryption random header */ /* the crc_32_tab array has to be provided externally for the crypt calculus */ /* encode byte c, using temp t. Warning: c must not have side effects. */ #define zencode(c,t) (t=decrypt_byte(__G), update_keys(c), t^(c)) /* decode byte c in place */ #define zdecode(c) update_keys(__G__ c ^= decrypt_byte(__G)) int decrypt_byte OF((__GPRO)); int update_keys OF((__GPRO__ int c)); void init_keys OF((__GPRO__ ZCONST char *passwd)); #ifdef ZIP void crypthead OF((ZCONST char *, ulg, FILE *)); # ifdef UTIL int zipcloak OF((struct zlist far *, FILE *, FILE *, ZCONST char *)); int zipbare OF((struct zlist far *, FILE *, FILE *, ZCONST char *)); # else unsigned zfwrite OF((zvoid *, extent, extent, FILE *)); extern char *key; # endif #endif /* ZIP */ #if (defined(UNZIP) && !defined(FUNZIP)) int decrypt OF((__GPRO__ ZCONST char *passwrd)); #endif #ifdef FUNZIP extern int encrypted; # ifdef NEXTBYTE # undef NEXTBYTE # endif # define NEXTBYTE \ (encrypted? update_keys(__G__ getc(G.in)^decrypt_byte(__G)) : getc(G.in)) #endif /* FUNZIP */ #else /* !CRYPT */ /* dummy version */ #define zencode #define zdecode #define zfwrite fwrite #endif /* ?CRYPT */ #endif /* !__crypt_h */ Carla-2.1/data/windows/unzipfx-carla/ebcdic.h000066400000000000000000000365531364475620200211730ustar00rootroot00000000000000/* Copyright (c) 1990-2008 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- ebcdic.h The CECP 1047 (Extended de-facto EBCDIC) <-> ISO 8859-1 conversion tables, from ftp://aix1.segi.ulg.ac.be/pub/docs/iso8859/iso8859.networking NOTES: (OS/390 port 12/97) These table no longer represent the standard mappings (for example in the OS/390 iconv utility). In order to follow current standards I remapped ebcdic x0a to ascii x15 and ebcdic x85 to ascii x25 (and vice-versa) Without these changes, newlines in auto-convert text files appeared as literal \045. I'm not sure what effect this remap would have on the MVS and CMS ports, so I ifdef'd these changes. Hopefully these ifdef's can be removed when the MVS/CMS folks test the new mappings. Christian Spieler , 27-Apr-1998 The problem mentioned by Paul von Behren was already observed previously on VM/CMS, during the preparation of the CMS&MVS port of UnZip 5.20 in 1996. At that point, the ebcdic tables were not changed since they seemed to be an adopted standard (to my knowledge, these tables are still used as presented in mainfraime KERMIT). Instead, the "end-of-line" conversion feature of Zip's and UnZip's "text-translation" mode was used to force correct mappings between ASCII and EBCDIC newline markers. Before interchanging the ASCII mappings of the EBCDIC control characters "NL" 0x25 and "LF" 0x15 according to the OS/390 setting, we have to make sure that EBCDIC 0x15 is never used as line termination. ---------------------------------------------------------------------------*/ #ifndef __ebcdic_h /* prevent multiple inclusions */ #define __ebcdic_h #ifndef ZCONST # define ZCONST const #endif #ifdef EBCDIC #ifndef MTS /* MTS uses a slightly "special" EBCDIC code page */ ZCONST uch ebcdic[] = { 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 00 - 07 */ #ifdef OS390 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ #else 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ #endif 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /* 10 - 17 */ 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /* 20 - 27 */ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /* 28 - 2F */ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /* 30 - 37 */ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /* 38 - 3F */ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 40 - 47 */ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /* 48 - 4F */ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /* 50 - 57 */ 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, /* 58 - 5F */ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60 - 67 */ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 68 - 6F */ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /* 70 - 77 */ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, /* 78 - 7F */ #ifdef OS390 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17, /* 80 - 87 */ #else 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, /* 80 - 87 */ #endif 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, /* 88 - 8F */ 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, /* 90 - 97 */ 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF, /* 98 - 9F */ 0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, /* A0 - A7 */ 0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC, /* A8 - AF */ 0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, /* B0 - B7 */ 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB, /* B8 - BF */ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, /* C0 - C7 */ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* C8 - CF */ 0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, /* D0 - D7 */ 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59, /* D8 - DF */ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, /* E0 - E7 */ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* E8 - EF */ 0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, /* F0 - F7 */ 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF /* F8 - FF */ }; #if (defined(ZIP) || CRYPT) ZCONST uch ascii[] = { 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, /* 00 - 07 */ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ #ifdef OS390 0x10, 0x11, 0x12, 0x13, 0x9D, 0x0A, 0x08, 0x87, /* 10 - 17 */ #else 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, /* 10 - 17 */ #endif 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ #ifdef OS390 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1B, /* 20 - 27 */ #else 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, /* 20 - 27 */ #endif 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, /* 28 - 2F */ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30 - 37 */ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, /* 38 - 3F */ 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, /* 40 - 47 */ 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, /* 48 - 4F */ 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, /* 50 - 57 */ 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, /* 58 - 5F */ 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, /* 60 - 67 */ 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 68 - 6F */ 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, /* 70 - 77 */ 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /* 78 - 7F */ 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80 - 87 */ 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, /* 88 - 8F */ 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 90 - 97 */ 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, /* 98 - 9F */ 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* A0 - A7 */ 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE, /* A8 - AF */ 0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, /* B0 - B7 */ 0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7, /* B8 - BF */ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 - C7 */ 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, /* C8 - CF */ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* D0 - D7 */ 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, /* D8 - DF */ 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* E0 - E7 */ 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, /* E8 - EF */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* F0 - F7 */ 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F /* F8 - FF */ }; #endif /* ZIP || CRYPT */ #else /* MTS */ /* * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1 * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC. */ ZCONST uch ebcdic[] = { 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 00 - 07 */ 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /* 10 - 17 */ 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /* 20 - 27 */ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /* 28 - 2F */ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /* 30 - 37 */ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /* 38 - 3F */ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 40 - 47 */ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /* 48 - 4F */ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /* 50 - 57 */ 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D, /* 58 - 5F */ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60 - 67 */ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 68 - 6F */ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /* 70 - 77 */ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, /* 78 - 7F */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, /* 80 - 87 */ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, /* 88 - 8F */ 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, /* 90 - 97 */ 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF, /* 98 - 9F */ 0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, /* A0 - A7 */ 0xBD, 0xB4, 0x9A, 0x8A, 0x5F, 0xCA, 0xAF, 0xBC, /* A8 - AF */ 0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, /* B0 - B7 */ 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB, /* B8 - BF */ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, /* C0 - C7 */ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* C8 - CF */ 0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, /* D0 - D7 */ 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xAD, 0xAE, 0x59, /* D8 - DF */ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, /* E0 - E7 */ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* E8 - EF */ 0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, /* F0 - F7 */ 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF /* F8 - FF */ }; #if (defined(ZIP) || CRYPT) ZCONST uch ascii[] = { 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, /* 00 - 07 */ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, /* 10 - 17 */ 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, /* 20 - 27 */ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, /* 28 - 2F */ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30 - 37 */ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, /* 38 - 3F */ 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, /* 40 - 47 */ 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, /* 48 - 4F */ 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, /* 50 - 57 */ 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC, /* 58 - 5F */ 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, /* 60 - 67 */ 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 68 - 6F */ 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, /* 70 - 77 */ 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /* 78 - 7F */ 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80 - 87 */ 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, /* 88 - 8F */ 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 90 - 97 */ 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, /* 98 - 9F */ 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* A0 - A7 */ 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE, /* A8 - AF */ 0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, /* B0 - B7 */ 0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7, /* B8 - BF */ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 - C7 */ 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, /* C8 - CF */ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* D0 - D7 */ 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, /* D8 - DF */ 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* E0 - E7 */ 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, /* E8 - EF */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* F0 - F7 */ 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F /* F8 - FF */ }; #endif /* ZIP || CRYPT */ #endif /* ?MTS */ #endif /* EBCDIC */ /*--------------------------------------------------------------------------- The following conversion tables translate between IBM PC CP 850 (OEM codepage) and the "Western Europe & America" Windows codepage 1252. The Windows codepage 1252 contains the ISO 8859-1 "Latin 1" codepage, with some additional printable characters in the range (0x80 - 0x9F), that is reserved to control codes in the ISO 8859-1 character table. The ISO <--> OEM conversion tables were constructed with the help of the WIN32 (Win16?) API's OemToAnsi() and AnsiToOem() conversion functions and have been checked against the CP850 and LATIN1 tables provided in the MS-Kermit 3.14 distribution. ---------------------------------------------------------------------------*/ #ifdef IZ_ISO2OEM_ARRAY ZCONST uch Far iso2oem_850[] = { 0x3F, 0x3F, 0x27, 0x9F, 0x22, 0x2E, 0xC5, 0xCE, /* 80 - 87 */ 0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F, /* 88 - 8F */ 0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D, /* 90 - 97 */ 0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59, /* 98 - 9F */ 0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5, /* A0 - A7 */ 0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE, /* A8 - AF */ 0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA, /* B0 - B7 */ 0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8, /* B8 - BF */ 0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80, /* C0 - C7 */ 0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8, /* C8 - CF */ 0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E, /* D0 - D7 */ 0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1, /* D8 - DF */ 0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87, /* E0 - E7 */ 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B, /* E8 - EF */ 0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6, /* F0 - F7 */ 0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98 /* F8 - FF */ }; #endif /* IZ_ISO2OEM_ARRAY */ #ifdef IZ_OEM2ISO_ARRAY ZCONST uch Far oem2iso_850[] = { 0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7, /* 80 - 87 */ 0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5, /* 88 - 8F */ 0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9, /* 90 - 97 */ 0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, 0x83, /* 98 - 9F */ 0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA, /* A0 - A7 */ 0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB, /* A8 - AF */ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xC1, 0xC2, 0xC0, /* B0 - B7 */ 0xA9, 0xA6, 0xA6, 0x2B, 0x2B, 0xA2, 0xA5, 0x2B, /* B8 - BF */ 0x2B, 0x2D, 0x2D, 0x2B, 0x2D, 0x2B, 0xE3, 0xC3, /* C0 - C7 */ 0x2B, 0x2B, 0x2D, 0x2D, 0xA6, 0x2D, 0x2B, 0xA4, /* C8 - CF */ 0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x69, 0xCD, 0xCE, /* D0 - D7 */ 0xCF, 0x2B, 0x2B, 0xA6, 0x5F, 0xA6, 0xCC, 0xAF, /* D8 - DF */ 0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE, /* E0 - E7 */ 0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4, /* E8 - EF */ 0xAD, 0xB1, 0x3D, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8, /* F0 - F7 */ 0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, 0xA6, 0xA0 /* F8 - FF */ }; #endif /* IZ_OEM2ISO_ARRAY */ /* The following pointers to the OEM<-->ISO translation tables are used by the translation code portions. They may get initialized at program startup to point to the matching static translation tables, or to NULL to disable OEM-ISO translation. The compile-time initialization used here provides the backward compatible setting, as can be found in UnZip 5.52 and earlier. In case this mechanism will ever get used on a multithreading system that allows different codepage setups for concurrently running threads, these pointers should get moved into UnZip's thread-safe global data structure. */ #ifdef IZ_ISO2OEM_ARRAY ZCONST uch Far *iso2oem = iso2oem_850; /* backward compatibility default */ #endif /* IZ_ISO2OEM_ARRAY */ #ifdef IZ_OEM2ISO_ARRAY ZCONST uch Far *oem2iso = oem2iso_850; /* backward compatibility default */ #endif /* IZ_OEM2ISO_ARRAY */ #if defined(THEOS) || defined(THEOS_SUPPORT) # include "theos/charconv.h" #endif #endif /* __ebcdic_h */ Carla-2.1/data/windows/unzipfx-carla/extract.c000066400000000000000000003137161364475620200214260ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- extract.c This file contains the high-level routines ("driver routines") for extrac- ting and testing zipfile members. It calls the low-level routines in files explode.c, inflate.c, unreduce.c and unshrink.c. Contains: extract_or_test_files() store_info() find_compr_idx() extract_or_test_entrylist() extract_or_test_member() TestExtraField() test_compr_eb() memextract() memflush() extract_izvms_block() (VMS or VMS_TEXT_CONV) set_deferred_symlink() (SYMLINKS only) fnfilter() dircomp() (SET_DIR_ATTRIB only) UZbunzip2() (USE_BZIP2 only) ---------------------------------------------------------------------------*/ #define __EXTRACT_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" #ifdef WINDLL # ifdef POCKET_UNZIP # include "wince/intrface.h" # else # include "windll/windll.h" # endif #endif #include "crc32.h" #include "crypt.h" #define GRRDUMP(buf,len) { \ int i, j; \ \ for (j = 0; j < (len)/16; ++j) { \ printf(" "); \ for (i = 0; i < 16; ++i) \ printf("%02x ", (uch)(buf)[i+(j<<4)]); \ printf("\n "); \ for (i = 0; i < 16; ++i) { \ char c = (char)(buf)[i+(j<<4)]; \ \ if (c == '\n') \ printf("\\n "); \ else if (c == '\r') \ printf("\\r "); \ else \ printf(" %c ", c); \ } \ printf("\n"); \ } \ if ((len) % 16) { \ printf(" "); \ for (i = j<<4; i < (len); ++i) \ printf("%02x ", (uch)(buf)[i]); \ printf("\n "); \ for (i = j<<4; i < (len); ++i) { \ char c = (char)(buf)[i]; \ \ if (c == '\n') \ printf("\\n "); \ else if (c == '\r') \ printf("\\r "); \ else \ printf(" %c ", c); \ } \ printf("\n"); \ } \ } static int store_info OF((__GPRO)); #ifdef SET_DIR_ATTRIB static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk, ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes, unsigned *pnum_dirs, direntry **pdirlist, int error_in_archive)); #else static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk, ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes, int error_in_archive)); #endif static int extract_or_test_member OF((__GPRO)); #ifndef SFX static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len)); static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size, unsigned compr_offset, int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, uch *eb_ucptr, ulg eb_ucsize))); #endif #if (defined(VMS) || defined(VMS_TEXT_CONV)) static void decompress_bits OF((uch *outptr, unsigned needlen, ZCONST uch *bitptr)); #endif #ifdef SYMLINKS static void set_deferred_symlink OF((__GPRO__ slinkentry *slnk_entry)); #endif #ifdef SET_DIR_ATTRIB static int Cdecl dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b)); #endif /*******************************/ /* Strings used in extract.c */ /*******************************/ static ZCONST char Far VersionMsg[] = " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n"; static ZCONST char Far ComprMsgNum[] = " skipping: %-22s unsupported compression method %u\n"; #ifndef SFX static ZCONST char Far ComprMsgName[] = " skipping: %-22s `%s' method not supported\n"; static ZCONST char Far CmprNone[] = "store"; static ZCONST char Far CmprShrink[] = "shrink"; static ZCONST char Far CmprReduce[] = "reduce"; static ZCONST char Far CmprImplode[] = "implode"; static ZCONST char Far CmprTokenize[] = "tokenize"; static ZCONST char Far CmprDeflate[] = "deflate"; static ZCONST char Far CmprDeflat64[] = "deflate64"; static ZCONST char Far CmprDCLImplode[] = "DCL implode"; static ZCONST char Far CmprBzip[] = "bzip2"; static ZCONST char Far CmprLZMA[] = "LZMA"; static ZCONST char Far CmprIBMTerse[] = "IBM/Terse"; static ZCONST char Far CmprIBMLZ77[] = "IBM LZ77"; static ZCONST char Far CmprWavPack[] = "WavPack"; static ZCONST char Far CmprPPMd[] = "PPMd"; static ZCONST char Far *ComprNames[NUM_METHODS] = { CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce, CmprImplode, CmprTokenize, CmprDeflate, CmprDeflat64, CmprDCLImplode, CmprBzip, CmprLZMA, CmprIBMTerse, CmprIBMLZ77, CmprWavPack, CmprPPMd }; static ZCONST unsigned ComprIDs[NUM_METHODS] = { STORED, SHRUNK, REDUCED1, REDUCED2, REDUCED3, REDUCED4, IMPLODED, TOKENIZED, DEFLATED, ENHDEFLATED, DCLIMPLODED, BZIPPED, LZMAED, IBMTERSED, IBMLZ77ED, WAVPACKED, PPMDED }; #endif /* !SFX */ static ZCONST char Far FilNamMsg[] = "%s: bad filename length (%s)\n"; #ifndef SFX static ZCONST char Far WarnNoMemCFName[] = "%s: warning, no memory for comparison with local header\n"; static ZCONST char Far LvsCFNamMsg[] = "%s: mismatching \"local\" filename (%s),\n\ continuing with \"central\" filename version\n"; #endif /* !SFX */ #if (!defined(SFX) && defined(UNICODE_SUPPORT)) static ZCONST char Far GP11FlagsDiffer[] = "file #%lu (%s):\n\ mismatch between local and central GPF bit 11 (\"UTF-8\"),\n\ continuing with central flag (IsUTF8 = %d)\n"; #endif /* !SFX && UNICODE_SUPPORT */ static ZCONST char Far WrnStorUCSizCSizDiff[] = "%s: ucsize %s <> csize %s for STORED entry\n\ continuing with \"compressed\" size value\n"; static ZCONST char Far ExtFieldMsg[] = "%s: bad extra field length (%s)\n"; static ZCONST char Far OffsetMsg[] = "file #%lu: bad zipfile offset (%s): %ld\n"; static ZCONST char Far ExtractMsg[] = "%8sing: %-22s %s%s"; #ifndef SFX static ZCONST char Far LengthMsg[] = "%s %s: %s bytes required to uncompress to %s bytes;\n %s\ supposed to require %s bytes%s%s%s\n"; #endif static ZCONST char Far BadFileCommLength[] = "%s: bad file comment length\n"; static ZCONST char Far LocalHdrSig[] = "local header sig"; static ZCONST char Far BadLocalHdr[] = "file #%lu: bad local header\n"; static ZCONST char Far AttemptRecompensate[] = " (attempting to re-compensate)\n"; #ifndef SFX static ZCONST char Far BackslashPathSep[] = "warning: %s appears to use backslashes as path separators\n"; #endif static ZCONST char Far AbsolutePathWarning[] = "warning: stripped absolute path spec from %s\n"; static ZCONST char Far SkipVolumeLabel[] = " skipping: %-22s %svolume label\n"; #ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */ static ZCONST char Far DirlistEntryNoMem[] = "warning: cannot alloc memory for dir times/permissions/UID/GID\n"; static ZCONST char Far DirlistSortNoMem[] = "warning: cannot alloc memory to sort dir times/perms/etc.\n"; static ZCONST char Far DirlistSetAttrFailed[] = "warning: set times/attribs failed for %s\n"; static ZCONST char Far DirlistFailAttrSum[] = " failed setting times/attribs for %lu dir entries"; #endif #ifdef SYMLINKS /* messages of the deferred symlinks handler */ static ZCONST char Far SymLnkWarnNoMem[] = "warning: deferred symlink (%s) failed:\n\ out of memory\n"; static ZCONST char Far SymLnkWarnInvalid[] = "warning: deferred symlink (%s) failed:\n\ invalid placeholder file\n"; static ZCONST char Far SymLnkDeferred[] = "finishing deferred symbolic links:\n"; static ZCONST char Far SymLnkFinish[] = " %-22s -> %s\n"; #endif #ifndef WINDLL static ZCONST char Far ReplaceQuery[] = # ifdef VMS "new version of %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; # else "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; # endif static ZCONST char Far AssumeNone[] = " NULL\n(EOF or read error, treating as \"[N]one\" ...)\n"; static ZCONST char Far NewNameQuery[] = "new name: "; static ZCONST char Far InvalidResponse[] = "error: invalid response [%s]\n"; #endif /* !WINDLL */ static ZCONST char Far ErrorInArchive[] = "At least one %serror was detected in %s.\n"; static ZCONST char Far ZeroFilesTested[] = "Caution: zero files tested in %s.\n"; #ifndef VMS static ZCONST char Far VMSFormatQuery[] = "\n%s: stored in VMS format. Extract anyway? (y/n) "; #endif #if CRYPT static ZCONST char Far SkipCannotGetPasswd[] = " skipping: %-22s unable to get password\n"; static ZCONST char Far SkipIncorrectPasswd[] = " skipping: %-22s incorrect password\n"; static ZCONST char Far FilesSkipBadPasswd[] = "%lu file%s skipped because of incorrect password.\n"; static ZCONST char Far MaybeBadPasswd[] = " (may instead be incorrect password)\n"; #else static ZCONST char Far SkipEncrypted[] = " skipping: %-22s encrypted (not supported)\n"; #endif static ZCONST char Far NoErrInCompData[] = "No errors detected in compressed data of %s.\n"; static ZCONST char Far NoErrInTestedFiles[] = "No errors detected in %s for the %lu file%s tested.\n"; static ZCONST char Far FilesSkipped[] = "%lu file%s skipped because of unsupported compression or encoding.\n"; static ZCONST char Far ErrUnzipFile[] = " error: %s%s %s\n"; static ZCONST char Far ErrUnzipNoFile[] = "\n error: %s%s\n"; static ZCONST char Far NotEnoughMem[] = "not enough memory to "; static ZCONST char Far InvalidComprData[] = "invalid compressed data to "; static ZCONST char Far Inflate[] = "inflate"; #ifdef USE_BZIP2 static ZCONST char Far BUnzip[] = "bunzip"; #endif #ifndef SFX static ZCONST char Far Explode[] = "explode"; #ifndef LZW_CLEAN static ZCONST char Far Unshrink[] = "unshrink"; #endif #endif #if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK)) static ZCONST char Far FileTruncated[] = "warning: %s is probably truncated\n"; #endif static ZCONST char Far FileUnknownCompMethod[] = "%s: unknown compression method\n"; static ZCONST char Far BadCRC[] = " bad CRC %08lx (should be %08lx)\n"; /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */ char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s"; char ZCONST Far TruncNTSD[] = " compressed WinNT security data missing (%d bytes)%s"; #ifndef SFX static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \ EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n"; static ZCONST char Far InvalidComprDataEAs[] = " invalid compressed data for EAs\n"; # if (defined(WIN32) && defined(NTSD_EAS)) static ZCONST char Far InvalidSecurityEAs[] = " EAs fail security check\n"; # endif static ZCONST char Far UnsuppNTSDVersEAs[] = " unsupported NTSD EAs version %d\n"; static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n"; static ZCONST char Far UnknComprMethodEAs[] = " unknown compression method for EAs (%u)\n"; static ZCONST char Far NotEnoughMemEAs[] = " out of memory while inflating EAs\n"; static ZCONST char Far UnknErrorEAs[] = " unknown error on extended attributes\n"; #endif /* !SFX */ static ZCONST char Far UnsupportedExtraField[] = "\nerror: unsupported extra-field compression type (%u)--skipping\n"; static ZCONST char Far BadExtraFieldCRC[] = "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n"; /**************************************/ /* Function extract_or_test_files() */ /**************************************/ int extract_or_test_files(__G) /* return PK-type error code */ __GDEF { unsigned i, j; zoff_t cd_bufstart; uch *cd_inptr; int cd_incnt; ulg filnum=0L, blknum=0L; int reached_end; #ifndef SFX int no_endsig_found; #endif int error, error_in_archive=PK_COOL; int *fn_matched=NULL, *xn_matched=NULL; zucn_t members_processed; ulg num_skipped=0L, num_bad_pwd=0L; zoff_t old_extra_bytes = 0L; #ifdef SET_DIR_ATTRIB unsigned num_dirs=0; direntry *dirlist=(direntry *)NULL, **sorted_dirlist=(direntry **)NULL; #endif /* * First, two general initializations are applied. These have been moved * here from process_zipfiles() because they are only needed for accessing * and/or extracting the data content of the zip archive. */ /* a) initialize the CRC table pointer (once) */ if (CRC_32_TAB == NULL) { if ((CRC_32_TAB = get_crc_table()) == NULL) { return PK_MEM; } } #if (!defined(SFX) || defined(SFX_EXDIR)) /* b) check out if specified extraction root directory exists */ if (uO.exdir != (char *)NULL && G.extract_flag) { G.create_dirs = !uO.fflag; if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) { /* out of memory, or file in way */ return (error == MPN_NOMEM ? PK_MEM : PK_ERR); } } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- The basic idea of this function is as follows. Since the central di- rectory lies at the end of the zipfile and the member files lie at the beginning or middle or wherever, it is not very desirable to simply read a central directory entry, jump to the member and extract it, and then jump back to the central directory. In the case of a large zipfile this would lead to a whole lot of disk-grinding, especially if each mem- ber file is small. Instead, we read from the central directory the per- tinent information for a block of files, then go extract/test the whole block. Thus this routine contains two small(er) loops within a very large outer loop: the first of the small ones reads a block of files from the central directory; the second extracts or tests each file; and the outer one loops over blocks. There's some file-pointer positioning stuff in between, but that's about it. Btw, it's because of this jump- ing around that we can afford to be lenient if an error occurs in one of the member files: we should still be able to go find the other members, since we know the offset of each from the beginning of the zipfile. ---------------------------------------------------------------------------*/ G.pInfo = G.info; #if CRYPT G.newzip = TRUE; #endif #ifndef SFX G.reported_backslash = FALSE; #endif /* malloc space for check on unmatched filespecs (OK if one or both NULL) */ if (G.filespecs > 0 && (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL) for (i = 0; i < G.filespecs; ++i) fn_matched[i] = FALSE; if (G.xfilespecs > 0 && (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL) for (i = 0; i < G.xfilespecs; ++i) xn_matched[i] = FALSE; /*--------------------------------------------------------------------------- Begin main loop over blocks of member files. We know the entire central directory is on this disk: we would not have any of this information un- less the end-of-central-directory record was on this disk, and we would not have gotten to this routine unless this is also the disk on which the central directory starts. In practice, this had better be the ONLY disk in the archive, but we'll add multi-disk support soon. ---------------------------------------------------------------------------*/ members_processed = 0; #ifndef SFX no_endsig_found = FALSE; #endif reached_end = FALSE; while (!reached_end) { j = 0; #ifdef AMIGA memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *)); #endif /* * Loop through files in central directory, storing offsets, file * attributes, case-conversion and text-conversion flags until block * size is reached. */ while ((j < DIR_BLKSIZ)) { G.pInfo = &G.info[j]; if (readbuf(__G__ G.sig, 4) == 0) { error_in_archive = PK_EOF; reached_end = TRUE; /* ...so no more left to do */ break; } if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a new entry? */ /* no new central directory entry * -> is the number of processed entries compatible with the * number of entries as stored in the end_central record? */ if ((members_processed & (G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16)) == G.ecrec.total_entries_central_dir) { #ifndef SFX /* yes, so look if we ARE back at the end_central record */ no_endsig_found = ( (memcmp(G.sig, (G.ecrec.have_ecr64 ? end_central64_sig : end_central_sig), 4) != 0) && (!G.ecrec.is_zip64_archive) && (memcmp(G.sig, end_central_sig, 4) != 0) ); #endif /* !SFX */ } else { /* no; we have found an error in the central directory * -> report it and stop searching for more Zip entries */ Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1)); Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); error_in_archive = PK_BADERR; } reached_end = TRUE; /* ...so no more left to do */ break; } /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */ if ((error = process_cdir_file_hdr(__G)) != PK_COOL) { error_in_archive = error; /* only PK_EOF defined */ reached_end = TRUE; /* ...so no more left to do */ break; } if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { /* fatal: no more left to do */ Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg), FnFilter1(G.filename), "central")); reached_end = TRUE; break; } } if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { /* fatal */ Info(slide, 0x401, ((char *)slide, LoadFarString(ExtFieldMsg), FnFilter1(G.filename), "central")); reached_end = TRUE; break; } } #ifdef AMIGA G.filenote_slot = j; if ((error = do_string(__G__ G.crec.file_comment_length, uO.N_flag ? FILENOTE : SKIP)) != PK_COOL) #else if ((error = do_string(__G__ G.crec.file_comment_length, SKIP)) != PK_COOL) #endif { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { /* fatal */ Info(slide, 0x421, ((char *)slide, LoadFarString(BadFileCommLength), FnFilter1(G.filename))); reached_end = TRUE; break; } } if (G.process_all_files) { if (store_info(__G)) ++j; /* file is OK; info[] stored; continue with next */ else ++num_skipped; } else { int do_this_file; if (G.filespecs == 0) do_this_file = TRUE; else { /* check if this entry matches an `include' argument */ do_this_file = FALSE; for (i = 0; i < G.filespecs; i++) if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) { do_this_file = TRUE; /* ^-- ignore case or not? */ if (fn_matched) fn_matched[i] = TRUE; break; /* found match, so stop looping */ } } if (do_this_file) { /* check if this is an excluded file */ for (i = 0; i < G.xfilespecs; i++) if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) { do_this_file = FALSE; /* ^-- ignore case or not? */ if (xn_matched) xn_matched[i] = TRUE; break; } } if (do_this_file) { if (store_info(__G)) ++j; /* file is OK */ else ++num_skipped; /* unsupp. compression or encryption */ } } /* end if (process_all_files) */ members_processed++; } /* end while-loop (adding files to current block) */ /* save position in central directory so can come back later */ cd_bufstart = G.cur_zipfile_bufstart; cd_inptr = G.inptr; cd_incnt = G.incnt; /*----------------------------------------------------------------------- Second loop: process files in current block, extracting or testing each one. -----------------------------------------------------------------------*/ error = extract_or_test_entrylist(__G__ j, &filnum, &num_bad_pwd, &old_extra_bytes, #ifdef SET_DIR_ATTRIB &num_dirs, &dirlist, #endif error_in_archive); if (error != PK_COOL) { if (error > error_in_archive) error_in_archive = error; /* ...and keep going (unless disk full or user break) */ if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) { /* clear reached_end to signal premature stop ... */ reached_end = FALSE; /* ... and cancel scanning the central directory */ break; } } /* * Jump back to where we were in the central directory, then go and do * the next batch of files. */ #ifdef USE_STRM_INPUT zfseeko(G.zipfd, cd_bufstart, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, cd_bufstart, SEEK_SET); #endif /* ?USE_STRM_INPUT */ read(G.zipfd, (char *)G.inbuf, INBUFSIZ); /* been here before... */ G.inptr = cd_inptr; G.incnt = cd_incnt; ++blknum; #ifdef TEST printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart); printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart, cur_zipfile_bufstart); printf("inptr-inbuf = %d\n", G.inptr-G.inbuf); printf("incnt = %d\n\n", G.incnt); #endif } /* end while-loop (blocks of files in central directory) */ /*--------------------------------------------------------------------------- Process the list of deferred symlink extractions and finish up the symbolic links. ---------------------------------------------------------------------------*/ #ifdef SYMLINKS if (G.slink_last != NULL) { if (QCOND2) Info(slide, 0, ((char *)slide, LoadFarString(SymLnkDeferred))); while (G.slink_head != NULL) { set_deferred_symlink(__G__ G.slink_head); /* remove the processed entry from the chain and free its memory */ G.slink_last = G.slink_head; G.slink_head = G.slink_last->next; free(G.slink_last); } G.slink_last = NULL; } #endif /* SYMLINKS */ /*--------------------------------------------------------------------------- Go back through saved list of directories, sort and set times/perms/UIDs and GIDs from the deepest level on up. ---------------------------------------------------------------------------*/ #ifdef SET_DIR_ATTRIB if (num_dirs > 0) { sorted_dirlist = (direntry **)malloc(num_dirs*sizeof(direntry *)); if (sorted_dirlist == (direntry **)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(DirlistSortNoMem))); while (dirlist != (direntry *)NULL) { direntry *d = dirlist; dirlist = dirlist->next; free(d); } } else { ulg ndirs_fail = 0; if (num_dirs == 1) sorted_dirlist[0] = dirlist; else { for (i = 0; i < num_dirs; ++i) { sorted_dirlist[i] = dirlist; dirlist = dirlist->next; } qsort((char *)sorted_dirlist, num_dirs, sizeof(direntry *), dircomp); } Trace((stderr, "setting directory times/perms/attributes\n")); for (i = 0; i < num_dirs; ++i) { direntry *d = sorted_dirlist[i]; Trace((stderr, "dir = %s\n", d->fn)); if ((error = set_direc_attribs(__G__ d)) != PK_OK) { ndirs_fail++; Info(slide, 0x201, ((char *)slide, LoadFarString(DirlistSetAttrFailed), d->fn)); if (!error_in_archive) error_in_archive = error; } free(d); } free(sorted_dirlist); if (!uO.tflag && QCOND2) { if (ndirs_fail > 0) Info(slide, 0, ((char *)slide, LoadFarString(DirlistFailAttrSum), ndirs_fail)); } } } #endif /* SET_DIR_ATTRIB */ /*--------------------------------------------------------------------------- Check for unmatched filespecs on command line and print warning if any found. Free allocated memory. (But suppress check when central dir scan was interrupted prematurely.) ---------------------------------------------------------------------------*/ if (fn_matched) { if (reached_end) for (i = 0; i < G.filespecs; ++i) if (!fn_matched[i]) { #ifdef DLL if (!G.redirect_data && !G.redirect_text) Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameNotMatched), G.pfnames[i])); else setFileNotFound(__G); #else Info(slide, 1, ((char *)slide, LoadFarString(FilenameNotMatched), G.pfnames[i])); #endif if (error_in_archive <= PK_WARN) error_in_archive = PK_FIND; /* some files not found */ } free((zvoid *)fn_matched); } if (xn_matched) { if (reached_end) for (i = 0; i < G.xfilespecs; ++i) if (!xn_matched[i]) Info(slide, 0x401, ((char *)slide, LoadFarString(ExclFilenameNotMatched), G.pxnames[i])); free((zvoid *)xn_matched); } /*--------------------------------------------------------------------------- Now, all locally allocated memory has been released. When the central directory processing has been interrupted prematurely, it is safe to return immediately. All completeness checks and summary messages are skipped in this case. ---------------------------------------------------------------------------*/ if (!reached_end) return error_in_archive; /*--------------------------------------------------------------------------- Double-check that we're back at the end-of-central-directory record, and print quick summary of results, if we were just testing the archive. We send the summary to stdout so that people doing the testing in the back- ground and redirecting to a file can just do a "tail" on the output file. ---------------------------------------------------------------------------*/ #ifndef SFX if (no_endsig_found) { /* just to make sure */ Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); if (!error_in_archive) /* don't overwrite stronger error */ error_in_archive = PK_WARN; } #endif /* !SFX */ if (uO.tflag) { ulg num = filnum - num_bad_pwd; if (uO.qflag < 2) { /* GRR 930710: was (uO.qflag == 1) */ if (error_in_archive) Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive), (error_in_archive == PK_WARN)? "warning-" : "", G.zipfn)); else if (num == 0L) Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested), G.zipfn)); else if (G.process_all_files && (num_skipped+num_bad_pwd == 0L)) Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData), G.zipfn)); else Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles) , G.zipfn, num, (num==1L)? "":"s")); if (num_skipped > 0L) Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped), num_skipped, (num_skipped==1L)? "":"s")); #if CRYPT if (num_bad_pwd > 0L) Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd) , num_bad_pwd, (num_bad_pwd==1L)? "":"s")); #endif /* CRYPT */ } } /* give warning if files not tested or extracted (first condition can still * happen if zipfile is empty and no files specified on command line) */ if ((filnum == 0) && error_in_archive <= PK_WARN) { if (num_skipped > 0L) error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */ else error_in_archive = PK_FIND; /* no files found at all */ } #if CRYPT else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN) error_in_archive = IZ_BADPWD; /* bad passwd => all files skipped */ #endif else if ((num_skipped > 0L) && error_in_archive <= PK_WARN) error_in_archive = IZ_UNSUP; /* was PK_WARN; Jean-loup complained */ #if CRYPT else if ((num_bad_pwd > 0L) && !error_in_archive) error_in_archive = PK_WARN; #endif return error_in_archive; } /* end function extract_or_test_files() */ /***************************/ /* Function store_info() */ /***************************/ static int store_info(__G) /* return 0 if skipping, 1 if OK */ __GDEF { #ifdef USE_BZIP2 # define UNKN_BZ2 (G.crec.compression_method!=BZIPPED) #else # define UNKN_BZ2 TRUE /* bzip2 unknown */ #endif #ifdef USE_LZMA # define UNKN_LZMA (G.crec.compression_method!=LZMAED) #else # define UNKN_LZMA TRUE /* LZMA unknown */ #endif #ifdef USE_WAVP # define UNKN_WAVP (G.crec.compression_method!=WAVPACKED) #else # define UNKN_WAVP TRUE /* WavPack unknown */ #endif #ifdef USE_PPMD # define UNKN_PPMD (G.crec.compression_method!=PPMDED) #else # define UNKN_PPMD TRUE /* PPMd unknown */ #endif #ifdef SFX # ifdef USE_DEFLATE64 # define UNKN_COMPR \ (G.crec.compression_method!=STORED && G.crec.compression_methodENHDEFLATED \ && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD) # else # define UNKN_COMPR \ (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\ && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD) # endif #else # ifdef COPYRIGHT_CLEAN /* no reduced files */ # define UNKN_RED (G.crec.compression_method >= REDUCED1 && \ G.crec.compression_method <= REDUCED4) # else # define UNKN_RED FALSE /* reducing not unknown */ # endif # ifdef LZW_CLEAN /* no shrunk files */ # define UNKN_SHR (G.crec.compression_method == SHRUNK) # else # define UNKN_SHR FALSE /* unshrinking not unknown */ # endif # ifdef USE_DEFLATE64 # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ G.crec.compression_method==TOKENIZED || \ (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \ && UNKN_WAVP && UNKN_PPMD)) # else # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ G.crec.compression_method==TOKENIZED || \ (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \ && UNKN_WAVP && UNKN_PPMD)) # endif #endif #if (defined(USE_BZIP2) && (UNZIP_VERSION < UNZIP_BZ2VERS)) int unzvers_support = (UNKN_BZ2 ? UNZIP_VERSION : UNZIP_BZ2VERS); # define UNZVERS_SUPPORT unzvers_support #else # define UNZVERS_SUPPORT UNZIP_VERSION #endif /*--------------------------------------------------------------------------- Check central directory info for version/compatibility requirements. ---------------------------------------------------------------------------*/ G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1; /* bit field */ G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8; /* bit */ G.pInfo->textfile = G.crec.internal_file_attributes & 1; /* bit field */ G.pInfo->crc = G.crec.crc32; G.pInfo->compr_size = G.crec.csize; G.pInfo->uncompr_size = G.crec.ucsize; switch (uO.aflag) { case 0: G.pInfo->textmode = FALSE; /* bit field */ break; case 1: G.pInfo->textmode = G.pInfo->textfile; /* auto-convert mode */ break; default: /* case 2: */ G.pInfo->textmode = TRUE; break; } if (G.crec.version_needed_to_extract[1] == VMS_) { if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg), FnFilter1(G.filename), "VMS", G.crec.version_needed_to_extract[0] / 10, G.crec.version_needed_to_extract[0] % 10, VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10)); return 0; } #ifndef VMS /* won't be able to use extra field, but still have data */ else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */ Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery), FnFilter1(G.filename))); fgets(G.answerbuf, sizeof(G.answerbuf), stdin); if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y')) return 0; } #endif /* !VMS */ /* usual file type: don't need VMS to extract */ } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg), FnFilter1(G.filename), "PK", G.crec.version_needed_to_extract[0] / 10, G.crec.version_needed_to_extract[0] % 10, UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10)); return 0; } if (UNKN_COMPR) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) { #ifndef SFX unsigned cmpridx; if ((cmpridx = find_compr_idx(G.crec.compression_method)) < NUM_METHODS) Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName), FnFilter1(G.filename), LoadFarStringSmall(ComprNames[cmpridx]))); else #endif Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum), FnFilter1(G.filename), G.crec.compression_method)); } return 0; } #if (!CRYPT) if (G.pInfo->encrypted) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted), FnFilter1(G.filename))); return 0; } #endif /* !CRYPT */ #ifndef SFX /* store a copy of the central header filename for later comparison */ if ((G.pInfo->cfilname = zfmalloc(strlen(G.filename) + 1)) == NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(WarnNoMemCFName), FnFilter1(G.filename))); } else zfstrcpy(G.pInfo->cfilname, G.filename); #endif /* !SFX */ /* map whatever file attributes we have into the local format */ mapattr(__G); /* GRR: worry about return value later */ G.pInfo->diskstart = G.crec.disk_number_start; G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header; return 1; } /* end function store_info() */ #ifndef SFX /*******************************/ /* Function find_compr_idx() */ /*******************************/ unsigned find_compr_idx(compr_methodnum) unsigned compr_methodnum; { unsigned i; for (i = 0; i < NUM_METHODS; i++) { if (ComprIDs[i] == compr_methodnum) break; } return i; } #endif /* !SFX */ /******************************************/ /* Function extract_or_test_entrylist() */ /******************************************/ static int extract_or_test_entrylist(__G__ numchunk, pfilnum, pnum_bad_pwd, pold_extra_bytes, #ifdef SET_DIR_ATTRIB pnum_dirs, pdirlist, #endif error_in_archive) /* return PK-type error code */ __GDEF unsigned numchunk; ulg *pfilnum; ulg *pnum_bad_pwd; zoff_t *pold_extra_bytes; #ifdef SET_DIR_ATTRIB unsigned *pnum_dirs; direntry **pdirlist; #endif int error_in_archive; { unsigned i; int renamed, query; int skip_entry; zoff_t bufstart, inbuf_offset, request; int error, errcode; /* possible values for local skip_entry flag: */ #define SKIP_NO 0 /* do not skip this entry */ #define SKIP_Y_EXISTING 1 /* skip this entry, do not overwrite file */ #define SKIP_Y_NONEXIST 2 /* skip this entry, do not create new file */ /*----------------------------------------------------------------------- Second loop: process files in current block, extracting or testing each one. -----------------------------------------------------------------------*/ for (i = 0; i < numchunk; ++i) { (*pfilnum)++; /* *pfilnum = i + blknum*DIR_BLKSIZ + 1; */ G.pInfo = &G.info[i]; #ifdef NOVELL_BUG_FAILSAFE G.dne = FALSE; /* assume file exists until stat() says otherwise */ #endif /* if the target position is not within the current input buffer * (either haven't yet read far enough, or (maybe) skipping back- * ward), skip to the target position and reset readbuf(). */ /* seek_zipf(__G__ pInfo->offset); */ request = G.pInfo->offset + G.extra_bytes; inbuf_offset = request % INBUFSIZ; bufstart = request - inbuf_offset; Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n", (long)request, (long)inbuf_offset)); Trace((stderr, "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", (long)bufstart, (long)G.cur_zipfile_bufstart)); if (request < 0) { Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg), G.zipfn, LoadFarString(ReportMsg))); error_in_archive = PK_ERR; if (*pfilnum == 1 && G.extra_bytes != 0L) { Info(slide, 0x401, ((char *)slide, LoadFarString(AttemptRecompensate))); *pold_extra_bytes = G.extra_bytes; G.extra_bytes = 0L; request = G.pInfo->offset; /* could also check if != 0 */ inbuf_offset = request % INBUFSIZ; bufstart = request - inbuf_offset; Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n", (long)request, (long)inbuf_offset)); Trace((stderr, "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", (long)bufstart, (long)G.cur_zipfile_bufstart)); /* try again */ if (request < 0) { Trace((stderr, "debug: recompensated request still < 0\n")); Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg), G.zipfn, LoadFarString(ReportMsg))); error_in_archive = PK_BADERR; continue; } } else { error_in_archive = PK_BADERR; continue; /* this one hosed; try next */ } } if (bufstart != G.cur_zipfile_bufstart) { Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n")); #ifdef USE_STRM_INPUT zfseeko(G.zipfd, bufstart, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, bufstart, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) { Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), *pfilnum, "lseek", (long)bufstart)); error_in_archive = PK_BADERR; continue; /* can still do next file */ } G.inptr = G.inbuf + (int)inbuf_offset; G.incnt -= (int)inbuf_offset; } else { G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset; G.inptr = G.inbuf + (int)inbuf_offset; } /* should be in proper position now, so check for sig */ if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */ Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), *pfilnum, "EOF", (long)request)); error_in_archive = PK_BADERR; continue; /* but can still try next one */ } if (memcmp(G.sig, local_hdr_sig, 4)) { Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request)); /* GRRDUMP(G.sig, 4) GRRDUMP(local_hdr_sig, 4) */ error_in_archive = PK_ERR; if ((*pfilnum == 1 && G.extra_bytes != 0L) || (G.extra_bytes == 0L && *pold_extra_bytes != 0L)) { Info(slide, 0x401, ((char *)slide, LoadFarString(AttemptRecompensate))); if (G.extra_bytes) { *pold_extra_bytes = G.extra_bytes; G.extra_bytes = 0L; } else G.extra_bytes = *pold_extra_bytes; /* third attempt */ if (((error = seek_zipf(__G__ G.pInfo->offset)) != PK_OK) || (readbuf(__G__ G.sig, 4) == 0)) { /* bad offset */ if (error != PK_BADERR) Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), *pfilnum, "EOF", (long)request)); error_in_archive = PK_BADERR; continue; /* but can still try next one */ } if (memcmp(G.sig, local_hdr_sig, 4)) { Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request)); error_in_archive = PK_BADERR; continue; } } else continue; /* this one hosed; try next */ } if ((error = process_local_file_hdr(__G)) != PK_COOL) { Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr), *pfilnum)); error_in_archive = error; /* only PK_EOF defined */ continue; /* can still try next one */ } #if (!defined(SFX) && defined(UNICODE_SUPPORT)) if (((G.lrec.general_purpose_bit_flag & (1 << 11)) == (1 << 11)) != (G.pInfo->GPFIsUTF8 != 0)) { if (QCOND2) { # ifdef SMALL_MEM char *temp_cfilnam = slide + (7 * (WSIZE>>3)); zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname); # define cFile_PrintBuf temp_cfilnam # else # define cFile_PrintBuf G.pInfo->cfilname # endif Info(slide, 0x421, ((char *)slide, LoadFarStringSmall2(GP11FlagsDiffer), *pfilnum, FnFilter1(cFile_PrintBuf), G.pInfo->GPFIsUTF8)); # undef cFile_PrintBuf } if (error_in_archive < PK_WARN) error_in_archive = PK_WARN; } #endif /* !SFX && UNICODE_SUPPORT */ if ((error = do_string(__G__ G.lrec.filename_length, DS_FN_L)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg), FnFilter1(G.filename), "local")); continue; /* go on to next one */ } } if (G.extra_field != (uch *)NULL) { free(G.extra_field); G.extra_field = (uch *)NULL; } if ((error = do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { Info(slide, 0x401, ((char *)slide, LoadFarString(ExtFieldMsg), FnFilter1(G.filename), "local")); continue; /* go on */ } } #ifndef SFX /* Filename consistency checks must come after reading in the local * extra field, so that a UTF-8 entry name e.f. block has already * been processed. */ if (G.pInfo->cfilname != (char Far *)NULL) { if (zfstrcmp(G.pInfo->cfilname, G.filename) != 0) { # ifdef SMALL_MEM char *temp_cfilnam = slide + (7 * (WSIZE>>3)); zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname); # define cFile_PrintBuf temp_cfilnam # else # define cFile_PrintBuf G.pInfo->cfilname # endif Info(slide, 0x401, ((char *)slide, LoadFarStringSmall2(LvsCFNamMsg), FnFilter2(cFile_PrintBuf), FnFilter1(G.filename))); # undef cFile_PrintBuf zfstrcpy(G.filename, G.pInfo->cfilname); if (error_in_archive < PK_WARN) error_in_archive = PK_WARN; } zffree(G.pInfo->cfilname); G.pInfo->cfilname = (char Far *)NULL; } #endif /* !SFX */ /* Size consistency checks must come after reading in the local extra * field, so that any Zip64 extension local e.f. block has already * been processed. */ if (G.lrec.compression_method == STORED) { zusz_t csiz_decrypted = G.lrec.csize; if (G.pInfo->encrypted) csiz_decrypted -= 12; if (G.lrec.ucsize != csiz_decrypted) { Info(slide, 0x401, ((char *)slide, LoadFarStringSmall2(WrnStorUCSizCSizDiff), FnFilter1(G.filename), FmZofft(G.lrec.ucsize, NULL, "u"), FmZofft(csiz_decrypted, NULL, "u"))); G.lrec.ucsize = csiz_decrypted; if (error_in_archive < PK_WARN) error_in_archive = PK_WARN; } } #if CRYPT if (G.pInfo->encrypted && (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) { if (error == PK_WARN) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) Info(slide, 0x401, ((char *)slide, LoadFarString(SkipIncorrectPasswd), FnFilter1(G.filename))); ++(*pnum_bad_pwd); } else { /* (error > PK_WARN) */ if (error > error_in_archive) error_in_archive = error; Info(slide, 0x401, ((char *)slide, LoadFarString(SkipCannotGetPasswd), FnFilter1(G.filename))); } continue; /* go on to next file */ } #endif /* CRYPT */ /* * just about to extract file: if extracting to disk, check if * already exists, and if so, take appropriate action according to * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper * loop because we don't store the possibly renamed filename[] in * info[]) */ #ifdef DLL if (!uO.tflag && !uO.cflag && !G.redirect_data) #else if (!uO.tflag && !uO.cflag) #endif { renamed = FALSE; /* user hasn't renamed output file yet */ startover: query = FALSE; skip_entry = SKIP_NO; /* for files from DOS FAT, check for use of backslash instead * of slash as directory separator (bug in some zipper(s); so * far, not a problem in HPFS, NTFS or VFAT systems) */ #ifndef SFX if (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/')) { char *p=G.filename; if (*p) do { if (*p == '\\') { if (!G.reported_backslash) { Info(slide, 0x21, ((char *)slide, LoadFarString(BackslashPathSep), G.zipfn)); G.reported_backslash = TRUE; if (!error_in_archive) error_in_archive = PK_WARN; } *p = '/'; } } while (*PREINCSTR(p)); } #endif /* !SFX */ if (!renamed) { /* remove absolute path specs */ if (G.filename[0] == '/') { Info(slide, 0x401, ((char *)slide, LoadFarString(AbsolutePathWarning), FnFilter1(G.filename))); if (!error_in_archive) error_in_archive = PK_WARN; do { char *p = G.filename + 1; do { *(p-1) = *p; } while (*p++ != '\0'); } while (G.filename[0] == '/'); } } /* mapname can create dirs if not freshening or if renamed */ error = mapname(__G__ renamed); if ((errcode = error & ~MPN_MASK) != PK_OK && error_in_archive < errcode) error_in_archive = errcode; if ((errcode = error & MPN_MASK) > MPN_INF_TRUNC) { if (errcode == MPN_CREATED_DIR) { #ifdef SET_DIR_ATTRIB direntry *d_entry; error = defer_dir_attribs(__G__ &d_entry); if (d_entry == (direntry *)NULL) { /* There may be no dir_attribs info available, or * we have encountered a mem allocation error. * In case of an error, report it and set program * error state to warning level. */ if (error) { Info(slide, 0x401, ((char *)slide, LoadFarString(DirlistEntryNoMem))); if (!error_in_archive) error_in_archive = PK_WARN; } } else { d_entry->next = (*pdirlist); (*pdirlist) = d_entry; ++(*pnum_dirs); } #endif /* SET_DIR_ATTRIB */ } else if (errcode == MPN_VOL_LABEL) { #ifdef DOS_OS2_W32 Info(slide, 0x401, ((char *)slide, LoadFarString(SkipVolumeLabel), FnFilter1(G.filename), uO.volflag? "hard disk " : "")); #else Info(slide, 1, ((char *)slide, LoadFarString(SkipVolumeLabel), FnFilter1(G.filename), "")); #endif } else if (errcode > MPN_INF_SKIP && error_in_archive < PK_ERR) error_in_archive = PK_ERR; Trace((stderr, "mapname(%s) returns error code = %d\n", FnFilter1(G.filename), error)); continue; /* go on to next file */ } #ifdef QDOS QFilename(__G__ G.filename); #endif switch (check_for_newer(__G__ G.filename)) { case DOES_NOT_EXIST: #ifdef NOVELL_BUG_FAILSAFE G.dne = TRUE; /* stat() says file DOES NOT EXIST */ #endif /* freshen (no new files): skip unless just renamed */ if (uO.fflag && !renamed) skip_entry = SKIP_Y_NONEXIST; break; case EXISTS_AND_OLDER: #ifdef UNIXBACKUP if (!uO.B_flag) #endif { if (IS_OVERWRT_NONE) /* never overwrite: skip file */ skip_entry = SKIP_Y_EXISTING; else if (!IS_OVERWRT_ALL) query = TRUE; } break; case EXISTS_AND_NEWER: /* (or equal) */ #ifdef UNIXBACKUP if ((!uO.B_flag && IS_OVERWRT_NONE) || #else if (IS_OVERWRT_NONE || #endif (uO.uflag && !renamed)) { /* skip if update/freshen & orig name */ skip_entry = SKIP_Y_EXISTING; } else { #ifdef UNIXBACKUP if (!IS_OVERWRT_ALL && !uO.B_flag) #else if (!IS_OVERWRT_ALL) #endif query = TRUE; } break; } #ifdef VMS /* 2008-07-24 SMS. * On VMS, if the file name includes a version number, * and "-V" ("retain VMS version numbers", V_flag) is in * effect, then the VMS-specific code will handle any * conflicts with an existing file, making this query * redundant. (Implicit "y" response here.) */ if (query && uO.V_flag) { /* Not discarding file versions. Look for one. */ int cndx = strlen(G.filename) - 1; while ((cndx > 0) && (isdigit(G.filename[cndx]))) cndx--; if (G.filename[cndx] == ';') /* File version found; skip the generic query, * proceeding with its default response "y". */ query = FALSE; } #endif /* VMS */ if (query) { #ifdef WINDLL switch (G.lpUserFunctions->replace != NULL ? (*G.lpUserFunctions->replace)(G.filename, FILNAMSIZ) : IDM_REPLACE_NONE) { case IDM_REPLACE_RENAME: _ISO_INTERN(G.filename); renamed = TRUE; goto startover; case IDM_REPLACE_ALL: G.overwrite_mode = OVERWRT_ALWAYS; /* FALL THROUGH, extract */ case IDM_REPLACE_YES: break; case IDM_REPLACE_NONE: G.overwrite_mode = OVERWRT_NEVER; /* FALL THROUGH, skip */ case IDM_REPLACE_NO: skip_entry = SKIP_Y_EXISTING; break; } #else /* !WINDLL */ extent fnlen; reprompt: Info(slide, 0x81, ((char *)slide, LoadFarString(ReplaceQuery), FnFilter1(G.filename))); if (fgets(G.answerbuf, sizeof(G.answerbuf), stdin) == (char *)NULL) { Info(slide, 1, ((char *)slide, LoadFarString(AssumeNone))); *G.answerbuf = 'N'; if (!error_in_archive) error_in_archive = 1; /* not extracted: warning */ } switch (*G.answerbuf) { case 'r': case 'R': do { Info(slide, 0x81, ((char *)slide, LoadFarString(NewNameQuery))); fgets(G.filename, FILNAMSIZ, stdin); /* usually get \n here: better check for it */ fnlen = strlen(G.filename); if (lastchar(G.filename, fnlen) == '\n') G.filename[--fnlen] = '\0'; } while (fnlen == 0); #ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */ _OEM_INTERN(G.filename); #endif renamed = TRUE; goto startover; /* sorry for a goto */ case 'A': /* dangerous option: force caps */ G.overwrite_mode = OVERWRT_ALWAYS; /* FALL THROUGH, extract */ case 'y': case 'Y': break; case 'N': G.overwrite_mode = OVERWRT_NEVER; /* FALL THROUGH, skip */ case 'n': /* skip file */ skip_entry = SKIP_Y_EXISTING; break; case '\n': case '\r': /* Improve echo of '\n' and/or '\r' (sizeof(G.answerbuf) == 10 (see globals.h), so there is enough space for the provided text...) */ strcpy(G.answerbuf, "{ENTER}"); /* fall through ... */ default: /* usually get \n here: remove it for nice display (fnlen can be re-used here, we are outside the "enter new filename" loop) */ fnlen = strlen(G.answerbuf); if (lastchar(G.answerbuf, fnlen) == '\n') G.answerbuf[--fnlen] = '\0'; Info(slide, 1, ((char *)slide, LoadFarString(InvalidResponse), G.answerbuf)); goto reprompt; /* yet another goto? */ } /* end switch (*answerbuf) */ #endif /* ?WINDLL */ } /* end if (query) */ if (skip_entry != SKIP_NO) { #ifdef WINDLL if (skip_entry == SKIP_Y_EXISTING) { /* report skipping of an existing entry */ Info(slide, 0, ((char *)slide, ((IS_OVERWRT_NONE || !uO.uflag || renamed) ? "Target file exists. Skipping %s\n" : "Target file newer. Skipping %s\n"), FnFilter1(G.filename))); } #endif /* WINDLL */ continue; } } /* end if (extracting to disk) */ #ifdef DLL if ((G.statreportcb != NULL) && (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn, G.filename, NULL)) { return IZ_CTRLC; /* cancel operation by user request */ } #endif #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ UserStop(); #endif #ifdef AMIGA G.filenote_slot = i; #endif G.disk_full = 0; if ((error = extract_or_test_member(__G)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; /* ...and keep going */ #ifdef DLL if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) { #else if (G.disk_full > 1) { #endif return error_in_archive; /* (unless disk full) */ } } #ifdef DLL if ((G.statreportcb != NULL) && (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn, G.filename, (zvoid *)&G.lrec.ucsize)) { return IZ_CTRLC; /* cancel operation by user request */ } #endif #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ UserStop(); #endif } /* end for-loop (i: files in current block) */ return error_in_archive; } /* end function extract_or_test_entrylist() */ /* wsize is used in extract_or_test_member() and UZbunzip2() */ #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) # define wsize G._wsize /* wsize is a variable */ #else # define wsize WSIZE /* wsize is a constant */ #endif /***************************************/ /* Function extract_or_test_member() */ /***************************************/ static int extract_or_test_member(__G) /* return PK-type error code */ __GDEF { char *nul="[empty] ", *txt="[text] ", *bin="[binary]"; #ifdef CMS_MVS char *ebc="[ebcdic]"; #endif register int b; int r, error=PK_COOL; /*--------------------------------------------------------------------------- Initialize variables, buffers, etc. ---------------------------------------------------------------------------*/ G.bits_left = 0; G.bitbuf = 0L; /* unreduce and unshrink only */ G.zipeof = 0; G.newfile = TRUE; G.crc32val = CRCVAL_INITIAL; #ifdef SYMLINKS /* If file is a (POSIX-compatible) symbolic link and we are extracting * to disk, prepare to restore the link. */ G.symlnk = (G.pInfo->symlink && !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0)); #endif /* SYMLINKS */ if (uO.tflag) { if (!uO.qflag) Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test", FnFilter1(G.filename), "", "")); } else { #ifdef DLL if (uO.cflag && !G.redirect_data) #else if (uO.cflag) #endif { #if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200)) G.outfile = freopen("", "wb", stdout); /* VAC++ ignores setmode */ #else G.outfile = stdout; #endif #ifdef DOS_FLX_NLM_OS2_W32 #if (defined(__HIGHC__) && !defined(FLEXOS)) setmode(G.outfile, _BINARY); #else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */ setmode(fileno(G.outfile), O_BINARY); #endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */ # define NEWLINE "\r\n" #else /* !DOS_FLX_NLM_OS2_W32 */ # define NEWLINE "\n" #endif /* ?DOS_FLX_NLM_OS2_W32 */ #ifdef VMS /* VMS: required even for stdout! */ if ((r = open_outfile(__G)) != 0) switch (r) { case OPENOUT_SKIPOK: return PK_OK; case OPENOUT_SKIPWARN: return PK_WARN; default: return PK_DISK; } } else if ((r = open_outfile(__G)) != 0) switch (r) { case OPENOUT_SKIPOK: return PK_OK; case OPENOUT_SKIPWARN: return PK_WARN; default: return PK_DISK; } #else /* !VMS */ } else if (open_outfile(__G)) return PK_DISK; #endif /* ?VMS */ } /*--------------------------------------------------------------------------- Unpack the file. ---------------------------------------------------------------------------*/ defer_leftover_input(__G); /* so NEXTBYTE bounds check will work */ switch (G.lrec.compression_method) { case STORED: if (!uO.tflag && QCOND2) { #ifdef SYMLINKS if (G.symlnk) /* can also be deflated, but rarer... */ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "link", FnFilter1(G.filename), "", "")); else #endif /* SYMLINKS */ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "extract", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt : bin)), uO.cflag? NEWLINE : "")); } #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) { wsize = G.redirect_size; redirSlide = G.redirect_buffer; } else { wsize = WSIZE; redirSlide = slide; } #endif G.outptr = redirSlide; G.outcnt = 0L; while ((b = NEXTBYTE) != EOF) { *G.outptr++ = (uch)b; if (++G.outcnt == wsize) { error = flush(__G__ redirSlide, G.outcnt, 0); G.outptr = redirSlide; G.outcnt = 0L; if (error != PK_COOL || G.disk_full) break; } } if (G.outcnt) { /* flush final (partial) buffer */ r = flush(__G__ redirSlide, G.outcnt, 0); if (error < r) error = r; } break; #ifndef SFX #ifndef LZW_CLEAN case SHRUNK: if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), LoadFarStringSmall(Unshrink), FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } if ((r = unshrink(__G)) != PK_COOL) { if (r < PK_DISK) { if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipFile), r == PK_MEM3 ? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Unshrink), FnFilter1(G.filename))); else Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == PK_MEM3 ? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Unshrink))); } error = r; } break; #endif /* !LZW_CLEAN */ #ifndef COPYRIGHT_CLEAN case REDUCED1: case REDUCED2: case REDUCED3: case REDUCED4: if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "unreduc", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } if ((r = unreduce(__G)) != PK_COOL) { /* unreduce() returns only PK_COOL, PK_DISK, or IZ_CTRLC */ error = r; } break; #endif /* !COPYRIGHT_CLEAN */ case IMPLODED: if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "explod", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } if ((r = explode(__G)) != 0) { if (r == 5) { /* treat 5 specially */ int warning = ((zusz_t)G.used_csize <= G.lrec.csize); if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg), "", warning ? "warning" : "error", FmZofft(G.used_csize, NULL, NULL), FmZofft(G.lrec.ucsize, NULL, "u"), warning ? " " : "", FmZofft(G.lrec.csize, NULL, "u"), " [", FnFilter1(G.filename), "]")); else Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg), "\n", warning ? "warning" : "error", FmZofft(G.used_csize, NULL, NULL), FmZofft(G.lrec.ucsize, NULL, "u"), warning ? " " : "", FmZofft(G.lrec.csize, NULL, "u"), "", "", ".")); error = warning ? PK_WARN : PK_ERR; } else if (r < PK_DISK) { if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Explode), FnFilter1(G.filename))); else Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Explode))); error = ((r == 3) ? PK_MEM3 : PK_ERR); } else { error = r; } } break; #endif /* !SFX */ case DEFLATED: #ifdef USE_DEFLATE64 case ENHDEFLATED: #endif if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "inflat", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } #ifndef USE_ZLIB /* zlib's function is called inflate(), too */ # define UZinflate inflate #endif if ((r = UZinflate(__G__ (G.lrec.compression_method == ENHDEFLATED))) != 0) { if (r < PK_DISK) { if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Inflate), FnFilter1(G.filename))); else Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Inflate))); error = ((r == 3) ? PK_MEM3 : PK_ERR); } else { error = r; } } break; #ifdef USE_BZIP2 case BZIPPED: if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "bunzipp", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } if ((r = UZbunzip2(__G)) != 0) { if (r < PK_DISK) { if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(BUnzip), FnFilter1(G.filename))); else Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(BUnzip))); error = ((r == 3) ? PK_MEM3 : PK_ERR); } else { error = r; } } break; #endif /* USE_BZIP2 */ default: /* should never get to this point */ Info(slide, 0x401, ((char *)slide, LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename))); /* close and delete file before return? */ undefer_input(__G); return PK_WARN; } /* end switch (compression method) */ /*--------------------------------------------------------------------------- Close the file and set its date and time (not necessarily in that order), and make sure the CRC checked out OK. Logical-AND the CRC for 64-bit machines (redundant on 32-bit machines). ---------------------------------------------------------------------------*/ #ifdef VMS /* VMS: required even for stdout! (final flush) */ if (!uO.tflag) /* don't close NULL file */ close_outfile(__G); #else #ifdef DLL if (!uO.tflag && (!uO.cflag || G.redirect_data)) { if (G.redirect_data) FINISH_REDIRECT(); else close_outfile(__G); } #else if (!uO.tflag && !uO.cflag) /* don't close NULL file or stdout */ close_outfile(__G); #endif #endif /* VMS */ /* GRR: CONVERT close_outfile() TO NON-VOID: CHECK FOR ERRORS! */ if (G.disk_full) { /* set by flush() */ if (G.disk_full > 1) { #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK)) /* delete the incomplete file if we can */ if (unlink(G.filename) != 0) Trace((stderr, "extract.c: could not delete %s\n", FnFilter1(G.filename))); #else /* warn user about the incomplete file */ Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated), FnFilter1(G.filename))); #endif error = PK_DISK; } else { error = PK_WARN; } } if (error > PK_WARN) {/* don't print redundant CRC error if error already */ undefer_input(__G); return error; } if (G.crc32val != G.lrec.crc32) { /* if quiet enough, we haven't output the filename yet: do it */ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, "%-22s ", FnFilter1(G.filename))); Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val, G.lrec.crc32)); #if CRYPT if (G.pInfo->encrypted) Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd))); #endif error = PK_ERR; } else if (uO.tflag) { #ifndef SFX if (G.extra_field) { if ((r = TestExtraField(__G__ G.extra_field, G.lrec.extra_field_length)) > error) error = r; } else #endif /* !SFX */ if (!uO.qflag) Info(slide, 0, ((char *)slide, " OK\n")); } else { if (QCOND2 && !error) /* GRR: is stdout reset to text mode yet? */ Info(slide, 0, ((char *)slide, "\n")); } undefer_input(__G); return error; } /* end function extract_or_test_member() */ #ifndef SFX /*******************************/ /* Function TestExtraField() */ /*******************************/ static int TestExtraField(__G__ ef, ef_len) __GDEF uch *ef; unsigned ef_len; { ush ebID; unsigned ebLen; unsigned eb_cmpr_offs = 0; int r; /* we know the regular compressed file data tested out OK, or else we * wouldn't be here ==> print filename if any extra-field errors found */ while (ef_len >= EB_HEADSIZE) { ebID = makeword(ef); ebLen = (unsigned)makeword(ef+EB_LEN); if (ebLen > (ef_len - EB_HEADSIZE)) { /* Discovered some extra field inconsistency! */ if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength), ebLen, (ef_len - EB_HEADSIZE))); return PK_ERR; } switch (ebID) { case EF_OS2: case EF_ACL: case EF_MAC3: case EF_BEOS: case EF_ATHEOS: switch (ebID) { case EF_OS2: case EF_ACL: eb_cmpr_offs = EB_OS2_HLEN; break; case EF_MAC3: if (ebLen >= EB_MAC3_HLEN && (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_M3_FL_UNCMPR) && (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN)) eb_cmpr_offs = 0; else eb_cmpr_offs = EB_MAC3_HLEN; break; case EF_BEOS: case EF_ATHEOS: if (ebLen >= EB_BEOS_HLEN && (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) && (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN)) eb_cmpr_offs = 0; else eb_cmpr_offs = EB_BEOS_HLEN; break; } if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL)) != PK_OK) { if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); switch (r) { case IZ_EF_TRUNC: Info(slide, 1, ((char *)slide, LoadFarString(TruncEAs), ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n")); break; case PK_ERR: Info(slide, 1, ((char *)slide, LoadFarString(InvalidComprDataEAs))); break; case PK_MEM3: case PK_MEM4: Info(slide, 1, ((char *)slide, LoadFarString(NotEnoughMemEAs))); break; default: if ((r & 0xff) != PK_ERR) Info(slide, 1, ((char *)slide, LoadFarString(UnknErrorEAs))); else { ush m = (ush)(r >> 8); if (m == DEFLATED) /* GRR KLUDGE! */ Info(slide, 1, ((char *)slide, LoadFarString(BadCRC_EAs))); else Info(slide, 1, ((char *)slide, LoadFarString(UnknComprMethodEAs), m)); } break; } return r; } break; case EF_NTSD: Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen)); r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC : ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ? (PK_WARN | 0x4000) : test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD)); if (r != PK_OK) { if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); switch (r) { case IZ_EF_TRUNC: Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD), ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n")); break; #if (defined(WIN32) && defined(NTSD_EAS)) case PK_WARN: Info(slide, 1, ((char *)slide, LoadFarString(InvalidSecurityEAs))); break; #endif case PK_ERR: Info(slide, 1, ((char *)slide, LoadFarString(InvalidComprDataEAs))); break; case PK_MEM3: case PK_MEM4: Info(slide, 1, ((char *)slide, LoadFarString(NotEnoughMemEAs))); break; case (PK_WARN | 0x4000): Info(slide, 1, ((char *)slide, LoadFarString(UnsuppNTSDVersEAs), (int)ef[EB_HEADSIZE+EB_NTSD_VERSION])); r = PK_WARN; break; default: if ((r & 0xff) != PK_ERR) Info(slide, 1, ((char *)slide, LoadFarString(UnknErrorEAs))); else { ush m = (ush)(r >> 8); if (m == DEFLATED) /* GRR KLUDGE! */ Info(slide, 1, ((char *)slide, LoadFarString(BadCRC_EAs))); else Info(slide, 1, ((char *)slide, LoadFarString(UnknComprMethodEAs), m)); } break; } return r; } break; case EF_PKVMS: if (makelong(ef+EB_HEADSIZE) != crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4), (extent)(ebLen-4))) Info(slide, 1, ((char *)slide, LoadFarString(BadCRC_EAs))); break; case EF_PKW32: case EF_PKUNIX: case EF_ASIUNIX: case EF_IZVMS: case EF_IZUNIX: case EF_VMCMS: case EF_MVS: case EF_SPARK: case EF_TANDEM: case EF_THEOS: case EF_AV: default: break; } ef_len -= (ebLen + EB_HEADSIZE); ef += (ebLen + EB_HEADSIZE); } if (!uO.qflag) Info(slide, 0, ((char *)slide, " OK\n")); return PK_COOL; } /* end function TestExtraField() */ /******************************/ /* Function test_compr_eb() */ /******************************/ #ifdef PROTO static int test_compr_eb( __GPRO__ uch *eb, unsigned eb_size, unsigned compr_offset, int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, uch *eb_ucptr, ulg eb_ucsize)) #else /* !PROTO */ static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata) __GDEF uch *eb; unsigned eb_size; unsigned compr_offset; int (*test_uc_ebdata)(); #endif /* ?PROTO */ { ulg eb_ucsize; uch *eb_ucptr; int r; if (compr_offset < 4) /* field is not compressed: */ return PK_OK; /* do nothing and signal OK */ if ((eb_size < (EB_UCSIZE_P + 4)) || ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L && eb_size <= (compr_offset + EB_CMPRHEADLEN))) return IZ_EF_TRUNC; /* no compressed data! */ if ( #ifdef INT_16BIT (((ulg)(extent)eb_ucsize) != eb_ucsize) || #endif (eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL) return PK_MEM4; r = memextract(__G__ eb_ucptr, eb_ucsize, eb + (EB_HEADSIZE + compr_offset), (ulg)(eb_size - compr_offset)); if (r == PK_OK && test_uc_ebdata != NULL) r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize); free(eb_ucptr); return r; } /* end function test_compr_eb() */ #endif /* !SFX */ /***************************/ /* Function memextract() */ /***************************/ int memextract(__G__ tgt, tgtsize, src, srcsize) /* extract compressed */ __GDEF /* extra field block; */ uch *tgt; /* return PK-type error */ ulg tgtsize; /* level */ ZCONST uch *src; ulg srcsize; { zoff_t old_csize=G.csize; uch *old_inptr=G.inptr; int old_incnt=G.incnt; int r, error=PK_OK; ush method; ulg extra_field_crc; method = makeword(src); extra_field_crc = makelong(src+2); /* compressed extra field exists completely in memory at this location: */ G.inptr = (uch *)src + (2 + 4); /* method and extra_field_crc */ G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4))); G.mem_mode = TRUE; G.outbufptr = tgt; G.outsize = tgtsize; switch (method) { case STORED: memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt); G.outcnt = (ulg)G.csize; /* for CRC calculation */ break; case DEFLATED: #ifdef USE_DEFLATE64 case ENHDEFLATED: #endif G.outcnt = 0L; if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) { if (!uO.tflag) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Inflate))); error = (r == 3)? PK_MEM3 : PK_ERR; } if (G.outcnt == 0L) /* inflate's final FLUSH sets outcnt */ break; break; default: if (uO.tflag) error = PK_ERR | ((int)method << 8); else { Info(slide, 0x401, ((char *)slide, LoadFarString(UnsupportedExtraField), method)); error = PK_ERR; /* GRR: should be passed on up via SetEAs() */ } break; } G.inptr = old_inptr; G.incnt = old_incnt; G.csize = old_csize; G.mem_mode = FALSE; if (!error) { register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt); if (crcval != extra_field_crc) { if (uO.tflag) error = PK_ERR | (DEFLATED << 8); /* kludge for now */ else { Info(slide, 0x401, ((char *)slide, LoadFarString(BadExtraFieldCRC), G.zipfn, crcval, extra_field_crc)); error = PK_ERR; } } } return error; } /* end function memextract() */ /*************************/ /* Function memflush() */ /*************************/ int memflush(__G__ rawbuf, size) __GDEF ZCONST uch *rawbuf; ulg size; { if (size > G.outsize) /* Here, PK_DISK is a bit off-topic, but in the sense of marking "overflow of output space", its use may be tolerated. */ return PK_DISK; /* more data than output buffer can hold */ memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size); G.outbufptr += (unsigned int)size; G.outsize -= size; G.outcnt += size; return 0; } /* end function memflush() */ #if (defined(VMS) || defined(VMS_TEXT_CONV)) /************************************/ /* Function extract_izvms_block() */ /************************************/ /* * Extracts block from p. If resulting length is less than needed, fill * extra space with corresponding bytes from 'init'. * Currently understands 3 formats of block compression: * - Simple storing * - Compression of zero bytes to zero bits * - Deflation (see memextract()) * The IZVMS block data is returned in malloc'd space. */ uch *extract_izvms_block(__G__ ebdata, size, retlen, init, needlen) __GDEF ZCONST uch *ebdata; unsigned size; unsigned *retlen; ZCONST uch *init; unsigned needlen; { uch *ucdata; /* Pointer to block allocated */ int cmptype; unsigned usiz, csiz; cmptype = (makeword(ebdata+EB_IZVMS_FLGS) & EB_IZVMS_BCMASK); csiz = size - EB_IZVMS_HLEN; usiz = (cmptype == EB_IZVMS_BCSTOR ? csiz : makeword(ebdata+EB_IZVMS_UCSIZ)); if (retlen) *retlen = usiz; if ((ucdata = (uch *)malloc(MAX(needlen, usiz))) == NULL) return NULL; if (init && (usiz < needlen)) memcpy((char *)ucdata, (ZCONST char *)init, needlen); switch (cmptype) { case EB_IZVMS_BCSTOR: /* The simplest case */ memcpy(ucdata, ebdata+EB_IZVMS_HLEN, usiz); break; case EB_IZVMS_BC00: decompress_bits(ucdata, usiz, ebdata+EB_IZVMS_HLEN); break; case EB_IZVMS_BCDEFL: memextract(__G__ ucdata, (ulg)usiz, ebdata+EB_IZVMS_HLEN, (ulg)csiz); break; default: free(ucdata); ucdata = NULL; } return ucdata; } /* end of extract_izvms_block */ /********************************/ /* Function decompress_bits() */ /********************************/ /* * Simple uncompression routine. The compression uses bit stream. * Compression scheme: * * if (byte!=0) * putbit(1),putbyte(byte) * else * putbit(0) */ static void decompress_bits(outptr, needlen, bitptr) uch *outptr; /* Pointer into output block */ unsigned needlen; /* Size of uncompressed block */ ZCONST uch *bitptr; /* Pointer into compressed data */ { ulg bitbuf = 0; int bitcnt = 0; #define _FILL { bitbuf |= (*bitptr++) << bitcnt;\ bitcnt += 8; \ } while (needlen--) { if (bitcnt <= 0) _FILL; if (bitbuf & 1) { bitbuf >>= 1; if ((bitcnt -= 1) < 8) _FILL; *outptr++ = (uch)bitbuf; bitcnt -= 8; bitbuf >>= 8; } else { *outptr++ = '\0'; bitcnt -= 1; bitbuf >>= 1; } } } /* end function decompress_bits() */ #endif /* VMS || VMS_TEXT_CONV */ #ifdef SYMLINKS /***********************************/ /* Function set_deferred_symlink() */ /***********************************/ static void set_deferred_symlink(__G__ slnk_entry) __GDEF slinkentry *slnk_entry; { extent ucsize = slnk_entry->targetlen; char *linkfname = slnk_entry->fname; char *linktarget = (char *)malloc(ucsize+1); if (!linktarget) { Info(slide, 0x201, ((char *)slide, LoadFarString(SymLnkWarnNoMem), FnFilter1(linkfname))); return; } linktarget[ucsize] = '\0'; G.outfile = zfopen(linkfname, FOPR); /* open link placeholder for reading */ /* Check that the following conditions are all fulfilled: * a) the placeholder file exists, * b) the placeholder file contains exactly "ucsize" bytes * (read the expected placeholder content length + 1 extra byte, this * should return the expected content length), * c) the placeholder content matches the link target specification as * stored in the symlink control structure. */ if (!G.outfile || fread(linktarget, 1, ucsize+1, G.outfile) != ucsize || strcmp(slnk_entry->target, linktarget)) { Info(slide, 0x201, ((char *)slide, LoadFarString(SymLnkWarnInvalid), FnFilter1(linkfname))); free(linktarget); if (G.outfile) fclose(G.outfile); return; } fclose(G.outfile); /* close "data" file for good... */ unlink(linkfname); /* ...and delete it */ if (QCOND2) Info(slide, 0, ((char *)slide, LoadFarString(SymLnkFinish), FnFilter1(linkfname), FnFilter2(linktarget))); if (symlink(linktarget, linkfname)) /* create the real link */ perror("symlink error"); free(linktarget); #ifdef SET_SYMLINK_ATTRIBS set_symlnk_attribs(__G__ slnk_entry); #endif return; /* can't set time on symlinks */ } /* end function set_deferred_symlink() */ #endif /* SYMLINKS */ /*************************/ /* Function fnfilter() */ /* here instead of in list.c for SFX */ /*************************/ char *fnfilter(raw, space, size) /* convert name to safely printable form */ ZCONST char *raw; uch *space; extent size; { #ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */ ZCONST uch *r=(ZCONST uch *)raw; uch *s=space; uch *slim=NULL; uch *se=NULL; int have_overflow = FALSE; if (size > 0) { slim = space + size #ifdef _MBCS - (MB_CUR_MAX - 1) #endif - 4; } while (*r) { if (size > 0 && s >= slim && se == NULL) { se = s; } #ifdef QDOS if (qlflag & 2) { if (*r == '/' || *r == '.') { if (se != NULL && (s > (space + (size-3)))) { have_overflow = TRUE; break; } ++r; *s++ = '_'; continue; } } else #endif #ifdef HAVE_WORKING_ISPRINT # ifndef UZ_FNFILTER_REPLACECHAR /* A convenient choice for the replacement of unprintable char codes is * the "single char wildcard", as this character is quite unlikely to * appear in filenames by itself. The following default definition * sets the replacement char to a question mark as the most common * "single char wildcard"; this setting should be overridden in the * appropiate system-specific configuration header when needed. */ # define UZ_FNFILTER_REPLACECHAR '?' # endif if (!isprint(*r)) { if (*r < 32) { /* ASCII control codes are escaped as "^{letter}". */ if (se != NULL && (s > (space + (size-4)))) { have_overflow = TRUE; break; } *s++ = '^', *s++ = (uch)(64 + *r++); } else { /* Other unprintable codes are replaced by the * placeholder character. */ if (se != NULL && (s > (space + (size-3)))) { have_overflow = TRUE; break; } *s++ = UZ_FNFILTER_REPLACECHAR; INCSTR(r); } #else /* !HAVE_WORKING_ISPRINT */ if (*r < 32) { /* ASCII control codes are escaped as "^{letter}". */ if (se != NULL && (s > (space + (size-4)))) { have_overflow = TRUE; break; } *s++ = '^', *s++ = (uch)(64 + *r++); #endif /* ?HAVE_WORKING_ISPRINT */ } else { #ifdef _MBCS unsigned i = CLEN(r); if (se != NULL && (s > (space + (size-i-2)))) { have_overflow = TRUE; break; } for (; i > 0; i--) *s++ = *r++; #else if (se != NULL && (s > (space + (size-3)))) { have_overflow = TRUE; break; } *s++ = *r++; #endif } } if (have_overflow) { strcpy((char *)se, "..."); } else { *s = '\0'; } #ifdef WINDLL INTERN_TO_ISO((char *)space, (char *)space); /* translate to ANSI */ #else #if (defined(WIN32) && !defined(_WIN32_WCE)) /* Win9x console always uses OEM character coding, and WinNT console is set to OEM charset by default, too */ INTERN_TO_OEM((char *)space, (char *)space); #endif /* (WIN32 && !_WIN32_WCE) */ #endif /* ?WINDLL */ return (char *)space; #else /* NATIVE: EBCDIC or whatever */ return (char *)raw; #endif } /* end function fnfilter() */ #ifdef SET_DIR_ATTRIB /* must sort saved directories so can set perms from bottom up */ /************************/ /* Function dircomp() */ /************************/ static int Cdecl dircomp(a, b) /* used by qsort(); swiped from Zip */ ZCONST zvoid *a, *b; { /* order is significant: this sorts in reverse order (deepest first) */ return strcmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */ } #endif /* SET_DIR_ATTRIB */ #ifdef USE_BZIP2 /**************************/ /* Function UZbunzip2() */ /**************************/ int UZbunzip2(__G) __GDEF /* decompress a bzipped entry using the libbz2 routines */ { int retval = 0; /* return code: 0 = "no error" */ int err=BZ_OK; int repeated_buf_err; bz_stream bstrm; #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) wsize = G.redirect_size, redirSlide = G.redirect_buffer; else wsize = WSIZE, redirSlide = slide; #endif bstrm.next_out = (char *)redirSlide; bstrm.avail_out = wsize; bstrm.next_in = (char *)G.inptr; bstrm.avail_in = G.incnt; { /* local buffer for efficiency */ /* $TODO Check for BZIP LIB version? */ bstrm.bzalloc = NULL; bstrm.bzfree = NULL; bstrm.opaque = NULL; Trace((stderr, "initializing bzlib()\n")); err = BZ2_bzDecompressInit(&bstrm, 0, 0); if (err == BZ_MEM_ERROR) return 3; else if (err != BZ_OK) Trace((stderr, "oops! (BZ2_bzDecompressInit() err = %d)\n", err)); } #ifdef FUNZIP while (err != BZ_STREAM_END) { #else /* !FUNZIP */ while (G.csize > 0) { Trace((stderr, "first loop: G.csize = %ld\n", G.csize)); #endif /* ?FUNZIP */ while (bstrm.avail_out > 0) { err = BZ2_bzDecompress(&bstrm); if (err == BZ_DATA_ERROR) { retval = 2; goto uzbunzip_cleanup_exit; } else if (err == BZ_MEM_ERROR) { retval = 3; goto uzbunzip_cleanup_exit; } else if (err != BZ_OK && err != BZ_STREAM_END) Trace((stderr, "oops! (bzip(first loop) err = %d)\n", err)); #ifdef FUNZIP if (err == BZ_STREAM_END) /* "END-of-entry-condition" ? */ #else /* !FUNZIP */ if (G.csize <= 0L) /* "END-of-entry-condition" ? */ #endif /* ?FUNZIP */ break; if (bstrm.avail_in == 0) { if (fillinbuf(__G) == 0) { /* no "END-condition" yet, but no more data */ retval = 2; goto uzbunzip_cleanup_exit; } bstrm.next_in = (char *)G.inptr; bstrm.avail_in = G.incnt; } Trace((stderr, " avail_in = %u\n", bstrm.avail_in)); } /* flush slide[] */ if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0) goto uzbunzip_cleanup_exit; Trace((stderr, "inside loop: flushing %ld bytes (ptr diff = %ld)\n", (long)(wsize - bstrm.avail_out), (long)(bstrm.next_out-(char *)redirSlide))); bstrm.next_out = (char *)redirSlide; bstrm.avail_out = wsize; } /* no more input, so loop until we have all output */ Trace((stderr, "beginning final loop: err = %d\n", err)); repeated_buf_err = FALSE; while (err != BZ_STREAM_END) { err = BZ2_bzDecompress(&bstrm); if (err == BZ_DATA_ERROR) { retval = 2; goto uzbunzip_cleanup_exit; } else if (err == BZ_MEM_ERROR) { retval = 3; goto uzbunzip_cleanup_exit; } else if (err != BZ_OK && err != BZ_STREAM_END) { Trace((stderr, "oops! (bzip(final loop) err = %d)\n", err)); DESTROYGLOBALS(); EXIT(PK_MEM3); } /* final flush of slide[] */ if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0) goto uzbunzip_cleanup_exit; Trace((stderr, "final loop: flushing %ld bytes (ptr diff = %ld)\n", (long)(wsize - bstrm.avail_out), (long)(bstrm.next_out-(char *)redirSlide))); bstrm.next_out = (char *)redirSlide; bstrm.avail_out = wsize; } #ifdef LARGE_FILE_SUPPORT Trace((stderr, "total in = %llu, total out = %llu\n", (zusz_t)(bstrm.total_in_lo32) + ((zusz_t)(bstrm.total_in_hi32))<<32, (zusz_t)(bstrm.total_out_lo32) + ((zusz_t)(bstrm.total_out_hi32))<<32)); #else Trace((stderr, "total in = %lu, total out = %lu\n", bstrm.total_in_lo32, bstrm.total_out_lo32)); #endif G.inptr = (uch *)bstrm.next_in; G.incnt = (G.inbuf + INBUFSIZ) - G.inptr; /* reset for other routines */ uzbunzip_cleanup_exit: err = BZ2_bzDecompressEnd(&bstrm); if (err != BZ_OK) Trace((stderr, "oops! (BZ2_bzDecompressEnd() err = %d)\n", err)); return retval; } /* end function UZbunzip2() */ #endif /* USE_BZIP2 */ Carla-2.1/data/windows/unzipfx-carla/fileio.c000066400000000000000000002707121364475620200212210ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- fileio.c This file contains routines for doing direct but relatively generic input/ output, file-related sorts of things, plus some miscellaneous stuff. Most of the stuff has to do with opening, closing, reading and/or writing files. Contains: open_input_file() open_outfile() (not: VMS, AOS/VS, CMSMVS, MACOS, TANDEM) undefer_input() defer_leftover_input() readbuf() readbyte() fillinbuf() seek_zipf() flush() (non-VMS) is_vms_varlen_txt() (non-VMS, VMS_TEXT_CONV only) disk_error() (non-VMS) UzpMessagePrnt() UzpMessageNull() (DLL only) UzpInput() UzpMorePause() UzpPassword() (non-WINDLL) handler() dos_to_unix_time() (non-VMS, non-VM/CMS, non-MVS) check_for_newer() (non-VMS, non-OS/2, non-VM/CMS, non-MVS) do_string() makeword() makelong() makeint64() fzofft() str2iso() (CRYPT && NEED_STR2ISO, only) str2oem() (CRYPT && NEED_STR2OEM, only) memset() (ZMEM only) memcpy() (ZMEM only) zstrnicmp() (NO_STRNICMP only) zstat() (REGULUS only) plastchar() (_MBCS only) uzmbclen() (_MBCS && NEED_UZMBCLEN, only) uzmbschr() (_MBCS && NEED_UZMBSCHR, only) uzmbsrchr() (_MBCS && NEED_UZMBSRCHR, only) fLoadFarString() (SMALL_MEM only) fLoadFarStringSmall() (SMALL_MEM only) fLoadFarStringSmall2() (SMALL_MEM only) zfstrcpy() (SMALL_MEM only) zfstrcmp() (SMALL_MEM && !(SFX || FUNZIP) only) ---------------------------------------------------------------------------*/ #define __FILEIO_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" #ifdef WINDLL # ifdef POCKET_UNZIP # include "wince/intrface.h" # else # include "windll/windll.h" # endif # include #endif #include "crc32.h" #include "crypt.h" #include "ttyio.h" /* setup of codepage conversion for decryption passwords */ #if CRYPT # if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY)) # define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */ # endif # if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY)) # define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */ # endif #endif #include "ebcdic.h" /* definition/initialization of ebcdic[] */ /* Note: Under Windows, the maximum size of the buffer that can be used with any of the *printf calls is 16,384, so win_fprintf was used to feed the fprintf clone no more than 16K chunks at a time. This should be valid for anything up to 64K (and probably beyond, assuming your buffers are that big). */ #ifdef WINDLL # define WriteError(buf,len,strm) \ (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len)) #else /* !WINDLL */ # ifdef USE_FWRITE # define WriteError(buf,len,strm) \ ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len)) # else # define WriteError(buf,len,strm) \ ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len)) # endif #endif /* ?WINDLL */ /* 2005-09-16 SMS. On VMS, when output is redirected to a file, as in a command like "PIPE UNZIP -v > X.OUT", the output file is created with VFC record format, and multiple calls to write() or fwrite() will produce multiple records, even when there's no newline terminator in the buffer. The result is unsightly output with spurious newlines. Using fprintf() instead of write() here, and disabling a fflush(stdout) in UzpMessagePrnt() below, together seem to solve the problem. According to the C RTL manual, "The write and decc$record_write functions always generate at least one record." Also, "[T]he fwrite function always generates at least records." So, "fwrite(buf, len, 1, strm)" is much better ("1" record) than "fwrite(buf, 1, len, strm)" ("len" (1-character) records, _really_ ugly), but neither is better than write(). Similarly, "The fflush function always generates a record if there is unwritten data in the buffer." Apparently fprintf() buffers the stuff somewhere, and puts out a record (only) when it sees a newline. */ #ifdef VMS # define WriteTxtErr(buf,len,strm) \ ((extent)fprintf(strm, "%.*s", len, buf) != (extent)(len)) #else # define WriteTxtErr(buf,len,strm) WriteError(buf,len,strm) #endif #if (defined(USE_DEFLATE64) && defined(__16BIT__)) static int partflush OF((__GPRO__ uch *rawbuf, ulg size, int unshrink)); #endif #ifdef VMS_TEXT_CONV static int is_vms_varlen_txt OF((__GPRO__ uch *ef_buf, unsigned ef_len)); #endif static int disk_error OF((__GPRO)); /****************************/ /* Strings used in fileio.c */ /****************************/ static ZCONST char Far CannotOpenZipfile[] = "error: cannot open zipfile [ %s ]\n %s\n"; #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) #if (!defined(TANDEM)) #if (defined(ATH_BEO_THS_UNX) || defined(DOS_FLX_NLM_OS2_W32)) static ZCONST char Far CannotDeleteOldFile[] = "error: cannot delete old %s\n %s\n"; #ifdef UNIXBACKUP static ZCONST char Far CannotRenameOldFile[] = "error: cannot rename old %s\n %s\n"; static ZCONST char Far BackupSuffix[] = "~"; #endif #endif /* ATH_BEO_THS_UNX || DOS_FLX_NLM_OS2_W32 */ #ifdef NOVELL_BUG_FAILSAFE static ZCONST char Far NovellBug[] = "error: %s: stat() says does not exist, but fopen() found anyway\n"; #endif static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n %s\n"; #endif /* !TANDEM */ #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */ static ZCONST char Far ReadError[] = "error: zipfile read error\n"; static ZCONST char Far FilenameTooLongTrunc[] = "warning: filename too long--truncating.\n"; #ifdef UNICODE_SUPPORT static ZCONST char Far UFilenameTooLongTrunc[] = "warning: Converted unicode filename too long--truncating.\n"; #endif static ZCONST char Far ExtraFieldTooLong[] = "warning: extra field too long (%d). Ignoring...\n"; #ifdef WINDLL static ZCONST char Far DiskFullQuery[] = "%s: write error (disk full?).\n"; #else static ZCONST char Far DiskFullQuery[] = "%s: write error (disk full?). Continue? (y/n/^C) "; static ZCONST char Far ZipfileCorrupt[] = "error: zipfile probably corrupt (%s)\n"; # ifdef SYMLINKS static ZCONST char Far FileIsSymLink[] = "%s exists and is a symbolic link%s.\n"; # endif # ifdef MORE static ZCONST char Far MorePrompt[] = "--More--(%lu)"; # endif static ZCONST char Far QuitPrompt[] = "--- Press `Q' to quit, or any other key to continue ---"; static ZCONST char Far HidePrompt[] = /* "\r \r"; */ "\r \r"; # if CRYPT # ifdef MACOS /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */ static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: "; # else static ZCONST char Far PasswPrompt[] = "[%s] %s password: "; # endif static ZCONST char Far PasswPrompt2[] = "Enter password: "; static ZCONST char Far PasswRetry[] = "password incorrect--reenter: "; # endif /* CRYPT */ #endif /* !WINDLL */ /******************************/ /* Function open_input_file() */ /******************************/ int open_input_file(__G) /* return 1 if open failed */ __GDEF { /* * open the zipfile for reading and in BINARY mode to prevent cr/lf * translation, which would corrupt the bitstreams */ #ifdef VMS G.zipfd = open(G.zipfn, O_RDONLY, 0, OPNZIP_RMS_ARGS); #else /* !VMS */ #ifdef MACOS G.zipfd = open(G.zipfn, 0); #else /* !MACOS */ #ifdef CMS_MVS G.zipfd = vmmvs_open_infile(__G); #else /* !CMS_MVS */ #ifdef USE_STRM_INPUT G.zipfd = fopen(G.zipfn, FOPR); #else /* !USE_STRM_INPUT */ G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY); #endif /* ?USE_STRM_INPUT */ #endif /* ?CMS_MVS */ #endif /* ?MACOS */ #endif /* ?VMS */ #ifdef USE_STRM_INPUT if (G.zipfd == NULL) #else /* if (G.zipfd < 0) */ /* no good for Windows CE port */ if (G.zipfd == -1) #endif { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile), G.zipfn, strerror(errno))); return 1; } return 0; } /* end function open_input_file() */ #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) #if (!defined(TANDEM)) /***************************/ /* Function open_outfile() */ /***************************/ int open_outfile(__G) /* return 1 if fail */ __GDEF { #ifdef DLL if (G.redirect_data) return (redirect_outfile(__G) == FALSE); #endif #ifdef QDOS QFilename(__G__ G.filename); #endif #if (defined(DOS_FLX_NLM_OS2_W32) || defined(ATH_BEO_THS_UNX)) #ifdef BORLAND_STAT_BUG /* Borland 5.0's stat() barfs if the filename has no extension and the * file doesn't exist. */ if (access(G.filename, 0) == -1) { FILE *tmp = fopen(G.filename, "wb+"); /* file doesn't exist, so create a dummy file to keep stat() from * failing (will be over-written anyway) */ fputc('0', tmp); /* just to have something in the file */ fclose(tmp); } #endif /* BORLAND_STAT_BUG */ #ifdef SYMLINKS if (SSTAT(G.filename, &G.statbuf) == 0 || lstat(G.filename, &G.statbuf) == 0) #else if (SSTAT(G.filename, &G.statbuf) == 0) #endif /* ?SYMLINKS */ { Trace((stderr, "open_outfile: stat(%s) returns 0: file exists\n", FnFilter1(G.filename))); #ifdef UNIXBACKUP if (uO.B_flag) { /* do backup */ char *tname; z_stat tmpstat; int blen, flen, tlen; blen = strlen(BackupSuffix); flen = strlen(G.filename); tlen = flen + blen + 6; /* includes space for 5 digits */ if (tlen >= FILNAMSIZ) { /* in case name is too long, truncate */ tname = (char *)malloc(FILNAMSIZ); if (tname == NULL) return 1; /* in case we run out of space */ tlen = FILNAMSIZ - 1 - blen; strcpy(tname, G.filename); /* make backup name */ tname[tlen] = '\0'; if (flen > tlen) flen = tlen; tlen = FILNAMSIZ; } else { tname = (char *)malloc(tlen); if (tname == NULL) return 1; /* in case we run out of space */ strcpy(tname, G.filename); /* make backup name */ } strcpy(tname+flen, BackupSuffix); if (IS_OVERWRT_ALL) { /* If there is a previous backup file, delete it, * otherwise the following rename operation may fail. */ if (SSTAT(tname, &tmpstat) == 0) unlink(tname); } else { /* Check if backupname exists, and, if it's true, try * appending numbers of up to 5 digits (or the maximum * "unsigned int" number on 16-bit systems) to the * BackupSuffix, until an unused name is found. */ unsigned maxtail, i; char *numtail = tname + flen + blen; /* take account of the "unsigned" limit on 16-bit systems: */ maxtail = ( ((~0) >= 99999L) ? 99999 : (~0) ); switch (tlen - flen - blen - 1) { case 4: maxtail = 9999; break; case 3: maxtail = 999; break; case 2: maxtail = 99; break; case 1: maxtail = 9; break; case 0: maxtail = 0; break; } /* while filename exists */ for (i = 0; (i < maxtail) && (SSTAT(tname, &tmpstat) == 0);) sprintf(numtail,"%u", ++i); } if (rename(G.filename, tname) != 0) { /* move file */ Info(slide, 0x401, ((char *)slide, LoadFarString(CannotRenameOldFile), FnFilter1(G.filename), strerror(errno))); free(tname); return 1; } Trace((stderr, "open_outfile: %s now renamed into %s\n", FnFilter1(G.filename), FnFilter2(tname))); free(tname); } else #endif /* UNIXBACKUP */ { #ifdef DOS_FLX_OS2_W32 if (!(G.statbuf.st_mode & S_IWRITE)) { Trace((stderr, "open_outfile: existing file %s is read-only\n", FnFilter1(G.filename))); chmod(G.filename, S_IREAD | S_IWRITE); Trace((stderr, "open_outfile: %s now writable\n", FnFilter1(G.filename))); } #endif /* DOS_FLX_OS2_W32 */ #ifdef NLM /* Give the file read/write permission (non-POSIX shortcut) */ chmod(G.filename, 0); #endif /* NLM */ if (unlink(G.filename) != 0) { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename), strerror(errno))); return 1; } Trace((stderr, "open_outfile: %s now deleted\n", FnFilter1(G.filename))); } } #endif /* DOS_FLX_NLM_OS2_W32 || ATH_BEO_THS_UNX */ #ifdef RISCOS if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) { Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), FnFilter1(G.filename), strerror(errno))); return 1; } #endif /* RISCOS */ #ifdef TOPS20 char *tfilnam; if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL) return 1; strcpy(tfilnam, G.filename); upper(tfilnam); enquote(tfilnam); if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) { Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), tfilnam, strerror(errno))); free(tfilnam); return 1; } free(tfilnam); #else /* !TOPS20 */ #ifdef MTS if (uO.aflag) G.outfile = zfopen(G.filename, FOPWT); else G.outfile = zfopen(G.filename, FOPW); if (G.outfile == (FILE *)NULL) { Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), FnFilter1(G.filename), strerror(errno))); return 1; } #else /* !MTS */ #ifdef DEBUG Info(slide, 1, ((char *)slide, "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G.filename))); if ((G.outfile = zfopen(G.filename, FOPR)) == (FILE *)NULL) Info(slide, 1, ((char *)slide, "open_outfile: fopen(%s) for reading failed: does not exist\n", FnFilter1(G.filename))); else { Info(slide, 1, ((char *)slide, "open_outfile: fopen(%s) for reading succeeded: file exists\n", FnFilter1(G.filename))); fclose(G.outfile); } #endif /* DEBUG */ #ifdef NOVELL_BUG_FAILSAFE if (G.dne && ((G.outfile = zfopen(G.filename, FOPR)) != (FILE *)NULL)) { Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug), FnFilter1(G.filename))); fclose(G.outfile); return 1; /* with "./" fix in checkdir(), should never reach here */ } #endif /* NOVELL_BUG_FAILSAFE */ Trace((stderr, "open_outfile: doing fopen(%s) for writing\n", FnFilter1(G.filename))); { #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM) mode_t umask_sav = umask(0077); #endif #if defined(SYMLINKS) || defined(QLZIP) /* These features require the ability to re-read extracted data from the output files. Output files are created with Read&Write access. */ G.outfile = zfopen(G.filename, FOPWR); #else G.outfile = zfopen(G.filename, FOPW); #endif #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM) umask(umask_sav); #endif } if (G.outfile == (FILE *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile), FnFilter1(G.filename), strerror(errno))); return 1; } Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n", FnFilter1(G.filename))); #endif /* !MTS */ #endif /* !TOPS20 */ #ifdef USE_FWRITE #ifdef DOS_NLM_OS2_W32 /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */ setbuf(G.outfile, (char *)NULL); /* make output unbuffered */ #else /* !DOS_NLM_OS2_W32 */ #ifndef RISCOS #ifdef _IOFBF /* make output fully buffered (works just about like write()) */ setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE); #else setbuf(G.outfile, (char *)slide); #endif #endif /* !RISCOS */ #endif /* ?DOS_NLM_OS2_W32 */ #endif /* USE_FWRITE */ #ifdef OS2_W32 /* preallocate the final file size to prevent file fragmentation */ SetFileSize(G.outfile, G.lrec.ucsize); #endif return 0; } /* end function open_outfile() */ #endif /* !TANDEM */ #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */ /* * These functions allow NEXTBYTE to function without needing two bounds * checks. Call defer_leftover_input() if you ever have filled G.inbuf * by some means other than readbyte(), and you then want to start using * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call * undefer_input(). For example, extract_or_test_member brackets its * central section that does the decompression with these two functions. * If you need to check the number of bytes remaining in the current * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize. */ /****************************/ /* function undefer_input() */ /****************************/ void undefer_input(__G) __GDEF { if (G.incnt > 0) G.csize += G.incnt; if (G.incnt_leftover > 0) { /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int: * This condition was checked when G.incnt_leftover was set > 0 in * defer_leftover_input(), and it is NOT allowed to touch G.csize * before calling undefer_input() when (G.incnt_leftover > 0) * (single exception: see read_byte()'s "G.csize <= 0" handling) !! */ G.incnt = G.incnt_leftover + (int)G.csize; G.inptr = G.inptr_leftover - (int)G.csize; G.incnt_leftover = 0; } else if (G.incnt < 0) G.incnt = 0; } /* end function undefer_input() */ /***********************************/ /* function defer_leftover_input() */ /***********************************/ void defer_leftover_input(__G) __GDEF { if ((zoff_t)G.incnt > G.csize) { /* (G.csize < MAXINT), we can safely cast it to int !! */ if (G.csize < 0L) G.csize = 0L; G.inptr_leftover = G.inptr + (int)G.csize; G.incnt_leftover = G.incnt - (int)G.csize; G.incnt = (int)G.csize; } else G.incnt_leftover = 0; G.csize -= G.incnt; } /* end function defer_leftover_input() */ /**********************/ /* Function readbuf() */ /**********************/ unsigned readbuf(__G__ buf, size) /* return number of bytes read into buf */ __GDEF char *buf; register unsigned size; { register unsigned count; unsigned n; n = size; while (size) { if (G.incnt <= 0) { if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) return (n-size); else if (G.incnt < 0) { /* another hack, but no real harm copying same thing twice */ (*G.message)((zvoid *)&G, (uch *)LoadFarString(ReadError), /* CANNOT use slide */ (ulg)strlen(LoadFarString(ReadError)), 0x401); return 0; /* discarding some data; better than lock-up */ } /* buffer ALWAYS starts on a block boundary: */ G.cur_zipfile_bufstart += INBUFSIZ; G.inptr = G.inbuf; } count = MIN(size, (unsigned)G.incnt); memcpy(buf, G.inptr, count); buf += count; G.inptr += count; G.incnt -= count; size -= count; } return n; } /* end function readbuf() */ /***********************/ /* Function readbyte() */ /***********************/ int readbyte(__G) /* refill inbuf and return a byte if available, else EOF */ __GDEF { if (G.mem_mode) return EOF; if (G.csize <= 0) { G.csize--; /* for tests done after exploding */ G.incnt = 0; return EOF; } if (G.incnt <= 0) { if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) { return EOF; } else if (G.incnt < 0) { /* "fail" (abort, retry, ...) returns this */ /* another hack, but no real harm copying same thing twice */ (*G.message)((zvoid *)&G, (uch *)LoadFarString(ReadError), (ulg)strlen(LoadFarString(ReadError)), 0x401); echon(); #ifdef WINDLL longjmp(dll_error_return, 1); #else DESTROYGLOBALS(); EXIT(PK_BADERR); /* totally bailing; better than lock-up */ #endif } G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */ G.inptr = G.inbuf; defer_leftover_input(__G); /* decrements G.csize */ } #if CRYPT if (G.pInfo->encrypted) { uch *p; int n; /* This was previously set to decrypt one byte beyond G.csize, when * incnt reached that far. GRR said, "but it's required: why?" This * was a bug in fillinbuf() -- was it also a bug here? */ for (n = G.incnt, p = G.inptr; n--; p++) zdecode(*p); } #endif /* CRYPT */ --G.incnt; return *G.inptr++; } /* end function readbyte() */ #if defined(USE_ZLIB) || defined(USE_BZIP2) /************************/ /* Function fillinbuf() */ /************************/ int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */ __GDEF { if (G.mem_mode || (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) return 0; G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on a block boundary */ G.inptr = G.inbuf; defer_leftover_input(__G); /* decrements G.csize */ #if CRYPT if (G.pInfo->encrypted) { uch *p; int n; for (n = G.incnt, p = G.inptr; n--; p++) zdecode(*p); } #endif /* CRYPT */ return G.incnt; } /* end function fillinbuf() */ #endif /* USE_ZLIB || USE_BZIP2 */ /************************/ /* Function seek_zipf() */ /************************/ int seek_zipf(__G__ abs_offset) __GDEF zoff_t abs_offset; { /* * Seek to the block boundary of the block which includes abs_offset, * then read block into input buffer and set pointers appropriately. * If block is already in the buffer, just set the pointers. This function * is used by do_seekable (process.c), extract_or_test_entrylist (extract.c) * and do_string (fileio.c). Also, a slightly modified version is embedded * within extract_or_test_entrylist (extract.c). readbyte() and readbuf() * (fileio.c) are compatible. NOTE THAT abs_offset is intended to be the * "proper offset" (i.e., if there were no extra bytes prepended); * cur_zipfile_bufstart contains the corrected offset. * * Since seek_zipf() is never used during decompression, it is safe to * use the slide[] buffer for the error message. * * returns PK error codes: * PK_BADERR if effective offset in zipfile is negative * PK_EOF if seeking past end of zipfile * PK_OK when seek was successful */ zoff_t request = abs_offset + G.extra_bytes; zoff_t inbuf_offset = request % INBUFSIZ; zoff_t bufstart = request - inbuf_offset; if (request < 0) { Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg), G.zipfn, LoadFarString(ReportMsg))); return(PK_BADERR); } else if (bufstart != G.cur_zipfile_bufstart) { Trace((stderr, "fpos_zip: abs_offset = %s, G.extra_bytes = %s\n", FmZofft(abs_offset, NULL, NULL), FmZofft(G.extra_bytes, NULL, NULL))); #ifdef USE_STRM_INPUT zfseeko(G.zipfd, bufstart, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, bufstart, SEEK_SET); #endif /* ?USE_STRM_INPUT */ Trace((stderr, " request = %s, (abs+extra) = %s, inbuf_offset = %s\n", FmZofft(request, NULL, NULL), FmZofft((abs_offset+G.extra_bytes), NULL, NULL), FmZofft(inbuf_offset, NULL, NULL))); Trace((stderr, " bufstart = %s, cur_zipfile_bufstart = %s\n", FmZofft(bufstart, NULL, NULL), FmZofft(G.cur_zipfile_bufstart, NULL, NULL))); if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) return(PK_EOF); G.incnt -= (int)inbuf_offset; G.inptr = G.inbuf + (int)inbuf_offset; } else { G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset; G.inptr = G.inbuf + (int)inbuf_offset; } return(PK_OK); } /* end function seek_zipf() */ #ifndef VMS /* for VMS use code in vms.c */ /********************/ /* Function flush() */ /* returns PK error codes: */ /********************/ /* if tflag => always 0; PK_DISK if write error */ int flush(__G__ rawbuf, size, unshrink) __GDEF uch *rawbuf; ulg size; int unshrink; #if (defined(USE_DEFLATE64) && defined(__16BIT__)) { int ret; /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions * cannot handle writes of 64k blocks at once. For these systems, the * blocks to flush are split into pieces of 32k or less. */ while (size > 0x8000L) { ret = partflush(__G__ rawbuf, 0x8000L, unshrink); if (ret != PK_OK) return ret; size -= 0x8000L; rawbuf += (extent)0x8000; } return partflush(__G__ rawbuf, size, unshrink); } /* end function flush() */ /************************/ /* Function partflush() */ /* returns PK error codes: */ /************************/ /* if tflag => always 0; PK_DISK if write error */ static int partflush(__G__ rawbuf, size, unshrink) __GDEF uch *rawbuf; /* cannot be ZCONST, gets passed to (*G.message)() */ ulg size; int unshrink; #endif /* USE_DEFLATE64 && __16BIT__ */ { register uch *p; register uch *q; uch *transbuf; #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) ulg transbufsiz; #endif /* static int didCRlast = FALSE; moved to globals.h */ /*--------------------------------------------------------------------------- Compute the CRC first; if testing or if disk is full, that's it. ---------------------------------------------------------------------------*/ G.crc32val = crc32(G.crc32val, rawbuf, (extent)size); #ifdef DLL if ((G.statreportcb != NULL) && (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL)) return IZ_CTRLC; /* cancel operation by user request */ #endif if (uO.tflag || size == 0L) /* testing or nothing to write: all done */ return PK_OK; if (G.disk_full) return PK_DISK; /* disk already full: ignore rest of file */ /*--------------------------------------------------------------------------- Write the bytes rawbuf[0..size-1] to the output device, first converting end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT defined, outbuf is assumed to be at least as large as rawbuf and is not necessarily checked for overflow. ---------------------------------------------------------------------------*/ if (!G.pInfo->textmode) { /* write raw binary data */ /* GRR: note that for standard MS-DOS compilers, size argument to * fwrite() can never be more than 65534, so WriteError macro will * have to be rewritten if size can ever be that large. For now, * never more than 32K. Also note that write() returns an int, which * doesn't necessarily limit size to 32767 bytes if write() is used * on 16-bit systems but does make it more of a pain; however, because * at least MSC 5.1 has a lousy implementation of fwrite() (as does * DEC Ultrix cc), write() is used anyway. */ #ifdef DLL if (G.redirect_data) { #ifdef NO_SLIDE_REDIR if (writeToMemory(__G__ rawbuf, (extent)size)) return PK_ERR; #else writeToMemory(__G__ rawbuf, (extent)size); #endif } else #endif if (!uO.cflag && WriteError(rawbuf, size, G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0)) return PK_OK; } else { /* textmode: aflag is true */ if (unshrink) { /* rawbuf = outbuf */ transbuf = G.outbuf2; #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) transbufsiz = TRANSBUFSIZ; #endif } else { /* rawbuf = slide */ transbuf = G.outbuf; #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) transbufsiz = OUTBUFSIZ; Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", (unsigned)OUTBUFSIZ)); #endif } if (G.newfile) { #ifdef VMS_TEXT_CONV if (G.pInfo->hostnum == VMS_ && G.extra_field && is_vms_varlen_txt(__G__ G.extra_field, G.lrec.extra_field_length)) G.VMS_line_state = 0; /* 0: ready to read line length */ else G.VMS_line_state = -1; /* -1: don't treat as VMS text */ #endif G.didCRlast = FALSE; /* no previous buffers written */ G.newfile = FALSE; } #ifdef VMS_TEXT_CONV if (G.VMS_line_state >= 0) { p = rawbuf; q = transbuf; while ((extent)(p-rawbuf) < (extent)size) { switch (G.VMS_line_state) { /* 0: ready to read line length */ case 0: G.VMS_line_length = 0; if ((extent)(p-rawbuf) == (extent)size-1) { /* last char */ G.VMS_line_length = (unsigned)(*p++); G.VMS_line_state = 1; } else { G.VMS_line_length = makeword(p); p += 2; G.VMS_line_state = 2; } G.VMS_line_pad = ((G.VMS_line_length & 1) != 0); /* odd */ break; /* 1: read one byte of length, need second */ case 1: G.VMS_line_length += ((unsigned)(*p++) << 8); G.VMS_line_state = 2; break; /* 2: ready to read VMS_line_length chars */ case 2: { extent remaining = (extent)size+(rawbuf-p); extent outroom; if (G.VMS_line_length < remaining) { remaining = G.VMS_line_length; G.VMS_line_state = 3; } outroom = transbuf+(extent)transbufsiz-q; if (remaining >= outroom) { remaining -= outroom; for (;outroom > 0; p++, outroom--) *q++ = native(*p); #ifdef DLL if (G.redirect_data) { if (writeToMemory(__G__ transbuf, (extent)(q-transbuf))) return PK_ERR; } else #endif if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf), G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)(q-transbuf), 0)) return PK_OK; q = transbuf; /* fall through to normal case */ } G.VMS_line_length -= remaining; for (;remaining > 0; p++, remaining--) *q++ = native(*p); } break; /* 3: ready to PutNativeEOL */ case 3: if (q > transbuf+(extent)transbufsiz-lenEOL) { #ifdef DLL if (G.redirect_data) { if (writeToMemory(__G__ transbuf, (extent)(q-transbuf))) return PK_ERR; } else #endif if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf), G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)(q-transbuf), 0)) return PK_OK; q = transbuf; } PutNativeEOL G.VMS_line_state = G.VMS_line_pad ? 4 : 0; break; /* 4: ready to read pad byte */ case 4: ++p; G.VMS_line_state = 0; break; } } /* end while */ } else #endif /* VMS_TEXT_CONV */ /*----------------------------------------------------------------------- Algorithm: CR/LF => native; lone CR => native; lone LF => native. This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e., stream-oriented files, not record-oriented). -----------------------------------------------------------------------*/ /* else not VMS text */ { p = rawbuf; if (*p == LF && G.didCRlast) ++p; G.didCRlast = FALSE; for (q = transbuf; (extent)(p-rawbuf) < (extent)size; ++p) { if (*p == CR) { /* lone CR or CR/LF: treat as EOL */ PutNativeEOL if ((extent)(p-rawbuf) == (extent)size-1) /* last char in buffer */ G.didCRlast = TRUE; else if (p[1] == LF) /* get rid of accompanying LF */ ++p; } else if (*p == LF) /* lone LF */ PutNativeEOL else #ifndef DOS_FLX_OS2_W32 if (*p != CTRLZ) /* lose all ^Z's */ #endif *q++ = native(*p); #if (defined(SMALL_MEM) || defined(MED_MEM)) # if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */ if (!unshrink) # endif /* check for danger of buffer overflow and flush */ if (q > transbuf+(extent)transbufsiz-lenEOL) { Trace((stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n", (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size)); if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf), G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)(q-transbuf), 0)) return PK_OK; q = transbuf; continue; } #endif /* SMALL_MEM || MED_MEM */ } } /*----------------------------------------------------------------------- Done translating: write whatever we've got to file (or screen). -----------------------------------------------------------------------*/ Trace((stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n", (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size)); if (q > transbuf) { #ifdef DLL if (G.redirect_data) { if (writeToMemory(__G__ transbuf, (extent)(q-transbuf))) return PK_ERR; } else #endif if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf), G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)(q-transbuf), 0)) return PK_OK; } } return PK_OK; } /* end function flush() [resp. partflush() for 16-bit Deflate64 support] */ #ifdef VMS_TEXT_CONV /********************************/ /* Function is_vms_varlen_txt() */ /********************************/ static int is_vms_varlen_txt(__G__ ef_buf, ef_len) __GDEF uch *ef_buf; /* buffer containing extra field */ unsigned ef_len; /* total length of extra field */ { unsigned eb_id; unsigned eb_len; uch *eb_data; unsigned eb_datlen; #define VMSREC_C_UNDEF 0 #define VMSREC_C_VAR 2 uch vms_rectype = VMSREC_C_UNDEF; /* uch vms_fileorg = 0; */ /* currently, fileorg is not used... */ #define VMSPK_ITEMID 0 #define VMSPK_ITEMLEN 2 #define VMSPK_ITEMHEADSZ 4 #define VMSATR_C_RECATTR 4 #define VMS_FABSIG 0x42414656 /* "VFAB" */ /* offsets of interesting fields in VMS fabdef structure */ #define VMSFAB_B_RFM 31 /* record format byte */ #define VMSFAB_B_ORG 29 /* file organization byte */ if (ef_len == 0 || ef_buf == NULL) return FALSE; while (ef_len >= EB_HEADSIZE) { eb_id = makeword(EB_ID + ef_buf); eb_len = makeword(EB_LEN + ef_buf); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ Trace((stderr, "is_vms_varlen_txt: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } switch (eb_id) { case EF_PKVMS: /* The PKVMS e.f. raw data part consists of: * a) 4 bytes CRC checksum * b) list of uncompressed variable-length data items * Each data item is introduced by a fixed header * - 2 bytes data type ID * - 2 bytes of data * - bytes of actual attribute data */ /* get pointer to start of data and its total length */ eb_data = ef_buf+(EB_HEADSIZE+4); eb_datlen = eb_len-4; /* test the CRC checksum */ if (makelong(ef_buf+EB_HEADSIZE) != crc32(CRCVAL_INITIAL, eb_data, (extent)eb_datlen)) { Info(slide, 1, ((char *)slide, "[Warning: CRC error, discarding PKWARE extra field]\n")); /* skip over the data analysis code */ break; } /* scan through the attribute data items */ while (eb_datlen > 4) { unsigned fldsize = makeword(&eb_data[VMSPK_ITEMLEN]); /* check the item type word */ switch (makeword(&eb_data[VMSPK_ITEMID])) { case VMSATR_C_RECATTR: /* we have found the (currently only) interesting * data item */ if (fldsize >= 1) { vms_rectype = eb_data[VMSPK_ITEMHEADSZ] & 15; /* vms_fileorg = eb_data[VMSPK_ITEMHEADSZ] >> 4; */ } break; default: break; } /* skip to next data item */ eb_datlen -= fldsize + VMSPK_ITEMHEADSZ; eb_data += fldsize + VMSPK_ITEMHEADSZ; } break; case EF_IZVMS: if (makelong(ef_buf+EB_HEADSIZE) == VMS_FABSIG) { if ((eb_data = extract_izvms_block(__G__ ef_buf+EB_HEADSIZE, eb_len, &eb_datlen, NULL, 0)) != NULL) { if (eb_datlen >= VMSFAB_B_RFM+1) { vms_rectype = eb_data[VMSFAB_B_RFM] & 15; /* vms_fileorg = eb_data[VMSFAB_B_ORG] >> 4; */ } free(eb_data); } } break; default: break; } /* Skip this extra field block */ ef_buf += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return (vms_rectype == VMSREC_C_VAR); } /* end function is_vms_varlen_txtfile() */ #endif /* VMS_TEXT_CONV */ /*************************/ /* Function disk_error() */ /*************************/ static int disk_error(__G) __GDEF { /* OK to use slide[] here because this file is finished regardless */ Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery), FnFilter1(G.filename))); #ifndef WINDLL fgets(G.answerbuf, sizeof(G.answerbuf), stdin); if (*G.answerbuf == 'y') /* stop writing to this file */ G.disk_full = 1; /* (outfile bad?), but new OK */ else #endif G.disk_full = 2; /* no: exit program */ return PK_DISK; } /* end function disk_error() */ #endif /* !VMS */ /*****************************/ /* Function UzpMessagePrnt() */ /*****************************/ int UZ_EXP UzpMessagePrnt(pG, buf, size, flag) zvoid *pG; /* globals struct: always passed */ uch *buf; /* preformatted string to be printed */ ulg size; /* length of string (may include nulls) */ int flag; /* flag bits */ { /* IMPORTANT NOTE: * The name of the first parameter of UzpMessagePrnt(), which passes * the "Uz_Globs" address, >>> MUST <<< be identical to the string * expansion of the __G__ macro in the REENTRANT case (see globals.h). * This name identity is mandatory for the LoadFarString() macro * (in the SMALL_MEM case) !!! */ int error; uch *q=buf, *endbuf=buf+(unsigned)size; #ifdef MORE uch *p=buf; #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) int islinefeed = FALSE; #endif #endif FILE *outfp; /*--------------------------------------------------------------------------- These tests are here to allow fine-tuning of UnZip's output messages, but none of them will do anything without setting the appropriate bit in the flag argument of every Info() statement which is to be turned *off*. That is, all messages are currently turned on for all ports. To turn off *all* messages, use the UzpMessageNull() function instead of this one. ---------------------------------------------------------------------------*/ #if (defined(OS2) && defined(DLL)) if (MSG_NO_DLL2(flag)) /* if OS/2 DLL bit is set, do NOT print this msg */ return 0; #endif #ifdef WINDLL if (MSG_NO_WDLL(flag)) return 0; #endif #ifdef WINDLL if (MSG_NO_WGUI(flag)) return 0; #endif /* #ifdef ACORN_GUI if (MSG_NO_AGUI(flag)) return 0; #endif */ #ifdef DLL /* don't display message if data is redirected */ if (((Uz_Globs *)pG)->redirect_data && !((Uz_Globs *)pG)->redirect_text) return 0; #endif if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag) outfp = (FILE *)stderr; else outfp = (FILE *)stdout; #ifdef QUERY_TRNEWLN /* some systems require termination of query prompts with '\n' to force * immediate display */ if (MSG_MNEWLN(flag)) { /* assumes writable buffer (e.g., slide[]) */ *endbuf++ = '\n'; /* with room for one more char at end of buf */ ++size; /* (safe assumption: only used for four */ } /* short queries in extract.c and fileio.c) */ #endif if (MSG_TNEWLN(flag)) { /* again assumes writable buffer: fragile... */ if ((!size && !((Uz_Globs *)pG)->sol) || (size && (endbuf[-1] != '\n'))) { *endbuf++ = '\n'; ++size; } } #ifdef MORE # ifdef SCREENSIZE /* room for --More-- and one line of overlap: */ # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) SCREENSIZE(&((Uz_Globs *)pG)->height, &((Uz_Globs *)pG)->width); # else SCREENSIZE(&((Uz_Globs *)pG)->height, (int *)NULL); # endif ((Uz_Globs *)pG)->height -= 2; # else /* room for --More-- and one line of overlap: */ ((Uz_Globs *)pG)->height = SCREENLINES - 2; # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) ((Uz_Globs *)pG)->width = SCREENWIDTH; # endif # endif #endif /* MORE */ if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) { /* not at start of line: want newline */ #ifdef OS2DLL if (!((Uz_Globs *)pG)->redirect_text) { #endif putc('\n', outfp); fflush(outfp); #ifdef MORE if (((Uz_Globs *)pG)->M_flag) { #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) ((Uz_Globs *)pG)->chars = 0; #endif ++((Uz_Globs *)pG)->numlines; ++((Uz_Globs *)pG)->lines; if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height) (*((Uz_Globs *)pG)->mpause)((zvoid *)pG, LoadFarString(MorePrompt), 1); } #endif /* MORE */ if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && !isatty(1) && isatty(2)) { /* error output from testing redirected: also send to stderr */ putc('\n', stderr); fflush(stderr); } #ifdef OS2DLL } else REDIRECTC('\n'); #endif ((Uz_Globs *)pG)->sol = TRUE; } /* put zipfile name, filename and/or error/warning keywords here */ #ifdef MORE if (((Uz_Globs *)pG)->M_flag #ifdef OS2DLL && !((Uz_Globs *)pG)->redirect_text #endif ) { while (p < endbuf) { if (*p == '\n') { #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) islinefeed = TRUE; } else if (SCREENLWRAP) { if (*p == '\r') { ((Uz_Globs *)pG)->chars = 0; } else { # ifdef TABSIZE if (*p == '\t') ((Uz_Globs *)pG)->chars += (TABSIZE - (((Uz_Globs *)pG)->chars % TABSIZE)); else # endif ++((Uz_Globs *)pG)->chars; if (((Uz_Globs *)pG)->chars >= ((Uz_Globs *)pG)->width) islinefeed = TRUE; } } if (islinefeed) { islinefeed = FALSE; ((Uz_Globs *)pG)->chars = 0; #endif /* (SCREENWIDTH && SCREEN_LWRAP) */ ++((Uz_Globs *)pG)->numlines; ++((Uz_Globs *)pG)->lines; if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height) { if ((error = WriteTxtErr(q, p-q+1, outfp)) != 0) return error; fflush(outfp); ((Uz_Globs *)pG)->sol = TRUE; q = p + 1; (*((Uz_Globs *)pG)->mpause)((zvoid *)pG, LoadFarString(MorePrompt), 1); } } INCSTR(p); } /* end while */ size = (ulg)(p - q); /* remaining text */ } #endif /* MORE */ if (size) { #ifdef OS2DLL if (!((Uz_Globs *)pG)->redirect_text) { #endif if ((error = WriteTxtErr(q, size, outfp)) != 0) return error; #ifndef VMS /* 2005-09-16 SMS. See note at "WriteTxtErr()", above. */ fflush(outfp); #endif if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && !isatty(1) && isatty(2)) { /* error output from testing redirected: also send to stderr */ if ((error = WriteTxtErr(q, size, stderr)) != 0) return error; fflush(stderr); } #ifdef OS2DLL } else { /* GRR: this is ugly: hide with macro */ if ((error = REDIRECTPRINT(q, size)) != 0) return error; } #endif /* OS2DLL */ ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n'); } return 0; } /* end function UzpMessagePrnt() */ #ifdef DLL /*****************************/ /* Function UzpMessageNull() */ /* convenience routine for no output at all */ /*****************************/ int UZ_EXP UzpMessageNull(pG, buf, size, flag) zvoid *pG; /* globals struct: always passed */ uch *buf; /* preformatted string to be printed */ ulg size; /* length of string (may include nulls) */ int flag; /* flag bits */ { return 0; } /* end function UzpMessageNull() */ #endif /* DLL */ /***********************/ /* Function UzpInput() */ /* GRR: this is a placeholder for now */ /***********************/ int UZ_EXP UzpInput(pG, buf, size, flag) zvoid *pG; /* globals struct: always passed */ uch *buf; /* preformatted string to be printed */ int *size; /* (address of) size of buf and of returned string */ int flag; /* flag bits (bit 0: no echo) */ { /* tell picky compilers to shut up about "unused variable" warnings */ pG = pG; buf = buf; flag = flag; *size = 0; return 0; } /* end function UzpInput() */ #if (!defined(WINDLL) && !defined(MACOS)) /***************************/ /* Function UzpMorePause() */ /***************************/ void UZ_EXP UzpMorePause(pG, prompt, flag) zvoid *pG; /* globals struct: always passed */ ZCONST char *prompt; /* "--More--" prompt */ int flag; /* 0 = any char OK; 1 = accept only '\n', ' ', q */ { uch c; /*--------------------------------------------------------------------------- Print a prompt and wait for the user to press a key, then erase prompt if possible. ---------------------------------------------------------------------------*/ if (!((Uz_Globs *)pG)->sol) fprintf(stderr, "\n"); /* numlines may or may not be used: */ fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines); fflush(stderr); if (flag & 1) { do { c = (uch)FGETCH(0); } while ( #ifdef THEOS c != 17 && /* standard QUIT key */ #endif c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q'); } else c = (uch)FGETCH(0); /* newline was not echoed, so cover up prompt line */ fprintf(stderr, LoadFarString(HidePrompt)); fflush(stderr); if ( #ifdef THEOS (c == 17) || /* standard QUIT key */ #endif (ToLower(c) == 'q')) { DESTROYGLOBALS(); EXIT(PK_COOL); } ((Uz_Globs *)pG)->sol = TRUE; #ifdef MORE /* space for another screen, enter for another line. */ if ((flag & 1) && c == ' ') ((Uz_Globs *)pG)->lines = 0; #endif /* MORE */ } /* end function UzpMorePause() */ #endif /* !WINDLL && !MACOS */ #ifndef WINDLL /**************************/ /* Function UzpPassword() */ /**************************/ int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn) zvoid *pG; /* pointer to UnZip's internal global vars */ int *rcnt; /* retry counter */ char *pwbuf; /* buffer for password */ int size; /* size of password buffer */ ZCONST char *zfn; /* name of zip archive */ ZCONST char *efn; /* name of archive entry being processed */ { #if CRYPT int r = IZ_PW_ENTERED; char *m; char *prompt; #ifndef REENTRANT /* tell picky compilers to shut up about "unused variable" warnings */ pG = pG; #endif if (*rcnt == 0) { /* First call for current entry */ *rcnt = 2; if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) { sprintf(prompt, LoadFarString(PasswPrompt), FnFilter1(zfn), FnFilter2(efn)); m = prompt; } else m = (char *)LoadFarString(PasswPrompt2); } else { /* Retry call, previous password was wrong */ (*rcnt)--; prompt = NULL; m = (char *)LoadFarString(PasswRetry); } m = getp(__G__ m, pwbuf, size); if (prompt != (char *)NULL) { free(prompt); } if (m == (char *)NULL) { r = IZ_PW_ERROR; } else if (*pwbuf == '\0') { r = IZ_PW_CANCELALL; } return r; #else /* !CRYPT */ /* tell picky compilers to shut up about "unused variable" warnings */ pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn; return IZ_PW_ERROR; /* internal error; function should never get called */ #endif /* ?CRYPT */ } /* end function UzpPassword() */ /**********************/ /* Function handler() */ /**********************/ void handler(signal) /* upon interrupt, turn on echo and exit cleanly */ int signal; { GETGLOBALS(); #if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */ (*G.message)((zvoid *)&G, slide, 0L, 0x41); /* start of line (to stderr; */ #endif /* slide[] should be safe) */ echon(); #ifdef SIGBUS if (signal == SIGBUS) { Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), "bus error")); DESTROYGLOBALS(); EXIT(PK_BADERR); } #endif /* SIGBUS */ #ifdef SIGILL if (signal == SIGILL) { Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), "illegal instruction")); DESTROYGLOBALS(); EXIT(PK_BADERR); } #endif /* SIGILL */ #ifdef SIGSEGV if (signal == SIGSEGV) { Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), "segmentation violation")); DESTROYGLOBALS(); EXIT(PK_BADERR); } #endif /* SIGSEGV */ /* probably ctrl-C */ DESTROYGLOBALS(); #if defined(AMIGA) && defined(__SASC) _abort(); #endif EXIT(IZ_CTRLC); /* was EXIT(0), then EXIT(PK_ERR) */ } #endif /* !WINDLL */ #if (!defined(VMS) && !defined(CMS_MVS)) #if (!defined(OS2) || defined(TIMESTAMP)) #if (!defined(HAVE_MKTIME) || defined(WIN32)) /* also used in amiga/filedate.c and win32/win32.c */ ZCONST ush ydays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; #endif /*******************************/ /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */ /*******************************/ time_t dos_to_unix_time(dosdatetime) ulg dosdatetime; { time_t m_time; #ifdef HAVE_MKTIME ZCONST time_t now = time(NULL); struct tm *tm; # define YRBASE 1900 tm = localtime(&now); tm->tm_isdst = -1; /* let mktime determine if DST is in effect */ /* dissect date */ tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE); tm->tm_mon = ((int)(dosdatetime >> 21) & 0x0f) - 1; tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f); /* dissect time */ tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f; tm->tm_min = (int)((unsigned)dosdatetime >> 5) & 0x3f; tm->tm_sec = (int)((unsigned)dosdatetime << 1) & 0x3e; m_time = mktime(tm); NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */ TTrace((stderr, " final m_time = %lu\n", (ulg)m_time)); #else /* !HAVE_MKTIME */ int yr, mo, dy, hh, mm, ss; #ifdef TOPS20 # define YRBASE 1900 struct tmx *tmx; char temp[20]; #else /* !TOPS20 */ # define YRBASE 1970 int leap; unsigned days; struct tm *tm; #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM)) #ifdef WIN32 TIME_ZONE_INFORMATION tzinfo; DWORD res; #else /* ! WIN32 */ #ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */ #if (defined(BSD) || defined(MTS) || defined(__GO32__)) struct timeb tbp; #else /* !(BSD || MTS || __GO32__) */ #ifdef DECLARE_TIMEZONE extern time_t timezone; #endif #endif /* ?(BSD || MTS || __GO32__) */ #endif /* !BSD4_4 */ #endif /* ?WIN32 */ #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */ #endif /* ?TOPS20 */ /* dissect date */ yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE); mo = ((int)(dosdatetime >> 21) & 0x0f) - 1; dy = ((int)(dosdatetime >> 16) & 0x1f) - 1; /* dissect time */ hh = (int)((unsigned)dosdatetime >> 11) & 0x1f; mm = (int)((unsigned)dosdatetime >> 5) & 0x3f; ss = (int)((unsigned)dosdatetime & 0x1f) * 2; #ifdef TOPS20 tmx = (struct tmx *)malloc(sizeof(struct tmx)); sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss); time_parse(temp, tmx, (char *)0); m_time = time_make(tmx); free(tmx); #else /* !TOPS20 */ /*--------------------------------------------------------------------------- Calculate the number of seconds since the epoch, usually 1 January 1970. ---------------------------------------------------------------------------*/ /* leap = # of leap yrs from YRBASE up to but not including current year */ leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */ /* calculate days from BASE to this year and add expired days this year */ days = (yr * 365) + (leap - 492) + ydays[mo]; /* if year is a leap year and month is after February, add another day */ if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100)) ++days; /* OK through 2199 */ /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */ m_time = (time_t)((unsigned long)(days + dy) * 86400L + (unsigned long)hh * 3600L + (unsigned long)(mm * 60 + ss)); /* - 1; MS-DOS times always rounded up to nearest even second */ TTrace((stderr, "dos_to_unix_time:\n")); TTrace((stderr, " m_time before timezone = %lu\n", (ulg)m_time)); /*--------------------------------------------------------------------------- Adjust for local standard timezone offset. ---------------------------------------------------------------------------*/ #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM)) #ifdef WIN32 /* account for timezone differences */ res = GetTimeZoneInformation(&tzinfo); if (res != TIME_ZONE_ID_INVALID) { m_time += 60*(tzinfo.Bias); #else /* !WIN32 */ #if (defined(BSD) || defined(MTS) || defined(__GO32__)) #ifdef BSD4_4 if ( (dosdatetime >= DOSTIME_2038_01_18) && (m_time < (time_t)0x70000000L) ) m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ if ((tm = localtime(&m_time)) != (struct tm *)NULL) m_time -= tm->tm_gmtoff; /* sec. EAST of GMT: subtr. */ #else /* !(BSD4_4 */ ftime(&tbp); /* get `timezone' */ m_time += tbp.timezone * 60L; /* seconds WEST of GMT: add */ #endif /* ?(BSD4_4 || __EMX__) */ #else /* !(BSD || MTS || __GO32__) */ /* tzset was already called at start of process_zipfiles() */ /* tzset(); */ /* set `timezone' variable */ #ifndef __BEOS__ /* BeOS DR8 has no timezones... */ m_time += timezone; /* seconds WEST of GMT: add */ #endif #endif /* ?(BSD || MTS || __GO32__) */ #endif /* ?WIN32 */ TTrace((stderr, " m_time after timezone = %lu\n", (ulg)m_time)); /*--------------------------------------------------------------------------- Adjust for local daylight savings (summer) time. ---------------------------------------------------------------------------*/ #ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */ if ( (dosdatetime >= DOSTIME_2038_01_18) && (m_time < (time_t)0x70000000L) ) m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ TIMET_TO_NATIVE(m_time) /* NOP unless MSC 7.0 or Macintosh */ if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst) #ifdef WIN32 m_time += 60L * tzinfo.DaylightBias; /* adjust with DST bias */ else m_time += 60L * tzinfo.StandardBias; /* add StdBias (normally 0) */ #else m_time -= 60L * 60L; /* adjust for daylight savings time */ #endif NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */ TTrace((stderr, " m_time after DST = %lu\n", (ulg)m_time)); #endif /* !BSD4_4 */ #ifdef WIN32 } #endif #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */ #endif /* ?TOPS20 */ #endif /* ?HAVE_MKTIME */ if ( (dosdatetime >= DOSTIME_2038_01_18) && (m_time < (time_t)0x70000000L) ) m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ return m_time; } /* end function dos_to_unix_time() */ #endif /* !OS2 || TIMESTAMP */ #endif /* !VMS && !CMS_MVS */ #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS)) /******************************/ /* Function check_for_newer() */ /* used for overwriting/freshening/updating */ /******************************/ int check_for_newer(__G__ filename) /* return 1 if existing file is newer */ __GDEF /* or equal; 0 if older; -1 if doesn't */ char *filename; /* exist yet */ { time_t existing, archive; #ifdef USE_EF_UT_TIME iztimes z_utime; #endif #ifdef AOS_VS long dyy, dmm, ddd, dhh, dmin, dss; dyy = (lrec.last_mod_dos_datetime >> 25) + 1980; dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f; ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f; dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f; dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f; dss = (lrec.last_mod_dos_datetime & 0x1f) * 2; /* under AOS/VS, file times can only be set at creation time, * with the info in a special DG format. Make sure we can create * it here - we delete it later & re-create it, whether or not * it exists now. */ if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) | (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1)) return DOES_NOT_EXIST; #endif /* AOS_VS */ Trace((stderr, "check_for_newer: doing stat(%s)\n", FnFilter1(filename))); if (SSTAT(filename, &G.statbuf)) { Trace((stderr, "check_for_newer: stat(%s) returns %d: file does not exist\n", FnFilter1(filename), SSTAT(filename, &G.statbuf))); #ifdef SYMLINKS Trace((stderr, "check_for_newer: doing lstat(%s)\n", FnFilter1(filename))); /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ if (lstat(filename, &G.statbuf) == 0) { Trace((stderr, "check_for_newer: lstat(%s) returns 0: symlink does exist\n", FnFilter1(filename))); if (QCOND2 && !IS_OVERWRT_ALL) Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), FnFilter1(filename), " with no real file")); return EXISTS_AND_OLDER; /* symlink dates are meaningless */ } #endif /* SYMLINKS */ return DOES_NOT_EXIST; } Trace((stderr, "check_for_newer: stat(%s) returns 0: file exists\n", FnFilter1(filename))); #ifdef SYMLINKS /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) { Trace((stderr, "check_for_newer: %s is a symbolic link\n", FnFilter1(filename))); if (QCOND2 && !IS_OVERWRT_ALL) Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), FnFilter1(filename), "")); return EXISTS_AND_OLDER; /* symlink dates are meaningless */ } #endif /* SYMLINKS */ NATIVE_TO_TIMET(G.statbuf.st_mtime) /* NOP unless MSC 7.0 or Macintosh */ #ifdef USE_EF_UT_TIME /* The `Unix extra field mtime' should be used for comparison with the * time stamp of the existing file >>>ONLY<<< when the EF info is also * used to set the modification time of the extracted file. */ if (G.extra_field && #ifdef IZ_CHECK_TZ G.tz_is_valid && #endif (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME)) { TTrace((stderr, "check_for_newer: using Unix extra field mtime\n")); existing = G.statbuf.st_mtime; archive = z_utime.mtime; } else { /* round up existing filetime to nearest 2 seconds for comparison, * but saturate in case of arithmetic overflow */ existing = ((G.statbuf.st_mtime & 1) && (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); } #else /* !USE_EF_UT_TIME */ /* round up existing filetime to nearest 2 seconds for comparison, * but saturate in case of arithmetic overflow */ existing = ((G.statbuf.st_mtime & 1) && (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); #endif /* ?USE_EF_UT_TIME */ TTrace((stderr, "check_for_newer: existing %lu, archive %lu, e-a %ld\n", (ulg)existing, (ulg)archive, (long)(existing-archive))); return (existing >= archive); } /* end function check_for_newer() */ #endif /* !VMS && !OS2 && !CMS_MVS */ /************************/ /* Function do_string() */ /************************/ int do_string(__G__ length, option) /* return PK-type error code */ __GDEF unsigned int length; /* without prototype, ush converted to this */ int option; { unsigned comment_bytes_left; unsigned int block_len; int error=PK_OK; #ifdef AMIGA char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */ #endif /*--------------------------------------------------------------------------- This function processes arbitrary-length (well, usually) strings. Four major options are allowed: SKIP, wherein the string is skipped (pretty logical, eh?); DISPLAY, wherein the string is printed to standard output after undergoing any necessary or unnecessary character conversions; DS_FN, wherein the string is put into the filename[] array after under- going appropriate conversions (including case-conversion, if that is indicated: see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the `string' is assumed to be an extra field and is copied to the (freshly malloced) buffer G.extra_field. The third option should be OK since filename is dimensioned at 1025, but we check anyway. The string, by the way, is assumed to start at the current file-pointer position; its length is given by 'length'. So start off by checking the length of the string: if zero, we're already done. ---------------------------------------------------------------------------*/ if (!length) return PK_COOL; switch (option) { #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) /* * Special case: See if the comment begins with an autorun command line. * Save that and display (or skip) the remainder. */ case CHECK_AUTORUN: case CHECK_AUTORUN_Q: comment_bytes_left = length; if (length >= 10) { block_len = readbuf(__G__ (char *)G.outbuf, 10); if (block_len == 0) return PK_EOF; comment_bytes_left -= block_len; G.outbuf[block_len] = '\0'; if (!strcmp((char *)G.outbuf, "$AUTORUN$>")) { char *eol; length -= 10; block_len = readbuf(__G__ G.autorun_command, MIN(length, sizeof(G.autorun_command)-1)); if (block_len == 0) return PK_EOF; comment_bytes_left -= block_len; G.autorun_command[block_len] = '\0'; A_TO_N(G.autorun_command); eol = strchr(G.autorun_command, '\n'); if (!eol) eol = G.autorun_command + strlen(G.autorun_command) - 1; length -= eol + 1 - G.autorun_command; while (eol >= G.autorun_command && isspace(*eol)) *eol-- = '\0'; #if (defined(WIN32) && !defined(_WIN32_WCE)) /* Win9x console always uses OEM character coding, and WinNT console is set to OEM charset by default, too */ INTERN_TO_OEM(G.autorun_command, G.autorun_command); #endif /* (WIN32 && !_WIN32_WCE) */ } } if (option == CHECK_AUTORUN_Q) /* don't display the remainder */ length = 0; /* seek to beginning of remaining part of comment -- rewind if */ /* displaying entire comment, or skip to end if discarding it */ seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr - G.inbuf) + comment_bytes_left - length); if (!length) break; /* FALL THROUGH... */ #endif /* SFX && CHEAP_SFX_AUTORUN */ /* * First normal case: print string on standard output. First set loop * variables, then loop through the comment in chunks of OUTBUFSIZ bytes, * converting formats and printing as we go. The second half of the * loop conditional was added because the file might be truncated, in * which case comment_bytes_left will remain at some non-zero value for * all time. outbuf and slide are used as scratch buffers because they * are available (we should be either before or in between any file pro- * cessing). */ case DISPLAY: case DISPL_8: comment_bytes_left = length; block_len = OUTBUFSIZ; /* for the while statement, first time */ while (comment_bytes_left > 0 && block_len > 0) { register uch *p = G.outbuf; register uch *q = G.outbuf; if ((block_len = readbuf(__G__ (char *)G.outbuf, MIN((unsigned)OUTBUFSIZ, comment_bytes_left))) == 0) return PK_EOF; comment_bytes_left -= block_len; /* this is why we allocated an extra byte for outbuf: terminate * with zero (ASCIIZ) */ G.outbuf[block_len] = '\0'; /* remove all ASCII carriage returns from comment before printing * (since used before A_TO_N(), check for CR instead of '\r') */ while (*p) { while (*p == CR) ++p; *q++ = *p++; } /* could check whether (p - outbuf) == block_len here */ *q = '\0'; if (option == DISPL_8) { /* translate the text coded in the entry's host-dependent "extended ASCII" charset into the compiler's (system's) internal text code page */ Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum, G.pInfo->hostver, G.pInfo->HasUxAtt, FALSE); #ifdef WINDLL /* translate to ANSI (RTL internal codepage may be OEM) */ INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf); #else /* !WINDLL */ #if (defined(WIN32) && !defined(_WIN32_WCE)) /* Win9x console always uses OEM character coding, and WinNT console is set to OEM charset by default, too */ INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf); #endif /* (WIN32 && !_WIN32_WCE) */ #endif /* ?WINDLL */ } else { A_TO_N(G.outbuf); /* translate string to native */ } #ifdef WINDLL /* ran out of local mem -- had to cheat */ win_fprintf((zvoid *)&G, stdout, (extent)(q-G.outbuf), (char *)G.outbuf); win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n"); #else /* !WINDLL */ #ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */ (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0); #else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */ p = G.outbuf - 1; q = slide; while (*++p) { int pause = FALSE; if (*p == 0x1B) { /* ASCII escape char */ *q++ = '^'; *q++ = '['; } else if (*p == 0x13) { /* ASCII ^S (pause) */ pause = TRUE; if (p[1] == LF) /* ASCII LF */ *q++ = *++p; else if (p[1] == CR && p[2] == LF) { /* ASCII CR LF */ *q++ = *++p; *q++ = *++p; } } else *q++ = *p; if ((unsigned)(q-slide) > WSIZE-3 || pause) { /* flush */ (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); q = slide; if (pause && G.extract_flag) /* don't pause for list/test */ (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0); } } (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); #endif /* ?NOANSIFILT */ #endif /* ?WINDLL */ } /* add '\n' if not at start of line */ (*G.message)((zvoid *)&G, slide, 0L, 0x40); break; /* * Second case: read string into filename[] array. The filename should * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check, * just to be sure. */ case DS_FN: case DS_FN_L: #ifdef UNICODE_SUPPORT /* get the whole filename as need it for Unicode checksum */ if (G.fnfull_bufsize <= length) { extent fnbufsiz = FILNAMSIZ; if (fnbufsiz <= length) fnbufsiz = length + 1; if (G.filename_full) free(G.filename_full); G.filename_full = malloc(fnbufsiz); if (G.filename_full == NULL) return PK_MEM; G.fnfull_bufsize = fnbufsiz; } if (readbuf(__G__ G.filename_full, length) == 0) return PK_EOF; G.filename_full[length] = '\0'; /* terminate w/zero: ASCIIZ */ /* if needed, chop off end so standard filename is a valid length */ if (length >= FILNAMSIZ) { Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameTooLongTrunc))); error = PK_WARN; length = FILNAMSIZ - 1; } /* no excess size */ block_len = 0; strncpy(G.filename, G.filename_full, length); G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */ #else /* !UNICODE_SUPPORT */ if (length >= FILNAMSIZ) { Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameTooLongTrunc))); error = PK_WARN; /* remember excess length in block_len */ block_len = length - (FILNAMSIZ - 1); length = FILNAMSIZ - 1; } else /* no excess size */ block_len = 0; if (readbuf(__G__ G.filename, length) == 0) return PK_EOF; G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */ #endif /* ?UNICODE_SUPPORT */ /* translate the Zip entry filename coded in host-dependent "extended ASCII" into the compiler's (system's) internal text code page */ Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum, G.pInfo->hostver, G.pInfo->HasUxAtt, (option == DS_FN_L)); if (G.pInfo->lcflag) /* replace with lowercase filename */ STRLOWER(G.filename, G.filename); if (G.pInfo->vollabel && length > 8 && G.filename[8] == '.') { char *p = G.filename+8; while (*p++) p[-1] = *p; /* disk label, and 8th char is dot: remove dot */ } if (!block_len) /* no overflow, we're done here */ break; /* * We truncated the filename, so print what's left and then fall * through to the SKIP routine. */ Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename))); length = block_len; /* SKIP the excess bytes... */ /* FALL THROUGH... */ /* * Third case: skip string, adjusting readbuf's internal variables * as necessary (and possibly skipping to and reading a new block of * data). */ case SKIP: /* cur_zipfile_bufstart already takes account of extra_bytes, so don't * correct for it twice: */ seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr-G.inbuf) + length); break; /* * Fourth case: assume we're at the start of an "extra field"; malloc * storage for it and read data into the allocated space. */ case EXTRA_FIELD: if (G.extra_field != (uch *)NULL) free(G.extra_field); if ((G.extra_field = (uch *)malloc(length)) == (uch *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong), length)); /* cur_zipfile_bufstart already takes account of extra_bytes, * so don't correct for it twice: */ seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr-G.inbuf) + length); } else { if (readbuf(__G__ (char *)G.extra_field, length) == 0) return PK_EOF; /* Looks like here is where extra fields are read */ getZip64Data(__G__ G.extra_field, length); #ifdef UNICODE_SUPPORT G.unipath_filename = NULL; if (G.UzO.U_flag < 2) { /* check if GPB11 (General Purpuse Bit 11) is set indicating the standard path and comment are UTF-8 */ if (G.pInfo->GPFIsUTF8) { /* if GPB11 set then filename_full is untruncated UTF-8 */ G.unipath_filename = G.filename_full; } else { /* Get the Unicode fields if exist */ getUnicodeData(__G__ G.extra_field, length); if (G.unipath_filename && strlen(G.unipath_filename) == 0) { /* the standard filename field is UTF-8 */ free(G.unipath_filename); G.unipath_filename = G.filename_full; } } if (G.unipath_filename) { # ifdef UTF8_MAYBE_NATIVE if (G.native_is_utf8 # ifdef UNICODE_WCHAR && (!G.unicode_escape_all) # endif ) { strncpy(G.filename, G.unipath_filename, FILNAMSIZ - 1); /* make sure filename is short enough */ if (strlen(G.unipath_filename) >= FILNAMSIZ) { G.filename[FILNAMSIZ - 1] = '\0'; Info(slide, 0x401, ((char *)slide, LoadFarString(UFilenameTooLongTrunc))); error = PK_WARN; } } # ifdef UNICODE_WCHAR else # endif # endif /* UTF8_MAYBE_NATIVE */ # ifdef UNICODE_WCHAR { char *fn; /* convert UTF-8 to local character set */ fn = utf8_to_local_string(G.unipath_filename, G.unicode_escape_all); /* make sure filename is short enough */ if (strlen(fn) >= FILNAMSIZ) { fn[FILNAMSIZ - 1] = '\0'; Info(slide, 0x401, ((char *)slide, LoadFarString(UFilenameTooLongTrunc))); error = PK_WARN; } /* replace filename with converted UTF-8 */ strcpy(G.filename, fn); free(fn); } # endif /* UNICODE_WCHAR */ if (G.unipath_filename != G.filename_full) free(G.unipath_filename); G.unipath_filename = NULL; } } #endif /* UNICODE_SUPPORT */ } break; #ifdef AMIGA /* * Fifth case, for the Amiga only: take the comment that would ordinarily * be skipped over, and turn it into a 79 character string that will be * attached to the file as a "filenote" after it is extracted. */ case FILENOTE: if ((block_len = readbuf(__G__ tmp_fnote, (unsigned) MIN(length, 2 * AMIGA_FILENOTELEN - 1))) == 0) return PK_EOF; if ((length -= block_len) > 0) /* treat remainder as in case SKIP: */ seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr - G.inbuf) + length); /* convert multi-line text into single line with no ctl-chars: */ tmp_fnote[block_len] = '\0'; while ((short int) --block_len >= 0) if ((unsigned) tmp_fnote[block_len] < ' ') if (tmp_fnote[block_len+1] == ' ') /* no excess */ strcpy(tmp_fnote+block_len, tmp_fnote+block_len+1); else tmp_fnote[block_len] = ' '; tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0'; if (G.filenotes[G.filenote_slot]) free(G.filenotes[G.filenote_slot]); /* should not happen */ G.filenotes[G.filenote_slot] = NULL; if (tmp_fnote[0]) { if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1))) return PK_MEM; strcpy(G.filenotes[G.filenote_slot], tmp_fnote); } break; #endif /* AMIGA */ } /* end switch (option) */ return error; } /* end function do_string() */ /***********************/ /* Function makeword() */ /***********************/ ush makeword(b) ZCONST uch *b; { /* * Convert Intel style 'short' integer to non-Intel non-16-bit * host format. This routine also takes care of byte-ordering. */ return (ush)((b[1] << 8) | b[0]); } /***********************/ /* Function makelong() */ /***********************/ ulg makelong(sig) ZCONST uch *sig; { /* * Convert intel style 'long' variable to non-Intel non-16-bit * host format. This routine also takes care of byte-ordering. */ return (((ulg)sig[3]) << 24) + (((ulg)sig[2]) << 16) + (ulg)((((unsigned)sig[1]) << 8) + ((unsigned)sig[0])); } /************************/ /* Function makeint64() */ /************************/ zusz_t makeint64(sig) ZCONST uch *sig; { #ifdef LARGE_FILE_SUPPORT /* * Convert intel style 'int64' variable to non-Intel non-16-bit * host format. This routine also takes care of byte-ordering. */ return (((zusz_t)sig[7]) << 56) + (((zusz_t)sig[6]) << 48) + (((zusz_t)sig[4]) << 32) + (zusz_t)((((ulg)sig[3]) << 24) + (((ulg)sig[2]) << 16) + (((unsigned)sig[1]) << 8) + (sig[0])); #else /* !LARGE_FILE_SUPPORT */ if ((sig[7] | sig[6] | sig[5] | sig[4]) != 0) return (zusz_t)0xffffffffL; else return (zusz_t)((((ulg)sig[3]) << 24) + (((ulg)sig[2]) << 16) + (((unsigned)sig[1]) << 8) + (sig[0])); #endif /* ?LARGE_FILE_SUPPORT */ } /*********************/ /* Function fzofft() */ /*********************/ /* Format a zoff_t value in a cylindrical buffer set. */ char *fzofft(__G__ val, pre, post) __GDEF zoff_t val; ZCONST char *pre; ZCONST char *post; { /* Storage cylinder. (now in globals.h) */ /*static char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN];*/ /*static int fzofft_index = 0;*/ /* Temporary format string storage. */ char fmt[16]; /* Assemble the format string. */ fmt[0] = '%'; fmt[1] = '\0'; /* Start after initial "%". */ if (pre == FZOFFT_HEX_WID) /* Special hex width. */ { strcat(fmt, FZOFFT_HEX_WID_VALUE); } else if (pre == FZOFFT_HEX_DOT_WID) /* Special hex ".width". */ { strcat(fmt, "."); strcat(fmt, FZOFFT_HEX_WID_VALUE); } else if (pre != NULL) /* Caller's prefix (width). */ { strcat(fmt, pre); } strcat(fmt, FZOFFT_FMT); /* Long or long-long or whatever. */ if (post == NULL) strcat(fmt, "d"); /* Default radix = decimal. */ else strcat(fmt, post); /* Caller's radix. */ /* Advance the cylinder. */ G.fzofft_index = (G.fzofft_index + 1) % FZOFFT_NUM; /* Write into the current chamber. */ sprintf(G.fzofft_buf[G.fzofft_index], fmt, val); /* Return a pointer to this chamber. */ return G.fzofft_buf[G.fzofft_index]; } #if CRYPT #ifdef NEED_STR2ISO /**********************/ /* Function str2iso() */ /**********************/ char *str2iso(dst, src) char *dst; /* destination buffer */ register ZCONST char *src; /* source string */ { #ifdef INTERN_TO_ISO INTERN_TO_ISO(src, dst); #else register uch c; register char *dstp = dst; do { c = (uch)foreign(*src++); *dstp++ = (char)ASCII2ISO(c); } while (c != '\0'); #endif return dst; } #endif /* NEED_STR2ISO */ #ifdef NEED_STR2OEM /**********************/ /* Function str2oem() */ /**********************/ char *str2oem(dst, src) char *dst; /* destination buffer */ register ZCONST char *src; /* source string */ { #ifdef INTERN_TO_OEM INTERN_TO_OEM(src, dst); #else register uch c; register char *dstp = dst; do { c = (uch)foreign(*src++); *dstp++ = (char)ASCII2OEM(c); } while (c != '\0'); #endif return dst; } #endif /* NEED_STR2OEM */ #endif /* CRYPT */ #ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */ /* bzero/bcmp/bcopy */ /* (no known systems as of 960211) */ /*********************/ /* Function memset() */ /*********************/ zvoid *memset(buf, init, len) register zvoid *buf; /* buffer location */ register int init; /* initializer character */ register unsigned int len; /* length of the buffer */ { zvoid *start; start = buf; while (len--) *((char *)buf++) = (char)init; return start; } /*********************/ /* Function memcmp() */ /*********************/ int memcmp(b1, b2, len) register ZCONST zvoid *b1; register ZCONST zvoid *b2; register unsigned int len; { register int c; if (len > 0) do { if ((c = (int)(*((ZCONST unsigned char *)b1)++) - (int)(*((ZCONST unsigned char *)b2)++)) != 0) return c; } while (--len > 0) return 0; } /*********************/ /* Function memcpy() */ /*********************/ zvoid *memcpy(dst, src, len) register zvoid *dst; register ZCONST zvoid *src; register unsigned int len; { zvoid *start; start = dst; while (len-- > 0) *((char *)dst)++ = *((ZCONST char *)src)++; return start; } #endif /* ZMEM */ #ifdef NO_STRNICMP /************************/ /* Function zstrnicmp() */ /************************/ int zstrnicmp(s1, s2, n) register ZCONST char *s1, *s2; register unsigned n; { for (; n > 0; --n, ++s1, ++s2) { if (ToLower(*s1) != ToLower(*s2)) /* test includes early termination of one string */ return ((uch)ToLower(*s1) < (uch)ToLower(*s2))? -1 : 1; if (*s1 == '\0') /* both strings terminate early */ return 0; } return 0; } #endif /* NO_STRNICMP */ #ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */ # undef stat /********************/ /* Function zstat() */ /********************/ int zstat(p, s) ZCONST char *p; struct stat *s; { return (stat((char *)p,s) >= 0? 0 : (-1)); } #endif /* REGULUS */ #ifdef _MBCS /* DBCS support for Info-ZIP's zip (mainly for japanese (-: ) * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp) * This code is public domain! Date: 1998/12/20 */ /************************/ /* Function plastchar() */ /************************/ char *plastchar(ptr, len) ZCONST char *ptr; extent len; { unsigned clen; ZCONST char *oldptr = ptr; while(*ptr != '\0' && len > 0){ oldptr = ptr; clen = CLEN(ptr); ptr += clen; len -= clen; } return (char *)oldptr; } #ifdef NEED_UZMBCLEN /***********************/ /* Function uzmbclen() */ /***********************/ extent uzmbclen(ptr) ZCONST unsigned char *ptr; { int mbl; mbl = mblen((ZCONST char *)ptr, MB_CUR_MAX); /* For use in code scanning through MBCS strings, we need a strictly positive "MB char bytes count". For our scanning purpose, it is not not relevant whether the MB character is valid or not. And, the NUL char '\0' has a byte count of 1, but mblen() returns 0. So, we make sure that the uzmbclen() return value is not less than 1. */ return (extent)(mbl > 0 ? mbl : 1); } #endif /* NEED_UZMBCLEN */ #ifdef NEED_UZMBSCHR /***********************/ /* Function uzmbschr() */ /***********************/ unsigned char *uzmbschr(str, c) ZCONST unsigned char *str; unsigned int c; { while(*str != '\0'){ if (*str == c) {return (unsigned char *)str;} INCSTR(str); } return NULL; } #endif /* NEED_UZMBSCHR */ #ifdef NEED_UZMBSRCHR /************************/ /* Function uzmbsrchr() */ /************************/ unsigned char *uzmbsrchr(str, c) ZCONST unsigned char *str; unsigned int c; { unsigned char *match = NULL; while(*str != '\0'){ if (*str == c) {match = (unsigned char *)str;} INCSTR(str); } return match; } #endif /* NEED_UZMBSRCHR */ #endif /* _MBCS */ #ifdef SMALL_MEM /*******************************/ /* Function fLoadFarString() */ /* (and friends...) */ /*******************************/ char *fLoadFarString(__GPRO__ const char Far *sz) { (void)zfstrcpy(G.rgchBigBuffer, sz); return G.rgchBigBuffer; } char *fLoadFarStringSmall(__GPRO__ const char Far *sz) { (void)zfstrcpy(G.rgchSmallBuffer, sz); return G.rgchSmallBuffer; } char *fLoadFarStringSmall2(__GPRO__ const char Far *sz) { (void)zfstrcpy(G.rgchSmallBuffer2, sz); return G.rgchSmallBuffer2; } #if (!defined(_MSC_VER) || (_MSC_VER < 600)) /*************************/ /* Function zfstrcpy() */ /* portable clone of _fstrcpy() */ /*************************/ char Far * Far zfstrcpy(char Far *s1, const char Far *s2) { char Far *p = s1; while ((*s1++ = *s2++) != '\0'); return p; } #if (!(defined(SFX) || defined(FUNZIP))) /*************************/ /* Function zfstrcmp() */ /* portable clone of _fstrcmp() */ /*************************/ int Far zfstrcmp(const char Far *s1, const char Far *s2) { int ret; while ((ret = (int)(uch)*s1 - (int)(uch)*s2) == 0 && *s2 != '\0') { ++s2; ++s1; } return ret; } #endif /* !(SFX || FUNZIP) */ #endif /* !_MSC_VER || (_MSC_VER < 600) */ #endif /* SMALL_MEM */ Carla-2.1/data/windows/unzipfx-carla/globals.c000066400000000000000000000145331364475620200213720ustar00rootroot00000000000000/* Copyright (c) 1990-2007 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2003-May-08 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- globals.c Routines to allocate and initialize globals, with or without threads. Contents: registerGlobalPointer() deregisterGlobalPointer() getGlobalPointer() globalsCtor() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #ifndef FUNZIP /* initialization of sigs is completed at runtime so unzip(sfx) executable * won't look like a zipfile */ char central_hdr_sig[4] = {0, 0, 0x01, 0x02}; char local_hdr_sig[4] = {0, 0, 0x03, 0x04}; char end_central_sig[4] = {0, 0, 0x05, 0x06}; char end_central64_sig[4] = {0, 0, 0x06, 0x06}; char end_centloc64_sig[4] = {0, 0, 0x06, 0x07}; /* extern char extd_local_sig[4] = {0, 0, 0x07, 0x08}; NOT USED YET */ ZCONST char *fnames[2] = {"*", NULL}; /* default filenames vector */ #endif #ifndef REENTRANT Uz_Globs G; #else /* REENTRANT */ # ifndef USETHREADID Uz_Globs *GG; # else /* USETHREADID */ # define THREADID_ENTRIES 0x40 int lastScan; Uz_Globs *threadPtrTable[THREADID_ENTRIES]; ulg threadIdTable [THREADID_ENTRIES] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* Make sure there are */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* THREADID_ENTRIES 0s */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; static ZCONST char Far TooManyThreads[] = "error: more than %d simultaneous threads.\n\ Some threads are probably not calling DESTROYTHREAD()\n"; static ZCONST char Far EntryNotFound[] = "error: couldn't find global pointer in table.\n\ Maybe somebody accidentally called DESTROYTHREAD() twice.\n"; static ZCONST char Far GlobalPointerMismatch[] = "error: global pointer in table does not match pointer passed as\ parameter\n"; static void registerGlobalPointer OF((__GPRO)); static void registerGlobalPointer(__G) __GDEF { int scan=0; ulg tid = GetThreadId(); while (threadIdTable[scan] && scan < THREADID_ENTRIES) scan++; if (scan == THREADID_ENTRIES) { ZCONST char *tooMany = LoadFarString(TooManyThreads); Info(slide, 0x421, ((char *)slide, tooMany, THREADID_ENTRIES)); free(pG); EXIT(PK_MEM); /* essentially memory error before we've started */ } threadIdTable [scan] = tid; threadPtrTable[scan] = pG; lastScan = scan; } void deregisterGlobalPointer(__G) __GDEF { int scan=0; ulg tid = GetThreadId(); while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES) scan++; /*--------------------------------------------------------------------------- There are two things we can do if we can't find the entry: ignore it or scream. The most likely reason for it not to be here is the user calling this routine twice. Since this could cause BIG problems if any globals are accessed after the first call, we'd better scream. ---------------------------------------------------------------------------*/ if (scan == THREADID_ENTRIES || threadPtrTable[scan] != pG) { ZCONST char *noEntry; if (scan == THREADID_ENTRIES) noEntry = LoadFarString(EntryNotFound); else noEntry = LoadFarString(GlobalPointerMismatch); Info(slide, 0x421, ((char *)slide, noEntry)); EXIT(PK_WARN); /* programming error, but after we're all done */ } threadIdTable [scan] = 0; lastScan = scan; free(threadPtrTable[scan]); } Uz_Globs *getGlobalPointer() { int scan=0; ulg tid = GetThreadId(); while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES) scan++; /*--------------------------------------------------------------------------- There are two things we can do if we can't find the entry: ignore it or scream. The most likely reason for it not to be here is the user calling this routine twice. Since this could cause BIG problems if any globals are accessed after the first call, we'd better scream. ---------------------------------------------------------------------------*/ if (scan == THREADID_ENTRIES) { ZCONST char *noEntry = LoadFarString(EntryNotFound); fprintf(stderr, noEntry); /* can't use Info w/o a global pointer */ EXIT(PK_ERR); /* programming error while still working */ } return threadPtrTable[scan]; } # endif /* ?USETHREADID */ #endif /* ?REENTRANT */ Uz_Globs *globalsCtor() { #ifdef REENTRANT Uz_Globs *pG = (Uz_Globs *)malloc(sizeof(Uz_Globs)); if (!pG) return (Uz_Globs *)NULL; #endif /* REENTRANT */ /* for REENTRANT version, G is defined as (*pG) */ memzero(&G, sizeof(Uz_Globs)); #ifndef FUNZIP #ifdef CMS_MVS uO.aflag=1; uO.C_flag=1; #endif #ifdef TANDEM uO.aflag=1; /* default to '-a' auto create Text Files as type 101 */ #endif #ifdef VMS # if (!defined(NO_TIMESTAMPS)) uO.D_flag=1; /* default to '-D', no restoration of dir timestamps */ # endif #endif uO.lflag=(-1); G.wildzipfn = ""; G.pfnames = (char **)fnames; G.pxnames = (char **)&fnames[1]; G.pInfo = G.info; G.sol = TRUE; /* at start of line */ G.message = UzpMessagePrnt; G.input = UzpInput; /* not used by anyone at the moment... */ #if defined(WINDLL) || defined(MACOS) G.mpause = NULL; /* has scrollbars: no need for pausing */ #else G.mpause = UzpMorePause; #endif G.decr_passwd = UzpPassword; #endif /* !FUNZIP */ #if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) #if (!defined(MACOS) && !defined(ATARI) && !defined(VMS)) G.echofd = -1; #endif /* !(MACOS || ATARI || VMS) */ #endif /* !(DOS_FLX_H68_NLM_OS2_W32 || AMIGA || RISCOS) */ #ifdef SYSTEM_SPECIFIC_CTOR SYSTEM_SPECIFIC_CTOR(__G); #endif #ifdef REENTRANT #ifdef USETHREADID registerGlobalPointer(__G); #else GG = &G; #endif /* ?USETHREADID */ #endif /* REENTRANT */ return &G; } Carla-2.1/data/windows/unzipfx-carla/globals.h000066400000000000000000000410711364475620200213740ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- globals.h There is usually no need to include this file since unzip.h includes it. This header file is used by all of the UnZip source files. It contains a struct definition that is used to "house" all of the global variables. This is done to allow for multithreaded environments (OS/2, NT, Win95, Unix) to call UnZip through an API without a semaphore. REENTRANT should be defined for all platforms that require this. GLOBAL CONSTRUCTOR AND DESTRUCTOR (API WRITERS READ THIS!!!) ------------------------------------------------------------ No, it's not C++, but it's as close as we can get with K&R. The main() of each process that uses these globals must include the CONSTRUCTGLOBALS; statement. This will malloc enough memory for the structure and initialize any variables that require it. This must also be done by any API function that jumps into the middle of the code. The DESTROYGLOBALS(); statement should be inserted before EVERY "EXIT(n)". Naturally, it also needs to be put before any API returns as well. In fact, it's much more important in API functions since the process will NOT end, and therefore the memory WON'T automatically be freed by the operating system. USING VARIABLES FROM THE STRUCTURE ---------------------------------- All global variables must now be prefixed with `G.' which is either a global struct (in which case it should be the only global variable) or a macro for the value of a local pointer variable that is passed from function to function. Yes, this is a pain. But it's the only way to allow full reentrancy. ADDING VARIABLES TO THE STRUCTURE --------------------------------- If you make the inclusion of any variables conditional, be sure to only check macros that are GUARANTEED to be included in every module. For instance, newzip and pwdarg are needed only if CRYPT is TRUE, but this is defined after unzip.h has been read. If you are not careful, some modules will expect your variable to be part of this struct while others won't. This will cause BIG problems. (Inexplicable crashes at strange times, car fires, etc.) When in doubt, always include it! Note also that UnZipSFX needs a few variables that UnZip doesn't. However, it also includes some object files from UnZip. If we were to conditionally include the extra variables that UnZipSFX needs, the object files from UnZip would not mesh with the UnZipSFX object files. Result: we just include the UnZipSFX variables every time. (It's only an extra 4 bytes so who cares!) ADDING FUNCTIONS ---------------- To support this new global struct, all functions must now conditionally pass the globals pointer (pG) to each other. This is supported by 5 macros: __GPRO, __GPRO__, __G, __G__ and __GDEF. A function that needs no other parameters would look like this: int extract_or_test_files(__G) __GDEF { ... stuff ... } A function with other parameters would look like: int memextract(__G__ tgt, tgtsize, src, srcsize) __GDEF uch *tgt, *src; ulg tgtsize, srcsize; { ... stuff ... } In the Function Prototypes section of unzpriv.h, you should use __GPRO and __GPRO__ instead: int uz_opts OF((__GPRO__ int *pargc, char ***pargv)); int process_zipfiles OF((__GPRO)); Note that there is NO comma after __G__ or __GPRO__ and no semi-colon after __GDEF. I wish there was another way but I don't think there is. TESTING THE CODE ----------------- Whether your platform requires reentrancy or not, you should always try building with REENTRANT defined if any functions have been added. It is pretty easy to forget a __G__ or a __GDEF and this mistake will only show up if REENTRANT is defined. All platforms should run with REENTRANT defined. Platforms that can't take advantage of it will just be paying a performance penalty needlessly. SIGNAL MADNESS -------------- This whole pointer passing scheme falls apart when it comes to SIGNALs. I handle this situation 2 ways right now. If you define USETHREADID, UnZip will include a 64-entry table. Each entry can hold a global pointer and thread ID for one thread. This should allow up to 64 threads to access UnZip simultaneously. Calling DESTROYGLOBALS() will free the global struct and zero the table entry. If somebody forgets to call DESTROYGLOBALS(), this table will eventually fill up and UnZip will exit with an error message. A good way to test your code to make sure you didn't forget a DESTROYGLOBALS() is to change THREADID_ENTRIES to 3 or 4 in globals.c, making the table real small. Then make a small test program that calls your API a dozen times. Those platforms that don't have threads still need to be able to compile with REENTRANT defined to test and see if new code is correctly written to work either way. For these platforms, I simply keep a global pointer called GG that points to the Globals structure. Good enough for testing. I believe that NT has thread level storage. This could probably be used to store a global pointer for the sake of the signal handler more cleanly than my table approach. ---------------------------------------------------------------------------*/ #ifndef __globals_h #define __globals_h #ifdef USE_ZLIB # include "zlib.h" # ifdef zlib_version /* This name is used internally in unzip */ # undef zlib_version /* and must not be defined as a macro. */ # endif #endif #ifdef USE_BZIP2 # include "bzlib.h" #endif /*************/ /* Globals */ /*************/ typedef struct Globals { #ifdef DLL zvoid *callerglobs; /* pointer to structure of pass-through global vars */ #endif /* command options of general use */ UzpOpts UzO; /* command options of general use */ #ifndef FUNZIP /* command options specific to the high level command line interface */ #ifdef MORE int M_flag; /* -M: built-in "more" function */ #endif /* internal flags and general globals */ #ifdef MORE int height; /* check for SIGWINCH, etc., eventually... */ int lines; /* count of lines displayed on current screen */ # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) int width; int chars; /* count of screen characters in current line */ # endif #endif /* MORE */ #if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) int tz_is_valid; /* indicates that timezone info can be used */ #endif int noargs; /* did true command line have *any* arguments? */ unsigned filespecs; /* number of real file specifications to be matched */ unsigned xfilespecs; /* number of excluded filespecs to be matched */ int process_all_files; int overwrite_mode; /* 0 - query, 1 - always, 2 - never */ int create_dirs; /* used by main(), mapname(), checkdir() */ int extract_flag; int newzip; /* reset in extract.c; used in crypt.c */ zoff_t real_ecrec_offset; zoff_t expect_ecrec_offset; zoff_t csize; /* used by decompr. (NEXTBYTE): must be signed */ zoff_t used_csize; /* used by extract_or_test_member(), explode() */ #ifdef DLL int fValidate; /* true if only validating an archive */ int filenotfound; int redirect_data; /* redirect data to memory buffer */ int redirect_text; /* redirect text output to buffer */ # ifndef NO_SLIDE_REDIR int redirect_slide; /* redirect decompression area to mem buffer */ # if (defined(USE_DEFLATE64) && defined(INT_16BIT)) ulg _wsize; /* size of sliding window exceeds "unsigned" range */ # else unsigned _wsize; /* sliding window size can be hold in unsigned */ # endif # endif ulg redirect_size; /* size of redirected output buffer */ uch *redirect_buffer; /* pointer to head of allocated buffer */ uch *redirect_pointer; /* pointer past end of written data */ # ifndef NO_SLIDE_REDIR uch *redirect_sldptr; /* head of decompression slide buffer */ # endif # ifdef OS2DLL cbList(processExternally); /* call-back list */ # endif #endif /* DLL */ char **pfnames; char **pxnames; char sig[4]; char answerbuf[10]; min_info info[DIR_BLKSIZ]; min_info *pInfo; #endif /* !FUNZIP */ union work area; /* see unzpriv.h for definition of work */ #if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) ZCONST ulg near *crc_32_tab; #else ZCONST ulg Far *crc_32_tab; #endif ulg crc32val; /* CRC shift reg. (was static in funzip) */ #ifdef FUNZIP FILE *in; /* file descriptor of compressed stream */ #endif uch *inbuf; /* input buffer (any size is OK) */ uch *inptr; /* pointer into input buffer */ int incnt; #ifndef FUNZIP ulg bitbuf; int bits_left; /* unreduce and unshrink only */ int zipeof; char *argv0; /* used for NT and EXE_EXTENSION */ char *wildzipfn; char *zipfn; /* GRR: WINDLL: must nuke any malloc'd zipfn... */ #ifdef USE_STRM_INPUT FILE *zipfd; /* zipfile file descriptor */ #else int zipfd; /* zipfile file handle */ #endif zoff_t ziplen; zoff_t cur_zipfile_bufstart; /* extract_or_test, readbuf, ReadByte */ zoff_t extra_bytes; /* used in unzip.c, misc.c */ uch *extra_field; /* Unix, VMS, Mac, OS/2, Acorn, ... */ uch *hold; local_file_hdr lrec; /* used in unzip.c, extract.c */ cdir_file_hdr crec; /* used in unzip.c, extract.c, misc.c */ ecdir_rec ecrec; /* used in unzip.c, extract.c */ z_stat statbuf; /* used by main, mapname, check_for_newer */ int mem_mode; uch *outbufptr; /* extract.c static */ ulg outsize; /* extract.c static */ int reported_backslash; /* extract.c static */ int disk_full; int newfile; int didCRlast; /* fileio static */ ulg numlines; /* fileio static: number of lines printed */ int sol; /* fileio static: at start of line */ int no_ecrec; /* process static */ #ifdef SYMLINKS int symlnk; slinkentry *slink_head; /* pointer to head of symlinks list */ slinkentry *slink_last; /* pointer to last entry in symlinks list */ #endif #ifdef NOVELL_BUG_FAILSAFE int dne; /* true if stat() says file doesn't exist */ #endif FILE *outfile; uch *outbuf; uch *realbuf; #ifndef VMS /* if SMALL_MEM, outbuf2 is initialized in */ uch *outbuf2; /* process_zipfiles() (never changes); */ #endif /* else malloc'd ONLY if unshrink and -a */ #endif /* !FUNZIP */ uch *outptr; ulg outcnt; /* number of chars stored in outbuf */ #ifndef FUNZIP char filename[FILNAMSIZ]; /* also used by NT for temporary SFX path */ #ifdef UNICODE_SUPPORT char *filename_full; /* the full path so Unicode checks work */ extent fnfull_bufsize; /* size of allocated filename buffer */ int unicode_escape_all; int unicode_mismatch; #ifdef UTF8_MAYBE_NATIVE int native_is_utf8; /* bool, TRUE => native charset == UTF-8 */ #endif int unipath_version; /* version of Unicode field */ ulg unipath_checksum; /* Unicode field checksum */ char *unipath_filename; /* UTF-8 path */ #endif /* UNICODE_SUPPORT */ #ifdef CMS_MVS char *tempfn; /* temp file used; erase on close */ #endif char *key; /* crypt static: decryption password or NULL */ int nopwd; /* crypt static */ #endif /* !FUNZIP */ z_uint4 keys[3]; /* crypt static: keys defining pseudo-random sequence */ #if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) #if (!defined(MACOS) && !defined(ATARI) && !defined(VMS)) int echofd; /* ttyio static: file descriptor whose echo is off */ #endif /* !(MACOS || ATARI || VMS) */ #endif /* !(DOS_FLX_H68_NLM_OS2_W32 || AMIGA || RISCOS) */ unsigned hufts; /* track memory usage */ #ifdef USE_ZLIB int inflInit; /* inflate static: zlib inflate() initialized */ z_stream dstrm; /* inflate global: decompression stream */ #else struct huft *fixed_tl; /* inflate static */ struct huft *fixed_td; /* inflate static */ unsigned fixed_bl, fixed_bd; /* inflate static */ #ifdef USE_DEFLATE64 struct huft *fixed_tl64; /* inflate static */ struct huft *fixed_td64; /* inflate static */ unsigned fixed_bl64, fixed_bd64; /* inflate static */ struct huft *fixed_tl32; /* inflate static */ struct huft *fixed_td32; /* inflate static */ unsigned fixed_bl32, fixed_bd32; /* inflate static */ ZCONST ush *cplens; /* inflate static */ ZCONST uch *cplext; /* inflate static */ ZCONST uch *cpdext; /* inflate static */ #endif unsigned wp; /* inflate static: current position in slide */ ulg bb; /* inflate static: bit buffer */ unsigned bk; /* inflate static: bits count in bit buffer */ #endif /* ?USE_ZLIB */ #ifndef FUNZIP /* cylindric buffer space for formatting zoff_t values (fileio static) */ char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN]; int fzofft_index; #ifdef SMALL_MEM char rgchBigBuffer[512]; char rgchSmallBuffer[96]; char rgchSmallBuffer2[160]; /* boosted to 160 for local3[] in unzip.c */ #endif MsgFn *message; InputFn *input; PauseFn *mpause; PasswdFn *decr_passwd; StatCBFn *statreportcb; #ifdef WINDLL LPUSERFUNCTIONS lpUserFunctions; #endif int incnt_leftover; /* so improved NEXTBYTE does not waste input */ uch *inptr_leftover; #ifdef VMS_TEXT_CONV unsigned VMS_line_length; /* so native VMS variable-length text files */ int VMS_line_state; /* are readable on other platforms */ int VMS_line_pad; #endif #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) char autorun_command[FILNAMSIZ]; #endif #endif /* !FUNZIP */ #ifdef SYSTEM_SPECIFIC_GLOBALS SYSTEM_SPECIFIC_GLOBALS #endif } Uz_Globs; /* end of struct Globals */ /***************************************************************************/ #define CRC_32_TAB G.crc_32_tab Uz_Globs *globalsCtor OF((void)); /* pseudo constant sigs; they are initialized at runtime so unzip executable * won't look like a zipfile */ extern char local_hdr_sig[4]; extern char central_hdr_sig[4]; extern char end_central_sig[4]; extern char end_central32_sig[4]; extern char end_central64_sig[4]; extern char end_centloc64_sig[4]; /* extern char extd_local_sig[4]; NOT USED YET */ #ifdef REENTRANT # define G (*(Uz_Globs *)pG) # define __G pG # define __G__ pG, # define __GPRO Uz_Globs *pG # define __GPRO__ Uz_Globs *pG, # define __GDEF Uz_Globs *pG; # ifdef USETHREADID extern int lastScan; void deregisterGlobalPointer OF((__GPRO)); Uz_Globs *getGlobalPointer OF((void)); # define GETGLOBALS() Uz_Globs *pG = getGlobalPointer() # define DESTROYGLOBALS() do {free_G_buffers(pG); \ deregisterGlobalPointer(pG);} while (0) # else extern Uz_Globs *GG; # define GETGLOBALS() Uz_Globs *pG = GG # define DESTROYGLOBALS() do {free_G_buffers(pG); free(pG);} while (0) # endif /* ?USETHREADID */ # define CONSTRUCTGLOBALS() Uz_Globs *pG = globalsCtor() #else /* !REENTRANT */ extern Uz_Globs G; # define __G # define __G__ # define __GPRO void # define __GPRO__ # define __GDEF # define GETGLOBALS() # define CONSTRUCTGLOBALS() globalsCtor() # define DESTROYGLOBALS() #endif /* ?REENTRANT */ #define uO G.UzO #endif /* __globals_h */ Carla-2.1/data/windows/unzipfx-carla/inflate.c000066400000000000000000001742151364475620200213750ustar00rootroot00000000000000/* Copyright (c) 1990-2008 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2007-Mar-04 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* inflate.c -- by Mark Adler version c17e, 30 Mar 2007 */ /* Copyright history: - Starting with UnZip 5.41 of 16-April-2000, this source file is covered by the Info-Zip LICENSE cited above. - Prior versions of this source file, found in UnZip source packages up to UnZip 5.40, were put in the public domain. The original copyright note by Mark Adler was: "You can do whatever you like with this source file, though I would prefer that if you modify it and redistribute it that you include comments to that effect with your name and the date. Thank you." History: vers date who what ---- --------- -------------- ------------------------------------ a ~~ Feb 92 M. Adler used full (large, one-step) lookup table b1 21 Mar 92 M. Adler first version with partial lookup tables b2 21 Mar 92 M. Adler fixed bug in fixed-code blocks b3 22 Mar 92 M. Adler sped up match copies, cleaned up some b4 25 Mar 92 M. Adler added prototypes; removed window[] (now is the responsibility of unzip.h--also changed name to slide[]), so needs diffs for unzip.c and unzip.h (this allows compiling in the small model on MSDOS); fixed cast of q in huft_build(); b5 26 Mar 92 M. Adler got rid of unintended macro recursion. b6 27 Mar 92 M. Adler got rid of nextbyte() routine. fixed bug in inflate_fixed(). c1 30 Mar 92 M. Adler removed lbits, dbits environment variables. changed BMAX to 16 for explode. Removed OUTB usage, and replaced it with flush()-- this was a 20% speed improvement! Added an explode.c (to replace unimplod.c) that uses the huft routines here. Removed register union. c2 4 Apr 92 M. Adler fixed bug for file sizes a multiple of 32k. c3 10 Apr 92 M. Adler reduced memory of code tables made by huft_build significantly (factor of two to three). c4 15 Apr 92 M. Adler added NOMEMCPY do kill use of memcpy(). worked around a Turbo C optimization bug. c5 21 Apr 92 M. Adler added the WSIZE #define to allow reducing the 32K window size for specialized applications. c6 31 May 92 M. Adler added some typecasts to eliminate warnings c7 27 Jun 92 G. Roelofs added some more typecasts (444: MSC bug). c8 5 Oct 92 J-l. Gailly added ifdef'd code to deal with PKZIP bug. c9 9 Oct 92 M. Adler removed a memory error message (~line 416). c10 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch, removed old inflate, renamed inflate_entry to inflate, added Mark's fix to a comment. c10.5 14 Dec 92 M. Adler fix up error messages for incomplete trees. c11 2 Jan 93 M. Adler fixed bug in detection of incomplete tables, and removed assumption that EOB is the longest code (bad assumption). c12 3 Jan 93 M. Adler make tables for fixed blocks only once. c13 5 Jan 93 M. Adler allow all zero length codes (pkzip 2.04c outputs one zero length code for an empty distance tree). c14 12 Mar 93 M. Adler made inflate.c standalone with the introduction of inflate.h. c14b 16 Jul 93 G. Roelofs added (unsigned) typecast to w at 470. c14c 19 Jul 93 J. Bush changed v[N_MAX], l[288], ll[28x+3x] arrays to static for Amiga. c14d 13 Aug 93 J-l. Gailly de-complicatified Mark's c[*p++]++ thing. c14e 8 Oct 93 G. Roelofs changed memset() to memzero(). c14f 22 Oct 93 G. Roelofs renamed quietflg to qflag; made Trace() conditional; added inflate_free(). c14g 28 Oct 93 G. Roelofs changed l/(lx+1) macro to pointer (Cray bug) c14h 7 Dec 93 C. Ghisler huft_build() optimizations. c14i 9 Jan 94 A. Verheijen set fixed_t{d,l} to NULL after freeing; G. Roelofs check NEXTBYTE macro for EOF. c14j 23 Jan 94 G. Roelofs removed Ghisler "optimizations"; ifdef'd EOF check. c14k 27 Feb 94 G. Roelofs added some typecasts to avoid warnings. c14l 9 Apr 94 G. Roelofs fixed split comments on preprocessor lines to avoid bug in Encore compiler. c14m 7 Jul 94 P. Kienitz modified to allow assembler version of inflate_codes() (define ASM_INFLATECODES) c14n 22 Jul 94 G. Roelofs changed fprintf to macro for DLL versions c14o 23 Aug 94 C. Spieler added a newline to a debug statement; G. Roelofs added another typecast to avoid MSC warning c14p 4 Oct 94 G. Roelofs added (voidp *) cast to free() argument c14q 30 Oct 94 G. Roelofs changed fprintf macro to MESSAGE() c14r 1 Nov 94 G. Roelofs fixed possible redefinition of CHECK_EOF c14s 7 May 95 S. Maxwell OS/2 DLL globals stuff incorporated; P. Kienitz "fixed" ASM_INFLATECODES macro/prototype c14t 18 Aug 95 G. Roelofs added UZinflate() to use zlib functions; changed voidp to zvoid; moved huft_build() and huft_free() to end of file c14u 1 Oct 95 G. Roelofs moved G into definition of MESSAGE macro c14v 8 Nov 95 P. Kienitz changed ASM_INFLATECODES to use a regular call with __G__ instead of a macro c15 3 Aug 96 M. Adler fixed bomb-bug on random input data (Adobe) c15b 24 Aug 96 M. Adler more fixes for random input data c15c 28 Mar 97 G. Roelofs changed USE_ZLIB fatal exit code from PK_MEM2 to PK_MEM3 c16 20 Apr 97 J. Altman added memzero(v[]) in huft_build() c16b 29 Mar 98 C. Spieler modified DLL code for slide redirection c16c 04 Apr 99 C. Spieler fixed memory leaks when processing gets stopped because of input data errors c16d 05 Jul 99 C. Spieler take care of FLUSH() return values and stop processing in case of errors c17 31 Dec 00 C. Spieler added preliminary support for Deflate64 c17a 04 Feb 01 C. Spieler complete integration of Deflate64 support c17b 16 Feb 02 C. Spieler changed type of "extra bits" arrays and corresponding huft_build() parameter e from ush into uch, to save space c17c 9 Mar 02 C. Spieler fixed NEEDBITS() "read beyond EOF" problem with CHECK_EOF enabled c17d 23 Jul 05 C. Spieler fixed memory leaks in inflate_dynamic() when processing invalid compressed literal/ distance table data c17e 30 Mar 07 C. Spieler in inflate_dynamic(), initialize tl and td to prevent freeing unallocated huft tables when processing invalid compressed data and hitting premature EOF, do not reuse td as temp work ptr during tables decoding */ /* Inflate deflated (PKZIP's method 8 compressed) data. The compression method searches for as much of the current string of bytes (up to a length of 258) in the previous 32K bytes. If it doesn't find any matches (of at least length 3), it codes the next byte. Otherwise, it codes the length of the matched string and its distance backwards from the current position. There is a single Huffman code that codes both single bytes (called "literals") and match lengths. A second Huffman code codes the distance information, which follows a length code. Each length or distance code actually represents a base value and a number of "extra" (sometimes zero) bits to get to add to the base value. At the end of each deflated block is a special end-of-block (EOB) literal/ length code. The decoding process is basically: get a literal/length code; if EOB then done; if a literal, emit the decoded byte; if a length then get the distance and emit the referred-to bytes from the sliding window of previously emitted data. There are (currently) three kinds of inflate blocks: stored, fixed, and dynamic. The compressor outputs a chunk of data at a time and decides which method to use on a chunk-by-chunk basis. A chunk might typically be 32K to 64K, uncompressed. If the chunk is uncompressible, then the "stored" method is used. In this case, the bytes are simply stored as is, eight bits per byte, with none of the above coding. The bytes are preceded by a count, since there is no longer an EOB code. If the data are compressible, then either the fixed or dynamic methods are used. In the dynamic method, the compressed data are preceded by an encoding of the literal/length and distance Huffman codes that are to be used to decode this block. The representation is itself Huffman coded, and so is preceded by a description of that code. These code descriptions take up a little space, and so for small blocks, there is a predefined set of codes, called the fixed codes. The fixed method is used if the block ends up smaller that way (usually for quite small chunks); otherwise the dynamic method is used. In the latter case, the codes are customized to the probabilities in the current block and so can code it much better than the pre-determined fixed codes can. The Huffman codes themselves are decoded using a multi-level table lookup, in order to maximize the speed of decoding plus the speed of building the decoding tables. See the comments below that precede the lbits and dbits tuning parameters. GRR: return values(?) 0 OK 1 incomplete table 2 bad input 3 not enough memory the following return codes are passed through from FLUSH() errors 50 (PK_DISK) "overflow of output space" 80 (IZ_CTRLC) "canceled by user's request" */ /* Notes beyond the 1.93a appnote.txt: 1. Distance pointers never point before the beginning of the output stream. 2. Distance pointers can point back across blocks, up to 32k away. 3. There is an implied maximum of 7 bits for the bit length table and 15 bits for the actual data. 4. If only one code exists, then it is encoded using one bit. (Zero would be more efficient, but perhaps a little confusing.) If two codes exist, they are coded using one bit each (0 and 1). 5. There is no way of sending zero distance codes--a dummy must be sent if there are none. (History: a pre 2.0 version of PKZIP would store blocks with no distance codes, but this was discovered to be too harsh a criterion.) Valid only for 1.93a. 2.04c does allow zero distance codes, which is sent as one code of zero bits in length. 6. There are up to 286 literal/length codes. Code 256 represents the end-of-block. Note however that the static length tree defines 288 codes just to fill out the Huffman codes. Codes 286 and 287 cannot be used though, since there is no length base or extra bits defined for them. Similarily, there are up to 30 distance codes. However, static trees define 32 codes (all 5 bits) to fill out the Huffman codes, but the last two had better not show up in the data. 7. Unzip can check dynamic Huffman blocks for complete code sets. The exception is that a single code would not be complete (see #4). 8. The five bits following the block type is really the number of literal codes sent minus 257. 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits (1+6+6). Therefore, to output three times the length, you output three codes (1+1+1), whereas to output four times the same length, you only need two codes (1+3). Hmm. 10. In the tree reconstruction algorithm, Code = Code + Increment only if BitLength(i) is not zero. (Pretty obvious.) 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) 12. Note: length code 284 can represent 227-258, but length code 285 really is 258. The last length deserves its own, short code since it gets used a lot in very redundant files. The length 258 is special since 258 - 3 (the min match length) is 255. 13. The literal/length and distance code bit lengths are read as a single stream of lengths. It is possible (and advantageous) for a repeat code (16, 17, or 18) to go across the boundary between the two sets of lengths. 14. The Deflate64 (PKZIP method 9) variant of the compression algorithm differs from "classic" deflate in the following 3 aspect: a) The size of the sliding history window is expanded to 64 kByte. b) The previously unused distance codes #30 and #31 code distances from 32769 to 49152 and 49153 to 65536. Both codes take 14 bits of extra data to determine the exact position in their 16 kByte range. c) The last lit/length code #285 gets a different meaning. Instead of coding a fixed maximum match length of 258, it is used as a "generic" match length code, capable of coding any length from 3 (min match length + 0) to 65538 (min match length + 65535). This means that the length code #285 takes 16 bits (!) of uncoded extra data, added to a fixed min length of 3. Changes a) and b) would have been transparent for valid deflated data, but change c) requires to switch decoder configurations between Deflate and Deflate64 modes. */ #define PKZIP_BUG_WORKAROUND /* PKZIP 1.93a problem--live with it */ /* inflate.h must supply the uch slide[WSIZE] array, the zvoid typedef (void if (void *) is accepted, else char) and the NEXTBYTE, FLUSH() and memzero macros. If the window size is not 32K, it should also define WSIZE. If INFMOD is defined, it can include compiled functions to support the NEXTBYTE and/or FLUSH() macros. There are defaults for NEXTBYTE and FLUSH() below for use as examples of what those functions need to do. Normally, you would also want FLUSH() to compute a crc on the data. inflate.h also needs to provide these typedefs: typedef unsigned char uch; typedef unsigned short ush; typedef unsigned long ulg; This module uses the external functions malloc() and free() (and probably memset() or bzero() in the memzero() macro). Their prototypes are normally found in and . */ #define __INFLATE_C /* identifies this source module */ /* #define DEBUG */ #define INFMOD /* tell inflate.h to include code to be compiled */ #include "inflate.h" /* marker for "unused" huft code, and corresponding check macro */ #define INVALID_CODE 99 #define IS_INVALID_CODE(c) ((c) == INVALID_CODE) #ifndef WSIZE /* default is 32K resp. 64K */ # ifdef USE_DEFLATE64 # define WSIZE 65536L /* window size--must be a power of two, and */ # else /* at least 64K for PKZip's deflate64 method */ # define WSIZE 0x8000 /* window size--must be a power of two, and */ # endif /* at least 32K for zip's deflate method */ #endif /* some buffer counters must be capable of holding 64k for Deflate64 */ #if (defined(USE_DEFLATE64) && defined(INT_16BIT)) # define UINT_D64 ulg #else # define UINT_D64 unsigned #endif #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) # define wsize G._wsize /* wsize is a variable */ #else # define wsize WSIZE /* wsize is a constant */ #endif #ifndef NEXTBYTE /* default is to simply get a byte from stdin */ # define NEXTBYTE getchar() #endif #ifndef MESSAGE /* only used twice, for fixed strings--NOT general-purpose */ # define MESSAGE(str,len,flag) fprintf(stderr,(char *)(str)) #endif #ifndef FLUSH /* default is to simply write the buffer to stdout */ # define FLUSH(n) \ (((extent)fwrite(redirSlide, 1, (extent)(n), stdout) == (extent)(n)) ? \ 0 : PKDISK) #endif /* Warning: the fwrite above might not work on 16-bit compilers, since 0x8000 might be interpreted as -32,768 by the library function. When support for Deflate64 is enabled, the window size is 64K and the simple fwrite statement is definitely broken for 16-bit compilers. */ #ifndef Trace # ifdef DEBUG # define Trace(x) fprintf x # else # define Trace(x) # endif #endif /*---------------------------------------------------------------------------*/ #ifdef USE_ZLIB /* Beginning with zlib version 1.2.0, a new inflate callback interface is provided that allows tighter integration of the zlib inflate service into unzip's extraction framework. The advantages are: - uses the windows buffer supplied by the unzip code; this saves one copy process between zlib's internal decompression buffer and unzip's post-decompression output buffer and improves performance. - does not pull in unused checksum code (adler32). The preprocessor flag NO_ZLIBCALLBCK can be set to force usage of the old zlib 1.1.x interface, for testing purpose. */ #ifdef USE_ZLIB_INFLATCB # undef USE_ZLIB_INFLATCB #endif #if (defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1200 && !defined(NO_ZLIBCALLBCK)) # define USE_ZLIB_INFLATCB 1 #else # define USE_ZLIB_INFLATCB 0 #endif /* Check for incompatible combinations of zlib and Deflate64 support. */ #if defined(USE_DEFLATE64) # if !USE_ZLIB_INFLATCB #error Deflate64 is incompatible with traditional (pre-1.2.x) zlib interface! # else /* The Deflate64 callback function in the framework of zlib 1.2.x requires the inclusion of the unsupported infback9 header file: */ # include "infback9.h" # endif #endif /* USE_DEFLATE64 */ #if USE_ZLIB_INFLATCB static unsigned zlib_inCB OF((void FAR *pG, unsigned char FAR * FAR * pInbuf)); static int zlib_outCB OF((void FAR *pG, unsigned char FAR *outbuf, unsigned outcnt)); static unsigned zlib_inCB(pG, pInbuf) void FAR *pG; unsigned char FAR * FAR * pInbuf; { *pInbuf = G.inbuf; return fillinbuf(__G); } static int zlib_outCB(pG, outbuf, outcnt) void FAR *pG; unsigned char FAR *outbuf; unsigned outcnt; { #ifdef FUNZIP return flush(__G__ (ulg)(outcnt)); #else return ((G.mem_mode) ? memflush(__G__ outbuf, (ulg)(outcnt)) : flush(__G__ outbuf, (ulg)(outcnt), 0)); #endif } #endif /* USE_ZLIB_INFLATCB */ /* GRR: return values for both original inflate() and UZinflate() 0 OK 1 incomplete table(?) 2 bad input 3 not enough memory */ /**************************/ /* Function UZinflate() */ /**************************/ int UZinflate(__G__ is_defl64) __GDEF int is_defl64; /* decompress an inflated entry using the zlib routines */ { int retval = 0; /* return code: 0 = "no error" */ int err=Z_OK; #if USE_ZLIB_INFLATCB #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) wsize = G.redirect_size, redirSlide = G.redirect_buffer; else wsize = WSIZE, redirSlide = slide; #endif if (!G.inflInit) { /* local buffer for efficiency */ ZCONST char *zlib_RtVersion = zlibVersion(); /* only need to test this stuff once */ if ((zlib_RtVersion[0] != ZLIB_VERSION[0]) || (zlib_RtVersion[2] != ZLIB_VERSION[2])) { Info(slide, 0x21, ((char *)slide, "error: incompatible zlib version (expected %s, found %s)\n", ZLIB_VERSION, zlib_RtVersion)); return 3; } else if (strcmp(zlib_RtVersion, ZLIB_VERSION) != 0) Info(slide, 0x21, ((char *)slide, "warning: different zlib version (expected %s, using %s)\n", ZLIB_VERSION, zlib_RtVersion)); G.dstrm.zalloc = (alloc_func)Z_NULL; G.dstrm.zfree = (free_func)Z_NULL; G.inflInit = 1; } #ifdef USE_DEFLATE64 if (is_defl64) { Trace((stderr, "initializing inflate9()\n")); err = inflateBack9Init(&G.dstrm, redirSlide); if (err == Z_MEM_ERROR) return 3; else if (err != Z_OK) { Trace((stderr, "oops! (inflateBack9Init() err = %d)\n", err)); return 2; } G.dstrm.next_in = G.inptr; G.dstrm.avail_in = G.incnt; err = inflateBack9(&G.dstrm, zlib_inCB, &G, zlib_outCB, &G); if (err != Z_STREAM_END) { if (err == Z_DATA_ERROR || err == Z_STREAM_ERROR) { Trace((stderr, "oops! (inflateBack9() err = %d)\n", err)); retval = 2; } else if (err == Z_MEM_ERROR) { retval = 3; } else if (err == Z_BUF_ERROR) { Trace((stderr, "oops! (inflateBack9() err = %d)\n", err)); if (G.dstrm.next_in == Z_NULL) { /* input failure */ Trace((stderr, " inflateBack9() input failure\n")); retval = 2; } else { /* output write failure */ retval = (G.disk_full != 0 ? PK_DISK : IZ_CTRLC); } } else { Trace((stderr, "oops! (inflateBack9() err = %d)\n", err)); retval = 2; } } if (G.dstrm.next_in != NULL) { G.inptr = (uch *)G.dstrm.next_in; G.incnt = G.dstrm.avail_in; } err = inflateBack9End(&G.dstrm); if (err != Z_OK) { Trace((stderr, "oops! (inflateBack9End() err = %d)\n", err)); if (retval == 0) retval = 2; } } else #endif /* USE_DEFLATE64 */ { /* For the callback interface, inflate initialization has to be called before each decompression call. */ { unsigned i; int windowBits; /* windowBits = log2(wsize) */ for (i = (unsigned)wsize, windowBits = 0; !(i & 1); i >>= 1, ++windowBits); if ((unsigned)windowBits > (unsigned)15) windowBits = 15; else if (windowBits < 8) windowBits = 8; Trace((stderr, "initializing inflate()\n")); err = inflateBackInit(&G.dstrm, windowBits, redirSlide); if (err == Z_MEM_ERROR) return 3; else if (err != Z_OK) { Trace((stderr, "oops! (inflateBackInit() err = %d)\n", err)); return 2; } } G.dstrm.next_in = G.inptr; G.dstrm.avail_in = G.incnt; err = inflateBack(&G.dstrm, zlib_inCB, &G, zlib_outCB, &G); if (err != Z_STREAM_END) { if (err == Z_DATA_ERROR || err == Z_STREAM_ERROR) { Trace((stderr, "oops! (inflateBack() err = %d)\n", err)); retval = 2; } else if (err == Z_MEM_ERROR) { retval = 3; } else if (err == Z_BUF_ERROR) { Trace((stderr, "oops! (inflateBack() err = %d)\n", err)); if (G.dstrm.next_in == Z_NULL) { /* input failure */ Trace((stderr, " inflateBack() input failure\n")); retval = 2; } else { /* output write failure */ retval = (G.disk_full != 0 ? PK_DISK : IZ_CTRLC); } } else { Trace((stderr, "oops! (inflateBack() err = %d)\n", err)); retval = 2; } } if (G.dstrm.next_in != NULL) { G.inptr = (uch *)G.dstrm.next_in; G.incnt = G.dstrm.avail_in; } err = inflateBackEnd(&G.dstrm); if (err != Z_OK) { Trace((stderr, "oops! (inflateBackEnd() err = %d)\n", err)); if (retval == 0) retval = 2; } } #else /* !USE_ZLIB_INFLATCB */ int repeated_buf_err; #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) wsize = G.redirect_size, redirSlide = G.redirect_buffer; else wsize = WSIZE, redirSlide = slide; #endif G.dstrm.next_out = redirSlide; G.dstrm.avail_out = wsize; G.dstrm.next_in = G.inptr; G.dstrm.avail_in = G.incnt; if (!G.inflInit) { unsigned i; int windowBits; /* local buffer for efficiency */ ZCONST char *zlib_RtVersion = zlibVersion(); /* only need to test this stuff once */ if (zlib_RtVersion[0] != ZLIB_VERSION[0]) { Info(slide, 0x21, ((char *)slide, "error: incompatible zlib version (expected %s, found %s)\n", ZLIB_VERSION, zlib_RtVersion)); return 3; } else if (strcmp(zlib_RtVersion, ZLIB_VERSION) != 0) Info(slide, 0x21, ((char *)slide, "warning: different zlib version (expected %s, using %s)\n", ZLIB_VERSION, zlib_RtVersion)); /* windowBits = log2(wsize) */ for (i = (unsigned)wsize, windowBits = 0; !(i & 1); i >>= 1, ++windowBits); if ((unsigned)windowBits > (unsigned)15) windowBits = 15; else if (windowBits < 8) windowBits = 8; G.dstrm.zalloc = (alloc_func)Z_NULL; G.dstrm.zfree = (free_func)Z_NULL; Trace((stderr, "initializing inflate()\n")); err = inflateInit2(&G.dstrm, -windowBits); if (err == Z_MEM_ERROR) return 3; else if (err != Z_OK) Trace((stderr, "oops! (inflateInit2() err = %d)\n", err)); G.inflInit = 1; } #ifdef FUNZIP while (err != Z_STREAM_END) { #else /* !FUNZIP */ while (G.csize > 0) { Trace((stderr, "first loop: G.csize = %ld\n", G.csize)); #endif /* ?FUNZIP */ while (G.dstrm.avail_out > 0) { err = inflate(&G.dstrm, Z_PARTIAL_FLUSH); if (err == Z_DATA_ERROR) { retval = 2; goto uzinflate_cleanup_exit; } else if (err == Z_MEM_ERROR) { retval = 3; goto uzinflate_cleanup_exit; } else if (err != Z_OK && err != Z_STREAM_END) Trace((stderr, "oops! (inflate(first loop) err = %d)\n", err)); #ifdef FUNZIP if (err == Z_STREAM_END) /* "END-of-entry-condition" ? */ #else /* !FUNZIP */ if (G.csize <= 0L) /* "END-of-entry-condition" ? */ #endif /* ?FUNZIP */ break; if (G.dstrm.avail_in == 0) { if (fillinbuf(__G) == 0) { /* no "END-condition" yet, but no more data */ retval = 2; goto uzinflate_cleanup_exit; } G.dstrm.next_in = G.inptr; G.dstrm.avail_in = G.incnt; } Trace((stderr, " avail_in = %u\n", G.dstrm.avail_in)); } /* flush slide[] */ if ((retval = FLUSH(wsize - G.dstrm.avail_out)) != 0) goto uzinflate_cleanup_exit; Trace((stderr, "inside loop: flushing %ld bytes (ptr diff = %ld)\n", (long)(wsize - G.dstrm.avail_out), (long)(G.dstrm.next_out-(Bytef *)redirSlide))); G.dstrm.next_out = redirSlide; G.dstrm.avail_out = wsize; } /* no more input, so loop until we have all output */ Trace((stderr, "beginning final loop: err = %d\n", err)); repeated_buf_err = FALSE; while (err != Z_STREAM_END) { err = inflate(&G.dstrm, Z_PARTIAL_FLUSH); if (err == Z_DATA_ERROR) { retval = 2; goto uzinflate_cleanup_exit; } else if (err == Z_MEM_ERROR) { retval = 3; goto uzinflate_cleanup_exit; } else if (err == Z_BUF_ERROR) { /* DEBUG */ #ifdef FUNZIP Trace((stderr, "zlib inflate() did not detect stream end\n")); #else Trace((stderr, "zlib inflate() did not detect stream end (%s, %s)\n", G.zipfn, G.filename)); #endif if ((!repeated_buf_err) && (G.dstrm.avail_in == 0)) { /* when detecting this problem for the first time, try to provide one fake byte beyond "EOF"... */ G.dstrm.next_in = ""; G.dstrm.avail_in = 1; repeated_buf_err = TRUE; } else break; } else if (err != Z_OK && err != Z_STREAM_END) { Trace((stderr, "oops! (inflate(final loop) err = %d)\n", err)); DESTROYGLOBALS(); EXIT(PK_MEM3); } /* final flush of slide[] */ if ((retval = FLUSH(wsize - G.dstrm.avail_out)) != 0) goto uzinflate_cleanup_exit; Trace((stderr, "final loop: flushing %ld bytes (ptr diff = %ld)\n", (long)(wsize - G.dstrm.avail_out), (long)(G.dstrm.next_out-(Bytef *)redirSlide))); G.dstrm.next_out = redirSlide; G.dstrm.avail_out = wsize; } Trace((stderr, "total in = %lu, total out = %lu\n", G.dstrm.total_in, G.dstrm.total_out)); G.inptr = (uch *)G.dstrm.next_in; G.incnt = (G.inbuf + INBUFSIZ) - G.inptr; /* reset for other routines */ uzinflate_cleanup_exit: err = inflateReset(&G.dstrm); if (err != Z_OK) Trace((stderr, "oops! (inflateReset() err = %d)\n", err)); #endif /* ?USE_ZLIB_INFLATCB */ return retval; } /*---------------------------------------------------------------------------*/ #else /* !USE_ZLIB */ /* Function prototypes */ #ifndef OF # ifdef __STDC__ # define OF(a) a # else # define OF(a) () # endif #endif /* !OF */ int inflate_codes OF((__GPRO__ struct huft *tl, struct huft *td, unsigned bl, unsigned bd)); static int inflate_stored OF((__GPRO)); static int inflate_fixed OF((__GPRO)); static int inflate_dynamic OF((__GPRO)); static int inflate_block OF((__GPRO__ int *e)); /* The inflate algorithm uses a sliding 32K byte window on the uncompressed stream to find repeated byte strings. This is implemented here as a circular buffer. The index is updated simply by incrementing and then and'ing with 0x7fff (32K-1). */ /* It is left to other modules to supply the 32K area. It is assumed to be usable as if it were declared "uch slide[32768];" or as just "uch *slide;" and then malloc'ed in the latter case. The definition must be in unzip.h, included above. */ /* unsigned wp; moved to globals.h */ /* current position in slide */ /* Tables for deflate from PKZIP's appnote.txt. */ /* - Order of the bit length code lengths */ static ZCONST unsigned border[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; /* - Copy lengths for literal codes 257..285 */ #ifdef USE_DEFLATE64 static ZCONST ush cplens64[] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 3, 0, 0}; /* For Deflate64, the code 285 is defined differently. */ #else # define cplens32 cplens #endif static ZCONST ush cplens32[] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; /* note: see note #13 above about the 258 in this list. */ /* - Extra bits for literal codes 257..285 */ #ifdef USE_DEFLATE64 static ZCONST uch cplext64[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16, INVALID_CODE, INVALID_CODE}; #else # define cplext32 cplext #endif static ZCONST uch cplext32[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, INVALID_CODE, INVALID_CODE}; /* - Copy offsets for distance codes 0..29 (0..31 for Deflate64) */ static ZCONST ush cpdist[] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, #if (defined(USE_DEFLATE64) || defined(PKZIP_BUG_WORKAROUND)) 8193, 12289, 16385, 24577, 32769, 49153}; #else 8193, 12289, 16385, 24577}; #endif /* - Extra bits for distance codes 0..29 (0..31 for Deflate64) */ #ifdef USE_DEFLATE64 static ZCONST uch cpdext64[] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14}; #else # define cpdext32 cpdext #endif static ZCONST uch cpdext32[] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, #ifdef PKZIP_BUG_WORKAROUND 12, 12, 13, 13, INVALID_CODE, INVALID_CODE}; #else 12, 12, 13, 13}; #endif #ifdef PKZIP_BUG_WORKAROUND # define MAXLITLENS 288 #else # define MAXLITLENS 286 #endif #if (defined(USE_DEFLATE64) || defined(PKZIP_BUG_WORKAROUND)) # define MAXDISTS 32 #else # define MAXDISTS 30 #endif /* moved to consts.h (included in unzip.c), resp. funzip.c */ #if 0 /* And'ing with mask_bits[n] masks the lower n bits */ ZCONST unsigned near mask_bits[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; #endif /* 0 */ /* Macros for inflate() bit peeking and grabbing. The usage is: NEEDBITS(j) x = b & mask_bits[j]; DUMPBITS(j) where NEEDBITS makes sure that b has at least j bits in it, and DUMPBITS removes the bits from b. The macros use the variable k for the number of bits in b. Normally, b and k are register variables for speed and are initialized at the beginning of a routine that uses these macros from a global bit buffer and count. In order to not ask for more bits than there are in the compressed stream, the Huffman tables are constructed to only ask for just enough bits to make up the end-of-block code (value 256). Then no bytes need to be "returned" to the buffer at the end of the last block. See the huft_build() routine. Actually, the precautions mentioned above are not sufficient to prevent fetches of bits beyound the end of the last block in every case. When the last code fetched before the end-of-block code was a very short distance code (shorter than "distance-prefetch-bits" - "end-of-block code bits"), this last distance code fetch already exausts the available data. To prevent failure of extraction in this case, the "read beyond EOF" check delays the raise of the "invalid data" error until an actual overflow of "used data" is detected. This error condition is only fulfilled when the "number of available bits" counter k is found to be negative in the NEEDBITS() macro. An alternate fix for that problem adjusts the size of the distance code base table so that it does not exceed the length of the end-of-block code plus the minimum length of a distance code. This alternate fix can be enabled by defining the preprocessor symbol FIX_PAST_EOB_BY_TABLEADJUST. */ /* These have been moved to globals.h */ #if 0 ulg bb; /* bit buffer */ unsigned bk; /* bits in bit buffer */ #endif #ifndef CHECK_EOF # define CHECK_EOF /* default as of 5.13/5.2 */ #endif #ifndef CHECK_EOF # define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<=0)break;retval=1;goto cleanup_and_exit;}\ b|=((ulg)c)<>=(n);k-=(n);} /* Huffman code decoding is performed using a multi-level table lookup. The fastest way to decode is to simply build a lookup table whose size is determined by the longest code. However, the time it takes to build this table can also be a factor if the data being decoded are not very long. The most common codes are necessarily the shortest codes, so those codes dominate the decoding time, and hence the speed. The idea is you can have a shorter table that decodes the shorter, more probable codes, and then point to subsidiary tables for the longer codes. The time it costs to decode the longer codes is then traded against the time it takes to make longer tables. This results of this trade are in the variables lbits and dbits below. lbits is the number of bits the first level table for literal/ length codes can decode in one step, and dbits is the same thing for the distance codes. Subsequent tables are also less than or equal to those sizes. These values may be adjusted either when all of the codes are shorter than that, in which case the longest code length in bits is used, or when the shortest code is *longer* than the requested table size, in which case the length of the shortest code in bits is used. There are two different values for the two tables, since they code a different number of possibilities each. The literal/length table codes 286 possible values, or in a flat code, a little over eight bits. The distance table codes 30 possible values, or a little less than five bits, flat. The optimum values for speed end up being about one bit more than those, so lbits is 8+1 and dbits is 5+1. The optimum values may differ though from machine to machine, and possibly even between compilers. Your mileage may vary. */ /* bits in base literal/length lookup table */ static ZCONST unsigned lbits = 9; /* bits in base distance lookup table */ static ZCONST unsigned dbits = 6; #ifndef ASM_INFLATECODES int inflate_codes(__G__ tl, td, bl, bd) __GDEF struct huft *tl, *td; /* literal/length and distance decoder tables */ unsigned bl, bd; /* number of bits decoded by tl[] and td[] */ /* inflate (decompress) the codes in a deflated (compressed) block. Return an error code or zero if it all goes ok. */ { register unsigned e; /* table entry flag/number of extra bits */ unsigned d; /* index for copy */ UINT_D64 n; /* length for copy (deflate64: might be 64k+2) */ UINT_D64 w; /* current window position (deflate64: up to 64k) */ struct huft *t; /* pointer to table entry */ unsigned ml, md; /* masks for bl and bd bits */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ int retval = 0; /* error code returned: initialized to "no error" */ /* make local copies of globals */ b = G.bb; /* initialize bit buffer */ k = G.bk; w = G.wp; /* initialize window position */ /* inflate the coded data */ ml = mask_bits[bl]; /* precompute masks for speed */ md = mask_bits[bd]; while (1) /* do until end of block */ { NEEDBITS(bl) t = tl + ((unsigned)b & ml); while (1) { DUMPBITS(t->b) if ((e = t->e) == 32) /* then it's a literal */ { redirSlide[w++] = (uch)t->v.n; if (w == wsize) { if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit; w = 0; } break; } if (e < 31) /* then it's a length */ { /* get length of block to copy */ NEEDBITS(e) n = t->v.n + ((unsigned)b & mask_bits[e]); DUMPBITS(e) /* decode distance of block to copy */ NEEDBITS(bd) t = td + ((unsigned)b & md); while (1) { DUMPBITS(t->b) if ((e = t->e) < 32) break; if (IS_INVALID_CODE(e)) return 1; e &= 31; NEEDBITS(e) t = t->v.t + ((unsigned)b & mask_bits[e]); } NEEDBITS(e) d = (unsigned)w - t->v.n - ((unsigned)b & mask_bits[e]); DUMPBITS(e) /* do the copy */ do { #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) { /* &= w/ wsize unnecessary & wrong if redirect */ if ((UINT_D64)d >= wsize) return 1; /* invalid compressed data */ e = (unsigned)(wsize - (d > (unsigned)w ? (UINT_D64)d : w)); } else #endif e = (unsigned)(wsize - ((d &= (unsigned)(wsize-1)) > (unsigned)w ? (UINT_D64)d : w)); if ((UINT_D64)e > n) e = (unsigned)n; n -= e; #ifndef NOMEMCPY if ((unsigned)w - d >= e) /* (this test assumes unsigned comparison) */ { memcpy(redirSlide + (unsigned)w, redirSlide + d, e); w += e; d += e; } else /* do it slowly to avoid memcpy() overlap */ #endif /* !NOMEMCPY */ do { redirSlide[w++] = redirSlide[d++]; } while (--e); if (w == wsize) { if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit; w = 0; } } while (n); break; } if (e == 31) /* it's the EOB signal */ { /* sorry for this goto, but we have to exit two loops at once */ goto cleanup_decode; } if (IS_INVALID_CODE(e)) return 1; e &= 31; NEEDBITS(e) t = t->v.t + ((unsigned)b & mask_bits[e]); } } cleanup_decode: /* restore the globals from the locals */ G.wp = (unsigned)w; /* restore global window pointer */ G.bb = b; /* restore global bit buffer */ G.bk = k; cleanup_and_exit: /* done */ return retval; } #endif /* ASM_INFLATECODES */ static int inflate_stored(__G) __GDEF /* "decompress" an inflated type 0 (stored) block. */ { UINT_D64 w; /* current window position (deflate64: up to 64k!) */ unsigned n; /* number of bytes in block */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ int retval = 0; /* error code returned: initialized to "no error" */ /* make local copies of globals */ Trace((stderr, "\nstored block")); b = G.bb; /* initialize bit buffer */ k = G.bk; w = G.wp; /* initialize window position */ /* go to byte boundary */ n = k & 7; DUMPBITS(n); /* get the length and its complement */ NEEDBITS(16) n = ((unsigned)b & 0xffff); DUMPBITS(16) NEEDBITS(16) if (n != (unsigned)((~b) & 0xffff)) return 1; /* error in compressed data */ DUMPBITS(16) /* read and output the compressed data */ while (n--) { NEEDBITS(8) redirSlide[w++] = (uch)b; if (w == wsize) { if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit; w = 0; } DUMPBITS(8) } /* restore the globals from the locals */ G.wp = (unsigned)w; /* restore global window pointer */ G.bb = b; /* restore global bit buffer */ G.bk = k; cleanup_and_exit: return retval; } /* Globals for literal tables (built once) */ /* Moved to globals.h */ #if 0 struct huft *fixed_tl = (struct huft *)NULL; struct huft *fixed_td; int fixed_bl, fixed_bd; #endif static int inflate_fixed(__G) __GDEF /* decompress an inflated type 1 (fixed Huffman codes) block. We should either replace this with a custom decoder, or at least precompute the Huffman tables. */ { /* if first time, set up tables for fixed blocks */ Trace((stderr, "\nliteral block")); if (G.fixed_tl == (struct huft *)NULL) { int i; /* temporary variable */ unsigned l[288]; /* length list for huft_build */ /* literal table */ for (i = 0; i < 144; i++) l[i] = 8; for (; i < 256; i++) l[i] = 9; for (; i < 280; i++) l[i] = 7; for (; i < 288; i++) /* make a complete, but wrong code set */ l[i] = 8; G.fixed_bl = 7; #ifdef USE_DEFLATE64 if ((i = huft_build(__G__ l, 288, 257, G.cplens, G.cplext, &G.fixed_tl, &G.fixed_bl)) != 0) #else if ((i = huft_build(__G__ l, 288, 257, cplens, cplext, &G.fixed_tl, &G.fixed_bl)) != 0) #endif { G.fixed_tl = (struct huft *)NULL; return i; } /* distance table */ for (i = 0; i < MAXDISTS; i++) /* make an incomplete code set */ l[i] = 5; G.fixed_bd = 5; #ifdef USE_DEFLATE64 if ((i = huft_build(__G__ l, MAXDISTS, 0, cpdist, G.cpdext, &G.fixed_td, &G.fixed_bd)) > 1) #else if ((i = huft_build(__G__ l, MAXDISTS, 0, cpdist, cpdext, &G.fixed_td, &G.fixed_bd)) > 1) #endif { huft_free(G.fixed_tl); G.fixed_td = G.fixed_tl = (struct huft *)NULL; return i; } } /* decompress until an end-of-block code */ return inflate_codes(__G__ G.fixed_tl, G.fixed_td, G.fixed_bl, G.fixed_bd); } static int inflate_dynamic(__G) __GDEF /* decompress an inflated type 2 (dynamic Huffman codes) block. */ { unsigned i; /* temporary variables */ unsigned j; unsigned l; /* last length */ unsigned m; /* mask for bit lengths table */ unsigned n; /* number of lengths to get */ struct huft *tl = (struct huft *)NULL; /* literal/length code table */ struct huft *td = (struct huft *)NULL; /* distance code table */ struct huft *th; /* temp huft table pointer used in tables decoding */ unsigned bl; /* lookup bits for tl */ unsigned bd; /* lookup bits for td */ unsigned nb; /* number of bit length codes */ unsigned nl; /* number of literal/length codes */ unsigned nd; /* number of distance codes */ unsigned ll[MAXLITLENS+MAXDISTS]; /* lit./length and distance code lengths */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ int retval = 0; /* error code returned: initialized to "no error" */ /* make local bit buffer */ Trace((stderr, "\ndynamic block")); b = G.bb; k = G.bk; /* read in table lengths */ NEEDBITS(5) nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */ DUMPBITS(5) NEEDBITS(5) nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */ DUMPBITS(5) NEEDBITS(4) nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */ DUMPBITS(4) if (nl > MAXLITLENS || nd > MAXDISTS) return 1; /* bad lengths */ /* read in bit-length-code lengths */ for (j = 0; j < nb; j++) { NEEDBITS(3) ll[border[j]] = (unsigned)b & 7; DUMPBITS(3) } for (; j < 19; j++) ll[border[j]] = 0; /* build decoding table for trees--single level, 7 bit lookup */ bl = 7; retval = huft_build(__G__ ll, 19, 19, NULL, NULL, &tl, &bl); if (bl == 0) /* no bit lengths */ retval = 1; if (retval) { if (retval == 1) huft_free(tl); return retval; /* incomplete code set */ } /* read in literal and distance code lengths */ n = nl + nd; m = mask_bits[bl]; i = l = 0; while (i < n) { NEEDBITS(bl) j = (th = tl + ((unsigned)b & m))->b; DUMPBITS(j) j = th->v.n; if (j < 16) /* length of code in bits (0..15) */ ll[i++] = l = j; /* save last length in l */ else if (j == 16) /* repeat last length 3 to 6 times */ { NEEDBITS(2) j = 3 + ((unsigned)b & 3); DUMPBITS(2) if ((unsigned)i + j > n) { huft_free(tl); return 1; } while (j--) ll[i++] = l; } else if (j == 17) /* 3 to 10 zero length codes */ { NEEDBITS(3) j = 3 + ((unsigned)b & 7); DUMPBITS(3) if ((unsigned)i + j > n) { huft_free(tl); return 1; } while (j--) ll[i++] = 0; l = 0; } else /* j == 18: 11 to 138 zero length codes */ { NEEDBITS(7) j = 11 + ((unsigned)b & 0x7f); DUMPBITS(7) if ((unsigned)i + j > n) { huft_free(tl); return 1; } while (j--) ll[i++] = 0; l = 0; } } /* free decoding table for trees */ huft_free(tl); /* restore the global bit buffer */ G.bb = b; G.bk = k; /* build the decoding tables for literal/length and distance codes */ bl = lbits; #ifdef USE_DEFLATE64 retval = huft_build(__G__ ll, nl, 257, G.cplens, G.cplext, &tl, &bl); #else retval = huft_build(__G__ ll, nl, 257, cplens, cplext, &tl, &bl); #endif if (bl == 0) /* no literals or lengths */ retval = 1; if (retval) { if (retval == 1) { if (!uO.qflag) MESSAGE((uch *)"(incomplete l-tree) ", 21L, 1); huft_free(tl); } return retval; /* incomplete code set */ } #ifdef FIX_PAST_EOB_BY_TABLEADJUST /* Adjust the requested distance base table size so that a distance code fetch never tries to get bits behind an immediatly following end-of-block code. */ bd = (dbits <= bl+1 ? dbits : bl+1); #else bd = dbits; #endif #ifdef USE_DEFLATE64 retval = huft_build(__G__ ll + nl, nd, 0, cpdist, G.cpdext, &td, &bd); #else retval = huft_build(__G__ ll + nl, nd, 0, cpdist, cpdext, &td, &bd); #endif #ifdef PKZIP_BUG_WORKAROUND if (retval == 1) retval = 0; #endif if (bd == 0 && nl > 257) /* lengths but no distances */ retval = 1; if (retval) { if (retval == 1) { if (!uO.qflag) MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1); huft_free(td); } huft_free(tl); return retval; } /* decompress until an end-of-block code */ retval = inflate_codes(__G__ tl, td, bl, bd); cleanup_and_exit: /* free the decoding tables, return */ if (tl != (struct huft *)NULL) huft_free(tl); if (td != (struct huft *)NULL) huft_free(td); return retval; } static int inflate_block(__G__ e) __GDEF int *e; /* last block flag */ /* decompress an inflated block */ { unsigned t; /* block type */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ int retval = 0; /* error code returned: initialized to "no error" */ /* make local bit buffer */ b = G.bb; k = G.bk; /* read in last block bit */ NEEDBITS(1) *e = (int)b & 1; DUMPBITS(1) /* read in block type */ NEEDBITS(2) t = (unsigned)b & 3; DUMPBITS(2) /* restore the global bit buffer */ G.bb = b; G.bk = k; /* inflate that block type */ if (t == 2) return inflate_dynamic(__G); if (t == 0) return inflate_stored(__G); if (t == 1) return inflate_fixed(__G); /* bad block type */ retval = 2; cleanup_and_exit: return retval; } int inflate(__G__ is_defl64) __GDEF int is_defl64; /* decompress an inflated entry */ { int e; /* last block flag */ int r; /* result code */ #ifdef DEBUG unsigned h = 0; /* maximum struct huft's malloc'ed */ #endif #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) wsize = G.redirect_size, redirSlide = G.redirect_buffer; else wsize = WSIZE, redirSlide = slide; /* how they're #defined if !DLL */ #endif /* initialize window, bit buffer */ G.wp = 0; G.bk = 0; G.bb = 0; #ifdef USE_DEFLATE64 if (is_defl64) { G.cplens = cplens64; G.cplext = cplext64; G.cpdext = cpdext64; G.fixed_tl = G.fixed_tl64; G.fixed_bl = G.fixed_bl64; G.fixed_td = G.fixed_td64; G.fixed_bd = G.fixed_bd64; } else { G.cplens = cplens32; G.cplext = cplext32; G.cpdext = cpdext32; G.fixed_tl = G.fixed_tl32; G.fixed_bl = G.fixed_bl32; G.fixed_td = G.fixed_td32; G.fixed_bd = G.fixed_bd32; } #else /* !USE_DEFLATE64 */ if (is_defl64) { /* This should not happen unless UnZip is built from object files * compiled with inconsistent option setting. Handle this by * returning with "bad input" error code. */ Trace((stderr, "\nThis inflate() cannot handle Deflate64!\n")); return 2; } #endif /* ?USE_DEFLATE64 */ /* decompress until the last block */ do { #ifdef DEBUG G.hufts = 0; #endif if ((r = inflate_block(__G__ &e)) != 0) return r; #ifdef DEBUG if (G.hufts > h) h = G.hufts; #endif } while (!e); Trace((stderr, "\n%u bytes in Huffman tables (%u/entry)\n", h * (unsigned)sizeof(struct huft), (unsigned)sizeof(struct huft))); #ifdef USE_DEFLATE64 if (is_defl64) { G.fixed_tl64 = G.fixed_tl; G.fixed_bl64 = G.fixed_bl; G.fixed_td64 = G.fixed_td; G.fixed_bd64 = G.fixed_bd; } else { G.fixed_tl32 = G.fixed_tl; G.fixed_bl32 = G.fixed_bl; G.fixed_td32 = G.fixed_td; G.fixed_bd32 = G.fixed_bd; } #endif /* flush out redirSlide and return (success, unless final FLUSH failed) */ return (FLUSH(G.wp)); } int inflate_free(__G) __GDEF { if (G.fixed_tl != (struct huft *)NULL) { huft_free(G.fixed_td); huft_free(G.fixed_tl); G.fixed_td = G.fixed_tl = (struct huft *)NULL; } return 0; } #endif /* ?USE_ZLIB */ /* * GRR: moved huft_build() and huft_free() down here; used by explode() * and fUnZip regardless of whether USE_ZLIB defined or not */ /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ #define BMAX 16 /* maximum bit length of any code (16 for explode) */ #define N_MAX 288 /* maximum number of codes in any set */ int huft_build(__G__ b, n, s, d, e, t, m) __GDEF ZCONST unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ unsigned n; /* number of codes (assumed <= N_MAX) */ unsigned s; /* number of simple-valued codes (0..s-1) */ ZCONST ush *d; /* list of base values for non-simple codes */ ZCONST uch *e; /* list of extra bits for non-simple codes */ struct huft **t; /* result: starting table */ unsigned *m; /* maximum lookup bits, returns actual */ /* Given a list of code lengths and a maximum table size, make a set of tables to decode that set of codes. Return zero on success, one if the given code set is incomplete (the tables are still built in this case), two if the input is invalid (all zero length codes or an oversubscribed set of lengths), and three if not enough memory. The code with value 256 is special, and the tables are constructed so that no bits beyond that code are fetched when that code is decoded. */ { unsigned a; /* counter for codes of length k */ unsigned c[BMAX+1]; /* bit length count table */ unsigned el; /* length of EOB code (value 256) */ unsigned f; /* i repeats in table every f entries */ int g; /* maximum code length */ int h; /* table level */ register unsigned i; /* counter, current code */ register unsigned j; /* counter */ register int k; /* number of bits in current code */ int lx[BMAX+1]; /* memory for l[-1..BMAX-1] */ int *l = lx+1; /* stack of bits per table */ register unsigned *p; /* pointer into c[], b[], or v[] */ register struct huft *q; /* points to current table */ struct huft r; /* table entry for structure assignment */ struct huft *u[BMAX]; /* table stack */ unsigned v[N_MAX]; /* values in order of bit length */ register int w; /* bits before this table == (l * h) */ unsigned x[BMAX+1]; /* bit offsets, then code stack */ unsigned *xp; /* pointer into x */ int y; /* number of dummy codes added */ unsigned z; /* number of entries in current table */ /* Generate counts for each bit length */ el = n > 256 ? b[256] : BMAX; /* set length of EOB code, if any */ memzero((char *)c, sizeof(c)); p = (unsigned *)b; i = n; do { c[*p]++; p++; /* assume all entries <= BMAX */ } while (--i); if (c[0] == n) /* null input--all zero length codes */ { *t = (struct huft *)NULL; *m = 0; return 0; } /* Find minimum and maximum length, bound *m by those */ for (j = 1; j <= BMAX; j++) if (c[j]) break; k = j; /* minimum code length */ if (*m < j) *m = j; for (i = BMAX; i; i--) if (c[i]) break; g = i; /* maximum code length */ if (*m > i) *m = i; /* Adjust last length count to fill out codes, if needed */ for (y = 1 << j; j < i; j++, y <<= 1) if ((y -= c[j]) < 0) return 2; /* bad input: more codes than bits */ if ((y -= c[i]) < 0) return 2; c[i] += y; /* Generate starting offsets into the value table for each length */ x[1] = j = 0; p = c + 1; xp = x + 2; while (--i) { /* note that i == g from above */ *xp++ = (j += *p++); } /* Make a table of values in order of bit lengths */ memzero((char *)v, sizeof(v)); p = (unsigned *)b; i = 0; do { if ((j = *p++) != 0) v[x[j]++] = i; } while (++i < n); n = x[g]; /* set n to length of v */ /* Generate the Huffman codes and for each, make the table entries */ x[0] = i = 0; /* first Huffman code is zero */ p = v; /* grab values in bit order */ h = -1; /* no tables yet--level -1 */ w = l[-1] = 0; /* no bits decoded yet */ u[0] = (struct huft *)NULL; /* just to keep compilers happy */ q = (struct huft *)NULL; /* ditto */ z = 0; /* ditto */ /* go through the bit lengths (k already is bits in shortest code) */ for (; k <= g; k++) { a = c[k]; while (a--) { /* here i is the Huffman code of length k bits for value *p */ /* make tables up to required level */ while (k > w + l[h]) { w += l[h++]; /* add bits already decoded */ /* compute minimum size table less than or equal to *m bits */ z = (z = g - w) > *m ? *m : z; /* upper limit */ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ { /* too few codes for k-w bit table */ f -= a + 1; /* deduct codes from patterns left */ xp = c + k; while (++j < z) /* try smaller tables up to z bits */ { if ((f <<= 1) <= *++xp) break; /* enough codes to use up j bits */ f -= *xp; /* else deduct codes from patterns */ } } if ((unsigned)w + j > el && (unsigned)w < el) j = el - w; /* make EOB code end at table */ z = 1 << j; /* table entries for j-bit table */ l[h] = j; /* set table size in stack */ /* allocate and link in new table */ if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) == (struct huft *)NULL) { if (h) huft_free(u[0]); return 3; /* not enough memory */ } #ifdef DEBUG G.hufts += z + 1; /* track memory usage */ #endif *t = q + 1; /* link to list for huft_free() */ *(t = &(q->v.t)) = (struct huft *)NULL; u[h] = ++q; /* table starts after link */ /* connect to last table, if there is one */ if (h) { x[h] = i; /* save pattern for backing up */ r.b = (uch)l[h-1]; /* bits to dump before this table */ r.e = (uch)(32 + j); /* bits in this table */ r.v.t = q; /* pointer to this table */ j = (i & ((1 << w) - 1)) >> (w - l[h-1]); u[h-1][j] = r; /* connect to last table */ } } /* set up table entry in r */ r.b = (uch)(k - w); if (p >= v + n) r.e = INVALID_CODE; /* out of values--invalid code */ else if (*p < s) { r.e = (uch)(*p < 256 ? 32 : 31); /* 256 is end-of-block code */ r.v.n = (ush)*p++; /* simple code is just the value */ } else { r.e = e[*p - s]; /* non-simple--look up in lists */ r.v.n = d[*p++ - s]; } /* fill code-like entries with r */ f = 1 << (k - w); for (j = i >> w; j < z; j += f) q[j] = r; /* backwards increment the k-bit code i */ for (j = 1 << (k - 1); i & j; j >>= 1) i ^= j; i ^= j; /* backup over finished tables */ while ((i & ((1 << w) - 1)) != x[h]) w -= l[--h]; /* don't need to update q */ } } /* return actual size of base table */ *m = l[0]; /* Return true (1) if we were given an incomplete table */ return y != 0 && g != 1; } int huft_free(t) struct huft *t; /* table to free */ /* Free the malloc'ed tables built by huft_build(), which makes a linked list of the tables it made, with the links in a dummy first entry of each table. */ { register struct huft *p, *q; /* Go through linked list, freeing from the malloced (t[-1]) address. */ p = t; while (p != (struct huft *)NULL) { q = (--p)->v.t; free((zvoid *)p); p = q; } return 0; } Carla-2.1/data/windows/unzipfx-carla/inflate.h000066400000000000000000000033051364475620200213710ustar00rootroot00000000000000/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* inflate.h for UnZip -- by Mark Adler version c14f, 23 November 1995 */ /* Copyright history: - Starting with UnZip 5.41 of 16-April-2000, this source file is covered by the Info-Zip LICENSE cited above. - Prior versions of this source file, found in UnZip source packages up to UnZip 5.40, were put in the public domain. The original copyright note by Mark Adler was: "You can do whatever you like with this source file, though I would prefer that if you modify it and redistribute it that you include comments to that effect with your name and the date. Thank you." History: vers date who what ---- --------- -------------- ------------------------------------ c14 12 Mar 93 M. Adler made inflate.c standalone with the introduction of inflate.h. c14d 28 Aug 93 G. Roelofs replaced flush/FlushOutput with new version c14e 29 Sep 93 G. Roelofs moved everything into unzip.h; added crypt.h c14f 23 Nov 95 G. Roelofs added UNZIP_INTERNAL to accommodate newly split unzip.h */ #define UNZIP_INTERNAL #include "unzip.h" /* provides slide[], typedefs and macros */ #ifdef FUNZIP # include "crypt.h" /* provides NEXTBYTE macro for crypt version of funzip */ #endif Carla-2.1/data/windows/unzipfx-carla/match.c000066400000000000000000000367721364475620200210540ustar00rootroot00000000000000/* Copyright (c) 1990-2005 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- match.c The match() routine recursively compares a string to a "pattern" (regular expression), returning TRUE if a match is found or FALSE if not. This version is specifically for use with unzip.c: as did the previous match() routines from SEA and J. Kercheval, it leaves the case (upper, lower, or mixed) of the string alone, but converts any uppercase characters in the pattern to lowercase if indicated by the global var pInfo->lcflag (which is to say, string is assumed to have been converted to lowercase already, if such was necessary). GRR: reversed order of text, pattern in matche() (now same as match()); added ignore_case/ic flags, Case() macro. PaulK: replaced matche() with recmatch() from Zip, modified to have an ignore_case argument; replaced test frame with simpler one. --------------------------------------------------------------------------- Copyright on recmatch() from Zip's util.c (although recmatch() was almost certainly written by Mark Adler...ask me how I can tell :-) ): Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly, Kai Uwe Rommel and Igor Mandrichenko. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as all of the original files are included unmodified, that it is not sold for profit, and that this copy- right notice is retained. --------------------------------------------------------------------------- Match the pattern (wildcard) against the string (fixed): match(string, pattern, ignore_case, sepc); returns TRUE if string matches pattern, FALSE otherwise. In the pattern: `*' matches any sequence of characters (zero or more) `?' matches any single character [SET] matches any character in the specified set, [!SET] or [^SET] matches any character not in the specified set. A set is composed of characters or ranges; a range looks like ``character hyphen character'' (as in 0-9 or A-Z). [0-9a-zA-Z_] is the minimal set of characters allowed in the [..] pattern construct. Other characters are allowed (i.e., 8-bit characters) if your system will support them. To suppress the special syntactic significance of any of ``[]*?!^-\'', in- side or outside a [..] construct, and match the character exactly, precede it with a ``\'' (backslash). Note that "*.*" and "*." are treated specially under MS-DOS if DOSWILD is defined. See the DOSWILD section below for an explanation. Note also that with VMSWILD defined, '%' is used instead of '?', and sets (ranges) are delimited by () instead of []. ---------------------------------------------------------------------------*/ #define __MATCH_C /* identifies this source module */ /* define ToLower() in here (for Unix, define ToLower to be macro (using * isupper()); otherwise just use tolower() */ #define UNZIP_INTERNAL #include "unzip.h" #ifndef THEOS /* the Theos port defines its own variant of match() */ #if 0 /* this is not useful until it matches Amiga names insensitively */ #ifdef AMIGA /* some other platforms might also want to use this */ # define ANSI_CHARSET /* MOVE INTO UNZIP.H EVENTUALLY */ #endif #endif /* 0 */ #ifdef ANSI_CHARSET # ifdef ToLower # undef ToLower # endif /* uppercase letters are values 41 thru 5A, C0 thru D6, and D8 thru DE */ # define IsUpper(c) (c>=0xC0 ? c<=0xDE && c!=0xD7 : c>=0x41 && c<=0x5A) # define ToLower(c) (IsUpper((uch) c) ? (unsigned) c | 0x20 : (unsigned) c) #endif #define Case(x) (ic? ToLower(x) : (x)) #ifdef VMSWILD # define WILDCHAR '%' # define BEG_RANGE '(' # define END_RANGE ')' #else # define WILDCHAR '?' # define BEG_RANGE '[' # define END_RANGE ']' #endif #if 0 /* GRR: add this to unzip.h someday... */ #if !(defined(MSDOS) && defined(DOSWILD)) #ifdef WILD_STOP_AT_DIR #define match(s,p,ic,sc) (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic,sc) == 1) #else #define match(s,p,ic) (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic) == 1) #endif int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, int ignore_case __WDLPRO)); #endif #endif /* 0 */ static int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, int ignore_case __WDLPRO)); static char *isshexp OF((ZCONST char *p)); static int namecmp OF((ZCONST char *s1, ZCONST char *s2)); /* match() is a shell to recmatch() to return only Boolean values. */ int match(string, pattern, ignore_case __WDL) ZCONST char *string, *pattern; int ignore_case; __WDLDEF { #if (defined(MSDOS) && defined(DOSWILD)) char *dospattern; int j = strlen(pattern); /*--------------------------------------------------------------------------- Optional MS-DOS preprocessing section: compare last three chars of the wildcard to "*.*" and translate to "*" if found; else compare the last two characters to "*." and, if found, scan the non-wild string for dots. If in the latter case a dot is found, return failure; else translate the "*." to "*". In either case, continue with the normal (Unix-like) match procedure after translation. (If not enough memory, default to normal match.) This causes "a*.*" and "a*." to behave as MS-DOS users expect. ---------------------------------------------------------------------------*/ if ((dospattern = (char *)malloc(j+1)) != NULL) { strcpy(dospattern, pattern); if (!strcmp(dospattern+j-3, "*.*")) { dospattern[j-2] = '\0'; /* nuke the ".*" */ } else if (!strcmp(dospattern+j-2, "*.")) { char *p = MBSCHR(string, '.'); if (p) { /* found a dot: match fails */ free(dospattern); return 0; } dospattern[j-1] = '\0'; /* nuke the end "." */ } j = recmatch((uch *)dospattern, (uch *)string, ignore_case __WDL); free(dospattern); return j == 1; } else #endif /* MSDOS && DOSWILD */ return recmatch((uch *)pattern, (uch *)string, ignore_case __WDL) == 1; } static int recmatch(p, s, ic __WDL) ZCONST uch *p; /* sh pattern to match */ ZCONST uch *s; /* string to which to match it */ int ic; /* true for case insensitivity */ __WDLDEF /* directory sepchar for WildStopAtDir mode, or 0 */ /* Recursively compare the sh pattern p with the string s and return 1 if * they match, and 0 or 2 if they don't or if there is a syntax error in the * pattern. This routine recurses on itself no more deeply than the number * of characters in the pattern. */ { unsigned int c; /* pattern char or start of range in [-] loop */ /* Get first character, the pattern for new recmatch calls follows */ c = *p; INCSTR(p); /* If that was the end of the pattern, match if string empty too */ if (c == 0) return *s == 0; /* '?' (or '%') matches any character (but not an empty string). */ if (c == WILDCHAR) #ifdef WILD_STOP_AT_DIR /* If uO.W_flag is non-zero, it won't match '/' */ return (*s && (!sepc || *s != (uch)sepc)) ? recmatch(p, s + CLEN(s), ic, sepc) : 0; #else return *s ? recmatch(p, s + CLEN(s), ic) : 0; #endif /* '*' matches any number of characters, including zero */ #ifdef AMIGA if (c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */ c = '*', p++; #endif /* AMIGA */ if (c == '*') { #ifdef WILD_STOP_AT_DIR if (sepc) { /* check for single "*" or double "**" */ # ifdef AMIGA if ((c = p[0]) == '#' && p[1] == '?') /* "#?" is Amiga-ese for "*" */ c = '*', p++; if (c != '*') { # else /* !AMIGA */ if (*p != '*') { # endif /* ?AMIGA */ /* single "*": this doesn't match the dirsep character */ for (; *s && *s != (uch)sepc; INCSTR(s)) if ((c = recmatch(p, s, ic, sepc)) != 0) return (int)c; /* end of pattern: matched if at end of string, else continue */ if (*p == '\0') return (*s == 0); /* continue to match if at sepc in pattern, else give up */ return (*p == (uch)sepc || (*p == '\\' && p[1] == (uch)sepc)) ? recmatch(p, s, ic, sepc) : 2; } /* "**": this matches slashes */ ++p; /* move p behind the second '*' */ /* and continue with the non-W_flag code variant */ } #endif /* WILD_STOP_AT_DIR */ if (*p == 0) return 1; if (isshexp((ZCONST char *)p) == NULL) { /* Optimization for rest of pattern being a literal string: * If there are no other shell expression chars in the rest * of the pattern behind the multi-char wildcard, then just * compare the literal string tail. */ ZCONST uch *srest; srest = s + (strlen((ZCONST char *)s) - strlen((ZCONST char *)p)); if (srest - s < 0) /* remaining literal string from pattern is longer than rest * of test string, there can't be a match */ return 0; else /* compare the remaining literal pattern string with the last * bytes of the test string to check for a match */ #ifdef _MBCS { ZCONST uch *q = s; /* MBCS-aware code must not scan backwards into a string from * the end. * So, we have to move forward by character from our well-known * character position s in the test string until we have * advanced to the srest position. */ while (q < srest) INCSTR(q); /* In case the byte *srest is a trailing byte of a multibyte * character in the test string s, we have actually advanced * past the position (srest). * For this case, the match has failed! */ if (q != srest) return 0; return ((ic ? namecmp((ZCONST char *)p, (ZCONST char *)q) : strcmp((ZCONST char *)p, (ZCONST char *)q) ) == 0); } #else /* !_MBCS */ return ((ic ? namecmp((ZCONST char *)p, (ZCONST char *)srest) : strcmp((ZCONST char *)p, (ZCONST char *)srest) ) == 0); #endif /* ?_MBCS */ } else { /* pattern contains more wildcards, continue with recursion... */ for (; *s; INCSTR(s)) if ((c = recmatch(p, s, ic __WDL)) != 0) return (int)c; return 2; /* 2 means give up--match will return false */ } } /* Parse and process the list of characters and ranges in brackets */ if (c == BEG_RANGE) { int e; /* flag true if next char to be taken literally */ ZCONST uch *q; /* pointer to end of [-] group */ int r; /* flag true to match anything but the range */ if (*s == 0) /* need a character to match */ return 0; p += (r = (*p == '!' || *p == '^')); /* see if reverse */ for (q = p, e = 0; *q; INCSTR(q)) /* find closing bracket */ if (e) e = 0; else if (*q == '\\') /* GRR: change to ^ for MS-DOS, OS/2? */ e = 1; else if (*q == END_RANGE) break; if (*q != END_RANGE) /* nothing matches if bad syntax */ return 0; for (c = 0, e = (*p == '-'); p < q; INCSTR(p)) { /* go through the list */ if (!e && *p == '\\') /* set escape flag if \ */ e = 1; else if (!e && *p == '-') /* set start of range if - */ c = *(p-1); else { unsigned int cc = Case(*s); if (*(p+1) != '-') for (c = c ? c : *p; c <= *p; c++) /* compare range */ if ((unsigned)Case(c) == cc) /* typecast for MSC bug */ return r ? 0 : recmatch(q + 1, s + 1, ic __WDL); c = e = 0; /* clear range, escape flags */ } } return r ? recmatch(q + CLEN(q), s + CLEN(s), ic __WDL) : 0; /* bracket match failed */ } /* if escape ('\\'), just compare next character */ if (c == '\\' && (c = *p++) == 0) /* if \ at end, then syntax error */ return 0; /* just a character--compare it */ #ifdef QDOS return QMatch(Case((uch)c), Case(*s)) ? recmatch(p, s + CLEN(s), ic __WDL) : 0; #else return Case((uch)c) == Case(*s) ? recmatch(p, s + CLEN(s), ic __WDL) : 0; #endif } /* end function recmatch() */ static char *isshexp(p) ZCONST char *p; /* If p is a sh expression, a pointer to the first special character is returned. Otherwise, NULL is returned. */ { for (; *p; INCSTR(p)) if (*p == '\\' && *(p+1)) p++; else if (*p == WILDCHAR || *p == '*' || *p == BEG_RANGE) return (char *)p; return NULL; } /* end function isshexp() */ static int namecmp(s1, s2) ZCONST char *s1, *s2; { int d; for (;;) { d = (int)ToLower((uch)*s1) - (int)ToLower((uch)*s2); if (d || *s1 == 0 || *s2 == 0) return d; s1++; s2++; } } /* end function namecmp() */ #endif /* !THEOS */ int iswild(p) /* originally only used for stat()-bug workaround in */ ZCONST char *p; /* VAX C, Turbo/Borland C, Watcom C, Atari MiNT libs; */ { /* now used in process_zipfiles() as well */ for (; *p; INCSTR(p)) if (*p == '\\' && *(p+1)) ++p; #ifdef THEOS else if (*p == '?' || *p == '*' || *p=='#'|| *p == '@') #else /* !THEOS */ #ifdef VMS else if (*p == '%' || *p == '*') #else /* !VMS */ #ifdef AMIGA else if (*p == '?' || *p == '*' || (*p=='#' && p[1]=='?') || *p == '[') #else /* !AMIGA */ else if (*p == '?' || *p == '*' || *p == '[') #endif /* ?AMIGA */ #endif /* ?VMS */ #endif /* ?THEOS */ #ifdef QDOS return (int)p; #else return TRUE; #endif return FALSE; } /* end function iswild() */ #ifdef TEST_MATCH #define put(s) {fputs(s,stdout); fflush(stdout);} #ifdef main # undef main #endif int main(int argc, char **argv) { char pat[256], str[256]; for (;;) { put("Pattern (return to exit): "); gets(pat); if (!pat[0]) break; for (;;) { put("String (return for new pattern): "); gets(str); if (!str[0]) break; printf("Case sensitive: %s insensitive: %s\n", match(str, pat, 0) ? "YES" : "NO", match(str, pat, 1) ? "YES" : "NO"); } } EXIT(0); } #endif /* TEST_MATCH */ Carla-2.1/data/windows/unzipfx-carla/process.c000066400000000000000000003250071364475620200214260ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- process.c This file contains the top-level routines for processing multiple zipfiles. Contains: process_zipfiles() free_G_buffers() do_seekable() file_size() rec_find() find_ecrec64() find_ecrec() process_zip_cmmnt() process_cdir_file_hdr() get_cdir_ent() process_local_file_hdr() getZip64Data() ef_scan_for_izux() getRISCOSexfield() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #ifdef WINDLL # ifdef POCKET_UNZIP # include "wince/intrface.h" # else # include "windll/windll.h" # endif #endif #if defined(DYNALLOC_CRCTAB) || defined(UNICODE_SUPPORT) # include "crc32.h" #endif #include "unzipfx/appDetails.h" static int do_seekable OF((__GPRO__ int lastchance)); #ifdef DO_SAFECHECK_2GB # ifdef USE_STRM_INPUT static zoff_t file_size OF((FILE *file)); # else static zoff_t file_size OF((int fh)); # endif #endif /* DO_SAFECHECK_2GB */ static int rec_find OF((__GPRO__ zoff_t, char *, int)); static int find_ecrec64 OF((__GPRO__ zoff_t searchlen)); static int find_ecrec OF((__GPRO__ zoff_t searchlen)); static int process_zip_cmmnt OF((__GPRO)); static int get_cdir_ent OF((__GPRO)); #ifdef IZ_HAVE_UXUIDGID static int read_ux3_value OF((ZCONST uch *dbuf, unsigned uidgid_sz, ulg *p_uidgid)); #endif /* IZ_HAVE_UXUIDGID */ static ZCONST char Far CannotAllocateBuffers[] = "error: cannot allocate unzip buffers\n"; #ifdef SFX static ZCONST char Far CannotFindMyself[] = "unzipsfx: cannot find myself! [%s]\n"; # ifdef CHEAP_SFX_AUTORUN static ZCONST char Far AutorunPrompt[] = "\nAuto-run command: %s\nExecute this command? [y/n] "; static ZCONST char Far NotAutoRunning[] = "Not executing auto-run command."; # endif #else /* !SFX */ /* process_zipfiles() strings */ # if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) static ZCONST char Far WarnInvalidTZ[] = "Warning: TZ environment variable not found, cannot use UTC times!!\n"; # endif # if !(defined(UNIX) || defined(AMIGA)) static ZCONST char Far CannotFindWildcardMatch[] = "%s: cannot find any matches for wildcard specification \"%s\".\n"; # endif /* !(UNIX || AMIGA) */ static ZCONST char Far FilesProcessOK[] = "%d archive%s successfully processed.\n"; static ZCONST char Far ArchiveWarning[] = "%d archive%s had warnings but no fatal errors.\n"; static ZCONST char Far ArchiveFatalError[] = "%d archive%s had fatal errors.\n"; static ZCONST char Far FileHadNoZipfileDir[] = "%d file%s had no zipfile directory.\n"; static ZCONST char Far ZipfileWasDir[] = "1 \"zipfile\" was a directory.\n"; static ZCONST char Far ManyZipfilesWereDir[] = "%d \"zipfiles\" were directories.\n"; static ZCONST char Far NoZipfileFound[] = "No zipfiles found.\n"; /* do_seekable() strings */ # ifdef UNIX static ZCONST char Far CannotFindZipfileDirMsg[] = "%s: cannot find zipfile directory in one of %s or\n\ %s%s.zip, and cannot find %s, period.\n"; static ZCONST char Far CannotFindEitherZipfile[] = "%s: cannot find or open %s, %s.zip or %s.\n"; # else /* !UNIX */ static ZCONST char Far CannotFindZipfileDirMsg[] = "%s: cannot find zipfile directory in %s,\n\ %sand cannot find %s, period.\n"; # ifdef VMS static ZCONST char Far CannotFindEitherZipfile[] = "%s: cannot find %s (%s).\n"; # else /* !VMS */ static ZCONST char Far CannotFindEitherZipfile[] = "%s: cannot find either %s or %s.\n"; # endif /* ?VMS */ # endif /* ?UNIX */ extern ZCONST char Far Zipnfo[]; /* in unzip.c */ #ifndef WINDLL static ZCONST char Far Unzip[] = "unzip"; #else static ZCONST char Far Unzip[] = "UnZip DLL"; #endif #ifdef DO_SAFECHECK_2GB static ZCONST char Far ZipfileTooBig[] = "Trying to read large file (> 2 GiB) without large file support\n"; #endif /* DO_SAFECHECK_2GB */ static ZCONST char Far MaybeExe[] = "note: %s may be a plain executable, not an archive\n"; static ZCONST char Far CentDirNotInZipMsg[] = "\n\ [%s]:\n\ Zipfile is disk %lu of a multi-disk archive, and this is not the disk on\n\ which the central zipfile directory begins (disk %lu).\n"; static ZCONST char Far EndCentDirBogus[] = "\nwarning [%s]: end-of-central-directory record claims this\n\ is disk %lu but that the central directory starts on disk %lu; this is a\n\ contradiction. Attempting to process anyway.\n"; # ifdef NO_MULTIPART static ZCONST char Far NoMultiDiskArcSupport[] = "\nerror [%s]: zipfile is part of multi-disk archive\n\ (sorry, not yet supported).\n"; static ZCONST char Far MaybePakBug[] = "warning [%s]:\ zipfile claims to be 2nd disk of a 2-part archive;\n\ attempting to process anyway. If no further errors occur, this archive\n\ was probably created by PAK v2.51 or earlier. This bug was reported to\n\ NoGate in March 1991 and was supposed to have been fixed by mid-1991; as\n\ of mid-1992 it still hadn't been. (If further errors do occur, archive\n\ was probably created by PKZIP 2.04c or later; UnZip does not yet support\n\ multi-part archives.)\n"; # else static ZCONST char Far MaybePakBug[] = "warning [%s]:\ zipfile claims to be last disk of a multi-part archive;\n\ attempting to process anyway, assuming all parts have been concatenated\n\ together in order. Expect \"errors\" and warnings...true multi-part support\ \n doesn't exist yet (coming soon).\n"; # endif static ZCONST char Far ExtraBytesAtStart[] = "warning [%s]: %s extra byte%s at beginning or within zipfile\n\ (attempting to process anyway)\n"; #endif /* ?SFX */ #if ((!defined(WINDLL) && !defined(SFX)) || !defined(NO_ZIPINFO)) static ZCONST char Far LogInitline[] = "Archive: %s\n"; #endif static ZCONST char Far MissingBytes[] = "error [%s]: missing %s bytes in zipfile\n\ (attempting to process anyway)\n"; static ZCONST char Far NullCentDirOffset[] = "error [%s]: NULL central directory offset\n\ (attempting to process anyway)\n"; static ZCONST char Far ZipfileEmpty[] = "warning [%s]: zipfile is empty\n"; static ZCONST char Far CentDirStartNotFound[] = "error [%s]: start of central directory not found;\n\ zipfile corrupt.\n%s"; static ZCONST char Far Cent64EndSigSearchErr[] = "fatal error: read failure while seeking for End-of-centdir-64 signature.\n\ This zipfile is corrupt.\n"; static ZCONST char Far Cent64EndSigSearchOff[] = "error: End-of-centdir-64 signature not where expected (prepended bytes?)\n\ (attempting to process anyway)\n"; #ifndef SFX static ZCONST char Far CentDirTooLong[] = "error [%s]: reported length of central directory is\n\ %s bytes too long (Atari STZip zipfile? J.H.Holm ZIPSPLIT 1.1\n\ zipfile?). Compensating...\n"; static ZCONST char Far CentDirEndSigNotFound[] = "\ End-of-central-directory signature not found. Either this file is not\n\ a zipfile, or it constitutes one disk of a multi-part archive. In the\n\ latter case the central directory and zipfile comment will be found on\n\ the last disk(s) of this archive.\n"; #else /* SFX */ static ZCONST char Far CentDirEndSigNotFound[] = " End-of-central-directory signature not found.\n"; #endif /* ?SFX */ #ifdef TIMESTAMP static ZCONST char Far ZipTimeStampFailed[] = "warning: cannot set time for %s\n"; static ZCONST char Far ZipTimeStampSuccess[] = "Updated time stamp for %s.\n"; #endif static ZCONST char Far ZipfileCommTrunc1[] = "\ncaution: zipfile comment truncated\n"; #ifndef NO_ZIPINFO static ZCONST char Far NoZipfileComment[] = "There is no zipfile comment.\n"; static ZCONST char Far ZipfileCommentDesc[] = "The zipfile comment is %u bytes long and contains the following text:\n"; static ZCONST char Far ZipfileCommBegin[] = "======================== zipfile comment begins\ ==========================\n"; static ZCONST char Far ZipfileCommEnd[] = "========================= zipfile comment ends\ ===========================\n"; static ZCONST char Far ZipfileCommTrunc2[] = "\n The zipfile comment is truncated.\n"; #endif /* !NO_ZIPINFO */ #ifdef UNICODE_SUPPORT static ZCONST char Far UnicodeVersionError[] = "\nwarning: Unicode Path version > 1\n"; static ZCONST char Far UnicodeMismatchError[] = "\nwarning: Unicode Path checksum invalid\n"; #endif /*******************************/ /* Function process_zipfiles() */ /*******************************/ int process_zipfiles(__G) /* return PK-type error code */ __GDEF { #ifndef SFX char *lastzipfn = (char *)NULL; int NumWinFiles, NumLoseFiles, NumWarnFiles; int NumMissDirs, NumMissFiles; #endif int error=0, error_in_archive=0; /*--------------------------------------------------------------------------- Start by allocating buffers and (re)constructing the various PK signature strings. ---------------------------------------------------------------------------*/ G.inbuf = (uch *)malloc(INBUFSIZ + 4); /* 4 extra for hold[] (below) */ G.outbuf = (uch *)malloc(OUTBUFSIZ + 1); /* 1 extra for string term. */ if ((G.inbuf == (uch *)NULL) || (G.outbuf == (uch *)NULL)) { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotAllocateBuffers))); return(PK_MEM); } G.hold = G.inbuf + INBUFSIZ; /* to check for boundary-spanning sigs */ #ifndef VMS /* VMS uses its own buffer scheme for textmode flush(). */ #ifdef SMALL_MEM G.outbuf2 = G.outbuf+RAWBUFSIZ; /* never changes */ #endif #endif /* !VMS */ #if 0 /* CRC_32_TAB has been NULLified by CONSTRUCTGLOBALS !!!! */ /* allocate the CRC table later when we know we can read zipfile data */ CRC_32_TAB = NULL; #endif /* 0 */ /* finish up initialization of magic signature strings */ local_hdr_sig[0] /* = extd_local_sig[0] */ = /* ASCII 'P', */ central_hdr_sig[0] = end_central_sig[0] = /* not EBCDIC */ end_centloc64_sig[0] = end_central64_sig[0] = 0x50; local_hdr_sig[1] /* = extd_local_sig[1] */ = /* ASCII 'K', */ central_hdr_sig[1] = end_central_sig[1] = /* not EBCDIC */ end_centloc64_sig[1] = end_central64_sig[1] = 0x4B; /*--------------------------------------------------------------------------- Make sure timezone info is set correctly; localtime() returns GMT on some OSes (e.g., Solaris 2.x) if this isn't done first. The ifdefs around tzset() were initially copied from dos_to_unix_time() in fileio.c. They may still be too strict; any listed OS that supplies tzset(), regardless of whether the function does anything, should be removed from the ifdefs. ---------------------------------------------------------------------------*/ #if (defined(WIN32) && defined(USE_EF_UT_TIME)) /* For the Win32 environment, we may have to "prepare" the environment prior to the tzset() call, to work around tzset() implementation bugs. */ iz_w32_prepareTZenv(); #endif #if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) # ifndef VALID_TIMEZONE # define VALID_TIMEZONE(tmp) \ (((tmp = getenv("TZ")) != NULL) && (*tmp != '\0')) # endif { char *p; G.tz_is_valid = VALID_TIMEZONE(p); # ifndef SFX if (!G.tz_is_valid) { Info(slide, 0x401, ((char *)slide, LoadFarString(WarnInvalidTZ))); error_in_archive = error = PK_WARN; } # endif /* !SFX */ } #endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */ /* For systems that do not have tzset() but supply this function using another name (_tzset() or something similar), an appropiate "#define tzset ..." should be added to the system specifc configuration section. */ #if (!defined(T20_VMS) && !defined(MACOS) && !defined(RISCOS) && !defined(QDOS)) #if (!defined(BSD) && !defined(MTS) && !defined(CMS_MVS) && !defined(TANDEM)) tzset(); #endif #endif /* Initialize UnZip's built-in pseudo hard-coded "ISO <--> OEM" translation, depending on the detected codepage setup. */ #ifdef NEED_ISO_OEM_INIT prepare_ISO_OEM_translat(__G); #endif /*--------------------------------------------------------------------------- Initialize the internal flag holding the mode of processing "overwrite existing file" cases. We do not use the calling interface flags directly because the overwrite mode may be changed by user interaction while processing archive files. Such a change should not affect the option settings as passed through the DLL calling interface. In case of conflicting options, the 'safer' flag uO.overwrite_none takes precedence. ---------------------------------------------------------------------------*/ G.overwrite_mode = (uO.overwrite_none ? OVERWRT_NEVER : (uO.overwrite_all ? OVERWRT_ALWAYS : OVERWRT_QUERY)); /*--------------------------------------------------------------------------- Match (possible) wildcard zipfile specification with existing files and attempt to process each. If no hits, try again after appending ".zip" suffix. If still no luck, give up. ---------------------------------------------------------------------------*/ #ifdef SFX if ((error = do_seekable(__G__ 0)) == PK_NOZIP) { #ifdef EXE_EXTENSION int len=strlen(G.argv0); /* append .exe if appropriate; also .sfx? */ if ( (G.zipfn = (char *)malloc(len+sizeof(EXE_EXTENSION))) != (char *)NULL ) { strcpy(G.zipfn, G.argv0); strcpy(G.zipfn+len, EXE_EXTENSION); error = do_seekable(__G__ 0); free(G.zipfn); G.zipfn = G.argv0; /* for "cannot find myself" message only */ } #endif /* EXE_EXTENSION */ #ifdef WIN32 G.zipfn = G.argv0; /* for "cannot find myself" message only */ #endif } if (error) { if (error == IZ_DIR) error_in_archive = PK_NOZIP; else error_in_archive = error; if (error == PK_NOZIP) Info(slide, 1, ((char *)slide, LoadFarString(CannotFindMyself), G.zipfn)); } #ifdef CHEAP_SFX_AUTORUN if (G.autorun_command[0] && !uO.qflag) { /* NO autorun without prompt! */ Info(slide, 0x81, ((char *)slide, LoadFarString(AutorunPrompt), FnFilter1(G.autorun_command))); if (fgets(G.answerbuf, 9, stdin) != (char *)NULL && toupper(*G.answerbuf) == 'Y') system(G.autorun_command); else Info(slide, 1, ((char *)slide, LoadFarString(NotAutoRunning))); } #endif /* CHEAP_SFX_AUTORUN */ int sfx_app_ret = sfx_app_autorun_now(); #else /* !SFX */ NumWinFiles = NumLoseFiles = NumWarnFiles = 0; NumMissDirs = NumMissFiles = 0; while ((G.zipfn = do_wild(__G__ G.wildzipfn)) != (char *)NULL) { Trace((stderr, "do_wild( %s ) returns %s\n", G.wildzipfn, G.zipfn)); lastzipfn = G.zipfn; /* print a blank line between the output of different zipfiles */ if (!uO.qflag && error != PK_NOZIP && error != IZ_DIR #ifdef TIMESTAMP && (!uO.T_flag || uO.zipinfo_mode) #endif && (NumWinFiles+NumLoseFiles+NumWarnFiles+NumMissFiles) > 0) (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); if ((error = do_seekable(__G__ 0)) == PK_WARN) ++NumWarnFiles; else if (error == IZ_DIR) ++NumMissDirs; else if (error == PK_NOZIP) ++NumMissFiles; else if (error != PK_OK) ++NumLoseFiles; else ++NumWinFiles; Trace((stderr, "do_seekable(0) returns %d\n", error)); if (error != IZ_DIR && error > error_in_archive) error_in_archive = error; #ifdef WINDLL if (error == IZ_CTRLC) { free_G_buffers(__G); return error; } #endif } /* end while-loop (wildcard zipfiles) */ if ((NumWinFiles + NumWarnFiles + NumLoseFiles) == 0 && (NumMissDirs + NumMissFiles) == 1 && lastzipfn != (char *)NULL) { #if (!defined(UNIX) && !defined(AMIGA)) /* filenames with wildcard characters */ if (iswild(G.wildzipfn)) { if (iswild(lastzipfn)) { NumMissDirs = NumMissFiles = 0; error_in_archive = PK_COOL; if (uO.qflag < 3) Info(slide, 0x401, ((char *)slide, LoadFarString(CannotFindWildcardMatch), LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), G.wildzipfn)); } } else #endif { #ifndef VMS /* 2004-11-24 SMS. * VMS has already tried a default file type of ".zip" in * do_wild(), so adding ZSUFX here only causes confusion by * corrupting some valid (though nonexistent) file names. * Complaining below about "fred;4.zip" is unlikely to be * helpful to the victim. */ /* 2005-08-14 Chr. Spieler * Although we already "know" the failure result, we call * do_seekable() again with the same zipfile name (and the * lastchance flag set), just to trigger the error report... */ #if defined(UNIX) || defined(QDOS) char *p = #endif strcpy(lastzipfn + strlen(lastzipfn), ZSUFX); #endif /* !VMS */ G.zipfn = lastzipfn; NumMissDirs = NumMissFiles = 0; error_in_archive = PK_COOL; #if defined(UNIX) || defined(QDOS) /* only Unix has case-sensitive filesystems */ /* Well FlexOS (sometimes) also has them, but support is per media */ /* and a pig to code for, so treat as case insensitive for now */ /* we do this under QDOS to check for .zip as well as _zip */ if ((error = do_seekable(__G__ 0)) == PK_NOZIP || error == IZ_DIR) { if (error == IZ_DIR) ++NumMissDirs; strcpy(p, ALT_ZSUFX); error = do_seekable(__G__ 1); } #else error = do_seekable(__G__ 1); #endif Trace((stderr, "do_seekable(1) returns %d\n", error)); switch (error) { case PK_WARN: ++NumWarnFiles; break; case IZ_DIR: ++NumMissDirs; error = PK_NOZIP; break; case PK_NOZIP: /* increment again => bug: "1 file had no zipfile directory." */ /* ++NumMissFiles */ ; break; default: if (error) ++NumLoseFiles; else ++NumWinFiles; break; } if (error > error_in_archive) error_in_archive = error; #ifdef WINDLL if (error == IZ_CTRLC) { free_G_buffers(__G); return error; } #endif } } #endif /* ?SFX */ /*--------------------------------------------------------------------------- Print summary of all zipfiles, assuming zipfile spec was a wildcard (no need for a summary if just one zipfile). ---------------------------------------------------------------------------*/ #ifndef SFX if (iswild(G.wildzipfn) && uO.qflag < 3 #ifdef TIMESTAMP && !(uO.T_flag && !uO.zipinfo_mode && uO.qflag > 1) #endif ) { if ((NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1) #ifdef TIMESTAMP && !(uO.T_flag && !uO.zipinfo_mode && uO.qflag) #endif && !(uO.tflag && uO.qflag > 1)) (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0x401); if ((NumWinFiles > 1) || (NumWinFiles == 1 && NumMissDirs + NumMissFiles + NumLoseFiles + NumWarnFiles > 0)) Info(slide, 0x401, ((char *)slide, LoadFarString(FilesProcessOK), NumWinFiles, (NumWinFiles == 1)? " was" : "s were")); if (NumWarnFiles > 0) Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveWarning), NumWarnFiles, (NumWarnFiles == 1)? "" : "s")); if (NumLoseFiles > 0) Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveFatalError), NumLoseFiles, (NumLoseFiles == 1)? "" : "s")); if (NumMissFiles > 0) Info(slide, 0x401, ((char *)slide, LoadFarString(FileHadNoZipfileDir), NumMissFiles, (NumMissFiles == 1)? "" : "s")); if (NumMissDirs == 1) Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileWasDir))); else if (NumMissDirs > 0) Info(slide, 0x401, ((char *)slide, LoadFarString(ManyZipfilesWereDir), NumMissDirs)); if (NumWinFiles + NumLoseFiles + NumWarnFiles == 0) Info(slide, 0x401, ((char *)slide, LoadFarString(NoZipfileFound))); } #endif /* !SFX */ /* free allocated memory */ free_G_buffers(__G); return sfx_app_ret; } /* end function process_zipfiles() */ /*****************************/ /* Function free_G_buffers() */ /*****************************/ void free_G_buffers(__G) /* releases all memory allocated in global vars */ __GDEF { #ifndef SFX unsigned i; #endif #ifdef SYSTEM_SPECIFIC_DTOR SYSTEM_SPECIFIC_DTOR(__G); #endif inflate_free(__G); checkdir(__G__ (char *)NULL, END); #ifdef DYNALLOC_CRCTAB if (CRC_32_TAB) { free_crc_table(); CRC_32_TAB = NULL; } #endif if (G.key != (char *)NULL) { free(G.key); G.key = (char *)NULL; } if (G.extra_field != (uch *)NULL) { free(G.extra_field); G.extra_field = (uch *)NULL; } #if (!defined(VMS) && !defined(SMALL_MEM)) /* VMS uses its own buffer scheme for textmode flush() */ if (G.outbuf2) { free(G.outbuf2); /* malloc'd ONLY if unshrink and -a */ G.outbuf2 = (uch *)NULL; } #endif if (G.outbuf) free(G.outbuf); if (G.inbuf) free(G.inbuf); G.inbuf = G.outbuf = (uch *)NULL; #ifdef UNICODE_SUPPORT if (G.filename_full) { free(G.filename_full); G.filename_full = (char *)NULL; G.fnfull_bufsize = 0; } #endif /* UNICODE_SUPPORT */ #ifndef SFX for (i = 0; i < DIR_BLKSIZ; i++) { if (G.info[i].cfilname != (char Far *)NULL) { zffree(G.info[i].cfilname); G.info[i].cfilname = (char Far *)NULL; } } #endif #ifdef MALLOC_WORK if (G.area.Slide) { free(G.area.Slide); G.area.Slide = (uch *)NULL; } #endif } /* end function free_G_buffers() */ /**************************/ /* Function do_seekable() */ /**************************/ static int do_seekable(__G__ lastchance) /* return PK-type error code */ __GDEF int lastchance; { #ifndef SFX /* static int no_ecrec = FALSE; SKM: moved to globals.h */ int maybe_exe=FALSE; int too_weird_to_continue=FALSE; #ifdef TIMESTAMP time_t uxstamp; ulg nmember = 0L; #endif #endif int error=0, error_in_archive; /*--------------------------------------------------------------------------- Open the zipfile for reading in BINARY mode to prevent CR/LF translation, which would corrupt the bit streams. ---------------------------------------------------------------------------*/ if (SSTAT(G.zipfn, &G.statbuf) || #ifdef THEOS (error = S_ISLIB(G.statbuf.st_mode)) != 0 || #endif (error = S_ISDIR(G.statbuf.st_mode)) != 0) { #ifndef SFX if (lastchance && (uO.qflag < 3)) { #if defined(UNIX) || defined(QDOS) if (G.no_ecrec) Info(slide, 1, ((char *)slide, LoadFarString(CannotFindZipfileDirMsg), LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), G.wildzipfn, uO.zipinfo_mode? " " : "", G.wildzipfn, G.zipfn)); else Info(slide, 1, ((char *)slide, LoadFarString(CannotFindEitherZipfile), LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), G.wildzipfn, G.wildzipfn, G.zipfn)); #else /* !(UNIX || QDOS) */ if (G.no_ecrec) Info(slide, 0x401, ((char *)slide, LoadFarString(CannotFindZipfileDirMsg), LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), G.wildzipfn, uO.zipinfo_mode? " " : "", G.zipfn)); else #ifdef VMS Info(slide, 0x401, ((char *)slide, LoadFarString(CannotFindEitherZipfile), LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), G.wildzipfn, (*G.zipfn ? G.zipfn : vms_msg_text()))); #else /* !VMS */ Info(slide, 0x401, ((char *)slide, LoadFarString(CannotFindEitherZipfile), LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), G.wildzipfn, G.zipfn)); #endif /* ?VMS */ #endif /* ?(UNIX || QDOS) */ } #endif /* !SFX */ return error? IZ_DIR : PK_NOZIP; } G.ziplen = G.statbuf.st_size; #ifndef SFX #if defined(UNIX) || defined(DOS_OS2_W32) || defined(THEOS) if (G.statbuf.st_mode & S_IEXEC) /* no extension on Unix exes: might */ maybe_exe = TRUE; /* find unzip, not unzip.zip; etc. */ #endif #endif /* !SFX */ #ifdef VMS if (check_format(__G)) /* check for variable-length format */ return PK_ERR; #endif if (open_input_file(__G)) /* this should never happen, given */ return PK_NOZIP; /* the stat() test above, but... */ #ifdef DO_SAFECHECK_2GB /* Need more care: Do not trust the size returned by stat() but determine it by reading beyond the end of the file. */ G.ziplen = file_size(G.zipfd); if (G.ziplen == EOF) { Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileTooBig))); /* printf( " We need a better error message for: 64-bit file, 32-bit program.\n"); */ CLOSE_INFILE(); return IZ_ERRBF; } #endif /* DO_SAFECHECK_2GB */ /*--------------------------------------------------------------------------- Find and process the end-of-central-directory header. UnZip need only check last 65557 bytes of zipfile: comment may be up to 65535, end-of- central-directory record is 18 bytes, and signature itself is 4 bytes; add some to allow for appended garbage. Since ZipInfo is often used as a debugging tool, search the whole zipfile if zipinfo_mode is true. ---------------------------------------------------------------------------*/ G.cur_zipfile_bufstart = 0; G.inptr = G.inbuf; #if ((!defined(WINDLL) && !defined(SFX)) || !defined(NO_ZIPINFO)) # if (!defined(WINDLL) && !defined(SFX)) if ( (!uO.zipinfo_mode && !uO.qflag # ifdef TIMESTAMP && !uO.T_flag # endif ) # ifndef NO_ZIPINFO || (uO.zipinfo_mode && uO.hflag) # endif ) # else /* not (!WINDLL && !SFX) ==> !NO_ZIPINFO !! */ if (uO.zipinfo_mode && uO.hflag) # endif /* if..else..: (!WINDLL && !SFX) */ # ifdef WIN32 /* Win32 console may require codepage conversion for G.zipfn */ Info(slide, 0, ((char *)slide, LoadFarString(LogInitline), FnFilter1(G.zipfn))); # else Info(slide, 0, ((char *)slide, LoadFarString(LogInitline), G.zipfn)); # endif #endif /* (!WINDLL && !SFX) || !NO_ZIPINFO */ if ( (error_in_archive = find_ecrec(__G__ #ifndef NO_ZIPINFO uO.zipinfo_mode ? G.ziplen : #endif MIN(G.ziplen, 66000L))) > PK_WARN ) { CLOSE_INFILE(); #ifdef SFX ++lastchance; /* avoid picky compiler warnings */ return error_in_archive; #else if (maybe_exe) Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeExe), G.zipfn)); if (lastchance) return error_in_archive; else { G.no_ecrec = TRUE; /* assume we found wrong file: e.g., */ return PK_NOZIP; /* unzip instead of unzip.zip */ } #endif /* ?SFX */ } if ((uO.zflag > 0) && !uO.zipinfo_mode) { /* unzip: zflag = comment ONLY */ CLOSE_INFILE(); return error_in_archive; } /*--------------------------------------------------------------------------- Test the end-of-central-directory info for incompatibilities (multi-disk archives) or inconsistencies (missing or extra bytes in zipfile). ---------------------------------------------------------------------------*/ #ifdef NO_MULTIPART error = !uO.zipinfo_mode && (G.ecrec.number_this_disk == 1) && (G.ecrec.num_disk_start_cdir == 1); #else error = !uO.zipinfo_mode && (G.ecrec.number_this_disk != 0); #endif #ifndef SFX if (uO.zipinfo_mode && G.ecrec.number_this_disk != G.ecrec.num_disk_start_cdir) { if (G.ecrec.number_this_disk > G.ecrec.num_disk_start_cdir) { Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirNotInZipMsg), G.zipfn, (ulg)G.ecrec.number_this_disk, (ulg)G.ecrec.num_disk_start_cdir)); error_in_archive = PK_FIND; too_weird_to_continue = TRUE; } else { Info(slide, 0x401, ((char *)slide, LoadFarString(EndCentDirBogus), G.zipfn, (ulg)G.ecrec.number_this_disk, (ulg)G.ecrec.num_disk_start_cdir)); error_in_archive = PK_WARN; } #ifdef NO_MULTIPART /* concatenation of multiple parts works in some cases */ } else if (!uO.zipinfo_mode && !error && G.ecrec.number_this_disk != 0) { Info(slide, 0x401, ((char *)slide, LoadFarString(NoMultiDiskArcSupport), G.zipfn)); error_in_archive = PK_FIND; too_weird_to_continue = TRUE; #endif } if (!too_weird_to_continue) { /* (relatively) normal zipfile: go for it */ if (error) { Info(slide, 0x401, ((char *)slide, LoadFarString(MaybePakBug), G.zipfn)); error_in_archive = PK_WARN; } #endif /* !SFX */ if ((G.extra_bytes = G.real_ecrec_offset-G.expect_ecrec_offset) < (zoff_t)0) { Info(slide, 0x401, ((char *)slide, LoadFarString(MissingBytes), G.zipfn, FmZofft((-G.extra_bytes), NULL, NULL))); error_in_archive = PK_ERR; } else if (G.extra_bytes > 0) { if ((G.ecrec.offset_start_central_directory == 0) && (G.ecrec.size_central_directory != 0)) /* zip 1.5 -go bug */ { Info(slide, 0x401, ((char *)slide, LoadFarString(NullCentDirOffset), G.zipfn)); G.ecrec.offset_start_central_directory = G.extra_bytes; G.extra_bytes = 0; error_in_archive = PK_ERR; } #ifndef SFX else { Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraBytesAtStart), G.zipfn, FmZofft(G.extra_bytes, NULL, NULL), (G.extra_bytes == 1)? "":"s")); error_in_archive = PK_WARN; } #endif /* !SFX */ } /*----------------------------------------------------------------------- Check for empty zipfile and exit now if so. -----------------------------------------------------------------------*/ if (G.expect_ecrec_offset==0L && G.ecrec.size_central_directory==0) { if (uO.zipinfo_mode) Info(slide, 0, ((char *)slide, "%sEmpty zipfile.\n", uO.lflag>9? "\n " : "")); else Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileEmpty), G.zipfn)); CLOSE_INFILE(); return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN; } /*----------------------------------------------------------------------- Compensate for missing or extra bytes, and seek to where the start of central directory should be. If header not found, uncompensate and try again (necessary for at least some Atari archives created with STZip, as well as archives created by J.H. Holm's ZIPSPLIT 1.1). -----------------------------------------------------------------------*/ error = seek_zipf(__G__ G.ecrec.offset_start_central_directory); if (error == PK_BADERR) { CLOSE_INFILE(); return PK_BADERR; } #ifdef OLD_SEEK_TEST if (error != PK_OK || readbuf(__G__ G.sig, 4) == 0) { CLOSE_INFILE(); return PK_ERR; /* file may be locked, or possibly disk error(?) */ } if (memcmp(G.sig, central_hdr_sig, 4)) #else if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) || memcmp(G.sig, central_hdr_sig, 4)) #endif { #ifndef SFX zoff_t tmp = G.extra_bytes; #endif G.extra_bytes = 0; error = seek_zipf(__G__ G.ecrec.offset_start_central_directory); if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) || memcmp(G.sig, central_hdr_sig, 4)) { if (error != PK_BADERR) Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirStartNotFound), G.zipfn, LoadFarStringSmall(ReportMsg))); CLOSE_INFILE(); return (error != PK_OK ? error : PK_BADERR); } #ifndef SFX Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong), G.zipfn, FmZofft((-tmp), NULL, NULL))); #endif error_in_archive = PK_ERR; } /*----------------------------------------------------------------------- Seek to the start of the central directory one last time, since we have just read the first entry's signature bytes; then list, extract or test member files as instructed, and close the zipfile. -----------------------------------------------------------------------*/ error = seek_zipf(__G__ G.ecrec.offset_start_central_directory); if (error != PK_OK) { CLOSE_INFILE(); return error; } Trace((stderr, "about to extract/list files (error = %d)\n", error_in_archive)); #ifdef DLL /* G.fValidate is used only to look at an archive to see if it appears to be a valid archive. There is no interest in what the archive contains, nor in validating that the entries in the archive are in good condition. This is currently used only in the Windows DLLs for purposes of checking archives within an archive to determine whether or not to display the inner archives. */ if (!G.fValidate) #endif { #ifndef NO_ZIPINFO if (uO.zipinfo_mode) error = zipinfo(__G); /* ZIPINFO 'EM */ else #endif #ifndef SFX #ifdef TIMESTAMP if (uO.T_flag) error = get_time_stamp(__G__ &uxstamp, &nmember); else #endif if (uO.vflag && !uO.tflag && !uO.cflag) error = list_files(__G); /* LIST 'EM */ else #endif /* !SFX */ error = extract_or_test_files(__G); /* EXTRACT OR TEST 'EM */ Trace((stderr, "done with extract/list files (error = %d)\n", error)); } if (error > error_in_archive) /* don't overwrite stronger error */ error_in_archive = error; /* with (for example) a warning */ #ifndef SFX } /* end if (!too_weird_to_continue) */ #endif CLOSE_INFILE(); #ifdef TIMESTAMP if (uO.T_flag && !uO.zipinfo_mode && (nmember > 0L)) { # ifdef WIN32 if (stamp_file(__G__ G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */ # else if (stamp_file(G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */ # endif if (uO.qflag < 3) Info(slide, 0x201, ((char *)slide, LoadFarString(ZipTimeStampFailed), G.zipfn)); if (error_in_archive < PK_WARN) error_in_archive = PK_WARN; } else { if (!uO.qflag) Info(slide, 0, ((char *)slide, LoadFarString(ZipTimeStampSuccess), G.zipfn)); } } #endif return error_in_archive; } /* end function do_seekable() */ #ifdef DO_SAFECHECK_2GB /************************/ /* Function file_size() */ /************************/ /* File size determination which does not mislead for large files in a small-file program. Probably should be somewhere else. The file has to be opened previously */ #ifdef USE_STRM_INPUT static zoff_t file_size(file) FILE *file; { int sts; size_t siz; #else /* !USE_STRM_INPUT */ static zoff_t file_size(fh) int fh; { int siz; #endif /* ?USE_STRM_INPUT */ zoff_t ofs; char waste[4]; #ifdef USE_STRM_INPUT /* Seek to actual EOF. */ sts = zfseeko(file, 0, SEEK_END); if (sts != 0) { /* fseeko() failed. (Unlikely.) */ ofs = EOF; } else { /* Get apparent offset at EOF. */ ofs = zftello(file); if (ofs < 0) { /* Offset negative (overflow). File too big. */ ofs = EOF; } else { /* Seek to apparent EOF offset. Won't be at actual EOF if offset was truncated. */ sts = zfseeko(file, ofs, SEEK_SET); if (sts != 0) { /* fseeko() failed. (Unlikely.) */ ofs = EOF; } else { /* Read a byte at apparent EOF. Should set EOF flag. */ siz = fread(waste, 1, 1, file); if (feof(file) == 0) { /* Not at EOF, but should be. File too big. */ ofs = EOF; } } } } #else /* !USE_STRM_INPUT */ /* Seek to actual EOF. */ ofs = zlseek(fh, 0, SEEK_END); if (ofs == (zoff_t) -1) { /* zlseek() failed. (Unlikely.) */ ofs = EOF; } else if (ofs < 0) { /* Offset negative (overflow). File too big. */ ofs = EOF; } else { /* Seek to apparent EOF offset. Won't be at actual EOF if offset was truncated. */ ofs = zlseek(fh, ofs, SEEK_SET); if (ofs == (zoff_t) -1) { /* zlseek() failed. (Unlikely.) */ ofs = EOF; } else { /* Read a byte at apparent EOF. Should set EOF flag. */ siz = read(fh, waste, 1); if (siz != 0) { /* Not at EOF, but should be. File too big. */ ofs = EOF; } } } #endif /* ?USE_STRM_INPUT */ return ofs; } /* end function file_size() */ #endif /* DO_SAFECHECK_2GB */ /***********************/ /* Function rec_find() */ /***********************/ static int rec_find(__G__ searchlen, signature, rec_size) /* return 0 when rec found, 1 when not found, 2 in case of read error */ __GDEF zoff_t searchlen; char* signature; int rec_size; { int i, numblks, found=FALSE; zoff_t tail_len; /*--------------------------------------------------------------------------- Zipfile is longer than INBUFSIZ: may need to loop. Start with short block at end of zipfile (if not TOO short). ---------------------------------------------------------------------------*/ if ((tail_len = G.ziplen % INBUFSIZ) > rec_size) { #ifdef USE_STRM_INPUT zfseeko(G.zipfd, G.ziplen-tail_len, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, G.ziplen-tail_len, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd, (char *)G.inbuf, (unsigned int)tail_len)) != (int)tail_len) return 2; /* it's expedient... */ /* 'P' must be at least (rec_size+4) bytes from end of zipfile */ for (G.inptr = G.inbuf+(int)tail_len-(rec_size+4); G.inptr >= G.inbuf; --G.inptr) { if ( (*G.inptr == (uch)0x50) && /* ASCII 'P' */ !memcmp((char *)G.inptr, signature, 4) ) { G.incnt -= (int)(G.inptr - G.inbuf); found = TRUE; break; } } /* sig may span block boundary: */ memcpy((char *)G.hold, (char *)G.inbuf, 3); } else G.cur_zipfile_bufstart = G.ziplen - tail_len; /*----------------------------------------------------------------------- Loop through blocks of zipfile data, starting at the end and going toward the beginning. In general, need not check whole zipfile for signature, but may want to do so if testing. -----------------------------------------------------------------------*/ numblks = (int)((searchlen - tail_len + (INBUFSIZ-1)) / INBUFSIZ); /* ==amount= ==done== ==rounding== =blksiz= */ for (i = 1; !found && (i <= numblks); ++i) { G.cur_zipfile_bufstart -= INBUFSIZ; #ifdef USE_STRM_INPUT zfseeko(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET); #else /* !USE_STRM_INPUT */ zlseek(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) != INBUFSIZ) return 2; /* read error is fatal failure */ for (G.inptr = G.inbuf+INBUFSIZ-1; G.inptr >= G.inbuf; --G.inptr) if ( (*G.inptr == (uch)0x50) && /* ASCII 'P' */ !memcmp((char *)G.inptr, signature, 4) ) { G.incnt -= (int)(G.inptr - G.inbuf); found = TRUE; break; } /* sig may span block boundary: */ memcpy((char *)G.hold, (char *)G.inbuf, 3); } return (found ? 0 : 1); } /* end function rec_find() */ #if 0 /********************************/ /* Function check_ecrec_zip64() */ /********************************/ static int check_ecrec_zip64(__G) __GDEF { return G.ecrec.offset_start_central_directory == 0xFFFFFFFFL || G.ecrec.size_central_directory == 0xFFFFFFFFL || G.ecrec.total_entries_central_dir == 0xFFFF || G.ecrec.num_entries_centrl_dir_ths_disk == 0xFFFF || G.ecrec.num_disk_start_cdir == 0xFFFF || G.ecrec.number_this_disk == 0xFFFF; } /* end function check_ecrec_zip64() */ #endif /* never */ /***************************/ /* Function find_ecrec64() */ /***************************/ static int find_ecrec64(__G__ searchlen) /* return PK-class error */ __GDEF zoff_t searchlen; { ec_byte_rec64 byterec; /* buf for ecrec64 */ ec_byte_loc64 byterecL; /* buf for ecrec64 locator */ zoff_t ecloc64_start_offset; /* start offset of ecrec64 locator */ zusz_t ecrec64_start_offset; /* start offset of ecrec64 */ zuvl_t ecrec64_start_disk; /* start disk of ecrec64 */ zuvl_t ecloc64_total_disks; /* total disks */ zuvl_t ecrec64_disk_cdstart; /* disk number of central dir start */ zucn_t ecrec64_this_entries; /* entries on disk with ecrec64 */ zucn_t ecrec64_tot_entries; /* total number of entries */ zusz_t ecrec64_cdirsize; /* length of central dir */ zusz_t ecrec64_offs_cdstart; /* offset of central dir start */ /* First, find the ecrec64 locator. By definition, this must be before ecrec with nothing in between. We back up the size of the ecrec64 locator and check. */ ecloc64_start_offset = G.real_ecrec_offset - (ECLOC64_SIZE+4); if (ecloc64_start_offset < 0) /* Seeking would go past beginning, so probably empty archive */ return PK_COOL; #ifdef USE_STRM_INPUT zfseeko(G.zipfd, ecloc64_start_offset, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, ecloc64_start_offset, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd, (char *)byterecL, ECLOC64_SIZE+4)) != (ECLOC64_SIZE+4)) { if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(Cent64EndSigSearchErr))); return PK_ERR; } if (memcmp((char *)byterecL, end_centloc64_sig, 4) ) { /* not found */ return PK_COOL; } /* Read the locator. */ ecrec64_start_disk = (zuvl_t)makelong(&byterecL[NUM_DISK_START_EOCDR64]); ecrec64_start_offset = (zusz_t)makeint64(&byterecL[OFFSET_START_EOCDR64]); ecloc64_total_disks = (zuvl_t)makelong(&byterecL[NUM_THIS_DISK_LOC64]); /* Check for consistency */ #ifdef TEST fprintf(stdout,"\nnumber of disks (ECR) %u, (ECLOC64) %lu\n", G.ecrec.number_this_disk, ecloc64_total_disks); fflush(stdout); #endif if ((G.ecrec.number_this_disk != 0xFFFF) && (G.ecrec.number_this_disk != ecloc64_total_disks - 1)) { /* Note: For some unknown reason, the developers at PKWARE decided to store the "zip64 total disks" value as a counter starting from 1, whereas all other "split/span volume" related fields use 0-based volume numbers. Sigh... */ /* When the total number of disks as found in the traditional ecrec is not 0xFFFF, the disk numbers in ecrec and ecloc64 must match. When this is not the case, the found ecrec64 locator cannot be valid. -> This is not a Zip64 archive. */ Trace((stderr, "\ninvalid ECLOC64, differing disk# (ECR %u, ECL64 %lu)\n", G.ecrec.number_this_disk, ecloc64_total_disks - 1)); return PK_COOL; } /* If found locator, look for ecrec64 where the locator says it is. */ /* For now assume that ecrec64 is on the same disk as ecloc64 and ecrec, which is usually the case and is how Zip writes it. To do this right, however, we should allow the ecrec64 to be on another disk since the AppNote allows it and the ecrec64 can be large, especially if Version 2 is used (AppNote uses 8 bytes for the size of this record). */ /* FIX BELOW IF ADD SUPPORT FOR MULTIPLE DISKS */ if (ecrec64_start_offset > (zusz_t)ecloc64_start_offset) { /* ecrec64 has to be before ecrec64 locator */ if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(Cent64EndSigSearchErr))); return PK_ERR; } #ifdef USE_STRM_INPUT zfseeko(G.zipfd, ecrec64_start_offset, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, ecrec64_start_offset, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd, (char *)byterec, ECREC64_SIZE+4)) != (ECREC64_SIZE+4)) { if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(Cent64EndSigSearchErr))); return PK_ERR; } if (memcmp((char *)byterec, end_central64_sig, 4) ) { /* Zip64 EOCD Record not found */ /* Since we already have seen the Zip64 EOCD Locator, it's possible we got here because there are bytes prepended to the archive, like the sfx prefix. */ /* Make a guess as to where the Zip64 EOCD Record might be */ ecrec64_start_offset = ecloc64_start_offset - ECREC64_SIZE - 4; #ifdef USE_STRM_INPUT zfseeko(G.zipfd, ecrec64_start_offset, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = zlseek(G.zipfd, ecrec64_start_offset, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd, (char *)byterec, ECREC64_SIZE+4)) != (ECREC64_SIZE+4)) { if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(Cent64EndSigSearchErr))); return PK_ERR; } if (memcmp((char *)byterec, end_central64_sig, 4) ) { /* Zip64 EOCD Record not found */ /* Probably something not so easy to handle so exit */ if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(Cent64EndSigSearchErr))); return PK_ERR; } if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(Cent64EndSigSearchOff))); } /* Check consistency of found ecrec64 with ecloc64 (and ecrec): */ if ( (zuvl_t)makelong(&byterec[NUMBER_THIS_DSK_REC64]) != ecrec64_start_disk ) /* found ecrec64 does not match ecloc64 info -> no Zip64 archive */ return PK_COOL; /* Read all relevant ecrec64 fields and compare them to the corresponding ecrec fields unless those are set to "all-ones". */ ecrec64_disk_cdstart = (zuvl_t)makelong(&byterec[NUM_DISK_START_CEN_DIR64]); if ( (G.ecrec.num_disk_start_cdir != 0xFFFF) && (G.ecrec.num_disk_start_cdir != ecrec64_disk_cdstart) ) return PK_COOL; ecrec64_this_entries = makeint64(&byterec[NUM_ENTRIES_CEN_DIR_THS_DISK64]); if ( (G.ecrec.num_entries_centrl_dir_ths_disk != 0xFFFF) && (G.ecrec.num_entries_centrl_dir_ths_disk != ecrec64_this_entries) ) return PK_COOL; ecrec64_tot_entries = makeint64(&byterec[TOTAL_ENTRIES_CENTRAL_DIR64]); if ( (G.ecrec.total_entries_central_dir != 0xFFFF) && (G.ecrec.total_entries_central_dir != ecrec64_tot_entries) ) return PK_COOL; ecrec64_cdirsize = makeint64(&byterec[SIZE_CENTRAL_DIRECTORY64]); if ( (G.ecrec.size_central_directory != 0xFFFFFFFFL) && (G.ecrec.size_central_directory != ecrec64_cdirsize) ) return PK_COOL; ecrec64_offs_cdstart = makeint64(&byterec[OFFSET_START_CENTRAL_DIRECT64]); if ( (G.ecrec.offset_start_central_directory != 0xFFFFFFFFL) && (G.ecrec.offset_start_central_directory != ecrec64_offs_cdstart) ) return PK_COOL; /* Now, we are (almost) sure that we have a Zip64 archive. */ G.ecrec.have_ecr64 = 1; /* Update the "end-of-central-dir offset" for later checks. */ G.real_ecrec_offset = ecrec64_start_offset; /* Update all ecdir_rec data that are flagged to be invalid in Zip64 mode. Set the ecrec64-mandatory flag when such a case is found. */ if (G.ecrec.number_this_disk == 0xFFFF) { G.ecrec.number_this_disk = ecrec64_start_disk; if (ecrec64_start_disk != 0xFFFF) G.ecrec.is_zip64_archive = TRUE; } if (G.ecrec.num_disk_start_cdir == 0xFFFF) { G.ecrec.num_disk_start_cdir = ecrec64_disk_cdstart; if (ecrec64_disk_cdstart != 0xFFFF) G.ecrec.is_zip64_archive = TRUE; } if (G.ecrec.num_entries_centrl_dir_ths_disk == 0xFFFF) { G.ecrec.num_entries_centrl_dir_ths_disk = ecrec64_this_entries; if (ecrec64_this_entries != 0xFFFF) G.ecrec.is_zip64_archive = TRUE; } if (G.ecrec.total_entries_central_dir == 0xFFFF) { G.ecrec.total_entries_central_dir = ecrec64_tot_entries; if (ecrec64_tot_entries != 0xFFFF) G.ecrec.is_zip64_archive = TRUE; } if (G.ecrec.size_central_directory == 0xFFFFFFFFL) { G.ecrec.size_central_directory = ecrec64_cdirsize; if (ecrec64_cdirsize != 0xFFFFFFFF) G.ecrec.is_zip64_archive = TRUE; } if (G.ecrec.offset_start_central_directory == 0xFFFFFFFFL) { G.ecrec.offset_start_central_directory = ecrec64_offs_cdstart; if (ecrec64_offs_cdstart != 0xFFFFFFFF) G.ecrec.is_zip64_archive = TRUE; } return PK_COOL; } /* end function find_ecrec64() */ /*************************/ /* Function find_ecrec() */ /*************************/ static int find_ecrec(__G__ searchlen) /* return PK-class error */ __GDEF zoff_t searchlen; { int found = FALSE; int error_in_archive; int result; ec_byte_rec byterec; /*--------------------------------------------------------------------------- Treat case of short zipfile separately. ---------------------------------------------------------------------------*/ if (G.ziplen <= INBUFSIZ) { #ifdef USE_STRM_INPUT zfseeko(G.zipfd, 0L, SEEK_SET); #else /* !USE_STRM_INPUT */ zlseek(G.zipfd, 0L, SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd,(char *)G.inbuf,(unsigned int)G.ziplen)) == (int)G.ziplen) /* 'P' must be at least (ECREC_SIZE+4) bytes from end of zipfile */ for (G.inptr = G.inbuf+(int)G.ziplen-(ECREC_SIZE+4); G.inptr >= G.inbuf; --G.inptr) { if ( (*G.inptr == (uch)0x50) && /* ASCII 'P' */ !memcmp((char *)G.inptr, end_central_sig, 4)) { G.incnt -= (int)(G.inptr - G.inbuf); found = TRUE; break; } } /*--------------------------------------------------------------------------- Zipfile is longer than INBUFSIZ: MB - this next block of code moved to rec_find so that same code can be used to look for zip64 ec record. No need to include code above since a zip64 ec record will only be looked for if it is a BIG file. ---------------------------------------------------------------------------*/ } else { found = (rec_find(__G__ searchlen, end_central_sig, ECREC_SIZE) == 0 ? TRUE : FALSE); } /* end if (ziplen > INBUFSIZ) */ /*--------------------------------------------------------------------------- Searched through whole region where signature should be without finding it. Print informational message and die a horrible death. ---------------------------------------------------------------------------*/ if (!found) { if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirEndSigNotFound))); return PK_ERR; /* failed */ } /*--------------------------------------------------------------------------- Found the signature, so get the end-central data before returning. Do any necessary machine-type conversions (byte ordering, structure padding compensation) by reading data into character array and copying to struct. ---------------------------------------------------------------------------*/ G.real_ecrec_offset = G.cur_zipfile_bufstart + (G.inptr-G.inbuf); #ifdef TEST printf("\n found end-of-central-dir signature at offset %s (%sh)\n", FmZofft(G.real_ecrec_offset, NULL, NULL), FmZofft(G.real_ecrec_offset, FZOFFT_HEX_DOT_WID, "X")); printf(" from beginning of file; offset %d (%.4Xh) within block\n", G.inptr-G.inbuf, G.inptr-G.inbuf); #endif if (readbuf(__G__ (char *)byterec, ECREC_SIZE+4) == 0) return PK_EOF; G.ecrec.number_this_disk = makeword(&byterec[NUMBER_THIS_DISK]); G.ecrec.num_disk_start_cdir = makeword(&byterec[NUM_DISK_WITH_START_CEN_DIR]); G.ecrec.num_entries_centrl_dir_ths_disk = makeword(&byterec[NUM_ENTRIES_CEN_DIR_THS_DISK]); G.ecrec.total_entries_central_dir = makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]); G.ecrec.size_central_directory = makelong(&byterec[SIZE_CENTRAL_DIRECTORY]); G.ecrec.offset_start_central_directory = makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]); G.ecrec.zipfile_comment_length = makeword(&byterec[ZIPFILE_COMMENT_LENGTH]); /* Now, we have to read the archive comment, BEFORE the file pointer is moved away backwards to seek for a Zip64 ECLOC64 structure. */ if ( (error_in_archive = process_zip_cmmnt(__G)) > PK_WARN ) return error_in_archive; /* Next: Check for existence of Zip64 end-of-cent-dir locator ECLOC64. This structure must reside on the same volume as the classic ECREC, at exactly (ECLOC64_SIZE+4) bytes in front of the ECREC. The ECLOC64 structure directs to the longer ECREC64 structure A ECREC64 will ALWAYS exist for a proper Zip64 archive, as the "Version Needed To Extract" field is required to be set to 4.5 or higher whenever any Zip64 features are used anywhere in the archive, so just check for that to see if this is a Zip64 archive. */ result = find_ecrec64(__G__ searchlen+76); /* 76 bytes for zip64ec & zip64 locator */ if (result != PK_COOL) { if (error_in_archive < result) error_in_archive = result; return error_in_archive; } G.expect_ecrec_offset = G.ecrec.offset_start_central_directory + G.ecrec.size_central_directory; #ifndef NO_ZIPINFO if (uO.zipinfo_mode) { /* In ZipInfo mode, additional info about the data found in the end-of-central-directory areas is printed out. */ zi_end_central(__G); } #endif return error_in_archive; } /* end function find_ecrec() */ /********************************/ /* Function process_zip_cmmnt() */ /********************************/ static int process_zip_cmmnt(__G) /* return PK-type error code */ __GDEF { int error = PK_COOL; /*--------------------------------------------------------------------------- Get the zipfile comment (up to 64KB long), if any, and print it out. ---------------------------------------------------------------------------*/ #ifdef WINDLL /* for comment button: */ if ((!G.fValidate) && (G.lpUserFunctions != NULL)) G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length; #endif /* WINDLL */ #ifndef NO_ZIPINFO /* ZipInfo, verbose format */ if (uO.zipinfo_mode && uO.lflag > 9) { /*------------------------------------------------------------------- Get the zipfile comment, if any, and print it out. (Comment may be up to 64KB long. May the fleas of a thousand camels infest the arm-pits of anyone who actually takes advantage of this fact.) -------------------------------------------------------------------*/ if (!G.ecrec.zipfile_comment_length) Info(slide, 0, ((char *)slide, LoadFarString(NoZipfileComment))); else { Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommentDesc), G.ecrec.zipfile_comment_length)); Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommBegin))); if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) error = PK_WARN; Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommEnd))); if (error) Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommTrunc2))); } /* endif (comment exists) */ /* ZipInfo, non-verbose mode: print zipfile comment only if requested */ } else if (G.ecrec.zipfile_comment_length && (uO.zflag > 0) && uO.zipinfo_mode) { if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) { Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileCommTrunc1))); error = PK_WARN; } } else #endif /* !NO_ZIPINFO */ if ( G.ecrec.zipfile_comment_length && (uO.zflag > 0 #ifndef WINDLL || (uO.zflag == 0 # ifndef NO_ZIPINFO && !uO.zipinfo_mode # endif # ifdef TIMESTAMP && !uO.T_flag # endif && !uO.qflag) #endif /* !WINDLL */ ) ) { if (do_string(__G__ G.ecrec.zipfile_comment_length, #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) # ifndef NO_ZIPINFO (oU.zipinfo_mode ? DISPLAY : CHECK_AUTORUN) # else CHECK_AUTORUN # endif #else DISPLAY #endif )) { Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileCommTrunc1))); error = PK_WARN; } } #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) else if (G.ecrec.zipfile_comment_length) { if (do_string(__G__ G.ecrec.zipfile_comment_length, CHECK_AUTORUN_Q)) { Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileCommTrunc1))); error = PK_WARN; } } #endif return error; } /* end function process_zip_cmmnt() */ /************************************/ /* Function process_cdir_file_hdr() */ /************************************/ int process_cdir_file_hdr(__G) /* return PK-type error code */ __GDEF { int error; /*--------------------------------------------------------------------------- Get central directory info, save host and method numbers, and set flag for lowercase conversion of filename, depending on the OS from which the file is coming. ---------------------------------------------------------------------------*/ if ((error = get_cdir_ent(__G)) != 0) return error; G.pInfo->hostver = G.crec.version_made_by[0]; G.pInfo->hostnum = MIN(G.crec.version_made_by[1], NUM_HOSTS); /* extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */ G.pInfo->lcflag = 0; if (uO.L_flag == 1) /* name conversion for monocase systems */ switch (G.pInfo->hostnum) { case FS_FAT_: /* PKZIP and zip -k store in uppercase */ case CPM_: /* like MS-DOS, right? */ case VM_CMS_: /* all caps? */ case MVS_: /* all caps? */ case TANDEM_: case TOPS20_: case VMS_: /* our Zip uses lowercase, but ASi's doesn't */ /* case Z_SYSTEM_: ? */ /* case QDOS_: ? */ G.pInfo->lcflag = 1; /* convert filename to lowercase */ break; default: /* AMIGA_, FS_HPFS_, FS_NTFS_, MAC_, UNIX_, ATARI_, */ break; /* FS_VFAT_, ATHEOS_, BEOS_ (Z_SYSTEM_), THEOS_: */ /* no conversion */ } else if (uO.L_flag > 1) /* let -LL force lower case for all names */ G.pInfo->lcflag = 1; /* do Amigas (AMIGA_) also have volume labels? */ if (IS_VOLID(G.crec.external_file_attributes) && (G.pInfo->hostnum == FS_FAT_ || G.pInfo->hostnum == FS_HPFS_ || G.pInfo->hostnum == FS_NTFS_ || G.pInfo->hostnum == ATARI_)) { G.pInfo->vollabel = TRUE; G.pInfo->lcflag = 0; /* preserve case of volume labels */ } else G.pInfo->vollabel = FALSE; /* this flag is needed to detect archives made by "PKZIP for Unix" when deciding which kind of codepage conversion has to be applied to strings (see do_string() function in fileio.c) */ G.pInfo->HasUxAtt = (G.crec.external_file_attributes & 0xffff0000L) != 0L; #ifdef UNICODE_SUPPORT /* remember the state of GPB11 (General Purpuse Bit 11) which indicates that the standard path and comment are UTF-8. */ G.pInfo->GPFIsUTF8 = (G.crec.general_purpose_bit_flag & (1 << 11)) == (1 << 11); #endif return PK_COOL; } /* end function process_cdir_file_hdr() */ /***************************/ /* Function get_cdir_ent() */ /***************************/ static int get_cdir_ent(__G) /* return PK-type error code */ __GDEF { cdir_byte_hdr byterec; /*--------------------------------------------------------------------------- Read the next central directory entry and do any necessary machine-type conversions (byte ordering, structure padding compensation--do so by copying the data from the array into which it was read (byterec) to the usable struct (crec)). ---------------------------------------------------------------------------*/ if (readbuf(__G__ (char *)byterec, CREC_SIZE) == 0) return PK_EOF; G.crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0]; G.crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1]; G.crec.version_needed_to_extract[0] = byterec[C_VERSION_NEEDED_TO_EXTRACT_0]; G.crec.version_needed_to_extract[1] = byterec[C_VERSION_NEEDED_TO_EXTRACT_1]; G.crec.general_purpose_bit_flag = makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]); G.crec.compression_method = makeword(&byterec[C_COMPRESSION_METHOD]); G.crec.last_mod_dos_datetime = makelong(&byterec[C_LAST_MOD_DOS_DATETIME]); G.crec.crc32 = makelong(&byterec[C_CRC32]); G.crec.csize = makelong(&byterec[C_COMPRESSED_SIZE]); G.crec.ucsize = makelong(&byterec[C_UNCOMPRESSED_SIZE]); G.crec.filename_length = makeword(&byterec[C_FILENAME_LENGTH]); G.crec.extra_field_length = makeword(&byterec[C_EXTRA_FIELD_LENGTH]); G.crec.file_comment_length = makeword(&byterec[C_FILE_COMMENT_LENGTH]); G.crec.disk_number_start = makeword(&byterec[C_DISK_NUMBER_START]); G.crec.internal_file_attributes = makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]); G.crec.external_file_attributes = makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]); /* LONG, not word! */ G.crec.relative_offset_local_header = makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]); return PK_COOL; } /* end function get_cdir_ent() */ /*************************************/ /* Function process_local_file_hdr() */ /*************************************/ int process_local_file_hdr(__G) /* return PK-type error code */ __GDEF { local_byte_hdr byterec; /*--------------------------------------------------------------------------- Read the next local file header and do any necessary machine-type con- versions (byte ordering, structure padding compensation--do so by copy- ing the data from the array into which it was read (byterec) to the usable struct (lrec)). ---------------------------------------------------------------------------*/ if (readbuf(__G__ (char *)byterec, LREC_SIZE) == 0) return PK_EOF; G.lrec.version_needed_to_extract[0] = byterec[L_VERSION_NEEDED_TO_EXTRACT_0]; G.lrec.version_needed_to_extract[1] = byterec[L_VERSION_NEEDED_TO_EXTRACT_1]; G.lrec.general_purpose_bit_flag = makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]); G.lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]); G.lrec.last_mod_dos_datetime = makelong(&byterec[L_LAST_MOD_DOS_DATETIME]); G.lrec.crc32 = makelong(&byterec[L_CRC32]); G.lrec.csize = makelong(&byterec[L_COMPRESSED_SIZE]); G.lrec.ucsize = makelong(&byterec[L_UNCOMPRESSED_SIZE]); G.lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]); G.lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]); if ((G.lrec.general_purpose_bit_flag & 8) != 0) { /* can't trust local header, use central directory: */ G.lrec.crc32 = G.pInfo->crc; G.lrec.csize = G.pInfo->compr_size; G.lrec.ucsize = G.pInfo->uncompr_size; } G.csize = G.lrec.csize; return PK_COOL; } /* end function process_local_file_hdr() */ /*******************************/ /* Function getZip64Data() */ /*******************************/ int getZip64Data(__G__ ef_buf, ef_len) __GDEF ZCONST uch *ef_buf; /* buffer containing extra field */ unsigned ef_len; /* total length of extra field */ { unsigned eb_id; unsigned eb_len; /*--------------------------------------------------------------------------- This function scans the extra field for zip64 information, ie 8-byte versions of compressed file size, uncompressed file size, relative offset and a 4-byte version of disk start number. Sets both local header and central header fields. Not terribly clever, but it means that this procedure is only called in one place. ---------------------------------------------------------------------------*/ if (ef_len == 0 || ef_buf == NULL) return PK_COOL; Trace((stderr,"\ngetZip64Data: scanning extra field of length %u\n", ef_len)); while (ef_len >= EB_HEADSIZE) { eb_id = makeword(EB_ID + ef_buf); eb_len = makeword(EB_LEN + ef_buf); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ Trace((stderr, "getZip64Data: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } if (eb_id == EF_PKSZ64) { int offset = EB_HEADSIZE; if (G.crec.ucsize == 0xffffffff || G.lrec.ucsize == 0xffffffff){ G.lrec.ucsize = G.crec.ucsize = makeint64(offset + ef_buf); offset += sizeof(G.crec.ucsize); } if (G.crec.csize == 0xffffffff || G.lrec.csize == 0xffffffff){ G.csize = G.lrec.csize = G.crec.csize = makeint64(offset + ef_buf); offset += sizeof(G.crec.csize); } if (G.crec.relative_offset_local_header == 0xffffffff){ G.crec.relative_offset_local_header = makeint64(offset + ef_buf); offset += sizeof(G.crec.relative_offset_local_header); } if (G.crec.disk_number_start == 0xffff){ G.crec.disk_number_start = (zuvl_t)makelong(offset + ef_buf); offset += sizeof(G.crec.disk_number_start); } } /* Skip this extra field block */ ef_buf += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return PK_COOL; } /* end function getZip64Data() */ #ifdef UNICODE_SUPPORT /*******************************/ /* Function getUnicodeData() */ /*******************************/ int getUnicodeData(__G__ ef_buf, ef_len) __GDEF ZCONST uch *ef_buf; /* buffer containing extra field */ unsigned ef_len; /* total length of extra field */ { unsigned eb_id; unsigned eb_len; /*--------------------------------------------------------------------------- This function scans the extra field for Unicode information, ie UTF-8 path extra fields. On return, G.unipath_filename = NULL, if no Unicode path extra field or error "", if the standard path is UTF-8 (free when done) null-terminated UTF-8 path (free when done) Return PK_COOL if no error. ---------------------------------------------------------------------------*/ G.unipath_filename = NULL; if (ef_len == 0 || ef_buf == NULL) return PK_COOL; Trace((stderr,"\ngetUnicodeData: scanning extra field of length %u\n", ef_len)); while (ef_len >= EB_HEADSIZE) { eb_id = makeword(EB_ID + ef_buf); eb_len = makeword(EB_LEN + ef_buf); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ Trace((stderr, "getUnicodeData: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } if (eb_id == EF_UNIPATH) { int offset = EB_HEADSIZE; ush ULen = eb_len - 5; ulg chksum = CRCVAL_INITIAL; /* version */ G.unipath_version = (uch) *(offset + ef_buf); offset += 1; if (G.unipath_version > 1) { /* can do only version 1 */ Info(slide, 0x401, ((char *)slide, LoadFarString(UnicodeVersionError))); return PK_ERR; } /* filename CRC */ G.unipath_checksum = makelong(offset + ef_buf); offset += 4; /* * Compute 32-bit crc */ chksum = crc32(chksum, (uch *)(G.filename_full), strlen(G.filename_full)); /* If the checksums's don't match then likely filename has been * modified and the Unicode Path is no longer valid. */ if (chksum != G.unipath_checksum) { Info(slide, 0x401, ((char *)slide, LoadFarString(UnicodeMismatchError))); if (G.unicode_mismatch == 1) { /* warn and continue */ } else if (G.unicode_mismatch == 2) { /* ignore and continue */ } else if (G.unicode_mismatch == 0) { } return PK_ERR; } /* UTF-8 Path */ if ((G.unipath_filename = malloc(ULen + 1)) == NULL) { return PK_ERR; } if (ULen == 0) { /* standard path is UTF-8 so use that */ G.unipath_filename[0] = '\0'; } else { /* UTF-8 path */ strncpy(G.unipath_filename, (ZCONST char *)(offset + ef_buf), ULen); G.unipath_filename[ULen] = '\0'; } } /* Skip this extra field block */ ef_buf += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return PK_COOL; } /* end function getUnicodeData() */ #ifdef UNICODE_WCHAR /*--------------------------------------------- * Unicode conversion functions * * Based on functions provided by Paul Kienitz * *--------------------------------------------- */ /* NOTES APPLICABLE TO ALL STRING FUNCTIONS: All of the x_to_y functions take parameters for an output buffer and its available length, and return an int. The value returned is the length of the string that the input produces, which may be larger than the provided buffer length. If the returned value is less than the buffer length, then the contents of the buffer will be null-terminated; otherwise, it will not be terminated and may be invalid, possibly stopping in the middle of a multibyte sequence. In all cases you may pass NULL as the buffer and/or 0 as the length, if you just want to learn how much space the string is going to require. The functions will return -1 if the input is invalid UTF-8 or cannot be encoded as UTF-8. */ static int utf8_char_bytes OF((ZCONST char *utf8)); static ulg ucs4_char_from_utf8 OF((ZCONST char **utf8)); static int utf8_to_ucs4_string OF((ZCONST char *utf8, ulg *ucs4buf, int buflen)); /* utility functions for managing UTF-8 and UCS-4 strings */ /* utf8_char_bytes * * Returns the number of bytes used by the first character in a UTF-8 * string, or -1 if the UTF-8 is invalid or null. */ static int utf8_char_bytes(utf8) ZCONST char *utf8; { int t, r; unsigned lead; if (!utf8) return -1; /* no input */ lead = (unsigned char) *utf8; if (lead < 0x80) r = 1; /* an ascii-7 character */ else if (lead < 0xC0) return -1; /* error: trailing byte without lead byte */ else if (lead < 0xE0) r = 2; /* an 11 bit character */ else if (lead < 0xF0) r = 3; /* a 16 bit character */ else if (lead < 0xF8) r = 4; /* a 21 bit character (the most currently used) */ else if (lead < 0xFC) r = 5; /* a 26 bit character (shouldn't happen) */ else if (lead < 0xFE) r = 6; /* a 31 bit character (shouldn't happen) */ else return -1; /* error: invalid lead byte */ for (t = 1; t < r; t++) if ((unsigned char) utf8[t] < 0x80 || (unsigned char) utf8[t] >= 0xC0) return -1; /* error: not enough valid trailing bytes */ return r; } /* ucs4_char_from_utf8 * * Given a reference to a pointer into a UTF-8 string, returns the next * UCS-4 character and advances the pointer to the next character sequence. * Returns ~0 (= -1 in twos-complement notation) and does not advance the * pointer when input is ill-formed. */ static ulg ucs4_char_from_utf8(utf8) ZCONST char **utf8; { ulg ret; int t, bytes; if (!utf8) return ~0L; /* no input */ bytes = utf8_char_bytes(*utf8); if (bytes <= 0) return ~0L; /* invalid input */ if (bytes == 1) ret = **utf8; /* ascii-7 */ else ret = **utf8 & (0x7F >> bytes); /* lead byte of a multibyte sequence */ (*utf8)++; for (t = 1; t < bytes; t++) /* consume trailing bytes */ ret = (ret << 6) | (*((*utf8)++) & 0x3F); return (zwchar) ret; } #if 0 /* currently unused */ /* utf8_from_ucs4_char - Convert UCS char to UTF-8 * * Returns the number of bytes put into utf8buf to represent ch, from 1 to 6, * or -1 if ch is too large to represent. utf8buf must have room for 6 bytes. */ static int utf8_from_ucs4_char(utf8buf, ch) char *utf8buf; ulg ch; { int trailing = 0; int leadmask = 0x80; int leadbits = 0x3F; int tch = ch; int ret; if (ch > 0x7FFFFFFFL) return -1; /* UTF-8 can represent 31 bits */ if (ch < 0x7F) { *utf8buf++ = (char) ch; /* ascii-7 */ return 1; } do { trailing++; leadmask = (leadmask >> 1) | 0x80; leadbits >>= 1; tch >>= 6; } while (tch & ~leadbits); ret = trailing + 1; /* produce lead byte */ *utf8buf++ = (char) (leadmask | (ch >> (6 * trailing))); while (--trailing >= 0) /* produce trailing bytes */ *utf8buf++ = (char) (0x80 | ((ch >> (6 * trailing)) & 0x3F)); return ret; } #endif /* unused */ /*===================================================================*/ /* utf8_to_ucs4_string - convert UTF-8 string to UCS string * * Return UCS count. Now returns int so can return -1. */ static int utf8_to_ucs4_string(utf8, ucs4buf, buflen) ZCONST char *utf8; ulg *ucs4buf; int buflen; { int count = 0; for (;;) { ulg ch = ucs4_char_from_utf8(&utf8); if (ch == ~0L) return -1; else { if (ucs4buf && count < buflen) ucs4buf[count] = ch; if (ch == 0) return count; count++; } } } #if 0 /* currently unused */ /* ucs4_string_to_utf8 * * */ static int ucs4_string_to_utf8(ucs4, utf8buf, buflen) ZCONST ulg *ucs4; char *utf8buf; int buflen; { char mb[6]; int count = 0; if (!ucs4) return -1; for (;;) { int mbl = utf8_from_ucs4_char(mb, *ucs4++); int c; if (mbl <= 0) return -1; /* We could optimize this a bit by passing utf8buf + count */ /* directly to utf8_from_ucs4_char when buflen >= count + 6... */ c = buflen - count; if (mbl < c) c = mbl; if (utf8buf && count < buflen) strncpy(utf8buf + count, mb, c); if (mbl == 1 && !mb[0]) return count; /* terminating nul */ count += mbl; } } /* utf8_chars * * Wrapper: counts the actual unicode characters in a UTF-8 string. */ static int utf8_chars(utf8) ZCONST char *utf8; { return utf8_to_ucs4_string(utf8, NULL, 0); } #endif /* unused */ /* --------------------------------------------------- */ /* Unicode Support * * These functions common for all Unicode ports. * * These functions should allocate and return strings that can be * freed with free(). * * 8/27/05 EG * * Use zwchar for wide char which is unsigned long * in zip.h and 32 bits. This avoids problems with * different sizes of wchar_t. */ #if 0 /* currently unused */ /* is_ascii_string * Checks if a string is all ascii */ int is_ascii_string(mbstring) ZCONST char *mbstring; { char *p; uch c; for (p = mbstring; c = (uch)*p; p++) { if (c > 0x7F) { return 0; } } return 1; } /* local to UTF-8 */ char *local_to_utf8_string(local_string) ZCONST char *local_string; { return wide_to_utf8_string(local_to_wide_string(local_string)); } # endif /* unused */ /* wide_to_escape_string provides a string that represents a wide char not in local char set An initial try at an algorithm. Suggestions welcome. According to the standard, Unicode character points are restricted to the number range from 0 to 0x10FFFF, respective 21 bits. For a hexadecimal notation, 2 octets are sufficient for the mostly used characters from the "Basic Multilingual Plane", all other Unicode characters can be represented by 3 octets (= 6 hex digits). The Unicode standard suggests to write Unicode character points as 4 resp. 6 hex digits, preprended by "U+". (e.g.: U+10FFFF for the highest character point, or U+0030 for the ASCII digit "0") However, for the purpose of escaping non-ASCII chars in an ASCII character stream, the "U" is not a very good escape initializer. Therefore, we use the following convention within our Info-ZIP code: If not an ASCII char probably need 2 bytes at least. So if a 2-byte wide encode it as 4 hex digits with a leading #U. If needs 3 bytes then prefix the string with #L. So #U1234 is a 2-byte wide character with bytes 0x12 and 0x34 while #L123456 is a 3-byte wide character with bytes 0x12, 0x34, 0x56. On Windows, wide that need two wide characters need to be converted to a single number. */ /* set this to the max bytes an escape can be */ #define MAX_ESCAPE_BYTES 8 char *wide_to_escape_string(wide_char) zwchar wide_char; { int i; zwchar w = wide_char; uch b[sizeof(zwchar)]; char d[3]; char e[11]; int len; char *r; /* fill byte array with zeros */ memzero(b, sizeof(zwchar)); /* get bytes in right to left order */ for (len = 0; w; len++) { b[len] = (char)(w % 0x100); w /= 0x100; } strcpy(e, "#"); /* either 2 bytes or 3 bytes */ if (len <= 2) { len = 2; strcat(e, "U"); } else { strcat(e, "L"); } for (i = len - 1; i >= 0; i--) { sprintf(d, "%02x", b[i]); strcat(e, d); } if ((r = malloc(strlen(e) + 1)) == NULL) { return NULL; } strcpy(r, e); return r; } #if 0 /* currently unused */ /* returns the wide character represented by the escape string */ zwchar escape_string_to_wide(escape_string) ZCONST char *escape_string; { int i; zwchar w; char c; int len; ZCONST char *e = escape_string; if (e == NULL) { return 0; } if (e[0] != '#') { /* no leading # */ return 0; } len = strlen(e); /* either #U1234 or #L123456 format */ if (len != 6 && len != 8) { return 0; } w = 0; if (e[1] == 'L') { if (len != 8) { return 0; } /* 3 bytes */ for (i = 2; i < 8; i++) { c = e[i]; if (c < '0' || c > '9') { return 0; } w = w * 0x10 + (zwchar)(c - '0'); } } else if (e[1] == 'U') { /* 2 bytes */ for (i = 2; i < 6; i++) { c = e[i]; if (c < '0' || c > '9') { return 0; } w = w * 0x10 + (zwchar)(c - '0'); } } return w; } #endif /* unused */ #ifndef WIN32 /* WIN32 supplies a special variant of this function */ /* convert wide character string to multi-byte character string */ char *wide_to_local_string(wide_string, escape_all) ZCONST zwchar *wide_string; int escape_all; { int i; wchar_t wc; int b; int state_dependent; int wsize = 0; int max_bytes = MB_CUR_MAX; char buf[9]; char *buffer = NULL; char *local_string = NULL; for (wsize = 0; wide_string[wsize]; wsize++) ; if (max_bytes < MAX_ESCAPE_BYTES) max_bytes = MAX_ESCAPE_BYTES; if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) { return NULL; } /* convert it */ buffer[0] = '\0'; /* set initial state if state-dependent encoding */ wc = (wchar_t)'a'; b = wctomb(NULL, wc); if (b == 0) state_dependent = 0; else state_dependent = 1; for (i = 0; i < wsize; i++) { if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) { /* wchar_t probably 2 bytes */ /* could do surrogates if state_dependent and wctomb can do */ wc = zwchar_to_wchar_t_default_char; } else { wc = (wchar_t)wide_string[i]; } b = wctomb(buf, wc); if (escape_all) { if (b == 1 && (uch)buf[0] <= 0x7f) { /* ASCII */ strncat(buffer, buf, b); } else { /* use escape for wide character */ char *escape_string = wide_to_escape_string(wide_string[i]); strcat(buffer, escape_string); free(escape_string); } } else if (b > 0) { /* multi-byte char */ strncat(buffer, buf, b); } else { /* no MB for this wide */ /* use escape for wide character */ char *escape_string = wide_to_escape_string(wide_string[i]); strcat(buffer, escape_string); free(escape_string); } } if ((local_string = (char *)malloc(strlen(buffer) + 1)) != NULL) { strcpy(local_string, buffer); } free(buffer); return local_string; } #endif /* !WIN32 */ #if 0 /* currently unused */ /* convert local string to display character set string */ char *local_to_display_string(local_string) ZCONST char *local_string; { char *display_string; /* For Windows, OEM string should never be bigger than ANSI string, says CharToOem description. For all other ports, just make a copy of local_string. */ if ((display_string = (char *)malloc(strlen(local_string) + 1)) == NULL) { return NULL; } strcpy(display_string, local_string); #ifdef EBCDIC { char *ebc; if ((ebc = malloc(strlen(display_string) + 1)) == NULL) { return NULL; } strtoebc(ebc, display_string); free(display_string); display_string = ebc; } #endif return display_string; } #endif /* unused */ /* UTF-8 to local */ char *utf8_to_local_string(utf8_string, escape_all) ZCONST char *utf8_string; int escape_all; { zwchar *wide = utf8_to_wide_string(utf8_string); char *loc = wide_to_local_string(wide, escape_all); free(wide); return loc; } #if 0 /* currently unused */ /* convert multi-byte character string to wide character string */ zwchar *local_to_wide_string(local_string) ZCONST char *local_string; { int wsize; wchar_t *wc_string; zwchar *wide_string; /* for now try to convert as string - fails if a bad char in string */ wsize = mbstowcs(NULL, local_string, strlen(local_string) + 1); if (wsize == (size_t)-1) { /* could not convert */ return NULL; } /* convert it */ if ((wc_string = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t))) == NULL) { return NULL; } wsize = mbstowcs(wc_string, local_string, strlen(local_string) + 1); wc_string[wsize] = (wchar_t) 0; /* in case wchar_t is not zwchar */ if ((wide_string = (zwchar *)malloc((wsize + 1) * sizeof(zwchar))) == NULL) { return NULL; } for (wsize = 0; wide_string[wsize] = (zwchar)wc_string[wsize]; wsize++) ; wide_string[wsize] = (zwchar) 0; free(wc_string); return wide_string; } /* convert wide string to UTF-8 */ char *wide_to_utf8_string(wide_string) ZCONST zwchar *wide_string; { int mbcount; char *utf8_string; /* get size of utf8 string */ mbcount = ucs4_string_to_utf8(wide_string, NULL, 0); if (mbcount == -1) return NULL; if ((utf8_string = (char *) malloc(mbcount + 1)) == NULL) { return NULL; } mbcount = ucs4_string_to_utf8(wide_string, utf8_string, mbcount + 1); if (mbcount == -1) return NULL; return utf8_string; } #endif /* unused */ /* convert UTF-8 string to wide string */ zwchar *utf8_to_wide_string(utf8_string) ZCONST char *utf8_string; { int wcount; zwchar *wide_string; wcount = utf8_to_ucs4_string(utf8_string, NULL, 0); if (wcount == -1) return NULL; if ((wide_string = (zwchar *) malloc((wcount + 1) * sizeof(zwchar))) == NULL) { return NULL; } wcount = utf8_to_ucs4_string(utf8_string, wide_string, wcount + 1); return wide_string; } #endif /* UNICODE_WCHAR */ #endif /* UNICODE_SUPPORT */ #ifdef USE_EF_UT_TIME #ifdef IZ_HAVE_UXUIDGID static int read_ux3_value(dbuf, uidgid_sz, p_uidgid) ZCONST uch *dbuf; /* buffer a uid or gid value */ unsigned uidgid_sz; /* size of uid/gid value */ ulg *p_uidgid; /* return storage: uid or gid value */ { zusz_t uidgid64; switch (uidgid_sz) { case 2: *p_uidgid = (ulg)makeword(dbuf); break; case 4: *p_uidgid = (ulg)makelong(dbuf); break; case 8: uidgid64 = makeint64(dbuf); #ifndef LARGE_FILE_SUPPORT if (uidgid64 == (zusz_t)0xffffffffL) return FALSE; #endif *p_uidgid = (ulg)uidgid64; if ((zusz_t)(*p_uidgid) != uidgid64) return FALSE; break; } return TRUE; } #endif /* IZ_HAVE_UXUIDGID */ /*******************************/ /* Function ef_scan_for_izux() */ /*******************************/ unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime, z_utim, z_uidgid) ZCONST uch *ef_buf; /* buffer containing extra field */ unsigned ef_len; /* total length of extra field */ int ef_is_c; /* flag indicating "is central extra field" */ ulg dos_mdatetime; /* last_mod_file_date_time in DOS format */ iztimes *z_utim; /* return storage: atime, mtime, ctime */ ulg *z_uidgid; /* return storage: uid and gid */ { unsigned flags = 0; unsigned eb_id; unsigned eb_len; int have_new_type_eb = 0; long i_time; /* buffer for Unix style 32-bit integer time value */ #ifdef TIME_T_TYPE_DOUBLE int ut_in_archive_sgn = 0; #else int ut_zip_unzip_compatible = FALSE; #endif /*--------------------------------------------------------------------------- This function scans the extra field for EF_TIME, EF_IZUNIX2, EF_IZUNIX, or EF_PKUNIX blocks containing Unix-style time_t (GMT) values for the entry's access, creation, and modification time. If a valid block is found, the time stamps are copied to the iztimes structure (provided the z_utim pointer is not NULL). If a IZUNIX2 block is found or the IZUNIX block contains UID/GID fields, and the z_uidgid array pointer is valid (!= NULL), the owner info is transfered as well. The presence of an EF_TIME or EF_IZUNIX2 block results in ignoring all data from probably present obsolete EF_IZUNIX blocks. If multiple blocks of the same type are found, only the information from the last block is used. The return value is a combination of the EF_TIME Flags field with an additional flag bit indicating the presence of valid UID/GID info, or 0 in case of failure. ---------------------------------------------------------------------------*/ if (ef_len == 0 || ef_buf == NULL || (z_utim == 0 && z_uidgid == NULL)) return 0; TTrace((stderr,"\nef_scan_for_izux: scanning extra field of length %u\n", ef_len)); while (ef_len >= EB_HEADSIZE) { eb_id = makeword(EB_ID + ef_buf); eb_len = makeword(EB_LEN + ef_buf); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ TTrace((stderr, "ef_scan_for_izux: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } switch (eb_id) { case EF_TIME: flags &= ~0x0ff; /* ignore previous IZUNIX or EF_TIME fields */ have_new_type_eb = 1; if ( eb_len >= EB_UT_MINLEN && z_utim != NULL) { unsigned eb_idx = EB_UT_TIME1; TTrace((stderr,"ef_scan_for_izux: found TIME extra field\n")); flags |= (ef_buf[EB_HEADSIZE+EB_UT_FLAGS] & 0x0ff); if ((flags & EB_UT_FL_MTIME)) { if ((eb_idx+4) <= eb_len) { i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf); eb_idx += 4; TTrace((stderr," UT e.f. modification time = %ld\n", i_time)); #ifdef TIME_T_TYPE_DOUBLE if ((ulg)(i_time) & (ulg)(0x80000000L)) { if (dos_mdatetime == DOSTIME_MINIMUM) { ut_in_archive_sgn = -1; z_utim->mtime = (time_t)((long)i_time | (~(long)0x7fffffffL)); } else if (dos_mdatetime >= DOSTIME_2038_01_18) { ut_in_archive_sgn = 1; z_utim->mtime = (time_t)((ulg)i_time & (ulg)0xffffffffL); } else { ut_in_archive_sgn = 0; /* cannot determine sign of mtime; without modtime: ignore complete UT field */ flags &= ~0x0ff; /* no time_t times available */ TTrace((stderr, " UT modtime range error; ignore e.f.!\n")); break; /* stop scanning this field */ } } else { /* cannot determine, safe assumption is FALSE */ ut_in_archive_sgn = 0; z_utim->mtime = (time_t)i_time; } #else /* !TIME_T_TYPE_DOUBLE */ if ((ulg)(i_time) & (ulg)(0x80000000L)) { ut_zip_unzip_compatible = ((time_t)0x80000000L < (time_t)0L) ? (dos_mdatetime == DOSTIME_MINIMUM) : (dos_mdatetime >= DOSTIME_2038_01_18); if (!ut_zip_unzip_compatible) { /* UnZip interprets mtime differently than Zip; without modtime: ignore complete UT field */ flags &= ~0x0ff; /* no time_t times available */ TTrace((stderr, " UT modtime range error; ignore e.f.!\n")); break; /* stop scanning this field */ } } else { /* cannot determine, safe assumption is FALSE */ ut_zip_unzip_compatible = FALSE; } z_utim->mtime = (time_t)i_time; #endif /* ?TIME_T_TYPE_DOUBLE */ } else { flags &= ~EB_UT_FL_MTIME; TTrace((stderr," UT e.f. truncated; no modtime\n")); } } if (ef_is_c) { break; /* central version of TIME field ends here */ } if (flags & EB_UT_FL_ATIME) { if ((eb_idx+4) <= eb_len) { i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf); eb_idx += 4; TTrace((stderr," UT e.f. access time = %ld\n", i_time)); #ifdef TIME_T_TYPE_DOUBLE if ((ulg)(i_time) & (ulg)(0x80000000L)) { if (ut_in_archive_sgn == -1) z_utim->atime = (time_t)((long)i_time | (~(long)0x7fffffffL)); } else if (ut_in_archive_sgn == 1) { z_utim->atime = (time_t)((ulg)i_time & (ulg)0xffffffffL); } else { /* sign of 32-bit time is unknown -> ignore it */ flags &= ~EB_UT_FL_ATIME; TTrace((stderr, " UT access time range error: skip time!\n")); } } else { z_utim->atime = (time_t)i_time; } #else /* !TIME_T_TYPE_DOUBLE */ if (((ulg)(i_time) & (ulg)(0x80000000L)) && !ut_zip_unzip_compatible) { flags &= ~EB_UT_FL_ATIME; TTrace((stderr, " UT access time range error: skip time!\n")); } else { z_utim->atime = (time_t)i_time; } #endif /* ?TIME_T_TYPE_DOUBLE */ } else { flags &= ~EB_UT_FL_ATIME; } } if (flags & EB_UT_FL_CTIME) { if ((eb_idx+4) <= eb_len) { i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf); TTrace((stderr," UT e.f. creation time = %ld\n", i_time)); #ifdef TIME_T_TYPE_DOUBLE if ((ulg)(i_time) & (ulg)(0x80000000L)) { if (ut_in_archive_sgn == -1) z_utim->ctime = (time_t)((long)i_time | (~(long)0x7fffffffL)); } else if (ut_in_archive_sgn == 1) { z_utim->ctime = (time_t)((ulg)i_time & (ulg)0xffffffffL); } else { /* sign of 32-bit time is unknown -> ignore it */ flags &= ~EB_UT_FL_CTIME; TTrace((stderr, " UT creation time range error: skip time!\n")); } } else { z_utim->ctime = (time_t)i_time; } #else /* !TIME_T_TYPE_DOUBLE */ if (((ulg)(i_time) & (ulg)(0x80000000L)) && !ut_zip_unzip_compatible) { flags &= ~EB_UT_FL_CTIME; TTrace((stderr, " UT creation time range error: skip time!\n")); } else { z_utim->ctime = (time_t)i_time; } #endif /* ?TIME_T_TYPE_DOUBLE */ } else { flags &= ~EB_UT_FL_CTIME; } } } break; case EF_IZUNIX2: if (have_new_type_eb == 0) { flags &= ~0x0ff; /* ignore any previous IZUNIX field */ have_new_type_eb = 1; } #ifdef IZ_HAVE_UXUIDGID if (have_new_type_eb > 1) break; /* IZUNIX3 overrides IZUNIX2 e.f. block ! */ if (eb_len == EB_UX2_MINLEN && z_uidgid != NULL) { z_uidgid[0] = (ulg)makeword((EB_HEADSIZE+EB_UX2_UID) + ef_buf); z_uidgid[1] = (ulg)makeword((EB_HEADSIZE+EB_UX2_GID) + ef_buf); flags |= EB_UX2_VALID; /* signal success */ } #endif break; case EF_IZUNIX3: /* new 3rd generation Unix ef */ have_new_type_eb = 2; /* Version 1 byte version of this extra field, currently 1 UIDSize 1 byte Size of UID field UID Variable UID for this entry GIDSize 1 byte Size of GID field GID Variable GID for this entry */ #ifdef IZ_HAVE_UXUIDGID if (eb_len >= EB_UX3_MINLEN && z_uidgid != NULL && (*((EB_HEADSIZE + 0) + ef_buf) == 1) /* only know about version 1 */ { uch uid_size; uch gid_size; uid_size = *((EB_HEADSIZE + 1) + ef_buf); gid_size = *((EB_HEADSIZE + uid_size + 2) + ef_buf); flags &= ~0x0ff; /* ignore any previous UNIX field */ if ( read_ux3_value((EB_HEADSIZE + 2) + ef_buf, uid_size, z_uidgid[0]) && read_ux3_value((EB_HEADSIZE + uid_size + 3) + ef_buf, gid_size, z_uidgid[1]) ) { flags |= EB_UX2_VALID; /* signal success */ } } #endif /* IZ_HAVE_UXUIDGID */ break; case EF_IZUNIX: case EF_PKUNIX: /* PKUNIX e.f. layout is identical to IZUNIX */ if (eb_len >= EB_UX_MINLEN) { TTrace((stderr,"ef_scan_for_izux: found %s extra field\n", (eb_id == EF_IZUNIX ? "IZUNIX" : "PKUNIX"))); if (have_new_type_eb > 0) { break; /* Ignore IZUNIX extra field block ! */ } if (z_utim != NULL) { flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME); i_time = (long)makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf); TTrace((stderr," Unix EF modtime = %ld\n", i_time)); #ifdef TIME_T_TYPE_DOUBLE if ((ulg)(i_time) & (ulg)(0x80000000L)) { if (dos_mdatetime == DOSTIME_MINIMUM) { ut_in_archive_sgn = -1; z_utim->mtime = (time_t)((long)i_time | (~(long)0x7fffffffL)); } else if (dos_mdatetime >= DOSTIME_2038_01_18) { ut_in_archive_sgn = 1; z_utim->mtime = (time_t)((ulg)i_time & (ulg)0xffffffffL); } else { ut_in_archive_sgn = 0; /* cannot determine sign of mtime; without modtime: ignore complete UT field */ flags &= ~0x0ff; /* no time_t times available */ TTrace((stderr, " UX modtime range error: ignore e.f.!\n")); } } else { /* cannot determine, safe assumption is FALSE */ ut_in_archive_sgn = 0; z_utim->mtime = (time_t)i_time; } #else /* !TIME_T_TYPE_DOUBLE */ if ((ulg)(i_time) & (ulg)(0x80000000L)) { ut_zip_unzip_compatible = ((time_t)0x80000000L < (time_t)0L) ? (dos_mdatetime == DOSTIME_MINIMUM) : (dos_mdatetime >= DOSTIME_2038_01_18); if (!ut_zip_unzip_compatible) { /* UnZip interpretes mtime differently than Zip; without modtime: ignore complete UT field */ flags &= ~0x0ff; /* no time_t times available */ TTrace((stderr, " UX modtime range error: ignore e.f.!\n")); } } else { /* cannot determine, safe assumption is FALSE */ ut_zip_unzip_compatible = FALSE; } z_utim->mtime = (time_t)i_time; #endif /* ?TIME_T_TYPE_DOUBLE */ i_time = (long)makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf); TTrace((stderr," Unix EF actime = %ld\n", i_time)); #ifdef TIME_T_TYPE_DOUBLE if ((ulg)(i_time) & (ulg)(0x80000000L)) { if (ut_in_archive_sgn == -1) z_utim->atime = (time_t)((long)i_time | (~(long)0x7fffffffL)); } else if (ut_in_archive_sgn == 1) { z_utim->atime = (time_t)((ulg)i_time & (ulg)0xffffffffL); } else if (flags & 0x0ff) { /* sign of 32-bit time is unknown -> ignore it */ flags &= ~EB_UT_FL_ATIME; TTrace((stderr, " UX access time range error: skip time!\n")); } } else { z_utim->atime = (time_t)i_time; } #else /* !TIME_T_TYPE_DOUBLE */ if (((ulg)(i_time) & (ulg)(0x80000000L)) && !ut_zip_unzip_compatible && (flags & 0x0ff)) { /* atime not in range of UnZip's time_t */ flags &= ~EB_UT_FL_ATIME; TTrace((stderr, " UX access time range error: skip time!\n")); } else { z_utim->atime = (time_t)i_time; } #endif /* ?TIME_T_TYPE_DOUBLE */ } #ifdef IZ_HAVE_UXUIDGID if (eb_len >= EB_UX_FULLSIZE && z_uidgid != NULL) { z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX_UID) + ef_buf); z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX_GID) + ef_buf); flags |= EB_UX2_VALID; } #endif /* IZ_HAVE_UXUIDGID */ } break; default: break; } /* Skip this extra field block */ ef_buf += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return flags; } #endif /* USE_EF_UT_TIME */ #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS)) #define SPARKID_2 0x30435241 /* = "ARC0" */ /*******************************/ /* Function getRISCOSexfield() */ /*******************************/ zvoid *getRISCOSexfield(ef_buf, ef_len) ZCONST uch *ef_buf; /* buffer containing extra field */ unsigned ef_len; /* total length of extra field */ { unsigned eb_id; unsigned eb_len; /*--------------------------------------------------------------------------- This function scans the extra field for a Acorn SPARK filetype ef-block. If a valid block is found, the function returns a pointer to the start of the SPARK_EF block in the extra field buffer. Otherwise, a NULL pointer is returned. ---------------------------------------------------------------------------*/ if (ef_len == 0 || ef_buf == NULL) return NULL; Trace((stderr,"\ngetRISCOSexfield: scanning extra field of length %u\n", ef_len)); while (ef_len >= EB_HEADSIZE) { eb_id = makeword(EB_ID + ef_buf); eb_len = makeword(EB_LEN + ef_buf); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ Trace((stderr, "getRISCOSexfield: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } if (eb_id == EF_SPARK && (eb_len == 24 || eb_len == 20)) { if (makelong(EB_HEADSIZE + ef_buf) == SPARKID_2) { /* Return a pointer to the valid SPARK filetype ef block */ return (zvoid *)ef_buf; } } /* Skip this extra field block */ ef_buf += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return NULL; } #endif /* (RISCOS || ACORN_FTYPE_NFS) */ Carla-2.1/data/windows/unzipfx-carla/ttyio.c000066400000000000000000000510341364475620200211140ustar00rootroot00000000000000/* Copyright (c) 1990-2008 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- ttyio.c This file contains routines for doing console input/output, including code for non-echoing input. It is used by the encryption/decryption code but does not contain any restricted code itself. This file is shared between Info-ZIP's Zip and UnZip. Contains: echo() (VMS only) Echon() (Unix only) Echoff() (Unix only) screensize() (Unix only) zgetch() (Unix, VMS, and non-Unix/VMS versions) getp() ("PC," Unix/Atari/Be, VMS/VMCMS/MVS) ---------------------------------------------------------------------------*/ #define __TTYIO_C /* identifies this source module */ #include "zip.h" #include "crypt.h" #if (CRYPT || (defined(UNZIP) && !defined(FUNZIP))) /* Non-echo console/keyboard input is needed for (en/de)cryption's password * entry, and for UnZip(SFX)'s MORE and Pause features. * (The corresponding #endif is found at the end of this module.) */ #include "ttyio.h" #ifndef PUTC # define PUTC putc #endif #ifdef ZIP # ifdef GLOBAL /* used in Amiga system headers, maybe others too */ # undef GLOBAL # endif # define GLOBAL(g) g #else # define GLOBAL(g) G.g #endif #if (defined(__ATHEOS__) || defined(__BEOS__)) /* why yes, we do */ # define HAVE_TERMIOS_H #endif #ifdef _POSIX_VERSION # ifndef USE_POSIX_TERMIOS # define USE_POSIX_TERMIOS /* use POSIX style termio (termios) */ # endif # ifndef HAVE_TERMIOS_H # define HAVE_TERMIOS_H /* POSIX termios.h */ # endif #endif /* _POSIX_VERSION */ #ifdef UNZIP /* Zip handles this with the unix/configure script */ # ifndef _POSIX_VERSION # if (defined(SYSV) || defined(CRAY)) && !defined(__MINT__) # ifndef USE_SYSV_TERMIO # define USE_SYSV_TERMIO # endif # ifdef COHERENT # ifndef HAVE_TERMIO_H # define HAVE_TERMIO_H # endif # ifdef HAVE_SYS_TERMIO_H # undef HAVE_SYS_TERMIO_H # endif # else /* !COHERENT */ # ifdef HAVE_TERMIO_H # undef HAVE_TERMIO_H # endif # ifndef HAVE_SYS_TERMIO_H # define HAVE_SYS_TERMIO_H # endif # endif /* ?COHERENT */ # endif /* (SYSV || CRAY) && !__MINT__ */ # endif /* !_POSIX_VERSION */ # if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__)) # ifndef NO_FCNTL_H # define NO_FCNTL_H # endif # endif /* !(BSD4_4 || SYSV || __convexc__) */ #endif /* UNZIP */ #ifdef HAVE_TERMIOS_H # ifndef USE_POSIX_TERMIOS # define USE_POSIX_TERMIOS # endif #endif #if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H)) # ifndef USE_SYSV_TERMIO # define USE_SYSV_TERMIO # endif #endif #if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE)) # include # define GOT_IOCTL_H /* int ioctl OF((int, int, zvoid *)); GRR: may need for some systems */ #endif #ifndef HAVE_WORKING_GETCH /* include system support for switching of console echo */ # ifdef VMS # include # include # include /* Workaround for broken header files of older DECC distributions * that are incompatible with the /NAMES=AS_IS qualifier. */ # define sys$assign SYS$ASSIGN # define sys$dassgn SYS$DASSGN # define sys$qiow SYS$QIOW # include # include # else /* !VMS */ # ifdef HAVE_TERMIOS_H # include # define sgttyb termios # define sg_flags c_lflag # define GTTY(f, s) tcgetattr(f, (zvoid *) s) # define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s) # else /* !HAVE_TERMIOS_H */ # ifdef USE_SYSV_TERMIO /* Amdahl, Cray, all SysV? */ # ifdef HAVE_TERMIO_H # include # endif # ifdef HAVE_SYS_TERMIO_H # include # endif # ifdef NEED_PTEM # include # include # endif # define sgttyb termio # define sg_flags c_lflag # define GTTY(f,s) ioctl(f,TCGETA,(zvoid *)s) # define STTY(f,s) ioctl(f,TCSETAW,(zvoid *)s) # else /* !USE_SYSV_TERMIO */ # ifndef CMS_MVS # if (!defined(MINIX) && !defined(GOT_IOCTL_H)) # include # endif # include # define GTTY gtty # define STTY stty # ifdef UNZIP /* * XXX : Are these declarations needed at all ???? */ /* * GRR: let's find out... Hmmm, appears not... int gtty OF((int, struct sgttyb *)); int stty OF((int, struct sgttyb *)); */ # endif # endif /* !CMS_MVS */ # endif /* ?USE_SYSV_TERMIO */ # endif /* ?HAVE_TERMIOS_H */ # ifndef NO_FCNTL_H # ifndef UNZIP # include # endif # else char *ttyname OF((int)); # endif # endif /* ?VMS */ #endif /* !HAVE_WORKING_GETCH */ #ifndef HAVE_WORKING_GETCH #ifdef VMS static struct dsc$descriptor_s DevDesc = {11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND"}; /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */ /* * Turn keyboard echoing on or off (VMS). Loosely based on VMSmunch.c * and hence on Joe Meadows' file.c code. */ int echo(opt) int opt; { /* * For VMS v5.x: * IO$_SENSEMODE/SETMODE info: Programming, Vol. 7A, System Programming, * I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6 * sys$assign(), sys$qio() info: Programming, Vol. 4B, System Services, * System Services Reference Manual, pp. sys-23, sys-379 * fixed-length descriptor info: Programming, Vol. 3, System Services, * Intro to System Routines, sec. 2.9.2 * Greg Roelofs, 15 Aug 91 */ short DevChan, iosb[4]; long status; unsigned long ttmode[2]; /* space for 8 bytes */ /* assign a channel to standard input */ status = sys$assign(&DevDesc, &DevChan, 0, 0); if (!(status & 1)) return status; /* use sys$qio and the IO$_SENSEMODE function to determine the current * tty status (for password reading, could use IO$_READVBLK function * instead, but echo on/off will be more general) */ status = sys$qiow(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0, ttmode, 8, 0, 0, 0, 0); if (!(status & 1)) return status; status = iosb[0]; if (!(status & 1)) return status; /* modify mode buffer to be either NOECHO or ECHO * (depending on function argument opt) */ if (opt == 0) /* off */ ttmode[1] |= TT$M_NOECHO; /* set NOECHO bit */ else ttmode[1] &= ~((unsigned long) TT$M_NOECHO); /* clear NOECHO bit */ /* use the IO$_SETMODE function to change the tty status */ status = sys$qiow(0, DevChan, IO$_SETMODE, &iosb, 0, 0, ttmode, 8, 0, 0, 0, 0); if (!(status & 1)) return status; status = iosb[0]; if (!(status & 1)) return status; /* deassign the sys$input channel by way of clean-up */ status = sys$dassgn(DevChan); if (!(status & 1)) return status; return SS$_NORMAL; /* we be happy */ } /* end function echo() */ /* * Read a single character from keyboard in non-echoing mode (VMS). * (returns EOF in case of errors) */ int tt_getch() { short DevChan, iosb[4]; long status; char kbbuf[16]; /* input buffer with - some - excess length */ /* assign a channel to standard input */ status = sys$assign(&DevDesc, &DevChan, 0, 0); if (!(status & 1)) return EOF; /* read a single character from SYS$COMMAND (no-echo) and * wait for completion */ status = sys$qiow(0,DevChan, IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR, &iosb, 0, 0, &kbbuf, 1, 0, 0, 0, 0); if ((status&1) == 1) status = iosb[0]; /* deassign the sys$input channel by way of clean-up * (for this step, we do not need to check the completion status) */ sys$dassgn(DevChan); /* return the first char read, or EOF in case the read request failed */ return (int)(((status&1) == 1) ? (uch)kbbuf[0] : EOF); } /* end function tt_getch() */ #else /* !VMS: basically Unix */ /* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */ #ifndef CMS_MVS #ifdef ZIP /* moved to globals.h for UnZip */ static int echofd=(-1); /* file descriptor whose echo is off */ #endif /* * Turn echo off for file descriptor f. Assumes that f is a tty device. */ void Echoff(__G__ f) __GDEF int f; /* file descriptor for which to turn echo off */ { struct sgttyb sg; /* tty device structure */ GLOBAL(echofd) = f; GTTY(f, &sg); /* get settings */ sg.sg_flags &= ~ECHO; /* turn echo off */ STTY(f, &sg); } /* * Turn echo back on for file descriptor echofd. */ void Echon(__G) __GDEF { struct sgttyb sg; /* tty device structure */ if (GLOBAL(echofd) != -1) { GTTY(GLOBAL(echofd), &sg); /* get settings */ sg.sg_flags |= ECHO; /* turn echo on */ STTY(GLOBAL(echofd), &sg); GLOBAL(echofd) = -1; } } #endif /* !CMS_MVS */ #endif /* ?VMS */ #if (defined(UNZIP) && !defined(FUNZIP)) #ifdef ATH_BEO_UNX #ifdef MORE /* * Get the number of lines on the output terminal. SCO Unix apparently * defines TIOCGWINSZ but doesn't support it (!M_UNIX). * * GRR: will need to know width of terminal someday, too, to account for * line-wrapping. */ #if (defined(TIOCGWINSZ) && !defined(M_UNIX)) int screensize(tt_rows, tt_cols) int *tt_rows; int *tt_cols; { struct winsize wsz; #ifdef DEBUG_WINSZ static int firsttime = TRUE; #endif /* see termio(4) under, e.g., SunOS */ if (ioctl(1, TIOCGWINSZ, &wsz) == 0) { #ifdef DEBUG_WINSZ if (firsttime) { firsttime = FALSE; fprintf(stderr, "ttyio.c screensize(): ws_row = %d\n", wsz.ws_row); fprintf(stderr, "ttyio.c screensize(): ws_col = %d\n", wsz.ws_col); } #endif /* number of rows */ if (tt_rows != NULL) *tt_rows = (int)((wsz.ws_row > 0) ? wsz.ws_row : 24); /* number of columns */ if (tt_cols != NULL) *tt_cols = (int)((wsz.ws_col > 0) ? wsz.ws_col : 80); return 0; /* signal success */ } else { /* this happens when piping to more(1), for example */ #ifdef DEBUG_WINSZ if (firsttime) { firsttime = FALSE; fprintf(stderr, "ttyio.c screensize(): ioctl(TIOCGWINSZ) failed\n")); } #endif /* VT-100 assumed to be minimal hardware */ if (tt_rows != NULL) *tt_rows = 24; if (tt_cols != NULL) *tt_cols = 80; return 1; /* signal failure */ } } #else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */ int screensize(tt_rows, tt_cols) int *tt_rows; int *tt_cols; { char *envptr, *getenv(); int n; int errstat = 0; /* GRR: this is overly simplistic, but don't have access to stty/gtty * system anymore */ if (tt_rows != NULL) { envptr = getenv("LINES"); if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) { /* VT-100 assumed to be minimal hardware */ *tt_rows = 24; errstat = 1; /* signal failure */ } else { *tt_rows = n; } } if (tt_cols != NULL) { envptr = getenv("COLUMNS"); if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) { *tt_cols = 80; errstat = 1; /* signal failure */ } else { *tt_cols = n; } } return errstat; } #endif /* ?(TIOCGWINSZ && !M_UNIX) */ #endif /* MORE */ /* * Get a character from the given file descriptor without echo or newline. */ int zgetch(__G__ f) __GDEF int f; /* file descriptor from which to read */ { #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)) char oldmin, oldtim; #endif char c; struct sgttyb sg; /* tty device structure */ GTTY(f, &sg); /* get settings */ #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)) oldmin = sg.c_cc[VMIN]; /* save old values */ oldtim = sg.c_cc[VTIME]; sg.c_cc[VMIN] = 1; /* need only one char to return read() */ sg.c_cc[VTIME] = 0; /* no timeout */ sg.sg_flags &= ~ICANON; /* canonical mode off */ #else sg.sg_flags |= CBREAK; /* cbreak mode on */ #endif sg.sg_flags &= ~ECHO; /* turn echo off, too */ STTY(f, &sg); /* set cbreak mode */ GLOBAL(echofd) = f; /* in case ^C hit (not perfect: still CBREAK) */ read(f, &c, 1); /* read our character */ #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)) sg.c_cc[VMIN] = oldmin; /* restore old values */ sg.c_cc[VTIME] = oldtim; sg.sg_flags |= ICANON; /* canonical mode on */ #else sg.sg_flags &= ~CBREAK; /* cbreak mode off */ #endif sg.sg_flags |= ECHO; /* turn echo on */ STTY(f, &sg); /* restore canonical mode */ GLOBAL(echofd) = -1; return (int)(uch)c; } #else /* !ATH_BEO_UNX */ #ifndef VMS /* VMS supplies its own variant of getch() */ int zgetch(__G__ f) __GDEF int f; /* file descriptor from which to read (must be open already) */ { char c, c2; /*--------------------------------------------------------------------------- Get a character from the given file descriptor without echo; can't fake CBREAK mode (i.e., newline required), but can get rid of all chars up to and including newline. ---------------------------------------------------------------------------*/ echoff(f); read(f, &c, 1); if (c != '\n') do { read(f, &c2, 1); /* throw away all other chars up thru newline */ } while (c2 != '\n'); echon(); return (int)c; } #endif /* !VMS */ #endif /* ?ATH_BEO_UNX */ #endif /* UNZIP && !FUNZIP */ #endif /* !HAVE_WORKING_GETCH */ #if CRYPT /* getp() is only used with full encryption */ /* * Simple compile-time check for source compatibility between * zcrypt and ttyio: */ #if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7)) error: This Info-ZIP tool requires zcrypt 2.7 or later. #endif /* * Get a password of length n-1 or less into *p using the prompt *m. * The entered password is not echoed. */ #ifdef HAVE_WORKING_GETCH /* * For the AMIGA, getch() is defined as Agetch(), which is in * amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch() * uses the infrastructure that is already in place in filedate.c, it is * smaller. With this function, echoff() and echon() are not needed. * * For the MAC, a non-echo macgetch() function is defined in the MacOS * specific sources which uses the event handling mechanism of the * desktop window manager to get a character from the keyboard. * * For the other systems in this section, a non-echo getch() function * is either contained the C runtime library (conio package), or getch() * is defined as an alias for a similar system specific RTL function. */ #ifndef WINDLL /* WINDLL does not support a console interface */ #ifndef QDOS /* QDOS supplies a variant of this function */ /* This is the getp() function for all systems (with TTY type user interface) * that supply a working `non-echo' getch() function for "raw" console input. */ char *getp(__G__ m, p, n) __GDEF ZCONST char *m; /* prompt for password */ char *p; /* return value: line input */ int n; /* bytes available in p[] */ { char c; /* one-byte buffer for read() to use */ int i; /* number of characters input */ char *w; /* warning on retry */ /* get password */ w = ""; do { fputs(w, stderr); /* warning if back again */ fputs(m, stderr); /* display prompt and flush */ fflush(stderr); i = 0; do { /* read line, keeping first n characters */ if ((c = (char)getch()) == '\r') c = '\n'; /* until user hits CR */ if (c == 8 || c == 127) { if (i > 0) i--; /* the `backspace' and `del' keys works */ } else if (i < n) p[i++] = c; /* truncate past n */ } while (c != '\n'); PUTC('\n', stderr); fflush(stderr); w = "(line too long--try again)\n"; } while (p[i-1] != '\n'); p[i-1] = 0; /* terminate at newline */ return p; /* return pointer to password */ } /* end function getp() */ #endif /* !QDOS */ #endif /* !WINDLL */ #else /* !HAVE_WORKING_GETCH */ #if (defined(ATH_BEO_UNX) || defined(__MINT__)) #ifndef _PATH_TTY # ifdef __MINT__ # define _PATH_TTY ttyname(2) # else # define _PATH_TTY "/dev/tty" # endif #endif char *getp(__G__ m, p, n) __GDEF ZCONST char *m; /* prompt for password */ char *p; /* return value: line input */ int n; /* bytes available in p[] */ { char c; /* one-byte buffer for read() to use */ int i; /* number of characters input */ char *w; /* warning on retry */ int f; /* file descriptor for tty device */ #ifdef PASSWD_FROM_STDIN /* Read from stdin. This is unsafe if the password is stored on disk. */ f = 0; #else /* turn off echo on tty */ if ((f = open(_PATH_TTY, 0)) == -1) return NULL; #endif /* get password */ w = ""; do { fputs(w, stderr); /* warning if back again */ fputs(m, stderr); /* prompt */ fflush(stderr); i = 0; echoff(f); do { /* read line, keeping n */ read(f, &c, 1); if (i < n) p[i++] = c; } while (c != '\n'); echon(); PUTC('\n', stderr); fflush(stderr); w = "(line too long--try again)\n"; } while (p[i-1] != '\n'); p[i-1] = 0; /* terminate at newline */ #ifndef PASSWD_FROM_STDIN close(f); #endif return p; /* return pointer to password */ } /* end function getp() */ #endif /* ATH_BEO_UNX || __MINT__ */ #if (defined(VMS) || defined(CMS_MVS)) char *getp(__G__ m, p, n) __GDEF ZCONST char *m; /* prompt for password */ char *p; /* return value: line input */ int n; /* bytes available in p[] */ { char c; /* one-byte buffer for read() to use */ int i; /* number of characters input */ char *w; /* warning on retry */ FILE *f; /* file structure for SYS$COMMAND device */ #ifdef PASSWD_FROM_STDIN f = stdin; #else if ((f = fopen(ctermid(NULL), "r")) == NULL) return NULL; #endif /* get password */ fflush(stdout); w = ""; do { if (*w) /* bug: VMS apparently adds \n to NULL fputs */ fputs(w, stderr); /* warning if back again */ fputs(m, stderr); /* prompt */ fflush(stderr); i = 0; echoff(f); do { /* read line, keeping n */ if ((c = (char)getc(f)) == '\r') c = '\n'; if (i < n) p[i++] = c; } while (c != '\n'); echon(); PUTC('\n', stderr); fflush(stderr); w = "(line too long--try again)\n"; } while (p[i-1] != '\n'); p[i-1] = 0; /* terminate at newline */ #ifndef PASSWD_FROM_STDIN fclose(f); #endif return p; /* return pointer to password */ } /* end function getp() */ #endif /* VMS || CMS_MVS */ #endif /* ?HAVE_WORKING_GETCH */ #endif /* CRYPT */ #endif /* CRYPT || (UNZIP && !FUNZIP) */ Carla-2.1/data/windows/unzipfx-carla/ttyio.h000066400000000000000000000123441364475620200211220ustar00rootroot00000000000000/* Copyright (c) 1990-2004 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* ttyio.h */ #ifndef __ttyio_h /* don't include more than once */ #define __ttyio_h #ifndef __crypt_h # include "crypt.h" /* ensure that encryption header file has been seen */ #endif #if (CRYPT || (defined(UNZIP) && !defined(FUNZIP))) /* * Non-echo keyboard/console input support is needed and enabled. */ #ifndef __G /* UnZip only, for now (DLL stuff) */ # define __G # define __G__ # define __GDEF # define __GPRO void # define __GPRO__ #endif #ifndef ZCONST /* UnZip only (until have configure script like Zip) */ # define ZCONST const #endif #if (defined(MSDOS) || defined(OS2) || defined(WIN32)) # ifndef DOS_OS2_W32 # define DOS_OS2_W32 # endif #endif #if (defined(DOS_OS2_W32) || defined(__human68k__)) # ifndef DOS_H68_OS2_W32 # define DOS_H68_OS2_W32 # endif #endif #if (defined(DOS_OS2_W32) || defined(FLEXOS)) # ifndef DOS_FLX_OS2_W32 # define DOS_FLX_OS2_W32 # endif #endif #if (defined(DOS_H68_OS2_W32) || defined(FLEXOS)) # ifndef DOS_FLX_H68_OS2_W32 # define DOS_FLX_H68_OS2_W32 # endif #endif #if (defined(__ATHEOS__) || defined(__BEOS__) || defined(UNIX)) # ifndef ATH_BEO_UNX # define ATH_BEO_UNX # endif #endif #if (defined(VM_CMS) || defined(MVS)) # ifndef CMS_MVS # define CMS_MVS # endif #endif /* Function prototypes */ /* The following systems supply a `non-echo' character input function "getch()" * (or an alias) and do not need the echoff() / echon() function pair. */ #ifdef AMIGA # define echoff(f) # define echon() # define getch() Agetch() # define HAVE_WORKING_GETCH #endif /* AMIGA */ #ifdef ATARI # define echoff(f) # define echon() # include # define getch() (Cnecin() & 0x000000ff) # define HAVE_WORKING_GETCH #endif #ifdef MACOS # define echoff(f) # define echon() # define getch() macgetch() # define HAVE_WORKING_GETCH #endif #ifdef NLM # define echoff(f) # define echon() # define HAVE_WORKING_GETCH #endif #ifdef QDOS # define echoff(f) # define echon() # define HAVE_WORKING_GETCH #endif #ifdef RISCOS # define echoff(f) # define echon() # define getch() SWI_OS_ReadC() # define HAVE_WORKING_GETCH #endif #ifdef DOS_H68_OS2_W32 # define echoff(f) # define echon() # ifdef WIN32 # ifndef getch # define getch() getch_win32() # endif # else /* !WIN32 */ # ifdef __EMX__ # ifndef getch # define getch() _read_kbd(0, 1, 0) # endif # else /* !__EMX__ */ # ifdef __GO32__ # include # define getch() getkey() # else /* !__GO32__ */ # include # endif /* ?__GO32__ */ # endif /* ?__EMX__ */ # endif /* ?WIN32 */ # define HAVE_WORKING_GETCH #endif /* DOS_H68_OS2_W32 */ #ifdef FLEXOS # define echoff(f) # define echon() # define getch() getchar() /* not correct, but may not be on a console */ # define HAVE_WORKING_GETCH #endif /* For VM/CMS and MVS, we do not (yet) have any support to switch terminal * input echo on and off. The following "fake" definitions allow inclusion * of crypt support and UnZip's "pause prompting" features, but without * any echo suppression. */ #ifdef CMS_MVS # define echoff(f) # define echon() #endif #ifdef TANDEM # define echoff(f) # define echon() # define getch() zgetch() /* defined in TANDEMC */ # define HAVE_WORKING_GETCH #endif /* The THEOS C runtime library supplies the function conmask() to toggle * terminal input echo on (conmask("e")) and off (conmask("n")). But, * since THEOS C RTL also contains a working non-echo getch() function, * the echo toggles are not needed. */ #ifdef THEOS # define echoff(f) # define echon() # define HAVE_WORKING_GETCH #endif /* VMS has a single echo() function in ttyio.c to toggle terminal * input echo on and off. */ #ifdef VMS # define echoff(f) echo(0) # define echon() echo(1) # define getch() tt_getch() # define FGETCH(f) tt_getch() int echo OF((int)); int tt_getch OF((void)); #endif /* For all other systems, ttyio.c supplies the two functions Echoff() and * Echon() for suppressing and (re)enabling console input echo. */ #ifndef echoff # define echoff(f) Echoff(__G__ f) # define echon() Echon(__G) void Echoff OF((__GPRO__ int f)); void Echon OF((__GPRO)); #endif /* this stuff is used by MORE and also now by the ctrl-S code; fileio.c only */ #if (defined(UNZIP) && !defined(FUNZIP)) # ifdef HAVE_WORKING_GETCH # define FGETCH(f) getch() # endif # ifndef FGETCH /* default for all systems where no getch()-like function is available */ int zgetch OF((__GPRO__ int f)); # define FGETCH(f) zgetch(__G__ f) # endif #endif /* UNZIP && !FUNZIP */ #if (CRYPT && !defined(WINDLL)) char *getp OF((__GPRO__ ZCONST char *m, char *p, int n)); #endif #else /* !(CRYPT || (UNZIP && !FUNZIP)) */ /* * No need for non-echo keyboard/console input; provide dummy definitions. */ #define echoff(f) #define echon() #endif /* ?(CRYPT || (UNZIP && !FUNZIP)) */ #endif /* !__ttyio_h */ Carla-2.1/data/windows/unzipfx-carla/ubz2err.c000066400000000000000000000036551364475620200213450ustar00rootroot00000000000000/* Copyright (c) 1990-2008 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2007-Mar-04 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- ubz2err.c This file contains the "fatal error" callback routine required by the "minimal" (silent, non-stdio) setup of the bzip2 compression library. The fatal bzip2 error bail-out routine is provided in a separate code module, so that it can be easily overridden when the UnZip package is used as a static link library. One example is the WinDLL static library usage for building a monolythic binary of the Windows application "WiZ" that supports bzip2 both in compression and decompression operations. Contains: bz_internal_error() (USE_BZIP2 only) ---------------------------------------------------------------------------*/ #define __UBZ2ERR_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" #ifdef WINDLL # ifdef POCKET_UNZIP # include "wince/intrface.h" # else # include "windll/windll.h" # endif #endif #ifdef USE_BZIP2 /**********************************/ /* Function bz_internal_error() */ /**********************************/ /* Call-back function for the bzip2 decompression code (compiled with * BZ_NO_STDIO), required to handle fatal internal bug-type errors of * the bzip2 library. */ void bz_internal_error(bzerrcode) int bzerrcode; { GETGLOBALS(); Info(slide, 0x421, ((char *)slide, "error: internal fatal libbzip2 error number %d\n", bzerrcode)); #ifdef WINDLL longjmp(dll_error_return, 1); #else DESTROYGLOBALS(); EXIT(PK_BADERR); #endif } /* end function bz_internal_error() */ #endif /* USE_BZIP2 */ Carla-2.1/data/windows/unzipfx-carla/unix/000077500000000000000000000000001364475620200205605ustar00rootroot00000000000000Carla-2.1/data/windows/unzipfx-carla/unix/unix.c000066400000000000000000001711131364475620200217130ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- unix.c Unix-specific routines for use with Info-ZIP's UnZip 5.41 and later. Contains: readdir() do_wild() <-- generic enough to put in fileio.c? mapattr() mapname() checkdir() mkdir() close_outfile() defer_dir_attribs() set_direc_attribs() stamp_file() version() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #ifdef SCO_XENIX # define SYSNDIR #else /* SCO Unix, AIX, DNIX, TI SysV, Coherent 4.x, ... */ # if defined(__convexc__) || defined(SYSV) || defined(CRAY) || defined(BSD4_4) # define DIRENT # endif #endif #if defined(_AIX) || defined(__mpexl) # define DIRENT #endif #ifdef COHERENT # if defined(_I386) || (defined(__COHERENT__) && (__COHERENT__ >= 0x420)) # define DIRENT # endif #endif #ifdef _POSIX_VERSION # ifndef DIRENT # define DIRENT # endif #endif #ifdef DIRENT # include #else # ifdef SYSV # ifdef SYSNDIR # include # else # include # endif # else /* !SYSV */ # ifndef NO_SYSDIR # include # endif # endif /* ?SYSV */ # ifndef dirent # define dirent direct # endif #endif /* ?DIRENT */ #ifdef SET_DIR_ATTRIB typedef struct uxdirattr { /* struct for holding unix style directory */ struct uxdirattr *next; /* info until can be sorted and set at end */ char *fn; /* filename of directory */ union { iztimes t3; /* mtime, atime, ctime */ ztimbuf t2; /* modtime, actime */ } u; unsigned perms; /* same as min_info.file_attr */ int have_uidgid; /* flag */ ulg uidgid[2]; char fnbuf[1]; /* buffer stub for directory name */ } uxdirattr; #define UxAtt(d) ((uxdirattr *)d) /* typecast shortcut */ #endif /* SET_DIR_ATTRIB */ #ifdef ACORN_FTYPE_NFS /* Acorn bits for NFS filetyping */ typedef struct { uch ID[2]; uch size[2]; uch ID_2[4]; uch loadaddr[4]; uch execaddr[4]; uch attr[4]; } RO_extra_block; #endif /* ACORN_FTYPE_NFS */ /* static int created_dir; */ /* used in mapname(), checkdir() */ /* static int renamed_fullpath; */ /* ditto */ static unsigned filtattr OF((__GPRO__ unsigned perms)); /*****************************/ /* Strings used multiple */ /* times in unix.c */ /*****************************/ #ifndef MTS /* messages of code for setting file/directory attributes */ static ZCONST char CannotSetItemUidGid[] = "warning: cannot set UID %lu and/or GID %lu for %s\n %s\n"; static ZCONST char CannotSetUidGid[] = " (warning) cannot set UID %lu and/or GID %lu\n %s"; static ZCONST char CannotSetItemTimestamps[] = "warning: cannot set modif./access times for %s\n %s\n"; static ZCONST char CannotSetTimestamps[] = " (warning) cannot set modif./access times\n %s"; #endif /* !MTS */ #ifndef SFX #ifdef NO_DIR /* for AT&T 3B1 */ #define opendir(path) fopen(path,"r") #define closedir(dir) fclose(dir) typedef FILE DIR; typedef struct zdir { FILE *dirhandle; struct dirent *entry; } DIR DIR *opendir OF((ZCONST char *dirspec)); void closedir OF((DIR *dirp)); struct dirent *readdir OF((DIR *dirp)); DIR *opendir(dirspec) ZCONST char *dirspec; { DIR *dirp; if ((dirp = malloc(sizeof(DIR)) != NULL) { if ((dirp->dirhandle = fopen(dirspec, "r")) == NULL) { free(dirp); dirp = NULL; } } return dirp; } void closedir(dirp) DIR *dirp; { fclose(dirp->dirhandle); free(dirp); } /* * Apparently originally by Rich Salz. * Cleaned up and modified by James W. Birdsall. */ struct dirent *readdir(dirp) DIR *dirp; { if (dirp == NULL) return NULL; for (;;) if (fread(&(dirp->entry), sizeof (struct dirent), 1, dirp->dirhandle) == 0) return (struct dirent *)NULL; else if ((dirp->entry).d_ino) return &(dirp->entry); } /* end function readdir() */ #endif /* NO_DIR */ /**********************/ /* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ /**********************/ char *do_wild(__G__ wildspec) __GDEF ZCONST char *wildspec; /* only used first time on a given dir */ { /* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in unxcfg.h: static DIR *wild_dir = (DIR *)NULL; static ZCONST char *wildname; static char *dirname, matchname[FILNAMSIZ]; static int notfirstcall=FALSE, have_dirname, dirnamelen; */ struct dirent *file; /* Even when we're just returning wildspec, we *always* do so in * matchname[]--calling routine is allowed to append four characters * to the returned string, and wildspec may be a pointer to argv[]. */ if (!G.notfirstcall) { /* first call: must initialize everything */ G.notfirstcall = TRUE; if (!iswild(wildspec)) { strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; G.have_dirname = FALSE; G.wild_dir = NULL; return G.matchname; } /* break the wildspec into a directory part and a wildcard filename */ if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL) { G.dirname = "."; G.dirnamelen = 1; G.have_dirname = FALSE; G.wildname = wildspec; } else { ++G.wildname; /* point at character after '/' */ G.dirnamelen = G.wildname - wildspec; if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == (char *)NULL) { Info(slide, 0x201, ((char *)slide, "warning: cannot allocate wildcard buffers\n")); strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; return G.matchname; /* but maybe filespec was not a wildcard */ } strncpy(G.dirname, wildspec, G.dirnamelen); G.dirname[G.dirnamelen] = '\0'; /* terminate for strcpy below */ G.have_dirname = TRUE; } if ((G.wild_dir = (zvoid *)opendir(G.dirname)) != (zvoid *)NULL) { while ((file = readdir((DIR *)G.wild_dir)) != (struct dirent *)NULL) { Trace((stderr, "do_wild: readdir returns %s\n", FnFilter1(file->d_name))); if (file->d_name[0] == '.' && G.wildname[0] != '.') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, G.wildname, 0 WISEP) &&/*0=case sens.*/ /* skip "." and ".." directory entries */ strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { Trace((stderr, "do_wild: match() succeeds\n")); if (G.have_dirname) { strcpy(G.matchname, G.dirname); strcpy(G.matchname+G.dirnamelen, file->d_name); } else strcpy(G.matchname, file->d_name); return G.matchname; } } /* if we get to here directory is exhausted, so close it */ closedir((DIR *)G.wild_dir); G.wild_dir = (zvoid *)NULL; } Trace((stderr, "do_wild: opendir(%s) returns NULL\n", FnFilter1(G.dirname))); /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; return G.matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if ((DIR *)G.wild_dir == (DIR *)NULL) { G.notfirstcall = FALSE; /* nothing left--reset for new wildspec */ if (G.have_dirname) free(G.dirname); return (char *)NULL; } /* If we've gotten this far, we've read and matched at least one entry * successfully (in a previous call), so dirname has been copied into * matchname already. */ while ((file = readdir((DIR *)G.wild_dir)) != (struct dirent *)NULL) { Trace((stderr, "do_wild: readdir returns %s\n", FnFilter1(file->d_name))); if (file->d_name[0] == '.' && G.wildname[0] != '.') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, G.wildname, 0 WISEP)) { /* 0 == case sens. */ Trace((stderr, "do_wild: match() succeeds\n")); if (G.have_dirname) { /* strcpy(G.matchname, G.dirname); */ strcpy(G.matchname+G.dirnamelen, file->d_name); } else strcpy(G.matchname, file->d_name); return G.matchname; } } closedir((DIR *)G.wild_dir); /* at least one entry read; nothing left */ G.wild_dir = (zvoid *)NULL; G.notfirstcall = FALSE; /* reset for new wildspec */ if (G.have_dirname) free(G.dirname); return (char *)NULL; } /* end function do_wild() */ #endif /* !SFX */ #ifndef S_ISUID # define S_ISUID 0004000 /* set user id on execution */ #endif #ifndef S_ISGID # define S_ISGID 0002000 /* set group id on execution */ #endif #ifndef S_ISVTX # define S_ISVTX 0001000 /* save swapped text even after use */ #endif /************************/ /* Function filtattr() */ /************************/ /* This is used to clear or keep the SUID and SGID bits on file permissions. * It's possible that a file in an archive could have one of these bits set * and, unknown to the person unzipping, could allow others to execute the * file as the user or group. The new option -K bypasses this check. */ static unsigned filtattr(__G__ perms) __GDEF unsigned perms; { /* keep setuid/setgid/tacky perms? */ if (!uO.K_flag) perms &= ~(S_ISUID | S_ISGID | S_ISVTX); return (0xffff & perms); } /* end function filtattr() */ /**********************/ /* Function mapattr() */ /**********************/ int mapattr(__G) __GDEF { int r; ulg tmp = G.crec.external_file_attributes; G.pInfo->file_attr = 0; /* initialized to 0 for check in "default" branch below... */ switch (G.pInfo->hostnum) { case AMIGA_: tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); break; case THEOS_: tmp &= 0xF1FFFFFFL; if ((tmp & 0xF0000000L) != 0x40000000L) tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ else tmp &= 0x41FFFFFFL; /* leave directory bit as set */ /* fall through! */ case UNIX_: case VMS_: case ACORN_: case ATARI_: case ATHEOS_: case BEOS_: case QDOS_: case TANDEM_: r = FALSE; G.pInfo->file_attr = (unsigned)(tmp >> 16); if (G.pInfo->file_attr == 0 && G.extra_field) { /* Some (non-Info-ZIP) implementations of Zip for Unix and * VMS (and probably others ??) leave 0 in the upper 16-bit * part of the external_file_attributes field. Instead, they * store file permission attributes in some extra field. * As a work-around, we search for the presence of one of * these extra fields and fall back to the MSDOS compatible * part of external_file_attributes if one of the known * e.f. types has been detected. * Later, we might implement extraction of the permission * bits from the VMS extra field. But for now, the work-around * should be sufficient to provide "readable" extracted files. * (For ASI Unix e.f., an experimental remap of the e.f. * mode value IS already provided!) */ ush ebID; unsigned ebLen; uch *ef = G.extra_field; unsigned ef_len = G.crec.extra_field_length; while (!r && ef_len >= EB_HEADSIZE) { ebID = makeword(ef); ebLen = (unsigned)makeword(ef+EB_LEN); if (ebLen > (ef_len - EB_HEADSIZE)) /* discoverd some e.f. inconsistency! */ break; switch (ebID) { case EF_ASIUNIX: if (ebLen >= (EB_ASI_MODE+2)) { G.pInfo->file_attr = (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); /* force stop of loop: */ ef_len = (ebLen + EB_HEADSIZE); break; } /* else: fall through! */ case EF_PKVMS: /* "found nondecypherable e.f. with perm. attr" */ r = TRUE; default: break; } ef_len -= (ebLen + EB_HEADSIZE); ef += (ebLen + EB_HEADSIZE); } } if (!r) { #ifdef SYMLINKS /* Check if the file is a (POSIX-compatible) symbolic link. * We restrict symlink support to those "made-by" hosts that * are known to support symbolic links. */ G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && SYMLINK_HOST(G.pInfo->hostnum); #endif return 0; } /* fall through! */ /* all remaining cases: expand MSDOS read-only bit into write perms */ case FS_FAT_: /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the * Unix attributes in the upper 16 bits of the external attributes * field, just like Info-ZIP's Zip for Unix. We try to use that * value, after a check for consistency with the MSDOS attribute * bits (see below). */ G.pInfo->file_attr = (unsigned)(tmp >> 16); /* fall through! */ case FS_HPFS_: case FS_NTFS_: case MAC_: case TOPS20_: default: /* Ensure that DOS subdir bit is set when the entry's name ends * in a '/'. Some third-party Zip programs fail to set the subdir * bit for directory entries. */ if ((tmp & 0x10) == 0) { extent fnlen = strlen(G.filename); if (fnlen > 0 && G.filename[fnlen-1] == '/') tmp |= 0x10; } /* read-only bit --> write perms; subdir bit --> dir exec bit */ tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4; if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) { /* keep previous G.pInfo->file_attr setting, when its "owner" * part appears to be consistent with DOS attribute flags! */ #ifdef SYMLINKS /* Entries "made by FS_FAT_" could have been zipped on a * system that supports POSIX-style symbolic links. */ G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && (G.pInfo->hostnum == FS_FAT_); #endif return 0; } G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp); break; } /* end switch (host-OS-created-by) */ /* for originating systems with no concept of "group," "other," "system": */ umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */ G.pInfo->file_attr &= ~tmp; return 0; } /* end function mapattr() */ /************************/ /* Function mapname() */ /************************/ int mapname(__G__ renamed) __GDEF int renamed; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - caution (truncated filename) * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) * MPN_ERR_SKIP - error -> skip entry * MPN_ERR_TOOLONG - error -> path is too long * MPN_NOMEM - error (memory allocation failed) -> skip entry * [also MPN_VOL_LABEL, MPN_CREATED_DIR] */ { char pathcomp[FILNAMSIZ]; /* path-component buffer */ char *pp, *cp=(char *)NULL; /* character pointers */ char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ #ifdef ACORN_FTYPE_NFS char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ #endif int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ int error = MPN_OK; register unsigned workch; /* hold the character being tested */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return MPN_VOL_LABEL; /* can't set disk volume labels in Unix */ /* can create path as long as not just freshening, or if user told us */ G.create_dirs = (!uO.fflag || renamed); G.created_dir = FALSE; /* not yet */ /* user gave full pathname: don't prepend rootpath */ G.renamed_fullpath = (renamed && (*G.filename == '/')); if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM) return MPN_NOMEM; /* initialize path buffer, unless no memory */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (uO.jflag) /* junking directories */ cp = (char *)strrchr(G.filename, '/'); if (cp == (char *)NULL) /* no '/' or not junking dirs */ cp = G.filename; /* point to internal zipfile-member pathname */ else ++cp; /* point to start of last component of path */ /*--------------------------------------------------------------------------- Begin main loop through characters in filename. ---------------------------------------------------------------------------*/ while ((workch = (uch)*cp++) != 0) { switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if (strcmp(pathcomp, ".") == 0) { /* don't bother appending "./" to the path */ *pathcomp = '\0'; } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { /* "../" dir traversal detected, skip over it */ *pathcomp = '\0'; killed_ddot = TRUE; /* set "show message" flag */ } /* when path component is not empty, append it now */ if (*pathcomp != '\0' && ((error = checkdir(__G__ pathcomp, APPEND_DIR)) & MPN_MASK) > MPN_INF_TRUNC) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ break; #ifdef __CYGWIN__ /* Cygwin runs on Win32, apply FAT/NTFS filename rules */ case ':': /* drive spec not stored, so no colon allowed */ case '\\': /* '\\' may come as normal filename char (not */ case '<': /* dir sep char!) from unix-like file system */ case '>': /* no redirection symbols allowed either */ case '|': /* no pipe signs allowed */ case '"': /* no double quotes allowed */ case '?': /* no wildcards allowed */ case '*': *pp++ = '_'; /* these rules apply equally to FAT and NTFS */ break; #endif case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; *pp++ = ';'; /* keep for now; remove VMS ";##" */ break; /* later, if requested */ #ifdef ACORN_FTYPE_NFS case ',': /* NFS filetype extension */ lastcomma = pp; *pp++ = ','; /* keep for now; may need to remove */ break; /* later, if requested */ #endif #ifdef MTS case ' ': /* change spaces to underscore under */ *pp++ = '_'; /* MTS; leave as spaces under Unix */ break; #endif default: /* disable control character filter when requested, * else allow 8-bit characters (e.g. UTF-8) in filenames: */ if (uO.cflxflag || (isprint(workch) || (128 <= workch && workch <= 254))) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ /* Show warning when stripping insecure "parent dir" path components */ if (killed_ddot && QCOND2) { Info(slide, 0, ((char *)slide, "warning: skipped \"../\" path component(s) in %s\n", FnFilter1(G.filename))); if (!(error & ~MPN_MASK)) error = (error & MPN_MASK) | PK_WARN; } /*--------------------------------------------------------------------------- Report if directory was created (and no file to create: filename ended in '/'), check name to be sure it exists, and combine path and name be- fore exiting. ---------------------------------------------------------------------------*/ if (G.filename[strlen(G.filename) - 1] == '/') { checkdir(__G__ G.filename, GETPATH); if (G.created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %s\n", FnFilter1(G.filename))); } #ifndef NO_CHMOD /* Filter out security-relevant attributes bits. */ G.pInfo->file_attr = filtattr(__G__ G.pInfo->file_attr); /* When extracting non-UNIX directories or when extracting * without UID/GID restoration or SGID preservation, any * SGID flag inherited from the parent directory should be * maintained to allow files extracted into this new folder * to inherit the GID setting from the parent directory. */ if (G.pInfo->hostnum != UNIX_ || !(uO.X_flag || uO.K_flag)) { /* preserve SGID bit when inherited from parent dir */ if (!SSTAT(G.filename, &G.statbuf)) { G.pInfo->file_attr |= G.statbuf.st_mode & S_ISGID; } else { perror("Could not read directory attributes"); } } /* set approx. dir perms (make sure can still read/write in dir) */ if (chmod(G.filename, G.pInfo->file_attr | 0700)) perror("chmod (directory attributes) error"); #endif /* set dir time (note trailing '/') */ return (error & ~MPN_MASK) | MPN_CREATED_DIR; } /* dir existed already; don't look for data to extract */ return (error & ~MPN_MASK) | MPN_INF_SKIP; } *pp = '\0'; /* done with pathcomp: terminate it */ /* if not saving them, remove VMS version numbers (appended ";###") */ if (!uO.V_flag && lastsemi) { pp = lastsemi + 1; while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; } /* On UNIX (and compatible systems), "." and ".." are reserved for * directory navigation and cannot be used as regular file names. * These reserved one-dot and two-dot names are mapped to "_" and "__". */ if (strcmp(pathcomp, ".") == 0) *pathcomp = '_'; else if (strcmp(pathcomp, "..") == 0) strcpy(pathcomp, "__"); #ifdef ACORN_FTYPE_NFS /* translate Acorn filetype information if asked to do so */ if (uO.acorn_nfs_ext && (ef_spark = (RO_extra_block *) getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) != (RO_extra_block *)NULL) { /* file *must* have a RISC OS extra field */ long ft = (long)makelong(ef_spark->loadaddr); /*32-bit*/ if (lastcomma) { pp = lastcomma + 1; while (isxdigit((uch)(*pp))) ++pp; if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ } if ((ft & 1<<31)==0) ft=0x000FFD00; sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); } #endif /* ACORN_FTYPE_NFS */ if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", FnFilter1(G.filename))); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ checkdir(__G__ G.filename, GETPATH); return error; } /* end function mapname() */ #if 0 /*========== NOTES ==========*/ extract-to dir: a:path/ buildpath: path1/path2/ ... (NULL-terminated) pathcomp: filename mapname(): loop over chars in zipfile member name checkdir(path component, COMPONENT | CREATEDIR) --> map as required? (d:/tmp/unzip/) (disk:[tmp.unzip.) (d:/tmp/unzip/jj/) (disk:[tmp.unzip.jj.) (d:/tmp/unzip/jj/temp/) (disk:[tmp.unzip.jj.temp.) finally add filename itself and check for existence? (could use with rename) (d:/tmp/unzip/jj/temp/msg.outdir) (disk:[tmp.unzip.jj.temp]msg.outdir) checkdir(name, GETPATH) --> copy path to name and free space #endif /* 0 */ /***********************/ /* Function checkdir() */ /***********************/ int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename * MPN_INF_SKIP - path doesn't exist, not allowed to create * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path * exists and is not a directory, but is supposed to be * MPN_ERR_TOOLONG - path is too long * MPN_NOMEM - can't allocate memory for filename buffers */ { /* static int rootlen = 0; */ /* length of rootpath */ /* static char *rootpath; */ /* user's "extract-to" directory */ /* static char *buildpath; */ /* full path (so far) to extracted file */ /* static char *end; */ /* pointer to end of buildpath ('\0') */ # define FN_MASK 7 # define FUNCTION (flag & FN_MASK) /*--------------------------------------------------------------------------- APPEND_DIR: append the path component to the path being built and check for its existence. If doesn't exist and we are creating directories, do so for this one; else signal success or error as appropriate. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_DIR) { int too_long = FALSE; #ifdef SHORT_NAMES char *old_end = end; #endif Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); while ((*G.end = *pathcomp++) != '\0') ++G.end; #ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(G.end = old_end + FILENAME_MAX) = '\0'; #endif /* GRR: could do better check, see if overrunning buffer as we go: * check end-buildpath after each append, set warning variable if * within 20 of FILNAMSIZ; then if var set, do careful check when * appending. Clear variable when begin new path. */ /* next check: need to append '/', at least one-char name, '\0' */ if ((G.end-G.buildpath) > FILNAMSIZ-3) too_long = TRUE; /* check if extracting dir? */ if (SSTAT(G.buildpath, &G.statbuf)) { /* path doesn't exist */ if (!G.create_dirs) { /* told not to create (freshening) */ free(G.buildpath); return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); free(G.buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } if (mkdir(G.buildpath, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ %s\n\ unable to process %s.\n", FnFilter2(G.buildpath), strerror(errno), FnFilter1(G.filename))); free(G.buildpath); /* path didn't exist, tried to create, failed */ return MPN_ERR_SKIP; } G.created_dir = TRUE; } else if (!S_ISDIR(G.statbuf.st_mode)) { Info(slide, 1, ((char *)slide, "checkdir error: %s exists but is not directory\n\ unable to process %s.\n", FnFilter2(G.buildpath), FnFilter1(G.filename))); free(G.buildpath); /* path existed but wasn't dir */ return MPN_ERR_SKIP; } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); free(G.buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } *G.end++ = '/'; *G.end = '\0'; Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); return MPN_OK; } /* end if (FUNCTION == APPEND_DIR) */ /*--------------------------------------------------------------------------- GETPATH: copy full path to the string pointed at by pathcomp, and free G.buildpath. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { strcpy(pathcomp, G.buildpath); Trace((stderr, "getting and freeing path [%s]\n", FnFilter1(pathcomp))); free(G.buildpath); G.buildpath = G.end = (char *)NULL; return MPN_OK; } /*--------------------------------------------------------------------------- APPEND_NAME: assume the path component is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) { #ifdef SHORT_NAMES char *old_end = end; #endif Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); while ((*G.end = *pathcomp++) != '\0') { ++G.end; #ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(G.end = old_end + FILENAME_MAX) = '\0'; #endif if ((G.end-G.buildpath) >= FILNAMSIZ) { *--G.end = '\0'; Info(slide, 0x201, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", FnFilter1(G.filename), FnFilter2(G.buildpath))); return MPN_INF_TRUNC; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); /* could check for existence here, prompt for new name... */ return MPN_OK; } /*--------------------------------------------------------------------------- INIT: allocate and initialize buffer space for the file currently being extracted. If file was renamed with an absolute path, don't prepend the extract-to path. ---------------------------------------------------------------------------*/ /* GRR: for VMS and TOPS-20, add up to 13 to strlen */ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpath to ")); #ifdef ACORN_FTYPE_NFS if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+ (uO.acorn_nfs_ext ? 5 : 1))) #else if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1)) #endif == (char *)NULL) return MPN_NOMEM; if ((G.rootlen > 0) && !G.renamed_fullpath) { strcpy(G.buildpath, G.rootpath); G.end = G.buildpath + G.rootlen; } else { *G.buildpath = '\0'; G.end = G.buildpath; } Trace((stderr, "[%s]\n", FnFilter1(G.buildpath))); return MPN_OK; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in rootpath and create it if necessary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. ---------------------------------------------------------------------------*/ #if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", FnFilter1(pathcomp))); if (pathcomp == (char *)NULL) { G.rootlen = 0; return MPN_OK; } if (G.rootlen > 0) /* rootpath was already set, nothing to do */ return MPN_OK; if ((G.rootlen = strlen(pathcomp)) > 0) { char *tmproot; if ((tmproot = (char *)malloc(G.rootlen+2)) == (char *)NULL) { G.rootlen = 0; return MPN_NOMEM; } strcpy(tmproot, pathcomp); if (tmproot[G.rootlen-1] == '/') { tmproot[--G.rootlen] = '\0'; } if (G.rootlen > 0 && (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))) { /* path does not exist */ if (!G.create_dirs /* || iswild(tmproot) */ ) { free(tmproot); G.rootlen = 0; /* skip (or treat as stored file) */ return MPN_INF_SKIP; } /* create the directory (could add loop here scanning tmproot * to create more than one level, but why really necessary?) */ if (mkdir(tmproot, 0777) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory: %s\n\ %s\n", FnFilter1(tmproot), strerror(errno))); free(tmproot); G.rootlen = 0; /* path didn't exist, tried to create, and failed: */ /* file exists, or 2+ subdir levels required */ return MPN_ERR_SKIP; } } tmproot[G.rootlen++] = '/'; tmproot[G.rootlen] = '\0'; if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) { free(tmproot); G.rootlen = 0; return MPN_NOMEM; } Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath))); } return MPN_OK; } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (G.rootlen > 0) { free(G.rootpath); G.rootlen = 0; } return MPN_OK; } return MPN_INVALID; /* should never reach */ } /* end function checkdir() */ #ifdef NO_MKDIR /********************/ /* Function mkdir() */ /********************/ int mkdir(path, mode) ZCONST char *path; int mode; /* ignored */ /* * returns: 0 - successful * -1 - failed (errno not set, however) */ { char command[FILNAMSIZ+40]; /* buffer for system() call */ /* GRR 930416: added single quotes around path to avoid bug with * creating directories with ampersands in name; not yet tested */ sprintf(command, "IFS=\" \t\n\" /bin/mkdir '%s' 2>/dev/null", path); if (system(command)) return -1; return 0; } #endif /* NO_MKDIR */ #if (!defined(MTS) || defined(SET_DIR_ATTRIB)) static int get_extattribs OF((__GPRO__ iztimes *pzt, ulg z_uidgid[2])); static int get_extattribs(__G__ pzt, z_uidgid) __GDEF iztimes *pzt; ulg z_uidgid[2]; { /*--------------------------------------------------------------------------- Convert from MSDOS-format local time and date to Unix-format 32-bit GMT time: adjust base year from 1980 to 1970, do usual conversions from yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day- light savings time differences. If we have a Unix extra field, however, we're laughing: both mtime and atime are ours. On the other hand, we then have to check for restoration of UID/GID. ---------------------------------------------------------------------------*/ int have_uidgid_flg; unsigned eb_izux_flg; eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, #ifdef IZ_CHECK_TZ (G.tz_is_valid ? pzt : NULL), #else pzt, #endif z_uidgid) : 0); if (eb_izux_flg & EB_UT_FL_MTIME) { TTrace((stderr, "\nget_extattribs: Unix e.f. modif. time = %ld\n", pzt->mtime)); } else { pzt->mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); } if (eb_izux_flg & EB_UT_FL_ATIME) { TTrace((stderr, "get_extattribs: Unix e.f. access time = %ld\n", pzt->atime)); } else { pzt->atime = pzt->mtime; TTrace((stderr, "\nget_extattribs: modification/access times = %ld\n", pzt->mtime)); } /* if -X option was specified and we have UID/GID info, restore it */ have_uidgid_flg = #ifdef RESTORE_UIDGID (uO.X_flag && (eb_izux_flg & EB_UX2_VALID)); #else 0; #endif return have_uidgid_flg; } #endif /* !MTS || SET_DIR_ATTRIB */ #ifndef MTS /****************************/ /* Function close_outfile() */ /****************************/ void close_outfile(__G) /* GRR: change to return PK-style warning level */ __GDEF { union { iztimes t3; /* mtime, atime, ctime */ ztimbuf t2; /* modtime, actime */ } zt; ulg z_uidgid[2]; int have_uidgid_flg; have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid); /*--------------------------------------------------------------------------- If symbolic links are supported, allocate storage for a symlink control structure, put the uncompressed "data" and other required info in it, and add the structure to the "deferred symlinks" chain. Since we know it's a symbolic link to start with, we shouldn't have to worry about overflowing unsigned ints with unsigned longs. ---------------------------------------------------------------------------*/ #ifdef SYMLINKS if (G.symlnk) { extent ucsize = (extent)G.lrec.ucsize; # ifdef SET_SYMLINK_ATTRIBS extent attribsize = sizeof(unsigned) + (have_uidgid_flg ? sizeof(z_uidgid) : 0); # else extent attribsize = 0; # endif /* size of the symlink entry is the sum of * (struct size (includes 1st '\0') + 1 additional trailing '\0'), * system specific attribute data size (might be 0), * and the lengths of name and link target. */ extent slnk_entrysize = (sizeof(slinkentry) + 1) + attribsize + ucsize + strlen(G.filename); slinkentry *slnk_entry; if (slnk_entrysize < ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: mem alloc overflow\n", FnFilter1(G.filename))); fclose(G.outfile); return; } if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: no mem\n", FnFilter1(G.filename))); fclose(G.outfile); return; } slnk_entry->next = NULL; slnk_entry->targetlen = ucsize; slnk_entry->attriblen = attribsize; # ifdef SET_SYMLINK_ATTRIBS memcpy(slnk_entry->buf, &(G.pInfo->file_attr), sizeof(unsigned)); if (have_uidgid_flg) memcpy(slnk_entry->buf + 4, z_uidgid, sizeof(z_uidgid)); # endif slnk_entry->target = slnk_entry->buf + slnk_entry->attriblen; slnk_entry->fname = slnk_entry->target + ucsize + 1; strcpy(slnk_entry->fname, G.filename); /* move back to the start of the file to re-read the "link data" */ rewind(G.outfile); if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed\n", FnFilter1(G.filename))); free(slnk_entry); fclose(G.outfile); return; } fclose(G.outfile); /* close "link" file for good... */ slnk_entry->target[ucsize] = '\0'; if (QCOND2) Info(slide, 0, ((char *)slide, "-> %s ", FnFilter1(slnk_entry->target))); /* add this symlink record to the list of deferred symlinks */ if (G.slink_last != NULL) G.slink_last->next = slnk_entry; else G.slink_head = slnk_entry; G.slink_last = slnk_entry; return; } #endif /* SYMLINKS */ #ifdef QLZIP if (G.extra_field) { static void qlfix OF((__GPRO__ uch *ef_ptr, unsigned ef_len)); qlfix(__G__ G.extra_field, G.lrec.extra_field_length); } #endif #if (defined(NO_FCHOWN)) fclose(G.outfile); #endif /* if -X option was specified and we have UID/GID info, restore it */ if (have_uidgid_flg /* check that both uid and gid values fit into their data sizes */ && ((ulg)(uid_t)(z_uidgid[0]) == z_uidgid[0]) && ((ulg)(gid_t)(z_uidgid[1]) == z_uidgid[1])) { TTrace((stderr, "close_outfile: restoring Unix UID/GID info\n")); #if (defined(NO_FCHOWN)) if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1])) #else if (fchown(fileno(G.outfile), (uid_t)z_uidgid[0], (gid_t)z_uidgid[1])) #endif { if (uO.qflag) Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid, z_uidgid[0], z_uidgid[1], FnFilter1(G.filename), strerror(errno))); else Info(slide, 0x201, ((char *)slide, CannotSetUidGid, z_uidgid[0], z_uidgid[1], strerror(errno))); } } #if (!defined(NO_FCHOWN) && defined(NO_FCHMOD)) fclose(G.outfile); #endif #if (!defined(NO_FCHOWN) && !defined(NO_FCHMOD)) /*--------------------------------------------------------------------------- Change the file permissions from default ones to those stored in the zipfile. ---------------------------------------------------------------------------*/ if (fchmod(fileno(G.outfile), filtattr(__G__ G.pInfo->file_attr))) perror("fchmod (file attributes) error"); fclose(G.outfile); #endif /* !NO_FCHOWN && !NO_FCHMOD */ /* skip restoring time stamps on user's request */ if (uO.D_flag <= 1) { /* set the file's access and modification times */ if (utime(G.filename, &(zt.t2))) { if (uO.qflag) Info(slide, 0x201, ((char *)slide, CannotSetItemTimestamps, FnFilter1(G.filename), strerror(errno))); else Info(slide, 0x201, ((char *)slide, CannotSetTimestamps, strerror(errno))); } } #if (defined(NO_FCHOWN) || defined(NO_FCHMOD)) /*--------------------------------------------------------------------------- Change the file permissions from default ones to those stored in the zipfile. ---------------------------------------------------------------------------*/ #ifndef NO_CHMOD if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr))) perror("chmod (file attributes) error"); #endif #endif /* NO_FCHOWN || NO_FCHMOD */ } /* end function close_outfile() */ #endif /* !MTS */ #if (defined(SYMLINKS) && defined(SET_SYMLINK_ATTRIBS)) int set_symlnk_attribs(__G__ slnk_entry) __GDEF slinkentry *slnk_entry; { if (slnk_entry->attriblen > 0) { # if (!defined(NO_LCHOWN)) if (slnk_entry->attriblen > sizeof(unsigned)) { ulg *z_uidgid_p = (zvoid *)(slnk_entry->buf + sizeof(unsigned)); /* check that both uid and gid values fit into their data sizes */ if (((ulg)(uid_t)(z_uidgid_p[0]) == z_uidgid_p[0]) && ((ulg)(gid_t)(z_uidgid_p[1]) == z_uidgid_p[1])) { TTrace((stderr, "set_symlnk_attribs: restoring Unix UID/GID info for\n\ %s\n", FnFilter1(slnk_entry->fname))); if (lchown(slnk_entry->fname, (uid_t)z_uidgid_p[0], (gid_t)z_uidgid_p[1])) { Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid, z_uidgid_p[0], z_uidgid_p[1], FnFilter1(slnk_entry->fname), strerror(errno))); } } } # endif /* !NO_LCHOWN */ # if (!defined(NO_LCHMOD)) TTrace((stderr, "set_symlnk_attribs: restoring Unix attributes for\n %s\n", FnFilter1(slnk_entry->fname))); if (lchmod(slnk_entry->fname, filtattr(__G__ *(unsigned *)(zvoid *)slnk_entry->buf))) perror("lchmod (file attributes) error"); # endif /* !NO_LCHMOD */ } /* currently, no error propagation... */ return PK_OK; } /* end function set_symlnk_attribs() */ #endif /* SYMLINKS && SET_SYMLINK_ATTRIBS */ #ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */ # ifndef NO_CHMOD static ZCONST char DirlistChmodFailed[] = "warning: cannot set permissions for %s\n %s\n"; # endif int defer_dir_attribs(__G__ pd) __GDEF direntry **pd; { uxdirattr *d_entry; d_entry = (uxdirattr *)malloc(sizeof(uxdirattr) + strlen(G.filename)); *pd = (direntry *)d_entry; if (d_entry == (uxdirattr *)NULL) { return PK_MEM; } d_entry->fn = d_entry->fnbuf; strcpy(d_entry->fn, G.filename); d_entry->perms = G.pInfo->file_attr; d_entry->have_uidgid = get_extattribs(__G__ &(d_entry->u.t3), d_entry->uidgid); return PK_OK; } /* end function defer_dir_attribs() */ int set_direc_attribs(__G__ d) __GDEF direntry *d; { int errval = PK_OK; if (UxAtt(d)->have_uidgid && /* check that both uid and gid values fit into their data sizes */ ((ulg)(uid_t)(UxAtt(d)->uidgid[0]) == UxAtt(d)->uidgid[0]) && ((ulg)(gid_t)(UxAtt(d)->uidgid[1]) == UxAtt(d)->uidgid[1]) && chown(UxAtt(d)->fn, (uid_t)UxAtt(d)->uidgid[0], (gid_t)UxAtt(d)->uidgid[1])) { Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid, UxAtt(d)->uidgid[0], UxAtt(d)->uidgid[1], FnFilter1(d->fn), strerror(errno))); if (!errval) errval = PK_WARN; } /* Skip restoring directory time stamps on user' request. */ if (uO.D_flag <= 0) { /* restore directory timestamps */ if (utime(d->fn, &UxAtt(d)->u.t2)) { Info(slide, 0x201, ((char *)slide, CannotSetItemTimestamps, FnFilter1(d->fn), strerror(errno))); if (!errval) errval = PK_WARN; } } #ifndef NO_CHMOD if (chmod(d->fn, UxAtt(d)->perms)) { Info(slide, 0x201, ((char *)slide, DirlistChmodFailed, FnFilter1(d->fn), strerror(errno))); if (!errval) errval = PK_WARN; } #endif /* !NO_CHMOD */ return errval; } /* end function set_direc_attribs() */ #endif /* SET_DIR_ATTRIB */ #ifdef TIMESTAMP /***************************/ /* Function stamp_file() */ /***************************/ int stamp_file(fname, modtime) ZCONST char *fname; time_t modtime; { ztimbuf tp; tp.modtime = tp.actime = modtime; return (utime(fname, &tp)); } /* end function stamp_file() */ #endif /* TIMESTAMP */ #ifndef SFX /************************/ /* Function version() */ /************************/ void version(__G) __GDEF { #if (defined(__GNUC__) && defined(NX_CURRENT_COMPILER_RELEASE)) char cc_namebuf[40]; char cc_versbuf[40]; #else #if (defined(__SUNPRO_C)) char cc_versbuf[17]; #else #if (defined(__HP_cc) || defined(__IBMC__)) char cc_versbuf[25]; #else #if (defined(__DECC_VER)) char cc_versbuf[17]; int cc_verstyp; #else #if (defined(CRAY) && defined(_RELEASE)) char cc_versbuf[40]; #endif /* (CRAY && _RELEASE) */ #endif /* __DECC_VER */ #endif /* __HP_cc || __IBMC__ */ #endif /* __SUNPRO_C */ #endif /* (__GNUC__ && NX_CURRENT_COMPILER_RELEASE) */ #if ((defined(CRAY) || defined(cray)) && defined(_UNICOS)) char os_namebuf[40]; #else #if defined(__NetBSD__) char os_namebuf[40]; #endif #endif /* Pyramid, NeXT have problems with huge macro expansion, too: no Info() */ sprintf((char *)slide, LoadFarString(CompiledWith), #ifdef __GNUC__ # ifdef NX_CURRENT_COMPILER_RELEASE (sprintf(cc_namebuf, "NeXT DevKit %d.%02d ", NX_CURRENT_COMPILER_RELEASE/100, NX_CURRENT_COMPILER_RELEASE%100), cc_namebuf), (strlen(__VERSION__) > 8)? "(gcc)" : (sprintf(cc_versbuf, "(gcc %s)", __VERSION__), cc_versbuf), # else "gcc ", __VERSION__, # endif #else #if defined(__SUNPRO_C) "Sun C ", (sprintf(cc_versbuf, "version %x", __SUNPRO_C), cc_versbuf), #else #if (defined(__HP_cc)) "HP C ", (((__HP_cc% 100) == 0) ? (sprintf(cc_versbuf, "version A.%02d.%02d", (__HP_cc/ 10000), ((__HP_cc% 10000)/ 100))) : (sprintf(cc_versbuf, "version A.%02d.%02d.%02d", (__HP_cc/ 10000), ((__HP_cc% 10000)/ 100), (__HP_cc% 100))), cc_versbuf), #else #if (defined(__DECC_VER)) "DEC C ", (sprintf(cc_versbuf, "%c%d.%d-%03d", ((cc_verstyp = (__DECC_VER / 10000) % 10) == 6 ? 'T' : (cc_verstyp == 8 ? 'S' : 'V')), __DECC_VER / 10000000, (__DECC_VER % 10000000) / 100000, __DECC_VER % 1000), cc_versbuf), #else #if defined(CRAY) && defined(_RELEASE) "cc ", (sprintf(cc_versbuf, "version %d", _RELEASE), cc_versbuf), #else #ifdef __IBMC__ "IBM C ", (sprintf(cc_versbuf, "version %d.%d.%d", (__IBMC__ / 100), ((__IBMC__ / 10) % 10), (__IBMC__ % 10)), cc_versbuf), #else #ifdef __VERSION__ # ifndef IZ_CC_NAME # define IZ_CC_NAME "cc " # endif IZ_CC_NAME, __VERSION__ #else # ifndef IZ_CC_NAME # define IZ_CC_NAME "cc" # endif IZ_CC_NAME, "", #endif /* ?__VERSION__ */ #endif /* ?__IBMC__ */ #endif /* ?(CRAY && _RELEASE) */ #endif /* ?__DECC_VER */ #endif /* ?__HP_cc */ #endif /* ?__SUNPRO_C */ #endif /* ?__GNUC__ */ #ifndef IZ_OS_NAME # define IZ_OS_NAME "Unix" #endif IZ_OS_NAME, #if defined(sgi) || defined(__sgi) " (Silicon Graphics IRIX)", #else #ifdef sun # ifdef sparc # ifdef __SVR4 " (Sun SPARC/Solaris)", # else /* may or may not be SunOS */ " (Sun SPARC)", # endif # else # if defined(sun386) || defined(i386) " (Sun 386i)", # else # if defined(mc68020) || defined(__mc68020__) " (Sun 3)", # else /* mc68010 or mc68000: Sun 2 or earlier */ " (Sun 2)", # endif # endif # endif #else #ifdef __hpux " (HP-UX)", #else #ifdef __osf__ " (DEC OSF/1)", #else #ifdef _AIX " (IBM AIX)", #else #ifdef aiws " (IBM RT/AIX)", #else #if defined(CRAY) || defined(cray) # ifdef _UNICOS (sprintf(os_namebuf, " (Cray UNICOS release %d)", _UNICOS), os_namebuf), # else " (Cray UNICOS)", # endif #else #if defined(uts) || defined(UTS) " (Amdahl UTS)", #else #ifdef NeXT # ifdef mc68000 " (NeXTStep/black)", # else " (NeXTStep for Intel)", # endif #else /* the next dozen or so are somewhat order-dependent */ #ifdef LINUX # ifdef __ELF__ " (Linux ELF)", # else " (Linux a.out)", # endif #else #ifdef MINIX " (Minix)", #else #ifdef M_UNIX " (SCO Unix)", #else #ifdef M_XENIX " (SCO Xenix)", #else #ifdef __NetBSD__ # ifdef NetBSD0_8 (sprintf(os_namebuf, " (NetBSD 0.8%c)", (char)(NetBSD0_8 - 1 + 'A')), os_namebuf), # else # ifdef NetBSD0_9 (sprintf(os_namebuf, " (NetBSD 0.9%c)", (char)(NetBSD0_9 - 1 + 'A')), os_namebuf), # else # ifdef NetBSD1_0 (sprintf(os_namebuf, " (NetBSD 1.0%c)", (char)(NetBSD1_0 - 1 + 'A')), os_namebuf), # else (BSD4_4 == 0.5)? " (NetBSD before 0.9)" : " (NetBSD 1.1 or later)", # endif # endif # endif #else #ifdef __FreeBSD__ (BSD4_4 == 0.5)? " (FreeBSD 1.x)" : " (FreeBSD 2.0 or later)", #else #ifdef __bsdi__ (BSD4_4 == 0.5)? " (BSD/386 1.0)" : " (BSD/386 1.1 or later)", #else #ifdef __386BSD__ (BSD4_4 == 1)? " (386BSD, post-4.4 release)" : " (386BSD)", #else #ifdef __CYGWIN__ " (Cygwin)", #else #if defined(i686) || defined(__i686) || defined(__i686__) " (Intel 686)", #else #if defined(i586) || defined(__i586) || defined(__i586__) " (Intel 586)", #else #if defined(i486) || defined(__i486) || defined(__i486__) " (Intel 486)", #else #if defined(i386) || defined(__i386) || defined(__i386__) " (Intel 386)", #else #ifdef pyr " (Pyramid)", #else #ifdef ultrix # ifdef mips " (DEC/MIPS)", # else # ifdef vax " (DEC/VAX)", # else /* __alpha? */ " (DEC/Alpha)", # endif # endif #else #ifdef gould " (Gould)", #else #ifdef MTS " (MTS)", #else #ifdef __convexc__ " (Convex)", #else #ifdef __QNX__ " (QNX 4)", #else #ifdef __QNXNTO__ " (QNX Neutrino)", #else #ifdef Lynx " (LynxOS)", #else #ifdef __APPLE__ # ifdef __i386__ " Mac OS X Intel i32", # else # ifdef __ppc__ " Mac OS X PowerPC", # else # ifdef __ppc64__ " Mac OS X PowerPC64", # else " Mac OS X", # endif /* __ppc64__ */ # endif /* __ppc__ */ # endif /* __i386__ */ #else "", #endif /* Apple */ #endif /* Lynx */ #endif /* QNX Neutrino */ #endif /* QNX 4 */ #endif /* Convex */ #endif /* MTS */ #endif /* Gould */ #endif /* DEC */ #endif /* Pyramid */ #endif /* 386 */ #endif /* 486 */ #endif /* 586 */ #endif /* 686 */ #endif /* Cygwin */ #endif /* 386BSD */ #endif /* BSDI BSD/386 */ #endif /* NetBSD */ #endif /* FreeBSD */ #endif /* SCO Xenix */ #endif /* SCO Unix */ #endif /* Minix */ #endif /* Linux */ #endif /* NeXT */ #endif /* Amdahl */ #endif /* Cray */ #endif /* RT/AIX */ #endif /* AIX */ #endif /* OSF/1 */ #endif /* HP-UX */ #endif /* Sun */ #endif /* SGI */ #ifdef __DATE__ " on ", __DATE__ #else "", "" #endif ); (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); } /* end function version() */ #endif /* !SFX */ #ifdef QLZIP struct qdirect { long d_length __attribute__ ((packed)); /* file length */ unsigned char d_access __attribute__ ((packed)); /* file access type */ unsigned char d_type __attribute__ ((packed)); /* file type */ long d_datalen __attribute__ ((packed)); /* data length */ long d_reserved __attribute__ ((packed));/* Unused */ short d_szname __attribute__ ((packed)); /* size of name */ char d_name[36] __attribute__ ((packed));/* name area */ long d_update __attribute__ ((packed)); /* last update */ long d_refdate __attribute__ ((packed)); long d_backup __attribute__ ((packed)); /* EOD */ }; #define LONGID "QDOS02" #define EXTRALEN (sizeof(struct qdirect) + 8) #define JBLONGID "QZHD" #define JBEXTRALEN (sizeof(jbextra) - 4 * sizeof(char)) typedef struct { char eb_header[4] __attribute__ ((packed)); /* place_holder */ char longid[8] __attribute__ ((packed)); struct qdirect header __attribute__ ((packed)); } qdosextra; typedef struct { char eb_header[4]; /* place_holder */ char longid[4]; struct qdirect header; } jbextra; /* The following two functions SH() and LG() convert big-endian short * and long numbers into native byte order. They are some kind of * counterpart to the generic UnZip's makeword() and makelong() functions. */ static ush SH(ush val) { uch swapbuf[2]; swapbuf[1] = (uch)(val & 0xff); swapbuf[0] = (uch)(val >> 8); return (*(ush *)swapbuf); } static ulg LG(ulg val) { /* convert the big-endian unsigned long number `val' to the machine * dependent representation */ ush swapbuf[2]; swapbuf[1] = SH((ush)(val & 0xffff)); swapbuf[0] = SH((ush)(val >> 16)); return (*(ulg *)swapbuf); } static void qlfix(__G__ ef_ptr, ef_len) __GDEF uch *ef_ptr; unsigned ef_len; { while (ef_len >= EB_HEADSIZE) { unsigned eb_id = makeword(EB_ID + ef_ptr); unsigned eb_len = makeword(EB_LEN + ef_ptr); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ Trace((stderr, "qlfix: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } switch (eb_id) { case EF_QDOS: { struct _ntc_ { long id; long dlen; } ntc; long dlen = 0; qdosextra *extra = (qdosextra *)ef_ptr; jbextra *jbp = (jbextra *)ef_ptr; if (!strncmp(extra->longid, LONGID, strlen(LONGID))) { if (eb_len != EXTRALEN) if (uO.qflag) Info(slide, 0x201, ((char *)slide, "warning: invalid length in Qdos field for %s\n", FnFilter1(G.filename))); else Info(slide, 0x201, ((char *)slide, "warning: invalid length in Qdos field")); if (extra->header.d_type) { dlen = extra->header.d_datalen; } } if (!strncmp(jbp->longid, JBLONGID, strlen(JBLONGID))) { if (eb_len != JBEXTRALEN) if (uO.qflag) Info(slide, 0x201, ((char *)slide, "warning: invalid length in QZ field for %s\n", FnFilter1(G.filename))); else Info(slide, 0x201, ((char *)slide, "warning: invalid length in QZ field")); if (jbp->header.d_type) { dlen = jbp->header.d_datalen; } } if ((long)LG(dlen) > 0) { zfseeko(G.outfile, -8, SEEK_END); fread(&ntc, 8, 1, G.outfile); if (ntc.id != *(long *)"XTcc") { ntc.id = *(long *)"XTcc"; ntc.dlen = dlen; fwrite (&ntc, 8, 1, G.outfile); } Info(slide, 0x201, ((char *)slide, "QData = %d", LG(dlen))); } return; /* finished, cancel further extra field scanning */ } default: Trace((stderr,"qlfix: unknown extra field block, ID=%d\n", eb_id)); } /* Skip this extra field block */ ef_ptr += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } } #endif /* QLZIP */ Carla-2.1/data/windows/unzipfx-carla/unix/unxcfg.h000066400000000000000000000146171364475620200222340ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- Unix specific configuration section: ---------------------------------------------------------------------------*/ #ifndef __unxcfg_h #define __unxcfg_h /* LARGE FILE SUPPORT - 10/6/04 EG */ /* This needs to be set before the includes so they set the right sizes */ #if (defined(NO_LARGE_FILE_SUPPORT) && defined(LARGE_FILE_SUPPORT)) # undef LARGE_FILE_SUPPORT #endif /* Automatically set ZIP64_SUPPORT if LFS */ #ifdef LARGE_FILE_SUPPORT # if (!defined(NO_ZIP64_SUPPORT) && !defined(ZIP64_SUPPORT)) # define ZIP64_SUPPORT # endif #endif /* NO_ZIP64_SUPPORT takes preceedence over ZIP64_SUPPORT */ #if defined(NO_ZIP64_SUPPORT) && defined(ZIP64_SUPPORT) # undef ZIP64_SUPPORT #endif #ifdef LARGE_FILE_SUPPORT /* 64-bit Large File Support */ /* The following Large File Summit (LFS) defines turn on large file support on Linux (probably 2.4 or later kernel) and many other unixen */ /* These have to be before any include that sets types so the large file versions of the types are set in the includes */ # define _LARGEFILE_SOURCE /* some OSes need this for fseeko */ # define _LARGEFILE64_SOURCE # define _FILE_OFFSET_BITS 64 /* select default interface as 64 bit */ # define _LARGE_FILES /* some OSes need this for 64-bit off_t */ # define __USE_LARGEFILE64 #endif /* LARGE_FILE_SUPPORT */ #include /* off_t, time_t, dev_t, ... */ #include #ifdef NO_OFF_T typedef long zoff_t; #else typedef off_t zoff_t; #endif #define ZOFF_T_DEFINED typedef struct stat z_stat; #define Z_STAT_DEFINED #ifndef COHERENT # include /* O_BINARY for open() w/o CR/LF translation */ #else /* COHERENT */ # ifdef _I386 # include /* Coherent 4.0.x, Mark Williams C */ # else # include /* Coherent 3.10, Mark Williams C */ # endif # define SHORT_SYMS # ifndef __COHERENT__ /* Coherent 4.2 has tzset() */ # define tzset settz # endif #endif /* ?COHERENT */ #ifndef NO_PARAM_H # ifdef NGROUPS_MAX # undef NGROUPS_MAX /* SCO bug: defined again in */ # endif # ifdef BSD # define TEMP_BSD /* may be defined again in */ # undef BSD # endif # include /* conflict with , some systems? */ # ifdef TEMP_BSD # undef TEMP_BSD # ifndef BSD # define BSD # endif # endif #endif /* !NO_PARAM_H */ #ifdef __osf__ # define DIRENT # ifdef BSD # undef BSD # endif #endif /* __osf__ */ #ifdef __CYGWIN__ # include # define DIRENT # define HAVE_TERMIOS_H # ifndef timezone # define timezone _timezone # endif #endif #ifdef BSD # include # include # if (defined(_AIX) || defined(__GLIBC__) || defined(__GNU__)) # include # endif #else # include struct tm *gmtime(), *localtime(); #endif #if (defined(BSD4_4) || (defined(SYSV) && defined(MODERN))) # include /* this includes utime.h on SGIs */ # if (defined(BSD4_4) || defined(linux) || defined(__GLIBC__)) # include # define GOT_UTIMBUF # endif # if (!defined(GOT_UTIMBUF) && (defined(__hpux) || defined(__SUNPRO_C))) # include # define GOT_UTIMBUF # endif # if (!defined(GOT_UTIMBUF) && defined(__GNU__)) # include # define GOT_UTIMBUF # endif #endif #if (defined(__DGUX__) && !defined(GOT_UTIMBUF)) /* DG/UX requires this because of a non-standard struct utimebuf */ # include # define GOT_UTIMBUF #endif #if (defined(V7) || defined(pyr_bsd)) # define strchr index # define strrchr rindex #endif #ifdef V7 # define O_RDONLY 0 # define O_WRONLY 1 # define O_RDWR 2 #endif #if defined(NO_UNICODE_SUPPORT) && defined(UNICODE_SUPPORT) /* disable Unicode (UTF-8) support when requested */ # undef UNICODE_SUPPORT #endif #if (defined(_MBCS) && defined(NO_MBCS)) /* disable MBCS support when requested */ # undef _MBCS #endif #if (!defined(NO_SETLOCALE) && !defined(_MBCS)) # if (!defined(UNICODE_SUPPORT) || !defined(UTF8_MAYBE_NATIVE)) /* enable setlocale here, unless this happens later for UTF-8 and/or * MBCS support */ # include # ifndef SETLOCALE # define SETLOCALE(category, locale) setlocale(category, locale) # endif # endif #endif #ifndef NO_SETLOCALE # if (!defined(NO_WORKING_ISPRINT) && !defined(HAVE_WORKING_ISPRINT)) /* enable "enhanced" unprintable chars detection in fnfilter() */ # define HAVE_WORKING_ISPRINT # endif #endif #ifdef MINIX # include #endif #if (!defined(HAVE_STRNICMP) & !defined(NO_STRNICMP)) # define NO_STRNICMP #endif #ifndef DATE_FORMAT # define DATE_FORMAT DF_MDY /* GRR: customize with locale.h somehow? */ #endif #define lenEOL 1 #ifdef EBCDIC # define PutNativeEOL *q++ = '\n'; #else # define PutNativeEOL *q++ = native(LF); #endif #define SCREENSIZE(ttrows, ttcols) screensize(ttrows, ttcols) #define SCREENWIDTH 80 #define SCREENLWRAP 1 #define USE_EF_UT_TIME #if (!defined(NO_LCHOWN) || !defined(NO_LCHMOD)) # define SET_SYMLINK_ATTRIBS #endif #ifdef MTS # ifdef SET_DIR_ATTRIB # undef SET_DIR_ATTRIB # endif #else /* !MTS */ # define SET_DIR_ATTRIB # if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) /* GRR 970513 */ # define TIMESTAMP # endif # define RESTORE_UIDGID #endif /* ?MTS */ /* Static variables that we have to add to Uz_Globs: */ #define SYSTEM_SPECIFIC_GLOBALS \ int created_dir, renamed_fullpath;\ char *rootpath, *buildpath, *end;\ ZCONST char *wildname;\ char *dirname, matchname[FILNAMSIZ];\ int rootlen, have_dirname, dirnamelen, notfirstcall;\ zvoid *wild_dir; /* created_dir, and renamed_fullpath are used by both mapname() and */ /* checkdir(). */ /* rootlen, rootpath, buildpath and end are used by checkdir(). */ /* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */ /* and notfirstcall are used by do_wild(). */ #endif /* !__unxcfg_h */ Carla-2.1/data/windows/unzipfx-carla/unzip.c000066400000000000000000002757611364475620200211300ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- unzip.c UnZip - a zipfile extraction utility. See below for make instructions, or read the comments in Makefile and the various Contents files for more de- tailed explanations. To report a bug, submit a *complete* description via //www.info-zip.org/zip-bug.html; include machine type, operating system and version, compiler and version, and reasonably detailed error messages or problem report. To join Info-ZIP, see the instructions in README. UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x, which in turn was almost a complete rewrite of version 3.x. For a detailed revision history, see UnzpHist.zip at quest.jpl.nasa.gov. For a list of the many (near infinite) contributors, see "CONTRIBS" in the UnZip source distribution. UnZip 6.0 adds support for archives larger than 4 GiB using the Zip64 extensions as well as support for Unicode information embedded per the latest zip standard additions. --------------------------------------------------------------------------- [from original zipinfo.c] This program reads great gobs of totally nifty information, including the central directory stuff, from ZIP archives ("zipfiles" for short). It started as just a testbed for fooling with zipfiles, but at this point it is actually a useful utility. It also became the basis for the rewrite of UnZip (3.16 -> 4.0), using the central directory for processing rather than the individual (local) file headers. As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one. If the executable is named "unzip" (or "unzip.exe", depending), it behaves like UnZip by default; if it is named "zipinfo" or "ii", it behaves like ZipInfo. The ZipInfo behavior may also be triggered by use of unzip's -Z option; for example, "unzip -Z [zipinfo_options] archive.zip". Another dandy product from your buddies at Newtware! Author: Greg Roelofs, newt@pobox.com, http://pobox.com/~newt/ 23 August 1990 -> April 1997 --------------------------------------------------------------------------- Version: unzip5??.{tar.Z | tar.gz | zip} for Unix, VMS, OS/2, MS-DOS, Amiga, Atari, Windows 3.x/95/NT/CE, Macintosh, Human68K, Acorn RISC OS, AtheOS, BeOS, SMS/QDOS, VM/CMS, MVS, AOS/VS, Tandem NSK, Theos and TOPS-20. Copyrights: see accompanying file "LICENSE" in UnZip source distribution. (This software is free but NOT IN THE PUBLIC DOMAIN.) ---------------------------------------------------------------------------*/ #define __UNZIP_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" /* includes, typedefs, macros, prototypes, etc. */ #include "crypt.h" #include "unzvers.h" #include "unzipfx/appDetails.h" #ifndef WINDLL /* The WINDLL port uses windll/windll.c instead... */ /***************************/ /* Local type declarations */ /***************************/ #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS)) typedef struct _sign_info { struct _sign_info *previous; void (*sighandler)(int); int sigtype; } savsigs_info; #endif /*******************/ /* Local Functions */ /*******************/ #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS)) static int setsignalhandler OF((__GPRO__ savsigs_info **p_savedhandler_chain, int signal_type, void (*newhandler)(int))); #endif #ifndef SFX static void help_extended OF((__GPRO)); static void show_version_info OF((__GPRO)); #endif /*************/ /* Constants */ /*************/ #include "consts.h" /* all constant global variables are in here */ /* (non-constant globals were moved to globals.c) */ /* constant local variables: */ #ifndef SFX #ifndef _WIN32_WCE /* Win CE does not support environment variables */ static ZCONST char Far EnvUnZip[] = ENV_UNZIP; static ZCONST char Far EnvUnZip2[] = ENV_UNZIP2; static ZCONST char Far EnvZipInfo[] = ENV_ZIPINFO; static ZCONST char Far EnvZipInfo2[] = ENV_ZIPINFO2; #ifdef RISCOS static ZCONST char Far EnvUnZipExts[] = ENV_UNZIPEXTS; #endif /* RISCOS */ static ZCONST char Far NoMemEnvArguments[] = "envargs: cannot get memory for arguments"; #endif /* !_WIN32_WCE */ static ZCONST char Far CmdLineParamTooLong[] = "error: command line parameter #%d exceeds internal size limit\n"; #endif /* !SFX */ #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS)) static ZCONST char Far CantSaveSigHandler[] = "error: cannot save signal handler settings\n"; #endif #if (!defined(SFX) || defined(SFX_EXDIR)) static ZCONST char Far NotExtracting[] = "caution: not extracting; -d ignored\n"; static ZCONST char Far MustGiveExdir[] = "error: must specify directory to which to extract with -d option\n"; static ZCONST char Far OnlyOneExdir[] = "error: -d option used more than once (only one exdir allowed)\n"; #endif #if (defined(UNICODE_SUPPORT) && !defined(UNICODE_WCHAR)) static ZCONST char Far UTF8EscapeUnSupp[] = "warning: -U \"escape all non-ASCII UTF-8 chars\" is not supported\n"; #endif #if CRYPT static ZCONST char Far MustGivePasswd[] = "error: must give decryption password with -P option\n"; #endif #ifndef SFX static ZCONST char Far Zfirst[] = "error: -Z must be first option for ZipInfo mode (check UNZIP variable?)\n"; #endif static ZCONST char Far InvalidOptionsMsg[] = "error:\ -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n"; static ZCONST char Far IgnoreOOptionMsg[] = "caution: both -n and -o specified; ignoring -o\n"; /* usage() strings */ #ifndef SFX #ifdef VMS static ZCONST char Far Example3[] = "vms.c"; static ZCONST char Far Example2[] = " unzip \"-V\" foo \"Bar\"\ (Quote names to preserve case, unless SET PROC/PARS=EXT)\n"; #else /* !VMS */ static ZCONST char Far Example3[] = "ReadMe"; #ifdef RISCOS static ZCONST char Far Example2[] = " unzip foo -d RAM:$ => extract all files from foo into RAMDisc\n"; #else /* !RISCOS */ #if (defined(OS2) || (defined(DOS_FLX_OS2_W32) && defined(MORE))) static ZCONST char Far Example2[] = ""; /* no room: too many local3[] items */ #else /* !OS2 */ #ifdef MACOS static ZCONST char Far Example2[] = ""; /* not needed */ #else /* !MACOS */ static ZCONST char Far Example2[] = " \ unzip -p foo | more => send contents of foo.zip via pipe into program more\n"; #endif /* ?MACOS */ #endif /* ?OS2 */ #endif /* ?RISCOS */ #endif /* ?VMS */ /* local1[]: command options */ #if defined(TIMESTAMP) static ZCONST char Far local1[] = " -T timestamp archive to latest"; #else /* !TIMESTAMP */ static ZCONST char Far local1[] = ""; #endif /* ?TIMESTAMP */ /* local2[] and local3[]: modifier options */ #ifdef DOS_FLX_H68_OS2_W32 #ifdef FLEXOS static ZCONST char Far local2[] = ""; #else static ZCONST char Far local2[] = " -$ label removables (-$$ => fixed disks)"; #endif #ifdef OS2 #ifdef MORE static ZCONST char Far local3[] = "\ -X restore ACLs if supported -s spaces in filenames => '_'\n\ -M pipe through \"more\" pager\n"; #else static ZCONST char Far local3[] = " \ -X restore ACLs if supported -s spaces in filenames => '_'\n\n"; #endif /* ?MORE */ #else /* !OS2 */ #ifdef WIN32 #ifdef NTSD_EAS #ifdef MORE static ZCONST char Far local3[] = "\ -X restore ACLs (-XX => use privileges) -s spaces in filenames => '_'\n\ -M pipe through \"more\" pager\n"; #else static ZCONST char Far local3[] = " \ -X restore ACLs (-XX => use privileges) -s spaces in filenames => '_'\n\n"; #endif /* ?MORE */ #else /* !NTSD_EAS */ #ifdef MORE static ZCONST char Far local3[] = "\ -M pipe through \"more\" pager \ -s spaces in filenames => '_'\n\n"; #else static ZCONST char Far local3[] = " \ -s spaces in filenames => '_'\n\n"; #endif /* ?MORE */ #endif /* ?NTSD_EAS */ #else /* !WIN32 */ #ifdef MORE static ZCONST char Far local3[] = " -\ M pipe through \"more\" pager -s spaces in filenames => '_'\n\n"; #else static ZCONST char Far local3[] = "\ -s spaces in filenames => '_'\n"; #endif #endif /* ?WIN32 */ #endif /* ?OS2 || ?WIN32 */ #else /* !DOS_FLX_OS2_W32 */ #ifdef VMS static ZCONST char Far local2[] = " -X restore owner/ACL protection info"; #ifdef MORE static ZCONST char Far local3[] = "\ -Y treat \".nnn\" as \";nnn\" version -2 force ODS2 names\n\ --D restore dir (-D: no) timestamps -M pipe through \"more\" pager\n\ (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\ \n\n"; #else static ZCONST char Far local3[] = "\n\ -Y treat \".nnn\" as \";nnn\" version -2 force ODS2 names\n\ --D restore dir (-D: no) timestamps\n\ (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\ \n\n"; #endif #else /* !VMS */ #ifdef ATH_BEO_UNX static ZCONST char Far local2[] = " -X restore UID/GID info"; #ifdef MORE static ZCONST char Far local3[] = "\ -K keep setuid/setgid/tacky permissions -M pipe through \"more\" pager\n"; #else static ZCONST char Far local3[] = "\ -K keep setuid/setgid/tacky permissions\n"; #endif #else /* !ATH_BEO_UNX */ #ifdef TANDEM static ZCONST char Far local2[] = "\ -X restore Tandem User ID -r remove file extensions\n\ -b create 'C' (180) text files "; #ifdef MORE static ZCONST char Far local3[] = " \ -M pipe through \"more\" pager\n"; #else static ZCONST char Far local3[] = "\n"; #endif #else /* !TANDEM */ #ifdef AMIGA static ZCONST char Far local2[] = " -N restore comments as filenotes"; #ifdef MORE static ZCONST char Far local3[] = " \ -M pipe through \"more\" pager\n"; #else static ZCONST char Far local3[] = "\n"; #endif #else /* !AMIGA */ #ifdef MACOS static ZCONST char Far local2[] = " -E show Mac info during extraction"; static ZCONST char Far local3[] = " \ -i ignore filenames in mac extra info -J junk (ignore) Mac extra info\n\ \n"; #else /* !MACOS */ #ifdef MORE static ZCONST char Far local2[] = " -M pipe through \"more\" pager"; static ZCONST char Far local3[] = "\n"; #else static ZCONST char Far local2[] = ""; /* Atari, Mac, CMS/MVS etc. */ static ZCONST char Far local3[] = ""; #endif #endif /* ?MACOS */ #endif /* ?AMIGA */ #endif /* ?TANDEM */ #endif /* ?ATH_BEO_UNX */ #endif /* ?VMS */ #endif /* ?DOS_FLX_OS2_W32 */ #endif /* !SFX */ #ifndef NO_ZIPINFO #ifdef VMS static ZCONST char Far ZipInfoExample[] = "* or % (e.g., \"*font-%.zip\")"; #else static ZCONST char Far ZipInfoExample[] = "*, ?, [] (e.g., \"[a-j]*.zip\")"; #endif static ZCONST char Far ZipInfoUsageLine1[] = "\ ZipInfo %d.%d%d%s of %s, by Greg Roelofs and the Info-ZIP group.\n\ \n\ List name, date/time, attribute, size, compression method, etc., about files\n\ in list (excluding those in xlist) contained in the specified .zip archive(s).\ \n\"file[.zip]\" may be a wildcard name containing %s.\n\n\ usage: zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n\ or: unzip %s-Z%s [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n"; static ZCONST char Far ZipInfoUsageLine2[] = "\nmain\ listing-format options: -s short Unix \"ls -l\" format (def.)\n\ -1 filenames ONLY, one per line -m medium Unix \"ls -l\" format\n\ -2 just filenames but allow -h/-t/-z -l long Unix \"ls -l\" format\n\ -v verbose, multi-page format\n"; static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\ -h print header line -t print totals for listed files or for all\n\ -z print zipfile comment -T print file times in sortable decimal format\ \n -C be case-insensitive %s\ -x exclude filenames that follow from listing\n"; #ifdef MORE static ZCONST char Far ZipInfoUsageLine4[] = " -M page output through built-in \"more\"\n"; #else /* !MORE */ static ZCONST char Far ZipInfoUsageLine4[] = ""; #endif /* ?MORE */ #endif /* !NO_ZIPINFO */ #ifdef BETA # ifdef VMSCLI /* BetaVersion[] is also used in vms/cmdline.c: do not make it static */ ZCONST char Far BetaVersion[] = "%s\ THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n"; # else static ZCONST char Far BetaVersion[] = "%s\ THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n"; # endif #endif #ifdef SFX # ifdef VMSCLI /* UnzipSFXBanner[] is also used in vms/cmdline.c: do not make it static */ ZCONST char Far UnzipSFXBanner[] = # else static ZCONST char Far UnzipSFXBanner[] = # endif SFX_APP_BANNER "\n"; # ifdef SFX_EXDIR static ZCONST char Far UnzipSFXOpts[] = "Valid options are -tfupcz and -d ; modifiers are -abjnoqCL%sV%s.\n"; # else static ZCONST char Far UnzipSFXOpts[] = "Valid options are -tfupcz; modifiers are -abjnoqCL%sV%s.\n"; # endif #else /* !SFX */ static ZCONST char Far CompileOptions[] = "UnZip special compilation options:\n"; static ZCONST char Far CompileOptFormat[] = " %s\n"; #ifndef _WIN32_WCE /* Win CE does not support environment variables */ static ZCONST char Far EnvOptions[] = "\nUnZip and ZipInfo environment options:\n"; static ZCONST char Far EnvOptFormat[] = "%16s: %.1024s\n"; #endif static ZCONST char Far None[] = "[none]"; # ifdef ACORN_FTYPE_NFS static ZCONST char Far AcornFtypeNFS[] = "ACORN_FTYPE_NFS"; # endif # ifdef ASM_CRC static ZCONST char Far AsmCRC[] = "ASM_CRC"; # endif # ifdef ASM_INFLATECODES static ZCONST char Far AsmInflateCodes[] = "ASM_INFLATECODES"; # endif # ifdef CHECK_VERSIONS static ZCONST char Far Check_Versions[] = "CHECK_VERSIONS"; # endif # ifdef COPYRIGHT_CLEAN static ZCONST char Far Copyright_Clean[] = "COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported)"; # endif # ifdef DEBUG static ZCONST char Far UDebug[] = "DEBUG"; # endif # ifdef DEBUG_TIME static ZCONST char Far DebugTime[] = "DEBUG_TIME"; # endif # ifdef DLL static ZCONST char Far Dll[] = "DLL"; # endif # ifdef DOSWILD static ZCONST char Far DosWild[] = "DOSWILD"; # endif # ifdef LZW_CLEAN static ZCONST char Far LZW_Clean[] = "LZW_CLEAN (PKZIP/Zip 1.x unshrinking method not supported)"; # endif # ifndef MORE static ZCONST char Far No_More[] = "NO_MORE"; # endif # ifdef NO_ZIPINFO static ZCONST char Far No_ZipInfo[] = "NO_ZIPINFO"; # endif # ifdef NTSD_EAS static ZCONST char Far NTSDExtAttrib[] = "NTSD_EAS"; # endif # if defined(WIN32) && defined(NO_W32TIMES_IZFIX) static ZCONST char Far W32NoIZTimeFix[] = "NO_W32TIMES_IZFIX"; # endif # ifdef OLD_THEOS_EXTRA static ZCONST char Far OldTheosExtra[] = "OLD_THEOS_EXTRA (handle also old Theos port extra field)"; # endif # ifdef OS2_EAS static ZCONST char Far OS2ExtAttrib[] = "OS2_EAS"; # endif # ifdef QLZIP static ZCONST char Far SMSExFldOnUnix[] = "QLZIP"; # endif # ifdef REENTRANT static ZCONST char Far Reentrant[] = "REENTRANT"; # endif # ifdef REGARGS static ZCONST char Far RegArgs[] = "REGARGS"; # endif # ifdef RETURN_CODES static ZCONST char Far Return_Codes[] = "RETURN_CODES"; # endif # ifdef SET_DIR_ATTRIB static ZCONST char Far SetDirAttrib[] = "SET_DIR_ATTRIB"; # endif # ifdef SYMLINKS static ZCONST char Far SymLinkSupport[] = "SYMLINKS (symbolic links supported, if RTL and file system permit)"; # endif # ifdef TIMESTAMP static ZCONST char Far TimeStamp[] = "TIMESTAMP"; # endif # ifdef UNIXBACKUP static ZCONST char Far UnixBackup[] = "UNIXBACKUP"; # endif # ifdef USE_EF_UT_TIME static ZCONST char Far Use_EF_UT_time[] = "USE_EF_UT_TIME"; # endif # ifndef LZW_CLEAN static ZCONST char Far Use_Unshrink[] = "USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)"; # endif # ifndef COPYRIGHT_CLEAN static ZCONST char Far Use_Smith_Code[] = "USE_SMITH_CODE (PKZIP 0.9x unreducing method supported)"; # endif # ifdef USE_DEFLATE64 static ZCONST char Far Use_Deflate64[] = "USE_DEFLATE64 (PKZIP 4.x Deflate64(tm) supported)"; # endif # ifdef UNICODE_SUPPORT # ifdef UTF8_MAYBE_NATIVE # ifdef UNICODE_WCHAR /* direct native UTF-8 check AND charset transform via wchar_t */ static ZCONST char Far Use_Unicode[] = "UNICODE_SUPPORT [wide-chars, char coding: %s] (handle UTF-8 paths)"; # else /* direct native UTF-8 check, only */ static ZCONST char Far Use_Unicode[] = "UNICODE_SUPPORT [char coding: %s] (handle UTF-8 paths)"; # endif static ZCONST char Far SysChUTF8[] = "UTF-8"; static ZCONST char Far SysChOther[] = "other"; # else /* !UTF8_MAYBE_NATIVE */ /* charset transform via wchar_t, no native UTF-8 support */ static ZCONST char Far Use_Unicode[] = "UNICODE_SUPPORT [wide-chars] (handle UTF-8 paths)"; # endif /* ?UTF8_MAYBE_NATIVE */ # endif /* UNICODE_SUPPORT */ # ifdef _MBCS static ZCONST char Far Have_MBCS_Support[] = "MBCS-support (multibyte character support, MB_CUR_MAX = %u)"; # endif # ifdef MULT_VOLUME static ZCONST char Far Use_MultiVol[] = "MULT_VOLUME (multi-volume archives supported)"; # endif # ifdef LARGE_FILE_SUPPORT static ZCONST char Far Use_LFS[] = "LARGE_FILE_SUPPORT (large files over 2 GiB supported)"; # endif # ifdef ZIP64_SUPPORT static ZCONST char Far Use_Zip64[] = "ZIP64_SUPPORT (archives using Zip64 for large files supported)"; # endif # if (defined(__DJGPP__) && (__DJGPP__ >= 2)) # ifdef USE_DJGPP_ENV static ZCONST char Far Use_DJGPP_Env[] = "USE_DJGPP_ENV"; # endif # ifdef USE_DJGPP_GLOB static ZCONST char Far Use_DJGPP_Glob[] = "USE_DJGPP_GLOB"; # endif # endif /* __DJGPP__ && (__DJGPP__ >= 2) */ # ifdef USE_VFAT static ZCONST char Far Use_VFAT_support[] = "USE_VFAT"; # endif # ifdef USE_ZLIB static ZCONST char Far UseZlib[] = "USE_ZLIB (compiled with version %s; using version %s)"; # endif # ifdef USE_BZIP2 static ZCONST char Far UseBZip2[] = "USE_BZIP2 (PKZIP 4.6+, using bzip2 lib version %s)"; # endif # ifdef VMS_TEXT_CONV static ZCONST char Far VmsTextConv[] = "VMS_TEXT_CONV"; # endif # ifdef VMSCLI static ZCONST char Far VmsCLI[] = "VMSCLI"; # endif # ifdef VMSWILD static ZCONST char Far VmsWild[] = "VMSWILD"; # endif # ifdef WILD_STOP_AT_DIR static ZCONST char Far WildStopAtDir[] = "WILD_STOP_AT_DIR"; # endif # if CRYPT # ifdef PASSWD_FROM_STDIN static ZCONST char Far PasswdStdin[] = "PASSWD_FROM_STDIN"; # endif static ZCONST char Far Decryption[] = " [decryption, version %d.%d%s of %s]\n"; static ZCONST char Far CryptDate[] = CR_VERSION_DATE; # endif # ifndef __RSXNT__ # ifdef __EMX__ static ZCONST char Far EnvEMX[] = "EMX"; static ZCONST char Far EnvEMXOPT[] = "EMXOPT"; # endif # if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2))) static ZCONST char Far EnvGO32[] = "GO32"; static ZCONST char Far EnvGO32TMP[] = "GO32TMP"; # endif # endif /* !__RSXNT__ */ #ifdef VMS /* UnzipUsageLine1[] is also used in vms/cmdline.c: do not make it static */ ZCONST char Far UnzipUsageLine1[] = "\ UnZip %d.%d%d%s of %s, by Info-ZIP. For more details see: unzip -v.\n\n"; # ifdef COPYRIGHT_CLEAN static ZCONST char Far UnzipUsageLine1v[] = "\ UnZip %d.%d%d%s of %s, by Info-ZIP. Maintained by C. Spieler. Send\n\ bug reports using http://www.info-zip.org/zip-bug.html; see README for details.\ \n\n"; # else static ZCONST char Far UnzipUsageLine1v[] = "\ UnZip %d.%d%d%s of %s, by Info-ZIP. UnReduce (c) 1989 by S. H. Smith.\n\ Send bug reports using //www.info-zip.org/zip-bug.html; see README for details.\ \n\n"; # endif /* ?COPYRIGHT_CLEAN */ #else /* !VMS */ # ifdef COPYRIGHT_CLEAN static ZCONST char Far UnzipUsageLine1[] = "\ UnZip %d.%d%d%s of %s, by Info-ZIP. Maintained by C. Spieler. Send\n\ bug reports using http://www.info-zip.org/zip-bug.html; see README for details.\ \n\n"; # else static ZCONST char Far UnzipUsageLine1[] = "\ UnZip %d.%d%d%s of %s, by Info-ZIP. UnReduce (c) 1989 by S. H. Smith.\n\ Send bug reports using //www.info-zip.org/zip-bug.html; see README for details.\ \n\n"; # endif /* ?COPYRIGHT_CLEAN */ # define UnzipUsageLine1v UnzipUsageLine1 #endif /* ?VMS */ static ZCONST char Far UnzipUsageLine2v[] = "\ Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip/ ;\ \nsee ftp://ftp.info-zip.org/pub/infozip/UnZip.html for other sites.\ \n\n"; #ifdef MACOS static ZCONST char Far UnzipUsageLine2[] = "\ Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-d exdir]\n \ Default action is to extract files in list, to exdir;\n\ file[.zip] may be a wildcard. %s\n"; #else /* !MACOS */ #ifdef VM_CMS static ZCONST char Far UnzipUsageLine2[] = "\ Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d fm]\n \ Default action is to extract files in list, except those in xlist, to disk fm;\ \n file[.zip] may be a wildcard. %s\n"; #else /* !VM_CMS */ static ZCONST char Far UnzipUsageLine2[] = "\ Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \ Default action is to extract files in list, except those in xlist, to exdir;\n\ file[.zip] may be a wildcard. %s\n"; #endif /* ?VM_CMS */ #endif /* ?MACOS */ #ifdef NO_ZIPINFO # define ZIPINFO_MODE_OPTION "" static ZCONST char Far ZipInfoMode[] = "(ZipInfo mode is disabled in this version.)"; #else # define ZIPINFO_MODE_OPTION "[-Z] " static ZCONST char Far ZipInfoMode[] = "-Z => ZipInfo mode (\"unzip -Z\" for usage)."; #endif /* ?NO_ZIPINFO */ #ifdef VMS static ZCONST char Far VMSusageLine2b[] = "\ => define foreign command symbol in LOGIN.COM: $ unzip :== $dev:[dir]unzip.exe\ \n"; #endif #ifdef MACOS static ZCONST char Far UnzipUsageLine3[] = "\n\ -d extract files into exdir -l list files (short format)\n\ -f freshen existing files, create none -t test compressed archive data\n\ -u update files, create if necessary -z display archive comment only\n\ -v list verbosely/show version info %s\n"; #else /* !MACOS */ #ifdef VM_CMS static ZCONST char Far UnzipUsageLine3[] = "\n\ -p extract files to pipe, no messages -l list files (short format)\n\ -f freshen existing files, create none -t test compressed archive data\n\ -u update files, create if necessary -z display archive comment only\n\ -v list verbosely/show version info %s\n\ -x exclude files that follow (in xlist) -d extract files onto disk fm\n"; #else /* !VM_CMS */ static ZCONST char Far UnzipUsageLine3[] = "\n\ -p extract files to pipe, no messages -l list files (short format)\n\ -f freshen existing files, create none -t test compressed archive data\n\ -u update files, create if necessary -z display archive comment only\n\ -v list verbosely/show version info %s\n\ -x exclude files that follow (in xlist) -d extract files into exdir\n"; #endif /* ?VM_CMS */ #endif /* ?MACOS */ /* There is not enough space on a standard 80x25 Windows console screen for * the additional line advertising the UTF-8 debugging options. This may * eventually also be the case for other ports. Probably, the -U option need * not be shown on the introductory screen at all. [Chr. Spieler, 2008-02-09] * * Likely, other advanced options should be moved to an extended help page and * the option to list that page put here. [E. Gordon, 2008-3-16] */ #if (defined(UNICODE_SUPPORT) && !defined(WIN32)) #ifdef VMS static ZCONST char Far UnzipUsageLine4[] = "\ modifiers:\n\ -n never overwrite or make a new version of an existing file\n\ -o always make a new version (-oo: overwrite original) of an existing file\n\ -q quiet mode (-qq => quieter) -a auto-convert any text files\n\ -j junk paths (do not make directories) -aa treat ALL files as text\n\ -U use escapes for all non-ASCII Unicode -UU ignore any Unicode fields\n\ -C match filenames case-insensitively -L make (some) names \ lowercase\n %-42s -V retain VMS version numbers\n%s"; #else /* !VMS */ static ZCONST char Far UnzipUsageLine4[] = "\ modifiers:\n\ -n never overwrite existing files -q quiet mode (-qq => quieter)\n\ -o overwrite files WITHOUT prompting -a auto-convert any text files\n\ -j junk paths (do not make directories) -aa treat ALL files as text\n\ -U use escapes for all non-ASCII Unicode -UU ignore any Unicode fields\n\ -C match filenames case-insensitively -L make (some) names \ lowercase\n %-42s -V retain VMS version numbers\n%s"; #endif /* ?VMS */ #else /* !UNICODE_SUPPORT */ #ifdef VMS static ZCONST char Far UnzipUsageLine4[] = "\ modifiers:\n\ -n never overwrite or make a new version of an existing file\n\ -o always make a new version (-oo: overwrite original) of an existing file\n\ -q quiet mode (-qq => quieter) -a auto-convert any text files\n\ -j junk paths (do not make directories) -aa treat ALL files as text\n\ -C match filenames case-insensitively -L make (some) names \ lowercase\n %-42s -V retain VMS version numbers\n%s"; #else /* !VMS */ static ZCONST char Far UnzipUsageLine4[] = "\ modifiers:\n\ -n never overwrite existing files -q quiet mode (-qq => quieter)\n\ -o overwrite files WITHOUT prompting -a auto-convert any text files\n\ -j junk paths (do not make directories) -aa treat ALL files as text\n\ -C match filenames case-insensitively -L make (some) names \ lowercase\n %-42s -V retain VMS version numbers\n%s"; #endif /* ?VMS */ #endif /* ?UNICODE_SUPPORT */ static ZCONST char Far UnzipUsageLine5[] = "\ See \"unzip -hh\" or unzip.txt for more help. Examples:\n\ unzip data1 -x joe => extract all files except joe from zipfile data1.zip\n\ %s\ unzip -fo foo %-6s => quietly replace existing %s if archive file newer\n"; #endif /* ?SFX */ /*****************************/ /* main() / UzpMain() stub */ /*****************************/ int MAIN(argc, argv) /* return PK-type error code (except under VMS) */ int argc; char *argv[]; { int r; CONSTRUCTGLOBALS(); r = unzip(__G__ argc, argv); DESTROYGLOBALS(); RETURN(r); } /*******************************/ /* Primary UnZip entry point */ /*******************************/ int unzip(__G__ argc, argv) __GDEF int argc; char *argv[]; { #ifndef NO_ZIPINFO char *p; #endif #if (defined(DOS_FLX_H68_NLM_OS2_W32) || !defined(SFX)) int i; #endif int retcode, error=FALSE; #ifndef NO_EXCEPT_SIGNALS #ifdef REENTRANT savsigs_info *oldsighandlers = NULL; # define SET_SIGHANDLER(sigtype, newsighandler) \ if ((retcode = setsignalhandler(__G__ &oldsighandlers, (sigtype), \ (newsighandler))) > PK_WARN) \ goto cleanup_and_exit #else # define SET_SIGHANDLER(sigtype, newsighandler) \ signal((sigtype), (newsighandler)) #endif #endif /* NO_EXCEPT_SIGNALS */ /* initialize international char support to the current environment */ SETLOCALE(LC_CTYPE, "C"); #ifdef UNICODE_SUPPORT /* see if can use UTF-8 Unicode locale */ # ifdef UTF8_MAYBE_NATIVE { char *codeset; # if !(defined(NO_NL_LANGINFO) || defined(NO_LANGINFO_H)) /* get the codeset (character set encoding) currently used */ # include codeset = nl_langinfo(CODESET); # else /* NO_NL_LANGINFO || NO_LANGINFO_H */ /* query the current locale setting for character classification */ codeset = setlocale(LC_CTYPE, NULL); if (codeset != NULL) { /* extract the codeset portion of the locale name */ codeset = strchr(codeset, '.'); if (codeset != NULL) ++codeset; } # endif /* ?(NO_NL_LANGINFO || NO_LANGINFO_H) */ /* is the current codeset UTF-8 ? */ if ((codeset != NULL) && (strcmp(codeset, "UTF-8") == 0)) { /* successfully found UTF-8 char coding */ G.native_is_utf8 = TRUE; } else { /* Current codeset is not UTF-8 or cannot be determined. */ G.native_is_utf8 = FALSE; } /* Note: At least for UnZip, trying to change the process codeset to * UTF-8 does not work. For the example Linux setup of the * UnZip maintainer, a successful switch to "en-US.UTF-8" * resulted in garbage display of all non-basic ASCII characters. */ } # endif /* UTF8_MAYBE_NATIVE */ /* initialize Unicode */ G.unicode_escape_all = 0; G.unicode_mismatch = 0; G.unipath_version = 0; G.unipath_checksum = 0; G.unipath_filename = NULL; #endif /* UNICODE_SUPPORT */ #if (defined(__IBMC__) && defined(__DEBUG_ALLOC__)) extern void DebugMalloc(void); atexit(DebugMalloc); #endif #ifdef MALLOC_WORK /* The following (rather complex) expression determines the allocation size of the decompression work area. It simulates what the combined "union" and "struct" declaration of the "static" work area reservation achieves automatically at compile time. Any decent compiler should evaluate this expression completely at compile time and provide constants to the zcalloc() call. (For better readability, some subexpressions are encapsulated in temporarly defined macros.) */ # define UZ_SLIDE_CHUNK (sizeof(shrint)+sizeof(uch)+sizeof(uch)) # define UZ_NUMOF_CHUNKS \ (unsigned)(((WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK > HSIZE) ? \ (WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK : HSIZE) G.area.Slide = (uch *)zcalloc(UZ_NUMOF_CHUNKS, UZ_SLIDE_CHUNK); # undef UZ_SLIDE_CHUNK # undef UZ_NUMOF_CHUNKS G.area.shrink.Parent = (shrint *)G.area.Slide; G.area.shrink.value = G.area.Slide + (sizeof(shrint)*(HSIZE)); G.area.shrink.Stack = G.area.Slide + (sizeof(shrint) + sizeof(uch))*(HSIZE); #endif /*--------------------------------------------------------------------------- Set signal handler for restoring echo, warn of zipfile corruption, etc. ---------------------------------------------------------------------------*/ #ifndef NO_EXCEPT_SIGNALS #ifdef SIGINT SET_SIGHANDLER(SIGINT, handler); #endif #ifdef SIGTERM /* some systems really have no SIGTERM */ SET_SIGHANDLER(SIGTERM, handler); #endif #if defined(SIGABRT) && !(defined(AMIGA) && defined(__SASC)) SET_SIGHANDLER(SIGABRT, handler); #endif #ifdef SIGBREAK SET_SIGHANDLER(SIGBREAK, handler); #endif #ifdef SIGBUS SET_SIGHANDLER(SIGBUS, handler); #endif #ifdef SIGILL SET_SIGHANDLER(SIGILL, handler); #endif #ifdef SIGSEGV SET_SIGHANDLER(SIGSEGV, handler); #endif #endif /* NO_EXCEPT_SIGNALS */ #if (defined(WIN32) && defined(__RSXNT__)) for (i = 0 ; i < argc; i++) { _ISO_INTERN(argv[i]); } #endif /*--------------------------------------------------------------------------- Macintosh initialization code. ---------------------------------------------------------------------------*/ #ifdef MACOS { int a; for (a = 0; a < 4; ++a) G.rghCursor[a] = GetCursor(a+128); G.giCursor = 0; } #endif /*--------------------------------------------------------------------------- NetWare initialization code. ---------------------------------------------------------------------------*/ #ifdef NLM InitUnZipConsole(); #endif /*--------------------------------------------------------------------------- Acorn RISC OS initialization code. ---------------------------------------------------------------------------*/ #ifdef RISCOS set_prefix(); #endif /*--------------------------------------------------------------------------- Theos initialization code. ---------------------------------------------------------------------------*/ #ifdef THEOS /* The easiest way found to force creation of libraries when selected * members are to be unzipped. Explicitly add libraries names to the * arguments list before the first member of the library. */ if (! _setargv(&argc, &argv)) { Info(slide, 0x401, ((char *)slide, "cannot process argv\n")); retcode = PK_MEM; goto cleanup_and_exit; } #endif /*--------------------------------------------------------------------------- Sanity checks. Commentary by Otis B. Driftwood and Fiorello: D: It's all right. That's in every contract. That's what they call a sanity clause. F: Ha-ha-ha-ha-ha. You can't fool me. There ain't no Sanity Claus. ---------------------------------------------------------------------------*/ #ifdef DEBUG # ifdef LARGE_FILE_SUPPORT /* test if we can support large files - 10/6/04 EG */ if (sizeof(zoff_t) < 8) { Info(slide, 0x401, ((char *)slide, "LARGE_FILE_SUPPORT set but not supported\n")); retcode = PK_BADERR; goto cleanup_and_exit; } /* test if we can show 64-bit values */ { zoff_t z = ~(zoff_t)0; /* z should be all 1s now */ char *sz; sz = FmZofft(z, FZOFFT_HEX_DOT_WID, "X"); if ((sz[0] != 'F') || (strlen(sz) != 16)) { z = 0; } /* shift z so only MSB is set */ z <<= 63; sz = FmZofft(z, FZOFFT_HEX_DOT_WID, "X"); if ((sz[0] != '8') || (strlen(sz) != 16)) { Info(slide, 0x401, ((char *)slide, "Can't show 64-bit values correctly\n")); retcode = PK_BADERR; goto cleanup_and_exit; } } # endif /* LARGE_FILE_SUPPORT */ /* 2004-11-30 SMS. Test the NEXTBYTE macro for proper operation. */ { int test_char; static uch test_buf[2] = { 'a', 'b' }; G.inptr = test_buf; G.incnt = 1; test_char = NEXTBYTE; /* Should get 'a'. */ if (test_char == 'a') { test_char = NEXTBYTE; /* Should get EOF, not 'b'. */ } if (test_char != EOF) { Info(slide, 0x401, ((char *)slide, "NEXTBYTE macro failed. Try compiling with ALT_NEXTBYTE defined?")); retcode = PK_BADERR; goto cleanup_and_exit; } } #endif /* DEBUG */ /*--------------------------------------------------------------------------- First figure out if we're running in UnZip mode or ZipInfo mode, and put the appropriate environment-variable options into the queue. Then rip through any command-line options lurking about... ---------------------------------------------------------------------------*/ #ifdef SFX G.argv0 = argv[0]; #if (defined(OS2) || defined(WIN32)) G.zipfn = GetLoadPath(__G);/* non-MSC NT puts path into G.filename[] */ #else G.zipfn = G.argv0; #endif #ifdef VMSCLI { ulg status = vms_unzip_cmdline(&argc, &argv); if (!(status & 1)) { retcode = (int)status; goto cleanup_and_exit; } } #endif /* VMSCLI */ uO.zipinfo_mode = FALSE; error = uz_opts(__G__ &argc, &argv); /* UnZipSFX call only */ #else /* !SFX */ #ifdef RISCOS /* get the extensions to swap from environment */ getRISCOSexts(ENV_UNZIPEXTS); #endif #ifdef MSDOS /* extract MKS extended argument list from environment (before envargs!) */ mksargs(&argc, &argv); #endif #ifdef VMSCLI { ulg status = vms_unzip_cmdline(&argc, &argv); if (!(status & 1)) { retcode = (int)status; goto cleanup_and_exit; } } #endif /* VMSCLI */ G.noargs = (argc == 1); /* no options, no zipfile, no anything */ #ifndef NO_ZIPINFO for (p = argv[0] + strlen(argv[0]); p >= argv[0]; --p) { if (*p == DIR_END #ifdef DIR_END2 || *p == DIR_END2 #endif ) break; } ++p; #ifdef THEOS if (strncmp(p, "ZIPINFO.",8) == 0 || strstr(p, ".ZIPINFO:") != NULL || strncmp(p, "II.",3) == 0 || strstr(p, ".II:") != NULL || #else if (STRNICMP(p, LoadFarStringSmall(Zipnfo), 7) == 0 || STRNICMP(p, "ii", 2) == 0 || #endif (argc > 1 && strncmp(argv[1], "-Z", 2) == 0)) { uO.zipinfo_mode = TRUE; #ifndef _WIN32_WCE /* Win CE does not support environment variables */ if ((error = envargs(&argc, &argv, LoadFarStringSmall(EnvZipInfo), LoadFarStringSmall2(EnvZipInfo2))) != PK_OK) perror(LoadFarString(NoMemEnvArguments)); #endif } else #endif /* !NO_ZIPINFO */ { uO.zipinfo_mode = FALSE; #ifndef _WIN32_WCE /* Win CE does not support environment variables */ if ((error = envargs(&argc, &argv, LoadFarStringSmall(EnvUnZip), LoadFarStringSmall2(EnvUnZip2))) != PK_OK) perror(LoadFarString(NoMemEnvArguments)); #endif } if (!error) { /* Check the length of all passed command line parameters. * Command arguments might get sent through the Info() message * system, which uses the sliding window area as string buffer. * As arguments may additionally get fed through one of the FnFilter * macros, we require all command line arguments to be shorter than * WSIZE/4 (and ca. 2 standard line widths for fixed message text). */ for (i = 1 ; i < argc; i++) { if (strlen(argv[i]) > ((WSIZE>>2) - 160)) { Info(slide, 0x401, ((char *)slide, LoadFarString(CmdLineParamTooLong), i)); retcode = PK_PARAM; goto cleanup_and_exit; } } #ifndef NO_ZIPINFO if (uO.zipinfo_mode) error = zi_opts(__G__ &argc, &argv); else #endif /* !NO_ZIPINFO */ error = uz_opts(__G__ &argc, &argv); } #endif /* ?SFX */ if ((argc < 0) || error) { retcode = error; goto cleanup_and_exit; } /*--------------------------------------------------------------------------- Now get the zipfile name from the command line and then process any re- maining options and file specifications. ---------------------------------------------------------------------------*/ #ifdef DOS_FLX_H68_NLM_OS2_W32 /* convert MSDOS-style 'backward slash' directory separators to Unix-style * 'forward slashes' for user's convenience (include zipfile name itself) */ #ifdef SFX for (G.pfnames = argv, i = argc; i > 0; --i) { #else /* argc does not include the zipfile specification */ for (G.pfnames = argv, i = argc+1; i > 0; --i) { #endif #ifdef __human68k__ extern char *_toslash(char *); _toslash(*G.pfnames); #else /* !__human68k__ */ char *q = *G.pfnames; while (*q != '\0') { if (*q == '\\') *q = '/'; INCSTR(q); } #endif /* ?__human68k__ */ ++G.pfnames; } #endif /* DOS_FLX_H68_NLM_OS2_W32 */ #ifndef SFX G.wildzipfn = *argv++; #endif #if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */ G.filespecs = argc; G.xfilespecs = 0; if (argc > 0) { char **pp = argv-1; G.pfnames = argv; while (*++pp) if (strcmp(*pp, "-x") == 0) { if (pp > argv) { *pp = 0; /* terminate G.pfnames */ G.filespecs = pp - G.pfnames; } else { G.pfnames = (char **)fnames; /* defaults */ G.filespecs = 0; } G.pxnames = pp + 1; /* excluded-names ptr: _after_ -x */ G.xfilespecs = argc - G.filespecs - 1; break; /* skip rest of args */ } G.process_all_files = FALSE; } else G.process_all_files = TRUE; /* for speed */ #else /* !SFX || SFX_EXDIR */ /* check for -x or -d */ G.filespecs = argc; G.xfilespecs = 0; if (argc > 0) { int in_files=FALSE, in_xfiles=FALSE; char **pp = argv-1; G.process_all_files = FALSE; G.pfnames = argv; while (*++pp) { Trace((stderr, "pp - argv = %d\n", pp-argv)); #ifdef CMS_MVS if (!uO.exdir && STRNICMP(*pp, "-d", 2) == 0) { #else if (!uO.exdir && strncmp(*pp, "-d", 2) == 0) { #endif int firstarg = (pp == argv); uO.exdir = (*pp) + 2; if (in_files) { /* ... zipfile ... -d exdir ... */ *pp = (char *)NULL; /* terminate G.pfnames */ G.filespecs = pp - G.pfnames; in_files = FALSE; } else if (in_xfiles) { *pp = (char *)NULL; /* terminate G.pxnames */ G.xfilespecs = pp - G.pxnames; /* "... -x xlist -d exdir": nothing left */ } /* first check for "-dexdir", then for "-d exdir" */ if (*uO.exdir == '\0') { if (*++pp) uO.exdir = *pp; else { Info(slide, 0x401, ((char *)slide, LoadFarString(MustGiveExdir))); /* don't extract here by accident */ retcode = PK_PARAM; goto cleanup_and_exit; } } if (firstarg) { /* ... zipfile -d exdir ... */ if (pp[1]) { G.pfnames = pp + 1; /* argv+2 */ G.filespecs = argc - (G.pfnames-argv); /* for now... */ } else { G.process_all_files = TRUE; G.pfnames = (char **)fnames; /* GRR: necessary? */ G.filespecs = 0; /* GRR: necessary? */ break; } } } else if (!in_xfiles) { if (strcmp(*pp, "-x") == 0) { in_xfiles = TRUE; if (pp == G.pfnames) { G.pfnames = (char **)fnames; /* defaults */ G.filespecs = 0; } else if (in_files) { *pp = 0; /* terminate G.pfnames */ G.filespecs = pp - G.pfnames; /* adjust count */ in_files = FALSE; } G.pxnames = pp + 1; /* excluded-names ptr starts after -x */ G.xfilespecs = argc - (G.pxnames-argv); /* anything left */ } else in_files = TRUE; } } } else G.process_all_files = TRUE; /* for speed */ if (uO.exdir != (char *)NULL && !G.extract_flag) /* -d ignored */ Info(slide, 0x401, ((char *)slide, LoadFarString(NotExtracting))); #endif /* ?(SFX && !SFX_EXDIR) */ #ifdef UNICODE_SUPPORT /* set Unicode-escape-all if option -U used */ if (uO.U_flag == 1) # ifdef UNICODE_WCHAR G.unicode_escape_all = TRUE; # else Info(slide, 0x401, ((char *)slide, LoadFarString(UTF8EscapeUnSupp))); # endif #endif /*--------------------------------------------------------------------------- Okey dokey, we have everything we need to get started. Let's roll. ---------------------------------------------------------------------------*/ retcode = process_zipfiles(__G); cleanup_and_exit: #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS)) /* restore all signal handlers back to their state at function entry */ while (oldsighandlers != NULL) { savsigs_info *thissigsav = oldsighandlers; signal(thissigsav->sigtype, thissigsav->sighandler); oldsighandlers = thissigsav->previous; free(thissigsav); } #endif #if (defined(MALLOC_WORK) && !defined(REENTRANT)) if (G.area.Slide != (uch *)NULL) { free(G.area.Slide); G.area.Slide = (uch *)NULL; } #endif #if (defined(MSDOS) && !defined(SFX) && !defined(WINDLL)) if (retcode != PK_OK) check_for_windows("UnZip"); #endif return(retcode); } /* end main()/unzip() */ #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS)) /*******************************/ /* Function setsignalhandler() */ /*******************************/ static int setsignalhandler(__G__ p_savedhandler_chain, signal_type, newhandler) __GDEF savsigs_info **p_savedhandler_chain; int signal_type; void (*newhandler)(int); { savsigs_info *savsig; savsig = malloc(sizeof(savsigs_info)); if (savsig == NULL) { /* error message and break */ Info(slide, 0x401, ((char *)slide, LoadFarString(CantSaveSigHandler))); return PK_MEM; } savsig->sigtype = signal_type; savsig->sighandler = signal(SIGINT, newhandler); if (savsig->sighandler == SIG_ERR) { free(savsig); } else { savsig->previous = *p_savedhandler_chain; *p_savedhandler_chain = savsig; } return PK_OK; } /* end function setsignalhandler() */ #endif /* REENTRANT && !NO_EXCEPT_SIGNALS */ /**********************/ /* Function uz_opts() */ /**********************/ int uz_opts(__G__ pargc, pargv) __GDEF int *pargc; char ***pargv; { char **argv, *s; int argc, c, error=FALSE, negative=0, showhelp=0; argc = *pargc; argv = *pargv; uO.exdir = sfx_get_tmp_path(0); uO.overwrite_all = 1; sfx_app_set_args(argc-1, argv+1); while (++argv, (--argc > 0 && *argv != NULL /*&& **argv == '-'*/)) { #if 0 s = *argv + 1; while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */ #ifdef CMS_MVS switch (tolower(c)) #else switch (c) #endif { case ('-'): ++negative; break; #ifdef RISCOS case ('/'): if (negative) { /* negative not allowed with -/ swap */ Info(slide, 0x401, ((char *)slide, "error: must give extensions list")); return(PK_PARAM); /* don't extract here by accident */ } exts2swap = s; /* override Unzip$Exts */ s += strlen(s); break; #endif case ('a'): if (negative) { uO.aflag = MAX(uO.aflag-negative,0); negative = 0; } else ++uO.aflag; break; #if (defined(DLL) && defined(API_DOC)) case ('A'): /* extended help for API */ APIhelp(__G__ argc, argv); *pargc = -1; /* signal to exit successfully */ return 0; #endif case ('b'): if (negative) { #if (defined(TANDEM) || defined(VMS)) uO.bflag = MAX(uO.bflag-negative,0); #endif negative = 0; /* do nothing: "-b" is default */ } else { #ifdef VMS if (uO.aflag == 0) ++uO.bflag; #endif #ifdef TANDEM ++uO.bflag; #endif uO.aflag = 0; } break; #ifdef UNIXBACKUP case ('B'): /* -B: back up existing files */ if (negative) uO.B_flag = FALSE, negative = 0; else uO.B_flag = TRUE; break; #endif case ('c'): if (negative) { uO.cflag = FALSE, negative = 0; #ifdef NATIVE uO.aflag = 0; #endif } else { uO.cflag = TRUE; #ifdef NATIVE uO.aflag = 2; /* so you can read it on the screen */ #endif #ifdef DLL if (G.redirect_text) G.redirect_data = 2; #endif } break; #ifndef CMS_MVS case ('C'): /* -C: match filenames case-insensitively */ if (negative) uO.C_flag = FALSE, negative = 0; else uO.C_flag = TRUE; break; #endif /* !CMS_MVS */ #if (!defined(SFX) || defined(SFX_EXDIR)) case ('d'): if (negative) { /* negative not allowed with -d exdir */ Info(slide, 0x401, ((char *)slide, LoadFarString(MustGiveExdir))); return(PK_PARAM); /* don't extract here by accident */ } if (uO.exdir != (char *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(OnlyOneExdir))); return(PK_PARAM); /* GRR: stupid restriction? */ } else { /* first check for "-dexdir", then for "-d exdir" */ uO.exdir = s; if (*uO.exdir == '\0') { if (argc > 1) { --argc; uO.exdir = *++argv; if (*uO.exdir == '-') { Info(slide, 0x401, ((char *)slide, LoadFarString(MustGiveExdir))); return(PK_PARAM); } /* else uO.exdir points at extraction dir */ } else { Info(slide, 0x401, ((char *)slide, LoadFarString(MustGiveExdir))); return(PK_PARAM); } } /* uO.exdir now points at extraction dir (-dexdir or * -d exdir); point s at end of exdir to avoid mis- * interpretation of exdir characters as more options */ if (*s != 0) while (*++s != 0) ; } break; #endif /* !SFX || SFX_EXDIR */ #if (!defined(NO_TIMESTAMPS)) case ('D'): /* -D: Skip restoring dir (or any) timestamp. */ if (negative) { uO.D_flag = MAX(uO.D_flag-negative,0); negative = 0; } else uO.D_flag++; break; #endif /* (!NO_TIMESTAMPS) */ case ('e'): /* just ignore -e, -x options (extract) */ break; #ifdef MACOS case ('E'): /* -E [MacOS] display Mac e.f. when restoring */ if( negative ) { uO.E_flag = FALSE, negative = 0; } else { uO.E_flag = TRUE; } break; #endif /* MACOS */ case ('f'): /* "freshen" (extract only newer files) */ if (negative) uO.fflag = uO.uflag = FALSE, negative = 0; else uO.fflag = uO.uflag = TRUE; break; #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS)) case ('F'): /* Acorn filetype & NFS extension handling */ if (negative) uO.acorn_nfs_ext = FALSE, negative = 0; else uO.acorn_nfs_ext = TRUE; break; #endif /* RISCOS || ACORN_FTYPE_NFS */ case ('h'): /* just print help message and quit */ if (showhelp == 0) { #ifndef SFX if (*s == 'h') showhelp = 2; else #endif /* !SFX */ { showhelp = 1; } } break; #ifdef MACOS case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */ if( negative ) { uO.i_flag = FALSE, negative = 0; } else { uO.i_flag = TRUE; } break; #endif /* MACOS */ case ('j'): /* junk pathnames/directory structure */ if (negative) uO.jflag = FALSE, negative = 0; else uO.jflag = TRUE; break; #if (defined(ATH_BEO) || defined(MACOS)) case ('J'): /* Junk AtheOS, BeOS or MacOS file attributes */ if( negative ) { uO.J_flag = FALSE, negative = 0; } else { uO.J_flag = TRUE; } break; #endif /* ATH_BEO || MACOS */ #ifdef ATH_BEO_UNX case ('K'): if (negative) { uO.K_flag = FALSE, negative = 0; } else { uO.K_flag = TRUE; } break; #endif /* ATH_BEO_UNX */ #ifndef SFX case ('l'): if (negative) { uO.vflag = MAX(uO.vflag-negative,0); negative = 0; } else ++uO.vflag; break; #endif /* !SFX */ #ifndef CMS_MVS case ('L'): /* convert (some) filenames to lowercase */ if (negative) { uO.L_flag = MAX(uO.L_flag-negative,0); negative = 0; } else ++uO.L_flag; break; #endif /* !CMS_MVS */ #ifdef MORE #ifdef CMS_MVS case ('m'): #endif case ('M'): /* send all screen output through "more" fn. */ /* GRR: eventually check for numerical argument => height */ if (negative) G.M_flag = FALSE, negative = 0; else G.M_flag = TRUE; break; #endif /* MORE */ case ('n'): /* don't overwrite any files */ if (negative) uO.overwrite_none = FALSE, negative = 0; else uO.overwrite_none = TRUE; break; #ifdef AMIGA case ('N'): /* restore comments as filenotes */ if (negative) uO.N_flag = FALSE, negative = 0; else uO.N_flag = TRUE; break; #endif /* AMIGA */ case ('o'): /* OK to overwrite files without prompting */ if (negative) { uO.overwrite_all = MAX(uO.overwrite_all-negative,0); negative = 0; } else ++uO.overwrite_all; break; case ('p'): /* pipes: extract to stdout, no messages */ if (negative) { uO.cflag = FALSE; uO.qflag = MAX(uO.qflag-999,0); negative = 0; } else { uO.cflag = TRUE; uO.qflag += 999; } break; #if CRYPT /* GRR: yes, this is highly insecure, but dozens of people * have pestered us for this, so here we go... */ case ('P'): if (negative) { /* negative not allowed with -P passwd */ Info(slide, 0x401, ((char *)slide, LoadFarString(MustGivePasswd))); return(PK_PARAM); /* don't extract here by accident */ } if (uO.pwdarg != (char *)NULL) { /* GRR: eventually support multiple passwords? Info(slide, 0x401, ((char *)slide, LoadFarString(OnlyOnePasswd))); return(PK_PARAM); */ } else { /* first check for "-Ppasswd", then for "-P passwd" */ uO.pwdarg = s; if (*uO.pwdarg == '\0') { if (argc > 1) { --argc; uO.pwdarg = *++argv; if (*uO.pwdarg == '-') { Info(slide, 0x401, ((char *)slide, LoadFarString(MustGivePasswd))); return(PK_PARAM); } /* else pwdarg points at decryption password */ } else { Info(slide, 0x401, ((char *)slide, LoadFarString(MustGivePasswd))); return(PK_PARAM); } } /* pwdarg now points at decryption password (-Ppasswd or * -P passwd); point s at end of passwd to avoid mis- * interpretation of passwd characters as more options */ if (*s != 0) while (*++s != 0) ; } break; #endif /* CRYPT */ case ('q'): /* quiet: fewer comments/messages */ if (negative) { uO.qflag = MAX(uO.qflag-negative,0); negative = 0; } else ++uO.qflag; break; #ifdef QDOS case ('Q'): /* QDOS flags */ qlflag ^= strtol(s, &s, 10); break; /* we XOR this as we can config qlflags */ #endif #ifdef TANDEM case ('r'): /* remove file extensions */ if (negative) uO.rflag = FALSE, negative = 0; else uO.rflag = TRUE; break; #endif /* TANDEM */ #ifdef DOS_FLX_NLM_OS2_W32 case ('s'): /* spaces in filenames: allow by default */ if (negative) uO.sflag = FALSE, negative = 0; else uO.sflag = TRUE; break; #endif /* DOS_FLX_NLM_OS2_W32 */ #ifdef VMS /* VMS: extract "text" files in Stream_LF format (-a[a]) */ case ('S'): if (negative) uO.S_flag = FALSE, negative = 0; else uO.S_flag = TRUE; break; #endif /* VMS */ case ('t'): if (negative) uO.tflag = FALSE, negative = 0; else uO.tflag = TRUE; break; #ifdef TIMESTAMP case ('T'): if (negative) uO.T_flag = FALSE, negative = 0; else uO.T_flag = TRUE; break; #endif case ('u'): /* update (extract only new and newer files) */ if (negative) uO.uflag = FALSE, negative = 0; else uO.uflag = TRUE; break; #ifdef UNICODE_SUPPORT case ('U'): /* escape UTF-8, or disable UTF-8 support */ if (negative) { uO.U_flag = MAX(uO.U_flag-negative,0); negative = 0; } else uO.U_flag++; break; #else /* !UNICODE_SUPPORT */ #ifndef CMS_MVS case ('U'): /* obsolete; to be removed in version 6.0 */ if (negative) uO.L_flag = TRUE, negative = 0; else uO.L_flag = FALSE; break; #endif /* !CMS_MVS */ #endif /* ?UNICODE_SUPPORT */ #ifndef SFX case ('v'): /* verbose */ if (negative) { uO.vflag = MAX(uO.vflag-negative,0); negative = 0; } else if (uO.vflag) ++uO.vflag; else uO.vflag = 2; break; #endif /* !SFX */ #ifndef CMS_MVS case ('V'): /* Version (retain VMS/DEC-20 file versions) */ if (negative) uO.V_flag = FALSE, negative = 0; else uO.V_flag = TRUE; break; #endif /* !CMS_MVS */ #ifdef WILD_STOP_AT_DIR case ('W'): /* Wildcard interpretation (stop at '/'?) */ if (negative) uO.W_flag = FALSE, negative = 0; else uO.W_flag = TRUE; break; #endif /* WILD_STOP_AT_DIR */ case ('x'): /* extract: default */ #ifdef SFX /* when 'x' is the only option in this argument, and the * next arg is not an option, assume this initiates an * exclusion list (-x xlist): terminate option-scanning * and leave uz_opts with argv still pointing to "-x"; * the xlist is processed later */ if (s - argv[0] == 2 && *s == '\0' && argc > 1 && argv[1][0] != '-') { /* break out of nested loops without "++argv;--argc" */ goto opts_done; } #endif /* SFX */ break; #if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL)) case ('X'): /* restore owner/protection info (need privs?) */ if (negative) { uO.X_flag = MAX(uO.X_flag-negative,0); negative = 0; } else ++uO.X_flag; break; #endif /* RESTORE_UIDGID || RESTORE_ACL */ #ifdef VMS case ('Y'): /* Treat ".nnn" as ";nnn" version. */ if (negative) uO.Y_flag = FALSE, negative = 0; else uO.Y_flag = TRUE; break; #endif /* VMS */ case ('z'): /* display only the archive comment */ if (negative) { uO.zflag = MAX(uO.zflag-negative,0); negative = 0; } else ++uO.zflag; break; #ifndef SFX case ('Z'): /* should have been first option (ZipInfo) */ Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst))); error = TRUE; break; #endif /* !SFX */ #ifdef VMS case ('2'): /* Force ODS2-compliant names. */ if (negative) uO.ods2_flag = FALSE, negative = 0; else uO.ods2_flag = TRUE; break; #endif /* VMS */ #ifdef DOS_H68_OS2_W32 case ('$'): if (negative) { uO.volflag = MAX(uO.volflag-negative,0); negative = 0; } else ++uO.volflag; break; #endif /* DOS_H68_OS2_W32 */ #if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM)) case (':'): /* allow "parent dir" path components */ if (negative) { uO.ddotflag = MAX(uO.ddotflag-negative,0); negative = 0; } else ++uO.ddotflag; break; #endif /* !RISCOS && !CMS_MVS && !TANDEM */ #ifdef UNIX case ('^'): /* allow control chars in filenames */ if (negative) { uO.cflxflag = MAX(uO.cflxflag-negative,0); negative = 0; } else ++uO.cflxflag; break; #endif /* UNIX */ default: error = TRUE; break; } /* end switch */ } /* end while (not end of argument string) */ #endif } /* end while (not done with switches) */ /*--------------------------------------------------------------------------- Check for nonsensical combinations of options. ---------------------------------------------------------------------------*/ #if 0 #ifdef SFX opts_done: /* yes, very ugly...but only used by UnZipSFX with -x xlist */ #endif if (showhelp > 0) { /* just print help message and quit */ *pargc = -1; #ifndef SFX if (showhelp == 2) { help_extended(__G); return PK_OK; } else #endif /* !SFX */ { return USAGE(PK_OK); } } if ((uO.cflag && (uO.tflag || uO.uflag)) || (uO.tflag && uO.uflag) || (uO.fflag && uO.overwrite_none)) { Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg))); error = TRUE; } if (uO.aflag > 2) uO.aflag = 2; #ifdef VMS if (uO.bflag > 2) uO.bflag = 2; /* Clear -s flag when converting text files. */ if (uO.aflag <= 0) uO.S_flag = 0; #endif /* VMS */ if (uO.overwrite_all && uO.overwrite_none) { Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg))); uO.overwrite_all = FALSE; } #ifdef MORE if (G.M_flag && !isatty(1)) /* stdout redirected: "more" func. useless */ G.M_flag = 0; #endif #ifdef SFX if (error) #else if ((argc-- == 0) || error) #endif { *pargc = argc; *pargv = argv; #ifndef SFX if (uO.vflag >= 2 && argc == -1) { /* "unzip -v" */ show_version_info(__G); return PK_OK; } if (!G.noargs && !error) error = TRUE; /* had options (not -h or -v) but no zipfile */ #endif /* !SFX */ return USAGE(error); } #endif #ifdef SFX /* print our banner unless we're being fairly quiet */ if (uO.qflag < 2) Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner), UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, LoadFarStringSmall(VersionDate))); #ifdef BETA /* always print the beta warning: no unauthorized distribution!! */ Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n", "SFX")); #endif #endif /* SFX */ if (uO.cflag || uO.tflag || uO.vflag || uO.zflag #ifdef TIMESTAMP || uO.T_flag #endif ) G.extract_flag = FALSE; else G.extract_flag = TRUE; *pargc = argc; *pargv = argv; return PK_OK; } /* end function uz_opts() */ /********************/ /* Function usage() */ /********************/ #ifdef SFX # ifdef VMS # define LOCAL "X.\n\ (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)" # endif # ifdef UNIX # define LOCAL "X" # endif # ifdef DOS_OS2_W32 # define LOCAL "s$" # endif # if (defined(FLEXOS) || defined(NLM)) # define LOCAL "s" # endif # ifdef AMIGA # define LOCAL "N" # endif /* Default for all other systems: */ # ifndef LOCAL # define LOCAL "" # endif # ifndef NO_TIMESTAMP # ifdef MORE # define SFXOPT1 "DM" # else # define SFXOPT1 "D" # endif # else # ifdef MORE # define SFXOPT1 "M" # else # define SFXOPT1 "" # endif # endif int usage(__G__ error) /* return PK-type error code */ __GDEF int error; { Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner), UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, LoadFarStringSmall(VersionDate))); Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXOpts), SFXOPT1, LOCAL)); #ifdef BETA Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n", "SFX")); #endif if (error) return PK_PARAM; else return PK_COOL; /* just wanted usage screen: no error */ } /* end function usage() */ #else /* !SFX */ # ifdef VMS # define QUOT '\"' # define QUOTS "\"" # else # define QUOT ' ' # define QUOTS "" # endif int usage(__G__ error) /* return PK-type error code */ __GDEF int error; { int flag = (error? 1 : 0); /*--------------------------------------------------------------------------- Print either ZipInfo usage or UnZip usage, depending on incantation. (Strings must be no longer than 512 bytes for Turbo C, apparently.) ---------------------------------------------------------------------------*/ if (uO.zipinfo_mode) { #ifndef NO_ZIPINFO Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine1), ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, LoadFarStringSmall(VersionDate), LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS)); Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine2))); Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine3), LoadFarStringSmall(ZipInfoUsageLine4))); #ifdef VMS Info(slide, flag, ((char *)slide, "\n\ You must quote non-lowercase options and filespecs, unless SET PROC/PARSE=EXT.\ \n")); #endif #endif /* !NO_ZIPINFO */ } else { /* UnZip mode */ Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine1), UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, LoadFarStringSmall(VersionDate))); #ifdef BETA Info(slide, flag, ((char *)slide, LoadFarString(BetaVersion), "", "")); #endif Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine2), ZIPINFO_MODE_OPTION, LoadFarStringSmall(ZipInfoMode))); #ifdef VMS if (!error) /* maybe no command-line tail found; show extra help */ Info(slide, flag, ((char *)slide, LoadFarString(VMSusageLine2b))); #endif Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine3), LoadFarStringSmall(local1))); Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine4), LoadFarStringSmall(local2), LoadFarStringSmall2(local3))); /* This is extra work for SMALL_MEM, but it will work since * LoadFarStringSmall2 uses the same buffer. Remember, this * is a hack. */ Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine5), LoadFarStringSmall(Example2), LoadFarStringSmall2(Example3), LoadFarStringSmall2(Example3))); } /* end if (uO.zipinfo_mode) */ if (error) return PK_PARAM; else return PK_COOL; /* just wanted usage screen: no error */ } /* end function usage() */ #endif /* ?SFX */ #ifndef SFX /* Print extended help to stdout. */ static void help_extended(__G) __GDEF { extent i; /* counter for help array */ /* help array */ static ZCONST char *text[] = { "", "Extended Help for UnZip", "", "See the UnZip Manual for more detailed help", "", "", "UnZip lists and extracts files in zip archives. The default action is to", "extract zipfile entries to the current directory, creating directories as", "needed. With appropriate options, UnZip lists the contents of archives", "instead.", "", "Basic unzip command line:", " unzip [-Z] options archive[.zip] [file ...] [-x xfile ...] [-d exdir]", "", "Some examples:", " unzip -l foo.zip - list files in short format in archive foo.zip", "", " unzip -t foo - test the files in archive foo", "", " unzip -Z foo - list files using more detailed zipinfo format", "", " unzip foo - unzip the contents of foo in current dir", "", " unzip -a foo - unzip foo and convert text files to local OS", "", "If unzip is run in zipinfo mode, a more detailed list of archive contents", "is provided. The -Z option sets zipinfo mode and changes the available", "options.", "", "Basic zipinfo command line:", " zipinfo options archive[.zip] [file ...] [-x xfile ...]", " unzip -Z options archive[.zip] [file ...] [-x xfile ...]", "", "Below, Mac OS refers to Mac OS before Mac OS X. Mac OS X is a Unix based", "port and is referred to as Unix Apple.", "", "", "unzip options:", " -Z Switch to zipinfo mode. Must be first option.", " -hh Display extended help.", " -A [OS/2, Unix DLL] Print extended help for DLL.", " -c Extract files to stdout/screen. As -p but include names. Also,", " -a allowed and EBCDIC conversions done if needed.", " -f Freshen by extracting only if older file on disk.", " -l List files using short form.", " -p Extract files to pipe (stdout). Only file data is output and all", " files extracted in binary mode (as stored).", " -t Test archive files.", " -T Set timestamp on archive(s) to that of newest file. Similar to", " zip -o but faster.", " -u Update existing older files on disk as -f and extract new files.", " -v Use verbose list format. If given alone as unzip -v show version", " information. Also can be added to other list commands for more", " verbose output.", " -z Display only archive comment.", "", "unzip modifiers:", " -a Convert text files to local OS format. Convert line ends, EOF", " marker, and from or to EBCDIC character set as needed.", " -b Treat all files as binary. [Tandem] Force filecode 180 ('C').", " [VMS] Autoconvert binary files. -bb forces convert of all files.", " -B [UNIXBACKUP compile option enabled] Save a backup copy of each", " overwritten file in foo~ or foo~99999 format.", " -C Use case-insensitive matching.", " -D Skip restoration of timestamps for extracted directories. On VMS this", " is on by default and -D essentially becames -DD.", " -DD Skip restoration of timestamps for all entries.", " -E [MacOS (not Unix Apple)] Display contents of MacOS extra field during", " restore.", " -F [Acorn] Suppress removal of NFS filetype extension. [Non-Acorn if", " ACORN_FTYPE_NFS] Translate filetype and append to name.", " -i [MacOS] Ignore filenames in MacOS extra field. Instead, use name in", " standard header.", " -j Junk paths and deposit all files in extraction directory.", " -J [BeOS] Junk file attributes. [MacOS] Ignore MacOS specific info.", " -K [AtheOS, BeOS, Unix] Restore SUID/SGID/Tacky file attributes.", " -L Convert to lowercase any names from uppercase only file system.", " -LL Convert all files to lowercase.", " -M Pipe all output through internal pager similar to Unix more(1).", " -n Never overwrite existing files. Skip extracting that file, no prompt.", " -N [Amiga] Extract file comments as Amiga filenotes.", " -o Overwrite existing files without prompting. Useful with -f. Use with", " care.", " -P p Use password p to decrypt files. THIS IS INSECURE! Some OS show", " command line to other users.", " -q Perform operations quietly. The more q (as in -qq) the quieter.", " -s [OS/2, NT, MS-DOS] Convert spaces in filenames to underscores.", " -S [VMS] Convert text files (-a, -aa) into Stream_LF format.", " -U [UNICODE enabled] Show non-local characters as #Uxxxx or #Lxxxxxx ASCII", " text escapes where x is hex digit. [Old] -U used to leave names", " uppercase if created on MS-DOS, VMS, etc. See -L.", " -UU [UNICODE enabled] Disable use of stored UTF-8 paths. Note that UTF-8", " paths stored as native local paths are still processed as Unicode.", " -V Retain VMS file version numbers.", " -W [Only if WILD_STOP_AT_DIR] Modify pattern matching so ? and * do not", " match directory separator /, but ** does. Allows matching at specific", " directory levels.", " -X [VMS, Unix, OS/2, NT, Tandem] Restore UICs and ACL entries under VMS,", " or UIDs/GIDs under Unix, or ACLs under certain network-enabled", " versions of OS/2, or security ACLs under Windows NT. Can require", " user privileges.", " -XX [NT] Extract NT security ACLs after trying to enable additional", " system privileges.", " -Y [VMS] Treat archived name endings of .nnn as VMS version numbers.", " -$ [MS-DOS, OS/2, NT] Restore volume label if extraction medium is", " removable. -$$ allows fixed media (hard drives) to be labeled.", " -/ e [Acorn] Use e as extension list.", " -: [All but Acorn, VM/CMS, MVS, Tandem] Allow extract archive members into", " locations outside of current extraction root folder. This allows", " paths such as ../foo to be extracted above the current extraction", " directory, which can be a security problem.", " -^ [Unix] Allow control characters in names of extracted entries. Usually", " this is not a good thing and should be avoided.", " -2 [VMS] Force unconditional conversion of names to ODS-compatible names.", " Default is to exploit destination file system, preserving cases and", " extended name characters on ODS5 and applying ODS2 filtering on ODS2.", "", "", "Wildcards:", " Internally unzip supports the following wildcards:", " ? (or %% or #, depending on OS) matches any single character", " * matches any number of characters, including zero", " [list] matches char in list (regex), can do range [ac-f], all but [!bf]", " If port supports [], must escape [ as [[]", " For shells that expand wildcards, escape (\\* or \"*\") so unzip can recurse.", "", "Include and Exclude:", " -i pattern pattern ... include files that match a pattern", " -x pattern pattern ... exclude files that match a pattern", " Patterns are paths with optional wildcards and match paths as stored in", " archive. Exclude and include lists end at next option or end of line.", " unzip archive -x pattern pattern ...", "", "Multi-part (split) archives (archives created as a set of split files):", " Currently split archives are not readable by unzip. A workaround is", " to use zip to convert the split archive to a single-file archive and", " use unzip on that. See the manual page for Zip 3.0 or later.", "", "Streaming (piping into unzip):", " Currently unzip does not support streaming. The funzip utility can be", " used to process the first entry in a stream.", " cat archive | funzip", "", "Testing archives:", " -t test contents of archive", " This can be modified using -q for quieter operation, and -qq for even", " quieter operation.", "", "Unicode:", " If compiled with Unicode support, unzip automatically handles archives", " with Unicode entries. Currently Unicode on Win32 systems is limited.", " Characters not in the current character set are shown as ASCII escapes", " in the form #Uxxxx where the Unicode character number fits in 16 bits,", " or #Lxxxxxx where it doesn't, where x is the ASCII character for a hex", " digit.", "", "", "zipinfo options (these are used in zipinfo mode (unzip -Z ...)):", " -1 List names only, one per line. No headers/trailers. Good for scripts.", " -2 List names only as -1, but include headers, trailers, and comments.", " -s List archive entries in short Unix ls -l format. Default list format.", " -m List in long Unix ls -l format. As -s, but includes compression %.", " -l List in long Unix ls -l format. As -m, but compression in bytes.", " -v List zipfile information in verbose, multi-page format.", " -h List header line. Includes archive name, actual size, total files.", " -M Pipe all output through internal pager similar to Unix more(1) command.", " -t List totals for files listed or for all files. Includes uncompressed", " and compressed sizes, and compression factors.", " -T Print file dates and times in a sortable decimal format (yymmdd.hhmmss)", " Default date and time format is a more human-readable version.", " -U [UNICODE] If entry has a UTF-8 Unicode path, display any characters", " not in current character set as text #Uxxxx and #Lxxxxxx escapes", " representing the Unicode character number of the character in hex.", " -UU [UNICODE] Disable use of any UTF-8 path information.", " -z Include archive comment if any in listing.", "", "", "funzip stream extractor:", " funzip extracts the first member in an archive to stdout. Typically", " used to unzip the first member of a stream or pipe. If a file argument", " is given, read from that file instead of stdin.", "", "funzip command line:", " funzip [-password] [input[.zip|.gz]]", "", "", "unzipsfx self extractor:", " Self-extracting archives made with unzipsfx are no more (or less)", " portable across different operating systems than unzip executables.", " In general, a self-extracting archive made on a particular Unix system,", " for example, will only self-extract under the same flavor of Unix.", " Regular unzip may still be used to extract embedded archive however.", "", "unzipsfx command line:", " [-options] [file(s) ... [-x xfile(s) ...]]", "", "unzipsfx options:", " -c, -p - Output to pipe. (See above for unzip.)", " -f, -u - Freshen and Update, as for unzip.", " -t - Test embedded archive. (Can be used to list contents.)", " -z - Print archive comment. (See unzip above.)", "", "unzipsfx modifiers:", " Most unzip modifiers are supported. These include", " -a - Convert text files.", " -n - Never overwrite.", " -o - Overwrite without prompting.", " -q - Quiet operation.", " -C - Match names case-insensitively.", " -j - Junk paths.", " -V - Keep version numbers.", " -s - Convert spaces to underscores.", " -$ - Restore volume label.", "", "If unzipsfx compiled with SFX_EXDIR defined, -d option also available:", " -d exd - Extract to directory exd.", "By default, all files extracted to current directory. This option", "forces extraction to specified directory.", "", "See unzipsfx manual page for more information.", "" }; for (i = 0; i < sizeof(text)/sizeof(char *); i++) { Info(slide, 0, ((char *)slide, "%s\n", text[i])); } } /* end function help_extended() */ #ifndef _WIN32_WCE /* Win CE does not support environment variables */ #if (!defined(MODERN) || defined(NO_STDLIB_H)) /* Declare getenv() to be sure (might be missing in some environments) */ extern char *getenv(); #endif #endif /********************************/ /* Function show_version_info() */ /********************************/ static void show_version_info(__G) __GDEF { if (uO.qflag > 3) /* "unzip -vqqqq" */ Info(slide, 0, ((char *)slide, "%d\n", (UZ_MAJORVER*100 + UZ_MINORVER*10 + UZ_PATCHLEVEL))); else { #ifndef _WIN32_WCE /* Win CE does not support environment variables */ char *envptr; #endif int numopts = 0; Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine1v), UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, LoadFarStringSmall(VersionDate))); Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine2v))); version(__G); Info(slide, 0, ((char *)slide, LoadFarString(CompileOptions))); #ifdef ACORN_FTYPE_NFS Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(AcornFtypeNFS))); ++numopts; #endif #ifdef ASM_CRC Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(AsmCRC))); ++numopts; #endif #ifdef ASM_INFLATECODES Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(AsmInflateCodes))); ++numopts; #endif #ifdef CHECK_VERSIONS Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Check_Versions))); ++numopts; #endif #ifdef COPYRIGHT_CLEAN Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Copyright_Clean))); ++numopts; #endif #ifdef DEBUG Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(UDebug))); ++numopts; #endif #ifdef DEBUG_TIME Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(DebugTime))); ++numopts; #endif #ifdef DLL Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Dll))); ++numopts; #endif #ifdef DOSWILD Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(DosWild))); ++numopts; #endif #ifdef LZW_CLEAN Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(LZW_Clean))); ++numopts; #endif #ifndef MORE Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(No_More))); ++numopts; #endif #ifdef NO_ZIPINFO Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(No_ZipInfo))); ++numopts; #endif #ifdef NTSD_EAS Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(NTSDExtAttrib))); ++numopts; #endif #if defined(WIN32) && defined(NO_W32TIMES_IZFIX) Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(W32NoIZTimeFix))); ++numopts; #endif #ifdef OLD_THEOS_EXTRA Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(OldTheosExtra))); ++numopts; #endif #ifdef OS2_EAS Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(OS2ExtAttrib))); ++numopts; #endif #ifdef QLZIP Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(SMSExFldOnUnix))); ++numopts; #endif #ifdef REENTRANT Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Reentrant))); ++numopts; #endif #ifdef REGARGS Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(RegArgs))); ++numopts; #endif #ifdef RETURN_CODES Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Return_Codes))); ++numopts; #endif #ifdef SET_DIR_ATTRIB Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(SetDirAttrib))); ++numopts; #endif #ifdef SYMLINKS Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(SymLinkSupport))); ++numopts; #endif #ifdef TIMESTAMP Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(TimeStamp))); ++numopts; #endif #ifdef UNIXBACKUP Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(UnixBackup))); ++numopts; #endif #ifdef USE_EF_UT_TIME Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_EF_UT_time))); ++numopts; #endif #ifndef COPYRIGHT_CLEAN Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_Smith_Code))); ++numopts; #endif #ifndef LZW_CLEAN Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_Unshrink))); ++numopts; #endif #ifdef USE_DEFLATE64 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_Deflate64))); ++numopts; #endif #ifdef UNICODE_SUPPORT # ifdef UTF8_MAYBE_NATIVE sprintf((char *)(slide+256), LoadFarStringSmall(Use_Unicode), LoadFarStringSmall2(G.native_is_utf8 ? SysChUTF8 : SysChOther)); Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), (char *)(slide+256))); # else Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_Unicode))); # endif ++numopts; #endif #ifdef _MBCS sprintf((char *)(slide+256), LoadFarStringSmall(Have_MBCS_Support), (unsigned int)MB_CUR_MAX); Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), (char *)(slide+256))); ++numopts; #endif #ifdef MULT_VOLUME Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_MultiVol))); ++numopts; #endif #ifdef LARGE_FILE_SUPPORT Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_LFS))); ++numopts; #endif #ifdef ZIP64_SUPPORT Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_Zip64))); ++numopts; #endif #if (defined(__DJGPP__) && (__DJGPP__ >= 2)) # ifdef USE_DJGPP_ENV Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_DJGPP_Env))); ++numopts; # endif # ifdef USE_DJGPP_GLOB Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_DJGPP_Glob))); ++numopts; # endif #endif /* __DJGPP__ && (__DJGPP__ >= 2) */ #ifdef USE_VFAT Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(Use_VFAT_support))); ++numopts; #endif #ifdef USE_ZLIB sprintf((char *)(slide+256), LoadFarStringSmall(UseZlib), ZLIB_VERSION, zlibVersion()); Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), (char *)(slide+256))); ++numopts; #endif #ifdef USE_BZIP2 sprintf((char *)(slide+256), LoadFarStringSmall(UseBZip2), BZ2_bzlibVersion()); Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), (char *)(slide+256))); ++numopts; #endif #ifdef VMS_TEXT_CONV Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(VmsTextConv))); ++numopts; #endif #ifdef VMSCLI Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(VmsCLI))); ++numopts; #endif #ifdef VMSWILD Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(VmsWild))); ++numopts; #endif #ifdef WILD_STOP_AT_DIR Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(WildStopAtDir))); ++numopts; #endif #if CRYPT # ifdef PASSWD_FROM_STDIN Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(PasswdStdin))); # endif Info(slide, 0, ((char *)slide, LoadFarString(Decryption), CR_MAJORVER, CR_MINORVER, CR_BETA_VER, LoadFarStringSmall(CryptDate))); ++numopts; #endif /* CRYPT */ if (numopts == 0) Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), LoadFarStringSmall(None))); #ifndef _WIN32_WCE /* Win CE does not support environment variables */ Info(slide, 0, ((char *)slide, LoadFarString(EnvOptions))); envptr = getenv(LoadFarStringSmall(EnvUnZip)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvUnZip), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); envptr = getenv(LoadFarStringSmall(EnvUnZip2)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvUnZip2), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); envptr = getenv(LoadFarStringSmall(EnvZipInfo)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvZipInfo), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); envptr = getenv(LoadFarStringSmall(EnvZipInfo2)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvZipInfo2), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); #ifndef __RSXNT__ #ifdef __EMX__ envptr = getenv(LoadFarStringSmall(EnvEMX)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvEMX), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); envptr = getenv(LoadFarStringSmall(EnvEMXOPT)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvEMXOPT), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); #endif /* __EMX__ */ #if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2))) envptr = getenv(LoadFarStringSmall(EnvGO32)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvGO32), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); envptr = getenv(LoadFarStringSmall(EnvGO32TMP)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvGO32TMP), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); #endif /* __GO32__ && !(__DJGPP__ >= 2) */ #endif /* !__RSXNT__ */ #ifdef RISCOS envptr = getenv(LoadFarStringSmall(EnvUnZipExts)); Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvUnZipExts), (envptr == (char *)NULL || *envptr == 0)? LoadFarStringSmall2(None) : envptr)); #endif /* RISCOS */ #endif /* !_WIN32_WCE */ } } /* end function show_version() */ #endif /* !SFX */ #endif /* !WINDLL */ Carla-2.1/data/windows/unzipfx-carla/unzip.h000066400000000000000000000630401364475620200211160ustar00rootroot00000000000000/*--------------------------------------------------------------------------- unzip.h (new) Copyright (c) 1990-2009 Info-ZIP. All rights reserved. This header file contains the public macros and typedefs required by both the UnZip sources and by any application using the UnZip API. If UNZIP_INTERNAL is defined, it includes unzpriv.h (containing includes, prototypes and extern variables used by the actual UnZip sources). ---------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- This is version 2009-Jan-02 of the Info-ZIP license. The definitive version of this document should be available at ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and a copy at http://www.info-zip.org/pub/infozip/license.html. Copyright (c) 1990-2009 Info-ZIP. All rights reserved. For the purposes of this copyright and license, "Info-ZIP" is defined as the following set of individuals: Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois, Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth, Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko, Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs, Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda, Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren, Rich Wales, Mike White. This software is provided "as is," without warranty of any kind, express or implied. In no event shall Info-ZIP or its contributors be held liable for any direct, indirect, incidental, special or consequential damages arising out of the use of or inability to use this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the above disclaimer and the following restrictions: 1. Redistributions of source code (in whole or in part) must retain the above copyright notice, definition, disclaimer, and this list of conditions. 2. Redistributions in binary form (compiled executables and libraries) must reproduce the above copyright notice, definition, disclaimer, and this list of conditions in documentation and/or other materials provided with the distribution. Additional documentation is not needed for executables where a command line license option provides these and a note regarding this option is in the executable's startup banner. The sole exception to this condition is redistribution of a standard UnZipSFX binary (including SFXWiz) as part of a self-extracting archive; that is permitted without inclusion of this license, as long as the normal SFX banner has not been removed from the binary or disabled. 3. Altered versions--including, but not limited to, ports to new operating systems, existing ports with new graphical interfaces, versions with modified or added functionality, and dynamic, shared, or static library versions not from Info-ZIP--must be plainly marked as such and must not be misrepresented as being the original source or, if binaries, compiled from the original source. Such altered versions also must not be misrepresented as being Info-ZIP releases--including, but not limited to, labeling of the altered versions with the names "Info-ZIP" (or any variation thereof, including, but not limited to, different capitalizations), "Pocket UnZip," "WiZ" or "MacZip" without the explicit permission of Info-ZIP. Such altered versions are further prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP will provide support for the altered versions. 4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip," "UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its own source and binary releases. ---------------------------------------------------------------------------*/ #ifndef __unzip_h /* prevent multiple inclusions */ #define __unzip_h /*--------------------------------------------------------------------------- Predefined, machine-specific macros. ---------------------------------------------------------------------------*/ #ifdef __GO32__ /* MS-DOS extender: NOT Unix */ # ifdef unix # undef unix # endif # ifdef _unix # undef _unix # endif # ifdef __unix # undef __unix # endif # ifdef __unix__ # undef __unix__ # endif #endif #if ((defined(__convex__) || defined(__convexc__)) && !defined(CONVEX)) # define CONVEX #endif #if (defined(unix) || defined(_unix) || defined(__unix) || defined(__unix__)) # ifndef UNIX # define UNIX # endif #endif /* unix || _unix || __unix || __unix__ */ #if (defined(M_XENIX) || defined(COHERENT) || defined(__hpux)) # ifndef UNIX # define UNIX # endif #endif /* M_XENIX || COHERENT || __hpux */ #if (defined(__NetBSD__) || defined(__FreeBSD__)) # ifndef UNIX # define UNIX # endif #endif /* __NetBSD__ || __FreeBSD__ */ #if (defined(CONVEX) || defined(MINIX) || defined(_AIX) || defined(__QNX__)) # ifndef UNIX # define UNIX # endif #endif /* CONVEX || MINIX || _AIX || __QNX__ */ #if (defined(VM_CMS) || defined(MVS)) # define CMS_MVS #endif #if (defined(__OS2__) && !defined(OS2)) # define OS2 #endif #if (defined(__TANDEM) && !defined(TANDEM)) # define TANDEM #endif #if (defined(__VMS) && !defined(VMS)) # define VMS #endif #if ((defined(__WIN32__) || defined(_WIN32)) && !defined(WIN32)) # define WIN32 #endif #if ((defined(__WINNT__) || defined(__WINNT)) && !defined(WIN32)) # define WIN32 #endif #if defined(_WIN32_WCE) # ifndef WIN32 /* WinCE is treated as a variant of the Win32 API */ # define WIN32 # endif # ifndef UNICODE /* WinCE requires UNICODE wide character support */ # define UNICODE # endif #endif #ifdef __COMPILER_KCC__ # include # ifdef SYS_T20 # define TOPS20 # endif #endif /* __COMPILER_KCC__ */ /* Borland C does not define __TURBOC__ if compiling for a 32-bit platform */ #ifdef __BORLANDC__ # ifndef __TURBOC__ # define __TURBOC__ # endif # if (!defined(__MSDOS__) && !defined(OS2) && !defined(WIN32)) # define __MSDOS__ # endif #endif /* define MSDOS for Turbo C (unless OS/2) and Power C as well as Microsoft C */ #ifdef __POWERC # define __TURBOC__ # define MSDOS #endif /* __POWERC */ #if (defined(__MSDOS__) && !defined(MSDOS)) /* just to make sure */ # define MSDOS #endif /* RSXNTDJ (at least up to v1.3) compiles for WIN32 (RSXNT) using a derivate of the EMX environment, but defines MSDOS and __GO32__. ARG !!! */ #if (defined(MSDOS) && defined(WIN32)) # undef MSDOS /* WIN32 is >>>not<<< MSDOS */ #endif #if (defined(__GO32__) && defined(__EMX__) && defined(__RSXNT__)) # undef __GO32__ #endif #if (defined(linux) && !defined(LINUX)) # define LINUX #endif #ifdef __riscos # define RISCOS #endif #if (defined(THINK_C) || defined(MPW)) # define MACOS #endif #if (defined(__MWERKS__) && defined(macintosh)) # define MACOS #endif /* use prototypes and ANSI libraries if __STDC__, or MS-DOS, or OS/2, or Win32, * or IBM C Set/2, or Borland C, or Watcom C, or GNU gcc (emx or Cygwin), * or Macintosh, or Sequent, or Atari, or IBM RS/6000, or Silicon Graphics, * or Convex?, or AtheOS, or BeOS. */ #if (defined(__STDC__) || defined(MSDOS) || defined(OS2) || defined(WIN32)) # ifndef PROTO # define PROTO # endif # ifndef MODERN # define MODERN # endif #endif #if (defined(__IBMC__) || defined(__BORLANDC__) || defined(__WATCOMC__)) # ifndef PROTO # define PROTO # endif # ifndef MODERN # define MODERN # endif #endif #if (defined(__EMX__) || defined(__CYGWIN__)) # ifndef PROTO # define PROTO # endif # ifndef MODERN # define MODERN # endif #endif #if (defined(MACOS) || defined(ATARI_ST) || defined(RISCOS) || defined(THEOS)) # ifndef PROTO # define PROTO # endif # ifndef MODERN # define MODERN # endif #endif /* Sequent running Dynix/ptx: non-modern compiler */ #if (defined(_AIX) || defined(sgi) || (defined(_SEQUENT_) && !defined(PTX))) # ifndef PROTO # define PROTO # endif # ifndef MODERN # define MODERN # endif #endif #if (defined(CMS_MVS) || defined(__ATHEOS__) || defined(__BEOS__)) /* || defined(CONVEX) ? */ # ifndef PROTO # define PROTO # endif # ifndef MODERN # define MODERN # endif #endif /* Bundled C compiler on HP-UX needs this. Others shouldn't care. */ #if (defined(__hpux)) # ifndef MODERN # define MODERN # endif #endif /* turn off prototypes if requested */ #if (defined(NOPROTO) && defined(PROTO)) # undef PROTO #endif /* used to remove arguments in function prototypes for non-ANSI C */ #ifdef PROTO # define OF(a) a #else # define OF(a) () #endif /* enable the "const" keyword only if MODERN and if not otherwise instructed */ #ifdef MODERN # if (!defined(ZCONST) && (defined(USE_CONST) || !defined(NO_CONST))) # define ZCONST const # endif #endif #ifndef ZCONST # define ZCONST #endif /* Tell Microsoft Visual C++ 2005 (and newer) to leave us alone * and let us use standard C functions the way we're supposed to. * (These preprocessor symbols must appear before the first system * header include. They are located here, because for WINDLL the * first system header includes follow just below.) */ #if defined(_MSC_VER) && (_MSC_VER >= 1400) # ifndef _CRT_SECURE_NO_WARNINGS # define _CRT_SECURE_NO_WARNINGS # endif # ifndef _CRT_NONSTDC_NO_WARNINGS # define _CRT_NONSTDC_NO_WARNINGS # endif # if defined(POCKET_UNZIP) && !defined(_CRT_NON_CONFORMING_SWPRINTFS) # define _CRT_NON_CONFORMING_SWPRINTFS # endif #endif /* NO_UNIXBACKUP overrides UNIXBACKUP */ #if defined(NO_UNIXBACKUP) && defined(UNIXBACKUP) # undef UNIXBACKUP #endif /*--------------------------------------------------------------------------- Grab system-specific public include headers. ---------------------------------------------------------------------------*/ #ifdef POCKET_UNZIP /* WinCE port */ # include "wince/punzip.h" /* must appear before windows.h */ #endif #ifdef WINDLL /* for UnZip, the "basic" part of the win32 api is sufficient */ # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # define IZ_HASDEFINED_WIN32LEAN # endif # include # include "windll/structs.h" # ifdef IZ_HASDEFINED_WIN32LEAN # undef WIN32_LEAN_AND_MEAN # undef IZ_HASDEFINED_WIN32LEAN # endif #endif /*--------------------------------------------------------------------------- Grab system-dependent definition of EXPENTRY for prototypes below. ---------------------------------------------------------------------------*/ #if 0 #if (defined(OS2) && !defined(FUNZIP)) # ifdef UNZIP_INTERNAL # define INCL_NOPM # define INCL_DOSNLS # define INCL_DOSPROCESS # define INCL_DOSDEVICES # define INCL_DOSDEVIOCTL # define INCL_DOSERRORS # define INCL_DOSMISC # ifdef OS2DLL # define INCL_REXXSAA # include # endif # endif /* UNZIP_INTERNAL */ # include # define UZ_EXP EXPENTRY #endif /* OS2 && !FUNZIP */ #endif /* 0 */ #if (defined(OS2) && !defined(FUNZIP)) # if (defined(__IBMC__) || defined(__WATCOMC__)) # define UZ_EXP _System /* compiler keyword */ # else # define UZ_EXP # endif #endif /* OS2 && !FUNZIP */ #if (defined(WINDLL) || defined(USE_UNZIP_LIB)) # ifndef EXPENTRY # define UZ_EXP WINAPI # else # define UZ_EXP EXPENTRY # endif #endif #ifndef UZ_EXP # define UZ_EXP #endif #ifdef __cplusplus extern "C" { #endif /*--------------------------------------------------------------------------- Public typedefs. ---------------------------------------------------------------------------*/ #ifndef _IZ_TYPES_DEFINED #ifdef MODERN typedef void zvoid; #else /* !MODERN */ # ifndef AOS_VS /* mostly modern? */ # ifndef VAXC /* not fully modern, but has knows 'void' */ # define void int # endif /* !VAXC */ # endif /* !AOS_VS */ typedef char zvoid; #endif /* ?MODERN */ typedef unsigned char uch; /* code assumes unsigned bytes; these type- */ typedef unsigned short ush; /* defs replace byte/UWORD/ULONG (which are */ typedef unsigned long ulg; /* predefined on some systems) & match zip */ #define _IZ_TYPES_DEFINED #endif /* !_IZ_TYPES_DEFINED */ /* InputFn is not yet used and is likely to change: */ #ifdef PROTO typedef int (UZ_EXP MsgFn) (zvoid *pG, uch *buf, ulg size, int flag); typedef int (UZ_EXP InputFn) (zvoid *pG, uch *buf, int *size, int flag); typedef void (UZ_EXP PauseFn) (zvoid *pG, ZCONST char *prompt, int flag); typedef int (UZ_EXP PasswdFn) (zvoid *pG, int *rcnt, char *pwbuf, int size, ZCONST char *zfn, ZCONST char *efn); typedef int (UZ_EXP StatCBFn) (zvoid *pG, int fnflag, ZCONST char *zfn, ZCONST char *efn, ZCONST zvoid *details); typedef void (UZ_EXP UsrIniFn) (void); #else /* !PROTO */ typedef int (UZ_EXP MsgFn) (); typedef int (UZ_EXP InputFn) (); typedef void (UZ_EXP PauseFn) (); typedef int (UZ_EXP PasswdFn) (); typedef int (UZ_EXP StatCBFn) (); typedef void (UZ_EXP UsrIniFn) (); #endif /* ?PROTO */ typedef struct _UzpBuffer { /* rxstr */ ulg strlength; /* length of string */ char *strptr; /* pointer to string */ } UzpBuffer; typedef struct _UzpInit { ulg structlen; /* length of the struct being passed */ /* GRR: can we assume that each of these is a 32-bit pointer? if not, * does it matter? add "far" keyword to make sure? */ MsgFn *msgfn; InputFn *inputfn; PauseFn *pausefn; UsrIniFn *userfn; /* user init function to be called after */ /* globals constructed and initialized */ /* pointer to program's environment area or something? */ /* hooks for performance testing? */ /* hooks for extra unzip -v output? (detect CPU or other hardware?) */ /* anything else? let me (Greg) know... */ } UzpInit; typedef struct _UzpCB { ulg structlen; /* length of the struct being passed */ /* GRR: can we assume that each of these is a 32-bit pointer? if not, * does it matter? add "far" keyword to make sure? */ MsgFn *msgfn; InputFn *inputfn; PauseFn *pausefn; PasswdFn *passwdfn; StatCBFn *statrepfn; } UzpCB; /* the collection of general UnZip option flags and option arguments */ typedef struct _UzpOpts { #ifndef FUNZIP char *exdir; /* pointer to extraction root directory (-d option) */ char *pwdarg; /* pointer to command-line password (-P option) */ int zipinfo_mode; /* behave like ZipInfo or like normal UnZip? */ int aflag; /* -a: do ASCII-EBCDIC and/or end-of-line translation */ #ifdef VMS int bflag; /* -b: force fixed record format for binary files */ #endif #ifdef TANDEM int bflag; /* -b: create text files in 'C' format (180)*/ #endif #if defined(UNIX) || defined(OS2) || defined(WIN32) int B_flag; /* -B: back up existing files by renaming to *~##### */ #else #ifdef UNIXBACKUP int B_flag; /* -B: back up existing files by renaming to *~##### */ #endif #endif int cflag; /* -c: output to stdout */ int C_flag; /* -C: match filenames case-insensitively */ int D_flag; /* -D: don't restore directory (-DD: any) timestamps */ #ifdef MACOS int E_flag; /* -E: [MacOS] show Mac extra field during restoring */ #endif int fflag; /* -f: "freshen" (extract only newer files) */ #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS)) int acorn_nfs_ext; /* -F: RISC OS types & NFS filetype extensions */ #endif int hflag; /* -h: header line (zipinfo) */ #ifdef MACOS int i_flag; /* -i: [MacOS] ignore filenames stored in Mac e.f. */ #endif #ifdef RISCOS int scanimage; /* -I: scan image files */ #endif int jflag; /* -j: junk pathnames (unzip) */ #if (defined(__ATHEOS__) || defined(__BEOS__) || defined(MACOS)) int J_flag; /* -J: ignore AtheOS/BeOS/MacOS e. f. info (unzip) */ #endif #if (defined(__ATHEOS__) || defined(__BEOS__) || defined(UNIX)) int K_flag; /* -K: keep setuid/setgid/tacky permissions */ #endif int lflag; /* -12slmv: listing format (zipinfo) */ int L_flag; /* -L: convert filenames from some OSes to lowercase */ int overwrite_none; /* -n: never overwrite files (no prompting) */ #ifdef AMIGA int N_flag; /* -N: restore comments as AmigaDOS filenotes */ #endif int overwrite_all; /* -o: OK to overwrite files without prompting */ #endif /* !FUNZIP */ int qflag; /* -q: produce a lot less output */ #ifdef TANDEM int rflag; /* -r: remove file extensions */ #endif #ifndef FUNZIP #if (defined(MSDOS) || defined(FLEXOS) || defined(OS2) || defined(WIN32)) int sflag; /* -s: convert spaces in filenames to underscores */ #endif #if (defined(NLM)) int sflag; /* -s: convert spaces in filenames to underscores */ #endif #ifdef VMS int S_flag; /* -S: use Stream_LF for text files (-a[a]) */ #endif #if (defined(MSDOS) || defined(__human68k__) || defined(OS2) || defined(WIN32)) int volflag; /* -$: extract volume labels */ #endif int tflag; /* -t: test (unzip) or totals line (zipinfo) */ int T_flag; /* -T: timestamps (unzip) or dec. time fmt (zipinfo) */ int uflag; /* -u: "update" (extract only newer/brand-new files) */ #if defined(UNIX) || defined(VMS) || defined(WIN32) int U_flag; /* -U: escape non-ASCII, -UU No Unicode paths */ #endif int vflag; /* -v: (verbosely) list directory */ int V_flag; /* -V: don't strip VMS version numbers */ int W_flag; /* -W: wildcard '*' won't match '/' dir separator */ #if (defined (__ATHEOS__) || defined(__BEOS__) || defined(UNIX)) int X_flag; /* -X: restore owner/protection or UID/GID or ACLs */ #else #if (defined(TANDEM) || defined(THEOS)) int X_flag; /* -X: restore owner/protection or UID/GID or ACLs */ #else #if (defined(OS2) || defined(VMS) || defined(WIN32)) int X_flag; /* -X: restore owner/protection or UID/GID or ACLs */ #endif #endif #endif #ifdef VMS int Y_flag; /* -Y: treat ".nnn" as ";nnn" version */ #endif int zflag; /* -z: display the zipfile comment (only, for unzip) */ #ifdef VMS int ods2_flag; /* -2: force names to conform to ODS2 */ #endif #if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM)) int ddotflag; /* -:: don't skip over "../" path elements */ #endif #ifdef UNIX int cflxflag; /* -^: allow control chars in extracted filenames */ #endif #endif /* !FUNZIP */ } UzpOpts; /* intended to be a private struct: */ typedef struct _ver { uch major; /* e.g., integer 5 */ uch minor; /* e.g., 2 */ uch patchlevel; /* e.g., 0 */ uch not_used; } _version_type; typedef struct _UzpVer { ulg structlen; /* length of the struct being passed */ ulg flag; /* bit 0: is_beta bit 1: uses_zlib */ ZCONST char *betalevel; /* e.g. "g BETA" or "" */ ZCONST char *date; /* e.g. "9 Oct 08" (beta) or "9 October 2008" */ ZCONST char *zlib_version;/* e.g. "1.2.3" or NULL */ _version_type unzip; /* current UnZip version */ _version_type zipinfo; /* current ZipInfo version */ _version_type os2dll; /* OS2DLL version (retained for compatibility */ _version_type windll; /* WinDLL version (retained for compatibility */ _version_type dllapimin; /* last incompatible change of library API */ } UzpVer; /* for Visual BASIC access to Windows DLLs: */ typedef struct _UzpVer2 { ulg structlen; /* length of the struct being passed */ ulg flag; /* bit 0: is_beta bit 1: uses_zlib */ char betalevel[10]; /* e.g. "g BETA" or "" */ char date[20]; /* e.g. "9 Oct 08" (beta) or "9 October 2008" */ char zlib_version[10]; /* e.g. "1.2.3" or NULL */ _version_type unzip; /* current UnZip version */ _version_type zipinfo; /* current ZipInfo version */ _version_type os2dll; /* OS2DLL version (retained for compatibility */ _version_type windll; /* WinDLL version (retained for compatibility */ _version_type dllapimin; /* last incompatible change of library API */ } UzpVer2; typedef struct _Uzp_Siz64 { unsigned long lo32; unsigned long hi32; } Uzp_Siz64; typedef struct _Uzp_cdir_Rec { uch version_made_by[2]; uch version_needed_to_extract[2]; ush general_purpose_bit_flag; ush compression_method; ulg last_mod_dos_datetime; ulg crc32; Uzp_Siz64 csize; Uzp_Siz64 ucsize; ush filename_length; ush extra_field_length; ush file_comment_length; ush disk_number_start; ush internal_file_attributes; ulg external_file_attributes; Uzp_Siz64 relative_offset_local_header; } Uzp_cdir_Rec; #define UZPINIT_LEN sizeof(UzpInit) #define UZPVER_LEN sizeof(UzpVer) #define cbList(func) int (* UZ_EXP func)(char *filename, Uzp_cdir_Rec *crec) /*--------------------------------------------------------------------------- Return (and exit) values of the public UnZip API functions. ---------------------------------------------------------------------------*/ /* external return codes */ #define PK_OK 0 /* no error */ #define PK_COOL 0 /* no error */ #define PK_WARN 1 /* warning error */ #define PK_ERR 2 /* error in zipfile */ #define PK_BADERR 3 /* severe error in zipfile */ #define PK_MEM 4 /* insufficient memory (during initialization) */ #define PK_MEM2 5 /* insufficient memory (password failure) */ #define PK_MEM3 6 /* insufficient memory (file decompression) */ #define PK_MEM4 7 /* insufficient memory (memory decompression) */ #define PK_MEM5 8 /* insufficient memory (not yet used) */ #define PK_NOZIP 9 /* zipfile not found */ #define PK_PARAM 10 /* bad or illegal parameters specified */ #define PK_FIND 11 /* no files found */ #define PK_DISK 50 /* disk full */ #define PK_EOF 51 /* unexpected EOF */ #define IZ_CTRLC 80 /* user hit ^C to terminate */ #define IZ_UNSUP 81 /* no files found: all unsup. compr/encrypt. */ #define IZ_BADPWD 82 /* no files found: all had bad password */ #define IZ_ERRBF 83 /* big-file archive, small-file program */ /* return codes of password fetches (negative = user abort; positive = error) */ #define IZ_PW_ENTERED 0 /* got some password string; use/try it */ #define IZ_PW_CANCEL -1 /* no password available (for this entry) */ #define IZ_PW_CANCELALL -2 /* no password, skip any further pwd. request */ #define IZ_PW_ERROR 5 /* = PK_MEM2 : failure (no mem, no tty, ...) */ /* flag values for status callback function */ #define UZ_ST_START_EXTRACT 1 /* no details */ #define UZ_ST_IN_PROGRESS 2 /* no details */ #define UZ_ST_FINISH_MEMBER 3 /* 'details': extracted size */ /* return values of status callback function */ #define UZ_ST_CONTINUE 0 #define UZ_ST_BREAK 1 /*--------------------------------------------------------------------------- Prototypes for public UnZip API (DLL) functions. ---------------------------------------------------------------------------*/ #define UzpMatch match int UZ_EXP UzpMain OF((int argc, char **argv)); int UZ_EXP UzpAltMain OF((int argc, char **argv, UzpInit *init)); ZCONST UzpVer * UZ_EXP UzpVersion OF((void)); void UZ_EXP UzpFreeMemBuffer OF((UzpBuffer *retstr)); #ifndef WINDLL int UZ_EXP UzpUnzipToMemory OF((char *zip, char *file, UzpOpts *optflgs, UzpCB *UsrFunc, UzpBuffer *retstr)); int UZ_EXP UzpGrep OF((char *archive, char *file, char *pattern, int cmd, int SkipBin, UzpCB *UsrFunc)); #endif #ifdef OS2 int UZ_EXP UzpFileTree OF((char *name, cbList(callBack), char *cpInclude[], char *cpExclude[])); #endif unsigned UZ_EXP UzpVersion2 OF((UzpVer2 *version)); int UZ_EXP UzpValidate OF((char *archive, int AllCodes)); /* default I/O functions (can be swapped out via UzpAltMain() entry point): */ int UZ_EXP UzpMessagePrnt OF((zvoid *pG, uch *buf, ulg size, int flag)); int UZ_EXP UzpMessageNull OF((zvoid *pG, uch *buf, ulg size, int flag)); int UZ_EXP UzpInput OF((zvoid *pG, uch *buf, int *size, int flag)); void UZ_EXP UzpMorePause OF((zvoid *pG, ZCONST char *prompt, int flag)); int UZ_EXP UzpPassword OF((zvoid *pG, int *rcnt, char *pwbuf, int size, ZCONST char *zfn, ZCONST char *efn)); #ifdef __cplusplus } #endif /*--------------------------------------------------------------------------- Remaining private stuff for UnZip compilation. ---------------------------------------------------------------------------*/ #ifdef UNZIP_INTERNAL # include "unzpriv.h" #endif #endif /* !__unzip_h */ Carla-2.1/data/windows/unzipfx-carla/unzipfx/000077500000000000000000000000001364475620200213005ustar00rootroot00000000000000Carla-2.1/data/windows/unzipfx-carla/unzipfx/appDetails.c000066400000000000000000000034251364475620200235360ustar00rootroot00000000000000 #include #include #include #ifdef WIN32 # include #endif #include "appDetails.h" #define CMD_BUF_LEN 1024 static int sfx_app_argc = 0; static char** sfx_app_argv = NULL; static char sfx_tmp_path[512] = { 0 }; void sfx_app_set_args(int argc, char** argv) { sfx_app_argc = argc; sfx_app_argv = argv; } int sfx_app_autorun_now() { int i, cmdBufLen = 0; char cmdBuf[CMD_BUF_LEN]; const char* const path = sfx_get_tmp_path(1); chdir(path); strcpy(cmdBuf, path); strcat(cmdBuf, SFX_AUTORUN_CMD); cmdBufLen = strlen(cmdBuf); for (i=0; i < sfx_app_argc; i++) { if (! sfx_app_argv[i]) continue; cmdBufLen += strlen(sfx_app_argv[i]) + 1; if (cmdBufLen >= CMD_BUF_LEN-1) break; strcat(cmdBuf, " "); strcat(cmdBuf, sfx_app_argv[i]); } puts(SFX_APP_BANNER); printf("Launching: '%s'\n", cmdBuf); #ifdef WIN32 ShellExecute(NULL, "open", cmdBuf, NULL, NULL, SW_SHOWNORMAL); return 0; #else char magicBuf[512]; strcpy(magicBuf, path); strcat(magicBuf, "magic.mgc"); setenv("CARLA_MAGIC_FILE", magicBuf, 1); const int ret = system(cmdBuf); exit(ret); return ret; #endif } char* sfx_get_tmp_path(int withAppName) { #ifdef WIN32 { GetTempPathA(512 - strlen(SFX_APP_MININAME_TITLE), sfx_tmp_path); if (withAppName == 1) strcat(sfx_tmp_path, SFX_APP_MININAME_TITLE "-2.1"); } #else { char* tmp = getenv("TMP"); if (tmp) strcpy(sfx_tmp_path, tmp); else strcpy(sfx_tmp_path, "/tmp"); if (withAppName == 1) strcat(sfx_tmp_path, "/" SFX_APP_MININAME_LCASE "-2.1"); } #endif return sfx_tmp_path; } Carla-2.1/data/windows/unzipfx-carla/unzipfx/appDetails.h000066400000000000000000000011501364475620200235340ustar00rootroot00000000000000 #ifndef __APP_DETAILS_H__ #define __APP_DETAILS_H__ #define REAL_BUILD #include "../../../../source/includes/CarlaDefines.h" #define SFX_APP_MININAME_TITLE "Carla" #define SFX_APP_MININAME_LCASE "carla" #define SFX_APP_BANNER SFX_APP_MININAME_TITLE " self-contained executable " CARLA_VERSION_STRING ", based on UnZipSFX." #ifdef WIN32 # define SFX_AUTORUN_CMD "\\" SFX_APP_MININAME_TITLE ".exe" #else # define SFX_AUTORUN_CMD "/" SFX_APP_MININAME_LCASE #endif void sfx_app_set_args(int argc, char** argv); int sfx_app_autorun_now(); char* sfx_get_tmp_path(int withAppName); #endif // __APP_DETAILS_H__ Carla-2.1/data/windows/unzipfx-carla/unzpriv.h000066400000000000000000003251651364475620200214770ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- unzpriv.h This header file contains private (internal) macros, typedefs, prototypes and global-variable declarations used by all of the UnZip source files. In a prior life it was part of the main unzip.h header, but now it is only included by that header if UNZIP_INTERNAL is defined. ---------------------------------------------------------------------------*/ #ifndef __unzpriv_h /* prevent multiple inclusions */ #define __unzpriv_h /* First thing: Signal all following code that we compile UnZip utilities! */ #ifndef UNZIP # define UNZIP #endif /* GRR 960204: MORE defined here in preparation for removal altogether */ #ifndef MORE # ifndef RISCOS # define MORE # endif #endif /* fUnZip should never need to be reentrant */ #ifdef FUNZIP # ifdef REENTRANT # undef REENTRANT # endif # ifdef DLL # undef DLL # endif # ifdef SFX /* fUnZip is NOT the sfx stub! */ # undef SFX # endif # ifdef USE_BZIP2 /* fUnZip does not support bzip2 decompression */ # undef USE_BZIP2 # endif #endif #if (defined(USE_ZLIB) && !defined(HAVE_ZL_INFLAT64) && !defined(NO_DEFLATE64)) /* zlib does not (yet?) provide Deflate64(tm) support */ # define NO_DEFLATE64 #endif #ifdef NO_DEFLATE64 /* disable support for Deflate64(tm) */ # ifdef USE_DEFLATE64 # undef USE_DEFLATE64 # endif #else /* enable Deflate64(tm) support unless compiling for SFX stub */ # if (!defined(USE_DEFLATE64) && !defined(SFX)) # define USE_DEFLATE64 # endif #endif /* disable bzip2 support for SFX stub, unless explicitly requested */ #if (defined(SFX) && !defined(BZIP2_SFX) && defined(USE_BZIP2)) # undef USE_BZIP2 #endif #if (defined(NO_VMS_TEXT_CONV) || defined(VMS)) # ifdef VMS_TEXT_CONV # undef VMS_TEXT_CONV # endif #else # if (!defined(VMS_TEXT_CONV) && !defined(SFX)) # define VMS_TEXT_CONV # endif #endif /* Enable -B option per default on specific systems, to allow backing up * files that would be overwritten. * (This list of systems must be kept in sync with the list of systems * that add the B_flag to the UzpOpts structure, see unzip.h.) */ #if (!defined(NO_UNIXBACKUP) && !defined(UNIXBACKUP)) # if defined(UNIX) || defined(OS2) || defined(WIN32) # define UNIXBACKUP # endif #endif #if (defined(DLL) && !defined(REENTRANT)) # define REENTRANT #endif #if (!defined(DYNAMIC_CRC_TABLE) && !defined(FUNZIP)) # define DYNAMIC_CRC_TABLE #endif #if (defined(DYNAMIC_CRC_TABLE) && !defined(REENTRANT)) # ifndef DYNALLOC_CRCTAB # define DYNALLOC_CRCTAB # endif #endif /*--------------------------------------------------------------------------- OS-dependent configuration for UnZip internals ---------------------------------------------------------------------------*/ /* Some compiler distributions for Win32/i386 systems try to emulate * a Unix (POSIX-compatible) environment. */ #if (defined(WIN32) && defined(UNIX)) /* UnZip does not support merging both ports in a single executable. */ # if (defined(FORCE_WIN32_OVER_UNIX) && defined(FORCE_UNIX_OVER_WIN32)) /* conflicting choice requests -> we prefer the Win32 environment */ # undef FORCE_UNIX_OVER_WIN32 # endif # ifdef FORCE_WIN32_OVER_UNIX /* native Win32 support was explicitly requested... */ # undef UNIX # else /* use the POSIX (Unix) emulation features by default... */ # undef WIN32 # endif #endif /* bad or (occasionally?) missing stddef.h: */ #if (defined(M_XENIX) || defined(DNIX)) # define NO_STDDEF_H #endif #if (defined(M_XENIX) && !defined(M_UNIX)) /* SCO Xenix only, not SCO Unix */ # define SCO_XENIX # define NO_LIMITS_H /* no limits.h, but MODERN defined */ # define NO_UID_GID /* no uid_t/gid_t */ # define size_t int #endif #ifdef realix /* Modcomp Real/IX, real-time SysV.3 variant */ # define SYSV # define NO_UID_GID /* no uid_t/gid_t */ #endif #if (defined(_AIX) && !defined(_ALL_SOURCE)) # define _ALL_SOURCE #endif #if defined(apollo) /* defines __STDC__ */ # define NO_STDLIB_H #endif #ifdef DNIX # define SYSV # define SHORT_NAMES /* 14-char limitation on path components */ /* # define FILENAME_MAX 14 */ # define FILENAME_MAX NAME_MAX /* GRR: experiment */ #endif #if (defined(SYSTEM_FIVE) || defined(__SYSTEM_FIVE)) # ifndef SYSV # define SYSV # endif #endif /* SYSTEM_FIVE || __SYSTEM_FIVE */ #if (defined(M_SYSV) || defined(M_SYS5)) # ifndef SYSV # define SYSV # endif #endif /* M_SYSV || M_SYS5 */ /* __SVR4 and __svr4__ catch Solaris on at least some combos of compiler+OS */ #if (defined(__SVR4) || defined(__svr4__) || defined(sgi) || defined(__hpux)) # ifndef SYSV # define SYSV # endif #endif /* __SVR4 || __svr4__ || sgi || __hpux */ #if (defined(LINUX) || defined(__QNX__)) # ifndef SYSV # define SYSV # endif #endif /* LINUX || __QNX__ */ #if (defined(ultrix) || defined(__ultrix) || defined(bsd4_2)) # if (!defined(BSD) && !defined(SYSV)) # define BSD # endif #endif /* ultrix || __ultrix || bsd4_2 */ #if (defined(sun) || defined(pyr) || defined(CONVEX)) # if (!defined(BSD) && !defined(SYSV)) # define BSD # endif #endif /* sun || pyr || CONVEX */ #ifdef pyr /* Pyramid: has BSD and AT&T "universes" */ # ifdef BSD # define pyr_bsd # define USE_STRINGS_H /* instead of more common string.h */ # define ZMEM /* ZMEM now uses bcopy/bzero: not in AT&T universe */ # endif /* (AT&T memcpy claimed to be very slow, though) */ # define DECLARE_ERRNO #endif /* pyr */ /* stat() bug for Borland, VAX C RTL, and Atari ST MiNT on TOS * filesystems: returns 0 for wildcards! (returns 0xffffffff on Minix * filesystem or `U:' drive under Atari MiNT.) Watcom C was previously * included on this list; it would be good to know what version the problem * was fixed at, if it did exist. */ #if (defined(__TURBOC__) && !defined(WIN32)) /*# define WILD_STAT_BUG*/ #endif #if (defined(VMS) || defined(__MINT__)) # define WILD_STAT_BUG #endif /*--------------------------------------------------------------------------- OS-dependent includes ---------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- API (DLL) section: ---------------------------------------------------------------------------*/ #ifdef DLL # define MAIN UZ_EXP UzpMain /* was UzpUnzip */ # ifdef OS2DLL # undef Info # define REDIRECTC(c) varputchar(__G__ c) # define REDIRECTPRINT(buf,size) varmessage(__G__ buf, size) # define FINISH_REDIRECT() finish_REXX_redirect(__G) # else # define REDIRECTC(c) # define REDIRECTPRINT(buf,size) 0 # define FINISH_REDIRECT() close_redirect(__G) # endif #endif /*--------------------------------------------------------------------------- Acorn RISCOS section: ---------------------------------------------------------------------------*/ #ifdef RISCOS # include "acorn/riscos.h" #endif /*--------------------------------------------------------------------------- Amiga section: ---------------------------------------------------------------------------*/ #ifdef AMIGA # include "amiga/amiga.h" #endif /*--------------------------------------------------------------------------- AOS/VS section (somewhat similar to Unix, apparently): ---------------------------------------------------------------------------*/ #ifdef AOS_VS # ifdef __FILEIO_C # include "aosvs/aosvs.h" # endif #endif /*--------------------------------------------------------------------------- Atari ST section: ---------------------------------------------------------------------------*/ #ifdef ATARI # include # include # include # include # define SYMLINKS # define EXE_EXTENSION ".tos" # ifndef DATE_FORMAT # define DATE_FORMAT DF_DMY # endif # define DIR_END '/' # define INT_SPRINTF # define timezone _timezone # define lenEOL 2 # define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);} # undef SHORT_NAMES # if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) # define TIMESTAMP # endif #endif /*--------------------------------------------------------------------------- AtheOS section: ---------------------------------------------------------------------------*/ #ifdef __ATHEOS__ # include "atheos/athcfg.h" #endif /*--------------------------------------------------------------------------- BeOS section: ---------------------------------------------------------------------------*/ #ifdef __BEOS__ # include "beos/beocfg.h" #endif /*--------------------------------------------------------------------------- Human68k/X680x0 section: ---------------------------------------------------------------------------*/ #ifdef __human68k__ /* DO NOT DEFINE DOS_OS2 HERE! If Human68k is so much */ /* like MS-DOS and/or OS/2, create DOS_H68_OS2 macro. */ # if (!defined(_MBCS) && !defined(NO_MBCS)) /* enable MBCS support by default for this system */ # define _MBCS # endif # if (defined(_MBCS) && defined(NO_MBCS)) /* disable MBCS support when explicitely requested */ # undef _MBCS # endif # include # include # include # include # include # ifdef HAVE_MBSTRING_H # include # endif # ifdef HAVE_MBCTYPE_H # include # else # ifndef _ismbblead # define _ismbblead(c) (0x80 <= (c) && ((c) < 0xa0 || 0xe0 <= (c))) # endif # endif # ifndef DATE_FORMAT # define DATE_FORMAT DF_YMD /* Japanese standard */ # endif # define lenEOL 1 # define PutNativeEOL *q++ = native(LF); # define INT_SPRINTF # define SYMLINKS # ifdef SFX # define MAIN main_sfx # endif #endif /*--------------------------------------------------------------------------- Mac section: ---------------------------------------------------------------------------*/ #ifdef MACOS # include "maccfg.h" #endif /* MACOS */ /*--------------------------------------------------------------------------- MS-DOS, OS/2, FLEXOS section: ---------------------------------------------------------------------------*/ #ifdef WINDLL # ifdef MORE # undef MORE # endif # ifdef OS2_EAS # undef OS2_EAS # endif #endif #if (defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__))) # ifndef MSC # define MSC /* This should work for older MSC, too! */ # endif #endif #if (defined(MSDOS) || defined(OS2) || defined(FLEXOS)) # include /* off_t, time_t, dev_t, ... */ # include # include /* lseek(), open(), setftime(), dup(), creat() */ # include /* localtime() */ # include /* O_BINARY for open() w/o CR/LF translation */ # ifdef OS2 /* defined for all OS/2 compilers */ # include "os2/os2cfg.h" # else # ifdef FLEXOS # include "flexos/flxcfg.h" # else # include "msdos/doscfg.h" # endif # endif # if (defined(_MSC_VER) && (_MSC_VER == 700) && !defined(GRR)) /* * ARGH. MSC 7.0 libraries think times are based on 1899 Dec 31 00:00, not * 1970 Jan 1 00:00. So we have to diddle time_t's appropriately: add or * subtract 70 years' worth of seconds; i.e., number of days times 86400; * i.e., (70*365 regular days + 17 leap days + 1 1899 day) * 86400 == * (25550 + 17 + 1) * 86400 == 2209075200 seconds. We know time_t is an * unsigned long (ulg) on the only system with this bug. */ # define TIMET_TO_NATIVE(x) (x) += (ulg)2209075200L; # define NATIVE_TO_TIMET(x) (x) -= (ulg)2209075200L; # endif # if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0450)) # define timezone _timezone # endif # if (defined(__GO32__) || defined(FLEXOS)) # define DIR_END '/' # else # define DIR_END '\\' /* OS uses '\\' as directory separator */ # define DIR_END2 '/' /* also check for '/' (RTL may convert) */ # endif # ifdef DATE_FORMAT # undef DATE_FORMAT # endif # define DATE_FORMAT dateformat() # define lenEOL 2 # define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);} # if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)) # define USE_EF_UT_TIME # endif #endif /* MSDOS || OS2 || FLEXOS */ /*--------------------------------------------------------------------------- MTS section (piggybacks UNIX, I think): ---------------------------------------------------------------------------*/ #ifdef MTS # include /* off_t, time_t, dev_t, ... */ # include # include /* MTS uses this instead of fcntl.h */ # include # include # include /* some important non-ANSI routines */ # define mkdir(s,n) (-1) /* no "make directory" capability */ # define EBCDIC /* set EBCDIC conversion on */ # define NO_STRNICMP /* unzip's is as good the one in MTS */ # define USE_FWRITE # define close_outfile() fclose(G.outfile) /* can't set time on files */ # define umask(n) /* don't have umask() on MTS */ # define FOPWT "w" /* open file for writing in TEXT mode */ # ifndef DATE_FORMAT # define DATE_FORMAT DF_MDY # endif # define lenEOL 1 # define PutNativeEOL *q++ = native(LF); #endif /* MTS */ /*--------------------------------------------------------------------------- Novell Netware NLM section ---------------------------------------------------------------------------*/ #ifdef NLM # include "netware/nlmcfg.h" #endif /*--------------------------------------------------------------------------- QDOS section ---------------------------------------------------------------------------*/ #ifdef QDOS # define DIRENT # include # include # include # include # include "qdos/izqdos.h" # ifndef DATE_FORMAT # define DATE_FORMAT DF_MDY # endif # define lenEOL 1 # define PutNativeEOL *q++ = native(LF); # define DIR_END '_' # define RETURN QReturn # undef PATH_MAX # define PATH_MAX 36 # if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) # define TIMESTAMP # endif # define SCREENSIZE(ttrows, ttcols) screensize(ttrows, ttcols) # define SCREENWIDTH 80 #endif /*--------------------------------------------------------------------------- Tandem NSK section: ---------------------------------------------------------------------------*/ #ifdef TANDEM # include "tandem.h" # include # ifndef __INT32 /* We are compiling with non-WIDE memory model, int = 16 bits */ # ifndef INT_16BIT # define INT_16BIT /* report "int" size is 16-bit to inflate setup */ # endif # ifdef USE_DEFLATE64 /* Following required for 64k WSIZE of Deflate64 support */ # define MED_MEM /* else OUTBUFSIZ is 64K and fails in do_string */ # define INBUFSIZ 8192 /* but larger buffer for real OSes */ # endif # endif /* use a single LF delimiter so that writes to 101 text files work */ # define PutNativeEOL *q++ = native(LF); # define lenEOL 1 # ifndef DATE_FORMAT # define DATE_FORMAT DF_DMY # endif # define SCREENLINES 25 /* USE_EF_UT_TIME is set in tandem.h */ # define RESTORE_UIDGID # define NO_STRNICMP #endif /*--------------------------------------------------------------------------- THEOS section: ---------------------------------------------------------------------------*/ #ifdef THEOS # include "theos/thscfg.h" #endif /*--------------------------------------------------------------------------- TOPS-20 section: ---------------------------------------------------------------------------*/ #ifdef TOPS20 # include /* off_t, time_t, dev_t, ... */ # include # include # include # include # include # include # include /* get amazing monsym() macro */ extern int open(), close(), read(); extern int stat(), unlink(), jsys(), fcntl(); extern long lseek(), dup(), creat(); # define strchr index /* GRR: necessary? */ # define strrchr rindex # define REALLY_SHORT_SYMS # define NO_MKDIR # ifndef HAVE_STRNICMP # define NO_STRNICMP /* probably not provided by TOPS20 C RTL */ # endif # define DIR_BEG '<' # define DIR_END '>' # define DIR_EXT ".directory" # ifndef DATE_FORMAT # define DATE_FORMAT DF_MDY # endif # define EXE_EXTENSION ".exe" /* just a guess... */ #endif /* TOPS20 */ /*--------------------------------------------------------------------------- Unix section: ---------------------------------------------------------------------------*/ #ifdef UNIX # include "unix/unxcfg.h" #endif /* UNIX */ /*--------------------------------------------------------------------------- VM/CMS and MVS section: ---------------------------------------------------------------------------*/ #ifdef CMS_MVS # include "vmmvs.h" # define CLOSE_INFILE() close_infile(__G) #endif /*--------------------------------------------------------------------------- VMS section: ---------------------------------------------------------------------------*/ #ifdef VMS # include "vms/vmscfg.h" #endif /* VMS */ /*--------------------------------------------------------------------------- Win32 (Windows 95/NT) section: ---------------------------------------------------------------------------*/ #if (defined(WIN32) && !defined(POCKET_UNZIP) && !defined(_WIN32_WCE)) # include "win32/w32cfg.h" #endif /*--------------------------------------------------------------------------- Win32 Windows CE section (also POCKET_UNZIP) ---------------------------------------------------------------------------*/ #if (defined(_WIN32_WCE) || defined(POCKET_UNZIP)) # include "wince/wcecfg.h" #endif /* ---------------------------------------------------------------------------- MUST BE AFTER LARGE FILE INCLUDES ---------------------------------------------------------------------------- */ /* This stuff calls in types and messes up large file includes. It needs to go after large file defines in local includes. I am guessing that moving them here probably broke some ports, but hey. 10/31/2004 EG */ /* ---------------------------------------------------------------------------- Common includes ---------------------------------------------------------------------------- */ /* Some ports apply specific adjustments which must be in effect before reading the "standard" include headers. */ #ifdef EFT # define Z_OFF_T off_t /* Amdahl UTS nonsense ("extended file types") */ #else #if (defined(UNIX) && defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)) # define Z_OFF_T off_t /* 64bit offsets to support 2GB < zipfile size < 4GB */ #else # define Z_OFF_T long long #endif #endif #ifndef ZOFF_T_DEFINED typedef Z_OFF_T zoff_t; # define ZOFF_T_DEFINED #endif #ifndef Z_STAT_DEFINED typedef struct stat z_stat; # define Z_STAT_DEFINED #endif #ifndef MINIX /* Minix needs it after all the other includes (?) */ # include #endif #include /* skip for VMS, to use tolower() function? */ #include /* used in mapname() */ #ifdef USE_STRINGS_H # include /* strcpy, strcmp, memcpy, index/rindex, etc. */ #else # include /* strcpy, strcmp, memcpy, strchr/strrchr, etc. */ #endif #if (defined(MODERN) && !defined(NO_LIMITS_H)) # include /* MAX/MIN constant symbols for system types... */ #endif /* this include must be down here for SysV.4, for some reason... */ #include /* used in unzip.c, fileio.c */ #ifdef MODERN # ifndef NO_STDDEF_H # include # endif # ifndef NO_STDLIB_H # include /* standard library prototypes, malloc(), etc. */ # endif typedef size_t extent; #else /* !MODERN */ # ifndef AOS_VS /* mostly modern? */ Z_OFF_T lseek(); # ifdef VAXC /* not fully modern, but has stdlib.h and void */ # include # else char *malloc(); # endif /* ?VAXC */ # endif /* !AOS_VS */ typedef unsigned int extent; #endif /* ?MODERN */ /*************/ /* Defines */ /*************/ #define UNZIP_BZ2VERS 46 #ifdef ZIP64_SUPPORT # ifdef USE_BZIP2 # define UNZIP_VERSION UNZIP_BZ2VERS # else # define UNZIP_VERSION 45 # endif #else #ifdef USE_DEFLATE64 # define UNZIP_VERSION 21 /* compatible with PKUNZIP 4.0 */ #else # define UNZIP_VERSION 20 /* compatible with PKUNZIP 2.0 */ #endif #endif #define VMS_UNZIP_VERSION 42 /* if OS-needed-to-extract is VMS: can do */ #if (defined(MSDOS) || defined(OS2)) # define DOS_OS2 #endif #if (defined(OS2) || defined(WIN32)) # define OS2_W32 #endif #if (defined(DOS_OS2) || defined(WIN32)) # define DOS_OS2_W32 # define DOS_W32_OS2 /* historical: don't use */ #endif #if (defined(DOS_OS2_W32) || defined(__human68k__)) # define DOS_H68_OS2_W32 #endif #if (defined(DOS_OS2) || defined(FLEXOS)) # define DOS_FLX_OS2 #endif #if (defined(DOS_OS2_W32) || defined(FLEXOS)) # define DOS_FLX_OS2_W32 #endif #if (defined(DOS_H68_OS2_W32) || defined(FLEXOS)) # define DOS_FLX_H68_OS2_W32 #endif #if (defined(DOS_FLX_OS2) || defined(NLM)) # define DOS_FLX_NLM_OS2 #endif #if (defined(DOS_FLX_OS2_W32) || defined(NLM)) # define DOS_FLX_NLM_OS2_W32 #endif #if (defined(DOS_FLX_H68_OS2_W32) || defined(NLM)) # define DOS_FLX_H68_NLM_OS2_W32 #endif #if (defined(TOPS20) || defined(VMS)) # define T20_VMS #endif #if (defined(MSDOS) || defined(T20_VMS)) # define DOS_T20_VMS #endif #if (defined(__ATHEOS__) || defined(__BEOS__)) # define ATH_BEO #endif #if (defined(ATH_BEO) || defined(UNIX)) # define ATH_BEO_UNX #endif #if (defined(ATH_BEO_UNX) || defined(THEOS)) # define ATH_BEO_THS_UNX #endif /* clean up with a few defaults */ #ifndef DIR_END # define DIR_END '/' /* last char before program name or filename */ #endif #ifndef DATE_FORMAT # ifdef DATEFMT_ISO_DEFAULT # define DATE_FORMAT DF_YMD /* defaults to invariant ISO-style */ # else # define DATE_FORMAT DF_MDY /* defaults to US convention */ # endif #endif #ifndef DATE_SEPCHAR # define DATE_SEPCHAR '-' #endif #ifndef CLOSE_INFILE # define CLOSE_INFILE() close(G.zipfd) #endif #ifndef RETURN # define RETURN return /* only used in main() */ #endif #ifndef EXIT # define EXIT exit #endif #ifndef USAGE # define USAGE(ret) usage(__G__ (ret)) /* used in unzip.c, zipinfo.c */ #endif #ifndef TIMET_TO_NATIVE /* everybody but MSC 7.0 and Macintosh */ # define TIMET_TO_NATIVE(x) # define NATIVE_TO_TIMET(x) #endif #ifndef STRNICMP # ifdef NO_STRNICMP # define STRNICMP zstrnicmp # else # define STRNICMP strnicmp # endif #endif #if (defined(DOS_FLX_NLM_OS2_W32) || defined(ATH_BEO_UNX) || defined(RISCOS)) # ifndef HAVE_UNLINK # define HAVE_UNLINK # endif #endif #if (defined(AOS_VS) || defined(ATARI)) /* GRR: others? */ # ifndef HAVE_UNLINK # define HAVE_UNLINK # endif #endif /* OS-specific exceptions to the "ANSI <--> INT_SPRINTF" rule */ #if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF)) # if (defined(SYSV) || defined(CONVEX) || defined(NeXT) || defined(BSD4_4)) # define INT_SPRINTF /* sprintf() returns int: SysVish/Posix */ # endif # if (defined(DOS_FLX_NLM_OS2_W32) || defined(VMS) || defined(AMIGA)) # define INT_SPRINTF /* sprintf() returns int: ANSI */ # endif # if (defined(ultrix) || defined(__ultrix)) /* Ultrix 4.3 and newer */ # if (defined(POSIX) || defined(__POSIX)) # define INT_SPRINTF /* sprintf() returns int: ANSI/Posix */ # endif # ifdef __GNUC__ # define PCHAR_SPRINTF /* undetermined actual return value */ # endif # endif # if (defined(__osf__) || defined(_AIX) || defined(CMS_MVS) || defined(THEOS)) # define INT_SPRINTF /* sprintf() returns int: ANSI/Posix */ # endif # if defined(sun) # define PCHAR_SPRINTF /* sprintf() returns char *: SunOS cc *and* gcc */ # endif #endif /* defaults that we hope will take care of most machines in the future */ #if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF)) # ifdef __STDC__ # define INT_SPRINTF /* sprintf() returns int: ANSI */ # endif # ifndef INT_SPRINTF # define PCHAR_SPRINTF /* sprintf() returns char *: BSDish */ # endif #endif #define MSG_STDERR(f) (f & 1) /* bit 0: 0 = stdout, 1 = stderr */ #define MSG_INFO(f) ((f & 6) == 0) /* bits 1 and 2: 0 = info */ #define MSG_WARN(f) ((f & 6) == 2) /* bits 1 and 2: 1 = warning */ #define MSG_ERROR(f) ((f & 6) == 4) /* bits 1 and 2: 2 = error */ #define MSG_FATAL(f) ((f & 6) == 6) /* bits 1 and 2: (3 = fatal error) */ #define MSG_ZFN(f) (f & 0x0008) /* bit 3: 1 = print zipfile name */ #define MSG_FN(f) (f & 0x0010) /* bit 4: 1 = print filename */ #define MSG_LNEWLN(f) (f & 0x0020) /* bit 5: 1 = leading newline if !SOL */ #define MSG_TNEWLN(f) (f & 0x0040) /* bit 6: 1 = trailing newline if !SOL */ #define MSG_MNEWLN(f) (f & 0x0080) /* bit 7: 1 = trailing NL for prompts */ /* the following are subject to change */ #define MSG_NO_WGUI(f) (f & 0x0100) /* bit 8: 1 = skip if Windows GUI */ #define MSG_NO_AGUI(f) (f & 0x0200) /* bit 9: 1 = skip if Acorn GUI */ #define MSG_NO_DLL2(f) (f & 0x0400) /* bit 10: 1 = skip if OS/2 DLL */ #define MSG_NO_NDLL(f) (f & 0x0800) /* bit 11: 1 = skip if WIN32 DLL */ #define MSG_NO_WDLL(f) (f & 0x1000) /* bit 12: 1 = skip if Windows DLL */ #if (defined(MORE) && !defined(SCREENLINES)) # ifdef DOS_FLX_NLM_OS2_W32 # define SCREENLINES 25 /* can be (should be) a function instead */ # else # define SCREENLINES 24 /* VT-100s are assumed to be minimal hardware */ # endif #endif #if (defined(MORE) && !defined(SCREENSIZE)) # ifndef SCREENWIDTH # define SCREENSIZE(scrrows, scrcols) { \ if ((scrrows) != NULL) *(scrrows) = SCREENLINES; } # else # define SCREENSIZE(scrrows, scrcols) { \ if ((scrrows) != NULL) *(scrrows) = SCREENLINES; \ if ((scrcols) != NULL) *(scrcols) = SCREENWIDTH; } # endif #endif #if (defined(__16BIT__) || defined(MED_MEM) || defined(SMALL_MEM)) # define DIR_BLKSIZ 64 /* number of directory entries per block * (should fit in 4096 bytes, usually) */ #else # define DIR_BLKSIZ 16384 /* use more memory, to reduce long-range seeks */ #endif #ifndef WSIZE # ifdef USE_DEFLATE64 # define WSIZE 65536L /* window size--must be a power of two, and */ # else /* at least 64K for PKZip's deflate64 method */ # define WSIZE 0x8000 /* window size--must be a power of two, and */ # endif /* at least 32K for zip's deflate method */ #endif #ifdef __16BIT__ # ifndef INT_16BIT # define INT_16BIT /* on 16-bit systems int size is 16 bits */ # endif #else # define nearmalloc malloc # define nearfree free # if (!defined(__IBMC__) || !defined(OS2)) # ifndef near # define near # endif # ifndef far # define far # endif # endif #endif #if (defined(DYNALLOC_CRCTAB) && !defined(DYNAMIC_CRC_TABLE)) # undef DYNALLOC_CRCTAB #endif #if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT)) # undef DYNALLOC_CRCTAB /* not safe with reentrant code */ #endif #if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB)) # ifdef DYNALLOC_CRCTAB # undef DYNALLOC_CRCTAB # endif #endif #if (defined(USE_ZLIB) && defined(ASM_CRC)) # undef ASM_CRC #endif #ifdef USE_ZLIB # ifdef IZ_CRC_BE_OPTIMIZ # undef IZ_CRC_BE_OPTIMIZ # endif # ifdef IZ_CRC_LE_OPTIMIZ # undef IZ_CRC_LE_OPTIMIZ # endif #endif #if (!defined(IZ_CRC_BE_OPTIMIZ) && !defined(IZ_CRC_LE_OPTIMIZ)) # ifdef IZ_CRCOPTIM_UNFOLDTBL # undef IZ_CRCOPTIM_UNFOLDTBL # endif #endif #ifndef INBUFSIZ # if (defined(MED_MEM) || defined(SMALL_MEM)) # define INBUFSIZ 2048 /* works for MS-DOS small model */ # else # define INBUFSIZ 8192 /* larger buffers for real OSes */ # endif #endif #if (defined(INT_16BIT) && (defined(USE_DEFLATE64) || lenEOL > 1)) /* For environments using 16-bit integers OUTBUFSIZ must be limited to * less than 64k (do_string() uses "unsigned" in calculations involving * OUTBUFSIZ). This is achieved by defining MED_MEM when WSIZE = 64k (aka * Deflate64 support enabled) or EOL markers contain multiple characters. * (The rule gets applied AFTER the default rule for INBUFSIZ because it * is not neccessary to reduce INBUFSIZE in this case.) */ # if (!defined(SMALL_MEM) && !defined(MED_MEM)) # define MED_MEM # endif #endif /* Logic for case of small memory, length of EOL > 1: if OUTBUFSIZ == 2048, * OUTBUFSIZ>>1 == 1024 and OUTBUFSIZ>>7 == 16; therefore rawbuf is 1008 bytes * and transbuf 1040 bytes. Have room for 32 extra EOL chars; 1008/32 == 31.5 * chars/line, smaller than estimated 35-70 characters per line for C source * and normal text. Hence difference is sufficient for most "average" files. * (Argument scales for larger OUTBUFSIZ.) */ #ifdef SMALL_MEM /* i.e., 16-bit OSes: MS-DOS, OS/2 1.x, etc. */ # define LoadFarString(x) fLoadFarString(__G__ (x)) # define LoadFarStringSmall(x) fLoadFarStringSmall(__G__ (x)) # define LoadFarStringSmall2(x) fLoadFarStringSmall2(__G__ (x)) # if (defined(_MSC_VER) && (_MSC_VER >= 600)) # define zfstrcpy(dest, src) _fstrcpy((dest), (src)) # define zfstrcmp(s1, s2) _fstrcmp((s1), (s2)) # endif # if !(defined(SFX) || defined(FUNZIP)) # if (defined(_MSC_VER)) # define zfmalloc(sz) _fmalloc((sz)) # define zffree(x) _ffree(x) # endif # if (defined(__TURBOC__)) # include # define zfmalloc(sz) farmalloc((unsigned long)(sz)) # define zffree(x) farfree(x) # endif # endif /* !(SFX || FUNZIP) */ # ifndef Far # define Far far /* __far only works for MSC 6.00, not 6.0a or Borland */ # endif # define OUTBUFSIZ INBUFSIZ # if (lenEOL == 1) # define RAWBUFSIZ (OUTBUFSIZ>>1) # else # define RAWBUFSIZ ((OUTBUFSIZ>>1) - (OUTBUFSIZ>>7)) # endif # define TRANSBUFSIZ (OUTBUFSIZ-RAWBUFSIZ) typedef short shrint; /* short/int or "shrink int" (unshrink) */ #else # define zfstrcpy(dest, src) strcpy((dest), (src)) # define zfstrcmp(s1, s2) strcmp((s1), (s2)) # define zfmalloc malloc # define zffree(x) free(x) # ifdef QDOS # define LoadFarString(x) Qstrfix(x) /* fix up _ for '.' */ # define LoadFarStringSmall(x) Qstrfix(x) # define LoadFarStringSmall2(x) Qstrfix(x) # else # define LoadFarString(x) (char *)(x) # define LoadFarStringSmall(x) (char *)(x) # define LoadFarStringSmall2(x) (char *)(x) # endif # ifdef MED_MEM # define OUTBUFSIZ 0xFF80 /* can't malloc arrays of 0xFFE8 or more */ # define TRANSBUFSIZ 0xFF80 typedef short shrint; # else # define OUTBUFSIZ (lenEOL*WSIZE) /* more efficient text conversion */ # define TRANSBUFSIZ (lenEOL*OUTBUFSIZ) # ifdef AMIGA typedef short shrint; # else typedef int shrint; /* for efficiency/speed, we hope... */ # endif # endif /* ?MED_MEM */ # define RAWBUFSIZ OUTBUFSIZ #endif /* ?SMALL_MEM */ #ifndef Far # define Far #endif #ifndef Cdecl # define Cdecl #endif #ifndef MAIN # define MAIN main #endif #ifdef SFX /* disable some unused features for SFX executables */ # ifndef NO_ZIPINFO # define NO_ZIPINFO # endif # ifdef TIMESTAMP # undef TIMESTAMP # endif #endif #ifdef SFX # ifdef CHEAP_SFX_AUTORUN # ifndef NO_SFX_EXDIR # define NO_SFX_EXDIR # endif # endif # ifndef NO_SFX_EXDIR # ifndef SFX_EXDIR # define SFX_EXDIR # endif # else # ifdef SFX_EXDIR # undef SFX_EXDIR # endif # endif #endif /* user may have defined both by accident... NOTIMESTAMP takes precedence */ #if (defined(TIMESTAMP) && defined(NOTIMESTAMP)) # undef TIMESTAMP #endif #if (!defined(COPYRIGHT_CLEAN) && !defined(USE_SMITH_CODE)) # define COPYRIGHT_CLEAN #endif /* The LZW patent is expired worldwide since 2004-Jul-07, so USE_UNSHRINK * is now enabled by default. See unshrink.c. */ #if (!defined(LZW_CLEAN) && !defined(USE_UNSHRINK)) # define USE_UNSHRINK #endif #ifndef O_BINARY # define O_BINARY 0 #endif #ifndef PIPE_ERROR # ifndef EPIPE # define EPIPE -1 # endif # define PIPE_ERROR (errno == EPIPE) #endif /* File operations--use "b" for binary if allowed or fixed length 512 on VMS */ #ifdef VMS # define FOPR "r","ctx=stm" # define FOPM "r+","ctx=stm","rfm=fix","mrs=512" # define FOPW "w","ctx=stm","rfm=fix","mrs=512" # define FOPWR "w+","ctx=stm","rfm=fix","mrs=512" #endif /* VMS */ #ifdef CMS_MVS /* Binary files must be RECFM=F,LRECL=1 for ftell() to get correct pos */ /* ...unless byteseek is used. Let's try that for a while. */ # define FOPR "rb,byteseek" # define FOPM "r+b,byteseek" # ifdef MVS # define FOPW "wb,recfm=u,lrecl=32760,byteseek" /* New binary files */ # define FOPWE "wb" /* Existing binary files */ # define FOPWT "w,lrecl=133" /* New text files */ # define FOPWTE "w" /* Existing text files */ # else # define FOPW "wb,recfm=v,lrecl=32760" # define FOPWT "w" # endif #endif /* CMS_MVS */ #ifdef TOPS20 /* TOPS-20 MODERN? You kidding? */ # define FOPW "w8" #endif /* TOPS20 */ /* Defaults when nothing special has been defined previously. */ #ifdef MODERN # ifndef FOPR # define FOPR "rb" # endif # ifndef FOPM # define FOPM "r+b" # endif # ifndef FOPW # define FOPW "wb" # endif # ifndef FOPWT # define FOPWT "wt" # endif # ifndef FOPWR # define FOPWR "w+b" # endif #else /* !MODERN */ # ifndef FOPR # define FOPR "r" # endif # ifndef FOPM # define FOPM "r+" # endif # ifndef FOPW # define FOPW "w" # endif # ifndef FOPWT # define FOPWT "w" # endif # ifndef FOPWR # define FOPWR "w+" # endif #endif /* ?MODERN */ /* * If exists on most systems, should include that, since it may * define some or all of the following: NAME_MAX, PATH_MAX, _POSIX_NAME_MAX, * _POSIX_PATH_MAX. */ #ifdef DOS_FLX_NLM_OS2_W32 # include #endif /* 2008-07-22 SMS. * Unfortunately, on VMS, exists, and is included by * (so it's pretty much unavoidable), and it defines PATH_MAX to a fixed * short value (256, correct only for older systems without ODS-5 support), * rather than one based on the real RMS NAM[L] situation. So, we * artificially undefine it here, to allow our better-defined _MAX_PATH * (see vms/vmscfg.h) to be used. */ #ifdef VMS # undef PATH_MAX #endif #ifndef PATH_MAX # ifdef MAXPATHLEN # define PATH_MAX MAXPATHLEN /* in on some systems */ # else # ifdef _MAX_PATH # define PATH_MAX _MAX_PATH # else # if FILENAME_MAX > 255 # define PATH_MAX FILENAME_MAX /* used like PATH_MAX on some systems */ # else # define PATH_MAX 1024 # endif # endif /* ?_MAX_PATH */ # endif /* ?MAXPATHLEN */ #endif /* !PATH_MAX */ /* * buffer size required to hold the longest legal local filepath * (including the trailing '\0') */ #define FILNAMSIZ PATH_MAX #ifdef UNICODE_SUPPORT # if !(defined(UTF8_MAYBE_NATIVE) || defined(UNICODE_WCHAR)) # undef UNICODE_SUPPORT # endif #endif /* 2007-09-18 SMS. * Include here if it will be needed later for Unicode. * Otherwise, SETLOCALE may be defined here, and then defined again * (differently) when is read later. */ #ifdef UNICODE_SUPPORT # ifdef UNICODE_WCHAR # if !(defined(_WIN32_WCE) || defined(POCKET_UNZIP)) # include # endif # endif # ifndef _MBCS /* no need to include twice, see below */ # include # ifndef SETLOCALE # define SETLOCALE(category, locale) setlocale(category, locale) # endif # endif #endif /* UNICODE_SUPPORT */ /* DBCS support for Info-ZIP (mainly for japanese (-: ) * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp) */ #ifdef _MBCS # include /* Multi Byte Character Set */ # define ___MBS_TMP_DEF char *___tmp_ptr; # define ___TMP_PTR ___tmp_ptr # ifndef CLEN # define NEED_UZMBCLEN # define CLEN(ptr) (int)uzmbclen((ZCONST unsigned char *)(ptr)) # endif # ifndef PREINCSTR # define PREINCSTR(ptr) (ptr += CLEN(ptr)) # endif # define POSTINCSTR(ptr) (___TMP_PTR=(char *)(ptr), PREINCSTR(ptr),___TMP_PTR) char *plastchar OF((ZCONST char *ptr, extent len)); # define lastchar(ptr, len) ((int)(unsigned)*plastchar(ptr, len)) # ifndef MBSCHR # define NEED_UZMBSCHR # define MBSCHR(str,c) (char *)uzmbschr((ZCONST unsigned char *)(str), c) # endif # ifndef MBSRCHR # define NEED_UZMBSRCHR # define MBSRCHR(str,c) (char *)uzmbsrchr((ZCONST unsigned char *)(str), c) # endif # ifndef SETLOCALE # define SETLOCALE(category, locale) setlocale(category, locale) # endif #else /* !_MBCS */ # define ___MBS_TMP_DEF # define ___TMP_PTR # define CLEN(ptr) 1 # define PREINCSTR(ptr) (++(ptr)) # define POSTINCSTR(ptr) ((ptr)++) # define plastchar(ptr, len) (&ptr[(len)-1]) # define lastchar(ptr, len) (ptr[(len)-1]) # define MBSCHR(str, c) strchr(str, c) # define MBSRCHR(str, c) strrchr(str, c) # ifndef SETLOCALE # define SETLOCALE(category, locale) # endif #endif /* ?_MBCS */ #define INCSTR(ptr) PREINCSTR(ptr) #if (defined(MALLOC_WORK) && !defined(MY_ZCALLOC)) /* Any system without a special calloc function */ # ifndef zcalloc # define zcalloc(items, size) \ (zvoid far *)calloc((unsigned)(items), (unsigned)(size)) # endif # ifndef zcfree # define zcfree free # endif #endif /* MALLOC_WORK && !MY_ZCALLOC */ #if (defined(CRAY) && defined(ZMEM)) # undef ZMEM #endif #ifdef ZMEM # undef ZMEM # define memcmp(b1,b2,len) bcmp(b2,b1,len) # define memcpy(dest,src,len) bcopy(src,dest,len) # define memzero bzero #else # define memzero(dest,len) memset(dest,0,len) #endif #ifndef TRUE # define TRUE 1 /* sort of obvious */ #endif #ifndef FALSE # define FALSE 0 #endif #ifndef SEEK_SET # define SEEK_SET 0 # define SEEK_CUR 1 # define SEEK_END 2 #endif #if (!defined(S_IEXEC) && defined(S_IXUSR)) # define S_IEXEC S_IXUSR #endif #if (defined(UNIX) && defined(S_IFLNK) && !defined(MTS)) # define SYMLINKS # ifndef S_ISLNK # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) # endif #endif /* UNIX && S_IFLNK && !MTS */ #ifndef S_ISDIR # ifdef CMS_MVS # define S_ISDIR(m) (FALSE) # else # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) # endif #endif #ifndef IS_VOLID # define IS_VOLID(m) ((m) & 0x08) #endif /***********************************/ /* LARGE_FILE_SUPPORT */ /***********************************/ /* This whole section lifted from Zip 3b tailor.h * Types are in OS dependent headers (eg, w32cfg.h) * * LARGE_FILE_SUPPORT and ZIP64_SUPPORT are automatically * set in OS dependent headers (for some ports) based on the port and compiler. * * Function prototypes are below as OF is defined earlier in this file * but after OS dependent header is included. * * E. Gordon 9/21/2003 * Updated 1/28/2004 * Lifted and placed here 6/7/2004 - Myles Bennett */ #ifdef LARGE_FILE_SUPPORT /* 64-bit Large File Support */ /* ---------------------------- */ # if defined(UNIX) || defined(VMS) /* 64-bit stat functions */ # define zstat stat # define zfstat fstat /* 64-bit fseeko */ # define zlseek lseek # define zfseeko fseeko /* 64-bit ftello */ # define zftello ftello /* 64-bit fopen */ # define zfopen fopen # define zfdopen fdopen # endif /* UNIX || VMS */ /* ---------------------------- */ # ifdef WIN32 # if defined(_MSC_VER) || defined(__MINGW32__) || defined(__LCC__) /* MS C (VC), MinGW GCC port and LCC-32 use the MS C Runtime lib */ /* 64-bit stat functions */ # define zstat _stati64 # define zfstat _fstati64 /* 64-bit lseek */ # define zlseek _lseeki64 # if defined(_MSC_VER) && (_MSC_VER >= 1400) /* Beginning with VS 8.0 (Visual Studio 2005, MSC 14), the Microsoft C rtl publishes its (previously internal) implmentations of "fseeko" and "ftello" for 64-bit file offsets. */ /* 64-bit fseeko */ # define zfseeko _fseeki64 /* 64-bit ftello */ # define zftello _ftelli64 # else /* not (defined(_MSC_VER) && (_MSC_VER >= 1400)) */ # if defined(__MSVCRT_VERSION__) && (__MSVCRT_VERSION__ >= 0x800) /* Up-to-date versions of MinGW define the macro __MSVCRT_VERSION__ to denote the version of the MS C rtl dll used for linking. When configured to link against the runtime of MS Visual Studio 8 (or newer), the built-in 64-bit fseek/ftell functions are available. */ /* 64-bit fseeko */ # define zfseeko _fseeki64 /* 64-bit ftello */ # define zftello _ftelli64 # else /* !(defined(__MSVCRT_VERSION__) && (__MSVCRT_VERSION__>=0x800)) */ /* The version of the C runtime is lower than MSC 14 or unknown. */ /* The newest MinGW port contains built-in extensions to the MSC rtl that provide fseeko and ftello, but our implementations will do for now. */ /* 64-bit fseeko */ int zfseeko OF((FILE *, zoff_t, int)); /* 64-bit ftello */ zoff_t zftello OF((FILE *)); # endif /* ? (__MSVCRT_VERSION__ >= 0x800) */ # endif /* ? (_MSC_VER >= 1400) */ /* 64-bit fopen */ # define zfopen fopen # define zfdopen fdopen # endif /* _MSC_VER || __MINGW__ || __LCC__ */ # ifdef __CYGWIN__ /* CYGWIN GCC Posix emulator on Windows (configuration not yet finished/tested) */ /* 64-bit stat functions */ # define zstat _stati64 # define zfstat _fstati64 /* 64-bit lseek */ # define zlseek _lseeki64 /* 64-bit fseeko */ # define zfseeko fseeko /* 64-bit ftello */ # define zftello ftello /* 64-bit fopen */ # define zfopen fopen # define zfdopen fdopen # endif # if defined(__WATCOMC__) || defined(__BORLANDC__) /* WATCOM C and Borland C provide their own C runtime libraries, but they are sufficiently compatible with MS CRTL. */ /* 64-bit stat functions */ # define zstat _stati64 # define zfstat _fstati64 # ifdef __WATCOMC__ /* 64-bit lseek */ # define zlseek _lseeki64 # endif /* 64-bit fseeko */ int zfseeko OF((FILE *, zoff_t, int)); /* 64-bit ftello */ zoff_t zftello OF((FILE *)); /* 64-bit fopen */ # define zfopen fopen # define zfdopen fdopen # endif # ifdef __IBMC__ /* IBM C */ /* 64-bit stat functions */ /* 64-bit fseeko */ /* 64-bit ftello */ /* 64-bit fopen */ # endif # endif /* WIN32 */ #else /* No Large File Support */ # ifndef REGULUS /* returns the inode number on success(!)...argh argh argh */ # define zstat stat # endif # define zfstat fstat # define zlseek lseek # define zfseeko fseek # define zftello ftell # define zfopen fopen # define zfdopen fdopen # if defined(UNIX) || defined(VMS) || defined(WIN32) /* For these systems, implement "64bit file vs. 32bit prog" check */ # ifndef DO_SAFECHECK_2GB # define DO_SAFECHECK_2GB # endif # endif #endif /* No "64bit file vs. 32bit prog" check for SFX stub, to save space */ #if (defined(DO_SAFECHECK_2GB) && defined(SFX)) # undef DO_SAFECHECK_2GB #endif #ifndef SSTAT # ifdef WILD_STAT_BUG # define SSTAT(path,pbuf) (iswild(path) || zstat(path,pbuf)) # else # define SSTAT zstat # endif #endif /* Default fzofft() format selection. */ #ifndef FZOFFT_FMT # ifdef LARGE_FILE_SUPPORT # define FZOFFT_FMT "ll" # define FZOFFT_HEX_WID_VALUE "16" # else /* def LARGE_FILE_SUPPORT */ # define FZOFFT_FMT "l" # define FZOFFT_HEX_WID_VALUE "8" # endif /* def LARGE_FILE_SUPPORT */ #endif /* ndef FZOFFT_FMT */ #define FZOFFT_HEX_WID ((char *) -1) #define FZOFFT_HEX_DOT_WID ((char *) -2) #define FZOFFT_NUM 4 /* Number of chambers. */ #define FZOFFT_LEN 24 /* Number of characters/chamber. */ #ifdef SHORT_SYMS /* Mark Williams C, ...? */ # define extract_or_test_files xtr_or_tst_files # define extract_or_test_member xtr_or_tst_member #endif #ifdef REALLY_SHORT_SYMS /* TOPS-20 linker: first 6 chars */ # define process_cdir_file_hdr XXpcdfh # define process_local_file_hdr XXplfh # define extract_or_test_files XXxotf /* necessary? */ # define extract_or_test_member XXxotm /* necessary? */ # define check_for_newer XXcfn # define overwrite_all XXoa # define process_all_files XXpaf # define extra_field XXef # define explode_lit8 XXel8 # define explode_lit4 XXel4 # define explode_nolit8 XXnl8 # define explode_nolit4 XXnl4 # define cpdist8 XXcpdist8 # define inflate_codes XXic # define inflate_stored XXis # define inflate_fixed XXif # define inflate_dynamic XXid # define inflate_block XXib # define maxcodemax XXmax #endif #ifndef S_TIME_T_MAX /* max value of signed (>= 32-bit) time_t */ # define S_TIME_T_MAX ((time_t)(ulg)0x7fffffffL) #endif #ifndef U_TIME_T_MAX /* max value of unsigned (>= 32-bit) time_t */ # define U_TIME_T_MAX ((time_t)(ulg)0xffffffffL) #endif #ifdef DOSTIME_MINIMUM /* min DOSTIME value (1980-01-01) */ # undef DOSTIME_MINIMUM #endif #define DOSTIME_MINIMUM ((ulg)0x00210000L) #ifdef DOSTIME_2038_01_18 /* approximate DOSTIME equivalent of */ # undef DOSTIME_2038_01_18 /* the signed-32-bit time_t limit */ #endif #define DOSTIME_2038_01_18 ((ulg)0x74320000L) #ifdef QDOS # define ZSUFX "_zip" # define ALT_ZSUFX ".zip" #else # ifdef RISCOS # define ZSUFX "/zip" # else # define ZSUFX ".zip" # endif # define ALT_ZSUFX ".ZIP" /* Unix-only so far (only case-sensitive fs) */ #endif #define CENTRAL_HDR_SIG "\001\002" /* the infamous "PK" signature bytes, */ #define LOCAL_HDR_SIG "\003\004" /* w/o "PK" (so unzip executable not */ #define END_CENTRAL_SIG "\005\006" /* mistaken for zipfile itself) */ #define EXTD_LOCAL_SIG "\007\010" /* [ASCII "\113" == EBCDIC "\080" ??] */ /** internal-only return codes **/ #define IZ_DIR 76 /* potential zipfile is a directory */ /* special return codes for mapname() */ #define MPN_OK 0 /* mapname successful */ #define MPN_INF_TRUNC (1<<8) /* caution - filename truncated */ #define MPN_INF_SKIP (2<<8) /* info - skipped because nothing to do */ #define MPN_ERR_SKIP (3<<8) /* error - entry skipped */ #define MPN_ERR_TOOLONG (4<<8) /* error - path too long */ #define MPN_NOMEM (10<<8) /* error - out of memory, file skipped */ #define MPN_CREATED_DIR (16<<8) /* directory created: set time & permission */ #define MPN_VOL_LABEL (17<<8) /* volume label, but can't set on hard disk */ #define MPN_INVALID (99<<8) /* internal logic error, should never reach */ /* mask for internal mapname&checkdir return codes */ #define MPN_MASK 0x7F00 /* error code for extracting/testing extra field blocks */ #define IZ_EF_TRUNC 79 /* local extra field truncated (PKZIP'd) */ /* choice of activities for do_string() */ #define SKIP 0 /* skip header block */ #define DISPLAY 1 /* display archive comment (ASCII) */ #define DISPL_8 5 /* display file comment (ext. ASCII) */ #define DS_FN 2 /* read filename (ext. ASCII, chead) */ #define DS_FN_C 2 /* read filename from central header */ #define DS_FN_L 6 /* read filename from local header */ #define EXTRA_FIELD 3 /* copy extra field into buffer */ #define DS_EF 3 #ifdef AMIGA # define FILENOTE 4 /* convert file comment to filenote */ #endif #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) # define CHECK_AUTORUN 7 /* copy command, display remainder */ # define CHECK_AUTORUN_Q 8 /* copy command, skip remainder */ #endif #define DOES_NOT_EXIST -1 /* return values for check_for_newer() */ #define EXISTS_AND_OLDER 0 #define EXISTS_AND_NEWER 1 #define OVERWRT_QUERY 0 /* status values for G.overwrite_mode */ #define OVERWRT_ALWAYS 1 #define OVERWRT_NEVER 2 #define IS_OVERWRT_ALL (G.overwrite_mode == OVERWRT_ALWAYS) #define IS_OVERWRT_NONE (G.overwrite_mode == OVERWRT_NEVER) #ifdef VMS /* return codes for VMS-specific open_outfile() function */ # define OPENOUT_OK 0 /* file openend normally */ # define OPENOUT_FAILED 1 /* file open failed */ # define OPENOUT_SKIPOK 2 /* file not opened, skip at error level OK */ # define OPENOUT_SKIPWARN 3 /* file not opened, skip at error level WARN */ #endif /* VMS */ #define ROOT 0 /* checkdir() extract-to path: called once */ #define INIT 1 /* allocate buildpath: called once per member */ #define APPEND_DIR 2 /* append a dir comp.: many times per member */ #define APPEND_NAME 3 /* append actual filename: once per member */ #define GETPATH 4 /* retrieve the complete path and free it */ #define END 5 /* free root path prior to exiting program */ /* version_made_by codes (central dir): make sure these */ /* are not defined on their respective systems!! */ #define FS_FAT_ 0 /* filesystem used by MS-DOS, OS/2, Win32 */ #define AMIGA_ 1 #define VMS_ 2 #define UNIX_ 3 #define VM_CMS_ 4 #define ATARI_ 5 /* what if it's a minix filesystem? [cjh] */ #define FS_HPFS_ 6 /* filesystem used by OS/2 (and NT 3.x) */ #define MAC_ 7 /* HFS filesystem used by MacOS */ #define Z_SYSTEM_ 8 #define CPM_ 9 #define TOPS20_ 10 #define FS_NTFS_ 11 /* filesystem used by Windows NT */ #define QDOS_ 12 #define ACORN_ 13 /* Archimedes Acorn RISC OS */ #define FS_VFAT_ 14 /* filesystem used by Windows 95, NT */ #define MVS_ 15 #define BEOS_ 16 /* hybrid POSIX/database filesystem */ #define TANDEM_ 17 /* Tandem NSK */ #define THEOS_ 18 /* THEOS */ #define MAC_OSX_ 19 /* Mac OS/X (Darwin) */ #define ATHEOS_ 30 /* AtheOS */ #define NUM_HOSTS 31 /* index of last system + 1 */ /* don't forget to update zipinfo.c appropiately if NUM_HOSTS changes! */ #define STORED 0 /* compression methods */ #define SHRUNK 1 #define REDUCED1 2 #define REDUCED2 3 #define REDUCED3 4 #define REDUCED4 5 #define IMPLODED 6 #define TOKENIZED 7 #define DEFLATED 8 #define ENHDEFLATED 9 #define DCLIMPLODED 10 #define BZIPPED 12 #define LZMAED 14 #define IBMTERSED 18 #define IBMLZ77ED 19 #define WAVPACKED 97 #define PPMDED 98 #define NUM_METHODS 17 /* number of known method IDs */ /* don't forget to update list.c (list_files()), extract.c and zipinfo.c * appropriately if NUM_METHODS changes */ /* (the PK-class error codes are public and have been moved into unzip.h) */ #define DF_MDY 0 /* date format 10/26/91 (USA only) */ #define DF_DMY 1 /* date format 26/10/91 (most of the world) */ #define DF_YMD 2 /* date format 91/10/26 (a few countries) */ /*--------------------------------------------------------------------------- Extra-field block ID values and offset info. ---------------------------------------------------------------------------*/ /* extra-field ID values, all little-endian: */ #define EF_PKSZ64 0x0001 /* PKWARE's 64-bit filesize extensions */ #define EF_AV 0x0007 /* PKWARE's authenticity verification */ #define EF_EFS 0x0008 /* PKWARE's extended language encoding */ #define EF_OS2 0x0009 /* OS/2 extended attributes */ #define EF_PKW32 0x000a /* PKWARE's Win95/98/WinNT filetimes */ #define EF_PKVMS 0x000c /* PKWARE's VMS */ #define EF_PKUNIX 0x000d /* PKWARE's Unix */ #define EF_PKFORK 0x000e /* PKWARE's future stream/fork descriptors */ #define EF_PKPATCH 0x000f /* PKWARE's patch descriptor */ #define EF_PKPKCS7 0x0014 /* PKWARE's PKCS#7 store for X.509 Certs */ #define EF_PKFX509 0x0015 /* PKWARE's file X.509 Cert&Signature ID */ #define EF_PKCX509 0x0016 /* PKWARE's central dir X.509 Cert ID */ #define EF_PKENCRHD 0x0017 /* PKWARE's Strong Encryption header */ #define EF_PKRMCTL 0x0018 /* PKWARE's Record Management Controls*/ #define EF_PKLSTCS7 0x0019 /* PKWARE's PKCS#7 Encr. Recipient Cert List */ #define EF_PKIBM 0x0065 /* PKWARE's IBM S/390 & AS/400 attributes */ #define EF_PKIBM2 0x0066 /* PKWARE's IBM S/390 & AS/400 compr. attribs */ #define EF_IZVMS 0x4d49 /* Info-ZIP's VMS ("IM") */ #define EF_IZUNIX 0x5855 /* Info-ZIP's first Unix[1] ("UX") */ #define EF_IZUNIX2 0x7855 /* Info-ZIP's second Unix[2] ("Ux") */ #define EF_IZUNIX3 0x7875 /* Info-ZIP's newest Unix[3] ("ux") */ #define EF_TIME 0x5455 /* universal timestamp ("UT") */ #define EF_UNIPATH 0x7075 /* Info-ZIP Unicode Path ("up") */ #define EF_UNICOMNT 0x6375 /* Info-ZIP Unicode Comment ("uc") */ #define EF_MAC3 0x334d /* Info-ZIP's new Macintosh (= "M3") */ #define EF_JLMAC 0x07c8 /* Johnny Lee's old Macintosh (= 1992) */ #define EF_ZIPIT 0x2605 /* Thomas Brown's Macintosh (ZipIt) */ #define EF_ZIPIT2 0x2705 /* T. Brown's Mac (ZipIt) v 1.3.8 and newer ? */ #define EF_SMARTZIP 0x4d63 /* Mac SmartZip by Marco Bambini */ #define EF_VMCMS 0x4704 /* Info-ZIP's VM/CMS ("\004G") */ #define EF_MVS 0x470f /* Info-ZIP's MVS ("\017G") */ #define EF_ACL 0x4c41 /* (OS/2) access control list ("AL") */ #define EF_NTSD 0x4453 /* NT security descriptor ("SD") */ #define EF_ATHEOS 0x7441 /* AtheOS ("At") */ #define EF_BEOS 0x6542 /* BeOS ("Be") */ #define EF_QDOS 0xfb4a /* SMS/QDOS ("J\373") */ #define EF_AOSVS 0x5356 /* AOS/VS ("VS") */ #define EF_SPARK 0x4341 /* David Pilling's Acorn/SparkFS ("AC") */ #define EF_TANDEM 0x4154 /* Tandem NSK ("TA") */ #define EF_THEOS 0x6854 /* Jean-Michel Dubois' Theos "Th" */ #define EF_THEOSO 0x4854 /* old Theos port */ #define EF_MD5 0x4b46 /* Fred Kantor's MD5 ("FK") */ #define EF_ASIUNIX 0x756e /* ASi's Unix ("nu") */ #define EB_HEADSIZE 4 /* length of extra field block header */ #define EB_ID 0 /* offset of block ID in header */ #define EB_LEN 2 /* offset of data length field in header */ #define EB_UCSIZE_P 0 /* offset of ucsize field in compr. data */ #define EB_CMPRHEADLEN 6 /* lenght of compression header */ #define EB_UX_MINLEN 8 /* minimal "UX" field contains atime, mtime */ #define EB_UX_FULLSIZE 12 /* full "UX" field (atime, mtime, uid, gid) */ #define EB_UX_ATIME 0 /* offset of atime in "UX" extra field data */ #define EB_UX_MTIME 4 /* offset of mtime in "UX" extra field data */ #define EB_UX_UID 8 /* byte offset of UID in "UX" field data */ #define EB_UX_GID 10 /* byte offset of GID in "UX" field data */ #define EB_UX2_MINLEN 4 /* minimal "Ux" field contains UID/GID */ #define EB_UX2_UID 0 /* byte offset of UID in "Ux" field data */ #define EB_UX2_GID 2 /* byte offset of GID in "Ux" field data */ #define EB_UX2_VALID (1 << 8) /* UID/GID present */ #define EB_UX3_MINLEN 7 /* minimal "ux" field size (2-byte UID/GID) */ #define EB_UT_MINLEN 1 /* minimal UT field contains Flags byte */ #define EB_UT_FLAGS 0 /* byte offset of Flags field */ #define EB_UT_TIME1 1 /* byte offset of 1st time value */ #define EB_UT_FL_MTIME (1 << 0) /* mtime present */ #define EB_UT_FL_ATIME (1 << 1) /* atime present */ #define EB_UT_FL_CTIME (1 << 2) /* ctime present */ #define EB_FLGS_OFFS 4 /* offset of flags area in generic compressed extra field blocks (BEOS, MAC, and others) */ #define EB_OS2_HLEN 4 /* size of OS2/ACL compressed data header */ #define EB_BEOS_HLEN 5 /* length of BeOS&AtheOS e.f attribute header */ #define EB_BE_FL_UNCMPR 0x01 /* "BeOS&AtheOS attribs uncompr." bit flag */ #define EB_MAC3_HLEN 14 /* length of Mac3 attribute block header */ #define EB_SMARTZIP_HLEN 64 /* fixed length of the SmartZip extra field */ #define EB_M3_FL_DATFRK 0x01 /* "this entry is data fork" flag */ #define EB_M3_FL_UNCMPR 0x04 /* "Mac3 attributes uncompressed" bit flag */ #define EB_M3_FL_TIME64 0x08 /* "Mac3 time fields are 64 bit wide" flag */ #define EB_M3_FL_NOUTC 0x10 /* "Mac3 timezone offset fields missing" flag */ #define EB_NTSD_C_LEN 4 /* length of central NT security data */ #define EB_NTSD_L_LEN 5 /* length of minimal local NT security data */ #define EB_NTSD_VERSION 4 /* offset of NTSD version byte */ #define EB_NTSD_MAX_VER (0) /* maximum version # we know how to handle */ #define EB_ASI_CRC32 0 /* offset of ASI Unix field's crc32 checksum */ #define EB_ASI_MODE 4 /* offset of ASI Unix permission mode field */ #define EB_IZVMS_HLEN 12 /* length of IZVMS attribute block header */ #define EB_IZVMS_FLGS 4 /* offset of compression type flag */ #define EB_IZVMS_UCSIZ 6 /* offset of ucsize field in IZVMS header */ #define EB_IZVMS_BCMASK 07 /* 3 bits for compression type */ #define EB_IZVMS_BCSTOR 0 /* Stored */ #define EB_IZVMS_BC00 1 /* 0byte -> 0bit compression */ #define EB_IZVMS_BCDEFL 2 /* Deflated */ /*--------------------------------------------------------------------------- True sizes of the various headers (excluding their 4-byte signatures), as defined by PKWARE--so it is not likely that these will ever change. But if they do, make sure both these defines AND the typedefs below get updated accordingly. 12/27/2006 The Zip64 End Of Central Directory record is variable size and now comes in two flavors, version 1 and the new version 2 that supports central directory encryption. We only use the old fields at the top of the Zip64 EOCDR, and this block is a fixed size still, but need to be aware of the stuff following. ---------------------------------------------------------------------------*/ #define LREC_SIZE 26 /* lengths of local file headers, central */ #define CREC_SIZE 42 /* directory headers, end-of-central-dir */ #define ECREC_SIZE 18 /* record, zip64 end-of-cent-dir locator */ #define ECLOC64_SIZE 16 /* and zip64 end-of-central-dir record, */ #define ECREC64_SIZE 52 /* respectively */ #define MAX_BITS 13 /* used in unshrink() */ #define HSIZE (1 << MAX_BITS) /* size of global work area */ #define LF 10 /* '\n' on ASCII machines; must be 10 due to EBCDIC */ #define CR 13 /* '\r' on ASCII machines; must be 13 due to EBCDIC */ #define CTRLZ 26 /* DOS & OS/2 EOF marker (used in fileio.c, vms.c) */ #ifdef EBCDIC # define foreign(c) ascii[(uch)(c)] # define native(c) ebcdic[(uch)(c)] # define NATIVE "EBCDIC" # define NOANSIFILT #endif #ifdef VMS # define ENV_UNZIP "UNZIP_OPTS" /* names of environment variables */ # define ENV_ZIPINFO "ZIPINFO_OPTS" #endif /* VMS */ #ifdef RISCOS # define ENV_UNZIP "Unzip$Options" # define ENV_ZIPINFO "Zipinfo$Options" # define ENV_UNZIPEXTS "Unzip$Exts" #endif /* RISCOS */ #ifndef ENV_UNZIP # define ENV_UNZIP "UNZIP" /* the standard names */ # define ENV_ZIPINFO "ZIPINFO" #endif #define ENV_UNZIP2 "UNZIPOPT" /* alternate names, for zip compat. */ #define ENV_ZIPINFO2 "ZIPINFOOPT" #if (!defined(QQ) && !defined(NOQQ)) # define QQ #endif #ifdef QQ /* Newtware version: no file */ # define QCOND (!uO.qflag) /* comments with -vq or -vqq */ #else /* Bill Davidsen version: no way to */ # define QCOND (longhdr) /* kill file comments when listing */ #endif #ifdef OLD_QQ # define QCOND2 (uO.qflag < 2) #else # define QCOND2 (!uO.qflag) #endif #ifdef WILD_STOP_AT_DIR # define __WDLPRO , int sepc # define __WDL , sepc # define __WDLDEF int sepc; # define WISEP , (uO.W_flag ? '/' : '\0') #else # define __WDLPRO # define __WDL # define __WDLDEF # define WISEP #endif /**************/ /* Typedefs */ /**************/ #ifdef ZIP64_SUPPORT # ifndef Z_UINT8_DEFINED # if (defined(__GNUC__) || defined(__hpux) || defined(__SUNPRO_C)) typedef unsigned long long z_uint8; # else typedef unsigned __int64 z_uint8; # endif # define Z_UINT8_DEFINED # endif #endif #ifndef Z_UINT4_DEFINED # if (defined(MODERN) && !defined(NO_LIMITS_H)) # if (defined(UINT_MAX) && (UINT_MAX == 0xffffffffUL)) typedef unsigned int z_uint4; # define Z_UINT4_DEFINED # else # if (defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL)) typedef unsigned long z_uint4; # define Z_UINT4_DEFINED # else # if (defined(USHRT_MAX) && (USHRT_MAX == 0xffffffffUL)) typedef unsigned short z_uint4; # define Z_UINT4_DEFINED # endif # endif # endif # endif /* MODERN && !NO_LIMITS_H */ #endif /* !Z_UINT4_DEFINED */ #ifndef Z_UINT4_DEFINED typedef ulg z_uint4; # define Z_UINT4_DEFINED #endif /* The following three user-defined unsigned integer types are used for holding zipfile entities (required widths without / with Zip64 support): a) sizes and offset of zipfile entries (4 bytes / 8 bytes) b) enumeration and counts of zipfile entries (2 bytes / 8 bytes) Remark: internally, we use 4 bytes for archive member counting in the No-Zip64 case, because UnZip supports more than 64k entries for classic Zip archives without Zip64 extensions. c) enumeration and counts of zipfile volumes of multivolume archives (2 bytes / 4 bytes) */ #ifdef ZIP64_SUPPORT typedef z_uint8 zusz_t; /* zipentry sizes & offsets */ typedef z_uint8 zucn_t; /* archive entry counts */ typedef z_uint4 zuvl_t; /* multivolume numbers */ # define MASK_ZUCN64 (~(zucn_t)0) /* In case we ever get to support an environment where z_uint8 may be WIDER than 64 bit wide, we will have to apply a construct similar to #define MASK_ZUCN64 (~(zucn_t)0 & (zucn_t)0xffffffffffffffffULL) for the 64-bit mask. */ #else typedef ulg zusz_t; /* zipentry sizes & offsets */ typedef unsigned int zucn_t; /* archive entry counts */ typedef unsigned short zuvl_t; /* multivolume numbers */ # define MASK_ZUCN64 (~(zucn_t)0) #endif #define MASK_ZUCN16 ((zucn_t)0xFFFF) #ifdef NO_UID_GID # ifdef UID_USHORT typedef unsigned short uid_t; /* TI SysV.3 */ typedef unsigned short gid_t; # else typedef unsigned int uid_t; /* SCO Xenix */ typedef unsigned int gid_t; # endif #endif #if (defined(GOT_UTIMBUF) || defined(sgi) || defined(ATARI)) typedef struct utimbuf ztimbuf; #else typedef struct ztimbuf { time_t actime; /* new access time */ time_t modtime; /* new modification time */ } ztimbuf; #endif typedef struct iztimes { time_t atime; /* new access time */ time_t mtime; /* new modification time */ time_t ctime; /* used for creation time; NOT same as st_ctime */ } iztimes; #ifdef SET_DIR_ATTRIB typedef struct direntry { /* head of system-specific struct holding */ struct direntry *next; /* defered directory attributes info */ char *fn; /* filename of directory */ char buf[1]; /* start of system-specific internal data */ } direntry; #endif /* SET_DIR_ATTRIB */ #ifdef SYMLINKS typedef struct slinkentry { /* info for deferred symlink creation */ struct slinkentry *next; /* pointer to next entry in chain */ extent targetlen; /* length of target filespec */ extent attriblen; /* length of system-specific attrib data */ char *target; /* pointer to target filespec */ char *fname; /* pointer to name of link */ char buf[1]; /* data/name/link buffer */ } slinkentry; #endif /* SYMLINKS */ typedef struct min_info { zoff_t offset; zusz_t compr_size; /* compressed size (needed if extended header) */ zusz_t uncompr_size; /* uncompressed size (needed if extended header) */ ulg crc; /* crc (needed if extended header) */ zuvl_t diskstart; /* no of volume where this entry starts */ uch hostver; uch hostnum; unsigned file_attr; /* local flavor, as used by creat(), chmod()... */ unsigned encrypted : 1; /* file encrypted: decrypt before uncompressing */ unsigned ExtLocHdr : 1; /* use time instead of CRC for decrypt check */ unsigned textfile : 1; /* file is text (according to zip) */ unsigned textmode : 1; /* file is to be extracted as text */ unsigned lcflag : 1; /* convert filename to lowercase */ unsigned vollabel : 1; /* "file" is an MS-DOS volume (disk) label */ #ifdef SYMLINKS unsigned symlink : 1; /* file is a symbolic link */ #endif unsigned HasUxAtt : 1; /* crec ext_file_attr has Unix style mode bits */ #ifdef UNICODE_SUPPORT unsigned GPFIsUTF8: 1; /* crec gen_purpose_flag UTF-8 bit 11 is set */ #endif #ifndef SFX char Far *cfilname; /* central header version of filename */ #endif } min_info; typedef struct VMStimbuf { char *revdate; /* (both roughly correspond to Unix modtime/st_mtime) */ char *credate; } VMStimbuf; /*--------------------------------------------------------------------------- Zipfile work area declarations. ---------------------------------------------------------------------------*/ #ifdef MALLOC_WORK union work { struct { /* unshrink(): */ shrint *Parent; /* pointer to (8192 * sizeof(shrint)) */ uch *value; /* pointer to 8KB char buffer */ uch *Stack; /* pointer to another 8KB char buffer */ } shrink; uch *Slide; /* explode(), inflate(), unreduce() */ }; #else /* !MALLOC_WORK */ union work { struct { /* unshrink(): */ shrint Parent[HSIZE]; /* (8192 * sizeof(shrint)) == 16KB minimum */ uch value[HSIZE]; /* 8KB */ uch Stack[HSIZE]; /* 8KB */ } shrink; /* total = 32KB minimum; 80KB on Cray/Alpha */ uch Slide[WSIZE]; /* explode(), inflate(), unreduce() */ }; #endif /* ?MALLOC_WORK */ #define slide G.area.Slide #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) # define redirSlide G.redirect_sldptr #else # define redirSlide G.area.Slide #endif /*--------------------------------------------------------------------------- Zipfile layout declarations. If these headers ever change, make sure the xxREC_SIZE defines (above) change with them! ---------------------------------------------------------------------------*/ typedef uch local_byte_hdr[ LREC_SIZE ]; # define L_VERSION_NEEDED_TO_EXTRACT_0 0 # define L_VERSION_NEEDED_TO_EXTRACT_1 1 # define L_GENERAL_PURPOSE_BIT_FLAG 2 # define L_COMPRESSION_METHOD 4 # define L_LAST_MOD_DOS_DATETIME 6 # define L_CRC32 10 # define L_COMPRESSED_SIZE 14 # define L_UNCOMPRESSED_SIZE 18 # define L_FILENAME_LENGTH 22 # define L_EXTRA_FIELD_LENGTH 24 typedef uch cdir_byte_hdr[ CREC_SIZE ]; # define C_VERSION_MADE_BY_0 0 # define C_VERSION_MADE_BY_1 1 # define C_VERSION_NEEDED_TO_EXTRACT_0 2 # define C_VERSION_NEEDED_TO_EXTRACT_1 3 # define C_GENERAL_PURPOSE_BIT_FLAG 4 # define C_COMPRESSION_METHOD 6 # define C_LAST_MOD_DOS_DATETIME 8 # define C_CRC32 12 # define C_COMPRESSED_SIZE 16 # define C_UNCOMPRESSED_SIZE 20 # define C_FILENAME_LENGTH 24 # define C_EXTRA_FIELD_LENGTH 26 # define C_FILE_COMMENT_LENGTH 28 # define C_DISK_NUMBER_START 30 # define C_INTERNAL_FILE_ATTRIBUTES 32 # define C_EXTERNAL_FILE_ATTRIBUTES 34 # define C_RELATIVE_OFFSET_LOCAL_HEADER 38 typedef uch ec_byte_rec[ ECREC_SIZE+4 ]; /* define SIGNATURE 0 space-holder only */ # define NUMBER_THIS_DISK 4 # define NUM_DISK_WITH_START_CEN_DIR 6 # define NUM_ENTRIES_CEN_DIR_THS_DISK 8 # define TOTAL_ENTRIES_CENTRAL_DIR 10 # define SIZE_CENTRAL_DIRECTORY 12 # define OFFSET_START_CENTRAL_DIRECTORY 16 # define ZIPFILE_COMMENT_LENGTH 20 typedef uch ec_byte_loc64[ ECLOC64_SIZE+4 ]; # define NUM_DISK_START_EOCDR64 4 # define OFFSET_START_EOCDR64 8 # define NUM_THIS_DISK_LOC64 16 typedef uch ec_byte_rec64[ ECREC64_SIZE+4 ]; # define ECREC64_LENGTH 4 # define EC_VERSION_MADE_BY_0 12 # define EC_VERSION_NEEDED_0 14 # define NUMBER_THIS_DSK_REC64 16 # define NUM_DISK_START_CEN_DIR64 20 # define NUM_ENTRIES_CEN_DIR_THS_DISK64 24 # define TOTAL_ENTRIES_CENTRAL_DIR64 32 # define SIZE_CENTRAL_DIRECTORY64 40 # define OFFSET_START_CENTRAL_DIRECT64 48 /* The following structs are used to hold all header data of a zip entry. Traditionally, the structs' layouts followed the data layout of the corresponding zipfile header structures. However, the zipfile header layouts were designed in the old ages of 16-bit CPUs, they are subject to structure padding and/or alignment issues on newer systems with a "natural word width" of more than 2 bytes. Please note that the structure members are now reordered by size (top-down), to prevent internal padding and optimize memory usage! */ typedef struct local_file_header { /* LOCAL */ zusz_t csize; zusz_t ucsize; ulg last_mod_dos_datetime; ulg crc32; uch version_needed_to_extract[2]; ush general_purpose_bit_flag; ush compression_method; ush filename_length; ush extra_field_length; } local_file_hdr; typedef struct central_directory_file_header { /* CENTRAL */ zusz_t csize; zusz_t ucsize; zusz_t relative_offset_local_header; ulg last_mod_dos_datetime; ulg crc32; ulg external_file_attributes; zuvl_t disk_number_start; ush internal_file_attributes; uch version_made_by[2]; uch version_needed_to_extract[2]; ush general_purpose_bit_flag; ush compression_method; ush filename_length; ush extra_field_length; ush file_comment_length; } cdir_file_hdr; typedef struct end_central_dir_record { /* END CENTRAL */ zusz_t size_central_directory; zusz_t offset_start_central_directory; zucn_t num_entries_centrl_dir_ths_disk; zucn_t total_entries_central_dir; zuvl_t number_this_disk; zuvl_t num_disk_start_cdir; int have_ecr64; /* valid Zip64 ecdir-record exists */ int is_zip64_archive; /* Zip64 ecdir-record is mandatory */ ush zipfile_comment_length; } ecdir_rec; /* Huffman code lookup table entry--this entry is four bytes for machines that have 16-bit pointers (e.g. PC's in the small or medium model). Valid extra bits are 0..16. e == 31 is EOB (end of block), e == 32 means that v is a literal, 32 < e < 64 means that v is a pointer to the next table, which codes (e & 31) bits, and lastly e == 99 indicates an unused code. If a code with e == 99 is looked up, this implies an error in the data. */ struct huft { uch e; /* number of extra bits or operation */ uch b; /* number of bits in this code or subcode */ union { ush n; /* literal, length base, or distance base */ struct huft *t; /* pointer to next level of table */ } v; }; typedef struct _APIDocStruct { char *compare; char *function; char *syntax; char *purpose; } APIDocStruct; /*************/ /* Globals */ /*************/ #if (defined(OS2) && !defined(FUNZIP)) # include "os2/os2data.h" #endif #include "globals.h" /*************************/ /* Function Prototypes */ /*************************/ /*--------------------------------------------------------------------------- Functions in unzip.c (initialization routines): ---------------------------------------------------------------------------*/ #ifndef WINDLL int MAIN OF((int argc, char **argv)); int unzip OF((__GPRO__ int argc, char **argv)); int uz_opts OF((__GPRO__ int *pargc, char ***pargv)); int usage OF((__GPRO__ int error)); #endif /* !WINDLL */ /*--------------------------------------------------------------------------- Functions in process.c (main driver routines): ---------------------------------------------------------------------------*/ int process_zipfiles OF((__GPRO)); void free_G_buffers OF((__GPRO)); /* static int do_seekable OF((__GPRO__ int lastchance)); */ /* static int find_ecrec OF((__GPRO__ long searchlen)); */ /* static int process_central_comment OF((__GPRO)); */ int process_cdir_file_hdr OF((__GPRO)); int process_local_file_hdr OF((__GPRO)); int getZip64Data OF((__GPRO__ ZCONST uch *ef_buf, unsigned ef_len)); #ifdef UNICODE_SUPPORT int getUnicodeData OF((__GPRO__ ZCONST uch *ef_buf, unsigned ef_len)); #endif unsigned ef_scan_for_izux OF((ZCONST uch *ef_buf, unsigned ef_len, int ef_is_c, ulg dos_mdatetime, iztimes *z_utim, ulg *z_uidgid)); #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS)) zvoid *getRISCOSexfield OF((ZCONST uch *ef_buf, unsigned ef_len)); #endif #ifndef SFX /*--------------------------------------------------------------------------- Functions in zipinfo.c (`zipinfo-style' listing routines): ---------------------------------------------------------------------------*/ #ifndef NO_ZIPINFO #ifndef WINDLL int zi_opts OF((__GPRO__ int *pargc, char ***pargv)); #endif void zi_end_central OF((__GPRO)); int zipinfo OF((__GPRO)); /* static int zi_long OF((__GPRO__ zusz_t *pEndprev)); */ /* static int zi_short OF((__GPRO)); */ /* static char *zi_time OF((__GPRO__ ZCONST ulg *datetimez, ZCONST time_t *modtimez, char *d_t_str));*/ #endif /* !NO_ZIPINFO */ /*--------------------------------------------------------------------------- Functions in list.c (generic zipfile-listing routines): ---------------------------------------------------------------------------*/ int list_files OF((__GPRO)); #ifdef TIMESTAMP int get_time_stamp OF((__GPRO__ time_t *last_modtime, ulg *nmember)); #endif int ratio OF((zusz_t uc, zusz_t c)); void fnprint OF((__GPRO)); #endif /* !SFX */ /*--------------------------------------------------------------------------- Functions in fileio.c: ---------------------------------------------------------------------------*/ int open_input_file OF((__GPRO)); int open_outfile OF((__GPRO)); /* also vms.c */ void undefer_input OF((__GPRO)); void defer_leftover_input OF((__GPRO)); unsigned readbuf OF((__GPRO__ char *buf, register unsigned len)); int readbyte OF((__GPRO)); int fillinbuf OF((__GPRO)); int seek_zipf OF((__GPRO__ zoff_t abs_offset)); #ifdef FUNZIP int flush OF((__GPRO__ ulg size)); /* actually funzip.c */ #else int flush OF((__GPRO__ uch *buf, ulg size, int unshrink)); #endif /* static int disk_error OF((__GPRO)); */ void handler OF((int signal)); time_t dos_to_unix_time OF((ulg dos_datetime)); int check_for_newer OF((__GPRO__ char *filename)); /* os2,vmcms,vms */ int do_string OF((__GPRO__ unsigned int length, int option)); ush makeword OF((ZCONST uch *b)); ulg makelong OF((ZCONST uch *sig)); zusz_t makeint64 OF((ZCONST uch *sig)); char *fzofft OF((__GPRO__ zoff_t val, ZCONST char *pre, ZCONST char *post)); #if (!defined(STR_TO_ISO) || defined(NEED_STR2ISO)) char *str2iso OF((char *dst, ZCONST char *src)); #endif #if (!defined(STR_TO_OEM) || defined(NEED_STR2OEM)) char *str2oem OF((char *dst, ZCONST char *src)); #endif #ifdef NO_STRNICMP int zstrnicmp OF((register ZCONST char *s1, register ZCONST char *s2, register unsigned n)); #endif #ifdef REGULUS int zstat OF((ZCONST char *p, struct stat *s)); #endif #ifdef ZMEM /* MUST be ifdef'd because of conflicts with the standard def. */ zvoid *memset OF((register zvoid *, register int, register unsigned int)); int memcmp OF((register ZCONST zvoid*, register ZCONST zvoid *, register unsigned int)); zvoid *memcpy OF((register zvoid *, register ZCONST zvoid *, register unsigned int)); #endif #ifdef NEED_UZMBCLEN extent uzmbclen OF((ZCONST unsigned char *ptr)); #endif #ifdef NEED_UZMBSCHR unsigned char *uzmbschr OF((ZCONST unsigned char *str, unsigned int c)); #endif #ifdef NEED_UZMBSRCHR unsigned char *uzmbsrchr OF((ZCONST unsigned char *str, unsigned int c)); #endif #ifdef SMALL_MEM char *fLoadFarString OF((__GPRO__ const char Far *sz)); char *fLoadFarStringSmall OF((__GPRO__ const char Far *sz)); char *fLoadFarStringSmall2 OF((__GPRO__ const char Far *sz)); #ifndef zfstrcpy char Far * Far zfstrcpy OF((char Far *s1, const char Far *s2)); #endif #if (!defined(SFX) && !defined(zfstrcmp)) int Far zfstrcmp OF((const char Far *s1, const char Far *s2)); #endif #endif /*--------------------------------------------------------------------------- Functions in extract.c: ---------------------------------------------------------------------------*/ int extract_or_test_files OF((__GPRO)); /* static int store_info OF((void)); */ /* static int extract_or_test_member OF((__GPRO)); */ /* static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len)); */ /* static int test_OS2 OF((__GPRO__ uch *eb, unsigned eb_size)); */ /* static int test_NT OF((__GPRO__ uch *eb, unsigned eb_size)); */ #ifndef SFX unsigned find_compr_idx OF((unsigned compr_methodnum)); #endif int memextract OF((__GPRO__ uch *tgt, ulg tgtsize, ZCONST uch *src, ulg srcsize)); int memflush OF((__GPRO__ ZCONST uch *rawbuf, ulg size)); #if (defined(VMS) || defined(VMS_TEXT_CONV)) uch *extract_izvms_block OF((__GPRO__ ZCONST uch *ebdata, unsigned size, unsigned *retlen, ZCONST uch *init, unsigned needlen)); #endif char *fnfilter OF((ZCONST char *raw, uch *space, extent size)); /*--------------------------------------------------------------------------- Decompression functions: ---------------------------------------------------------------------------*/ #if (!defined(SFX) && !defined(FUNZIP)) int explode OF((__GPRO)); /* explode.c */ #endif int huft_free OF((struct huft *t)); /* inflate.c */ int huft_build OF((__GPRO__ ZCONST unsigned *b, unsigned n, unsigned s, ZCONST ush *d, ZCONST uch *e, struct huft **t, unsigned *m)); #ifdef USE_ZLIB int UZinflate OF((__GPRO__ int is_defl64)); /* inflate.c */ # define inflate_free(x) inflateEnd(&((Uz_Globs *)(&G))->dstrm) #else int inflate OF((__GPRO__ int is_defl64)); /* inflate.c */ int inflate_free OF((__GPRO)); /* inflate.c */ #endif /* ?USE_ZLIB */ #if (!defined(SFX) && !defined(FUNZIP)) #ifndef COPYRIGHT_CLEAN int unreduce OF((__GPRO)); /* unreduce.c */ /* static void LoadFollowers OF((__GPRO__ f_array *follower, uch *Slen)); * unreduce.c */ #endif /* !COPYRIGHT_CLEAN */ #ifndef LZW_CLEAN int unshrink OF((__GPRO)); /* unshrink.c */ /* static void partial_clear OF((__GPRO)); * unshrink.c */ #endif /* !LZW_CLEAN */ #endif /* !SFX && !FUNZIP */ #ifdef USE_BZIP2 int UZbunzip2 OF((__GPRO)); /* extract.c */ void bz_internal_error OF((int bzerrcode)); /* ubz2err.c */ #endif /*--------------------------------------------------------------------------- Internal API functions (only included in DLL versions): ---------------------------------------------------------------------------*/ #ifdef DLL void setFileNotFound OF((__GPRO)); /* api.c */ int unzipToMemory OF((__GPRO__ char *zip, char *file, UzpBuffer *retstr)); /* api.c */ int redirect_outfile OF((__GPRO)); /* api.c */ int writeToMemory OF((__GPRO__ ZCONST uch *rawbuf, extent size)); /* api.c */ int close_redirect OF((__GPRO)); /* api.c */ /* this obsolescent entry point kept for compatibility: */ int UzpUnzip OF((int argc, char **argv));/* use UzpMain */ #ifdef OS2DLL int varmessage OF((__GPRO__ ZCONST uch *buf, ulg size)); int varputchar OF((__GPRO__ int c)); /* rexxapi.c */ int finish_REXX_redirect OF((__GPRO)); /* rexxapi.c */ #endif #ifdef API_DOC void APIhelp OF((__GPRO__ int argc, char **argv)); #endif /* apihelp.c */ #endif /* DLL */ /*--------------------------------------------------------------------------- MSDOS-only functions: ---------------------------------------------------------------------------*/ #ifdef MSDOS #if (!defined(FUNZIP) && !defined(SFX) && !defined(WINDLL)) void check_for_windows OF((ZCONST char *app)); /* msdos.c */ #endif #if (defined(__GO32__) || defined(__EMX__)) unsigned _dos_getcountryinfo(void *); /* msdos.c */ #if (!defined(__DJGPP__) || (__DJGPP__ < 2)) unsigned _dos_setftime(int, unsigned, unsigned); /* msdos.c */ unsigned _dos_setfileattr(const char *, unsigned); /* msdos.c */ unsigned _dos_creat(const char *, unsigned, int *); /* msdos.c */ void _dos_getdrive(unsigned *); /* msdos.c */ unsigned _dos_close(int); /* msdos.c */ #endif /* !__DJGPP__ || (__DJGPP__ < 2) */ #endif /* __GO32__ || __EMX__ */ #endif /*--------------------------------------------------------------------------- OS/2-only functions: ---------------------------------------------------------------------------*/ #ifdef OS2 /* GetFileTime conflicts with something in Win32 header files */ #if (defined(REENTRANT) && defined(USETHREADID)) ulg GetThreadId OF((void)); #endif int GetCountryInfo OF((void)); /* os2.c */ long GetFileTime OF((ZCONST char *name)); /* os2.c */ /* static void SetPathAttrTimes OF((__GPRO__ int flags, int dir)); os2.c */ /* static int SetEAs OF((__GPRO__ const char *path, void *eablock)); os2.c */ /* static int SetACL OF((__GPRO__ const char *path, void *eablock)); os2.c */ /* static int IsFileNameValid OF((const char *name)); os2.c */ /* static void map2fat OF((char *pathcomp, char **pEndFAT)); os2.c */ /* static int SetLongNameEA OF((char *name, char *longname)); os2.c */ /* static void InitNLS OF((void)); os2.c */ int IsUpperNLS OF((int nChr)); /* os2.c */ int ToLowerNLS OF((int nChr)); /* os2.c */ void DebugMalloc OF((void)); /* os2.c */ #endif /*--------------------------------------------------------------------------- QDOS-only functions: ---------------------------------------------------------------------------*/ #ifdef QDOS int QMatch (uch, uch); void QFilename (__GPRO__ char *); char *Qstrfix (char *); int QReturn (int zip_error); #endif /*--------------------------------------------------------------------------- TOPS20-only functions: ---------------------------------------------------------------------------*/ #ifdef TOPS20 int upper OF((char *s)); /* tops20.c */ int enquote OF((char *s)); /* tops20.c */ int dequote OF((char *s)); /* tops20.c */ int fnlegal OF(()); /* error if prototyped? */ /* tops20.c */ #endif /*--------------------------------------------------------------------------- VM/CMS- and MVS-only functions: ---------------------------------------------------------------------------*/ #ifdef CMS_MVS extent getVMMVSexfield OF((char *type, uch *ef_block, unsigned datalen)); FILE *vmmvs_open_infile OF((__GPRO)); /* vmmvs.c */ void close_infile OF((__GPRO)); /* vmmvs.c */ #endif /*--------------------------------------------------------------------------- VMS-only functions: ---------------------------------------------------------------------------*/ #ifdef VMS int check_format OF((__GPRO)); /* vms.c */ /* int open_outfile OF((__GPRO)); * (see fileio.c) vms.c */ /* int flush OF((__GPRO__ uch *rawbuf, unsigned size, int final_flag)); * (see fileio.c) vms.c */ char *vms_msg_text OF((void)); /* vms.c */ #ifdef RETURN_CODES void return_VMS OF((__GPRO__ int zip_error)); /* vms.c */ #else void return_VMS OF((int zip_error)); /* vms.c */ #endif #ifdef VMSCLI ulg vms_unzip_cmdline OF((int *, char ***)); /* cmdline.c */ int VMSCLI_usage OF((__GPRO__ int error)); /* cmdline.c */ #endif #endif /*--------------------------------------------------------------------------- WIN32-only functions: ---------------------------------------------------------------------------*/ #ifdef WIN32 int IsWinNT OF((void)); /* win32.c */ #ifdef NTSD_EAS void process_defer_NT OF((__GPRO)); /* win32.c */ int test_NTSD OF((__GPRO__ uch *eb, unsigned eb_size, uch *eb_ucptr, ulg eb_ucsize)); /* win32.c */ # define TEST_NTSD test_NTSD #endif #ifdef W32_STAT_BANDAID int zstat_win32 OF((__W32STAT_GLOBALS__ const char *path, z_stat *buf)); /* win32.c */ #endif #endif /*--------------------------------------------------------------------------- Miscellaneous/shared functions: ---------------------------------------------------------------------------*/ Uz_Globs *globalsCtor OF((void)); /* globals.c */ int envargs OF((int *Pargc, char ***Pargv, ZCONST char *envstr, ZCONST char *envstr2)); /* envargs.c */ void mksargs OF((int *argcp, char ***argvp)); /* envargs.c */ int match OF((ZCONST char *s, ZCONST char *p, int ic __WDLPRO)); /* match.c */ int iswild OF((ZCONST char *p)); /* match.c */ /* declarations of public CRC-32 functions have been moved into crc32.h (free_crc_table(), get_crc_table(), crc32()) crc32.c */ int dateformat OF((void)); /* local */ char dateseparator OF((void)); /* local */ #ifndef WINDLL void version OF((__GPRO)); /* local */ #endif int mapattr OF((__GPRO)); /* local */ int mapname OF((__GPRO__ int renamed)); /* local */ int checkdir OF((__GPRO__ char *pathcomp, int flag)); /* local */ char *do_wild OF((__GPRO__ ZCONST char *wildzipfn)); /* local */ char *GetLoadPath OF((__GPRO)); /* local */ #if (defined(MORE) && (defined(ATH_BEO_UNX) || defined(QDOS) || defined(VMS))) int screensize OF((int *tt_rows, int *tt_cols)); /* local */ # if defined(VMS) int screenlinewrap OF((void)); /* local */ # endif #endif /* MORE && (ATH_BEO_UNX || QDOS || VMS) */ #ifdef OS2_W32 int SetFileSize OF((FILE *file, zusz_t filesize)); /* local */ #endif #ifndef MTS /* macro in MTS */ void close_outfile OF((__GPRO)); /* local */ #endif #ifdef SET_SYMLINK_ATTRIBS int set_symlnk_attribs OF((__GPRO__ slinkentry *slnk_entry)); /* local */ #endif #ifdef SET_DIR_ATTRIB int defer_dir_attribs OF((__GPRO__ direntry **pd)); /* local */ int set_direc_attribs OF((__GPRO__ direntry *d)); /* local */ #endif #ifdef TIMESTAMP # ifdef WIN32 int stamp_file OF((__GPRO__ ZCONST char *fname, time_t modtime)); /* local */ # else int stamp_file OF((ZCONST char *fname, time_t modtime)); /* local */ # endif #endif #ifdef NEED_ISO_OEM_INIT void prepare_ISO_OEM_translat OF((__GPRO)); /* local */ #endif #if (defined(MALLOC_WORK) && defined(MY_ZCALLOC)) zvoid far *zcalloc OF((unsigned int, unsigned int)); zvoid zcfree OF((zvoid far *)); #endif /* MALLOC_WORK && MY_ZCALLOC */ #ifdef SYSTEM_SPECIFIC_CTOR void SYSTEM_SPECIFIC_CTOR OF((__GPRO)); /* local */ #endif #ifdef SYSTEM_SPECIFIC_DTOR void SYSTEM_SPECIFIC_DTOR OF((__GPRO)); /* local */ #endif /************/ /* Macros */ /************/ #ifndef MAX # define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif #ifndef MIN # define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif #ifdef DEBUG # if (defined(THEOS) && defined(NO_BOGUS_SPC)) # define NO_DEBUG_IN_MACROS # define Trace(x) _fprintf x # else # define Trace(x) fprintf x # endif #else # define Trace(x) #endif #ifdef DEBUG_TIME # define TTrace(x) fprintf x #else # define TTrace(x) #endif #ifdef NO_DEBUG_IN_MACROS # define MTrace(x) #else # define MTrace(x) Trace(x) #endif #if (defined(UNIX) || defined(T20_VMS)) /* generally old systems */ # define ToLower(x) ((char)(isupper((int)x)? tolower((int)x) : x)) #else # define ToLower tolower /* assumed "smart"; used in match() */ #endif #ifdef USE_STRM_INPUT /* ``Replace'' the unbuffered UNIX style I/O function with similar * standard C functions from . */ # define read(fd,buf,n) fread((buf),1,(n),(FILE *)(fd)) # ifdef zlseek # undef zlseek # endif # define zlseek(fd,o,w) zfseeko((FILE *)(fd),(o),(w)) # define close(fd) fclose((FILE *)(fd)) #endif /* USE_STRM_INPUT */ /* The return value of the Info() "macro function" is never checked in * UnZip. Otherwise, to get the same behaviour as for (*G.message)(), the * Info() definition for "FUNZIP" would have to be corrected: * #define Info(buf,flag,sprf_arg) \ * (fputs((char *)(sprintf sprf_arg, (buf)), \ * (flag)&1? stderr : stdout) < 0) */ static inline void noop(void) {} #define Info(...) noop() #ifndef Info /* may already have been defined for redirection */ # ifdef FUNZIP # define Info(buf,flag,sprf_arg) \ fputs((char *)(sprintf sprf_arg, (buf)), (flag)&1? stderr : stdout) # else # ifdef INT_SPRINTF /* optimized version for "int sprintf()" flavour */ # define Info(buf,flag,sprf_arg) \ (*G.message)((zvoid *)&G, (uch *)(buf), (ulg)sprintf sprf_arg, (flag)) # else /* generic version, does not use sprintf() return value */ # define Info(buf,flag,sprf_arg) \ (*G.message)((zvoid *)&G, (uch *)(buf), \ (ulg)(sprintf sprf_arg, strlen((char *)(buf))), (flag)) # endif # endif #endif /* !Info */ /* This wrapper macro around fzofft() is just defined to "hide" the * argument needed to reference the global storage buffers. */ #define FmZofft(val, pre, post) fzofft(__G__ val, pre, post) /* The following macro wrappers around the fnfilter function are used many * times to prepare archive entry names or name components for displaying * listings and (warning/error) messages. They use sections in the upper half * of 'slide' as buffer, since their output is normally fed through the * Info() macro with 'slide' (the start of this area) as message buffer. */ #define FnFilter1(fname) \ fnfilter((fname), slide + (extent)(WSIZE>>1), (extent)(WSIZE>>2)) #define FnFilter2(fname) \ fnfilter((fname), slide + (extent)((WSIZE>>1) + (WSIZE>>2)),\ (extent)(WSIZE>>2)) #ifndef FUNZIP /* used only in inflate.c */ # define MESSAGE(str,len,flag) (*G.message)((zvoid *)&G,(str),(len),(flag)) #endif #if 0 /* Optimization: use the (const) result of crc32(0L,NULL,0) */ # define CRCVAL_INITIAL crc32(0L, NULL, 0) #else # define CRCVAL_INITIAL 0L #endif #ifdef SYMLINKS /* This macro defines the Zip "made by" hosts that are considered to support storing symbolic link entries. */ # define SYMLINK_HOST(hn) ((hn) == UNIX_ || (hn) == ATARI_ || \ (hn) == ATHEOS_ || (hn) == BEOS_ || (hn) == VMS_) #endif #ifndef TEST_NTSD /* "NTSD valid?" checking function */ # define TEST_NTSD NULL /* ... is not available */ #endif #define SKIP_(length) if(length&&((error=do_string(__G__ length,SKIP))!=0))\ {error_in_archive=error; if(error>1) return error;} /* * Skip a variable-length field, and report any errors. Used in zipinfo.c * and unzip.c in several functions. * * macro SKIP_(length) * ush length; * { * if (length && ((error = do_string(length, SKIP)) != 0)) { * error_in_archive = error; /-* might be warning *-/ * if (error > 1) /-* fatal *-/ * return (error); * } * } * */ #ifdef FUNZIP # define FLUSH(w) flush(__G__ (ulg)(w)) # define NEXTBYTE getc(G.in) /* redefined in crypt.h if full version */ #else # define FLUSH(w) ((G.mem_mode) ? memflush(__G__ redirSlide,(ulg)(w)) \ : flush(__G__ redirSlide,(ulg)(w),0)) # define NEXTBYTE (G.incnt-- > 0 ? (int)(*G.inptr++) : readbyte(__G)) #endif #define READBITS(nbits,zdest) {if(nbits>G.bits_left) {int temp; G.zipeof=1;\ while (G.bits_left<=8*(int)(sizeof(G.bitbuf)-1) && (temp=NEXTBYTE)!=EOF) {\ G.bitbuf|=(ulg)temp<>=nbits;\ G.bits_left-=nbits;} /* * macro READBITS(nbits,zdest) * only used by unreduce and unshrink * * { * if (nbits > G.bits_left) { * fill G.bitbuf, 8*sizeof(ulg) bits * * int temp; * * G.zipeof = 1; * while (G.bits_left <= 8*(int)(sizeof(G.bitbuf)-1) && * (temp = NEXTBYTE) != EOF) { * G.bitbuf |= (ulg)temp << G.bits_left; * G.bits_left += 8; * G.zipeof = 0; * } * } * zdest = (shrint)((unsigned)G.bitbuf & mask_bits[nbits]); * G.bitbuf >>= nbits; * G.bits_left -= nbits; * } * */ /* GRR: should use StringLower for STRLOWER macro if possible */ /* * Copy the zero-terminated string in str1 into str2, converting any * uppercase letters to lowercase as we go. str2 gets zero-terminated * as well, of course. str1 and str2 may be the same character array. */ #ifdef _MBCS # define STRLOWER(str1, str2) \ { \ char *p, *q, c; unsigned i; \ p = (char *)(str1); \ q = (char *)(str2); \ while ((c = *p) != '\0') { \ if ((i = CLEN(p)) > 1) { \ while (i--) *q++ = *p++; \ } else { \ *q++ = (char)(isupper((int)(c))? tolower((int)(c)) : c); \ p++; \ } \ } \ *q = '\0'; \ } #else # define STRLOWER(str1, str2) \ { \ char *p, *q; \ p = (char *)(str1) - 1; \ q = (char *)(str2); \ while (*++p) \ *q++ = (char)(isupper((int)(*p))? tolower((int)(*p)) : *p); \ *q = '\0'; \ } #endif /* * NOTES: This macro makes no assumptions about the characteristics of * the tolower() function or macro (beyond its existence), nor does it * make assumptions about the structure of the character set (i.e., it * should work on EBCDIC machines, too). The fact that either or both * of isupper() and tolower() may be macros has been taken into account; * watch out for "side effects" (in the C sense) when modifying this * macro. */ #ifndef foreign # define foreign(c) (c) #endif #ifndef native # define native(c) (c) # define A_TO_N(str1) #else # ifndef NATIVE # define NATIVE "native chars" # endif # define A_TO_N(str1) {register uch *p;\ for (p=(uch *)(str1); *p; p++) *p=native(*p);} #endif /* * Translate the zero-terminated string in str1 from ASCII to the native * character set. The translation is performed in-place and uses the * "native" macro to translate each character. * * NOTE: Using the "native" macro means that is it the only part of unzip * which knows which translation table (if any) is actually in use to * produce the native character set. This makes adding new character set * translation tables easy, insofar as all that is needed is an appropriate * "native" macro definition and the translation table itself. Currently, * the only non-ASCII native character set implemented is EBCDIC, but this * may not always be so. */ /* default setup for internal codepage: assume ISO 8859-1 compatibility!! */ #if (!defined(NATIVE) && !defined(CRTL_CP_IS_ISO) && !defined(CRTL_CP_IS_OEM)) # define CRTL_CP_IS_ISO #endif /* Translate "extended ASCII" chars (OEM coding for DOS and OS/2; else * ISO-8859-1 [ISO Latin 1, Win Ansi,...]) into the internal "native" * code page. As with A_TO_N(), conversion is done in place. */ #ifndef _ISO_INTERN # ifdef CRTL_CP_IS_OEM # ifndef IZ_ISO2OEM_ARRAY # define IZ_ISO2OEM_ARRAY # endif # define _ISO_INTERN(str1) if (iso2oem) {register uch *p;\ for (p=(uch *)(str1); *p; p++)\ *p = native((*p & 0x80) ? iso2oem[*p & 0x7f] : *p);} # else # define _ISO_INTERN(str1) A_TO_N(str1) # endif #endif #ifndef _OEM_INTERN # ifdef CRTL_CP_IS_OEM # define _OEM_INTERN(str1) A_TO_N(str1) # else # ifndef IZ_OEM2ISO_ARRAY # define IZ_OEM2ISO_ARRAY # endif # define _OEM_INTERN(str1) if (oem2iso) {register uch *p;\ for (p=(uch *)(str1); *p; p++)\ *p = native((*p & 0x80) ? oem2iso[*p & 0x7f] : *p);} # endif #endif #ifndef STR_TO_ISO # ifdef CRTL_CP_IS_ISO # define STR_TO_ISO strcpy # else # define STR_TO_ISO str2iso # define NEED_STR2ISO # endif #endif #ifndef STR_TO_OEM # ifdef CRTL_CP_IS_OEM # define STR_TO_OEM strcpy # else # define STR_TO_OEM str2oem # define NEED_STR2OEM # endif #endif #if (!defined(INTERN_TO_ISO) && !defined(ASCII2ISO)) # ifdef CRTL_CP_IS_OEM /* know: "ASCII" is "OEM" */ # define ASCII2ISO(c) \ ((((c) & 0x80) && oem2iso) ? oem2iso[(c) & 0x7f] : (c)) # if (defined(NEED_STR2ISO) && !defined(CRYP_USES_OEM2ISO)) # define CRYP_USES_OEM2ISO # endif # else /* assume: "ASCII" is "ISO-ANSI" */ # define ASCII2ISO(c) (c) # endif #endif #if (!defined(INTERN_TO_OEM) && !defined(ASCII2OEM)) # ifdef CRTL_CP_IS_OEM /* know: "ASCII" is "OEM" */ # define ASCII2OEM(c) (c) # else /* assume: "ASCII" is "ISO-ANSI" */ # define ASCII2OEM(c) \ ((((c) & 0x80) && iso2oem) ? iso2oem[(c) & 0x7f] : (c)) # if (defined(NEED_STR2OEM) && !defined(CRYP_USES_ISO2OEM)) # define CRYP_USES_ISO2OEM # endif # endif #endif /* codepage conversion setup for testp() in crypt.c */ #ifdef CRTL_CP_IS_ISO # ifndef STR_TO_CP2 # define STR_TO_CP2 STR_TO_OEM # endif #else # ifdef CRTL_CP_IS_OEM # ifndef STR_TO_CP2 # define STR_TO_CP2 STR_TO_ISO # endif # else /* native internal CP is neither ISO nor OEM */ # ifndef STR_TO_CP1 # define STR_TO_CP1 STR_TO_ISO # endif # ifndef STR_TO_CP2 # define STR_TO_CP2 STR_TO_OEM # endif # endif #endif /* Convert filename (and file comment string) into "internal" charset. * This macro assumes that Zip entry filenames are coded in OEM (IBM DOS) * codepage when made on * -> DOS (this includes 16-bit Windows 3.1) (FS_FAT_) * -> OS/2 (FS_HPFS_) * -> Win95/WinNT with Nico Mak's WinZip (FS_NTFS_ && hostver == "5.0") * EXCEPTIONS: * PKZIP for Windows 2.5, 2.6, and 4.0 flag their entries as "FS_FAT_", but * the filename stored in the local header is coded in Windows ANSI (CP 1252 * resp. ISO 8859-1 on US and western Europe locale settings). * Likewise, PKZIP for UNIX 2.51 flags its entries as "FS_FAT_", but the * filenames stored in BOTH the local and the central header are coded * in the local system's codepage (usually ANSI codings like ISO 8859-1). * * All other ports are assumed to code zip entry filenames in ISO 8859-1. */ #ifndef Ext_ASCII_TO_Native # define Ext_ASCII_TO_Native(string, hostnum, hostver, isuxatt, islochdr) \ if (((hostnum) == FS_FAT_ && \ !(((islochdr) || (isuxatt)) && \ ((hostver) == 25 || (hostver) == 26 || (hostver) == 40))) || \ (hostnum) == FS_HPFS_ || \ ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \ _OEM_INTERN((string)); \ } else { \ _ISO_INTERN((string)); \ } #endif /**********************/ /* Global constants */ /**********************/ extern ZCONST unsigned near mask_bits[17]; extern ZCONST char *fnames[2]; #ifdef EBCDIC extern ZCONST uch ebcdic[]; #endif #ifdef IZ_ISO2OEM_ARRAY extern ZCONST uch Far *iso2oem; extern ZCONST uch Far iso2oem_850[]; #endif #ifdef IZ_OEM2ISO_ARRAY extern ZCONST uch Far *oem2iso; extern ZCONST uch Far oem2iso_850[]; #endif extern ZCONST char Far VersionDate[]; extern ZCONST char Far CentSigMsg[]; #ifndef SFX extern ZCONST char Far EndSigMsg[]; #endif extern ZCONST char Far SeekMsg[]; extern ZCONST char Far FilenameNotMatched[]; extern ZCONST char Far ExclFilenameNotMatched[]; extern ZCONST char Far ReportMsg[]; #ifndef SFX extern ZCONST char Far Zipnfo[]; extern ZCONST char Far CompiledWith[]; #endif /* !SFX */ /***********************************/ /* Global (shared?) RTL variables */ /***********************************/ #ifdef DECLARE_ERRNO extern int errno; #endif /*--------------------------------------------------------------------- Unicode Support 28 August 2005 ---------------------------------------------------------------------*/ #if (defined(UNICODE_SUPPORT) && defined(UNICODE_WCHAR)) /* Default character when a zwchar too big for wchar_t */ # define zwchar_to_wchar_t_default_char '_' /* Default character string when wchar_t does not convert to mb */ # define wide_to_mb_default_string "_" /* wide character type */ typedef unsigned long zwchar; /* UTF-8 related conversion functions, currently found in process.c */ # if 0 /* currently unused */ /* check if string is all ASCII */ int is_ascii_string OF((ZCONST char *mbstring)); # endif /* unused */ /* convert UTF-8 string to multi-byte string */ char *utf8_to_local_string OF((ZCONST char *utf8_string, int escape_all)); /* convert UTF-8 string to wide string */ zwchar *utf8_to_wide_string OF((ZCONST char *utf8_string)); /* convert wide string to multi-byte string */ char *wide_to_local_string OF((ZCONST zwchar *wide_string, int escape_all)); # if 0 /* currently unused */ /* convert local string to multi-byte display string */ char *local_to_display_string OF((ZCONST char *local_string)); # endif /* unused */ /* convert wide character to escape string */ char *wide_to_escape_string OF((unsigned long)); # define utf8_to_escaped_string(utf8_string) \ utf8_to_local_string(utf8_string, TRUE) # if 0 /* currently unused */ /* convert escape string to wide character */ unsigned long escape_string_to_wide OF((ZCONST char *escape_string)); /* convert local to UTF-8 */ char *local_to_utf8_string OF ((ZCONST char *local_string)); /* convert local to wide string */ zwchar *local_to_wide_string OF ((ZCONST char *local_string)); /* convert wide string to UTF-8 */ char *wide_to_utf8_string OF((ZCONST zwchar *wide_string)); # endif /* unused */ #endif /* UNICODE_SUPPORT && UNICODE_WCHAR */ #endif /* !__unzpriv_h */ Carla-2.1/data/windows/unzipfx-carla/unzvers.h000066400000000000000000000060411364475620200214630ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* unzvers.h (for UnZip) by Info-ZIP. */ #ifndef __unzvers_h /* don't include more than once */ #define __unzvers_h #ifdef BETA # undef BETA /* undefine BETA for public releases */ #endif #ifdef BETA # define UZ_BETALEVEL "h03 BETA" # define UZ_VERSION_DATE "17 Apr 09" /* internal beta version */ #else # define UZ_BETALEVEL "" # define UZ_VERSION_DATE "20 April 2009" /* official release version */ # define RELEASE #endif #define UZ_MAJORVER 6 /* UnZip */ #define UZ_MINORVER 0 #define ZI_MAJORVER 3 /* ZipInfo */ #define ZI_MINORVER 0 #define UZ_PATCHLEVEL 0 #define UZ_VER_STRING "6.0" /* keep in sync with Version numbers! */ #ifndef IZ_COMPANY_NAME /* might be already defined... */ # define IZ_COMPANY_NAME "Info-ZIP" #endif /* these are obsolete but remain for backward compatibility: */ #if (defined(OS2) || defined(__OS2__)) # define D2_MAJORVER UZ_MAJORVER /* DLL for OS/2 */ # define D2_MINORVER UZ_MINORVER # define D2_PATCHLEVEL UZ_PATCHLEVEL #endif #define DW_MAJORVER UZ_MAJORVER /* DLL for MS Windows */ #define DW_MINORVER UZ_MINORVER #define DW_PATCHLEVEL UZ_PATCHLEVEL #define WIN_VERSION_DATE UZ_VERSION_DATE #define UNZ_DLL_VERSION UZ_VER_STRING /* The following version constants specify the UnZip version that introduced * the most recent incompatible change (means: change that breaks backward * compatibility) of a DLL/Library binary API definition. * * Currently, UnZip supports three distinct DLL/Library APIs, which each * carry their own "compatibility level": * a) The "generic" (console-mode oriented) API has been used on UNIX, * for example. This API provides a "callable" interface similar to the * interactive command line of the normal program executables. * b) The OS/2-only API provides (additional) functions specially tailored * for interfacing with the REXX shell. * c) The Win32 DLL API with a pure binary interface which can be used to * build GUI mode as well as Console mode applications. * * Whenever a change that breaks backward compatibility gets applied to * any of the DLL/Library APIs, the corresponding compatibility level should * be synchronized with the current UnZip version numbers. */ /* generic DLL API minimum compatible version*/ #define UZ_GENAPI_COMP_MAJOR 6 #define UZ_GENAPI_COMP_MINOR 0 #define UZ_GENAPI_COMP_REVIS 0 /* os2dll API minimum compatible version*/ #define UZ_OS2API_COMP_MAJOR 6 #define UZ_OS2API_COMP_MINOR 0 #define UZ_OS2API_COMP_REVIS 0 /* windll API minimum compatible version*/ #define UZ_WINAPI_COMP_MAJOR 6 #define UZ_WINAPI_COMP_MINOR 0 #define UZ_WINAPI_COMP_REVIS 0 #endif /* !__unzvers_h */ Carla-2.1/data/windows/unzipfx-carla/win32/000077500000000000000000000000001364475620200205375ustar00rootroot00000000000000Carla-2.1/data/windows/unzipfx-carla/win32/nt.c000066400000000000000000000405051364475620200213300ustar00rootroot00000000000000/* Copyright (c) 1990-2007 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* Copyright (c) 1996 Scott Field (dedicated to Info-Zip group) Module Name: nt.c Abstract: This module implements WinNT security descriptor operations for the Win32 Info-ZIP project. Operation such as setting file security, using/querying local and remote privileges, and queuing of operations is performed here. The contents of this module are only relevant when the code is running on Windows NT, and the target volume supports persistent Acl storage. User privileges that allow accessing certain privileged aspects of the security descriptor (such as the Sacl) are only used if the user specified to do so. Author: Scott Field (sfield@microsoft.com) Last revised: 18 Jan 97 */ #define WIN32_LEAN_AND_MEAN #define UNZIP_INTERNAL #include #include "../unzip.h" #ifdef __RSXNT__ # include "../win32/rsxntwin.h" #endif #include "../win32/nt.h" #ifdef NTSD_EAS /* This file is only needed for NTSD handling */ /* Borland C++ does not define FILE_SHARE_DELETE. Others also? */ #ifndef FILE_SHARE_DELETE # define FILE_SHARE_DELETE 0x00000004 #endif /* This macro definition is missing in old versions of MS' winbase.h. */ #ifndef InterlockedExchangePointer # define InterlockedExchangePointer(Target, Value) \ (PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value)) #endif /* private prototypes */ static BOOL Initialize(VOID); static VOID GetRemotePrivilegesSet(CHAR *FileName, PDWORD dwRemotePrivileges); static VOID InitLocalPrivileges(VOID); volatile BOOL bInitialized = FALSE; /* module level stuff initialized? */ HANDLE hInitMutex = NULL; /* prevent multiple initialization */ BOOL g_bRestorePrivilege = FALSE; /* for local set file security override */ BOOL g_bSaclPrivilege = FALSE; /* for local set sacl operations, only when restore privilege not present */ /* our single cached volume capabilities structure that describes the last volume root we encountered. A single entry like this works well in the zip/unzip scenario for a number of reasons: 1. typically one extraction path during unzip. 2. typically process one volume at a time during zip, and then move on to the next. 3. no cleanup code required and no memory leaks. 4. simple code. This approach should be reworked to a linked list approach if we expect to be called by many threads which are processing a variety of input/output volumes, since lock contention and stale data may become a bottleneck. */ VOLUMECAPS g_VolumeCaps; CRITICAL_SECTION VolumeCapsLock; static BOOL Initialize(VOID) { HANDLE hMutex; HANDLE hOldMutex; if (bInitialized) return TRUE; hMutex = CreateMutex(NULL, TRUE, NULL); if(hMutex == NULL) return FALSE; hOldMutex = (HANDLE)InterlockedExchangePointer((void *)&hInitMutex, hMutex); if (hOldMutex != NULL) { /* somebody setup the mutex already */ InterlockedExchangePointer((void *)&hInitMutex, hOldMutex); CloseHandle(hMutex); /* close new, un-needed mutex */ /* wait for initialization to complete and return status */ WaitForSingleObject(hOldMutex, INFINITE); ReleaseMutex(hOldMutex); return bInitialized; } if (!bInitialized) { /* initialize module level resources */ InitializeCriticalSection( &VolumeCapsLock ); memset(&g_VolumeCaps, 0, sizeof(VOLUMECAPS)); InitLocalPrivileges(); bInitialized = TRUE; } InterlockedExchangePointer((void *)&hInitMutex, NULL); ReleaseMutex(hMutex); /* release correct mutex */ CloseHandle(hMutex); /* free the no longer needed handle resource */ return TRUE; } BOOL ValidateSecurity(uch *securitydata) { PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata; PACL pAcl; PSID pSid; BOOL bAclPresent; BOOL bDefaulted; if(!IsWinNT()) return TRUE; /* don't do anything if not on WinNT */ if(!IsValidSecurityDescriptor(sd)) return FALSE; /* verify Dacl integrity */ if(!GetSecurityDescriptorDacl(sd, &bAclPresent, &pAcl, &bDefaulted)) return FALSE; if(bAclPresent && pAcl!=NULL) { if(!IsValidAcl(pAcl)) return FALSE; } /* verify Sacl integrity */ if(!GetSecurityDescriptorSacl(sd, &bAclPresent, &pAcl, &bDefaulted)) return FALSE; if(bAclPresent && pAcl!=NULL) { if(!IsValidAcl(pAcl)) return FALSE; } /* verify owner integrity */ if(!GetSecurityDescriptorOwner(sd, &pSid, &bDefaulted)) return FALSE; if(pSid != NULL) { if(!IsValidSid(pSid)) return FALSE; } /* verify group integrity */ if(!GetSecurityDescriptorGroup(sd, &pSid, &bDefaulted)) return FALSE; if(pSid != NULL) { if(!IsValidSid(pSid)) return FALSE; } return TRUE; } static VOID GetRemotePrivilegesSet(char *FileName, PDWORD dwRemotePrivileges) { HANDLE hFile; *dwRemotePrivileges = 0; /* see if we have the SeRestorePrivilege */ hFile = CreateFileA( FileName, ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER | READ_CONTROL, FILE_SHARE_READ | FILE_SHARE_DELETE, /* no sd updating allowed here */ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL ); if(hFile != INVALID_HANDLE_VALUE) { /* no remote way to determine SeRestorePrivilege -- just try a read/write to simulate it */ SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION; PSECURITY_DESCRIPTOR sd; DWORD cbBuf = 0; GetKernelObjectSecurity(hFile, si, NULL, cbBuf, &cbBuf); if(ERROR_INSUFFICIENT_BUFFER == GetLastError()) { if((sd = HeapAlloc(GetProcessHeap(), 0, cbBuf)) != NULL) { if(GetKernelObjectSecurity(hFile, si, sd, cbBuf, &cbBuf)) { if(SetKernelObjectSecurity(hFile, si, sd)) *dwRemotePrivileges |= OVERRIDE_RESTORE; } HeapFree(GetProcessHeap(), 0, sd); } } CloseHandle(hFile); } else { /* see if we have the SeSecurityPrivilege */ /* note we don't need this if we have SeRestorePrivilege */ hFile = CreateFileA( FileName, ACCESS_SYSTEM_SECURITY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* max */ NULL, OPEN_EXISTING, 0, NULL ); if(hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); *dwRemotePrivileges |= OVERRIDE_SACL; } } } BOOL GetVolumeCaps( char *rootpath, /* filepath, or NULL */ char *name, /* filename associated with rootpath */ PVOLUMECAPS VolumeCaps /* result structure describing capabilities */ ) { char TempRootPath[MAX_PATH + 1]; DWORD cchTempRootPath = 0; BOOL bSuccess = TRUE; /* assume success until told otherwise */ if(!bInitialized) if(!Initialize()) return FALSE; /* process the input path to produce a consistent path suitable for compare operations and also suitable for certain picky Win32 API that don't like forward slashes */ if(rootpath != NULL && rootpath[0] != '\0') { DWORD i; cchTempRootPath = lstrlenA(rootpath); if(cchTempRootPath > MAX_PATH) return FALSE; /* copy input, converting forward slashes to back slashes as we go */ for(i = 0 ; i <= cchTempRootPath ; i++) { if(rootpath[i] == '/') TempRootPath[i] = '\\'; else TempRootPath[i] = rootpath[i]; } /* check for UNC and Null terminate or append trailing \ as appropriate */ /* possible valid UNCs we are passed follow: \\machine\foo\bar (path is \\machine\foo\) \\machine\foo (path is \\machine\foo\) \\machine\foo\ \\.\c$\ (FIXFIX: Win32API doesn't like this - GetComputerName()) LATERLATER: handling mounted DFS drives in the future will require slightly different logic which isn't available today. This is required because directories can point at different servers which have differing capabilities. */ if(TempRootPath[0] == '\\' && TempRootPath[1] == '\\') { DWORD slash = 0; for(i = 2 ; i < cchTempRootPath ; i++) { if(TempRootPath[i] == '\\') { slash++; if(slash == 2) { i++; TempRootPath[i] = '\0'; cchTempRootPath = i; break; } } } /* if there was only one slash found, just tack another onto the end */ if(slash == 1 && TempRootPath[cchTempRootPath] != '\\') { TempRootPath[cchTempRootPath] = TempRootPath[0]; /* '\\' */ TempRootPath[cchTempRootPath+1] = '\0'; cchTempRootPath++; } } else { if(TempRootPath[1] == ':') { /* drive letter specified, truncate to root */ TempRootPath[2] = '\\'; TempRootPath[3] = '\0'; cchTempRootPath = 3; } else { /* must be file on current drive */ TempRootPath[0] = '\0'; cchTempRootPath = 0; } } } /* if path != NULL */ /* grab lock protecting cached entry */ EnterCriticalSection( &VolumeCapsLock ); if(!g_VolumeCaps.bValid || lstrcmpiA(g_VolumeCaps.RootPath, TempRootPath) != 0) { /* no match found, build up new entry */ DWORD dwFileSystemFlags; DWORD dwRemotePrivileges = 0; BOOL bRemote = FALSE; /* release lock during expensive operations */ LeaveCriticalSection( &VolumeCapsLock ); bSuccess = GetVolumeInformationA( (TempRootPath[0] == '\0') ? NULL : TempRootPath, NULL, 0, NULL, NULL, &dwFileSystemFlags, NULL, 0); /* only if target volume supports Acls, and we were told to use privileges do we need to go out and test for the remote case */ if(bSuccess && (dwFileSystemFlags & FS_PERSISTENT_ACLS) && VolumeCaps->bUsePrivileges) { if(GetDriveTypeA( (TempRootPath[0] == '\0') ? NULL : TempRootPath ) == DRIVE_REMOTE) { bRemote = TRUE; /* make a determination about our remote capabilities */ GetRemotePrivilegesSet(name, &dwRemotePrivileges); } } /* always take the lock again, since we release it below */ EnterCriticalSection( &VolumeCapsLock ); /* replace the existing data if successful */ if(bSuccess) { lstrcpynA(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1); g_VolumeCaps.dwFileSystemFlags = dwFileSystemFlags; g_VolumeCaps.bRemote = bRemote; g_VolumeCaps.dwRemotePrivileges = dwRemotePrivileges; g_VolumeCaps.bValid = TRUE; } } if(bSuccess) { /* copy input elements */ g_VolumeCaps.bUsePrivileges = VolumeCaps->bUsePrivileges; g_VolumeCaps.dwFileAttributes = VolumeCaps->dwFileAttributes; /* give caller results */ memcpy(VolumeCaps, &g_VolumeCaps, sizeof(VOLUMECAPS)); } else { g_VolumeCaps.bValid = FALSE; } LeaveCriticalSection( &VolumeCapsLock ); /* release lock */ return bSuccess; } BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata) { HANDLE hFile; DWORD dwDesiredAccess = 0; DWORD dwFlags = 0; PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata; SECURITY_DESCRIPTOR_CONTROL sdc; SECURITY_INFORMATION RequestedInfo = 0; DWORD dwRev; BOOL bRestorePrivilege = FALSE; BOOL bSaclPrivilege = FALSE; BOOL bSuccess; if(!bInitialized) if(!Initialize()) return FALSE; /* defer directory processing */ if(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* opening a directory requires FILE_FLAG_BACKUP_SEMANTICS */ dwFlags |= FILE_FLAG_BACKUP_SEMANTICS; } /* evaluate the input security descriptor and act accordingly */ if(!IsValidSecurityDescriptor(sd)) return FALSE; if(!GetSecurityDescriptorControl(sd, &sdc, &dwRev)) return FALSE; /* setup privilege usage based on if told we can use privileges, and if so, what privileges we have */ if(VolumeCaps->bUsePrivileges) { if(VolumeCaps->bRemote) { /* use remotely determined privileges */ if(VolumeCaps->dwRemotePrivileges & OVERRIDE_RESTORE) bRestorePrivilege = TRUE; if(VolumeCaps->dwRemotePrivileges & OVERRIDE_SACL) bSaclPrivilege = TRUE; } else { /* use local privileges */ bRestorePrivilege = g_bRestorePrivilege; bSaclPrivilege = g_bSaclPrivilege; } } /* if a Dacl is present write Dacl out */ /* if we have SeRestorePrivilege, write owner and group info out */ if(sdc & SE_DACL_PRESENT) { dwDesiredAccess |= WRITE_DAC; RequestedInfo |= DACL_SECURITY_INFORMATION; if(bRestorePrivilege) { dwDesiredAccess |= WRITE_OWNER; RequestedInfo |= (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION); } } /* if a Sacl is present and we have either SeRestorePrivilege or SeSystemSecurityPrivilege try to write Sacl out */ if((sdc & SE_SACL_PRESENT) && (bRestorePrivilege || bSaclPrivilege)) { dwDesiredAccess |= ACCESS_SYSTEM_SECURITY; RequestedInfo |= SACL_SECURITY_INFORMATION; } if(RequestedInfo == 0) /* nothing to do */ return FALSE; if(bRestorePrivilege) dwFlags |= FILE_FLAG_BACKUP_SEMANTICS; hFile = CreateFileA( resource, dwDesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,/* max sharing */ NULL, OPEN_EXISTING, dwFlags, NULL ); if(hFile == INVALID_HANDLE_VALUE) return FALSE; bSuccess = SetKernelObjectSecurity(hFile, RequestedInfo, sd); CloseHandle(hFile); return bSuccess; } static VOID InitLocalPrivileges(VOID) { HANDLE hToken; TOKEN_PRIVILEGES tp; /* try to enable some interesting privileges that give us the ability to get some security information that we normally cannot. note that enabling privileges is only relevant on the local machine; when accessing files that are on a remote machine, any privileges that are present on the remote machine get enabled by default. */ if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) return; tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if(LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid)) { /* try to enable SeRestorePrivilege; if this succeeds, we can write all aspects of the security descriptor */ if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) && GetLastError() == ERROR_SUCCESS) g_bRestorePrivilege = TRUE; } /* try to enable SeSystemSecurityPrivilege, if SeRestorePrivilege not present; if this succeeds, we can write the Sacl */ if(!g_bRestorePrivilege && LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) { if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) && GetLastError() == ERROR_SUCCESS) g_bSaclPrivilege = TRUE; } CloseHandle(hToken); } #endif /* NTSD_EAS */ Carla-2.1/data/windows/unzipfx-carla/win32/nt.h000066400000000000000000000026141364475620200213340ustar00rootroot00000000000000/* Copyright (c) 1990-2005 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* nt.h: central header for EF_NTSD "SD" extra field */ #ifndef _NT_H #define _NT_H #define NTSD_BUFFERSIZE (1024) /* threshold to cause malloc() */ #define OVERRIDE_BACKUP 1 /* we have SeBackupPrivilege on remote */ #define OVERRIDE_RESTORE 2 /* we have SeRestorePrivilege on remote */ #define OVERRIDE_SACL 4 /* we have SeSystemSecurityPrivilege on remote */ typedef struct { BOOL bValid; /* are our contents valid? */ BOOL bUsePrivileges; /* use privilege overrides? */ DWORD dwFileSystemFlags; /* describes target file system */ BOOL bRemote; /* is volume remote? */ DWORD dwRemotePrivileges; /* relevant only on remote volumes */ DWORD dwFileAttributes; char RootPath[MAX_PATH+1]; /* path to network / filesystem */ } VOLUMECAPS, *PVOLUMECAPS, *LPVOLUMECAPS; BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata); BOOL GetVolumeCaps(char *rootpath, char *name, PVOLUMECAPS VolumeCaps); BOOL ValidateSecurity(uch *securitydata); #endif /* _NT_H */ Carla-2.1/data/windows/unzipfx-carla/win32/w32cfg.h000066400000000000000000000443251364475620200220130ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- Win32 specific configuration section: ---------------------------------------------------------------------------*/ #ifndef __w32cfg_h #define __w32cfg_h #ifdef __MINGW32__ # define USE_STRM_INPUT #endif #ifdef __CYGWIN__ /* We treat the file system underneath the Cygwin Unix emulator environment * as "native VFAT/NTFS" and use the WIN32 API for its special attributes... */ # ifdef UNIX # undef UNIX # endif #endif #if (defined(_MSC_VER) && !defined(MSC)) # define MSC #endif /* enable multibyte character set support by default */ #if (!defined(_MBCS) && !defined(NO_MBCS)) # define _MBCS #endif #if (defined(_MBCS) && defined(NO_MBCS)) # undef _MBCS #endif #if (defined(__CYGWIN__) && defined(_MBCS)) # undef _MBCS /* Cygwin RTL lacks support for __mb_cur_max */ #endif #if (defined(__DJGPP__) && !defined(__EMX__) && defined(_MBCS)) # undef _MBCS /* __mb_cur_max missing for RSXNTdj 1.6 beta */ #endif #include /* off_t, time_t, dev_t, ... */ #include #include /* read(), open(), etc. */ #include #if ((defined(__RSXNT__) || defined(__EMX__)) && !defined(tzset)) # define tzset _tzset #endif #if (defined(__LCC__) && !defined(tzset)) # define tzset _tzset #endif #ifdef W32_USE_IZ_TIMEZONE # ifdef __BORLANDC__ # define tzname tzname # define IZTZ_DEFINESTDGLOBALS # endif # ifdef __WATCOMC__ # define IZTZ_DEFINESTDGLOBALS # endif # ifndef tzset # define tzset _tzset # endif # ifndef timezone # define timezone _timezone # endif # ifndef daylight # define daylight _daylight # endif # ifndef tzname # define tzname _tzname # endif # if (!defined(NEED__ISINDST) && !defined(__BORLANDC__)) # define NEED__ISINDST # endif # ifdef IZTZ_GETLOCALETZINFO # undef IZTZ_GETLOCALETZINFO # endif # define IZTZ_GETLOCALETZINFO GetPlatformLocalTimezone #endif /* W32_USE_IZ_TIMEZONE */ #include #if (!defined(__RSXNT__) && !defined(__CYGWIN__)) # include /* mkdir() */ #endif #include #ifdef __CYGWIN__ # include extern int setmode(int, int); /* this is missing in */ #endif #if (defined(MSC) || defined(__WATCOMC__) || defined(__MINGW32__)) # include #else # include #endif #define GOT_UTIMBUF #ifdef _MBCS # if (!defined(__EMX__) && !defined(__DJGPP__) && !defined(__CYGWIN__)) # if (!defined(__MINGW32__) || defined(__MSVCRT__)) # include # include /* for MSC (and compatible compilers), use routines supplied by RTL */ # define CLEN(ptr) _mbclen((const uch *)(ptr)) # define PREINCSTR(ptr) (ptr = (char *)_mbsinc((const uch *)(ptr))) # define MBSCHR(str, c) (char *)_mbschr((const uch *)(str), (c)) # define MBSRCHR(str, c) (char *)_mbsrchr((const uch *)(str), (c)) # endif # endif # if (defined(__MINGW32__) && !defined(MB_CUR_MAX)) # ifdef __MSVCRT__ extern int *__p___mb_cur_max(void); # define MB_CUR_MAX (*__p___mb_cur_max()) # else extern int *_imp____mb_cur_max_dll; # define MB_CUR_MAX (*_imp____mb_cur_max_dll) # endif # endif # if (defined(__LCC__) && !defined(MB_CUR_MAX)) extern int *_imp____mb_cur_max; # define MB_CUR_MAX (*_imp____mb_cur_max) # endif # if (defined(__DJGPP__) && !defined(__EMX__) && !defined(MB_CUR_MAX)) extern int *_imp____mb_cur_max; # define MB_CUR_MAX (*_imp____mb_cur_max) # endif #endif /* for UnZip, the "basic" part of the win32 api is sufficient */ #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif #if defined(__FILEIO_C) # ifndef __CYGWIN__ # include # endif # include # ifdef __RSXNT__ # include "../win32/rsxntwin.h" # endif # ifndef TIME_ZONE_ID_INVALID # define TIME_ZONE_ID_INVALID (DWORD)0xFFFFFFFFL # endif #endif #if (defined(__ENVARGS_C) || defined(__EXTRACT_C) || defined(__UNZIP_C) || \ defined(ZCRYPT_INTERNAL)) # include # ifdef __RSXNT__ # include "../win32/rsxntwin.h" # endif # ifndef TIME_ZONE_ID_INVALID # define TIME_ZONE_ID_INVALID (DWORD)0xFFFFFFFFL # endif #endif #ifndef Cdecl # define Cdecl __cdecl #endif /* the following definitions are considered as "obsolete" by Microsoft and * might be missing in some versions of */ #ifndef AnsiToOem # define AnsiToOem CharToOemA #endif #ifndef OemToAnsi # define OemToAnsi OemToCharA #endif #define DIR_END '\\' /* OS uses '\\' as directory separator */ #define DIR_END2 '/' /* also check for '/' (RTL may convert) */ #ifdef DATE_FORMAT # undef DATE_FORMAT #endif #define DATE_FORMAT dateformat() #ifdef DATE_SEPCHAR # undef DATE_SEPCHAR #endif #define DATE_SEPCHAR dateseparator() #define lenEOL 2 #define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);} #if (defined(__RSXNT__) && !defined(HAVE_MKTIME)) # define HAVE_MKTIME /* use mktime() in time conversion routines */ #endif #if (defined(MSC) && !defined(HAVE_MKTIME)) # define HAVE_MKTIME /* use mktime() in time conversion routines */ #endif #if (defined(__CYGWIN__) && defined(HAVE_MKTIME)) # undef HAVE_MKTIME /* Cygnus' mktime() implementation is buggy */ #endif #if (defined(W32_USE_IZ_TIMEZONE) && !defined(HAVE_MKTIME)) # define HAVE_MKTIME /* use mktime() in time conversion routines */ #endif #if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)) # define USE_EF_UT_TIME #endif #if (!defined(NO_DIR_ATTRIB) && !defined(SET_DIR_ATTRIB)) # define SET_DIR_ATTRIB #endif #if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) # define TIMESTAMP #endif #if (!defined(NO_NTSD_EAS) && !defined(NTSD_EAS)) # define NTSD_EAS /* enable NTSD support unless explicitly suppressed */ #endif #if (defined(NTSD_EAS) && !defined(RESTORE_ACL)) # define RESTORE_ACL /* "restore ACLs" only needed when NTSD_EAS active */ #endif #if (!defined(NO_UNICODE_SUPPORT) && !defined(UNICODE_SUPPORT)) # define UNICODE_SUPPORT /* enable UTF-8 filename support by default */ #endif #if (defined(UNICODE_SUPPORT) && !defined(UNICODE_WCHAR)) # define UNICODE_WCHAR /* wchar_t is UTF-16 encoded on WIN32 */ #endif #ifdef UTF8_MAYBE_NATIVE # undef UTF8_MAYBE_NATIVE /* UTF-8 cannot be system charset on WIN32 */ #endif /* The following compiler systems provide or use a runtime library with a * locale-aware isprint() implementation. For these systems, the "enhanced" * unprintable charcode detection in fnfilter() gets enabled. */ #if (!defined(HAVE_WORKING_ISPRINT) && !defined(NO_WORKING_ISPRINT)) # if defined(MSC) || defined(__BORLANDC__) # define HAVE_WORKING_ISPRINT # endif # if defined(__MINGW32__) && defined(__MSVCRT__) # define HAVE_WORKING_ISPRINT # endif #endif /* WIN32 runs solely on little-endian processors; enable support * for the 32-bit optimized CRC-32 C code by default. */ #ifdef IZ_CRC_BE_OPTIMIZ # undef IZ_CRC_BE_OPTIMIZ #endif #if !defined(IZ_CRC_LE_OPTIMIZ) && !defined(NO_CRC_OPTIMIZ) # define IZ_CRC_LE_OPTIMIZ #endif /* handlers for OEM <--> ANSI string conversions */ #ifdef __RSXNT__ /* RSXNT uses OEM coded strings in functions supplied by C RTL */ # ifdef CRTL_CP_IS_ISO # undef CRTL_CP_IS_ISO # endif # ifndef CRTL_CP_IS_OEM # define CRTL_CP_IS_OEM # endif #else /* "real" native WIN32 compilers use ANSI coded strings in C RTL calls */ # ifndef CRTL_CP_IS_ISO # define CRTL_CP_IS_ISO # endif # ifdef CRTL_CP_IS_OEM # undef CRTL_CP_IS_OEM # endif #endif #ifdef CRTL_CP_IS_ISO /* C RTL's file system support assumes ANSI coded strings */ # define ISO_TO_INTERN(src, dst) {if ((src) != (dst)) strcpy((dst), (src));} # define OEM_TO_INTERN(src, dst) OemToAnsi(src, dst) # define INTERN_TO_ISO(src, dst) {if ((src) != (dst)) strcpy((dst), (src));} # define INTERN_TO_OEM(src, dst) AnsiToOem(src, dst) #endif /* CRTL_CP_IS_ISO */ #ifdef CRTL_CP_IS_OEM /* C RTL's file system support assumes OEM coded strings */ # define ISO_TO_INTERN(src, dst) AnsiToOem(src, dst) # define OEM_TO_INTERN(src, dst) {if ((src) != (dst)) strcpy((dst), (src));} # define INTERN_TO_ISO(src, dst) OemToAnsi(src, dst) # define INTERN_TO_OEM(src, dst) {if ((src) != (dst)) strcpy((dst), (src));} #endif /* CRTL_CP_IS_OEM */ #define _OEM_INTERN(str1) OEM_TO_INTERN(str1, str1) #define _ISO_INTERN(str1) ISO_TO_INTERN(str1, str1) #ifndef WINDLL /* Despite best intentions, for the command-line version UzpPassword() * could return either character set, depending on whether running under * Win95 (DOS-session) or WinNT (native WinNT command interpreter)! */ # define STR_TO_CP2(dst, src) (AnsiToOem(src, dst), dst) # define STR_TO_CP3(dst, src) (OemToAnsi(src, dst), dst) #else /* The WINDLL front end is known to supply ISO/ANSI-coded passwords! */ # define STR_TO_CP2(dst, src) (AnsiToOem(src, dst), dst) #endif /* dummy defines to disable these functions, they are not needed */ #define STR_TO_OEM #define STR_TO_ISO /* Static variables that we have to add to Uz_Globs: */ #define SYSTEM_SPECIFIC_GLOBALS \ int created_dir, renamed_fullpath, fnlen;\ unsigned nLabelDrive;\ char lastRootPath[4];\ int lastVolOldFAT, lastVolLocTim;\ char *rootpath, *buildpathHPFS, *buildpathFAT, *endHPFS, *endFAT;\ ZCONST char *wildname;\ char *dirname, matchname[FILNAMSIZ];\ int rootlen, have_dirname, dirnamelen, notfirstcall;\ zvoid *wild_dir; /* created_dir, renamed_fullpath, fnlen, and nLabelDrive are used by */ /* both mapname() and checkdir(). */ /* lastRootPath, lastVolOldFAT and lastVolLocTim are used by */ /* IsVolumeOldFAT() and NTQueryVolInfo(). */ /* rootlen, rootpath, buildpathHPFS, buildpathFAT, endHPFS, and endFAT */ /* are used by checkdir(). */ /* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */ /* and notfirstcall are used by do_wild(). */ /* This replacement for C-RTL-supplied getch() (or similar) functionality * avoids leaving unabsorbed LFs in the keyboard buffer under Windows95, * and supports the +[0] feature. */ int getch_win32 OF((void)); /* Up to now, all versions of Microsoft C runtime libraries lack the support * for customized (non-US) switching rules between daylight saving time and * standard time in the TZ environment variable string. * But non-US timezone rules are correctly supported when timezone information * is read from the OS system settings in the Win32 registry. * The following work-around deletes any TZ environment setting from * the process environment. This results in a fallback of the RTL time * handling code to the (correctly interpretable) OS system settings, read * from the registry. */ #ifdef USE_EF_UT_TIME # if (defined(__WATCOMC__) || defined(__CYGWIN__) || \ defined(W32_USE_IZ_TIMEZONE)) # define iz_w32_prepareTZenv() # else # define iz_w32_prepareTZenv() putenv("TZ=") # endif #endif /* This patch of stat() is useful for at least two compilers. It is */ /* difficult to take a stat() of a root directory under Windows95, so */ /* zstat_win32() detects that case and fills in suitable values. */ #ifndef __RSXNT__ # ifndef W32_STATROOT_FIX # define W32_STATROOT_FIX # endif #endif /* !__RSXNT__ */ #define W32_STAT_BANDAID #if defined(REENTRANT) # define __W32STAT_GLOBALS__ Uz_Globs *pG, # define __W32STAT_G__ pG, #else # define __W32STAT_GLOBALS__ # define __W32STAT_G__ #endif #ifdef SSTAT # undef SSTAT #endif #ifdef WILD_STAT_BUG # define SSTAT(path, pbuf) (iswild(path) || zstat_win32(__W32STAT_G__ path, pbuf)) #else # define SSTAT(path, pbuf) zstat_win32(__W32STAT_G__ path, pbuf) #endif #ifdef __WATCOMC__ # ifdef __386__ # ifndef WATCOMC_386 # define WATCOMC_386 # endif # define __32BIT__ # undef far # define far # undef near # define near # undef Cdecl # define Cdecl /* gaah -- Watcom's docs claim that _get_osfhandle exists, but it doesn't. */ # define _get_osfhandle _os_handle /* Get asm routines to link properly without using "__cdecl": */ # ifndef USE_ZLIB # pragma aux crc32 "_*" parm caller [] value [eax] modify [eax] # pragma aux get_crc_table "_*" parm caller [] value [eax] \ modify [eax ecx edx] # endif /* !USE_ZLIB */ # endif /* __386__ */ #endif /* __WATCOMC__ */ #define SCREENWIDTH 80 #define SCREENSIZE(scrrows, scrcols) screensize(scrrows, scrcols) int screensize(int *tt_rows, int *tt_cols); /* on the DOS or NT console screen, line-wraps are always enabled */ #define SCREENLWRAP 1 #define TABSIZE 8 /* 64-bit-Integers & Large File Support * (pasted here from Zip 3b, osdep.h - Myles Bennett 7-jun-2004) * (updated from Zip 3.0d - Ed Gordon 6-oct-2004) * * If this is set it is assumed that the port * supports 64-bit file calls. The types are * defined here. Any local implementations are * in w32i64.c and the prototypes for the calls are * in unzip.h. Note that a port must support * these calls fully or should not set * LARGE_FILE_SUPPORT. */ /* Automatically set ZIP64_SUPPORT if supported */ #ifndef NO_ZIP64_SUPPORT # ifndef ZIP64_SUPPORT # if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) # define ZIP64_SUPPORT # elif defined(__LCC__) /* LCC links against crtdll.dll -> no support of 64-bit offsets :( */ # elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100)) # define ZIP64_SUPPORT # elif (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0520)) /* Borland C RTL lacks any support to get/set 64-bit file pointer :( */ # endif # endif #endif #ifdef ZIP64_SUPPORT /* base type for file offsets and file sizes */ # if (defined(__GNUC__) || defined(ULONG_LONG_MAX)) typedef long long zoff_t; # else /* all other compilers use this as intrinsic 64-bit type */ typedef __int64 zoff_t; # endif # define ZOFF_T_DEFINED /* user-defined types and format strings for 64-bit numbers and * file pointer functions (these depend on the rtl library and library * headers used; they are NOT compiler-specific) */ # if defined(_MSC_VER) || defined(__MINGW32__) || defined(__LCC__) /* MS C and VC, MinGW32, lcc32 */ /* these systems use the Microsoft C RTL */ /* 64-bit stat struct */ typedef struct _stati64 z_stat; # define Z_STAT_DEFINED # ifdef __LCC__ /* The LCC headers lack these declarations of MSC rtl functions in sys/stat.h. */ struct _stati64 { unsigned int st_dev; unsigned short st_ino; unsigned short st_mode; short st_nlink; short st_uid; short st_gid; unsigned int st_rdev; __int64 st_size; time_t st_atime; time_t st_mtime; time_t st_ctime; }; int _stati64(const char *, struct _stati64 *); int _fstati64(int, struct _stati64 *); __int64 _lseeki64(int, __int64, int); # endif /* __LCC__ */ /* printf format size prefix for zoff_t values */ # define FZOFFT_FMT "I64" # define FZOFFT_HEX_WID_VALUE "16" # define SHORTHDRSTATS "%9I64u %02u%c%02u%c%02u %02u:%02u %c" # define SHORTFILETRAILER " -------- -------\n%9I64u %9lu file%s\n" # elif (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0520)) /* Borland C 5.2 or newer */ /* 64-bit stat struct */ typedef struct stati64 z_stat; # define Z_STAT_DEFINED /* Borland C does not provide a 64-bit-capable _lseeki64(), so we need to use the stdio.h stream functions instead. */ # ifndef USE_STRM_INPUT # define USE_STRM_INPUT # endif /* printf format size prefix for zoff_t values */ # define FZOFFT_FMT "L" # define FZOFFT_HEX_WID_VALUE "16" # define SHORTHDRSTATS "%9Lu %02u%c%02u%c%02u %02u:%02u %c" # define SHORTFILETRAILER " -------- -------\n%9Lu %9lu file%s\n" # elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100)) /* WATCOM C */ /* 64-bit stat struct */ typedef struct _stati64 z_stat; # define Z_STAT_DEFINED /* printf format size prefix for zoff_t values */ # define FZOFFT_FMT "ll" # define FZOFFT_HEX_WID_VALUE "16" # define SHORTHDRSTATS "%9llu %02u%c%02u%c%02u %02u:%02u %c" # define SHORTFILETRAILER " -------- -------\n%9llu %9lu file%s\n" # elif (defined(__IBMC__) && (__IBMC__ >= 350)) /* IBM C */ /* 64-bit stat struct */ /* printf format size prefix for zoff_t values */ # define FZOFFT_FMT "I64" # define FZOFFT_HEX_WID_VALUE "16" # define SHORTHDRSTATS "%9I64u %02u%c%02u%c%02u %02u:%02u %c" # define SHORTFILETRAILER " -------- -------\n%9I64u %9lu file%s\n" # endif #endif /* If port has LARGE_FILE_SUPPORT then define here to make automatic unless overridden */ #ifndef LARGE_FILE_SUPPORT # ifndef NO_LARGE_FILE_SUPPORT # if defined(_MSC_VER) || defined(__MINGW32__) # define LARGE_FILE_SUPPORT # elif defined(__LCC__) /* LCC links against crtdll.dll -> no support of 64-bit offsets :( */ # elif defined(__CYGWIN__) # define LARGE_FILE_SUPPORT # elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100)) # define LARGE_FILE_SUPPORT # elif (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0520)) /* Borland C RTL lacks any support to get/set 64-bit file pointer :( */ # endif # endif #endif #ifndef LARGE_FILE_SUPPORT /* No Large File Support */ /* base type for file offsets and file sizes */ typedef long zoff_t; # define ZOFF_T_DEFINED /* stat struct */ typedef struct stat z_stat; # define Z_STAT_DEFINED # define FZOFFT_FMT "l" # define FZOFFT_HEX_WID_VALUE "8" # define SHORTHDRSTATS "%9lu %02u%c%02u%c%02u %02u:%02u %c" # define SHORTFILETRAILER " -------- -------\n%9lu %9lu file%s\n" #endif /* LARGE_FILE_SUPPORT */ #endif /* !__w32cfg_h */ Carla-2.1/data/windows/unzipfx-carla/win32/win32.c000066400000000000000000003275571364475620200216700ustar00rootroot00000000000000/* Copyright (c) 1990-2008 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2007-Mar-04 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- win32.c 32-bit Windows-specific (NT/9x) routines for use with Info-ZIP's UnZip 5.3 and later. Contains: GetLoadPath() Opendir() Readdir() Closedir() SetSD() set security descriptor on file FindSDExtraField() extract SD e.f. block from extra field IsWinNT() indicate type of WIN32 platform test_NTSD() test integrity of NT security data utime2NtfsFileTime() utime2VFatFileTime() FStampIsLocTime() NtfsFileTime2utime() VFatFileTime2utime() getNTfiletime() SetFileSize() close_outfile() defer_dir_attribs() set_direc_attribs() stamp_file() isfloppy() NTQueryVolInfo() IsVolumeOldFAT() do_wild() mapattr() mapname() maskDOSdevice() map2fat() checkdir() dateformat() dateseparator() version() screensize() zstat_win32() conv_to_rule() GetPlatformLocalTimezone() getch_win32() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include #include "../unzip.h" #ifdef __RSXNT__ # include "../win32/rsxntwin.h" #endif #include "../win32/nt.h" #ifndef FUNZIP /* most of this file is not used with fUnZip */ /* some non-MS runtime headers (e.g. lcc) may miss this definition */ #ifndef FILE_WRITE_ATTRIBUTES # define FILE_WRITE_ATTRIBUTES 0x0100 #endif #if (defined(__EMX__) || defined(__CYGWIN__)) # define MKDIR(path,mode) mkdir(path,mode) #else # define MKDIR(path,mode) mkdir(path) #endif #ifdef HAVE_WORKING_DIRENT_H # undef HAVE_WORKING_DIRENT_H #endif /* The emxrtl dirent support of (__GO32__ || __EMX__) converts to lowercase! */ #if defined(__CYGWIN__) # define HAVE_WORKING_DIRENT_H #endif #ifndef SFX # ifdef HAVE_WORKING_DIRENT_H # include /* use readdir() */ # define zdirent dirent # define zDIR DIR # define Opendir opendir # define Readdir readdir # define Closedir closedir # else /* !HAVE_WORKING_DIRENT_H */ typedef struct zdirent { char reserved [21]; char ff_attrib; short ff_ftime; short ff_fdate; long size; char d_name[MAX_PATH]; int d_first; HANDLE d_hFindFile; } zDIR; static zDIR *Opendir (const char *n); static struct zdirent *Readdir (zDIR *d); static void Closedir (zDIR *d); # endif /* ?HAVE_WORKING_DIRENT_H */ #endif /* !SFX */ #ifdef SET_DIR_ATTRIB typedef struct NTdirattr { /* struct for holding unix style directory */ struct NTdirattr *next; /* info until can be sorted and set at end */ char *fn; /* filename of directory */ FILETIME Modft; /* File time type defined in NT, `last modified' time */ FILETIME Accft; /* NT file time type, `last access' time */ FILETIME Creft; /* NT file time type, `file creation' time */ int gotTime; unsigned perms; /* same as min_info.file_attr */ #ifdef NTSD_EAS unsigned SDlen; /* length of SD data in buf */ #endif char buf[1]; /* buffer stub for directory SD and name */ } NTdirattr; #define NtAtt(d) ((NTdirattr *)d) /* typecast shortcut */ #endif /* SET_DIR_ATTRIB */ /* Function prototypes */ #ifdef NTSD_EAS static int SetSD(__GPRO__ char *path, unsigned fperms, uch *eb_ptr, unsigned eb_len); static int FindSDExtraField(__GPRO__ uch *ef_ptr, unsigned ef_len, uch **p_ebSD_ptr, unsigned *p_ebSD_len); #endif #ifndef NO_W32TIMES_IZFIX static void utime2NtfsFileTime(time_t ut, FILETIME *pft); #endif static void utime2VFatFileTime(time_t ut, FILETIME *pft, int clipDosMin); #if (defined(W32_STAT_BANDAID) && !defined(NO_W32TIMES_IZFIX)) static int NtfsFileTime2utime(const FILETIME *pft, time_t *ut); #endif #ifdef W32_STAT_BANDAID static int VFatFileTime2utime(const FILETIME *pft, time_t *ut); #endif static int FStampIsLocTime(__GPRO__ const char *path); static int getNTfiletime (__GPRO__ FILETIME *pModFT, FILETIME *pAccFT, FILETIME *pCreFT); static int isfloppy (int nDrive); static int NTQueryVolInfo (__GPRO__ const char *name); static int IsVolumeOldFAT (__GPRO__ const char *name); static void maskDOSdevice (__GPRO__ char *pathcomp); static void map2fat (char *pathcomp, char **pEndFAT); #if (defined(__MINGW32__) && !defined(USE_MINGW_GLOBBING)) int _CRT_glob = 0; /* suppress command line globbing by C RTL */ #endif #ifdef ACORN_FTYPE_NFS /* Acorn bits for NFS filetyping */ typedef struct { uch ID[2]; uch size[2]; uch ID_2[4]; uch loadaddr[4]; uch execaddr[4]; uch attr[4]; } RO_extra_block; #endif /* ACORN_FTYPE_NFS */ /* static int created_dir; */ /* used by mapname(), checkdir() */ /* static int renamed_fullpath; */ /* ditto */ /* static int fnlen; */ /* ditto */ /* static unsigned nLabelDrive; */ /* ditto */ extern char Far TruncNTSD[]; /* in extract.c */ #ifdef SFX /**************************/ /* Function GetLoadPath() */ /**************************/ char *GetLoadPath(__GPRO) { #ifdef MSC extern char *_pgmptr; return _pgmptr; #else /* use generic API call */ GetModuleFileName(NULL, G.filename, FILNAMSIZ); _ISO_INTERN(G.filename); /* translate to codepage of C rtl's stdio */ return G.filename; #endif } /* end function GetLoadPath() */ #else /* !SFX */ #ifndef HAVE_WORKING_DIRENT_H /**********************/ /* Borrowed from ZIP 2.0 sources */ /* Function Opendir() */ /* Difference: no special handling for */ /**********************/ /* hidden or system files. */ static zDIR *Opendir(n) const char *n; /* directory to open */ { zDIR *d; /* malloc'd return value */ char *p; /* malloc'd temporary string */ WIN32_FIND_DATAA fd; extent len = strlen(n); /* Start searching for files in directory n */ if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL || (p = malloc(strlen(n) + 5)) == NULL) { if (d != (zDIR *)NULL) free((void *)d); return (zDIR *)NULL; } INTERN_TO_ISO(n, p); if (len > 0) { if (p[len-1] == ':') p[len++] = '.'; /* x: => x:. */ else if (p[len-1] == '/' || p[len-1] == '\\') --len; /* foo/ => foo */ } strcpy(p+len, "/*"); if (INVALID_HANDLE_VALUE == (d->d_hFindFile = FindFirstFileA(p, &fd))) { free((zvoid *)d); free((zvoid *)p); return NULL; } strcpy(d->d_name, fd.cFileName); free((zvoid *)p); d->d_first = 1; return d; } /* end of function Opendir() */ /**********************/ /* Borrowed from ZIP 2.0 sources */ /* Function Readdir() */ /* Difference: no special handling for */ /**********************/ /* hidden or system files. */ static struct zdirent *Readdir(d) zDIR *d; /* directory stream from which to read */ { /* Return pointer to first or next directory entry, or NULL if end. */ if ( d->d_first ) d->d_first = 0; else { WIN32_FIND_DATAA fd; if ( !FindNextFileA(d->d_hFindFile, &fd) ) return NULL; ISO_TO_INTERN(fd.cFileName, d->d_name); } return (struct zdirent *)d; } /* end of function Readdir() */ /***********************/ /* Function Closedir() */ /* Borrowed from ZIP 2.0 sources */ /***********************/ static void Closedir(d) zDIR *d; /* directory stream to close */ { FindClose(d->d_hFindFile); free(d); } #endif /* !HAVE_WORKING_DIRENT_H */ #endif /* ?SFX */ #ifdef NTSD_EAS /**********************/ /* Function SetSD() */ /* return almost-PK errors */ /**********************/ static int SetSD(__G__ path, fperms, eb_ptr, eb_len) __GDEF char *path; unsigned fperms; uch *eb_ptr; unsigned eb_len; { ulg ntsd_ucSize; VOLUMECAPS VolumeCaps; uch *security_data; int error; ntsd_ucSize = makelong(eb_ptr + (EB_HEADSIZE+EB_UCSIZE_P)); if (ntsd_ucSize > 0L && eb_len <= (EB_NTSD_L_LEN + EB_CMPRHEADLEN)) return IZ_EF_TRUNC; /* no compressed data! */ /* provide useful input */ VolumeCaps.dwFileAttributes = fperms; VolumeCaps.bUsePrivileges = (uO.X_flag > 1); /* check target volume capabilities - just fall through * and try if fail */ if (GetVolumeCaps(G.rootpath, path, &VolumeCaps) && !(VolumeCaps.dwFileSystemFlags & FS_PERSISTENT_ACLS)) return PK_OK; /* allocate storage for uncompressed data */ security_data = (uch *)malloc((extent)ntsd_ucSize); if (security_data == (uch *)NULL) return PK_MEM4; error = memextract(__G__ security_data, ntsd_ucSize, (eb_ptr + (EB_HEADSIZE+EB_NTSD_L_LEN)), (ulg)(eb_len - EB_NTSD_L_LEN)); if (error == PK_OK) { if (SecuritySet(path, &VolumeCaps, security_data)) { error = PK_COOL; if (!uO.tflag && QCOND2) Info(slide, 0, ((char *)slide, " (%ld bytes security)", ntsd_ucSize)); } } free(security_data); return error; } /********************************/ /* scan extra fields for something */ /* Function FindSDExtraField() */ /* we happen to know */ /********************************/ /* Returns TRUE when a valid NTFS SD block is found. * Address and size of the NTSD e.f. block are passed up to the caller. * In case of more than one valid NTSD block in the e.f., the last block * found is passed up. * Returns FALSE and leaves the content of the ebSD_ptr and ebSD_len * parameters untouched when no valid NTFS SD block is found. */ static int FindSDExtraField(__GPRO__ uch *ef_ptr, unsigned ef_len, uch **p_ebSD_ptr, unsigned *p_ebSD_len) { int rc = FALSE; if (!uO.X_flag) return FALSE; /* user said don't process ACLs; for now, no other extra block types are handled here */ while (ef_len >= EB_HEADSIZE) { unsigned eb_id = makeword(EB_ID + ef_ptr); unsigned eb_len = makeword(EB_LEN + ef_ptr); if (eb_len > (ef_len - EB_HEADSIZE)) { /* discovered some extra field inconsistency! */ Trace((stderr, "FindSDExtraField: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } switch (eb_id) { /* process security descriptor extra data if: Caller is WinNT AND Target local/remote drive supports acls AND Target file is not a directory (else we defer processing until later) */ case EF_NTSD: if (!IsWinNT()) break; /* OS not capable of handling NTFS attributes */ if (eb_len < EB_NTSD_L_LEN) break; /* not a valid NTSD extra field */ /* check if we know how to handle this version */ if (*(ef_ptr + (EB_HEADSIZE+EB_NTSD_VERSION)) > (uch)EB_NTSD_MAX_VER) break; *p_ebSD_ptr = ef_ptr; *p_ebSD_len = eb_len; rc = TRUE; break; #ifdef DEBUG case EF_OS2: case EF_AV: case EF_PKVMS: case EF_PKW32: case EF_PKUNIX: case EF_IZVMS: case EF_IZUNIX: case EF_IZUNIX2: case EF_TIME: case EF_MAC3: case EF_JLMAC: case EF_ZIPIT: case EF_VMCMS: case EF_MVS: case EF_ACL: case EF_ATHEOS: case EF_BEOS: case EF_QDOS: case EF_AOSVS: case EF_SPARK: case EF_MD5: case EF_ASIUNIX: break; /* shut up for other known e.f. blocks */ #endif /* DEBUG */ default: Trace((stderr, "FindSDExtraField: unknown extra field block, ID=%u\n", eb_id)); break; } ef_ptr += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return rc; } #ifndef SFX /**************************/ /* Function test_NTSD() */ /* returns PK_WARN when NTSD data is invalid */ /**************************/ #ifdef __BORLANDC__ /* Turn off warning about not using all parameters for this function only */ #pragma argsused #endif int test_NTSD(__G__ eb, eb_size, eb_ucptr, eb_ucsize) __GDEF uch *eb; unsigned eb_size; uch *eb_ucptr; ulg eb_ucsize; { return (ValidateSecurity(eb_ucptr) ? PK_OK : PK_WARN); } /* end function test_NTSD() */ #endif /* !SFX */ #endif /* NTSD_EAS */ /**********************/ /* Function IsWinNT() */ /**********************/ int IsWinNT(void) /* returns TRUE if real NT, FALSE if Win9x or Win32s */ { static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */ if (g_PlatformId == 0xFFFFFFFF) { /* note: GetVersionEx() doesn't exist on WinNT 3.1 */ if (GetVersion() < 0x80000000) g_PlatformId = TRUE; else g_PlatformId = FALSE; } return (int)g_PlatformId; } /* DEBUG_TIME insertion: */ #ifdef DEBUG_TIME static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft); static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft) { SYSTEMTIME w32tm; int rval; rval = FileTimeToSystemTime(pft, &w32tm); if (!rval) { fprintf(hdo, "%s\n %08lX,%08lX (%s) -> Conversion failed !!!\n", TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime), (isloc ? "local" : "UTC")); } else { fprintf(hdo, "%s\n %08lx,%08lx -> %04u-%02u-%02u, %02u:%02u:%02u %s\n", TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime), w32tm.wYear, w32tm.wMonth, w32tm.wDay, w32tm.wHour, w32tm.wMinute, w32tm.wSecond, (isloc ? "local" : "UTC")); } return rval; } #define FTTrace(x) show_NTFileTime x #else #define FTTrace(x) #endif /* DEBUG_TIME */ /* end of DEBUG_TIME insertion */ #ifndef IZ_USE_INT64 # if (defined(__GNUC__) || defined(ULONG_LONG_MAX)) typedef long long LLONG64; typedef unsigned long long ULLNG64; # define IZ_USE_INT64 # elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100)) typedef __int64 LLONG64; typedef unsigned __int64 ULLNG64; # define IZ_USE_INT64 # elif (defined(_MSC_VER) && (_MSC_VER >= 1100)) typedef __int64 LLONG64; typedef unsigned __int64 ULLNG64; # define IZ_USE_INT64 # elif (defined(__IBMC__) && (__IBMC__ >= 350)) typedef __int64 LLONG64; typedef unsigned __int64 ULLNG64; # define IZ_USE_INT64 # elif defined(HAVE_INT64) typedef __int64 LLONG64; typedef unsigned __int64 ULLNG64; # define IZ_USE_INT64 # endif #endif /* scale factor and offset for conversion time_t -> FILETIME */ #define NT_QUANTA_PER_UNIX 10000000L #define UNIX_TIME_ZERO_HI 0x019DB1DEUL #define UNIX_TIME_ZERO_LO 0xD53E8000UL /* special FILETIME values for bound-checks */ #define UNIX_TIME_UMAX_HI 0x0236485EUL #define UNIX_TIME_UMAX_LO 0xD4A5E980UL #define UNIX_TIME_SMIN_HI 0x0151669EUL #define UNIX_TIME_SMIN_LO 0xD53E8000UL #define UNIX_TIME_SMAX_HI 0x01E9FD1EUL #define UNIX_TIME_SMAX_LO 0xD4A5E980UL #define DOSTIME_MIN_FT_HI 0x01A8E79FUL #define DOSTIME_MIN_FT_LO 0xE1D58000UL /* time_t equivalent of DOSTIME_MINIMUM */ #define UTIME_1980_JAN_01_00_00 315532800L #ifndef NO_W32TIMES_IZFIX /*********************************/ /* Function utime2NtfsFileTime() */ /* convert Unix time_t format into the */ /*********************************/ /* form used by SetFileTime() in NT/9x */ static void utime2NtfsFileTime(time_t ut, FILETIME *pft) { #ifdef IZ_USE_INT64 ULLNG64 NTtime; /* NT_QUANTA_PER_UNIX is small enough so that "ut * NT_QUANTA_PER_UNIX" * cannot overflow in 64-bit signed calculation, regardless whether "ut" * is signed or unsigned. */ NTtime = ((LLONG64)ut * NT_QUANTA_PER_UNIX) + ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32)); pft->dwLowDateTime = (DWORD)NTtime; pft->dwHighDateTime = (DWORD)(NTtime >> 32); #else /* !IZ_USE_INT64 (64-bit integer arithmetics may not be supported) */ unsigned int b1, b2, carry = 0; unsigned long r0, r1, r2, r3; long r4; /* signed, to catch environments with signed time_t */ b1 = ut & 0xFFFF; b2 = (ut >> 16) & 0xFFFF; /* if ut is over 32 bits, too bad */ r1 = b1 * (NT_QUANTA_PER_UNIX & 0xFFFF); r2 = b1 * (NT_QUANTA_PER_UNIX >> 16); r3 = b2 * (NT_QUANTA_PER_UNIX & 0xFFFF); r4 = b2 * (NT_QUANTA_PER_UNIX >> 16); r0 = (r1 + (r2 << 16)) & 0xFFFFFFFFL; if (r0 < r1) carry++; r1 = r0; r0 = (r0 + (r3 << 16)) & 0xFFFFFFFFL; if (r0 < r1) carry++; pft->dwLowDateTime = r0 + UNIX_TIME_ZERO_LO; if (pft->dwLowDateTime < r0) carry++; pft->dwHighDateTime = r4 + (r2 >> 16) + (r3 >> 16) + UNIX_TIME_ZERO_HI + carry; #endif /* ?IZ_USE_INT64 */ } /* end function utime2NtfsFileTime() */ #endif /* !NO_W32TIMES_IZFIX */ /*********************************/ /* Function utime2VFatFileTime() */ /* convert Unix time_t format into the */ /*********************************/ /* form used by SetFileTime() in NT/9x */ static void utime2VFatFileTime(time_t ut, FILETIME *pft, int clipDosMin) { time_t utc = ut; struct tm *ltm; SYSTEMTIME w32tm; FILETIME lft; /* The milliseconds field gets always initialized to 0. */ w32tm.wMilliseconds = 0; #ifdef __BORLANDC__ /* Borland C++ 5.x crashes when trying to reference tm */ if (utc < UTIME_1980_JAN_01_00_00) utc = UTIME_1980_JAN_01_00_00; #endif ltm = localtime(&utc); if (ltm == (struct tm *)NULL) /* localtime() did not accept given utc time value; try to use the UTC value */ ltm = gmtime(&utc); if (ltm == (struct tm *)NULL) { if (ut <= (UTIME_1980_JAN_01_00_00 + 86400)) { /* use DOSTIME_MINIMUM date instead of "early" failure dates */ w32tm.wYear = 1980; w32tm.wMonth = 1; w32tm.wDay = 1; w32tm.wHour = 0; w32tm.wMinute = 0; w32tm.wSecond = 0; } else { /* as a last resort, use the current system time */ GetLocalTime(&w32tm); } } else if (clipDosMin && (ltm->tm_year < 80)) { w32tm.wYear = 1980; w32tm.wMonth = 1; w32tm.wDay = 1; w32tm.wHour = 0; w32tm.wMinute = 0; w32tm.wSecond = 0; } else { w32tm.wYear = ltm->tm_year + 1900; /* year + 1900 -> year */ w32tm.wMonth = ltm->tm_mon + 1; /* 0..11 -> 1..12 */ w32tm.wDay = ltm->tm_mday; /* 1..31 */ w32tm.wHour = ltm->tm_hour; /* 0..23 */ w32tm.wMinute = ltm->tm_min; /* 0..59 */ w32tm.wSecond = ltm->tm_sec; /* 0..61 in ANSI C */ } SystemTimeToFileTime(&w32tm, &lft); LocalFileTimeToFileTime(&lft, pft); } /* end function utime2VFatFileTime() */ /* nonzero if `y' is a leap year, else zero */ #define leap(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0) /* number of leap years from 1970 to `y' (not including `y' itself) */ #define nleap(y) (((y)-1969)/4 - ((y)-1901)/100 + ((y)-1601)/400) extern ZCONST ush ydays[]; /* defined in fileio.c */ #if (defined(W32_STAT_BANDAID) && !defined(NO_W32TIMES_IZFIX)) /*********************************/ /* Function NtfsFileTime2utime() */ /*********************************/ static int NtfsFileTime2utime(const FILETIME *pft, time_t *ut) { #ifdef IZ_USE_INT64 ULLNG64 NTtime; NTtime = ((ULLNG64)pft->dwLowDateTime + ((ULLNG64)pft->dwHighDateTime << 32)); #ifndef TIME_T_TYPE_DOUBLE /* underflow and overflow handling */ #ifdef CHECK_UTIME_SIGNED_UNSIGNED if ((time_t)0x80000000L < (time_t)0L) { if (NTtime < ((ULLNG64)UNIX_TIME_SMIN_LO + ((ULLNG64)UNIX_TIME_SMIN_HI << 32))) { *ut = (time_t)LONG_MIN; return FALSE; } if (NTtime > ((ULLNG64)UNIX_TIME_SMAX_LO + ((ULLNG64)UNIX_TIME_SMAX_HI << 32))) { *ut = (time_t)LONG_MAX; return FALSE; } } else #endif /* CHECK_UTIME_SIGNED_UNSIGNED */ { if (NTtime < ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32))) { *ut = (time_t)0; return FALSE; } if (NTtime > ((ULLNG64)UNIX_TIME_UMAX_LO + ((ULLNG64)UNIX_TIME_UMAX_HI << 32))) { *ut = (time_t)ULONG_MAX; return FALSE; } } #endif /* !TIME_T_TYPE_DOUBLE */ NTtime -= ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32)); *ut = (time_t)(NTtime / (unsigned long)NT_QUANTA_PER_UNIX); return TRUE; #else /* !IZ_USE_INT64 (64-bit integer arithmetics may not be supported) */ time_t days; SYSTEMTIME w32tm; #ifndef TIME_T_TYPE_DOUBLE /* underflow and overflow handling */ #ifdef CHECK_UTIME_SIGNED_UNSIGNED if ((time_t)0x80000000L < (time_t)0L) { if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) || ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) && (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) { *ut = (time_t)LONG_MIN; return FALSE; if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) || ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) && (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) { *ut = (time_t)LONG_MAX; return FALSE; } } else #endif /* CHECK_UTIME_SIGNED_UNSIGNED */ { if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) || ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) && (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) { *ut = (time_t)0; return FALSE; } if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) || ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) && (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) { *ut = (time_t)ULONG_MAX; return FALSE; } } #endif /* !TIME_T_TYPE_DOUBLE */ FileTimeToSystemTime(pft, &w32tm); /* set `days' to the number of days into the year */ days = w32tm.wDay - 1 + ydays[w32tm.wMonth-1] + (w32tm.wMonth > 2 && leap (w32tm.wYear)); /* now set `days' to the number of days since 1 Jan 1970 */ days += 365 * (time_t)(w32tm.wYear - 1970) + (time_t)(nleap(w32tm.wYear)); *ut = (time_t)(86400L * days + 3600L * (time_t)w32tm.wHour + (time_t)(60 * w32tm.wMinute + w32tm.wSecond)); return TRUE; #endif /* ?IZ_USE_INT64 */ } /* end function NtfsFileTime2utime() */ #endif /* W32_STAT_BANDAID && !NO_W32TIMES_IZFIX */ #ifdef W32_STAT_BANDAID /*********************************/ /* Function VFatFileTime2utime() */ /*********************************/ static int VFatFileTime2utime(const FILETIME *pft, time_t *ut) { FILETIME lft; #ifndef HAVE_MKTIME WORD wDOSDate, wDOSTime; #else SYSTEMTIME w32tm; struct tm ltm; #endif if (!FileTimeToLocalFileTime(pft, &lft)) { /* if pft cannot be converted to local time, set ut to current time */ time(ut); return FALSE; } FTTrace((stdout, "VFatFT2utime, feed for mktime()", 1, &lft)); #ifndef HAVE_MKTIME /* This version of the FILETIME-to-UNIXTIME conversion function * uses DOS-DATE-TIME format as intermediate stage. For modification * and access times, this is no problem. But, the extra fine resolution * of the VFAT-stored creation time gets lost. */ if (!FileTimeToDosDateTime(&lft, &wDOSDate, &wDOSTime)) { static const FILETIME dosmin_ft = {DOSTIME_MIN_FT_LO, DOSTIME_MIN_FT_HI}; if (CompareFileTime(&lft, &dosmin_ft) <= 0) { /* underflow -> set to minimum DOS time */ wDOSDate = (WORD)((DWORD)DOSTIME_MINIMUM >> 16); wDOSTime = (WORD)DOSTIME_MINIMUM; } else { /* overflow -> set to maximum DOS time */ wDOSDate = (WORD)0xFF9F; /* 2107-12-31 */ wDOSTime = (WORD)0xBF7D; /* 23:59:58 */ } } TTrace((stdout,"DosDateTime is %04u-%02u-%02u %02u:%02u:%02u\n", (unsigned)((wDOSDate>>9)&0x7f)+1980,(unsigned)((wDOSDate>>5)&0x0f), (unsigned)(wDOSDate&0x1f),(unsigned)((wDOSTime>>11)&0x1f), (unsigned)((wDOSTime>>5)&0x3f),(unsigned)((wDOSTime<<1)&0x3e))); *ut = dos_to_unix_time(((ulg)wDOSDate << 16) | (ulg)wDOSTime); /* a cheap error check: dos_to_unix_time() only returns an odd time * when clipping at maximum time_t value. DOS_DATE_TIME values have * a resolution of 2 seconds and are therefore even numbers. */ return (((*ut)&1) == (time_t)0); #else /* HAVE_MKTIME */ FileTimeToSystemTime(&lft, &w32tm); #ifndef TIME_T_TYPE_DOUBLE /* underflow and overflow handling */ /* TODO: The range checks are not accurate, the actual limits may * be off by one daylight-saving-time shift (typically 1 hour), * depending on the current state of "is_dst". */ #ifdef CHECK_UTIME_SIGNED_UNSIGNED if ((time_t)0x80000000L < (time_t)0L) { if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) || ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) && (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) { *ut = (time_t)LONG_MIN; return FALSE; if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) || ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) && (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) { *ut = (time_t)LONG_MAX; return FALSE; } } else #endif /* CHECK_UTIME_SIGNED_UNSIGNED */ { if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) || ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) && (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) { *ut = (time_t)0; return FALSE; } if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) || ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) && (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) { *ut = (time_t)ULONG_MAX; return FALSE; } } #endif /* !TIME_T_TYPE_DOUBLE */ ltm.tm_year = w32tm.wYear - 1900; ltm.tm_mon = w32tm.wMonth - 1; ltm.tm_mday = w32tm.wDay; ltm.tm_hour = w32tm.wHour; ltm.tm_min = w32tm.wMinute; ltm.tm_sec = w32tm.wSecond; ltm.tm_isdst = -1; /* let mktime determine if DST is in effect */ *ut = mktime(<m); /* a cheap error check: mktime returns "(time_t)-1L" on conversion errors. * Normally, we would have to apply a consistency check because "-1" * could also be a valid time. But, it is quite unlikely to read back odd * time numbers from file systems that store time stamps in DOS format. * (The only known exception is creation time on VFAT partitions.) */ return (*ut != (time_t)-1L); #endif /* ?HAVE_MKTIME */ } /* end function VFatFileTime2utime() */ #endif /* W32_STAT_BANDAID */ /******************************/ /* Function FStampIsLocTime() */ /******************************/ static int FStampIsLocTime(__GPRO__ const char *path) { return (NTQueryVolInfo(__G__ path) ? G.lastVolLocTim : FALSE); } #ifndef NO_W32TIMES_IZFIX # define UTIME_2_IZFILETIME(ut, pft) \ if (fs_uses_loctime) {utime2VFatFileTime(ut, pft, TRUE);} \ else {utime2NtfsFileTime(ut, pft);} #else # define UTIME_2_IZFILETIME(ut, pft) \ utime2VFatFileTime(ut, pft, fs_uses_loctime); #endif /****************************/ /* Get the file time in a format that */ /* Function getNTfiletime() */ /* can be used by SetFileTime() in NT */ /****************************/ static int getNTfiletime(__G__ pModFT, pAccFT, pCreFT) __GDEF FILETIME *pModFT; FILETIME *pAccFT; FILETIME *pCreFT; { #ifdef USE_EF_UT_TIME unsigned eb_izux_flg; iztimes z_utime; /* struct for Unix-style actime & modtime, + creatime */ #endif int fs_uses_loctime = FStampIsLocTime(__G__ G.filename); /* Copy and/or convert time and date variables, if necessary; * return a flag indicating which time stamps are available. */ #ifdef USE_EF_UT_TIME if (G.extra_field && #ifdef IZ_CHECK_TZ G.tz_is_valid && #endif ((eb_izux_flg = ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, &z_utime, NULL)) & EB_UT_FL_MTIME)) { TTrace((stderr, "getNTfiletime: Unix e.f. modif. time = %lu\n", z_utime.mtime)); UTIME_2_IZFILETIME(z_utime.mtime, pModFT) if (eb_izux_flg & EB_UT_FL_ATIME) { UTIME_2_IZFILETIME(z_utime.atime, pAccFT) } if (eb_izux_flg & EB_UT_FL_CTIME) { UTIME_2_IZFILETIME(z_utime.ctime, pCreFT) } return (int)eb_izux_flg; } #endif /* USE_EF_UT_TIME */ #ifndef NO_W32TIMES_IZFIX if (!fs_uses_loctime) { time_t ux_modtime; ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); utime2NtfsFileTime(ux_modtime, pModFT); } else #endif /* NO_W32TIMES_IZFIX */ { FILETIME lft; DosDateTimeToFileTime((WORD)(G.lrec.last_mod_dos_datetime >> 16), (WORD)(G.lrec.last_mod_dos_datetime & 0xFFFFL), &lft); LocalFileTimeToFileTime(&lft, pModFT); } *pAccFT = *pModFT; return (EB_UT_FL_MTIME | EB_UT_FL_ATIME); } /* end function getNTfiletime() */ /**************************/ /* Function SetFileSize() */ /**************************/ int SetFileSize(FILE *file, zusz_t filesize) { #ifdef __RSXNT__ /* RSXNT environment lacks a translation function from C file pointer to Win32-API file handle. So, simply do nothing. */ return 0; #else /* !__RSXNT__ */ /* not yet verified, if that really creates an unfragmented file rommel@ars.de */ HANDLE os_fh; #ifdef Z_UINT8_DEFINED LARGE_INTEGER fsbuf; #endif /* Win9x supports FAT file system, only; presetting file size does not help to prevent fragmentation. */ if (!IsWinNT()) return 0; /* Win32-API calls require access to the Win32 file handle. The interface function used to retrieve the Win32 handle for a file opened by the C rtl is non-standard and may not be available for every Win32 compiler environment. (see also win32/win32.c of the Zip distribution) */ os_fh = (HANDLE)_get_osfhandle(fileno(file)); /* move file pointer behind the last byte of the expected file size */ #ifdef Z_UINT8_DEFINED fsbuf.QuadPart = filesize; if ((SetFilePointer(os_fh, fsbuf.LowPart, &fsbuf.HighPart, FILE_BEGIN) == 0xFFFFFFFF) && GetLastError() != NO_ERROR) #else if (SetFilePointer(os_fh, (ulg)filesize, 0, FILE_BEGIN) == 0xFFFFFFFF) #endif return -1; /* extend/truncate file to the current position */ if (SetEndOfFile(os_fh) == 0) return -1; /* move file position pointer back to the start of the file! */ return (SetFilePointer(os_fh, 0, 0, FILE_BEGIN) == 0xFFFFFFFF) ? -1 : 0; #endif /* ?__RSXNT__ */ } /* end function SetFileSize() */ /****************************/ /* Function close_outfile() */ /****************************/ void close_outfile(__G) __GDEF { FILETIME Modft; /* File time type defined in NT, `last modified' time */ FILETIME Accft; /* NT file time type, `last access' time */ FILETIME Creft; /* NT file time type, `file creation' time */ HANDLE hFile = INVALID_HANDLE_VALUE; /* File handle defined in NT */ int gotTime; #ifdef NTSD_EAS uch *ebSDptr; unsigned ebSDlen; #endif #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(G.filename) + 1); INTERN_TO_ISO(G.filename, ansi_name); # define Ansi_Fname ansi_name #else # define Ansi_Fname G.filename #endif #ifndef __RSXNT__ if (IsWinNT()) { /* Truncate the file to the current position. * This is needed to remove excess allocation in case the * extraction has failed or stopped prematurely. */ SetEndOfFile((HANDLE)_get_osfhandle(fileno(G.outfile))); } #endif /* Close the file and then re-open it using the Win32 * CreateFile call, so that the file can be created * with GENERIC_WRITE access, otherwise the SetFileTime * call will fail. */ fclose(G.outfile); /* don't set the time stamp and attributes on standard output */ if (uO.cflag) return; /* skip restoring time stamps on user's request */ if (uO.D_flag <= 1) { gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft); /* open a handle to the file before processing extra fields; we do this in case new security on file prevents us from updating time stamps */ hFile = CreateFileA(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } else { gotTime = 0; } /* sfield@microsoft.com: set attributes before time in case we decide to support other filetime members later. This also allows us to apply attributes before the security is changed, which may prevent this from succeeding otherwise. Also, since most files don't have any interesting attributes, only change them if something other than FILE_ATTRIBUTE_ARCHIVE appears in the attributes. This works well as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the file anyway, when it's created new. */ if ((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) { if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F)) Info(slide, 1, ((char *)slide, "\nwarning (%d): could not set file attributes\n", (int)GetLastError())); } #ifdef NTSD_EAS /* set NTFS SD extra fields */ if (G.extra_field && /* zipfile extra field may have extended attribs */ FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length, &ebSDptr, &ebSDlen)) { int err = SetSD(__G__ Ansi_Fname, G.pInfo->file_attr, ebSDptr, ebSDlen); if (err == IZ_EF_TRUNC) { if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD), ebSDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), uO.qflag? "\n":"")); } } #endif /* NTSD_EAS */ /* skip restoring time stamps on user's request */ if (uO.D_flag <= 1) { if ( hFile == INVALID_HANDLE_VALUE ) Info(slide, 1, ((char *)slide, "\nCreateFile() error %d when trying set file time\n", (int)GetLastError())); else { if (gotTime) { FILETIME *pModft = (gotTime & EB_UT_FL_MTIME) ? &Modft : NULL; FILETIME *pAccft = (gotTime & EB_UT_FL_ATIME) ? &Accft : NULL; FILETIME *pCreft = (gotTime & EB_UT_FL_CTIME) ? &Creft : NULL; if (!SetFileTime(hFile, pCreft, pAccft, pModft)) Info(slide, 0, ((char *)slide, "\nSetFileTime failed: %d\n", (int)GetLastError())); } CloseHandle(hFile); } } return; #undef Ansi_Fname } /* end function close_outfile() */ #ifdef SET_DIR_ATTRIB int defer_dir_attribs(__G__ pd) __GDEF direntry **pd; { NTdirattr *d_entry; #ifdef NTSD_EAS uch *ebSDptr; unsigned ebSDlen; #endif /* Win9x does not support setting directory time stamps. */ if (!IsWinNT()) { *pd = (direntry *)NULL; return PK_OK; } #ifdef NTSD_EAS /* set extended attributes from extra fields */ if (G.extra_field && /* zipfile e.f. may have extended attribs */ FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length, &ebSDptr, &ebSDlen)) { /* ebSDlen contains the payload size of the e.f. block, but we store it including the e.b. header. */ ebSDlen += EB_HEADSIZE; } else { /* no NTSD e.f. block -> no space needed to allocate */ ebSDlen = 0; } #endif /* NTSD_EAS */ d_entry = (NTdirattr *)malloc(sizeof(NTdirattr) #ifdef NTSD_EAS + ebSDlen #endif + strlen(G.filename)); *pd = (direntry *)d_entry; if (d_entry == (NTdirattr *)NULL) { return PK_MEM; } #ifdef NTSD_EAS if (ebSDlen > 0) memcpy(d_entry->buf, ebSDptr, ebSDlen); d_entry->SDlen = ebSDlen; d_entry->fn = d_entry->buf + ebSDlen; #else d_entry->fn = d_entry->buf; #endif strcpy(d_entry->fn, G.filename); d_entry->perms = G.pInfo->file_attr; d_entry->gotTime = (uO.D_flag <= 0 ? getNTfiletime(__G__ &(d_entry->Modft), &(d_entry->Accft), &(d_entry->Creft)) : 0); return PK_OK; } /* end function defer_dir_attribs() */ int set_direc_attribs(__G__ d) __GDEF direntry *d; { int errval; HANDLE hFile = INVALID_HANDLE_VALUE; /* File handle defined in NT */ #ifdef __RSXNT__ char *ansi_name; #endif /* Win9x does not support setting directory time stamps. */ if (!IsWinNT()) return PK_OK; errval = PK_OK; #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ ansi_name = (char *)alloca(strlen(d->fn) + 1); INTERN_TO_ISO(d->fn, ansi_name); # define Ansi_Dirname ansi_name #else # define Ansi_Dirname d->fn #endif /* Skip restoring directory time stamps on user' request. */ if (uO.D_flag <= 0) { /* Open a handle to the directory before processing extra fields; we do this in case new security on file prevents us from updating time stamps. Although the WIN32 documentation recommends to use GENERIC_WRITE access flag to create the handle for SetFileTime(), this is too demanding for directories with the "read-only" attribute bit set. So we use the more specific flag FILE_WRITE_ATTRIBUTES here to request the minimum required access rights. (This problem is a Windows bug that has been silently fixed in Windows XP SP2.) */ hFile = CreateFileA(Ansi_Dirname, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #ifdef NTSD_EAS if (NtAtt(d)->SDlen > 0) { int err; if (QCOND2) { Info(slide, 1, ((char *)slide, " set attrib: %-22s ", FnFilter1(d->fn))); } /* set NTFS SD extra fields */ err = SetSD(__G__ Ansi_Dirname, NtAtt(d)->perms, NtAtt(d)->buf, NtAtt(d)->SDlen - EB_HEADSIZE); if (err == IZ_EF_TRUNC) { if (!QCOND2) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(d->fn))); Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD), NtAtt(d)->SDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n")); } else if (QCOND2) { Info(slide, 0, ((char *)slide, "\n")); } if (errval < err) errval = err; } #endif /* NTSD_EAS */ /* Skip restoring directory time stamps on user' request. */ if (uO.D_flag <= 0) { if (hFile == INVALID_HANDLE_VALUE) { Info(slide, 1, ((char *)slide, "warning: CreateFile() error %d (set file times for %s)\n", (int)GetLastError(), FnFilter1(d->fn))); if (!errval) errval = PK_WARN; } else { if (NtAtt(d)->gotTime) { FILETIME *pModft = (NtAtt(d)->gotTime & EB_UT_FL_MTIME) ? &(NtAtt(d)->Modft) : NULL; FILETIME *pAccft = (NtAtt(d)->gotTime & EB_UT_FL_ATIME) ? &(NtAtt(d)->Accft) : NULL; FILETIME *pCreft = (NtAtt(d)->gotTime & EB_UT_FL_CTIME) ? &(NtAtt(d)->Creft) : NULL; if (!SetFileTime(hFile, pCreft, pAccft, pModft)) { Info(slide, 0, ((char *)slide, "warning: SetFileTime() for %s error %d\n", FnFilter1(d->fn), (int)GetLastError())); if (!errval) errval = PK_WARN; } } CloseHandle(hFile); } } return errval; } /* end function set_direc_attribs() */ #endif /* SET_DIR_ATTRIB */ #ifdef TIMESTAMP /*************************/ /* Function stamp_file() */ /*************************/ int stamp_file(__GPRO__ ZCONST char *fname, time_t modtime) { FILETIME Modft; /* File time type defined in NT, `last modified' time */ HANDLE hFile; /* File handle defined in NT */ int errstat = 0; /* return status: 0 == "OK", -1 == "Failure" */ int fs_uses_loctime = FStampIsLocTime(__G__ fname); #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(fname) + 1); INTERN_TO_ISO(fname, ansi_name); # define Ansi_Fname ansi_name #else # define Ansi_Fname fname #endif /* open a handle to the file to prepare setting the mod-time stamp */ hFile = CreateFileA(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if ( hFile == INVALID_HANDLE_VALUE ) { errstat = -1; } else { /* convert time_t modtime into WIN32 native 64bit format */ UTIME_2_IZFILETIME(modtime, &Modft) /* set Access and Modification times of the file to modtime */ if (!SetFileTime(hFile, NULL, &Modft, &Modft)) { errstat = -1; } CloseHandle(hFile); } return errstat; #undef Ansi_Fname } /* end function stamp_file() */ #endif /* TIMESTAMP */ /***********************/ /* Function isfloppy() */ /* more precisely, is it removable? */ /***********************/ static int isfloppy(int nDrive) /* 1 == A:, 2 == B:, etc. */ { char rootPathName[4]; rootPathName[0] = (char)('A' + nDrive - 1); /* build the root path */ rootPathName[1] = ':'; /* name, e.g. "A:/" */ rootPathName[2] = '/'; rootPathName[3] = '\0'; return (GetDriveTypeA(rootPathName) == DRIVE_REMOVABLE); } /* end function isfloppy() */ /*****************************/ /* Function NTQueryVolInfo() */ /*****************************/ /* * Note: 8.3 limits on filenames apply only to old-style FAT filesystems. * More recent versions of Windows (Windows NT 3.5 / Windows 4.0) * can support long filenames (LFN) on FAT filesystems. Check the * filesystem maximum component length field to detect LFN support. */ static int NTQueryVolInfo(__GPRO__ const char *name) { /* static char lastRootPath[4] = ""; */ /* static int lastVolOldFAT; */ /* static int lastVolLocTim; */ char *tmp0; char tmp1[MAX_PATH], tmp2[MAX_PATH]; DWORD volSerNo, maxCompLen, fileSysFlags; #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(name) + 1); INTERN_TO_ISO(name, ansi_name); name = ansi_name; #endif if ((!strncmp(name, "//", 2) || !strncmp(name, "\\\\", 2)) && (name[2] != '\0' && name[2] != '/' && name[2] != '\\')) { /* GetFullPathname() and GetVolumeInformation() do not work * on UNC names. For now, we return "error". * **FIXME**: check if UNC name is mapped to a drive letter * and use mapped drive for volume info query. */ return FALSE; } if (isalpha((uch)name[0]) && (name[1] == ':')) tmp0 = (char *)name; else { if (!GetFullPathNameA(name, MAX_PATH, tmp1, &tmp0)) return FALSE; tmp0 = &tmp1[0]; } if (strncmp(G.lastRootPath, tmp0, 2) != 0) { /* For speed, we skip repeated queries for the same device */ strncpy(G.lastRootPath, tmp0, 2); /* Build the root path name, */ G.lastRootPath[2] = '/'; /* e.g. "A:/" */ G.lastRootPath[3] = '\0'; if (!GetVolumeInformationA((LPCSTR)G.lastRootPath, (LPSTR)tmp1, (DWORD)MAX_PATH, &volSerNo, &maxCompLen, &fileSysFlags, (LPSTR)tmp2, (DWORD)MAX_PATH)) { G.lastRootPath[0] = '\0'; return FALSE; } /* LFNs are available if the component length is > 12 */ G.lastVolOldFAT = (maxCompLen <= 12); /* G.lastVolOldFAT = !strncmp(strupr(tmp2), "FAT", 3); old version */ /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in * local time! */ G.lastVolLocTim = !strncmp(strupr(tmp2), "VFAT", 4) || !strncmp(tmp2, "HPFS", 4) || !strncmp(tmp2, "FAT", 3); } return TRUE; } /* end function NTQueryVolInfo() */ /*****************************/ /* Function IsVolumeOldFAT() */ /*****************************/ static int IsVolumeOldFAT(__GPRO__ const char *name) { return (NTQueryVolInfo(__G__ name) ? G.lastVolOldFAT : FALSE); } #ifndef SFX /************************/ /* Function do_wild() */ /* identical to OS/2 version */ /************************/ char *do_wild(__G__ wildspec) __GDEF ZCONST char *wildspec; /* only used first time on a given dir */ { /* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in w32cfg.h: static zDIR *wild_dir = NULL; static ZCONST char *wildname; static char *dirname, matchname[FILNAMSIZ]; static int notfirstcall=FALSE, have_dirname, dirnamelen; */ char *fnamestart; struct zdirent *file; /* Even when we're just returning wildspec, we *always* do so in * matchname[]--calling routine is allowed to append four characters * to the returned string, and wildspec may be a pointer to argv[]. */ if (!G.notfirstcall) { /* first call: must initialize everything */ G.notfirstcall = TRUE; if (!iswild(wildspec)) { strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; G.have_dirname = FALSE; G.wild_dir = NULL; return G.matchname; } /* break the wildspec into a directory part and a wildcard filename */ if ((G.wildname = MBSRCHR(wildspec, '/')) == (ZCONST char *)NULL && (G.wildname = MBSRCHR(wildspec, ':')) == (ZCONST char *)NULL) { G.dirname = "."; G.dirnamelen = 1; G.have_dirname = FALSE; G.wildname = wildspec; } else { ++G.wildname; /* point at character after '/' or ':' */ G.dirnamelen = G.wildname - wildspec; if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == NULL) { Info(slide, 1, ((char *)slide, "warning: cannot allocate wildcard buffers\n")); strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; return G.matchname; /* but maybe filespec was not a wildcard */ } strncpy(G.dirname, wildspec, G.dirnamelen); G.dirname[G.dirnamelen] = '\0'; /* terminate for strcpy below */ G.have_dirname = TRUE; } Trace((stderr, "do_wild: dirname = [%s]\n", FnFilter1(G.dirname))); if ((G.wild_dir = (zvoid *)Opendir(G.dirname)) != NULL) { if (G.have_dirname) { strcpy(G.matchname, G.dirname); fnamestart = G.matchname + G.dirnamelen; } else fnamestart = G.matchname; while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) { Trace((stderr, "do_wild: Readdir returns %s\n", FnFilter1(file->d_name))); strcpy(fnamestart, file->d_name); if (MBSRCHR(fnamestart, '.') == (char *)NULL) strcat(fnamestart, "."); if (match(fnamestart, G.wildname, TRUE WISEP) && /* skip "." and ".." directory entries */ strcmp(fnamestart, ".") && strcmp(fnamestart, "..")) { Trace((stderr, "do_wild: match() succeeds\n")); /* remove trailing dot */ fnamestart = plastchar(fnamestart, strlen(fnamestart)); if (*fnamestart == '.') *fnamestart = '\0'; return G.matchname; } } /* if we get to here directory is exhausted, so close it */ Closedir((zDIR *)G.wild_dir); G.wild_dir = NULL; } Trace((stderr, "do_wild: Opendir(%s) returns NULL\n", FnFilter1(G.dirname))); /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; return G.matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if (G.wild_dir == NULL) { G.notfirstcall = FALSE; /* reset for new wildspec */ if (G.have_dirname) free(G.dirname); return (char *)NULL; } /* If we've gotten this far, we've read and matched at least one entry * successfully (in a previous call), so dirname has been copied into * matchname already. */ if (G.have_dirname) { /* strcpy(G.matchname, G.dirname); */ fnamestart = G.matchname + G.dirnamelen; } else fnamestart = G.matchname; while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) { Trace((stderr, "do_wild: readdir returns %s\n", FnFilter1(file->d_name))); strcpy(fnamestart, file->d_name); if (MBSRCHR(fnamestart, '.') == (char *)NULL) strcat(fnamestart, "."); if (match(fnamestart, G.wildname, TRUE WISEP)) { Trace((stderr, "do_wild: match() succeeds\n")); /* remove trailing dot */ fnamestart = plastchar(fnamestart, strlen(fnamestart)); if (*fnamestart == '.') *fnamestart = '\0'; return G.matchname; } } Closedir((zDIR *)G.wild_dir); /* at least one entry read; nothing left */ G.wild_dir = NULL; G.notfirstcall = FALSE; /* reset for new wildspec */ if (G.have_dirname) free(G.dirname); return (char *)NULL; } /* end function do_wild() */ #endif /* !SFX */ /**********************/ /* Function mapattr() */ /**********************/ /* Identical to MS-DOS, OS/2 versions. However, NT has a lot of extra * permission stuff, so this function should probably be extended in the * future. */ int mapattr(__G) __GDEF { /* set archive bit for file entries (file is not backed up): */ G.pInfo->file_attr = ((unsigned)G.crec.external_file_attributes | (G.crec.external_file_attributes & FILE_ATTRIBUTE_DIRECTORY ? 0 : FILE_ATTRIBUTE_ARCHIVE)) & 0xff; return 0; } /* end function mapattr() */ /************************/ /* Function mapname() */ /************************/ int mapname(__G__ renamed) __GDEF int renamed; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - caution (truncated filename) * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) * MPN_ERR_SKIP - error -> skip entry * MPN_ERR_TOOLONG - error -> path is too long * MPN_NOMEM - error (memory allocation failed) -> skip entry * [also MPN_VOL_LABEL, MPN_CREATED_DIR] */ { char pathcomp[FILNAMSIZ]; /* path-component buffer */ char *pp, *cp=NULL; /* character pointers */ char *lastsemi = NULL; /* pointer to last semi-colon in pathcomp */ #ifdef ACORN_FTYPE_NFS char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ #endif int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ int error; register unsigned workch; /* hold the character being tested */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ /* can create path as long as not just freshening, or if user told us */ G.create_dirs = (!uO.fflag || renamed); G.created_dir = FALSE; /* not yet */ G.renamed_fullpath = FALSE; G.fnlen = strlen(G.filename); if (renamed) { cp = G.filename; /* point to beginning of renamed name... */ if (*cp) do { if (*cp == '\\') /* convert backslashes to forward */ *cp = '/'; } while (*PREINCSTR(cp)); cp = G.filename; /* use temporary rootpath if user gave full pathname */ if (G.filename[0] == '/') { G.renamed_fullpath = TRUE; pathcomp[0] = '/'; /* copy the '/' and terminate */ pathcomp[1] = '\0'; ++cp; } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') { G.renamed_fullpath = TRUE; pp = pathcomp; *pp++ = *cp++; /* copy the "d:" (+ '/', possibly) */ *pp++ = *cp++; if (*cp == '/') *pp++ = *cp++; /* otherwise add "./"? */ *pp = '\0'; } } /* pathcomp is ignored unless renamed_fullpath is TRUE: */ if ((error = checkdir(__G__ pathcomp, INIT)) != 0) /* init path buffer */ return error; /* ...unless no mem or vol label on hard disk */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (!renamed) { /* cp already set if renamed */ if (uO.jflag) /* junking directories */ cp = (char *)MBSRCHR(G.filename, '/'); if (cp == NULL) /* no '/' or not junking dirs */ cp = G.filename; /* point to internal zipfile-member pathname */ else ++cp; /* point to start of last component of path */ } /*--------------------------------------------------------------------------- Begin main loop through characters in filename. ---------------------------------------------------------------------------*/ for (; (workch = (uch)*cp) != 0; INCSTR(cp)) { switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; maskDOSdevice(__G__ pathcomp); if (strcmp(pathcomp, ".") == 0) { /* don't bother appending "./" to the path */ *pathcomp = '\0'; } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { /* "../" dir traversal detected, skip over it */ *pathcomp = '\0'; killed_ddot = TRUE; /* set "show message" flag */ } /* when path component is not empty, append it now */ if (*pathcomp != '\0' && ((error = checkdir(__G__ pathcomp, APPEND_DIR)) & MPN_MASK) > MPN_INF_TRUNC) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ break; case ':': /* drive spec not stored, so no colon allowed */ case '\\': /* '\\' may come as normal filename char (not */ case '<': /* dir sep char!) from unix-like file system */ case '>': /* no redirection symbols allowed either */ case '|': /* no pipe signs allowed */ case '"': /* no double quotes allowed */ case '?': /* no wildcards allowed */ case '*': *pp++ = '_'; /* these rules apply equally to FAT and NTFS */ break; case ';': /* start of VMS version? */ lastsemi = pp; /* remove VMS version later... */ *pp++ = ';'; /* but keep semicolon for now */ break; #ifdef ACORN_FTYPE_NFS case ',': /* NFS filetype extension */ lastcomma = pp; *pp++ = ','; /* keep for now; may need to remove */ break; /* later, if requested */ #endif case ' ': /* keep spaces unless specifically */ /* NT cannot create filenames with spaces on FAT volumes */ if (uO.sflag || IsVolumeOldFAT(__G__ G.filename)) *pp++ = '_'; else *pp++ = ' '; break; default: /* allow European characters in filenames: */ if (isprint(workch) || workch >= 127) #ifdef _MBCS { memcpy(pp, cp, CLEN(cp)); INCSTR(pp); } #else *pp++ = (char)workch; #endif } /* end switch */ } /* end while loop */ /* Show warning when stripping insecure "parent dir" path components */ if (killed_ddot && QCOND2) { Info(slide, 0, ((char *)slide, "warning: skipped \"../\" path component(s) in %s\n", FnFilter1(G.filename))); if (!(error & ~MPN_MASK)) error = (error & MPN_MASK) | PK_WARN; } /*--------------------------------------------------------------------------- Report if directory was created (and no file to create: filename ended in '/'), check name to be sure it exists, and combine path and name be- fore exiting. ---------------------------------------------------------------------------*/ if (lastchar(G.filename, G.fnlen) == '/') { #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(G.filename) + 1); INTERN_TO_ISO(G.filename, ansi_name); # define Ansi_Fname ansi_name #else # define Ansi_Fname G.filename #endif checkdir(__G__ G.filename, GETPATH); if (G.created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %-22s\n", FnFilter1(G.filename))); } /* set file attributes: The default for newly created directories is "DIR attribute flags set", so there is no need to change attributes unless one of the DOS style attribute flags is set. The readonly attribute need not be masked, since it does not prevent modifications in the new directory. */ if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) { if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F)) Info(slide, 1, ((char *)slide, "\nwarning (%d): could not set file attributes for %s\n", (int)GetLastError(), FnFilter1(G.filename))); } /* set dir time (note trailing '/') */ return (error & ~MPN_MASK) | MPN_CREATED_DIR; } else if (IS_OVERWRT_ALL) { /* overwrite attributes of existing directory on user's request */ /* set file attributes: */ if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) { if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F)) Info(slide, 1, ((char *)slide, "\nwarning (%d): could not set file attributes for %s\n", (int)GetLastError(), FnFilter1(G.filename))); } } /* dir existed already; don't look for data to extract */ return (error & ~MPN_MASK) | MPN_INF_SKIP; } *pp = '\0'; /* done with pathcomp: terminate it */ /* if not saving them, remove VMS version numbers (appended "###") */ if (!uO.V_flag && lastsemi) { pp = lastsemi + 1; /* semi-colon was kept: expect #'s after */ while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; } #ifdef ACORN_FTYPE_NFS /* translate Acorn filetype information if asked to do so */ if (uO.acorn_nfs_ext && (ef_spark = (RO_extra_block *) getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) != (RO_extra_block *)NULL) { /* file *must* have a RISC OS extra field */ long ft = (long)makelong(ef_spark->loadaddr); /*32-bit*/ if (lastcomma) { pp = lastcomma + 1; while (isxdigit((uch)(*pp))) ++pp; if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ } if ((ft & 1<<31)==0) ft=0x000FFD00; sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); } #endif /* ACORN_FTYPE_NFS */ maskDOSdevice(__G__ pathcomp); if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", FnFilter1(G.filename))); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ checkdir(__G__ G.filename, GETPATH); if (G.pInfo->vollabel) { /* set the volume label now */ char drive[4]; #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(G.filename) + 1); INTERN_TO_ISO(G.filename, ansi_name); # define Ansi_Fname ansi_name #else # define Ansi_Fname G.filename #endif /* Build a drive string, e.g. "b:" */ drive[0] = (char)('a' + G.nLabelDrive - 1); strcpy(drive + 1, ":\\"); if (QCOND2) Info(slide, 0, ((char *)slide, "labelling %s %-22s\n", drive, FnFilter1(G.filename))); if (!SetVolumeLabelA(drive, Ansi_Fname)) { Info(slide, 1, ((char *)slide, "mapname: error setting volume label\n")); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } /* success: skip the "extraction" quietly */ return (error & ~MPN_MASK) | MPN_INF_SKIP; #undef Ansi_Fname } Trace((stderr, "mapname returns with filename = [%s] (error = %d)\n\n", FnFilter1(G.filename), error)); return error; } /* end function mapname() */ /****************************/ /* Function maskDOSdevice() */ /****************************/ static void maskDOSdevice(__G__ pathcomp) __GDEF char *pathcomp; { /*--------------------------------------------------------------------------- Put an underscore in front of the file name if the file name is a DOS/WINDOWS device name like CON.*, AUX.*, PRN.*, etc. Trying to extract such a file would fail at best and wedge us at worst. ---------------------------------------------------------------------------*/ #if !defined(S_IFCHR) && defined(_S_IFCHR) # define S_IFCHR _S_IFCHR #endif #if !defined(S_ISCHR) # if defined(_S_ISCHR) # define S_ISCHR(m) _S_ISCHR(m) # elif defined(S_IFCHR) # define S_ISCHR(m) ((m) & S_IFCHR) # endif #endif #ifdef DEBUG if (zstat(pathcomp, &G.statbuf) == 0) { Trace((stderr, "maskDOSdevice() stat(\"%s\", buf) st_mode result: %X, %o\n", FnFilter1(pathcomp), G.statbuf.st_mode, G.statbuf.st_mode)); } else { Trace((stderr, "maskDOSdevice() stat(\"%s\", buf) failed\n", FnFilter1(pathcomp))); } #endif if (zstat(pathcomp, &G.statbuf) == 0 && S_ISCHR(G.statbuf.st_mode)) { extent i; /* pathcomp contains a name of a DOS character device (builtin or * installed device driver). * Prepend a '_' to allow creation of the item in the file system. */ for (i = strlen(pathcomp) + 1; i > 0; --i) pathcomp[i] = pathcomp[i - 1]; pathcomp[0] = '_'; } } /* end function maskDOSdevice() */ /**********************/ /* Function map2fat() */ /* Not quite identical to OS/2 version */ /**********************/ static void map2fat(pathcomp, pEndFAT) char *pathcomp, **pEndFAT; { char *ppc = pathcomp; /* variable pointer to pathcomp */ char *pEnd = *pEndFAT; /* variable pointer to buildpathFAT */ char *pBegin = *pEndFAT; /* constant pointer to start of this comp. */ char *last_dot = NULL; /* last dot not converted to underscore */ register unsigned workch; /* hold the character being tested */ /* Only need check those characters which are legal in NTFS but not * in FAT: to get here, must already have passed through mapname. * Also must truncate path component to ensure 8.3 compliance. */ while ((workch = (uch)*ppc++) != 0) { switch (workch) { case '[': case ']': case '+': case ',': case ';': case '=': *pEnd++ = '_'; /* convert brackets to underscores */ break; case '.': if (pEnd == *pEndFAT) { /* nothing appended yet... */ if (*ppc == '\0') /* don't bother appending a */ break; /* "./" component to the path */ else if (*ppc == '.' && ppc[1] == '\0') { /* "../" */ *pEnd++ = '.'; /* add first dot, */ *pEnd++ = '.'; /* add second dot, and */ ++ppc; /* skip over to pathcomp's end */ } else { /* FAT doesn't allow null filename */ *pEnd++ = '_'; /* bodies, so map .exrc -> _exrc */ } /* (_.exr would keep max 3 chars) */ } else { /* found dot within path component */ last_dot = pEnd; /* point at last dot so far... */ *pEnd++ = '_'; /* convert to underscore for now */ } break; default: *pEnd++ = (char)workch; } /* end switch */ } /* end while loop */ *pEnd = '\0'; /* terminate buildpathFAT */ /* NOTE: keep in mind that pEnd points to the end of the path * component, and *pEndFAT still points to the *beginning* of it... * Also note that the algorithm does not try to get too fancy: * if there are no dots already, the name either gets truncated * at 8 characters or the last underscore is converted to a dot * (only if more characters are saved that way). In no case is * a dot inserted between existing characters. */ if (last_dot == NULL) { /* no dots: check for underscores... */ char *plu = MBSRCHR(pBegin, '_'); /* pointer to last underscore */ if ((plu != NULL) && /* found underscore: convert to dot? */ (MIN(plu - pBegin, 8) + MIN(pEnd - plu - 1, 3) > 8)) { last_dot = plu; /* be lazy: drop through to next if-blk */ } else if ((pEnd - *pEndFAT) > 8) { /* no underscore; or converting underscore to dot would save less chars than leaving everything in the basename */ *pEndFAT += 8; /* truncate at 8 chars */ **pEndFAT = '\0'; } else *pEndFAT = pEnd; /* whole thing fits into 8 chars or less */ } if (last_dot != NULL) { /* one dot is OK: */ *last_dot = '.'; /* put it back in */ if ((last_dot - pBegin) > 8) { char *p, *q; int i; p = last_dot; q = last_dot = pBegin + 8; for (i = 0; (i < 4) && *p; ++i) /* too many chars in basename: */ *q++ = *p++; /* shift .ext left and trun- */ *q = '\0'; /* cate/terminate it */ *pEndFAT = q; } else if ((pEnd - last_dot) > 4) { /* too many chars in extension */ *pEndFAT = last_dot + 4; **pEndFAT = '\0'; } else *pEndFAT = pEnd; /* filename is fine; point at terminating zero */ if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ') last_dot[-1] = '_'; /* NO blank in front of '.'! */ } } /* end function map2fat() */ /***********************/ /* Borrowed from os2.c for UnZip 5.1. */ /* Function checkdir() */ /* Difference: no EA stuff */ /***********************/ /* HPFS stuff works on NTFS too */ int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename * MPN_INF_SKIP - path doesn't exist, not allowed to create * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path * exists and is not a directory, but is supposed to be * MPN_ERR_TOOLONG - path is too long * MPN_NOMEM - can't allocate memory for filename buffers */ { /* static int rootlen = 0; */ /* length of rootpath */ /* static char *rootpath; */ /* user's "extract-to" directory */ /* static char *buildpathHPFS; */ /* full path (so far) to extracted file, */ /* static char *buildpathFAT; */ /* both HPFS/EA (main) and FAT versions */ /* static char *endHPFS; */ /* corresponding pointers to end of */ /* static char *endFAT; */ /* buildpath ('\0') */ # define FN_MASK 7 # define FUNCTION (flag & FN_MASK) /*--------------------------------------------------------------------------- APPEND_DIR: append the path component to the path being built and check for its existence. If doesn't exist and we are creating directories, do so for this one; else signal success or error as appropriate. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_DIR) { char *p = pathcomp; int too_long = FALSE; Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); while ((*G.endHPFS = *p++) != '\0') /* copy to HPFS filename */ ++G.endHPFS; if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) { p = pathcomp; while ((*G.endFAT = *p++) != '\0') /* copy to FAT filename, too */ ++G.endFAT; } else map2fat(pathcomp, &G.endFAT); /* map into FAT fn, update endFAT */ /* GRR: could do better check, see if overrunning buffer as we go: * check endHPFS-buildpathHPFS after each append, set warning variable * if within 20 of FILNAMSIZ; then if var set, do careful check when * appending. Clear variable when begin new path. */ /* next check: need to append '/', at least one-char name, '\0' */ if ((G.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3) too_long = TRUE; /* check if extracting dir? */ #ifdef FIX_STAT_BUG /* Borland C++ 5.0 does not handle a call to stat() well if the * directory does not exist (it tends to crash in strange places.) * This is apparently a problem only when compiling for GUI rather * than console. The code below attempts to work around this problem. */ if (access(G.buildpathFAT, 0) != 0) { if (!G.create_dirs) { /* told not to create (freshening) */ free(G.buildpathHPFS); free(G.buildpathFAT); /* path doesn't exist: nothing to do */ return MPN_INF_SKIP; } if (too_long) { /* GRR: should allow FAT extraction w/o EAs */ Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpathHPFS))); free(G.buildpathHPFS); free(G.buildpathFAT); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ %s\n\ unable to process %s.\n", FnFilter2(G.buildpathFAT), strerror(errno), FnFilter1(G.filename))); free(G.buildpathHPFS); free(G.buildpathFAT); /* path didn't exist, tried to create, failed */ return MPN_ERR_SKIP; } G.created_dir = TRUE; } #endif /* FIX_STAT_BUG */ if (SSTAT(G.buildpathFAT, &G.statbuf)) /* path doesn't exist */ { if (!G.create_dirs) { /* told not to create (freshening) */ free(G.buildpathHPFS); free(G.buildpathFAT); /* path doesn't exist: nothing to do */ return MPN_INF_SKIP; } if (too_long) { /* GRR: should allow FAT extraction w/o EAs */ Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpathHPFS))); free(G.buildpathHPFS); free(G.buildpathFAT); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ %s\n\ unable to process %s.\n", FnFilter2(G.buildpathFAT), strerror(errno), FnFilter1(G.filename))); free(G.buildpathHPFS); free(G.buildpathFAT); /* path didn't exist, tried to create, failed */ return MPN_ERR_SKIP; } G.created_dir = TRUE; } else if (!S_ISDIR(G.statbuf.st_mode)) { Info(slide, 1, ((char *)slide, "checkdir error: %s exists but is not directory\n\ unable to process %s.\n", FnFilter2(G.buildpathFAT), FnFilter1(G.filename))); free(G.buildpathHPFS); free(G.buildpathFAT); /* path existed but wasn't dir */ return MPN_ERR_SKIP; } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpathHPFS))); free(G.buildpathHPFS); free(G.buildpathFAT); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } *G.endHPFS++ = '/'; *G.endFAT++ = '/'; *G.endHPFS = *G.endFAT = '\0'; Trace((stderr, "buildpathHPFS now = [%s]\nbuildpathFAT now = [%s]\n", FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT))); return MPN_OK; } /* end if (FUNCTION == APPEND_DIR) */ /*--------------------------------------------------------------------------- GETPATH: copy full FAT path to the string pointed at by pathcomp (want filename to reflect name used on disk, not EAs; if full path is HPFS, buildpathFAT and buildpathHPFS will be identical). Also free both paths. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { Trace((stderr, "getting and freeing FAT path [%s]\n", FnFilter1(G.buildpathFAT))); Trace((stderr, "freeing HPFS path [%s]\n", FnFilter1(G.buildpathHPFS))); strcpy(pathcomp, G.buildpathFAT); free(G.buildpathFAT); free(G.buildpathHPFS); G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL; return MPN_OK; } /*--------------------------------------------------------------------------- APPEND_NAME: assume the path component is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) { char *p = pathcomp; int error = MPN_OK; Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); /* The buildpathHPFS buffer has been allocated large enough to * hold the complete combined name, so there is no need to check * for OS filename size limit overflow within the copy loop. */ while ((*G.endHPFS = *p++) != '\0') { /* copy to HPFS filename */ ++G.endHPFS; } /* Now, check for OS filename size overflow. When detected, the * mapped HPFS name is truncated and a warning message is shown. */ if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) { G.buildpathHPFS[FILNAMSIZ-1] = '\0'; Info(slide, 1, ((char *)slide, "checkdir warning: path too long; truncating\n \ %s\n -> %s\n", FnFilter1(G.filename), FnFilter2(G.buildpathHPFS))); error = MPN_INF_TRUNC; /* filename truncated */ } /* The buildpathFAT buffer has the same allocated size as the * buildpathHPFS buffer, so there is no need for an overflow check * within the following copy loop, either. */ if (G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) { /* copy to FAT filename, too */ p = pathcomp; while ((*G.endFAT = *p++) != '\0') ++G.endFAT; } else /* map into FAT fn, update endFAT */ map2fat(pathcomp, &G.endFAT); /* Check that the FAT path does not exceed the FILNAMSIZ limit, and * truncate when neccessary. * Note that truncation can only happen when the HPFS path (which is * never shorter than the FAT path) has been already truncated. * So, emission of the warning message and setting the error code * has already happened. */ if ((G.endFAT-G.buildpathFAT) >= FILNAMSIZ) G.buildpathFAT[FILNAMSIZ-1] = '\0'; Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n", FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT))); return error; /* could check for existence, prompt for new name... */ } /* end if (FUNCTION == APPEND_NAME) */ /*--------------------------------------------------------------------------- INIT: allocate and initialize buffer space for the file currently being extracted. If file was renamed with an absolute path, don't prepend the extract-to path. ---------------------------------------------------------------------------*/ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpathHPFS and buildpathFAT to ")); #ifdef ACORN_FTYPE_NFS if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+ (uO.acorn_nfs_ext ? 5 : 1))) #else if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1)) #endif == NULL) return MPN_NOMEM; #ifdef ACORN_FTYPE_NFS if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+ (uO.acorn_nfs_ext ? 5 : 1))) #else if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1)) #endif == NULL) { free(G.buildpathHPFS); return MPN_NOMEM; } if (G.pInfo->vollabel) { /* use root or renamed path, but don't store */ /* GRR: for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */ if (G.renamed_fullpath && pathcomp[1] == ':') *G.buildpathHPFS = (char)ToLower(*pathcomp); else if (!G.renamed_fullpath && G.rootlen > 1 && G.rootpath[1] == ':') *G.buildpathHPFS = (char)ToLower(*G.rootpath); else { char tmpN[MAX_PATH], *tmpP; if (GetFullPathNameA(".", MAX_PATH, tmpN, &tmpP) > MAX_PATH) { /* by definition of MAX_PATH we should never get here */ Info(slide, 1, ((char *)slide, "checkdir warning: current dir path too long\n")); return MPN_INF_TRUNC; /* can't get drive letter */ } G.nLabelDrive = *tmpN - 'a' + 1; *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a'); } G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */ if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */ || (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */ free(G.buildpathHPFS); free(G.buildpathFAT); return MPN_VOL_LABEL; /* skipping with message */ } *G.buildpathHPFS = '\0'; } else if (G.renamed_fullpath) /* pathcomp = valid data */ strcpy(G.buildpathHPFS, pathcomp); else if (G.rootlen > 0) strcpy(G.buildpathHPFS, G.rootpath); else *G.buildpathHPFS = '\0'; G.endHPFS = G.buildpathHPFS; G.endFAT = G.buildpathFAT; while ((*G.endFAT = *G.endHPFS) != '\0') { ++G.endFAT; ++G.endHPFS; } Trace((stderr, "[%s]\n", FnFilter1(G.buildpathHPFS))); return MPN_OK; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in rootpath and create it if neces- sary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. Note that under OS/2 and MS-DOS, if a candidate extract-to directory specification includes a drive letter (leading "x:"), it is treated just as if it had a trailing '/'--that is, one directory level will be created if the path doesn't exist, unless this is otherwise pro- hibited (e.g., freshening). ---------------------------------------------------------------------------*/ #if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", FnFilter1(pathcomp))); if (pathcomp == NULL) { G.rootlen = 0; return MPN_OK; } if (G.rootlen > 0) /* rootpath was already set, nothing to do */ return MPN_OK; if ((G.rootlen = strlen(pathcomp)) > 0) { int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE; char *tmproot; if ((tmproot = (char *)malloc(G.rootlen+3)) == (char *)NULL) { G.rootlen = 0; return MPN_NOMEM; } strcpy(tmproot, pathcomp); if (isalpha((uch)tmproot[0]) && tmproot[1] == ':') has_drive = TRUE; /* drive designator */ if (tmproot[G.rootlen-1] == '/' || tmproot[G.rootlen-1] == '\\') { tmproot[--G.rootlen] = '\0'; had_trailing_pathsep = TRUE; } if (has_drive && (G.rootlen == 2)) { if (!had_trailing_pathsep) /* i.e., original wasn't "x:/" */ add_dot = TRUE; /* relative path: add '.' before '/' */ } else if (G.rootlen > 0) { /* need not check "x:." and "x:/" */ if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) { /* path does not exist */ if (!G.create_dirs /* || iswild(tmproot) */ ) { free(tmproot); G.rootlen = 0; /* treat as stored file */ return MPN_INF_SKIP; } /* create directory (could add loop here scanning tmproot * to create more than one level, but really necessary?) */ if (MKDIR(tmproot, 0777) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory: %s\n", FnFilter1(tmproot))); free(tmproot); G.rootlen = 0; /* path didn't exist, tried to create, failed: */ /* file exists, or need 2+ subdir levels */ return MPN_ERR_SKIP; } } } if (add_dot) /* had just "x:", make "x:." */ tmproot[G.rootlen++] = '.'; tmproot[G.rootlen++] = '/'; tmproot[G.rootlen] = '\0'; if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) { free(tmproot); G.rootlen = 0; return MPN_NOMEM; } Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath))); } return MPN_OK; } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (G.rootlen > 0) { free(G.rootpath); G.rootlen = 0; } return MPN_OK; } return MPN_INVALID; /* should never reach */ } /* end function checkdir() */ #ifndef SFX /*************************/ /* Function dateformat() */ /*************************/ int dateformat() { char df[2]; /* LOCALE_IDATE has a maximum value of 2 */ if (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IDATE, df, 2) != 0) { switch (df[0]) { case '0': return DF_MDY; case '1': return DF_DMY; case '2': return DF_YMD; } } return DF_MDY; } /****************************/ /* Function dateseparator() */ /****************************/ char dateseparator() { char df[2]; /* use only if it is one character */ if ((GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDATE, df, 2) != 0) && (df[0] != '\0')) return df[0]; else return '-'; } #ifndef WINDLL /************************/ /* Function version() */ /************************/ void version(__G) __GDEF { int len; #if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DJGPP__)) char buf[80]; #if (defined(_MSC_VER) && (_MSC_VER > 900)) char buf2[80]; #endif #endif len = sprintf((char *)slide, CompiledWith, #if defined(_MSC_VER) /* MSC == VC++, but what about SDK compiler? */ (sprintf(buf, "Microsoft C %d.%02d ", _MSC_VER/100, _MSC_VER%100), buf), # if (_MSC_VER == 800) "(Visual C++ v1.1)", # elif (_MSC_VER == 850) "(Windows NT v3.5 SDK)", # elif (_MSC_VER == 900) "(Visual C++ v2.x)", # elif (_MSC_VER > 900) (sprintf(buf2, "(Visual C++ %d.%d)", _MSC_VER/100 - 6, _MSC_VER%100/10), buf2), # else "(bad version)", # endif #elif defined(__WATCOMC__) # if (__WATCOMC__ % 10 > 0) (sprintf(buf, "Watcom C/C++ %d.%02d", __WATCOMC__ / 100, __WATCOMC__ % 100), buf), "", # else (sprintf(buf, "Watcom C/C++ %d.%d", __WATCOMC__ / 100, (__WATCOMC__ % 100) / 10), buf), "", # endif #elif defined(__BORLANDC__) "Borland C++", # if (__BORLANDC__ < 0x0200) " 1.0", # elif (__BORLANDC__ == 0x0200) " 2.0", # elif (__BORLANDC__ == 0x0400) " 3.0", # elif (__BORLANDC__ == 0x0410) /* __TURBOC__ = 0x0310 */ " 3.1", # elif (__BORLANDC__ == 0x0452) /* __TURBOC__ = 0x0320 */ " 4.0 or 4.02", # elif (__BORLANDC__ == 0x0460) /* __TURBOC__ = 0x0340 */ " 4.5", # elif (__BORLANDC__ == 0x0500) /* __TURBOC__ = 0x0340 */ " 5.0", # elif (__BORLANDC__ == 0x0520) /* __TURBOC__ = 0x0520 */ " 5.2 (C++ Builder 1.0)", # elif (__BORLANDC__ == 0x0530) /* __TURBOC__ = 0x0530 */ " 5.3 (C++ Builder 3.0)", # elif (__BORLANDC__ == 0x0540) /* __TURBOC__ = 0x0540 */ " 5.4 (C++ Builder 4.0)", # elif (__BORLANDC__ == 0x0550) /* __TURBOC__ = 0x0550 */ " 5.5 (C++ Builder 5.0)", # elif (__BORLANDC__ == 0x0551) /* __TURBOC__ = 0x0551 */ " 5.5.1 (C++ Builder 5.0.1)", # elif (__BORLANDC__ == 0x0560) /* __TURBOC__ = 0x0560 */ " 6.0 (C++ Builder 6.0)", # else " later than 6.0", # endif #elif defined(__LCC__) "LCC-Win32", "", #elif defined(__GNUC__) # if defined(__RSXNT__) # if (defined(__DJGPP__) && !defined(__EMX__)) (sprintf(buf, "rsxnt(djgpp v%d.%02d) / gcc ", __DJGPP__, __DJGPP_MINOR__), buf), # elif defined(__DJGPP__) (sprintf(buf, "rsxnt(emx+djgpp v%d.%02d) / gcc ", __DJGPP__, __DJGPP_MINOR__), buf), # elif (defined(__GO32__) && !defined(__EMX__)) "rsxnt(djgpp v1.x) / gcc ", # elif defined(__GO32__) "rsxnt(emx + djgpp v1.x) / gcc ", # elif defined(__EMX__) "rsxnt(emx)+gcc ", # else "rsxnt(unknown) / gcc ", # endif # elif defined(__CYGWIN__) "cygnus win32 / gcc ", # elif defined(__MINGW32__) "mingw32 / gcc ", # else "gcc ", # endif __VERSION__, #else /* !_MSC_VER, !__WATCOMC__, !__BORLANDC__, !__LCC__, !__GNUC__ */ "unknown compiler (SDK?)", "", #endif /* ?compilers */ "\nWindows 9x / Windows NT/2K/XP/2K3", " (32-bit)", #ifdef __DATE__ " on ", __DATE__ #else "", "" #endif ); (*G.message)((zvoid *)&G, slide, (ulg)len, 0); return; } /* end function version() */ #endif /* !WINDLL */ #endif /* !SFX */ #ifdef MORE int screensize(int *tt_rows, int *tt_cols) { HANDLE hstdout; CONSOLE_SCREEN_BUFFER_INFO scr; hstdout = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(hstdout, &scr); if (tt_rows != NULL) *tt_rows = scr.srWindow.Bottom - scr.srWindow.Top + 1; if (tt_cols != NULL) *tt_cols = scr.srWindow.Right - scr.srWindow.Left + 1; return 0; /* signal success */ } #endif /* MORE */ #ifdef W32_STAT_BANDAID /* All currently known variants of WIN32 operating systems (Windows 95/98, * WinNT 3.x, 4.0, 5.x) have a nasty bug in the OS kernel concerning * conversions between UTC and local time: In the time conversion functions * of the Win32 API, the timezone offset (including seasonal daylight saving * shift) between UTC and local time evaluation is erratically based on the * current system time. The correct evaluation must determine the offset * value as it {was/is/will be} for the actual time to be converted. * * Newer versions of MS C runtime lib's stat() returns utc time-stamps so * that localtime(timestamp) corresponds to the (potentially false) local * time shown by the OS' system programs (Explorer, command shell dir, etc.) * The RSXNT port follows the same strategy, but fails to recognize the * access-time attribute. * * For the NTFS file system (and other filesystems that store time-stamps * as UTC values), this results in st_mtime (, st_{c|a}time) fields which * are not stable but vary according to the seasonal change of "daylight * saving time in effect / not in effect". * * Other C runtime libs (CygWin), or the crtdll.dll supplied with Win9x/NT * return the unix-time equivalent of the UTC FILETIME values as got back * from the Win32 API call. This time, return values from NTFS are correct * whereas utimes from files on (V)FAT volumes vary according to the DST * switches. * * To achieve timestamp consistency of UTC (UT extra field) values in * Zip archives, the Info-ZIP programs require work-around code for * proper time handling in stat() (and other time handling routines). * * However, nowadays most other programs on Windows systems use the * time conversion strategy of Microsofts C runtime lib "msvcrt.dll". * To improve interoperability in environments where a "consistent" (but * false) "UTC<-->LocalTime" conversion is preferred over "stable" time * stamps, the Info-ZIP specific time conversion handling can be * deactivated by defining the preprocessor flag NO_W32TIMES_IZFIX. */ /* stat() functions under Windows95 tend to fail for root directories. * * Watcom and Borland, at least, are affected by this bug. Watcom made * * a partial fix for 11.0 but still missed some cases. This substitute * * detects the case and fills in reasonable values. Otherwise we get * * effects like failure to extract to a root dir because it's not found. */ int zstat_win32(__W32STAT_GLOBALS__ const char *path, z_stat *buf) { if (!zstat(path, buf)) { /* stat was successful, now redo the time-stamp fetches */ #ifndef NO_W32TIMES_IZFIX int fs_uses_loctime = FStampIsLocTime(__G__ path); #endif HANDLE h; FILETIME Modft, Accft, Creft; #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_path = (char *)alloca(strlen(path) + 1); INTERN_TO_ISO(path, ansi_path); # define Ansi_Path ansi_path #else # define Ansi_Path path #endif TTrace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime)); h = CreateFileA(Ansi_Path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h != INVALID_HANDLE_VALUE) { BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft); CloseHandle(h); if (ftOK) { FTTrace((stdout, "GetFileTime returned Modft", 0, &Modft)); FTTrace((stdout, "GetFileTime returned Creft", 0, &Creft)); #ifndef NO_W32TIMES_IZFIX if (!fs_uses_loctime) { /* On a filesystem that stores UTC timestamps, we refill * the time fields of the struct stat buffer by directly * using the UTC values as returned by the Win32 * GetFileTime() API call. */ NtfsFileTime2utime(&Modft, &(buf->st_mtime)); if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0) NtfsFileTime2utime(&Accft, &(buf->st_atime)); else buf->st_atime = buf->st_mtime; if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0) NtfsFileTime2utime(&Creft, &(buf->st_ctime)); else buf->st_ctime = buf->st_mtime; TTrace((stdout,"NTFS, recalculated modtime %08lx\n", buf->st_mtime)); } else #endif /* NO_W32TIMES_IZFIX */ { /* On VFAT and FAT-like filesystems, the FILETIME values * are converted back to the stable local time before * converting them to UTC unix time-stamps. */ VFatFileTime2utime(&Modft, &(buf->st_mtime)); if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0) VFatFileTime2utime(&Accft, &(buf->st_atime)); else buf->st_atime = buf->st_mtime; if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0) VFatFileTime2utime(&Creft, &(buf->st_ctime)); else buf->st_ctime = buf->st_mtime; TTrace((stdout, "VFAT, recalculated modtime %08lx\n", buf->st_mtime)); } } } # undef Ansi_Path return 0; } #ifdef W32_STATROOT_FIX else { DWORD flags; #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_path = (char *)alloca(strlen(path) + 1); INTERN_TO_ISO(path, ansi_path); # define Ansi_Path ansi_path #else # define Ansi_Path path #endif flags = GetFileAttributesA(Ansi_Path); if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) { Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n", FnFilter1(path))); memset(buf, 0, sizeof(z_stat)); buf->st_atime = buf->st_ctime = buf->st_mtime = dos_to_unix_time(DOSTIME_MINIMUM); /* 1-1-80 */ buf->st_mode = S_IFDIR | S_IREAD | ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE); return 0; } /* assumes: stat() won't fail on non-dirs without good reason */ # undef Ansi_Path } #endif /* W32_STATROOT_FIX */ return -1; } #endif /* W32_STAT_BANDAID */ #ifdef W32_USE_IZ_TIMEZONE #include "timezone.h" #define SECSPERMIN 60 #define MINSPERHOUR 60 #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) static void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule); static void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule) { if (lpw32tm->wYear != 0) { ptrule->r_type = JULIAN_DAY; ptrule->r_day = ydays[lpw32tm->wMonth - 1] + lpw32tm->wDay; } else { ptrule->r_type = MONTH_NTH_DAY_OF_WEEK; ptrule->r_mon = lpw32tm->wMonth; ptrule->r_day = lpw32tm->wDayOfWeek; ptrule->r_week = lpw32tm->wDay; } ptrule->r_time = (long)lpw32tm->wHour * SECSPERHOUR + (long)(lpw32tm->wMinute * SECSPERMIN) + (long)lpw32tm->wSecond; } int GetPlatformLocalTimezone(register struct state * ZCONST sp, void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res, ZCONST struct rule * ZCONST start, ZCONST struct rule * ZCONST end)) { TIME_ZONE_INFORMATION tzinfo; DWORD res; /* read current timezone settings from registry if TZ envvar missing */ res = GetTimeZoneInformation(&tzinfo); if (res != TIME_ZONE_ID_INVALID) { struct rule startrule, stoprule; conv_to_rule(&(tzinfo.StandardDate), &stoprule); conv_to_rule(&(tzinfo.DaylightDate), &startrule); sp->timecnt = 0; sp->ttis[0].tt_abbrind = 0; if ((sp->charcnt = WideCharToMultiByte(CP_ACP, 0, tzinfo.StandardName, -1, sp->chars, sizeof(sp->chars), NULL, NULL)) == 0) sp->chars[sp->charcnt++] = '\0'; sp->ttis[1].tt_abbrind = sp->charcnt; sp->charcnt += WideCharToMultiByte(CP_ACP, 0, tzinfo.DaylightName, -1, sp->chars + sp->charcnt, sizeof(sp->chars) - sp->charcnt, NULL, NULL); if ((sp->charcnt - sp->ttis[1].tt_abbrind) == 0) sp->chars[sp->charcnt++] = '\0'; sp->ttis[0].tt_gmtoff = - (tzinfo.Bias + tzinfo.StandardBias) * MINSPERHOUR; sp->ttis[1].tt_gmtoff = - (tzinfo.Bias + tzinfo.DaylightBias) * MINSPERHOUR; sp->ttis[0].tt_isdst = 0; sp->ttis[1].tt_isdst = 1; sp->typecnt = (startrule.r_mon == 0 && stoprule.r_mon == 0) ? 1 : 2; if (sp->typecnt > 1) (*fill_tzstate_from_rules)(sp, &startrule, &stoprule); return TRUE; } return FALSE; } #endif /* W32_USE_IZ_TIMEZONE */ #endif /* !FUNZIP */ #ifndef WINDLL /* This replacement getch() function was originally created for Watcom C * and then additionally used with CYGWIN. Since UnZip 5.4, all other Win32 * ports apply this replacement rather that their supplied getch() (or * alike) function. There are problems with unabsorbed LF characters left * over in the keyboard buffer under Win95 (and 98) when ENTER was pressed. * (Under Win95, ENTER returns two(!!) characters: CR-LF.) This problem * does not appear when run on a WinNT console prompt! */ /* Watcom 10.6's getch() does not handle Alt+. */ /* Note that if PASSWD_FROM_STDIN is defined, the file containing */ /* the password must have a carriage return after the word, not a */ /* Unix-style newline (linefeed only). This discards linefeeds. */ int getch_win32(void) { HANDLE stin; DWORD rc; unsigned char buf[2]; int ret = -1; DWORD odemode = ~(DWORD)0; # ifdef PASSWD_FROM_STDIN stin = GetStdHandle(STD_INPUT_HANDLE); # else stin = CreateFileA("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (stin == INVALID_HANDLE_VALUE) return -1; # endif if (GetConsoleMode(stin, &odemode)) SetConsoleMode(stin, ENABLE_PROCESSED_INPUT); /* raw except ^C noticed */ if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1) ret = buf[0]; /* when the user hits return we get CR LF. We discard the LF, not the CR, * because when we call this for the first time after a previous input * such as the one for "replace foo? [y]es, ..." the LF may still be in * the input stream before whatever the user types at our prompt. */ if (ret == '\n') if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1) ret = buf[0]; if (odemode != ~(DWORD)0) SetConsoleMode(stin, odemode); # ifndef PASSWD_FROM_STDIN CloseHandle(stin); # endif return ret; } #endif /* !WINDLL */ #if (defined(UNICODE_SUPPORT) && !defined(FUNZIP)) /* convert wide character string to multi-byte character string */ char *wide_to_local_string(wide_string, escape_all) ZCONST zwchar *wide_string; int escape_all; { int i; wchar_t wc; int bytes_char; int default_used; int wsize = 0; int max_bytes = 9; char buf[9]; char *buffer = NULL; char *local_string = NULL; for (wsize = 0; wide_string[wsize]; wsize++) ; if (max_bytes < MB_CUR_MAX) max_bytes = MB_CUR_MAX; if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) { return NULL; } /* convert it */ buffer[0] = '\0'; for (i = 0; i < wsize; i++) { if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) { /* wchar_t probably 2 bytes */ /* could do surrogates if state_dependent and wctomb can do */ wc = zwchar_to_wchar_t_default_char; } else { wc = (wchar_t)wide_string[i]; } /* Unter some vendor's C-RTL, the Wide-to-MultiByte conversion functions * (like wctomb() et. al.) do not use the same codepage as the other * string arguments I/O functions (fopen, mkdir, rmdir etc.). * Therefore, we have to fall back to the underlying Win32-API call to * achieve a consistent behaviour for all supported compiler environments. * Failing RTLs are for example: * Borland (locale uses OEM-CP as default, but I/O functions expect ANSI * names) * Watcom (only "C" locale, wctomb() always uses OEM CP) * (in other words: all supported environments except the Microsoft RTLs) */ bytes_char = WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK, &wc, 1, (LPSTR)buf, sizeof(buf), NULL, &default_used); if (default_used) bytes_char = -1; if (escape_all) { if (bytes_char == 1 && (uch)buf[0] <= 0x7f) { /* ASCII */ strncat(buffer, buf, 1); } else { /* use escape for wide character */ char *escape_string = wide_to_escape_string(wide_string[i]); strcat(buffer, escape_string); free(escape_string); } } else if (bytes_char > 0) { /* multi-byte char */ strncat(buffer, buf, bytes_char); } else { /* no MB for this wide */ /* use escape for wide character */ char *escape_string = wide_to_escape_string(wide_string[i]); strcat(buffer, escape_string); free(escape_string); } } if ((local_string = (char *)realloc(buffer, strlen(buffer) + 1)) == NULL) { free(buffer); return NULL; } return local_string; } #if 0 wchar_t *utf8_to_wchar_string(utf8_string) char *utf8_string; /* path to get utf-8 name for */ { wchar_t *qw; int ulen; int ulenw; if (utf8_string == NULL) return NULL; /* get length */ ulenw = MultiByteToWideChar( CP_UTF8, /* UTF-8 code page */ 0, /* flags for character-type options */ utf8_string, /* string to convert */ -1, /* string length (-1 = NULL terminated) */ NULL, /* buffer */ 0 ); /* buffer length (0 = return length) */ if (ulenw == 0) { /* failed */ return NULL; } ulenw++; /* get length in bytes */ ulen = sizeof(wchar_t) * (ulenw + 1); if ((qw = (wchar_t *)malloc(ulen + 1)) == NULL) { return NULL; } /* convert multibyte to wide */ ulen = MultiByteToWideChar( CP_UTF8, /* UTF-8 code page */ 0, /* flags for character-type options */ utf8_string, /* string to convert */ -1, /* string length (-1 = NULL terminated) */ qw, /* buffer */ ulenw); /* buffer length (0 = return length) */ if (ulen == 0) { /* failed */ free(qw); return NULL; } return qw; } wchar_t *local_to_wchar_string(local_string) char *local_string; /* path of local name */ { wchar_t *qw; int ulen; int ulenw; if (local_string == NULL) return NULL; /* get length */ ulenw = MultiByteToWideChar( CP_ACP, /* ANSI code page */ 0, /* flags for character-type options */ local_string, /* string to convert */ -1, /* string length (-1 = NULL terminated) */ NULL, /* buffer */ 0 ); /* buffer length (0 = return length) */ if (ulenw == 0) { /* failed */ return NULL; } ulenw++; /* get length in bytes */ ulen = sizeof(wchar_t) * (ulenw + 1); if ((qw = (wchar_t *)malloc(ulen + 1)) == NULL) { return NULL; } /* convert multibyte to wide */ ulen = MultiByteToWideChar( CP_ACP, /* ANSI code page */ 0, /* flags for character-type options */ local_string, /* string to convert */ -1, /* string length (-1 = NULL terminated) */ qw, /* buffer */ ulenw); /* buffer length (0 = return length) */ if (ulen == 0) { /* failed */ free(qw); return NULL; } return qw; } #endif /* 0 */ #endif /* UNICODE_SUPPORT && !FUNZIP */ /* --------------------------------------------------- */ /* Large File Support * * Initial functions by E. Gordon and R. Nausedat * 9/10/2003 * Lifted from Zip 3b, win32.c and place here by Myles Bennett * 7/6/2004 * * These implement 64-bit file support for Windows. The * defines and headers are in win32/w32cfg.h. * * Moved to win32i64.c by Mike White to avoid conflicts in * same name functions in WiZ using UnZip and Zip libraries. * 9/25/2003 */ Carla-2.1/data/windows/unzipfx-carla/win32/win32i64.c000066400000000000000000000067741364475620200222060ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- win32/win32i64.c - UnZip 6 64-bit filesize support for WIN32 Zip and UnZip. ---------------------------------------------------------------------------*/ #include "../zip.h" /* --------------------------------------------------- */ /* Large File Support * * Initial functions by E. Gordon and R. Nausedat * 9/10/2003 * * These implement 64-bit file support for Windows. The * defines and headers are in win32/osdep.h. * * These moved from win32.c by Mike White to avoid conflicts * in WiZ of same name functions in UnZip and Zip libraries. * 9/25/04 EG */ #if defined(LARGE_FILE_SUPPORT) && !defined(__CYGWIN__) # ifdef USE_STRM_INPUT # ifndef zftello /* 64-bit buffered ftello * * Win32 does not provide a 64-bit buffered * ftell (in the published api anyway) so below provides * hopefully close version. * We have not gotten _telli64 to work with buffered * streams. Below cheats by using fgetpos improperly and * may not work on other ports. */ zoff_t zftello(stream) FILE *stream; { fpos_t fpos = 0; if (fgetpos(stream, &fpos) != 0) { return -1L; } else { return fpos; } } # endif /* ndef zftello */ # ifndef zfseeko /* 64-bit buffered fseeko * * Win32 does not provide a 64-bit buffered * fseeko, so use _lseeki64 and fflush. Note * that SEEK_CUR can lose track of location * if fflush is done between the last buffered * io and this call. */ int zfseeko(stream, offset, origin) FILE *stream; zoff_t offset; int origin; { /* fseek() or its replacements are supposed to clear the eof status of the stream. fflush() and _lseeki64() do not touch the stream's eof flag, so we have to do it manually. */ #if ((defined(_MSC_VER) && (_MSC_VER >= 1200)) || \ (defined(__MINGW32__) && defined(__MSVCRT_VERSION__))) /* For the MSC environment (VS 6 or higher), and for recent releases of the MinGW environment, we "know" the internals of the FILE structure. So, we can clear just the EOF bit of the status flag. */ stream->_flag &= ~_IOEOF; #else /* Unfortunately, there is no standard "cleareof()" function, so we have to use clearerr(). This has the unwanted side effect of clearing the ferror() state as well. */ clearerr(stream); #endif if (origin == SEEK_CUR) { /* instead of synching up lseek easier just to figure and use an absolute offset */ offset += zftello(stream); origin = SEEK_SET; } fflush(stream); if (_lseeki64(fileno(stream), offset, origin) == (zoff_t)-1L) { return -1; } else { return 0; } } # endif /* ndef fseeko */ # endif /* USE_STRM_INPUT */ #endif /* Win32 LARGE_FILE_SUPPORT */ #if 0 FILE* zfopen(filename, mode) const char *filename; const char *mode; { FILE* fTemp; fTemp = fopen(filename, mode); if( fTemp == NULL ) return NULL; /* sorry, could not make VC60 and its rtl work properly without setting the * file buffer to NULL. the problem seems to be _telli64 which seems to * return the max stream position, comments are welcome */ setbuf(fTemp, NULL); return fTemp; } #endif /* --------------------------------------------------- */ Carla-2.1/data/windows/unzipfx-carla/zip.h000066400000000000000000000014431364475620200205520ustar00rootroot00000000000000/* Copyright (c) 1990-2005 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2003-May-08 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* This is a dummy zip.h to allow the source files shared with Zip (crypt.c, crc32.c, ttyio.c, win32/win32i64.c) to compile for UnZip. (In case you are looking for the Info-ZIP license, please follow the pointers above.) */ #ifndef __zip_h /* don't include more than once */ #define __zip_h #define UNZIP_INTERNAL #include "unzip.h" #define local static #define ZE_MEM PK_MEM #define ziperr(c, h) return #endif /* !__zip_h */ Carla-2.1/data/windows/unzipfx-carla/zipinfo.c000066400000000000000000002761221364475620200214310ustar00rootroot00000000000000/* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- zipinfo.c Greg Roelofs et al. This file contains all of the ZipInfo-specific listing routines for UnZip. Contains: zi_opts() zi_end_central() zipinfo() zi_long() zi_short() zi_time() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #ifndef NO_ZIPINFO /* strings use up too much space in small-memory systems */ /* Define OS-specific attributes for use on ALL platforms--the S_xxxx * versions of these are defined differently (or not defined) by different * compilers and operating systems. */ #define UNX_IFMT 0170000 /* Unix file type mask */ #define UNX_IFREG 0100000 /* Unix regular file */ #define UNX_IFSOCK 0140000 /* Unix socket (BSD, not SysV or Amiga) */ #define UNX_IFLNK 0120000 /* Unix symbolic link (not SysV, Amiga) */ #define UNX_IFBLK 0060000 /* Unix block special (not Amiga) */ #define UNX_IFDIR 0040000 /* Unix directory */ #define UNX_IFCHR 0020000 /* Unix character special (not Amiga) */ #define UNX_IFIFO 0010000 /* Unix fifo (BCC, not MSC or Amiga) */ #define UNX_ISUID 04000 /* Unix set user id on execution */ #define UNX_ISGID 02000 /* Unix set group id on execution */ #define UNX_ISVTX 01000 /* Unix directory permissions control */ #define UNX_ENFMT UNX_ISGID /* Unix record locking enforcement flag */ #define UNX_IRWXU 00700 /* Unix read, write, execute: owner */ #define UNX_IRUSR 00400 /* Unix read permission: owner */ #define UNX_IWUSR 00200 /* Unix write permission: owner */ #define UNX_IXUSR 00100 /* Unix execute permission: owner */ #define UNX_IRWXG 00070 /* Unix read, write, execute: group */ #define UNX_IRGRP 00040 /* Unix read permission: group */ #define UNX_IWGRP 00020 /* Unix write permission: group */ #define UNX_IXGRP 00010 /* Unix execute permission: group */ #define UNX_IRWXO 00007 /* Unix read, write, execute: other */ #define UNX_IROTH 00004 /* Unix read permission: other */ #define UNX_IWOTH 00002 /* Unix write permission: other */ #define UNX_IXOTH 00001 /* Unix execute permission: other */ #define VMS_IRUSR UNX_IRUSR /* VMS read/owner */ #define VMS_IWUSR UNX_IWUSR /* VMS write/owner */ #define VMS_IXUSR UNX_IXUSR /* VMS execute/owner */ #define VMS_IRGRP UNX_IRGRP /* VMS read/group */ #define VMS_IWGRP UNX_IWGRP /* VMS write/group */ #define VMS_IXGRP UNX_IXGRP /* VMS execute/group */ #define VMS_IROTH UNX_IROTH /* VMS read/other */ #define VMS_IWOTH UNX_IWOTH /* VMS write/other */ #define VMS_IXOTH UNX_IXOTH /* VMS execute/other */ #define AMI_IFMT 06000 /* Amiga file type mask */ #define AMI_IFDIR 04000 /* Amiga directory */ #define AMI_IFREG 02000 /* Amiga regular file */ #define AMI_IHIDDEN 00200 /* to be supported in AmigaDOS 3.x */ #define AMI_ISCRIPT 00100 /* executable script (text command file) */ #define AMI_IPURE 00040 /* allow loading into resident memory */ #define AMI_IARCHIVE 00020 /* not modified since bit was last set */ #define AMI_IREAD 00010 /* can be opened for reading */ #define AMI_IWRITE 00004 /* can be opened for writing */ #define AMI_IEXECUTE 00002 /* executable image, a loadable runfile */ #define AMI_IDELETE 00001 /* can be deleted */ #define THS_IFMT 0xF000 /* Theos file type mask */ #define THS_IFIFO 0x1000 /* pipe */ #define THS_IFCHR 0x2000 /* char device */ #define THS_IFSOCK 0x3000 /* socket */ #define THS_IFDIR 0x4000 /* directory */ #define THS_IFLIB 0x5000 /* library */ #define THS_IFBLK 0x6000 /* block device */ #define THS_IFREG 0x8000 /* regular file */ #define THS_IFREL 0x9000 /* relative (direct) */ #define THS_IFKEY 0xA000 /* keyed */ #define THS_IFIND 0xB000 /* indexed */ #define THS_IFRND 0xC000 /* ???? */ #define THS_IFR16 0xD000 /* 16 bit real mode program */ #define THS_IFP16 0xE000 /* 16 bit protected mode prog */ #define THS_IFP32 0xF000 /* 32 bit protected mode prog */ #define THS_IMODF 0x0800 /* modified */ #define THS_INHID 0x0400 /* not hidden */ #define THS_IEUSR 0x0200 /* erase permission: owner */ #define THS_IRUSR 0x0100 /* read permission: owner */ #define THS_IWUSR 0x0080 /* write permission: owner */ #define THS_IXUSR 0x0040 /* execute permission: owner */ #define THS_IROTH 0x0004 /* read permission: other */ #define THS_IWOTH 0x0002 /* write permission: other */ #define THS_IXOTH 0x0001 /* execute permission: other */ #ifdef OLD_THEOS_EXTRA # include "theos/oldstat.h" #endif #ifndef NSK_UNSTRUCTURED # define NSK_UNSTRUCTURED 0 #endif #ifndef NSK_OBJECTFILECODE # define NSK_OBJECTFILECODE 100 #endif #ifndef NSK_EDITFILECODE # define NSK_EDITFILECODE 101 #endif #define LFLAG 3 /* short "ls -l" type listing */ static int zi_long OF((__GPRO__ zusz_t *pEndprev, int error_in_archive)); static int zi_short OF((__GPRO)); static void zi_showMacTypeCreator OF((__GPRO__ uch *ebfield)); static char *zi_time OF((__GPRO__ ZCONST ulg *datetimez, ZCONST time_t *modtimez, char *d_t_str)); /**********************************************/ /* Strings used in zipinfo.c (ZipInfo half) */ /**********************************************/ static ZCONST char nullStr[] = ""; static ZCONST char PlurSufx[] = "s"; static ZCONST char Far ZipInfHeader2[] = "Zip file size: %s bytes, number of entries: %s\n"; static ZCONST char Far EndCentDirRec[] = "\nEnd-of-central-directory record:\n"; static ZCONST char Far LineSeparators[] = "-------------------------------\n\n"; static ZCONST char Far ZipFSizeVerbose[] = "\ Zip archive file size: %s (%sh)\n"; static ZCONST char Far ActOffsetCentDir[] = "\ Actual end-cent-dir record offset: %s (%sh)\n\ Expected end-cent-dir record offset: %s (%sh)\n\ (based on the length of the central directory and its expected offset)\n\n"; static ZCONST char Far SinglePartArchive1[] = "\ This zipfile constitutes the sole disk of a single-part archive; its\n\ central directory contains %s %s.\n\ The central directory is %s (%sh) bytes long,\n"; static ZCONST char Far SinglePartArchive2[] = "\ and its (expected) offset in bytes from the beginning of the zipfile\n\ is %s (%sh).\n\n"; static ZCONST char Far MultiPartArchive1[] = "\ This zipfile constitutes disk %lu of a multi-part archive. The central\n\ directory starts on disk %lu at an offset within that archive part\n"; static ZCONST char Far MultiPartArchive2[] = "\ of %s (%sh) bytes. The entire\n\ central directory is %s (%sh) bytes long.\n"; static ZCONST char Far MultiPartArchive3[] = "\ %s of the archive entries %s contained within this zipfile volume,\n\ out of a total of %s %s.\n\n"; static ZCONST char Far CentralDirEntry[] = "\nCentral directory entry #%lu:\n---------------------------\n\n"; static ZCONST char Far ZipfileStats[] = "%lu file%s, %s bytes uncompressed, %s bytes compressed: %s%d.%d%%\n"; /* zi_long() strings */ static ZCONST char Far OS_FAT[] = "MS-DOS, OS/2 or NT FAT"; static ZCONST char Far OS_Amiga[] = "Amiga"; static ZCONST char Far OS_VMS[] = "VMS"; static ZCONST char Far OS_Unix[] = "Unix"; static ZCONST char Far OS_VMCMS[] = "VM/CMS"; static ZCONST char Far OS_AtariST[] = "Atari ST"; static ZCONST char Far OS_HPFS[] = "OS/2 or NT HPFS"; static ZCONST char Far OS_Macintosh[] = "Macintosh HFS"; static ZCONST char Far OS_ZSystem[] = "Z-System"; static ZCONST char Far OS_CPM[] = "CP/M"; static ZCONST char Far OS_TOPS20[] = "TOPS-20"; static ZCONST char Far OS_NTFS[] = "NTFS"; static ZCONST char Far OS_QDOS[] = "SMS/QDOS"; static ZCONST char Far OS_Acorn[] = "Acorn RISC OS"; static ZCONST char Far OS_MVS[] = "MVS"; static ZCONST char Far OS_VFAT[] = "Win32 VFAT"; static ZCONST char Far OS_AtheOS[] = "AtheOS"; static ZCONST char Far OS_BeOS[] = "BeOS"; static ZCONST char Far OS_Tandem[] = "Tandem NSK"; static ZCONST char Far OS_Theos[] = "Theos"; static ZCONST char Far OS_MacDarwin[] = "Mac OS/X (Darwin)"; #ifdef OLD_THEOS_EXTRA static ZCONST char Far OS_TheosOld[] = "Theos (Old)"; #endif /* OLD_THEOS_EXTRA */ static ZCONST char Far MthdNone[] = "none (stored)"; static ZCONST char Far MthdShrunk[] = "shrunk"; static ZCONST char Far MthdRedF1[] = "reduced (factor 1)"; static ZCONST char Far MthdRedF2[] = "reduced (factor 2)"; static ZCONST char Far MthdRedF3[] = "reduced (factor 3)"; static ZCONST char Far MthdRedF4[] = "reduced (factor 4)"; static ZCONST char Far MthdImplode[] = "imploded"; static ZCONST char Far MthdToken[] = "tokenized"; static ZCONST char Far MthdDeflate[] = "deflated"; static ZCONST char Far MthdDeflat64[] = "deflated (enhanced-64k)"; static ZCONST char Far MthdDCLImplode[] = "imploded (PK DCL)"; static ZCONST char Far MthdBZip2[] = "bzipped"; static ZCONST char Far MthdLZMA[] = "LZMA-ed"; static ZCONST char Far MthdTerse[] = "tersed (IBM)"; static ZCONST char Far MthdLZ77[] = "LZ77-compressed (IBM)"; static ZCONST char Far MthdWavPack[] = "WavPacked"; static ZCONST char Far MthdPPMd[] = "PPMd-ed"; static ZCONST char Far DeflNorm[] = "normal"; static ZCONST char Far DeflMax[] = "maximum"; static ZCONST char Far DeflFast[] = "fast"; static ZCONST char Far DeflSFast[] = "superfast"; static ZCONST char Far ExtraBytesPreceding[] = " There are an extra %s bytes preceding this file.\n\n"; static ZCONST char Far UnknownNo[] = "unknown (%d)"; #ifdef ZIP64_SUPPORT static ZCONST char Far LocalHeaderOffset[] = "\n offset of local header from start of archive: %s\n\ (%sh) bytes\n"; #else static ZCONST char Far LocalHeaderOffset[] = "\n offset of local header from start of archive: %s (%sh) bytes\n"; #endif static ZCONST char Far HostOS[] = " file system or operating system of origin: %s\n"; static ZCONST char Far EncodeSWVer[] = " version of encoding software: %u.%u\n"; static ZCONST char Far MinOSCompReq[] = " minimum file system compatibility required: %s\n"; static ZCONST char Far MinSWVerReq[] = " minimum software version required to extract: %u.%u\n"; static ZCONST char Far CompressMethod[] = " compression method: %s\n"; static ZCONST char Far SlideWindowSizeImplode[] = " size of sliding dictionary (implosion): %cK\n"; static ZCONST char Far ShannonFanoTrees[] = " number of Shannon-Fano trees (implosion): %c\n"; static ZCONST char Far CompressSubtype[] = " compression sub-type (deflation): %s\n"; static ZCONST char Far FileSecurity[] = " file security status: %sencrypted\n"; static ZCONST char Far ExtendedLocalHdr[] = " extended local header: %s\n"; static ZCONST char Far FileModDate[] = " file last modified on (DOS date/time): %s\n"; #ifdef USE_EF_UT_TIME static ZCONST char Far UT_FileModDate[] = " file last modified on (UT extra field modtime): %s %s\n"; static ZCONST char Far LocalTime[] = "local"; #ifndef NO_GMTIME static ZCONST char Far GMTime[] = "UTC"; #endif #endif /* USE_EF_UT_TIME */ static ZCONST char Far CRC32Value[] = " 32-bit CRC value (hex): %.8lx\n"; static ZCONST char Far CompressedFileSize[] = " compressed size: %s bytes\n"; static ZCONST char Far UncompressedFileSize[] = " uncompressed size: %s bytes\n"; static ZCONST char Far FilenameLength[] = " length of filename: %u characters\n"; static ZCONST char Far ExtraFieldLength[] = " length of extra field: %u bytes\n"; static ZCONST char Far FileCommentLength[] = " length of file comment: %u characters\n"; static ZCONST char Far FileDiskNum[] = " disk number on which file begins: disk %lu\n"; static ZCONST char Far ApparentFileType[] = " apparent file type: %s\n"; static ZCONST char Far VMSFileAttributes[] = " VMS file attributes (%06o octal): %s\n"; static ZCONST char Far AmigaFileAttributes[] = " Amiga file attributes (%06o octal): %s\n"; static ZCONST char Far UnixFileAttributes[] = " Unix file attributes (%06o octal): %s\n"; static ZCONST char Far NonMSDOSFileAttributes[] = " non-MSDOS external file attributes: %06lX hex\n"; static ZCONST char Far MSDOSFileAttributes[] = " MS-DOS file attributes (%02X hex): none\n"; static ZCONST char Far MSDOSFileAttributesRO[] = " MS-DOS file attributes (%02X hex): read-only\n"; static ZCONST char Far MSDOSFileAttributesAlpha[] = " MS-DOS file attributes (%02X hex): %s%s%s%s%s%s%s%s\n"; static ZCONST char Far TheosFileAttributes[] = " Theos file attributes (%04X hex): %s\n"; static ZCONST char Far TheosFTypLib[] = "Library "; static ZCONST char Far TheosFTypDir[] = "Directory "; static ZCONST char Far TheosFTypReg[] = "Sequential "; static ZCONST char Far TheosFTypRel[] = "Direct "; static ZCONST char Far TheosFTypKey[] = "Keyed "; static ZCONST char Far TheosFTypInd[] = "Indexed "; static ZCONST char Far TheosFTypR16[] = " 86 program "; static ZCONST char Far TheosFTypP16[] = "286 program "; static ZCONST char Far TheosFTypP32[] = "386 program "; static ZCONST char Far TheosFTypUkn[] = "??? "; static ZCONST char Far ExtraFieldTrunc[] = "\n\ error: EF data block (type 0x%04x) size %u exceeds remaining extra field\n\ space %u; block length has been truncated.\n"; static ZCONST char Far ExtraFields[] = "\n\ The central-directory extra field contains:"; static ZCONST char Far ExtraFieldType[] = "\n\ - A subfield with ID 0x%04x (%s) and %u data bytes"; static ZCONST char Far efPKSZ64[] = "PKWARE 64-bit sizes"; static ZCONST char Far efAV[] = "PKWARE AV"; static ZCONST char Far efOS2[] = "OS/2"; static ZCONST char Far efPKVMS[] = "PKWARE VMS"; static ZCONST char Far efPKWin32[] = "PKWARE Win32"; static ZCONST char Far efPKUnix[] = "PKWARE Unix"; static ZCONST char Far efIZVMS[] = "Info-ZIP VMS"; static ZCONST char Far efIZUnix[] = "old Info-ZIP Unix/OS2/NT"; static ZCONST char Far efIZUnix2[] = "Unix UID/GID (16-bit)"; static ZCONST char Far efIZUnix3[] = "Unix UID/GID (any size)"; static ZCONST char Far efTime[] = "universal time"; static ZCONST char Far efU8Path[] = "UTF8 path name"; static ZCONST char Far efU8Commnt[] = "UTF8 entry comment"; static ZCONST char Far efJLMac[] = "old Info-ZIP Macintosh"; static ZCONST char Far efMac3[] = "new Info-ZIP Macintosh"; static ZCONST char Far efZipIt[] = "ZipIt Macintosh"; static ZCONST char Far efSmartZip[] = "SmartZip Macintosh"; static ZCONST char Far efZipIt2[] = "ZipIt Macintosh (short)"; static ZCONST char Far efVMCMS[] = "VM/CMS"; static ZCONST char Far efMVS[] = "MVS"; static ZCONST char Far efACL[] = "OS/2 ACL"; static ZCONST char Far efNTSD[] = "Security Descriptor"; static ZCONST char Far efAtheOS[] = "AtheOS"; static ZCONST char Far efBeOS[] = "BeOS"; static ZCONST char Far efQDOS[] = "SMS/QDOS"; static ZCONST char Far efAOSVS[] = "AOS/VS"; static ZCONST char Far efSpark[] = "Acorn SparkFS"; static ZCONST char Far efMD5[] = "Fred Kantor MD5"; static ZCONST char Far efASiUnix[] = "ASi Unix"; static ZCONST char Far efTandem[] = "Tandem NSK"; static ZCONST char Far efTheos[] = "Theos"; static ZCONST char Far efUnknown[] = "unknown"; static ZCONST char Far OS2EAs[] = ".\n\ The local extra field has %lu bytes of OS/2 extended attributes.\n\ (May not match OS/2 \"dir\" amount due to storage method)"; static ZCONST char Far izVMSdata[] = ". The extra\n\ field is %s and has %u bytes of VMS %s information%s"; static ZCONST char Far izVMSstored[] = "stored"; static ZCONST char Far izVMSrleenc[] = "run-length encoded"; static ZCONST char Far izVMSdeflat[] = "deflated"; static ZCONST char Far izVMScunknw[] = "compressed(?)"; static ZCONST char Far *izVMScomp[4] = {izVMSstored, izVMSrleenc, izVMSdeflat, izVMScunknw}; static ZCONST char Far ACLdata[] = ".\n\ The local extra field has %lu bytes of access control list information"; static ZCONST char Far NTSDData[] = ".\n\ The local extra field has %lu bytes of NT security descriptor data"; static ZCONST char Far UTdata[] = ".\n\ The local extra field has UTC/GMT %s time%s"; static ZCONST char Far UTmodification[] = "modification"; static ZCONST char Far UTaccess[] = "access"; static ZCONST char Far UTcreation[] = "creation"; static ZCONST char Far U8PthCmnComplete[] = ".\n\ The UTF8 data of the extra field (V%u, ASCII name CRC `%.8lx') are:\n "; static ZCONST char Far U8PthCmnF24[] = ". The first\n\ 24 UTF8 bytes in the extra field (V%u, ASCII name CRC `%.8lx') are:\n "; static ZCONST char Far ZipItFname[] = ".\n\ The Mac long filename is %s"; static ZCONST char Far Mac3data[] = ".\n\ The local extra field has %lu bytes of %scompressed Macintosh\n\ finder attributes"; /* MacOSdata[] is used by EF_MAC3, EF_ZIPIT, EF_ZIPIT2 and EF_JLEE e. f. */ static ZCONST char Far MacOSdata[] = ".\n\ The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'"; static ZCONST char Far MacOSdata1[] = ".\n\ The associated file has type code `0x%lx' and creator code `0x%lx'"; static ZCONST char Far MacOSJLEEflags[] = ".\n File is marked as %s"; static ZCONST char Far MacOS_RF[] = "Resource-fork"; static ZCONST char Far MacOS_DF[] = "Data-fork"; static ZCONST char Far MacOSMAC3flags[] = ".\n\ File is marked as %s, File Dates are in %d Bit"; static ZCONST char Far AtheOSdata[] = ".\n\ The local extra field has %lu bytes of %scompressed AtheOS file attributes"; static ZCONST char Far BeOSdata[] = ".\n\ The local extra field has %lu bytes of %scompressed BeOS file attributes"; /* The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'" */ static ZCONST char Far QDOSdata[] = ".\n\ The QDOS extra field subtype is `%c%c%c%c'"; static ZCONST char Far AOSVSdata[] = ".\n\ The AOS/VS extra field revision is %d.%d"; static ZCONST char Far TandemUnstr[] = "Unstructured"; static ZCONST char Far TandemRel[] = "Relative"; static ZCONST char Far TandemEntry[] = "Entry Sequenced"; static ZCONST char Far TandemKey[] = "Key Sequenced"; static ZCONST char Far TandemEdit[] = "Edit"; static ZCONST char Far TandemObj[] = "Object"; static ZCONST char Far *TandemFileformat[6] = {TandemUnstr, TandemRel, TandemEntry, TandemKey, TandemEdit, TandemObj}; static ZCONST char Far Tandemdata[] = ".\n\ The file was originally a Tandem %s file, with file code %u"; static ZCONST char Far MD5data[] = ".\n\ The 128-bit MD5 signature is %s"; #ifdef CMS_MVS static ZCONST char Far VmMvsExtraField[] = ".\n\ The stored file open mode (FLDATA TYPE) is \"%s\""; static ZCONST char Far VmMvsInvalid[] = "[invalid]"; #endif /* CMS_MVS */ static ZCONST char Far First20[] = ". The first\n 20 are: "; static ZCONST char Far ColonIndent[] = ":\n "; static ZCONST char Far efFormat[] = " %02x"; static ZCONST char Far lExtraFieldType[] = "\n\ There %s a local extra field with ID 0x%04x (%s) and\n\ %u data bytes (%s).\n"; static ZCONST char Far efIZuid[] = "GMT modification/access times and Unix UID/GID"; static ZCONST char Far efIZnouid[] = "GMT modification/access times only"; static ZCONST char Far NoFileComment[] = "\n There is no file comment.\n"; static ZCONST char Far FileCommBegin[] = "\n\ ------------------------- file comment begins ----------------------------\n"; static ZCONST char Far FileCommEnd[] = "\ -------------------------- file comment ends -----------------------------\n"; /* zi_time() strings */ static ZCONST char Far BogusFmt[] = "%03d"; static ZCONST char Far shtYMDHMTime[] = "%02u-%s-%02u %02u:%02u"; static ZCONST char Far lngYMDHMSTime[] = "%u %s %u %02u:%02u:%02u"; static ZCONST char Far DecimalTime[] = "%04u%02u%02u.%02u%02u%02u"; #ifdef USE_EF_UT_TIME static ZCONST char Far lngYMDHMSTimeError[] = "???? ??? ?? ??:??:??"; #endif #ifndef WINDLL /************************/ /* Function zi_opts() */ /************************/ int zi_opts(__G__ pargc, pargv) int *pargc; char ***pargv; __GDEF { char **argv, *s; int argc, c, error=FALSE, negative=0; int hflag_slmv=TRUE, hflag_2=FALSE; /* diff options => diff defaults */ int tflag_slm=TRUE, tflag_2v=FALSE; int explicit_h=FALSE, explicit_t=FALSE; #ifdef MACOS uO.lflag = LFLAG; /* reset default on each call */ #endif G.extract_flag = FALSE; /* zipinfo does not extract to disk */ argc = *pargc; argv = *pargv; while (--argc > 0 && (*++argv)[0] == '-') { s = argv[0] + 1; while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */ switch (c) { case '-': ++negative; break; case '1': /* shortest listing: JUST filenames */ if (negative) uO.lflag = -2, negative = 0; else uO.lflag = 1; break; case '2': /* just filenames, plus headers if specified */ if (negative) uO.lflag = -2, negative = 0; else uO.lflag = 2; break; #ifndef CMS_MVS case ('C'): /* -C: match filenames case-insensitively */ if (negative) uO.C_flag = FALSE, negative = 0; else uO.C_flag = TRUE; break; #endif /* !CMS_MVS */ case 'h': /* header line */ if (negative) hflag_2 = hflag_slmv = FALSE, negative = 0; else { hflag_2 = hflag_slmv = explicit_h = TRUE; if (uO.lflag == -1) uO.lflag = 0; } break; case 'l': /* longer form of "ls -l" type listing */ if (negative) uO.lflag = -2, negative = 0; else uO.lflag = 5; break; case 'm': /* medium form of "ls -l" type listing */ if (negative) uO.lflag = -2, negative = 0; else uO.lflag = 4; break; #ifdef MORE case 'M': /* send output through built-in "more" */ if (negative) G.M_flag = FALSE, negative = 0; else G.M_flag = TRUE; break; #endif case 's': /* default: shorter "ls -l" type listing */ if (negative) uO.lflag = -2, negative = 0; else uO.lflag = 3; break; case 't': /* totals line */ if (negative) tflag_2v = tflag_slm = FALSE, negative = 0; else { tflag_2v = tflag_slm = explicit_t = TRUE; if (uO.lflag == -1) uO.lflag = 0; } break; case ('T'): /* use (sortable) decimal time format */ if (negative) uO.T_flag = FALSE, negative = 0; else uO.T_flag = TRUE; break; #ifdef UNICODE_SUPPORT case ('U'): /* escape UTF-8, or disable UTF-8 support */ if (negative) { uO.U_flag = MAX(uO.U_flag-negative,0); negative = 0; } else uO.U_flag++; break; #endif /* UNICODE_SUPPORT */ case 'v': /* turbo-verbose listing */ if (negative) uO.lflag = -2, negative = 0; else uO.lflag = 10; break; #ifdef WILD_STOP_AT_DIR case ('W'): /* Wildcard interpretation (stop at '/'?) */ if (negative) uO.W_flag = FALSE, negative = 0; else uO.W_flag = TRUE; break; #endif /* WILD_STOP_AT_DIR */ case 'z': /* print zipfile comment */ if (negative) uO.zflag = negative = 0; else uO.zflag = 1; break; case 'Z': /* ZipInfo mode: ignore */ break; default: error = TRUE; break; } } } if ((argc-- == 0) || error) { *pargc = argc; *pargv = argv; return USAGE(error); } #ifdef MORE if (G.M_flag && !isatty(1)) /* stdout redirected: "more" func useless */ G.M_flag = 0; #endif /* if no listing options given (or all negated), or if only -h/-t given * with individual files specified, use default listing format */ if ((uO.lflag < 0) || ((argc > 0) && (uO.lflag == 0))) uO.lflag = LFLAG; /* set header and totals flags to default or specified values */ switch (uO.lflag) { case 0: /* 0: can only occur if either -t or -h explicitly given; */ case 2: /* therefore set both flags equal to normally false value */ uO.hflag = hflag_2; uO.tflag = tflag_2v; break; case 1: /* only filenames, *always* */ uO.hflag = FALSE; uO.tflag = FALSE; uO.zflag = FALSE; break; case 3: case 4: case 5: uO.hflag = ((argc > 0) && !explicit_h)? FALSE : hflag_slmv; uO.tflag = ((argc > 0) && !explicit_t)? FALSE : tflag_slm; break; case 10: uO.hflag = hflag_slmv; uO.tflag = tflag_2v; break; } *pargc = argc; *pargv = argv; return 0; } /* end function zi_opts() */ #endif /* !WINDLL */ /*******************************/ /* Function zi_end_central() */ /*******************************/ void zi_end_central(__G) __GDEF { /*--------------------------------------------------------------------------- Print out various interesting things about the zipfile. ---------------------------------------------------------------------------*/ if (uO.lflag > 9) { /* verbose format */ Info(slide, 0, ((char *)slide, LoadFarString(EndCentDirRec))); Info(slide, 0, ((char *)slide, LoadFarString(LineSeparators))); Info(slide, 0, ((char *)slide, LoadFarString(ZipFSizeVerbose), FmZofft(G.ziplen, "11", NULL), FmZofft(G.ziplen, FZOFFT_HEX_DOT_WID, "X"))); Info(slide, 0, ((char *)slide, LoadFarString(ActOffsetCentDir), FmZofft(G.real_ecrec_offset, "11", "u"), FmZofft(G.real_ecrec_offset, FZOFFT_HEX_DOT_WID, "X"), FmZofft(G.expect_ecrec_offset, "11", "u"), FmZofft(G.expect_ecrec_offset, FZOFFT_HEX_DOT_WID, "X"))); if (G.ecrec.number_this_disk == 0) { Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive1), FmZofft(G.ecrec.total_entries_central_dir, NULL, "u"), (G.ecrec.total_entries_central_dir == 1)? "entry" : "entries", FmZofft(G.ecrec.size_central_directory, NULL, "u"), FmZofft(G.ecrec.size_central_directory, FZOFFT_HEX_DOT_WID, "X"))); Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive2), FmZofft(G.ecrec.offset_start_central_directory, NULL, "u"), FmZofft(G.ecrec.offset_start_central_directory, FZOFFT_HEX_DOT_WID, "X"))); } else { Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive1), (ulg)(G.ecrec.number_this_disk + 1), (ulg)(G.ecrec.num_disk_start_cdir + 1))); Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive2), FmZofft(G.ecrec.offset_start_central_directory, NULL, "u"), FmZofft(G.ecrec.offset_start_central_directory, FZOFFT_HEX_DOT_WID, "X"), FmZofft(G.ecrec.size_central_directory, NULL, "u"), FmZofft(G.ecrec.size_central_directory, FZOFFT_HEX_DOT_WID, "X"))); Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive3), FmZofft(G.ecrec.num_entries_centrl_dir_ths_disk, NULL, "u"), (G.ecrec.num_entries_centrl_dir_ths_disk == 1)? "is" : "are", FmZofft(G.ecrec.total_entries_central_dir, NULL, "u"), (G.ecrec.total_entries_central_dir == 1) ? "entry" : "entries")); } } else if (uO.hflag) { /* print zip file size and number of contained entries: */ Info(slide, 0, ((char *)slide, LoadFarString(ZipInfHeader2), FmZofft(G.ziplen, NULL, NULL), FmZofft(G.ecrec.total_entries_central_dir, NULL, "u"))); } } /* end function zi_end_central() */ /************************/ /* Function zipinfo() */ /************************/ int zipinfo(__G) /* return PK-type error code */ __GDEF { int do_this_file=FALSE, error, error_in_archive=PK_COOL; int *fn_matched=NULL, *xn_matched=NULL; ulg j, members=0L; zusz_t tot_csize=0L, tot_ucsize=0L; zusz_t endprev; /* buffers end of previous entry for zi_long()'s check * of extra bytes */ /*--------------------------------------------------------------------------- Malloc space for check on unmatched filespecs (no big deal if one or both are NULL). ---------------------------------------------------------------------------*/ if (G.filespecs > 0 && (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != NULL) for (j = 0; j < G.filespecs; ++j) fn_matched[j] = FALSE; if (G.xfilespecs > 0 && (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != NULL) for (j = 0; j < G.xfilespecs; ++j) xn_matched[j] = FALSE; /*--------------------------------------------------------------------------- Set file pointer to start of central directory, then loop through cen- tral directory entries. Check that directory-entry signature bytes are actually there (just a precaution), then process the entry. We know the entire central directory is on this disk: we wouldn't have any of this information unless the end-of-central-directory record was on this disk, and we wouldn't have gotten to this routine unless this is also the disk on which the central directory starts. In practice, this had better be the *only* disk in the archive, but maybe someday we'll add multi-disk support. ---------------------------------------------------------------------------*/ uO.L_flag = FALSE; /* zipinfo mode: never convert name to lowercase */ G.pInfo = G.info; /* (re-)initialize, (just to make sure) */ G.pInfo->textmode = 0; /* so one can read on screen (is this ever used?) */ /* reset endprev for new zipfile; account for multi-part archives (?) */ endprev = (G.crec.relative_offset_local_header == 4L)? 4L : 0L; for (j = 1L;; j++) { if (readbuf(__G__ G.sig, 4) == 0) { error_in_archive = PK_EOF; break; } if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a CentDir entry? */ /* no new central directory entry * -> is the number of processed entries compatible with the * number of entries as stored in the end_central record? */ if (((j - 1) & (ulg)(G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16)) == (ulg)G.ecrec.total_entries_central_dir) { /* "j modulus 4T/64k" matches the reported 64/16-bit-unsigned * number of directory entries -> probably, the regular * end of the central directory has been reached */ break; } else { Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j)); Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); error_in_archive = PK_BADERR; /* sig not found */ break; } } /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */ if ((error = process_cdir_file_hdr(__G)) != PK_COOL) { error_in_archive = error; /* only PK_EOF defined */ break; } if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) /* fatal */ break; } if (!G.process_all_files) { /* check if specified on command line */ unsigned i; if (G.filespecs == 0) do_this_file = TRUE; else { /* check if this entry matches an `include' argument */ do_this_file = FALSE; for (i = 0; i < G.filespecs; i++) if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) { do_this_file = TRUE; if (fn_matched) fn_matched[i] = TRUE; break; /* found match, so stop looping */ } } if (do_this_file) { /* check if this is an excluded file */ for (i = 0; i < G.xfilespecs; i++) if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) { do_this_file = FALSE; /* ^-- ignore case in match */ if (xn_matched) xn_matched[i] = TRUE; break; } } } /*----------------------------------------------------------------------- If current file was specified on command line, or if no names were specified, do the listing for this file. Otherwise, get rid of the file comment and go back for the next file. -----------------------------------------------------------------------*/ if (G.process_all_files || do_this_file) { /* Read the extra field, if any. The extra field info is required * for resolving the Zip64 sizes/offsets and may be used in more * analysis of the entry below. */ if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0) { if (G.extra_field != NULL) { free(G.extra_field); G.extra_field = NULL; } error_in_archive = error; /* The premature return in case of a "fatal" error (PK_EOF) is * delayed until we analyze the extra field contents. * This allows us to display all the other info that has been * successfully read in. */ } switch (uO.lflag) { case 1: case 2: fnprint(__G); SKIP_(G.crec.file_comment_length) break; case 3: case 4: case 5: if ((error = zi_short(__G)) != PK_COOL) { error_in_archive = error; /* might be warning */ } break; case 10: Info(slide, 0, ((char *)slide, LoadFarString(CentralDirEntry), j)); if ((error = zi_long(__G__ &endprev, error_in_archive)) != PK_COOL) { error_in_archive = error; /* might be warning */ } break; default: SKIP_(G.crec.file_comment_length) break; } /* end switch (lflag) */ if (error > PK_WARN) /* fatal */ break; tot_csize += G.crec.csize; tot_ucsize += G.crec.ucsize; if (G.crec.general_purpose_bit_flag & 1) tot_csize -= 12; /* don't count encryption header */ ++members; #ifdef DLL if ((G.statreportcb != NULL) && (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn, G.filename, (zvoid *)&G.crec.ucsize)) { /* cancel operation by user request */ error_in_archive = IZ_CTRLC; break; } #endif #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ UserStop(); #endif } else { /* not listing this file */ SKIP_(G.crec.extra_field_length) SKIP_(G.crec.file_comment_length) if (endprev != 0) endprev = 0; } /* end if (list member?) */ } /* end for-loop (j: member files) */ /*--------------------------------------------------------------------------- Check that we actually found requested files; if so, print totals. ---------------------------------------------------------------------------*/ if ((error_in_archive <= PK_WARN) && uO.tflag) { char *sgn = ""; int cfactor = ratio(tot_ucsize, tot_csize); if (cfactor < 0) { sgn = "-"; cfactor = -cfactor; } Info(slide, 0, ((char *)slide, LoadFarString(ZipfileStats), members, (members==1L)? nullStr:PlurSufx, FmZofft(tot_ucsize, NULL, "u"), FmZofft(tot_csize, NULL, "u"), sgn, cfactor/10, cfactor%10)); } /*--------------------------------------------------------------------------- Check for unmatched filespecs on command line and print warning if any found. ---------------------------------------------------------------------------*/ if (fn_matched) { if (error_in_archive <= PK_WARN) for (j = 0; j < G.filespecs; ++j) if (!fn_matched[j]) Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameNotMatched), G.pfnames[j])); free((zvoid *)fn_matched); } if (xn_matched) { if (error_in_archive <= PK_WARN) for (j = 0; j < G.xfilespecs; ++j) if (!xn_matched[j]) Info(slide, 0x401, ((char *)slide, LoadFarString(ExclFilenameNotMatched), G.pxnames[j])); free((zvoid *)xn_matched); } /* Skip the following checks in case of a premature listing break. */ if (error_in_archive <= PK_WARN) { /*--------------------------------------------------------------------------- Double check that we're back at the end-of-central-directory record. ---------------------------------------------------------------------------*/ if ( (memcmp(G.sig, (G.ecrec.have_ecr64 ? end_central64_sig : end_central_sig), 4) != 0) && (!G.ecrec.is_zip64_archive) && (memcmp(G.sig, end_central_sig, 4) != 0) ) { /* just to make sure again */ Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); error_in_archive = PK_WARN; /* didn't find sig */ } /* Set specific return code when no files have been found. */ if (members == 0L && error_in_archive <= PK_WARN) error_in_archive = PK_FIND; if (uO.lflag >= 10) (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); } return error_in_archive; } /* end function zipinfo() */ /************************/ /* Function zi_long() */ /************************/ static int zi_long(__G__ pEndprev, error_in_archive) /* return PK-type error code */ __GDEF zusz_t *pEndprev; /* for zi_long() check of extra bytes */ int error_in_archive; /* may signal premature return */ { #ifdef USE_EF_UT_TIME iztimes z_utime; #endif int error; unsigned hostnum, hostver, extnum, extver, methid, methnum, xattr; char workspace[12], attribs[22]; ZCONST char *varmsg_str; char unkn[16]; static ZCONST char Far *os[NUM_HOSTS] = { OS_FAT, OS_Amiga, OS_VMS, OS_Unix, OS_VMCMS, OS_AtariST, OS_HPFS, OS_Macintosh, OS_ZSystem, OS_CPM, OS_TOPS20, OS_NTFS, OS_QDOS, OS_Acorn, OS_VFAT, OS_MVS, OS_BeOS, OS_Tandem, OS_Theos, OS_MacDarwin, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, OS_AtheOS }; static ZCONST char Far *method[NUM_METHODS] = { MthdNone, MthdShrunk, MthdRedF1, MthdRedF2, MthdRedF3, MthdRedF4, MthdImplode, MthdToken, MthdDeflate, MthdDeflat64, MthdDCLImplode, MthdBZip2, MthdLZMA, MthdTerse, MthdLZ77, MthdWavPack, MthdPPMd }; static ZCONST char Far *dtypelng[4] = { DeflNorm, DeflMax, DeflFast, DeflSFast }; /*--------------------------------------------------------------------------- Check whether there's any extra space inside the zipfile. If *pEndprev is zero, it's probably a signal that OS/2 extra fields are involved (with unknown compressed size). We won't worry about prepended junk here... ---------------------------------------------------------------------------*/ if (G.crec.relative_offset_local_header != *pEndprev && *pEndprev > 0L) { /* GRR DEBUG Info(slide, 0, ((char *)slide, " [crec.relative_offset_local_header = %lu, endprev = %lu]\n", G.crec.relative_offset_local_header, *pEndprev)); */ Info(slide, 0, ((char *)slide, LoadFarString(ExtraBytesPreceding), FmZofft((G.crec.relative_offset_local_header - (*pEndprev)), NULL, NULL))); } /* calculate endprev for next time around (problem: extra fields may * differ in length between local and central-directory records) */ *pEndprev = G.crec.relative_offset_local_header + (4L + LREC_SIZE) + G.crec.filename_length + G.crec.extra_field_length + G.crec.csize; /*--------------------------------------------------------------------------- Print out various interesting things about the compressed file. ---------------------------------------------------------------------------*/ hostnum = (unsigned)(G.pInfo->hostnum); hostver = (unsigned)(G.pInfo->hostver); extnum = (unsigned)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS); extver = (unsigned)G.crec.version_needed_to_extract[0]; methid = (unsigned)G.crec.compression_method; methnum = find_compr_idx(G.crec.compression_method); (*G.message)((zvoid *)&G, (uch *)" ", 2L, 0); fnprint(__G); Info(slide, 0, ((char *)slide, LoadFarString(LocalHeaderOffset), FmZofft(G.crec.relative_offset_local_header, NULL, "u"), FmZofft(G.crec.relative_offset_local_header, FZOFFT_HEX_DOT_WID, "X"))); if (hostnum >= NUM_HOSTS) { sprintf(unkn, LoadFarString(UnknownNo), (int)G.crec.version_made_by[1]); varmsg_str = unkn; } else { varmsg_str = LoadFarStringSmall(os[hostnum]); #ifdef OLD_THEOS_EXTRA if (hostnum == FS_VFAT_ && hostver == 20) { /* entry made by old non-official THEOS port zip archive */ varmsg_str = LoadFarStringSmall(OS_TheosOld); } #endif /* OLD_THEOS_EXTRA */ } Info(slide, 0, ((char *)slide, LoadFarString(HostOS), varmsg_str)); Info(slide, 0, ((char *)slide, LoadFarString(EncodeSWVer), hostver/10, hostver%10)); if ((extnum >= NUM_HOSTS) || (os[extnum] == NULL)) { sprintf(unkn, LoadFarString(UnknownNo), (int)G.crec.version_needed_to_extract[1]); varmsg_str = unkn; } else { varmsg_str = LoadFarStringSmall(os[extnum]); } Info(slide, 0, ((char *)slide, LoadFarString(MinOSCompReq), varmsg_str)); Info(slide, 0, ((char *)slide, LoadFarString(MinSWVerReq), extver/10, extver%10)); if (methnum >= NUM_METHODS) { sprintf(unkn, LoadFarString(UnknownNo), G.crec.compression_method); varmsg_str = unkn; } else { varmsg_str = LoadFarStringSmall(method[methnum]); } Info(slide, 0, ((char *)slide, LoadFarString(CompressMethod), varmsg_str)); if (methid == IMPLODED) { Info(slide, 0, ((char *)slide, LoadFarString(SlideWindowSizeImplode), (G.crec.general_purpose_bit_flag & 2)? '8' : '4')); Info(slide, 0, ((char *)slide, LoadFarString(ShannonFanoTrees), (G.crec.general_purpose_bit_flag & 4)? '3' : '2')); } else if (methid == DEFLATED || methid == ENHDEFLATED) { ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3); Info(slide, 0, ((char *)slide, LoadFarString(CompressSubtype), LoadFarStringSmall(dtypelng[dnum]))); } Info(slide, 0, ((char *)slide, LoadFarString(FileSecurity), (G.crec.general_purpose_bit_flag & 1) ? nullStr : "not ")); Info(slide, 0, ((char *)slide, LoadFarString(ExtendedLocalHdr), (G.crec.general_purpose_bit_flag & 8) ? "yes" : "no")); /* print upper 3 bits for amusement? */ /* For printing of date & time, a "char d_t_buf[21]" is required. * To save stack space, we reuse the "char attribs[22]" buffer which * is not used yet. */ # define d_t_buf attribs zi_time(__G__ &G.crec.last_mod_dos_datetime, NULL, d_t_buf); Info(slide, 0, ((char *)slide, LoadFarString(FileModDate), d_t_buf)); #ifdef USE_EF_UT_TIME if (G.extra_field && #ifdef IZ_CHECK_TZ G.tz_is_valid && #endif (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1, G.crec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME)) { TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7.0 or Macintosh */ d_t_buf[0] = (char)0; /* signal "show local time" */ zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf); Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate), d_t_buf, LoadFarStringSmall(LocalTime))); #ifndef NO_GMTIME d_t_buf[0] = (char)1; /* signal "show UTC (GMT) time" */ zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf); Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate), d_t_buf, LoadFarStringSmall(GMTime))); #endif /* !NO_GMTIME */ } #endif /* USE_EF_UT_TIME */ Info(slide, 0, ((char *)slide, LoadFarString(CRC32Value), G.crec.crc32)); Info(slide, 0, ((char *)slide, LoadFarString(CompressedFileSize), FmZofft(G.crec.csize, NULL, "u"))); Info(slide, 0, ((char *)slide, LoadFarString(UncompressedFileSize), FmZofft(G.crec.ucsize, NULL, "u"))); Info(slide, 0, ((char *)slide, LoadFarString(FilenameLength), G.crec.filename_length)); Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldLength), G.crec.extra_field_length)); Info(slide, 0, ((char *)slide, LoadFarString(FileCommentLength), G.crec.file_comment_length)); Info(slide, 0, ((char *)slide, LoadFarString(FileDiskNum), (ulg)(G.crec.disk_number_start + 1))); Info(slide, 0, ((char *)slide, LoadFarString(ApparentFileType), (G.crec.internal_file_attributes & 1)? "text" : (G.crec.internal_file_attributes & 2)? "ebcdic" : "binary")); /* changed to accept EBCDIC */ #ifdef ATARI printf(" external file attributes (hex): %.8lx\n", G.crec.external_file_attributes); #endif xattr = (unsigned)((G.crec.external_file_attributes >> 16) & 0xFFFF); if (hostnum == VMS_) { char *p=attribs, *q=attribs+1; int i, j, k; for (k = 0; k < 12; ++k) workspace[k] = 0; if (xattr & VMS_IRUSR) workspace[0] = 'R'; if (xattr & VMS_IWUSR) { workspace[1] = 'W'; workspace[3] = 'D'; } if (xattr & VMS_IXUSR) workspace[2] = 'E'; if (xattr & VMS_IRGRP) workspace[4] = 'R'; if (xattr & VMS_IWGRP) { workspace[5] = 'W'; workspace[7] = 'D'; } if (xattr & VMS_IXGRP) workspace[6] = 'E'; if (xattr & VMS_IROTH) workspace[8] = 'R'; if (xattr & VMS_IWOTH) { workspace[9] = 'W'; workspace[11] = 'D'; } if (xattr & VMS_IXOTH) workspace[10] = 'E'; *p++ = '('; for (k = j = 0; j < 3; ++j) { /* loop over groups of permissions */ for (i = 0; i < 4; ++i, ++k) /* loop over perms within a group */ if (workspace[k]) *p++ = workspace[k]; *p++ = ','; /* group separator */ if (j == 0) while ((*p++ = *q++) != ',') ; /* system, owner perms are same */ } *p-- = '\0'; *p = ')'; /* overwrite last comma */ Info(slide, 0, ((char *)slide, LoadFarString(VMSFileAttributes), xattr, attribs)); } else if (hostnum == AMIGA_) { switch (xattr & AMI_IFMT) { case AMI_IFDIR: attribs[0] = 'd'; break; case AMI_IFREG: attribs[0] = '-'; break; default: attribs[0] = '?'; break; } attribs[1] = (xattr & AMI_IHIDDEN)? 'h' : '-'; attribs[2] = (xattr & AMI_ISCRIPT)? 's' : '-'; attribs[3] = (xattr & AMI_IPURE)? 'p' : '-'; attribs[4] = (xattr & AMI_IARCHIVE)? 'a' : '-'; attribs[5] = (xattr & AMI_IREAD)? 'r' : '-'; attribs[6] = (xattr & AMI_IWRITE)? 'w' : '-'; attribs[7] = (xattr & AMI_IEXECUTE)? 'e' : '-'; attribs[8] = (xattr & AMI_IDELETE)? 'd' : '-'; attribs[9] = 0; /* better dlm the string */ Info(slide, 0, ((char *)slide, LoadFarString(AmigaFileAttributes), xattr, attribs)); } else if (hostnum == THEOS_) { ZCONST char Far *fpFtyp; switch (xattr & THS_IFMT) { case THS_IFLIB: fpFtyp = TheosFTypLib; break; case THS_IFDIR: fpFtyp = TheosFTypDir; break; case THS_IFREG: fpFtyp = TheosFTypReg; break; case THS_IFREL: fpFtyp = TheosFTypRel; break; case THS_IFKEY: fpFtyp = TheosFTypKey; break; case THS_IFIND: fpFtyp = TheosFTypInd; break; case THS_IFR16: fpFtyp = TheosFTypR16; break; case THS_IFP16: fpFtyp = TheosFTypP16; break; case THS_IFP32: fpFtyp = TheosFTypP32; break; default: fpFtyp = TheosFTypUkn; break; } strcpy(attribs, LoadFarStringSmall(fpFtyp)); attribs[12] = (xattr & THS_INHID) ? '.' : 'H'; attribs[13] = (xattr & THS_IMODF) ? '.' : 'M'; attribs[14] = (xattr & THS_IWOTH) ? '.' : 'W'; attribs[15] = (xattr & THS_IROTH) ? '.' : 'R'; attribs[16] = (xattr & THS_IEUSR) ? '.' : 'E'; attribs[17] = (xattr & THS_IXUSR) ? '.' : 'X'; attribs[18] = (xattr & THS_IWUSR) ? '.' : 'W'; attribs[19] = (xattr & THS_IRUSR) ? '.' : 'R'; attribs[20] = 0; Info(slide, 0, ((char *)slide, LoadFarString(TheosFileAttributes), xattr, attribs)); #ifdef OLD_THEOS_EXTRA } else if (hostnum == FS_VFAT_ && hostver == 20) { /* process old non-official THEOS port zip archive */ ZCONST char Far *fpFtyp; switch (xattr & _THS_IFMT) { case _THS_IFLIB: fpFtyp = TheosFTypLib; break; case _THS_IFDIR: fpFtyp = TheosFTypDir; break; case _THS_IFREG: fpFtyp = TheosFTypReg; break; case _THS_IODRC: fpFtyp = TheosFTypRel; break; case _THS_IOKEY: fpFtyp = TheosFTypKey; break; case _THS_IOIND: fpFtyp = TheosFTypInd; break; case _THS_IOPRG: fpFtyp = TheosFTypR16; break; case _THS_IO286: fpFtyp = TheosFTypP16; break; case _THS_IO386: fpFtyp = TheosFTypP32; break; default: fpFtyp = TheosFTypUkn; break; } strcpy(attribs, LoadFarStringSmall(fpFtyp)); attribs[12] = (xattr & _THS_HIDDN) ? 'H' : '.'; attribs[13] = (xattr & _THS_IXOTH) ? '.' : 'X'; attribs[14] = (xattr & _THS_IWOTH) ? '.' : 'W'; attribs[15] = (xattr & _THS_IROTH) ? '.' : 'R'; attribs[16] = (xattr & _THS_IEUSR) ? '.' : 'E'; attribs[17] = (xattr & _THS_IXUSR) ? '.' : 'X'; attribs[18] = (xattr & _THS_IWUSR) ? '.' : 'W'; attribs[19] = (xattr & _THS_IRUSR) ? '.' : 'R'; attribs[20] = 0; Info(slide, 0, ((char *)slide, LoadFarString(TheosFileAttributes), xattr, attribs)); #endif /* OLD_THEOS_EXTRA */ } else if ((hostnum != FS_FAT_) && (hostnum != FS_HPFS_) && (hostnum != FS_NTFS_) && (hostnum != FS_VFAT_) && (hostnum != ACORN_) && (hostnum != VM_CMS_) && (hostnum != MVS_)) { /* assume Unix-like */ switch ((unsigned)(xattr & UNX_IFMT)) { case (unsigned)UNX_IFDIR: attribs[0] = 'd'; break; case (unsigned)UNX_IFREG: attribs[0] = '-'; break; case (unsigned)UNX_IFLNK: attribs[0] = 'l'; break; case (unsigned)UNX_IFBLK: attribs[0] = 'b'; break; case (unsigned)UNX_IFCHR: attribs[0] = 'c'; break; case (unsigned)UNX_IFIFO: attribs[0] = 'p'; break; case (unsigned)UNX_IFSOCK: attribs[0] = 's'; break; default: attribs[0] = '?'; break; } attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-'; attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-'; attribs[7] = (xattr & UNX_IROTH)? 'r' : '-'; attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-'; attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-'; attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-'; if (xattr & UNX_IXUSR) attribs[3] = (xattr & UNX_ISUID)? 's' : 'x'; else attribs[3] = (xattr & UNX_ISUID)? 'S' : '-'; /* S = undefined */ if (xattr & UNX_IXGRP) attribs[6] = (xattr & UNX_ISGID)? 's' : 'x'; /* == UNX_ENFMT */ else attribs[6] = (xattr & UNX_ISGID)? 'l' : '-'; if (xattr & UNX_IXOTH) attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x'; /* "sticky bit" */ else attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-'; /* T = undefined */ attribs[10] = 0; Info(slide, 0, ((char *)slide, LoadFarString(UnixFileAttributes), xattr, attribs)); } else { Info(slide, 0, ((char *)slide, LoadFarString(NonMSDOSFileAttributes), G.crec.external_file_attributes >> 8)); } /* endif (hostnum: external attributes format) */ if ((xattr=(unsigned)(G.crec.external_file_attributes & 0xFF)) == 0) Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributes), xattr)); else if (xattr == 1) Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesRO), xattr)); else Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesAlpha), xattr, (xattr&1)? "rdo " : nullStr, (xattr&2)? "hid " : nullStr, (xattr&4)? "sys " : nullStr, (xattr&8)? "lab " : nullStr, (xattr&16)? "dir " : nullStr, (xattr&32)? "arc " : nullStr, (xattr&64)? "lnk " : nullStr, (xattr&128)? "exe" : nullStr)); /*--------------------------------------------------------------------------- Analyze the extra field, if any, and print the file comment, if any (the filename has already been printed, above). That finishes up this file entry... ---------------------------------------------------------------------------*/ if (G.crec.extra_field_length > 0) { uch *ef_ptr = G.extra_field; ush ef_len = G.crec.extra_field_length; ush eb_id, eb_datalen; ZCONST char Far *ef_fieldname; if (error_in_archive > PK_WARN) /* fatal: can't continue */ /* delayed "fatal error" return from extra field reading */ return error_in_archive; if (G.extra_field == (uch *)NULL) return PK_ERR; /* not consistent with crec length */ Info(slide, 0, ((char *)slide, LoadFarString(ExtraFields))); while (ef_len >= EB_HEADSIZE) { eb_id = makeword(&ef_ptr[EB_ID]); eb_datalen = makeword(&ef_ptr[EB_LEN]); ef_ptr += EB_HEADSIZE; ef_len -= EB_HEADSIZE; if (eb_datalen > (ush)ef_len) { Info(slide, 0x421, ((char *)slide, LoadFarString(ExtraFieldTrunc), eb_id, eb_datalen, ef_len)); eb_datalen = ef_len; } switch (eb_id) { case EF_PKSZ64: ef_fieldname = efPKSZ64; if ((G.crec.relative_offset_local_header & (~(zusz_t)0xFFFFFFFFL)) != 0) { /* Subtract the size of the 64bit local offset from the local e.f. size, local Z64 e.f. block has no offset; when only local offset present, the entire local PKSZ64 block is missing. */ *pEndprev -= (eb_datalen == 8 ? 12 : 8); } break; case EF_AV: ef_fieldname = efAV; break; case EF_OS2: ef_fieldname = efOS2; break; case EF_ACL: ef_fieldname = efACL; break; case EF_NTSD: ef_fieldname = efNTSD; break; case EF_PKVMS: ef_fieldname = efPKVMS; break; case EF_IZVMS: ef_fieldname = efIZVMS; break; case EF_PKW32: ef_fieldname = efPKWin32; break; case EF_PKUNIX: ef_fieldname = efPKUnix; break; case EF_IZUNIX: ef_fieldname = efIZUnix; if (hostnum == UNIX_ && *pEndprev > 0L) *pEndprev += 4L; /* also have UID/GID in local copy */ break; case EF_IZUNIX2: ef_fieldname = efIZUnix2; if (*pEndprev > 0L) *pEndprev += 4L; /* 4 byte UID/GID in local copy */ break; case EF_IZUNIX3: ef_fieldname = efIZUnix3; #if 0 if (*pEndprev > 0L) *pEndprev += 4L; /* 4 byte UID/GID in local copy */ #endif break; case EF_TIME: ef_fieldname = efTime; break; case EF_UNIPATH: ef_fieldname = efU8Path; break; case EF_UNICOMNT: ef_fieldname = efU8Commnt; break; case EF_MAC3: ef_fieldname = efMac3; break; case EF_JLMAC: ef_fieldname = efJLMac; break; case EF_ZIPIT: ef_fieldname = efZipIt; break; case EF_ZIPIT2: ef_fieldname = efZipIt2; break; case EF_VMCMS: ef_fieldname = efVMCMS; break; case EF_MVS: ef_fieldname = efMVS; break; case EF_ATHEOS: ef_fieldname = efAtheOS; break; case EF_BEOS: ef_fieldname = efBeOS; break; case EF_QDOS: ef_fieldname = efQDOS; break; case EF_AOSVS: ef_fieldname = efAOSVS; break; case EF_SPARK: /* from RISC OS */ ef_fieldname = efSpark; break; case EF_MD5: ef_fieldname = efMD5; break; case EF_ASIUNIX: ef_fieldname = efASiUnix; break; case EF_TANDEM: ef_fieldname = efTandem; break; case EF_SMARTZIP: ef_fieldname = efSmartZip; break; case EF_THEOS: #ifdef OLD_THEOS_EXTRA case EF_THEOSO: #endif ef_fieldname = efTheos; break; default: ef_fieldname = efUnknown; break; } Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldType), eb_id, LoadFarStringSmall(ef_fieldname), eb_datalen)); /* additional, field-specific information: */ switch (eb_id) { case EF_OS2: case EF_ACL: if (eb_datalen >= EB_OS2_HLEN) { if (eb_id == EF_OS2) ef_fieldname = OS2EAs; else ef_fieldname = ACLdata; Info(slide, 0, ((char *)slide, LoadFarString(ef_fieldname), makelong(ef_ptr))); *pEndprev = 0L; /* no clue about csize of local */ } else { goto ef_default_display; } break; case EF_NTSD: if (eb_datalen >= EB_NTSD_C_LEN) { Info(slide, 0, ((char *)slide, LoadFarString(NTSDData), makelong(ef_ptr))); *pEndprev = 0L; /* no clue about csize of local */ } else { goto ef_default_display; } break; case EF_IZVMS: if (eb_datalen >= 8) { char *p, q[8]; unsigned compr = makeword(ef_ptr+EB_IZVMS_FLGS) & EB_IZVMS_BCMASK; *q = '\0'; if (compr > 3) compr = 3; switch (makelong(ef_ptr)) { case 0x42414656: /* "VFAB" */ p = "FAB"; break; case 0x4C4C4156: /* "VALL" */ p = "XABALL"; break; case 0x43484656: /* "VFHC" */ p = "XABFHC"; break; case 0x54414456: /* "VDAT" */ p = "XABDAT"; break; case 0x54445256: /* "VRDT" */ p = "XABRDT"; break; case 0x4F525056: /* "VPRO" */ p = "XABPRO"; break; case 0x59454B56: /* "VKEY" */ p = "XABKEY"; break; case 0x56534D56: /* "VMSV" */ p = "version"; if (eb_datalen >= 16) { /* put termitation first, for A_TO_N() */ q[7] = '\0'; q[0] = ' '; q[1] = '('; strncpy(q+2, (char *)ef_ptr+EB_IZVMS_HLEN, 4); A_TO_N(q+2); q[6] = ')'; } break; default: p = "unknown"; } Info(slide, 0, ((char *)slide, LoadFarString(izVMSdata), LoadFarStringSmall(izVMScomp[compr]), makeword(ef_ptr+EB_IZVMS_UCSIZ), p, q)); } else { goto ef_default_display; } break; case EF_TIME: if (eb_datalen > 0) { char types[80]; int num = 0, len; *types = '\0'; if (*ef_ptr & 1) { strcpy(types, LoadFarString(UTmodification)); ++num; } if (*ef_ptr & 2) { len = strlen(types); if (num) types[len++] = '/'; strcpy(types+len, LoadFarString(UTaccess)); ++num; if (*pEndprev > 0L) *pEndprev += 4L; } if (*ef_ptr & 4) { len = strlen(types); if (num) types[len++] = '/'; strcpy(types+len, LoadFarString(UTcreation)); ++num; if (*pEndprev > 0L) *pEndprev += 4L; } if (num > 0) Info(slide, 0, ((char *)slide, LoadFarString(UTdata), types, num == 1? nullStr : PlurSufx)); } break; case EF_UNIPATH: case EF_UNICOMNT: if (eb_datalen >= 5) { unsigned i, n; ulg name_crc = makelong(ef_ptr+1); if (eb_datalen <= 29) { Info(slide, 0, ((char *)slide, LoadFarString(U8PthCmnComplete), (unsigned)ef_ptr[0], name_crc)); n = eb_datalen; } else { Info(slide, 0, ((char *)slide, LoadFarString(U8PthCmnF24), (unsigned)ef_ptr[0], name_crc)); n = 29; } for (i = 5; i < n; ++i) Info(slide, 0, ((char *)slide, LoadFarString(efFormat), ef_ptr[i])); } else { goto ef_default_display; } break; case EF_MAC3: if (eb_datalen >= EB_MAC3_HLEN) { ulg eb_uc = makelong(ef_ptr); unsigned mac3_flgs = makeword(ef_ptr+EB_FLGS_OFFS); unsigned eb_is_uc = mac3_flgs & EB_M3_FL_UNCMPR; Info(slide, 0, ((char *)slide, LoadFarString(Mac3data), eb_uc, eb_is_uc ? "un" : nullStr)); if (eb_is_uc) { if (*pEndprev > 0L) *pEndprev += makelong(ef_ptr); } else { *pEndprev = 0L; /* no clue about csize of local */ } Info(slide, 0, ((char *)slide, LoadFarString(MacOSMAC3flags), LoadFarStringSmall(mac3_flgs & EB_M3_FL_DATFRK ? MacOS_DF : MacOS_RF), (mac3_flgs & EB_M3_FL_TIME64 ? 64 : 32))); zi_showMacTypeCreator(__G__ &ef_ptr[6]); } else { goto ef_default_display; } break; case EF_ZIPIT2: if (eb_datalen >= 5 && makelong(ef_ptr) == 0x5449505A /* "ZPIT" */) { if (eb_datalen >= 12) { zi_showMacTypeCreator(__G__ &ef_ptr[4]); } } else { goto ef_default_display; } break; case EF_ZIPIT: if (eb_datalen >= 5 && makelong(ef_ptr) == 0x5449505A /* "ZPIT" */) { unsigned fnlen = ef_ptr[4]; if ((unsigned)eb_datalen >= fnlen + (5 + 8)) { uch nullchar = ef_ptr[fnlen+5]; ef_ptr[fnlen+5] = '\0'; /* terminate filename */ A_TO_N(ef_ptr+5); Info(slide, 0, ((char *)slide, LoadFarString(ZipItFname), (char *)ef_ptr+5)); ef_ptr[fnlen+5] = nullchar; zi_showMacTypeCreator(__G__ &ef_ptr[fnlen+5]); } } else { goto ef_default_display; } break; case EF_JLMAC: if (eb_datalen >= 40 && makelong(ef_ptr) == 0x45454C4A /* "JLEE" */) { zi_showMacTypeCreator(__G__ &ef_ptr[4]); Info(slide, 0, ((char *)slide, LoadFarString(MacOSJLEEflags), LoadFarStringSmall(ef_ptr[31] & 1 ? MacOS_DF : MacOS_RF))); } else { goto ef_default_display; } break; case EF_SMARTZIP: if ((eb_datalen == EB_SMARTZIP_HLEN) && makelong(ef_ptr) == 0x70695A64 /* "dZip" */) { char filenameBuf[32]; zi_showMacTypeCreator(__G__ &ef_ptr[4]); memcpy(filenameBuf, &ef_ptr[33], 31); filenameBuf[ef_ptr[32]] = '\0'; A_TO_N(filenameBuf); Info(slide, 0, ((char *)slide, LoadFarString(ZipItFname), filenameBuf)); } else { goto ef_default_display; } break; #ifdef CMS_MVS case EF_VMCMS: case EF_MVS: { char type[100]; Info(slide, 0, ((char *)slide, LoadFarString(VmMvsExtraField), (getVMMVSexfield(type, ef_ptr-EB_HEADSIZE, (unsigned)eb_datalen) > 0)? type : LoadFarStringSmall(VmMvsInvalid))); } break; #endif /* CMS_MVS */ case EF_ATHEOS: case EF_BEOS: if (eb_datalen >= EB_BEOS_HLEN) { ulg eb_uc = makelong(ef_ptr); unsigned eb_is_uc = *(ef_ptr+EB_FLGS_OFFS) & EB_BE_FL_UNCMPR; if (eb_id == EF_ATHEOS) ef_fieldname = AtheOSdata; else ef_fieldname = BeOSdata; Info(slide, 0, ((char *)slide, LoadFarString(ef_fieldname), eb_uc, eb_is_uc ? "un" : nullStr)); if (eb_is_uc) { if (*pEndprev > 0L) *pEndprev += makelong(ef_ptr); } else { *pEndprev = 0L; /* no clue about csize of local */ } } else { goto ef_default_display; } break; case EF_QDOS: if (eb_datalen >= 4) { Info(slide, 0, ((char *)slide, LoadFarString(QDOSdata), ef_ptr[0], ef_ptr[1], ef_ptr[2], ef_ptr[3])); } else { goto ef_default_display; } break; case EF_AOSVS: if (eb_datalen >= 5) { Info(slide, 0, ((char *)slide, LoadFarString(AOSVSdata), ((int)(uch)ef_ptr[4])/10, ((int)(uch)ef_ptr[4])%10)); } else { goto ef_default_display; } break; case EF_TANDEM: if (eb_datalen == 20) { unsigned type, code; type = (ef_ptr[18] & 0x60) >> 5; code = makeword(ef_ptr); /* Arrg..., Tandem e.f. uses BigEndian byte-order */ code = ((code << 8) & 0xff00) | ((code >> 8) & 0x00ff); if (type == NSK_UNSTRUCTURED) { if (code == NSK_EDITFILECODE) type = 4; else if (code == NSK_OBJECTFILECODE) type = 5; } Info(slide, 0, ((char *)slide, LoadFarString(Tandemdata), LoadFarStringSmall(TandemFileformat[type]), code)); } else { goto ef_default_display; } break; case EF_MD5: if (eb_datalen >= 19) { char md5[33]; int i; for (i = 0; i < 16; ++i) sprintf(&md5[i<<1], "%02x", ef_ptr[15-i]); md5[32] = '\0'; Info(slide, 0, ((char *)slide, LoadFarString(MD5data), md5)); break; } /* else: fall through !! */ default: ef_default_display: if (eb_datalen > 0) { unsigned i, n; if (eb_datalen <= 24) { Info(slide, 0, ((char *)slide, LoadFarString(ColonIndent))); n = eb_datalen; } else { Info(slide, 0, ((char *)slide, LoadFarString(First20))); n = 20; } for (i = 0; i < n; ++i) Info(slide, 0, ((char *)slide, LoadFarString(efFormat), ef_ptr[i])); } break; } (*G.message)((zvoid *)&G, (uch *)".", 1L, 0); ef_ptr += eb_datalen; ef_len -= eb_datalen; } (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); } /* high bit == Unix/OS2/NT GMT times (mtime, atime); next bit == UID/GID */ if ((xattr = (unsigned)((G.crec.external_file_attributes & 0xC000) >> 12)) & 8) { if (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_) { Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType), "is", EF_IZUNIX, LoadFarStringSmall(efIZUnix), (unsigned)(xattr&12), (xattr&4)? efIZuid : efIZnouid)); if (*pEndprev > 0L) *pEndprev += (ulg)(xattr&12); } else if (hostnum == FS_FAT_ && !(xattr&4)) Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType), "may be", EF_IZUNIX, LoadFarStringSmall(efIZUnix), 8, efIZnouid)); } if (!G.crec.file_comment_length) Info(slide, 0, ((char *)slide, LoadFarString(NoFileComment))); else { Info(slide, 0, ((char *)slide, LoadFarString(FileCommBegin))); if ((error = do_string(__G__ G.crec.file_comment_length, DISPL_8)) != PK_COOL) { error_in_archive = error; /* might be warning */ if (error > PK_WARN) /* fatal */ return error; } Info(slide, 0, ((char *)slide, LoadFarString(FileCommEnd))); } return error_in_archive; } /* end function zi_long() */ /*************************/ /* Function zi_short() */ /*************************/ static int zi_short(__G) /* return PK-type error code */ __GDEF { #ifdef USE_EF_UT_TIME iztimes z_utime; time_t *z_modtim; #endif int k, error, error_in_archive=PK_COOL; unsigned hostnum, hostver, methid, methnum, xattr; char *p, workspace[12], attribs[16]; char methbuf[5]; static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */ static ZCONST char Far os[NUM_HOSTS+1][4] = { "fat", "ami", "vms", "unx", "cms", "atr", "hpf", "mac", "zzz", "cpm", "t20", "ntf", "qds", "aco", "vft", "mvs", "be ", "nsk", "ths", "osx", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "ath", "???" }; #ifdef OLD_THEOS_EXTRA static ZCONST char Far os_TheosOld[] = "tho"; #endif static ZCONST char Far method[NUM_METHODS+1][5] = { "stor", "shrk", "re:1", "re:2", "re:3", "re:4", "i#:#", "tokn", "def#", "d64#", "dcli", "bzp2", "lzma", "ters", "lz77", "wavp", "ppmd", "u###" }; /*--------------------------------------------------------------------------- Print out various interesting things about the compressed file. ---------------------------------------------------------------------------*/ methid = (unsigned)(G.crec.compression_method); methnum = find_compr_idx(G.crec.compression_method); hostnum = (unsigned)(G.pInfo->hostnum); hostver = (unsigned)(G.pInfo->hostver); /* extnum = (unsigned)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS); extver = (unsigned)G.crec.version_needed_to_extract[0]; */ zfstrcpy(methbuf, method[methnum]); if (methid == IMPLODED) { methbuf[1] = (char)((G.crec.general_purpose_bit_flag & 2)? '8' : '4'); methbuf[3] = (char)((G.crec.general_purpose_bit_flag & 4)? '3' : '2'); } else if (methid == DEFLATED || methid == ENHDEFLATED) { ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3); methbuf[3] = dtype[dnum]; } else if (methnum >= NUM_METHODS) { /* unknown */ sprintf(&methbuf[1], "%03u", G.crec.compression_method); } for (k = 0; k < 15; ++k) attribs[k] = ' '; attribs[15] = 0; xattr = (unsigned)((G.crec.external_file_attributes >> 16) & 0xFFFF); switch (hostnum) { case VMS_: { int i, j; for (k = 0; k < 12; ++k) workspace[k] = 0; if (xattr & VMS_IRUSR) workspace[0] = 'R'; if (xattr & VMS_IWUSR) { workspace[1] = 'W'; workspace[3] = 'D'; } if (xattr & VMS_IXUSR) workspace[2] = 'E'; if (xattr & VMS_IRGRP) workspace[4] = 'R'; if (xattr & VMS_IWGRP) { workspace[5] = 'W'; workspace[7] = 'D'; } if (xattr & VMS_IXGRP) workspace[6] = 'E'; if (xattr & VMS_IROTH) workspace[8] = 'R'; if (xattr & VMS_IWOTH) { workspace[9] = 'W'; workspace[11] = 'D'; } if (xattr & VMS_IXOTH) workspace[10] = 'E'; p = attribs; for (k = j = 0; j < 3; ++j) { /* groups of permissions */ for (i = 0; i < 4; ++i, ++k) /* perms within a group */ if (workspace[k]) *p++ = workspace[k]; *p++ = ','; /* group separator */ } *--p = ' '; /* overwrite last comma */ if ((p - attribs) < 12) sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10); } break; case AMIGA_: switch (xattr & AMI_IFMT) { case AMI_IFDIR: attribs[0] = 'd'; break; case AMI_IFREG: attribs[0] = '-'; break; default: attribs[0] = '?'; break; } attribs[1] = (xattr & AMI_IHIDDEN)? 'h' : '-'; attribs[2] = (xattr & AMI_ISCRIPT)? 's' : '-'; attribs[3] = (xattr & AMI_IPURE)? 'p' : '-'; attribs[4] = (xattr & AMI_IARCHIVE)? 'a' : '-'; attribs[5] = (xattr & AMI_IREAD)? 'r' : '-'; attribs[6] = (xattr & AMI_IWRITE)? 'w' : '-'; attribs[7] = (xattr & AMI_IEXECUTE)? 'e' : '-'; attribs[8] = (xattr & AMI_IDELETE)? 'd' : '-'; sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10); break; case THEOS_: switch (xattr & THS_IFMT) { case THS_IFLIB: *attribs = 'L'; break; case THS_IFDIR: *attribs = 'D'; break; case THS_IFCHR: *attribs = 'C'; break; case THS_IFREG: *attribs = 'S'; break; case THS_IFREL: *attribs = 'R'; break; case THS_IFKEY: *attribs = 'K'; break; case THS_IFIND: *attribs = 'I'; break; case THS_IFR16: *attribs = 'P'; break; case THS_IFP16: *attribs = '2'; break; case THS_IFP32: *attribs = '3'; break; default: *attribs = '?'; break; } attribs[1] = (xattr & THS_INHID) ? '.' : 'H'; attribs[2] = (xattr & THS_IMODF) ? '.' : 'M'; attribs[3] = (xattr & THS_IWOTH) ? '.' : 'W'; attribs[4] = (xattr & THS_IROTH) ? '.' : 'R'; attribs[5] = (xattr & THS_IEUSR) ? '.' : 'E'; attribs[6] = (xattr & THS_IXUSR) ? '.' : 'X'; attribs[7] = (xattr & THS_IWUSR) ? '.' : 'W'; attribs[8] = (xattr & THS_IRUSR) ? '.' : 'R'; sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10); break; case FS_VFAT_: #ifdef OLD_THEOS_EXTRA if (hostver == 20) { switch (xattr & _THS_IFMT) { case _THS_IFLIB: *attribs = 'L'; break; case _THS_IFDIR: *attribs = 'd'; break; case _THS_IFCHR: *attribs = 'c'; break; case _THS_IFREG: *attribs = 'S'; break; case _THS_IODRC: *attribs = 'D'; break; case _THS_IOKEY: *attribs = 'K'; break; case _THS_IOIND: *attribs = 'I'; break; case _THS_IOPRG: *attribs = 'P'; break; case _THS_IO286: *attribs = '2'; break; case _THS_IO386: *attribs = '3'; break; default: *attribs = '?'; break; } attribs[1] = (xattr & _THS_HIDDN) ? 'H' : '.'; attribs[2] = (xattr & _THS_IXOTH) ? '.' : 'X'; attribs[3] = (xattr & _THS_IWOTH) ? '.' : 'W'; attribs[4] = (xattr & _THS_IROTH) ? '.' : 'R'; attribs[5] = (xattr & _THS_IEUSR) ? '.' : 'E'; attribs[6] = (xattr & _THS_IXUSR) ? '.' : 'X'; attribs[7] = (xattr & _THS_IWUSR) ? '.' : 'W'; attribs[8] = (xattr & _THS_IRUSR) ? '.' : 'R'; sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10); break; } /* else: fall through! */ #endif /* OLD_THEOS_EXTRA */ case FS_FAT_: case FS_HPFS_: case FS_NTFS_: case VM_CMS_: case MVS_: case ACORN_: if (hostnum != FS_FAT_ || (unsigned)(xattr & 0700) != ((unsigned)0400 | ((unsigned)!(G.crec.external_file_attributes & 1) << 7) | ((unsigned)(G.crec.external_file_attributes & 0x10) << 2)) ) { xattr = (unsigned)(G.crec.external_file_attributes & 0xFF); sprintf(attribs, ".r.-... %u.%u", hostver/10, hostver%10); attribs[2] = (xattr & 0x01)? '-' : 'w'; attribs[5] = (xattr & 0x02)? 'h' : '-'; attribs[6] = (xattr & 0x04)? 's' : '-'; attribs[4] = (xattr & 0x20)? 'a' : '-'; if (xattr & 0x10) { attribs[0] = 'd'; attribs[3] = 'x'; } else attribs[0] = '-'; if (IS_VOLID(xattr)) attribs[0] = 'V'; else if ((p = MBSRCHR(G.filename, '.')) != (char *)NULL) { ++p; if (STRNICMP(p, "com", 3) == 0 || STRNICMP(p, "exe", 3) == 0 || STRNICMP(p, "btm", 3) == 0 || STRNICMP(p, "cmd", 3) == 0 || STRNICMP(p, "bat", 3) == 0) attribs[3] = 'x'; } break; } /* else: fall through! */ default: /* assume Unix-like */ switch ((unsigned)(xattr & UNX_IFMT)) { case (unsigned)UNX_IFDIR: attribs[0] = 'd'; break; case (unsigned)UNX_IFREG: attribs[0] = '-'; break; case (unsigned)UNX_IFLNK: attribs[0] = 'l'; break; case (unsigned)UNX_IFBLK: attribs[0] = 'b'; break; case (unsigned)UNX_IFCHR: attribs[0] = 'c'; break; case (unsigned)UNX_IFIFO: attribs[0] = 'p'; break; case (unsigned)UNX_IFSOCK: attribs[0] = 's'; break; default: attribs[0] = '?'; break; } attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-'; attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-'; attribs[7] = (xattr & UNX_IROTH)? 'r' : '-'; attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-'; attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-'; attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-'; if (xattr & UNX_IXUSR) attribs[3] = (xattr & UNX_ISUID)? 's' : 'x'; else attribs[3] = (xattr & UNX_ISUID)? 'S' : '-'; /* S==undefined */ if (xattr & UNX_IXGRP) attribs[6] = (xattr & UNX_ISGID)? 's' : 'x'; /* == UNX_ENFMT */ else /* attribs[6] = (xattr & UNX_ISGID)? 'l' : '-'; real 4.3BSD */ attribs[6] = (xattr & UNX_ISGID)? 'S' : '-'; /* SunOS 4.1.x */ if (xattr & UNX_IXOTH) attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x'; /* "sticky bit" */ else attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-'; /* T==undefined */ sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10); break; } /* end switch (hostnum: external attributes format) */ #ifdef OLD_THEOS_EXTRA Info(slide, 0, ((char *)slide, "%s %s %s ", attribs, LoadFarStringSmall(((hostnum == FS_VFAT_ && hostver == 20) ? os_TheosOld : os[hostnum])), FmZofft(G.crec.ucsize, "8", "u"))); #else Info(slide, 0, ((char *)slide, "%s %s %s ", attribs, LoadFarStringSmall(os[hostnum]), FmZofft(G.crec.ucsize, "8", "u"))); #endif Info(slide, 0, ((char *)slide, "%c", (G.crec.general_purpose_bit_flag & 1)? ((G.crec.internal_file_attributes & 1)? 'T' : 'B') : /* encrypted */ ((G.crec.internal_file_attributes & 1)? 't' : 'b'))); /* plaintext */ k = (G.crec.extra_field_length || /* a local-only "UX" (old Unix/OS2/NT GMT times "IZUNIX") e.f.? */ ((G.crec.external_file_attributes & 0x8000) && (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_))); Info(slide, 0, ((char *)slide, "%c", k? ((G.crec.general_purpose_bit_flag & 8)? 'X' : 'x') : /* extra field */ ((G.crec.general_purpose_bit_flag & 8)? 'l' : '-'))); /* no extra field */ /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ extended local header or not */ if (uO.lflag == 4) { zusz_t csiz = G.crec.csize; if (G.crec.general_purpose_bit_flag & 1) csiz -= 12; /* if encrypted, don't count encryption header */ Info(slide, 0, ((char *)slide, "%3d%%", (ratio(G.crec.ucsize,csiz)+5)/10)); } else if (uO.lflag == 5) Info(slide, 0, ((char *)slide, " %s", FmZofft(G.crec.csize, "8", "u"))); /* For printing of date & time, a "char d_t_buf[16]" is required. * To save stack space, we reuse the "char attribs[16]" buffer whose * content is no longer needed. */ # define d_t_buf attribs #ifdef USE_EF_UT_TIME z_modtim = G.extra_field && #ifdef IZ_CHECK_TZ G.tz_is_valid && #endif (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1, G.crec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME) ? &z_utime.mtime : NULL; TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7.0 or Macintosh */ d_t_buf[0] = (char)0; /* signal "show local time" */ #else # define z_modtim NULL #endif Info(slide, 0, ((char *)slide, " %s %s ", methbuf, zi_time(__G__ &G.crec.last_mod_dos_datetime, z_modtim, d_t_buf))); fnprint(__G); /*--------------------------------------------------------------------------- Skip the file comment, if any (the filename has already been printed, above). That finishes up this file entry... ---------------------------------------------------------------------------*/ SKIP_(G.crec.file_comment_length) return error_in_archive; } /* end function zi_short() */ /**************************************/ /* Function zi_showMacTypeCreator() */ /**************************************/ static void zi_showMacTypeCreator(__G__ ebfield) __GDEF uch *ebfield; { /* not every Type / Creator character is printable */ if (isprint(native(ebfield[0])) && isprint(native(ebfield[1])) && isprint(native(ebfield[2])) && isprint(native(ebfield[3])) && isprint(native(ebfield[4])) && isprint(native(ebfield[5])) && isprint(native(ebfield[6])) && isprint(native(ebfield[7]))) { Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata), native(ebfield[0]), native(ebfield[1]), native(ebfield[2]), native(ebfield[3]), native(ebfield[4]), native(ebfield[5]), native(ebfield[6]), native(ebfield[7]))); } else { Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata1), (((ulg)ebfield[0]) << 24) + (((ulg)ebfield[1]) << 16) + (((ulg)ebfield[2]) << 8) + ((ulg)ebfield[3]), (((ulg)ebfield[4]) << 24) + (((ulg)ebfield[5]) << 16) + (((ulg)ebfield[6]) << 8) + ((ulg)ebfield[7]))); } } /* end function zi_showMacTypeCreator() */ /************************/ /* Function zi_time() */ /************************/ static char *zi_time(__G__ datetimez, modtimez, d_t_str) __GDEF ZCONST ulg *datetimez; ZCONST time_t *modtimez; char *d_t_str; { unsigned yr, mo, dy, hh, mm, ss; char monthbuf[4]; ZCONST char *monthstr; static ZCONST char Far month[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; #ifdef USE_EF_UT_TIME struct tm *t; #endif /*--------------------------------------------------------------------------- Convert the file-modification date and time info to a string of the form "1991 Feb 23 17:15:00", "23-Feb-91 17:15" or "19910223.171500", depending on values of lflag and T_flag. If using Unix-time extra fields, convert to local time or not, depending on value of first character in d_t_str[]. ---------------------------------------------------------------------------*/ #ifdef USE_EF_UT_TIME if (modtimez != NULL) { #ifndef NO_GMTIME /* check for our secret message from above... */ t = (d_t_str[0] == (char)1)? gmtime(modtimez) : localtime(modtimez); #else t = localtime(modtimez); #endif if (uO.lflag > 9 && t == (struct tm *)NULL) /* time conversion error in verbose listing format, * return string with '?' instead of data */ return (strcpy(d_t_str, LoadFarString(lngYMDHMSTimeError))); } else t = (struct tm *)NULL; if (t != (struct tm *)NULL) { mo = (unsigned)(t->tm_mon + 1); dy = (unsigned)(t->tm_mday); yr = (unsigned)(t->tm_year); hh = (unsigned)(t->tm_hour); mm = (unsigned)(t->tm_min); ss = (unsigned)(t->tm_sec); } else #endif /* USE_EF_UT_TIME */ { yr = ((unsigned)(*datetimez >> 25) & 0x7f) + 80; mo = ((unsigned)(*datetimez >> 21) & 0x0f); dy = ((unsigned)(*datetimez >> 16) & 0x1f); hh = (((unsigned)*datetimez >> 11) & 0x1f); mm = (((unsigned)*datetimez >> 5) & 0x3f); ss = (((unsigned)*datetimez << 1) & 0x3e); } if (mo == 0 || mo > 12) { sprintf(monthbuf, LoadFarString(BogusFmt), mo); monthstr = monthbuf; } else monthstr = LoadFarStringSmall(month[mo-1]); if (uO.lflag > 9) /* verbose listing format */ sprintf(d_t_str, LoadFarString(lngYMDHMSTime), yr+1900, monthstr, dy, hh, mm, ss); else if (uO.T_flag) sprintf(d_t_str, LoadFarString(DecimalTime), yr+1900, mo, dy, hh, mm, ss); else /* was: if ((uO.lflag >= 3) && (uO.lflag <= 5)) */ sprintf(d_t_str, LoadFarString(shtYMDHMTime), yr%100, monthstr, dy, hh, mm); return d_t_str; } /* end function zi_time() */ #endif /* !NO_ZIPINFO */ Carla-2.1/doc/000077500000000000000000000000001364475620200131545ustar00rootroot00000000000000Carla-2.1/doc/Carla-TODO000066400000000000000000000065171364475620200146750ustar00rootroot00000000000000# Carla TODO # ---------------------------------------------------------------------------- # in short 4. custom "plugin slots" skins, ala Reason (also define set of keys for a new LV2 extension, 80% done) 7. direct support for csound files (as plugins, inspired by 'cabbage') Ideas for later: 10. easier canvas connections by using smart key shortcuts 11. Mobile version (using Android Patchfield for example) 12. Mobile OSC Control app 13. Port good JACK-only apps as internal plugins (zita stuff would be nice) # ---------------------------------------------------------------------------- # current work FRONTEND: - more skins - testing stuff BACKEND: - noexcept wherever possible OTHER: - create tests for all utils code - fix reported bugs # ---------------------------------------------------------------------------- # more detailed GENERAL: - add direct program access on ui-dialogs (needed for standalone bridges), maybe add extra buttons too (reset plugin, fix ui size) - implement midi-learn (new dialog) - implement favorite plugins, add in new tab near file-browser - blender style canvas theme - NSM rework FRONTEND: - make always-on-top depend on it^ - complete zynfx, knob values on top - synth skin - samplers skin ENGINE: - allow to change position of plugins (up/down) - allow to add plugins when engine is stopped - implement Haiku Media support (based from JACK?, LATER) - implement latency in continuous-rack mode - add MIDI-bank change type (GM, GS, XG and MMA). See fluidsynth and los docs ~ allow to use static OSC ports - switch engine modes when opening project - don't pass audio buffers to plugin process, make them request via ports PLUGINS: - add control-out rate/freq option in frames (or just a regular block-size option?) - control/midi-out in singleProcess() calls, use timeoutFrames var - implement midi-cc automation special rules (invert, half, logarithmic, etc) - implement LSCP file support (new native plugin?) - implement Csound file support LADSPA: DSSI: - custom chunk-data extension, publish on kx website when complete LV2: - revisit all extensions - strict bounds recheck FluidSynth: - per-channel volume control - proper buffer-size/sample-rate change (needs testing) LinuxSampler: - per-channel volume pan&control - proper buffer-size/sample-rate change (needs testing) # ---------------------------------------------------------------------------- # //tb/150118 misc -allow to open instruments via file/open menu (same as drag from left-side tree) -allow drag of sfz/sf2/gig etc. also to patchbay (same effect as dragging to rack) -action "remove all" in toolbar and plugin menu: add confirm dialog /!\ -action "remove folder": add confirm dialog -add plugin macro "reset parameters" -allow re-ordering of rack components -setting: auto-connect to physical output when new instrument loaded (for quick audition) -for instruments: highlight keys with assigned samples or unhighlight keys without assigned sample -allow in-line edit window (i.e. right of rack/canvas) -> shows as soon as plugin/instr. is selected -indicate engine at work top right -if engine is jack, show load top right (percent and/or gauge) -warn on quit if unsaved patchbay -allow click a, click b port connections -allow multiple port selection + connection (i.e. with enter) -allow to select connections with lasso (to delete) Carla-2.1/doc/Carla-TestCases000066400000000000000000000054301364475620200160170ustar00rootroot00000000000000# This document describes manual test cases for Carla. ---------------------------------------------------------------------------------------- ----Section 1. ----------------------------------------------------------------------- REFRESH PLUGINS Native plugins: -N- LADSPA -N- DSSI -N- LV2 -N- VST -N- GIG -N- SF2 -N- SFZ -N- Native Non-native, posix plugins: -N- LADSPA -N- DSSI -N- LV2 -N- VST Non-native, win32 plugins: -N- LADSPA -N- DSSI [*] -N- LV2 -N- VST Non-native, win64 plugins: -N- LADSPA [*] -N- DSSI [*] -N- LV2 -N- VST ---------------------------------------------------------------------------------------- ----Section 2. ----------------------------------------------------------------------- LOADING PLUGINS (load and safely remove) Native plugins: -N- LADSPA -N- DSSI -N- LV2 -N- VST -N- GIG -N- SF2 -N- SFZ -N- Native Non-native, posix plugins: -N- LADSPA -N- DSSI -N- LV2 -N- VST Non-native, win32 plugins: -N- LADSPA -N- DSSI [*] -N- LV2 -N- VST Non-native, win64 plugins: -N- LADSPA [*] -N- DSSI [*] -N- LV2 -N- VST ---------------------------------------------------------------------------------------- ----Section 3. ----------------------------------------------------------------------- SAVE & RESTORE PLUGIN STATE (Manual and In-Project, verify data) Native plugins: -N- LADSPA -N- DSSI -N- LV2 -N- VST -N- SF2 Non-native, posix plugins: -N- LADSPA -N- DSSI -N- LV2 -N- VST Non-native, win32 plugins: -N- LADSPA -N- DSSI [*] -N- LV2 -N- VST Non-native, win64 plugins: -N- LADSPA [*] -N- DSSI [*] -N- LV2 -N- VST ---------------------------------------------------------------------------------------- ----Section 4. ----------------------------------------------------------------------- LOADING PLUGIN'S GUI (load, show/hide, close/reopen) Native plugins: -N- DSSI (OSC based) -N- LV2 (External-UI, internal) -N- LV2 (Qt4-UI, internal) -N- LV2 (X11-UI, internal) -N- LV2 (Suil-UI, internal) -N- LV2 (Gtk2-UI, OSC bridged) -N- LV2 (Gtk3-UI, OSC bridged) [*] -N- LV2 (Qt4-UI, OSC bridged) -N- LV2 (X11-UI, OSC bridged) -N- VST (internal) -N- VST (OSC bridged) Non-native, posix plugins: -N- LV2 (External-UI, internal) -N- LV2 (Qt4-UI, internal) -N- LV2 (X11-UI, internal) -N- VST (internal) Non-native, win32 plugins: -N- LV2 (External-UI, internal) -N- LV2 (Qt4-UI, internal) [*] -N- LV2 (Windows-UI, internal) [*] -N- VST (internal) Non-native, win64 plugins: -N- LV2 (External-UI, internal) -N- LV2 (Qt4-UI, internal) [*] -N- LV2 (Windows-UI, internal) [*] -N- VST (internal) ---------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------- [*] Cannot test, no such plugins yet Carla-2.1/doc/GPL.txt000066400000000000000000000355641364475620200143540ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Carla-2.1/doc/LGPL.txt000066400000000000000000000167431364475620200144660ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. Carla-2.1/resources/000077500000000000000000000000001364475620200144215ustar00rootroot00000000000000Carla-2.1/resources/128x128/000077500000000000000000000000001364475620200153565ustar00rootroot00000000000000Carla-2.1/resources/128x128/carla-control.png000066400000000000000000000314721364475620200206330ustar00rootroot00000000000000PNG  IHDR>a pHYsu852IDATx}kqU=Y , .L,ɔuxG=_݅-Y+Ζ}9ws#x˔eg٦dN$R&iK-!H $b>;3;Y :dnj&fƛ%"oƗ)I=@EO]3Smvя9r$m eZV$m5qykeB(X`GeL!]3 cjQ 5/dLj.`0ZVXe<92 ZMZ-}_/#T,F]f"DBn6VRJ8YZZqy\V#G,2a-FXF䤨jnˡ!nZ iQ8 ZCBa.3BEw:h,FJiq]W///uMZG` iЗG~yyY/Ţt8RZ;BZRJ)Y2sJ@Zk c!WJZk}P(f;cŢKJU ONNFAFCEn;Rʂ+p`)!bF`f)}‘ V|lDofXkێ㴍1cLu]lrYe>zLy^yH) V A/xDZk]"rQDBPt㰆3P }ٯ#Μd Iڰs6fn1'vgf}!DZ_ڶy-n;P%|u D`%e%~,8R!)@@E:8Txzr@tp~Nmg=lZuk` B !%})!D"/0@haLP95^Z'gak1ucLMksk;OXAD+D2Dd@h4p[k\B <FDJ!]`h]'9蟛ž1lXk#6y1QZ(%TB!W,bd ^Q>vq8nb@SCD(m"?y>ԨH6PX ~km @L!mkM'&[hGx-2"PVÇYZΗ,XkkB%!D]Jو͛u8EH< j}_pxC? `S)%]"! bq5ʕrwAN^ : X|9hmD#YfF&64!86{2!8V8{- La;q;*s qcաr! j jI'Q߽{h۲X,:J)G2sQ1DDՂLjp= !$"ʝ{Z'0( ρATʜ~-=e(U9em@x :N]b F:SX6<%}ʆ\P}$aVFygCB\_[ !f. !\)e!ݻwSHhZNGES=f.3sؼC+qAX$Ƣ+ZtMR=E !R#1>R%mhFtm)et%AH{8NܻlP^2TonEhj), \֫6A92~(-yf0sRBQZkj(y&''}Q*8Ӿ23I@ ?p%ua/#B//TaLj(qsX.:tLQsw,A@@AeX^@@A$$\p-kq lx,} "MD"fX  Ī)l>4JPE0=/:J%L9TR7 ut]Z{% WEz*CC fX0`5j+@` ል*E:01PLr$))x$ Q&tBOQ#~Ekq%=/z^oŰL xBQ;mAꢽbi"Ŏ[7ܹ`E*Zvl4&F;w1Fj#/ 24+&XB]t`X3Dzg5=⌵ 4.agє/g非|3e9L%^٠ن&/3Z`kAd9(lC^Mʦ" ! =!+r ZkP(b(455EQI- 8Jh RJ\Y,9YwE O ̏_Q?xOҖ|! wÓ~ف9e{,s">[g,-3,kA[XcC)&nX)di1cQZV+ձh۔!"hY: bmȪ.$)#.=r:o'؃%y.Z J'8nOueX& 2F0arWDϬ $l,yM 161P(H"XkQl :[V^#GՄ aɑ\MQHfn<~mB~Y$$S%f ,$l` B CX CX:Ņ 8;N8Bv:2ƈdTc֚"U@DH|P'Gksgp HYRǏl`,gg3./P%"ZHb(*XhI)Ea CU  H;uPcu,//=#lOU6 +pdv 1DZ@ U@<@gBREDckbsh `ӧOR-[#YBXu@ESAU/t䑵64 ̍fYO =R #Ht׹ZrezDDPBhoum4~/YH)EPs2"clEdAǡ_(ڳgoFkpYj5RlH=J)?~ OuĬ'8,HD̜!1&$%-\" @:Rp]P.7RR (YtyA,YcB'հ,t@)]dH!c,e[#FZjempcab9O؀y1siЕ=ֻIFIGM $Y"@^n@Jߝ!Sׄc@FE"JJ|/~;ɅD t}i 0X0m~=kH$Xj]ebSreO#b|#0k])0pJR`hh# X z}çxoJ-t>oHHw4SD;vʝ;AVCVU -[޽Z<󘟟 ,l.Bժ5` ̐݇"{}Lr 6ݨx#p'1wN6p3g/˜zZ1>>qp}B.8>O`ll +++x#y/YO8s r%g_Y֗"PVZ)ngqH)|+_u]B`+Pٳw܁᧞B8w~<57~7p|ӟƖ-[|:vڅv !{qa5 D~8 \ kKτc`;ե%obw}KJ8_NӧTctb~76aۖ-+lSSSx̘Çq뭷ٳx;߉~(t:y8|pl_|M  p?|``QL<|3XXY4N>iٳgU*k!?AL<4nC`cevvrǏooaǎ{r333 u|}v6u{'7T&[bɓx>3fgg1;;9'&@W]Aae[.{WVV`Ν;sK/8s Ow}7>ԩSb_%儞 ~ > H7$۔s(_  kwjaii KKKjjh "J%03AR{ΝaltNZ}Ox衇p 7lxߏ+owCg?Y~a8r{ >!63`~5%Y#J)bU߇/%Z&ZVVVh4)%p]vV CXЋ/b޽k'/I<8z(6&''166{x޽{gyf W~uݗ/iܑ|,VkI&_Hyr2l6H` VVV.<σ1&^*P \c=:g>[~fffp[ 2 2}X}prsOOg L{IZYYI4;xCCa 8DJ(077i܋MZ ޿Ogu͛7cӦM}Hk#0I\ ̰ *gΠTT*X,RZB"B\F\FXDT+/qZ^?#j ~ 0!ϓXǩ;YMLlZ |u]T*BJo~y~'po3&&&011Vi,--%ؾ};֘\zJ%\uU<8sǍ.}7솅D ~o^{u\q뭘Byd$v&Zbtt_?ĉ07܀x7r:qA|D^"Ν;Z D۷~|#Ek "TUگ&&&E|;KxR09֢ 0@N]p keJB(_{ ۷mëaǟ9^9xO_u6 cWbia/=k_~6ow }0N|_1::Eh!@Rm۰v`aaZ Z),..baa җ믿ZLOO_ză&q[oQiw0ffsu)*<T*븵T8mÓ B&''c#1F,:jv f{meIxAekk] tX0I1dǎ̹sQݿ?xV9*Zo|c͠ʹ9 ifP(`)0g6tFo ˳8䓘{Yto'N˯:pP"wމb~~ z++_ ;!>oDVÃ>W^y]~-wQWs`5 'd`RQkrH7ވj|fhki167Gɯ~CP*tY_E{?;vou]J׷w~Ν>98}L \~ /(`_ !aѷ(ZګF{=_DMs'=ogy}V~,--G7ߌ}8(J<055ñ]+ [Ci9>qkHH6A###:>O==0M={ϟD PV1e :şIlqA>|ccc=;>C2/g.fo l߶ W<'+Y 0s'̵עTضm۪{۷O3&~~ 8wC`/> j,cT0m?h۩<1^\\D^;ʕW<;5WW_u\i\}ַزe ۇ'N`aa?8~Wwƾ}я~t | ݻaᙈDI)(˨Z0&VVVjh4Pl6!Z8O`sT^~k%r/|y{}_t:;ߎx{뮻PCaVaLk \3SiF:l}F`&D\9T,!(VaCZkux󠵎cZ,/ch?xܙ3g}ˌG}>`}`/L,,wjn]MeޑlXH$A]5@d Ʉsshv:(qh0'0󐋋##|X+?<_ 60mb/A  aYH)SyRrT*ii7o Hˁ hBWc ( ~~xr^G}|g|(QK t: "xJM6P(_nCp[n86N>zj;ϟO]<;vyG1KZ?bm70:f wɓo|-R*06~l>yby݋O}ShZX\\ĩSq0֭[Zoo|_0== !{=w@~7Xg4/ mj2^;y1<8Ν> ܹ3WT'8^Gχ㍍kTr Z[o3C)CX"&w B̌CaϞ=ϟ?FG3Bd.WÂ)x8'V-^yUl߶ ۇ,{pdbز};ѣx1<~7 N{ž_۴iضm['!DR]v[ZZR Zr-qvqUWall OPE)'[O{_6w*9 J?9 `3Ϡ0KKΟǏ+֍7bkpW]iN(_6OX^^Ge,X\\DVuĉ],y lsk}/;{OXO,p!_MWjyg`j~U݆;?s'͛fϞœƚasssxWc#p_ucP#O]CلR }C_ mzF8lhHq!݆CW<( شiFGGsj߷Z-x; "gCx X=;wǏS8q7quŮ %dƩ T NF(ïO}܋UmH23)o\p7*W0Q M7$^"!D5J܋D PVq=Y`kQAȖ$9deX\E,m]Q2p7.YG4g>g ²l\bfXcF3+;@k80"?DTa#We0,ð'fXoAo2E{J!sB1B%Xia `X6m_LSdZk c-GKIz@ x"b!'TГ%(vd-oۙ,3|~O9#;ڀ/!d$#$1; !22')^1  k,4kp PBnU SkޤLs5+S65&emPgKN[ Fhkka55`- 'u[ mcR= SpޱcGcDdJXaA 6FPp]wl Y@M1Uݔ;;z6{*Zqn]җzQTHN0zFC?X` N? !EB[MZˡIpR1 `g: f L҈daČ63$` O$}FR.Ne Z3,ES΢N7HXֲ ?cCZqSL`,HI@)ϳR &"Z3c D`tcQ};VXX@%ބ*$?c1BRd#b.G!'n5EmB 8P$~a {'tjR{T %'0 B@^R"lj% c涵WJi23R8V)e1K);nwEn@t^4µKijB fً~b>~41u-ȷ]Z? Ek}O3s[JٱRJ-4Dd=ϋD`љ3ghttY(PJʢr *ŝĝ1pZq1+W?9ljD2r2~#;eS*)RX\=t̹XPJt:vŢylt/Q,9en6F)e־%hXY7 ! LGP$K}B>g8Z}qap|\~Hta_! ]ףᑱHN3s/_+ZڶWJ\.G?'k9z(;cWVV8M "Z^7೅vVyW?3*st=#{9r3@/XPhl˄WO|Z[tDZGd% y+LP637!X+vA53X_X7|NN$K'N| 밡Q`Ȕ+U5e(gaLjND+4t VJPVDq^y뺮i6~D4ԙX=9F ͖;`0w\죿I9{܏1?MwR;d4IH&f,2_m؂ac#X+ b:α_z̼d]&kmi6W^jJZeBL%_ccc.bX$DL v;@""[!]!wd LJׂiTx>t&\6`7.tUGAu_ 3W#GMtϰ^o@N6Z̙._ϓJ(ǕN TQ̺V[ډ_fky^}ZqJڙRwZM[(Yk+ڊJDÞRW "\3&pG9ar(ITnTs6>luc c, 0!RAp!K̾Akf810ZCN'F6WZ&_S qP(8p'gg~x9KBe!Dn;rY8q"ZO-IXڵKur](ZffBlv?=>>o!'Ē6AХn8LJRsd(CRнv>5ji4VqnfBF8WnJO8ak0@8%ֺju]L 3k/ !VJv !B! | |,Bz]'M2ې}˙u1nJfAPg~55umIGvul$]0n2]$BAOdQAr̝IENDB`Carla-2.1/resources/128x128/carla.png000066400000000000000000000277501364475620200171610ustar00rootroot00000000000000PNG  IHDR>a pHYsu85/IDATx}{\Gyﯻk;ie뱲"ie bcp+UI%!$TH9Rr+rU*Py Ebl  q~K-e]c3s̙33g]WutGO믻CZ"~()Wzct&l[*%q/X W :NQbYuẮbI"@REQ۪رcu&ž!6#iJB\%P!S)%f  I1A) EQd*a] >.#DQZ(eYY4McssTUe 6C4MCPKAm{qI)ApgmsEQnT⺮l6+;1A,iЖ{T*1qX"PmVTUUEQ]U)BB0R2),\ו4sN)RW(⸮8hj5GUUH$PPtdH?::* T*J"P-RccLsGsQJ}FR2J)hKLЙ|H! !Ƙ-ۺ;ZIRn*ǎ- ~W PciF@Aх:!D%H5IMHI!A+M+hyo$tId>I&{ԟEWO#yxxϞORB󅨷~J[:RJGJPJ-)l5)eMaaXe6LЎZu]# Rʤ2  D=[ĞU˱:G(xkKf%cIb%]IJd=n 8AFB B 'N:F= 0M PMkzku8ZZJZJZJ 8nUMD&#Uuifݽ{-a@T!*cPH.otR,MrDM!6='RJ;^#'d;lT5T1T& Ϳ~}~eZWGsB 4M(W/A&P eZ(0Tz4O1l}^jPRՕD *\\I % aDJi?%~e}, u "a`s|N@T.e9^CBJ  W< (AR8o5< \u\pu9xpq)$ e DǙg׸Fau %39~| dC} (i@k5EH=>yp@)-RJˌ,[m ]AB: UU ܽYE2N 58겇`ޛ#t D⥷C8 vi `퀾g;>yH+J)%M8P(D`[-[eY,HR]JB\z_R $ >`VWz)B#Sy?\9607>A)ŲOPJIJCweH{aMI\em+POJRm4T/Il[o^!n ~{LmF#~pJ)ž-=+ۤi)e`im+24ïn.(q&IEUUq a_@uu)@(Ɵ0D$^rv`TX` ܮQJ@h2r!0wll4%wwRp@a=,ˋ>{S7ADpyHB֬YukBBBBQP^֖-B1;;l8 Qp0eMkcR< b,V% l:dgXַ"{ (`Q̌\}n\t _~wL&ذa2|I|[.g?Y L\|ۺ)Q@c~G13ᕿ/S޹+''OQp+ám*mC;y)d{7]3t,'> =zg!֭[;vuO]vX,bMm޽“O>|>ߦHdDY *t[66mBXį=&d^{5?/^D\FV,lxi\Vj\UU{n<#/6mڄYٟv{q]w5T*UVP(ӟ4/_~e-߷ ֕%QL088e=wzUŋ111 .I4Vm wagW~0% nbjj 7tEԷ|=xA\[BEwewQwFG.PVXL)1==i`vv?333YmCVbE-u+WlJwߍw]r\ l۶ {%9rĿ^R\=g7q,d>soeDXDXDP@PeY LBJ UUNyv] qr}s}݇CVƍ`ٲeq:@Yk[o;9rd rRҠQ헃 '@I$u84Mj5jJj ue4Me2 嗱be|qqܹeᡇ8'?m۶ooHߑ#G`6 ~[ԧwPCzSBߡGj{vdf2 TJYJ%B.Yj ]qL&Q ]s{챦4k ɓ'=:|[ 36x]IRbdd###0M(MΚzj4d20 LOOҥK]׊dx%0P0zoip7CЙ^ê0c`ccHcxxT*x0f188?`Y;Qq]\pRbϞ={P.155P(իW//Q,q!Ń>3g΀l6~A>G>?S5NrWOzMH~+;VnڄoG, _~^y;]vÇ!#|cddGƍQV~>|!<ۇ ض`ʕr|2N> 0bO-:Q/z@o@B+Όp^ÚGgY V[b.^'a2y'^xELwy'yapp|Rt:+W"ò,޽\BB1yr9r9|֭[!"Bz_Qi3uq]=;ށ'~9Tvӫa NloH`k@^o+,%Uh 7"[톁w> ʶNeVA~;kAv&.]jqqw~|#(شi>cbb_q9⋾d4 \.73̢[R^ġExߏ~$~ _@VD7`𘜜DXy3[oŊgž={nd24|+_cpyoi_u+Y۶/'N@Tz {?W`\+9{( q߀333|2fff0v-HH8N@:}麎\p###ɖ=<I?~裏8qjΝÚ5k8tP["hЯ}m-㤅v\00H ATK%О@uQ.a À~~&ANJ2Q=z)g?Y ?~܏?+A+NVs%ݐ5Ia~7 ~RSwPVATlZ*/zcavv,ߏ;Įo ܽ{wKz/G- C('I0ƚ5T a Lepynev ZO4H :Q\Fyx}Hjh6!1f``?33(|3^x!Ċ+0<< ˲pE&%bddRJ\|sssMa`͚50 h|L{Ia/Yљs0?^O]ڿP,C9m`mn߾`&<Ο?~"b {p]7_011J)2 >a۶mÇ7_wRK' z{X\[@T™sp~>L?rS/bddk׮m:4K_'r{Ez!lڴ /6\r9@J EQ~DVCX-M ľ}m69T*Ne u6SzJٱxW1>2a,_b'É^ӧqa;/z:t+WJ)C:Ɔ `YNX,BQ!~;cŋ)ajEHp&|WoueGktcsA{qL*N/[^,˜Í0iƟyjgZ /'u]΢T*k4(( Ξ=Z d҈'fS>MU.bPEx0qvB2, ,ڵp-C^Q0=9^ :u^r?яu֦j5('x0cvv6O߈p7'0Գ4]j˗/?14MP(b7M?)'xrpiٳg_o~# ׷? =Yi%$P7mSSS2M?O}S2OSO=绮'ԩS8s_&@C4QdΠ`JB!RJB"Q~|' /KX`M`; \%z3 2\0:@xRbzhm`1$zc ".馶FX6v;q}1}~XQVtX}uWKR!"LB_?H E`) n >Z m&~Sp6xpIwa1x0ծ$C 0ܺW/LSJ!s9T2ƚ]һ@J)!zeRy- F?%̽v}\8޸ GIpw^U =~i)%pEqpBRJ]!UUrƘ+pcz,wݝQ[?%+>(ƂoX̽N w:\>>aU?y#_{)XrUUa>q(,¶m(#U^P~H$)w"O 0G!^;F "+-Xo?B.0(mۼX, EQ70H2JIUU(u]Ga>|xxLρ@nu&VFGU:yaF|d,[|k BX:pUUy*oRʠX;vL*ժ8 "$)=vP8P i lR^MMvy88W.\#}j% s> *jZ8jUUU;vI O 0(\4WaI)k kOQF?MڇJ( T7@a8%kvck?ylx%BHRR8綦i(7f z fVVUUU IUUӜ !Q }_RZU:$K.^yD,^T^+mbLKAK&1S/?<WI)s8eUqd2LLL#J'(rLQ !B4mb| b\z2j tPȤ`zz\O%$a롪0KX`Wk0KUXRH+5ϰ =JH0(5?]<), !hYJܳg0@ @bÆ n\&'}R J+~?n7vwBRِ&7 *{&ot ~,D<1 abyb0 1U ZyJ+Q nB1 JNI= }A'@:BPVA4%?$&f-Y_e+e}{ԟEGr)/EBJHkv7B @RB[HH)%`{jBsnafYqر!te(&R(DB,KUEhRq5JJ)Uzs!w^y5R!!R !Bڜssnj5'JCCCb||iAF@4 Z*8,Hm+*1s !cI)YDDQ%c>B!ě1s(⺮8hj5GUUdzl, 2]- Բ,lf(1ι9g2)%RR!Q%F o^aV16knT⺮oY,,;ܑ O4M8ue28S!I$TA@Y>y-椔Z&zUUyXٽPb`@Z1MT*.q !J)I6% h 3yvP(HB쨪*ETJnA@4B{ e%{ۊ"=N=6@ tc{fMccc׺ߔ4>>E6aO!S PW zwLlIENDB`Carla-2.1/resources/16x16/000077500000000000000000000000001364475620200152065ustar00rootroot00000000000000Carla-2.1/resources/16x16/application-exit.svgz000066400000000000000000000150771364475620200214050ustar00rootroot00000000000000|[oIre7qHh -l]lIR$AR#i~+ŖZ3`ח_Dedg]~o~\^]^?'g~_{ϯG7˓7oG˽?|zx{8]pq yԞ_?=9~lwr|<[]\~~ܺW?./޾8%ϯ0|uj݌y/c'*"2 =?}8E2"mz=p60Icֹ[5ﮎ%/o׿6 ܜ̆YnFxy}ƫГ7C2poܴӓg<?!cΛdvҮ`ᛋÓOOÿ,N_^c<[ \apov9X~8z.\7ɠF<݂W7NϖU󁻫dهw <u'CN0mmؚ wI!4R+;k۝FGK6Uߵ,})K+R#*VhG+e+X*N_Ry^v݆o9WQܚP1Lq@)$oW پ2M_,Ͱzy_u?vu}9 E}g^_[(o=:G(FH_;:(`!NW"a,OZX?;jn#"8"_t (}B%"?Юth7yE+aKP*q@LSJDַ8`x% vڎHճU 'ߖM{4d,Zʌ %vlPHo=gԯgþ, H:,vZPN"Zѻӣ}[U:ӣ+RF5|32w1CP "\V+]lLs ݠ0v9sGH/ b d%$#2MFd5ΫG(jlԹEh[V@XOb|6}ɦpg佛>)w6}ײI8zGPdtL '-/o[3>F@7(S?t'\D|*Bђ$j:| Gu!=BI;(Rkw # -ºIqÀCΏZ(M GF,B;.7qI"\?9y_*uO!e]74=6"~:|}suxSrbn@ӫw's/N{+m .^?U [ w@J6p) <K[X $FiLHI`52 x 0AkY:XRr߂*B#ܐ/.%nuT[  X+dĨ`BdV9W 1DlZ@ЅLbQH!(rLLLp-*k*lw []Ѱ[o:`Rx!QBE9"FtL pƂLc!kn!nj+Lc誁dUFRO%ZpdR(,R-F6b+8pp\*ZA@IZA]}0r !R+{z5}|%ox|uO<| $ וk&0C_mRBQa^pXRtX21.\&,ʆ27HB=wX&PR,ŧA#t`\f򊐮bl NI[#Q`ABB1/uPIP-bYm!9a&ޓBXNYjEa-Oz]P(chꍃ9j4b밂@)WQE-s#/ h?=[4l Lt'fO EUs si%BGho~WT~nJw]]gGulʵwmW|{y]oe?a?݄eѮTFn/\ۦ˾?=dVOtX1x)MZ:>En>7X p-҆~.,ݳn.oNn)FbmF/zR?>~.ˋwWi[n|vU}?o5t+ІZNFῷUnu̿W% ]/Fw/ϞG}=n.^,Wg~n[D'%͘M[^f @"u4 b5aج[a͵1fz,z̾7h*!,ꢺ lӘfDRL!j aN~ 52Gԕua2K)(sB2bD<`M8 ,|,zĴ4`e4+## j80 YD5c/9]bXC!DRQ3"PӭbL#ʣ;k z̆R b -d_L~&?|N޶\ vzU?"-'m,8˘f^'H']KYIJAHzW_9ȸjŜ6٭SFenX_hpd|ڔf؋9x>MY#gۯ}O]OlNn9K, cjBTfhB2zOW-6Ek~4 GMg)`Yt {Y/ ׉:ACy,ZʬufD#KE GY&XG%$*$2f6j$ b8^DTXS{_ ϟYPCzei@aTt6p:uTz]ŀQ)8hfAiuvx?ӄvyݣv7L9eo77m-X6pZtAm&d Hh` үTH'[NK h[g-ͩyOIfə diOTg#1gz`uwMp֔Ѥ:&9Ud$A@t]?S{BM p'a\ ?ВT J,h+%E KM]>A P;&RTAM'PFuD+Ƒ~I$;W;q{F f69>' XW6=Uo쵑Y)9&Ԋ[qu=SvWX5lw)^͂ 6v}5Z4h[>Je?uQɎłC(Z,|X^-,y}9@ ! ) &X z['+(HA>=cxizδOGM\KT$0W}qمgsR[W(BPW 5{Pg[Z !E K ElEV?產C%MOY8MD]ΛAxY}s)RJ+ٜqO󼁍$έR#rFMS1[nI XmrJ E%_ݬܦOBN=i&7F|ՀIiϕ %n [8!xuQThs,G=|G@C*77z_&JI|lJuT[ڜ4 ɯʨ=wW~_QxCCarla-2.1/resources/16x16/arrow-right.svgz000066400000000000000000000121321364475620200203650ustar00rootroot00000000000000]ms_~Y׉PZ;$6}LV"*K~CJ!"$ST3a9xnpėb]O/_aAsy6_yu?nxt1l^]N~_p͛>]5W''>|Kbޜ 7 Yђ:M8;͇fۏ沌ugwnfIsѼk.'pcмzz3;[ls6dn"eBw?:!fy~ۚ于EF֮J+w5%\'e.Ora<tspռkFg-0͊D|ۜy;ǯzxQujUӳף<쓷wx|9FpV;_[ʓhW|89hV卧.园WyO+ /:/q-WUY/[v8][:FNhcg=HA0gHVad8  #Cp0r҃FN逶Cq<~<څ;aq1g'\( |ij<>DQ">żbh.b[ݯ$NWG)1Ց JNw,;lty^Nj~S<\JT%)Ie/J`]L[N&Lޢ HGfKԕLv^"n`)j"`u۳zw VgrbJ xxh$xȷ]M鮶2OiwܻgF`6@XvHX4le@1Z"쎹-?Xrèwbɷa D1&+dQUAΰ#lËD8 >CJogM~o=TͩË^0(iK q0N&O@$+>ꐅPLCR9N?`@@I'ΊO3q &ԤAi'GLQFM*hH_y QiUcVJ_7kb'LQ2+MW(_n€7! hS:RG9F DZ@Iųˆimר'lK0 Y~:~9#g4guw=/F_F?[SB=tbo9ې(Sd)WȌ E#9'2?@$Nbc`ʼn@Y2-_Yd~yoUĴCxf27y13o?ӛwW˪-|8X chp;B y< Uen]3GQ; #Ǔww>ta0z=i,ge>ՠ~ڿ1{yU矮Lu{[p~O.{w^|AR"f.PmVI~- e)K( Uf0{AJ"[K#̙<&[4-Jcǀ 1'ˌN4RqN/s$Y\X 2]LH#w#0 `j\Hneچt1Gg,A,d.ր㢣m[Gq9rSu؝P=hqX`Id6jq2U%mu Sl `[X5<U@C4"I)8$K2@vDȋ/NƭRb*bLUxE9K%w?[ dssz9lO߲X\n.}s969N9raK*esf>_}z~y _38o6eO;>C[RˍN&}Ӳih84hO瞢K((qeB ]hQ0L4/7Zbk$#`QGԠTD4@r1GE]V{ 1d-rVnyw-%3Gb*`8`K"WAm, bB"I᜖4Uhd;vfx`zx`lfx`؅[c$F];gJ.'ikKG(R qST z,Ff#@ $0M@X=^)o f dgjmnf5c7\إ.aW>ǖ viJWv)SRA(E .E|12MUk֗c66Z,$56ܱ6րM=z`Զmf3&b dXǴЭ>8Y|lbJy7@zP)& j0蕃#+=c`iFh)HLbuq588V bW&!EOxpHFhsWn4/J*icx`EJ `LҀhQ)9ZG+*2F*ct}@(%nJ/U=O) 'l35%++QBSOtTL ʼn@SYY ATҟ P۔ʼnr#ŘtKJE9@zQGU d P)D/jIp`aB*τ=bbPZ[ ( '%RdJm1z`Y@m(Ȁ= Bp1H҄D2hn1ʦB4Mо_7onHCarla-2.1/resources/16x16/bookmarks.svgz000066400000000000000000000251241364475620200201150ustar00rootroot00000000000000}sȑ+p+Y|gj=c/w)q-:?d1ȷ7NdPڿvmo..y趗Wgy#ܞ\~?~ߎޞnϺ/ntm7_bG,Wׯ_vGGț^]u7.yc)'gWnջ?}j/qgw~vz}}9Sӑ4m?ͻ˛ y=.{jLzO'C Zqm|׫o{ ô{:e'ק~\no￿xT6{m5yyn{t{snF޾^~s;~8E>l_ӿZhk^6gWߞ}7=wgˣ.oF>>9ovQF^]_oJɮ>ܾp@\F! ۸;ۏﯮo/nَ\OⲗUf'߾=׫7xzo{ߜmoqPQ~vԛO.zJڞm~kF^#wRH^mou}tzկl[o.n?EjD/gY/f6[xN{|=@ӮL S֜f/{t:`?u>ޖc٘dqP1eH[ ֹ< i`?(~݀IFą.x=O7/>#Fg~Oϕ*Fgͅ=r>1cx~~Zb$\#g{gңĘO#ŘOSĸ.(csz~N)=Pw}zo|eq}o^9Zf|J29{*`2ȊKq>3w߼xwr{}u#Epv˗s?:qڗBOA-RG:%&}tVŸk(`ܣ}<Ƹw 賒A}k kݷ-U_B՟Pk2*/Oj|~>07O۷o~oXMHJs`))?Ta톥'd?VbuZy?9P2 ʚV@xQ=j$aF{i*^C\z9ݽNˍ`S?/y0&v 6 CyjYPבڃa^A4yE Q$Jr_b}C'>??NcwS_L }|0R;)!Q/z{O{T1oF=]z_}Ŵڍr1K>luZ_P. Y |Vff%Y1Z'ֻ=ȥ!O.wmi(FDX\BzYr4}oo &V @16g/~*NW !~GSOʿ\T{'CU*\q'sn,?Yhwy H O%$:Z(ΔIQjF3/~]0PC#~gw(:; oL r 3Y'!#e -1pbNU9uϣ4i8"SOLիȊʁ*^f%vRj<_Ԓ0g, F4*mD'w4"Vaj1)P2{NJ0Plj!i Gp|e|EU~>-hۣWj6QF{|^>JdQA~^ÙF^\\z)/@˳A%LWJP E*TiĬ 5Rk3oj׵3٪0RWX%j 7nd .ⳋC'pPl qFQ+"c3;'o׏jX8ɇC]ZTEB@SLax$_fI 5>$%}5_ZX sxXo!My}=߼[}s?f\sǑ@= M݁_-qBP˘+J!g4'g9ܜЋ9ʁ9s z9anL+_&x87 ~|)uO~ 94ոX`^ROQęb{XBEC,'.tt#^O0˯_٬lDBhDS[yY9 J|dd%XFyv%.q>E>Z |κ~au?c 6z A 3Se@A w,2\8JUېQbMbbUU7!Y"2 b?c yW\5!_wdi_Oi6//}w~oOu"meeG~c9p$#S͛__n?lG䕣Wưp)i3'IN!4֜iNݾ{:Six'ݥ6h{f٫6WclOo>hcv|gҕOn{7ݬNXF s\?@m]1'vtÌWپ>xY۷߼SZhK{vgg{ L6TߟܾYgJ_-_ lWGn_]^]_QW@:I92 |/lJ^?xO;;ɧٴImM# _ )Jpz;ߡVX3†0 t\ l( I?Eh@h*읔pfF3Q,WaԍD1D*KC)Qss6'z!63 0hGg~\" aVN=JA.rX*@Jr@6"@хv"A2E[kTa5+|Xvkm1kÀĩ˙*IM\{ &^9s&E]16L%s+*JHjMA3(sOӰzeM"0RRD)QS n0HZf i3nHWJ3MORje'3{wfWAAv~X$I.R`j$4[pn8pΥpp祊iJ j.Uha)JaX0c10nXـnV${ZC0@->8^d%E+l$D5Ol(6X W瞉 jI=`Ihbj.lm O Z4Å ў&XhؓzvdEQ5z mB1$N&6 b$ И7~hRi#͙.V E78$iHA"Q5 iVX&W#9X7D`Cc,$EZ*T-8Q4I SZ*ݍ bHYA'$EǺWQ35j s)6YE˸(nF;Ya! ֨֠t CfC*wä]1J=-C.2*J8Kxau7j!WdlB"v Tuq꘎jf)/"=J.0nPX3 v2hខF݈%*Eu})7aȥRAƵB85]˰/>"BshO# BVU"Mqbf.Q*jFrBMZ+)aն)su`86鶨Ҡ6}!";YS1Z۱(nQ*gɭD2mJ;$sXr.R(Nlͻ$,x3ci@cBʀ"iQd7n zK)HA Z(Q#a_[Kdz>Nl4d/KGꠜY`m#/P`TN`0gMxbbEZ7gbk Ɛ JB 0%1TU]MLtN_-i #<8 /VpXF.5ᓷ75D+R*I漻qV^\)6 20!W,=#%Ìsg䕕`^jU0T~VL HSTΖ"uyP5Y#/XbcXÏ |vGꅜ9k$&F4VfeBkS!2BT5;ւ"n؞hn(57G΅xwS,=1r6! (8CerJ5dz{9sxObA P 6s6r~/V_VDBL5Lx6Z$/\ pB,5˛E۵ F"4ˌ$7ȇxq*8r5HE B*T|*J!*@EJ]Td P5@(~$i$qP%R^*TYSNkp )S`!b%p%Sl L+` .[)SL0E` -\)ppbk`)Sp L`Jb ̡((P @)RBK(VZRhJ(֠\Rt`"%V8R bK(X@)uJ (K,) J9X@)I(YR S(EP XR` s(J@)IZ@)I\RJU(PJ]@)JIq-YRJIB) @ )Rb H+@ ,XRŗ@J]RpHC /[Rh "+@ /^RxHC ΀v( 4Y(8Q8 4CQK J](Qh b3E/@DV@]( (QD5V@:(|臇 ˳|+ D*J[LƢB7uPr@{5T)=ZOX*v>Ӡ5(0BRӬrG>w~gBqMWzY0F2<\XODYjuUyVPq4:iH%1vHLi$ij#@iŴbjV2\y{3>Oc+9@ y+HgIE"%)fUxLRZ.c*dF Vi>xE$8*U{u44= yҀ0uc]FXJ#2AH (M:`QoХg`@9챌ˤ6 ZZf,IaY R@`ViZQcQUtVb{#4DqX ǞW̆:m%vѹ p=&AxN!xfz-P ꈁ`YO(Ձ'xEGŬOI>r8YT@#4F#l%=*ELx CqAѪ=`]Yv7mn̻bh$hkj@ m4U:86oDz7F}@j4`kDhlhQ5,im\Ͼ(6.9m壚 {ZII ''o__D(c9<5ugmbګ9v~MN\h@t.n&tg;>P7vw8zh#-nu|+ [R*M;:N_y^$_R_R_R_R_R_RT',/*}}s}~Kx ~)')'\N.[ҎװZh= @ԗ6ƟxSveE_5:DiuDTWDTW4tO# < 8L+p&VW-ƤB 8)a;-2^#Ƥ|VIq&͌'Ek+(hӗ˦oA8٤ReLK+ A*L jhH:}IOYVuU#I \h4%7_sz7'JHc)| ׼8}X=$/i\Ի; ;IG^/N{enbbF;Mp,qFS;S-,z4}MѕlJroҝo>Lw><:;Μ] ˜|s>/z03V(=>VY7qVjPZ`¨}҂kƮAa_ ظ#ȪLU"!iCh;ީ U߰7lۯnUR [rܥ@ԓU#IڮDsXaEӗ'a l^(ZQ~qm 2h/2zrvЌLI[ad'i^*9KBR{-u) ta"wQLޏjI hP[_bIRI4vOސ@bQIX5IsFErf䂉Ri߷lu2:Mܡa*f&@}{ ]S.D3NnhRVю4@{ 3#܍ͪ_ hU}5[HEQሖ2`ҍ,{-dTI㽾d:vA{GOcf=l)h^n$UImv6KZU{Y@t/7Z'U͵-ƫb$ ɕt;4ޜ=;׏l2\o3tC@Tz-ZP(LOP4]]^_Go{g C_Y-`")RD bQ/EЯ$Nb^AFL^] YV#Bxu_oVmt[j4=l(f A6l d3f*UIÕFՊT^;ehޔB<@J|XcS~wtHss\ cSg:ƶ48ӺfalƦal:7MalƦ ce^;e c0697>[޺[g[|7 ;qNb#9W$IC^liDSKr-=R&HU:a=oy&3WJ.]JQe/e -[Qή%kFڪS&nSgbZ&/U!0oS84,eXA[蜍 %>^9'mRiNR ҳ܆ V[=S$iW,Bir-$8GdQ'8hӝN mRr+\Rkq MD1zӅ(E'?lvoH(6恴A&:h%qDeCPȩq&f"+*|x|˹]/g6'e"b:<_~m\^(u!q;08 ǀ~ 1ǀ~ 1ǀ~ڹ\;}%{`1ـ랕㿷{FyO@陋 m?(ikAk +kA~Su_yW7;(= 8o༁ۋ9o}&@z{қݒ< Ho }ODDD!5xZrTOqĄsEPd@EP]y؏ط-LGN (ʠ(|e Hꜟ>>222211766:99988888:::>>>000;;;C88;;;+++.**/**622955844855666>>>888%%%($$556333<<<<<<777<<<:::;J_9Po%-9PP{{U..;;;MMMNNNPPPAAAMa[ +8ssьx??@@@aaa]]]LLL>>???;H[7Kf4ARGtRNS- pHYs@IDATc`L,l쬬@.999yE%eUn!HD^, !穩  KHA` XK\"mኈ։OXhi6#3+;'7/:⒒R Y#'$0IENDB`Carla-2.1/resources/16x16/carla.png000066400000000000000000000012671364475620200170040ustar00rootroot00000000000000PNG  IHDR(-SkPLTE>>>222211766:99988888:::>>>000;;;C88;;;+++.**/**622955844855666>>>888%%%($$556333<<<<<<777<<<:::;J_9Po%-9PP{{U..;;;MMMNNNPPPAAAMa[ +8ssьx??@@@aaa]]]LLL>>???;H[7Kf4ARGtRNS- pHYs@IDATc`L,l쬬@.999yE%eUn!HD^, !穩  KHA` XK\"mኈ։OXhi6#3+;'7/:⒒R Y#'$0IENDB`Carla-2.1/resources/16x16/configure.svgz000066400000000000000000000403301364475620200201020ustar00rootroot00000000000000Ks9+t pg;{ؘv'8bVL*H-ϯ_-,-p$*U"Tzf^cfv9^޼>r5M'7Y|6?_Fgh&fzzfZ^Nn?]n_>|Hix3l4*g.{󧳳v|5|}~/~q^]3[-ǘp|܈_ʯk.g[‹U 0"@cQ-?VQ2]˱~Rn Br玴_\6W&͚oju;z;wd6y,o'r=mqǷb2Fև>_vh{sL,˸o`1OſWoǓUU}*&w5}GsjfFSlAZ^{vXoј˛xi匛?ooFv;{w/GR hWB;RwZa4ǨrHGj}1*WH*^ #izI3UBZ[eUW!Y~lXL;T.},nAerlDHT$Fڛˑ3VrcAs Z -{ ֪@e\ Tv:,-󱠲S(H{ctZ\s(|+.~[uԛAz `ߪ-c5RImrZ`r7+ڎSд Z,,U֛QH)IQ).P3j>?bH8̅wZD84[Ȇg]i ܂ ؕ~/Rp#PcHkEb Yv:;#ѻ^`|SEP U!1W%PqRSEYaZc!sׯ)1푸w+cmQąж}LPu*iЊJ.|K44^N`GLNN`O^Mczڼ?P[o>_7ΉJ;s*vX6kƇdnMu)ɢ;#:"A  Xhw9?&$_%sTtQۍ a<)^1PBU@Dm;amGSBY:>KaуPvD%j-j-kq@N~`܃օ\~G-w_\;04ٖg^]4ٮ [w:^/+~]6e|d{lͧ[-Y2SQ7´%\#Kdn۲*dG?tTAk|N,xK H5!g5>؟6^0^1wgN}xlXo%xzs栎Ic$k<@}2rQVшֻ.lԦ4Uɩtr.V\6F ,PK0Kc"-K%6=M[GD9Gl۔d&4HΌhWJw]%w-E3oz;/-wF$w{߀)|?Wmܤa.!t֏̐= >\Ή% 9up"hx9k~^OÖaidYtH_1mȘJƨOg5n2Kf qEnHs7_E 'q.B 0Ҿ|bNތg7OҏYgM (%1 yݧŐ Ð㊞ Hyi$rkDD>`T2Ȁ gN#>.>'w2dF^?uZ y)JCF^?}Fd4`gNęhȥ~4!:`ӧ6`#】렑ׯ&íꇖ_URկ"엪~aT_vh:ܪ~h:ܪ~h:ܪ~h:ܪ~hRկZU?4{ UC~ Ȩ9>H9̷!bM[pNYhLOQ﹪ eNt(/xZ$ 5/F)0{wr wRO;qNҝ0ҝRsbRZRZR\}l/9v v v[a!D|;ݼB#r:Pr, QNY=[ j3YZ(s̜zh\j9'Lvsͼ@0)4'@ᆖn-Q;jBegr9b |c,_?BA.. 3VP!FEF>#hC jx TFnaU\ywZ #P%QouTxfa.Xd^?+سF~~vUe.Y.OլüƑCEO#|md1Oͅ8q+#WO-ɒuzJd[,|Z=Fnȍ%YF5"L0ζu| 0r|ɳulsvNco'9ظ<`9jf:y׺Ngusɳ#n'gǙ6"pyb]'S;mO:y^n2N46=J[lƾ1l͕ m@yUjD;Yid<ΏZ]lZD<6a`Vj/E.mtw4H]6gr]zPpU&.5<ao>[=|];gf^ i`A)^MaY]ڟ>(VۏQ#.&ĪfUr'{. fI! ZK`J˴܄=%Q봞쳰(tT\ȃiŝ} "ìĚk+~,ryӠ.6d-lm)_6nkߠe^ݐwp?ͫ4mksHƺ搶٤m9ʯ!?s!amZK(kmY`f^l\;s_9)kX,6\)$ea*,I_l rim:QEra6j떉7iȧX/1/V%X ϶ q_-+`auKOPja"a&B?5FaXyȇ۴~*yW,|Z?uK^ #OKޒ"i4ԅc`I툕Ƒ #q #WOq-˃F>}agC W?' Bdw /ܼbK*}?'9dI 2;~-;8B.{w bn 38^zA0 *ll 4ߌ.#7X(TrSqӊq_mqzAPis>"N;2vLqr K}v#Fȕ2#]F^Ql"WG^Y VO'8| ?U=T2Tkku-< p|Z=H5N,JUѽ0qo?zZh,E-2ZHsNʐYԗfPX'|)*eKEPDPK x&R VXOwv[Aj[h$-9%+?"XL.umI8)EqisKrj&hFŷv/ÂRq.ۚڈ=$D9 #f?R&P=FY7 q\܏f4Y`LLV*f+ֵKdZp/J/u"sZdX1BwHͩ˽tF{{I}XvQ[Y'΃*hwϬ[C*6 0#m;9w/Z4RRO]wj^ _\I$gx,+ mɔ?d⹽ a_E3VCDkZ~jVU.tNaҟC'ՋǖKqt+kOmHsk7o[&Tԥ{N)z&N."(]4!XUvnv|q{؎ DwkjDhK7/>'n[Ǒ߿ʄ $~l?v8b~ IxAQwWVp(g8י]UʮzozT9鼚o3t<^=Xϣ?D\[WN2 w˯v0>fj_nG՟?6|gǮGcq[I89mG0C b*! E>T=\ZK.2r_J_M#qٮ'gyzzC!NOU=XUs~z~٫tg?9~zO¥H_SEy$??JJ9|J_z_:6*. [پ?{w;<4?_]P5NO< !QV~qJ DXJĞEiOr(4~IOѤz&aaϴ TOtBBt0}yT t";TPd@$qiAX ܘ\57)IF;vwq+)vyfNǵ @PF1j r$gNP~<Drh +?{Jg|zO,B6ГdqlՂЍ 9ww,FyPh`~vM<8 E~Y I@ %A &\#- i~P}b9U8Fz^ ?:eR$),q)ѸT a6QE@\s&宀byP;Ѵ}V:I o=l*Ċ(H]r&#Q t9h M )s=ܤgےXc$T"2@[I!(hfwˣ@G%8*m޷];dD݋wg\^ ;3T1Q ОظP0{0;4r9j~mz{MkRspHnBk#2` C * Qs(GD |`R> KIg]#q wDL4ųG&!GŽy%7x8AFe)(b8j`PJ{rœCq I%AR~58(eTqv="sNAZ$4X5)7E!4idrIMΨ:qO.4TZ26XV ><Ӆ=\ʭ QRo%=T`l23?׌(`Hrtz)dÛ\Ԝu\VB%n_I3̈>˼apd6`Th Rr$9. SA3?ǢY+*ZւyM)K Hq2@fd)< YycLEiG(WnLϣzY,53h.O4FZKX^}yB1UFUK7dD @r =.y}}so6~ŇoGo|b^~;~xm_}Ittlݨ,4'6΁)zoDhS~ճ/?3 yaVv/_<]- xӟ}Eio6p۫w޾$7Ͼ͇N}j:}޿zB>~t7?N __ bzy_ |{jwow!ஷض~ݛ٫f^6w_%ϡRw?,%d5~|ߞyTUyׄDgڎz]E}V||ճ﮿qLo^W'z&BUUq[[mG뻗w#v+W?^>۷ [ڏZxm.~N}oώsC "!yCH~$.k'Gm=}aaɥDxB$W̩fԸd!)CVWydeHͺ“qOYy6*}1$$n+$ҬK+0]T1Ud]e9%G8Z)2sQ3u [šJ7+Vmftj,?j&,4%^b*xڣu4uĚ7% eh*iCͽ))U]QYG,)~ʽk %Ic(a;) t@%\XPjcU\A \a&5Sδh`[_q%0|7jh͔x%@gdCI4BL BJTW)7#/ 3 ,9v:(D]eDPb޶ 7 =lf1)'ZL&JCۉq)P|u҈dQWޑhqiqI}/6MWڦ/OM ?;p\"HB|%c}7U۷1Y.?N]`0 EZ^Ĥ}rH gs]@_o=,omi窈9|KUJGNCʙ#uBg̶Ո`z>w"tS.B,|Aқ\rxq`V'$r!E!֩4‡ iy C g*Lnbw}2&ĝl2 ,*O,N5H@ )׻Hy s)l.#FqQҩ梜Uwt٠K"~(u۱I6d)҆F{bISUS=b*5UfNh,1Mi;/[gKjp5燜'Uj[-'{ qأO/>R]=~|F&8y*jB5* e u)`9 KDGҎGP˜ ȹ*}] 3Z,KNӟAdӻi7%Īf,Sw;(QG-VQ,m涨2ťꮰhz4ڑh6bLUStAjΓQP]BæzԷYQ(t\I@Te- I$ 3:ٱf*3Uj?15rǜJ$KbƗX\dkihcN I3N@#2RLQ:" VID'tx=^[n)uΛ|g50I/S`0 Ԟj )W'qti6uf1Hi3F Enh7 ůpu9"La$kkHLzlRɜRdu9e/5*7',IB/){= Kj㯨B;XMdDJr7P_\T *4j=d{6Q]4e\.Xb7 IyACDԝ)䬚2 oFY%V,fي-*i"L>~ 1-]零S|MNL%w^8ƛ!E,t1C*T&G߱fZC Cz}"8ŞXeJ̬&,TCO 8i%FS|()KKz. t5ٳEc#v Sm5Elˆ ц!nkjS9@1& CI ʼ-Dt֠1Q5(WB4yBgOIN0l_b(wę*Mѳ #8',PwSĊ@-PY&ԴXXI1LMk]Ms.CQTJWy&gŬ(!AxX  JAa0FDfͤʫ#r#4Q {&oT(R + 2iFnݤ{0RdgJk)q]Hs$E-ڙbT؉wHMS7V7K49be7sT3Y쌔soubUʼnE}Zru 3zEYzis ldXtkYOWs %`Dh̊ )WMFln9@I,e-Rj I\}r08h0"MJ'sR' Lw+$!J7Wb1 6]c}B]S=]30ʏE"Χ0ƶҮi+&m%drs6ѽ S?Qz:{D2o(RȞbu. A;| dzEbvb"ܹh3eo} :\>tw$S]*tهH.}WTF Wpzu.p]LL<WC2S[S>:kh SCl+5 }Y.?N>s\]F֝8{1( ~ڋmDŽKLƝqS}El.z^3NH5_o~}Zu{W MREמ󪿿F_{6ڙܴ 8[/FHMt>3+{S?9xLݭ4g6LZ:uM͐eKOV R38\NmZ#p@SG/b*p9U %*~8ٟOB͙g-G0Qm%n12o_t!ֻ^!eZ{QHI^f$:h4O;] F׼_!Ʊw߿m/RYpQfLԍYBǢ7Q'><vgI0:̨l`V-h1k"vVC &Bv23т txUUG(gcXvpHKiz;c I@I덿_6K8$nS$:;vSEkѢ.;(K;t wEJ'F"DZgXsV*WKI\ViD̖@қBt3.l|8YlLM-'S0ꇱU L:C=X+,rXxD>Y'Ӕ)zeQa/ɮS})zi9'׺>1pu|YaYaYaYaYaYaYaYaYa?TY:Ν o:i2Oo;1!$tTў-)u$UTME,yڌw:[7Ԏ[Gcy<#Fbs SyvY4+dVd@S*|b+J.^#x>o|˹NjΛ$ ƵK#kv-~m]_>[ܬ͘z vT(Q{]P9ݫ4Svҿ|hhNfC8I7%bd;[+/f|F?_z賰c8Ld_A(EXVWEiٕb *XVgf眹˚XP]R[սaգ@-qX MNeqJNfL׼aԁP.9H%kbI[$9C}*CV{ge BDeBua帞ΖqMliǜngASE^~mw6bH-/]G!iks xJr+XVJl8Pb9qz9g9n<+P}q?}׿E'O~cRyPA|.vy gMKt5g}.("Z9hWNw1FzTh5&[L;2;Od}$UQeʳ;qXbZMYKeӿ?߷}"}՚fR23NE0s-6S:Vrr`|=2ӝuNjwVhoy?^Zs>־BG>bdz;ُ_i6&Q,5uQ`7E=yg鋥3WAlEwoț50!pMB֊ehVvjQ7mbhŢ ̶vTph D& IF1 kCGfY,zP Gl yL"9zM>_l9Carla-2.1/resources/16x16/dialog-cancel.svgz000066400000000000000000000356471364475620200206220ustar00rootroot00000000000000[o9Wx/]̣sԴ{1yX Ӎ}\L[۲dH=~#ҒPegrn6 yoW?on/^ɫ'.|uy}~}ru}/?Y>^ܽ{W=[}X?~.=.oիWثn_܇?Sy}v6N} ᧛mN?{ qnַ?ݜ}y!o7](@TUȧ.rL]nvEeD<=l ˎ|ݧһru\OכK'<@V׷Vg>Pqzwﺟ۟o=8}eXk~փԀίg{}r~)l} r݇Kr]36WaOo߯OW?_z3 ?sfuL|v}uzw_Ot.Wo.ק.wWO%n]ăOnt:=__ߝr뛿v?7'8~tWo׽RNpxcu1Hݿ}^ɫӯyz_=ξ{x(k돝S%xqu~qPBdw:|ݪ wݼl@.?]/7=usq>}$zv|wɣUyf 7g{~_~v1֭/k뛁Q+=' ޶޳{[x}z]^{oY`ˏϷI JQ'ǚs{+s-g[1fs{`(!e]f#+Y=Cƽ:;~E!* ;H} 9QNJqը !8j%.`b mTn<&,n+i1IGt{jLҢr<%Yj`QLf*L<|-xdmL4Ij*Ld-ҎMcBY?ٛΝO)}5v 5ˑ"Us1 ;Ĉ)F/ I=Il~.;RSu6SS)7UXӖ(#ۿif2Bg9bw1"Q7;f]cn`y4X_4ŲGYWF블iM3-ZF㌲#]2kphpѬp̬obԣ1JL#1F.cmZOȅta2F2ƨ<כ}.*9s ahw>wpd PvaΔ 㻛[x_.n7AX_n׿nQ_}(Ww7~PJAi/"Z?](bGLA`ѣͮ>dG>F(c{. D=:HŒ(uQ [<mhl(MQH-W@㌬h )PXnH刊%848Z^aX:yo̎qc팂o`11ZCHɄn1Hp5a!B|9nF575bxT<5*&37q #&$1j``'VdDDBRz6Y U Jyg3WI0l2<NGJeZ_ x(/XcupVz il2`XZAlg ^D&Y._ܝ/[{EhXhX`6݁6KHj-5վ[P`T T,R 6BO*U l[SjmJm*5!(iHQ9.қΧ _/ J9sT &uddnj"X0*h6rTRTѝrMp:{m1^ X dc )Yw>& {#wyj۸fyq50P jcLkjYIMB,ܪw-BU7; Dy:*$2b\[ѭDI"^3yx.no'$L>8D.9N*Mkn R4^1jDYrݻ*F+s6KB(As4ɧ `# -~Egi& (pk~AQqb Sy)t !E5s$ ~+9вYfy,J@w$$h)gҸ1fozK(bAK:O̭ʒA 7pu(eQ H`3H`Pjk-m$0BY0%\/ W Bfd 6(˪U z ),[$M\*hCcЏ#VG; ՚Մ\D,=K"[7kBVU`ExWX)IYZP4B`B﮿\ݭoT1@LM:&. YjqiE*y&W`, lc<`DZ>[P6JbSR@ޖg"֖BhjȖa̿rrǘh fO5Ẅ́"1TPs+D~vfZ_M=6)=Vԁ~%h 'HPQ 9/$د_ƟiI.f=P %TXr,PSz6Eg3)# l *ɀ:0g(m{Ɇ=GB"Dm+u0MG„H2:e3e)k1R"!c!U:0XdY204+23 0;ojf Ri/hly5SFws?ИԸzLv6iL翚c@658mՐ1:l `^;VBFvR^Mbػz~vV|+Vl{5sGY@#EQ;eC]+:Z#uwGգFm(hbr0ٽlH 2Dž X&",qX4y1UF9]k8iyHXԖs`Ki"F"-&S[E]5W6Ocd򃭼Bd+YXH8erWΗd0ZOިN~P<.-$3߷|]4DDe, i,$2N%s#$/FIHI&y|j$#3&.% |ey{;Fގz`6_Dbo1B/LƋh^k &lM|fd֧*78%W"Y)@#䎜4$jIIx笋78g]\p:>峅*)pJ'ǰ{Jqlu뮢!ԊQ&Gߏs=ב9fs6A~ޏ8|{?6kLdIKd:JhK.mV9x#{dv̩E< 1ugB4ΈxM1w٩-x}Rcn1þ><e5[u ao06ۖa,6H²*70c2|L1Έx1ܶydl`uD=1bQFVGR[v^2m;o^:}4^e&m2y9Sa\O Jr紕ϑî^<52X9d/G~NyL%YˑO%#?'n<^<r災lϗ#?Gw/G~:ruq#?۴^rZcsDLՔih-c6Z j|*F&CRFY牭I"Y#1cF|`9jJJ*zۆ&x vZa.byO+ L3Y`*8)?Tߒ X}ܪIFkU< $=up޹ yZb[6@@sx^O_|ZQ΄C,lf_#Rӿc ZnP>V#.+>?P}'T#H6 Y2rPe6P^Ԁ_1sbjƨRfUz*ccd?*6-RئVr5=rZ[Kٶ뵵t#B44m;kV+mۯaGmOU:4Xm-wb=w1Q %& /IDfGPMRjc`M2-D7Y@`"o%d/{.0rdžnVN|dRqH+ưs侨EN;R`w7C7FsJnw??Dl*⣄䘮 $b@u- IB),9 : Yȷ,Uv EHl'D'BZřt>fQJGp/p\`utZ2} V,#?GURd1{u1%4AVG59D/^᮹!]2X"ȉ+ KZ$0!5xNJvT!/T.(վFIi'!M}"?~͢@c_2!xn6o hߛYǃC`Q`xԴD'ctNtkZ"v.]J5L`"O3riNa2>LbJ+lGN`cE:98iuB`$4k@ Dhhڐ @IiR4GFiV;\mGV3˗k.1՗^!@v@#U@ܩ( Swg?~gS,P}z@]*dX<9 LKXۂ}p* 79TH!hO!)h*y}*ͻ߼1[b/?ݾgW}ϛy_?49{?-h-Ezzff^D%l hn@hծ0#a?g SӂչJ7M2Œ[2ȥٴ@RX[ۓ eR-YOoo^/:˦$Vr^%Nm{rw{}j߭Wzq5F6ȔN/?8܎gSonxaBb9"Vl&0UID cM`IM.Ml7Gh܁ùxl#1'הl[zVl=i:{Nkgڦ0k X~1Fje3iQG;>aQ'OK&$)ŵ>Qŋ+S'J|{6QR0wF¹6n.]zv`ֈ@g"UU$TKtFÖ́L:p Td |@(d6q; GBIT# 9aXMGR;_ּ[(ϹqXrRI]Ԅ9ĭ`e' UU_ic1"ݠJҗh Șnjhάx.yל9շY狘DgIVi;r-镚*ӋwၱcHkDIs? PKhG|3#dP0M;@X7PMI(o{dcF6T293ڑ8eZ2?+J:S 'WPqJCvq5X_6²elKrWşGG~+#;d3Lc@6aBk n@r @A/63*WJlW[%6@a~~;%9r=^ZS Jt;=TWWZ9>ښ-ϳV?!zXVVOMUBLPBxh[4$ɹP@QLg2( l0Ky l Jl@> [^Nj'(Aϩw_ax=}6H|mɥOhS(cELxEbqELrELvESmTC yXB~FRDi}}1ˈ[*B+, ^usT;ca~Izo',NlJGAqHwP 7,9cp)B'Z , I#kPUfUITF u MUB~д_%4+7nig{c*-hEG'V0< 9R.;e;)ɗjv|?޿{&͇77m,3y@x'ȗNbf;_Ì8sC%z5%'8 *@}w'Kʮ]Rlrb7{~`rITv@eD *,D'dD)yI3_)X )^Oٴ%R7?%sw&y*Q`Pn"CԓMi?uB Yv;W)k'SAh տF.|ל<3"y %@ iln/#dݱ&aEL Y/ACCA3aOߐ2y$Hz㽍'n#j-ծ܈jodHqۓF̂%ټ,l9/i9 >[,l9/h9 }fRUT7,!}N8Gωsb%.}o}&jL@ӠSq+C\~kyO#uLx*I<2NƩWbٴg!q}kI\\/Ge *4ghM{\,ش3L3KttG"7KaXhde*<\)}TV3uHnYU궁p ! ~YC ՚.tXiA+fFd0df cB}wK/^-uT;cA=>HuHb|T|(]2/fe.z@_riZ)6[8$-9u" jR攖>_ $IԸkT~͊tKo"%>޷/v><3) ?[ݿח9`TVrw|g[}ysJmնЕ#w5""E^i\wOkku*)+Z81J]sJI^-q)j0I;Ǘ8jO;%?/|8o?Vه8@[Χ7ϧ +!g [}:kǿ㿾l4pV:aO[a{& YZݯ5&6jJfm}Z26 |v.Wg` 귮ޏ#?_G šE Y5T[K. ͔Q`6L(dr<4fN{0ݍ6jvP"1t*}w0-_wG*~im{ZXeZIkCN>{k&ѧ.?U~eK?LC n_X&8_(dn2mn mc?nWSc̊^Y>U?/R(]u( p l9TrSTnl(9bUԏѯo-+9FVB w" ^~!mՃ+?X]~3!S3>HP`3XA5ͧ n]K C< [uhˤ&|$Vo t$Z `> &cd+( ȺRz{ t# R6yj0NNG;Y%2LΞc >b:7^2zKe$&Я#A}0–Id:mCLĞ3_"iC=\Q>_2׋t|\&V~ĴoC7):HBT*Z*u" $upl\{D ۂDBEQY<=h>׏2AqKzи;Y&x@Jō uIJoT>g,䦂oA~*\BS:'Ф@U>=h>ƀ=-#(!W~'/k>2 &Jod2qiEOpȥ@%c.*؜"mJSgt8ݹ.R$ `gJWS`Lg iVS;Xg L]:_⌭(tS[o aҽl`u䥔ݠ3VދBǚ\\ձA9bM̂ *ytn>i+s݌_xz׮;9zݲ5k1ɁBk-k/,5ڨPI*F\⼗\{zy:k㝋Ss׬J@D7b}er(SkK&,=M ezdhf,1k߹l"ӶRH"8lj}Qgĥ,Cʐ9hsrns"Q#:qHIt5!!?hT SB^ZѢ6,ܰN0}:S.e`K>l+A Q`Em3Ev2Os6'}=:˯י̸RJ˯uX'zwT_LQ]Yk0g6iZ'n֋MިgYa.Z, i15!5فTD5[k`6E)BO=p*+Nd NkIZ.ӟIa7DX##k-}f  m舠N%u2'niǩYl/-hbv3pY| H9 #X\ԗEc,ԱRI" )ÃTU6i6A*iW]*P\gY>:f~ᨣo녾Ɓq^z"DzhPǁP t{^rel+A;')"Y'rhZIt&bTV3I"{eYda1-O YUna,W^^G&\;ީ !$f9툓eϬ[vv{" @3(8sHXnաLY:HV-uIr$Y,g,N̝pLW3m'4^n13]9LCe'M?gsF39sJ QS둵FR5?>P&5n?Ԩf#w;[ T\ u^ltrqoiW7ٹ%ePڷ"|34b0jCN3 0 'g[yAQ.Ћ*I 2ٱGA-yq!S>8y֜L@ (88C(b+!VѥUA .nf1tzޱ)DInL"2K3uJ)Ltpb龇*Y9񴿑EK ȧo*MEHg*-""1>blž~GNQ}rP,*.o«DQhV^6jS$ȩI营R)Cœ3Rokzgu@R%<Hs6^[~?t:r"ៜH%1+?Vj>_|u诿z۬}KYY. b=(\o_#UJbXyeQ(I\Y"QAM#ҳvSY&D^g嚽P;?_I^/mO6#$ICarla-2.1/resources/16x16/dialog-error.svgz000066400000000000000000000077221364475620200205170ustar00rootroot00000000000000][o#7~ϯѼdp$.,^q8 v@ Mpdek#K$n]m-yffb,69=x;i}lzFV6̆e bٟ4lOg?}ͧv[?̳2˛_.ryw=<͍rf˻gl*BY%²n6_vGI(oTu2ѐT? hlIJ?˼?k*d$h 'ϭrV!Q5X6˧ jq60~+D3%xtߵSh1$z]n a7Wv%u(QG*g&j*w`IwHki#_F}b387bw|DNcΚȧݫ14tW$8јQ W׫*kJ5w1@zɕ41б i 1f`yG"RS`1h6F~ צ5:s|4 W8;'7L`|؇%3xvh1T'@.UACdJ~~dȶZy-[̴w^Bf^o[4`HF`w.?&s)q@)\v!@M<*v@ ItlMFn͕!@[23NWmn8X4VNETT砵@)Lk ueZ{\@K* Xk#cNsY;HDdc1pp&*3AB MADth='f;fh2բɡS #X !tcc<:`u B#I>UGU’fWDZAIW]0< tu`{QgbD4}uV7Rڴ0dS뗔VF+5ʻ`)Te/&՗-ŏr! l_^|Lૡ; @FYBr}BF'I:uSM-9P0AvC&3/Ekf<a4΁:Ia".H޸iB_WJZ|˺ _&ũ#'-JE"))OTPO1)kRp`*FP5\#wAD U)J;T M#:WG{ʽdF rMw@{RwTM2z`Ofǟ cbؑ`"ygrW;}ݹzk8Te\ڹQBm:U ()"~>qA CҸ@hB ITRb@w^+I {']ͥF,Y[O e#CzqU[uV Ԩfa6$SJZyli)&6~Y.D2Pa<RBIytdv⠪qx2kdw[t:NЛM-g8MWS-||vw;fkvn҇n^My5}a|7R_|Iz]gfF(sa7a_7.i&ӫ lrlE&x~,qe : J8WUg$IvbbQj&DRnGxuiUSL``[h45th"I0$Ե p[k#>ЎJҐ 2@#T_R<2^0CpaW6(nI*D 59rކ"/F$%b؃86hzANҜg,s8"ˌ|~<%4D6R!8*͔D;TuRG>xe7(rY{KY@\LR(UJH^BK1w458K[JZ, 0I5ػ$-CH~,Hm&CW+"YKW皐J Im1cLUh/`Zn<)00Lb@)IOFHPjR o)H,&WOHz#}~/hđ}V\R h\56"ֱay;XpI%wmx1XrRaTNȄr*'4y+1V69u)x[d4IOiʼnFhUߧLwte`u寕ԯ́5#wO@b]z'ljU`ClI01Tlags\4,q+y|a%kƩJ4;=ruݔџwjCarla-2.1/resources/16x16/dialog-information.svgz000066400000000000000000000370701364475620200217120ustar00rootroot00000000000000}ks8_+hIT[[{yoS-'q,_Yc~A("AF߾~|^oO cO&'ogf3:_ϟ\/?>_䯋zYO'/W]^l|x26zZo&~yaI ;DgM^./' O'|vÏ;xuszu&է_oWY?Ο-67U֋fyқW7?Ee/_d_ιO8aͷ*BU;gU~N^.~Ov?q/v}7bs?_g,;ߜ8l~}(5-nNr~D`y;7%_盏X[qqS^.\}}M'yK+lr˛9^~^^_&͗q\ϟ\7eY&x0㙘K g`gL[;_?9_"C~-VWVoU%qoؿՀ}v(sål|zv\]:89^~:٬o~?$ۛ__}hm5j}z˳MAt́k,FJ^]ϗȿVV3k*ࡂ6'Ͼh|;W7 '=fͦai>epq$pu4ps$pH#(őM12.j\l1eSϖ!/4{1 E?ඦ03f:JBAM4@Vtum]ְ!8gg-QO)%HޔU86,w pЮn- v猕V; 9cE$G&1Fޒ--L9 fg]T[a/ߎola33P_W |hwJF?&Wӿ'3+ѶF"bߨHX9`c YƛU/z~uC'_¦0Mga} oiz y t5Kt3gw7͏ٰaH²Hi?*ٿ,X7[>+Pya'rqV'@.Sˌu* mL(!"?Cu7rNI~('Z ղղIl9\]}% ty`—r WڹJhh`|!|Q^v+"j:09ߠdZ85n} }aetͯ-}qxw{kCHL 4E|ˀZ,pHR˽K>Fh%UHD9dENvƾ{tڝ_$,Tݯ7g˺9\JWpQYϬ4r3Y/}I\f ٷOʌQ0]?"NpSXBي4*9 UVz=deD4RkOn_ix:DeS(zwCoO¶3dndEOHIVZ bkpIV QZYG9 aY_'qsE#t*\J%N'G!Y6DC{8Ƨ3$>~LkoŚGAЇ㳨p +)}G%D&ۑņH@ )'+Ӥ1ӊeCē@JcOZW#TdZK2f4Ze4CkhQ'we#Ƥtp,\ T^S~dr+@U@` >Kw6xUݠ,wÖej,@Qea2 _)q*3\GiҊhଦcTS @y 7`Tfw4Hc2?Y>Y91+7^2F1 Q$͌В0!p-PA^H0˅z1xKRwbǼY&GNQSH.ZLEoQ.6P[n[F$ &^ 5@"QjVaYr8ͪFpRb&Py{EAB@\EX*4jxc QxnF!A"hȘ#vwu1C5@P:+Fw]/Q ]ďS|P8ȓ0}_Dd*삂u͕eH-O8AaG Ɵ/ٶQ \͓z0W4Ա5?#Uґ9\tn;%jE1RW +cr/"@`5=7AcöDlm)Xfdrq.ǭȞǭ8pڋn8nk8O4 6@N4q(_w(|9 pCPAH@31ۤGW mBTtQ:]D䃶Z6h1QܠALvXRcm5u zT!cZj[}!(CwCt'r3R2CP̳:!A)LjvP}z?RQ$R1pY&YUs *vEUg,($DT!I*P&Zt0(!Y8Ї=Œ;tV)f) MgJhr)7FTLIrUT+i3b'\`v WwV#9|W1r.Ojk8 d;f"cz*:Ag8L+yOU2SWچ !y Gx%I;36"z P kP8É kH5¢}52ŅbWzk |X$C9&uZa)p7q# -#%6 D73B!VšFU9e֢rMejm-FU3zHhRM>m ]mq)4{/Mh=hj uz^Gh4%:%D;j}OF }p#6?FGx)>V+:eK<|,n.׋7_7 q>=9l]foVytyz?93mYVY2ƚڴvBD (::vڦhR\{_b)t nӥuPh c*UrBWUxGMgqJzzo"b:E8䜦6)\Ɯ"ӡA#H2c>*)J^[/W񘚸÷8LQxK!t iݔ8iupڌi#/ȜxRo1 O5UV!M+FHLÑb|uI Z;7+ ]}(]iȁ G NbP|}Fq5#+v}Q{zm 6h%\XՔ# 1G]sXņ*sH8M(v{#]ծwCz.ݱVG.zſUc/";,zS1(6GwGYv{N-&@Jm'Qj]Jw>dVfC؅ ᒶS\{9p,;x0c.b{)SeEPM!B=l=iNxOlOM< 7)}OlzO}wݿώ|J,X!n ="wdgc"'$))#B>n VXX"*|e@q?CbTHe#,s (5) IBbֿ*߼ּqɖDW-P4%)}(N)m7k1>ϜrbESiПmelfd1R<3\sUg[Qݼ\ áqt1pNWިc$c\IδCc2A8n4IДU}2)l%8) qAP/cű7/1v\I\c/I?qv7B3[g%@RU%$G] 1mo`:9Yڽ&˨GJur;'8MkeRaqw% 7NWwU:kې:4= x.3eu5!Z]ݏ0{uBH2)[q1DP]G ,Jx`'v䗎5hm766ݍ{l_u#U_~o@ .D5i%4Xj>M"*׹TvtV18nuNjEP0imh60jwO*v߶, ;^F30:C#9ZAt^=Q_Em|g!'T6>4% m]^n6([u~{s_]FjrAŇ(ט꭪26a+(ArIF2Mzth5dNKV$I^ɛ~D]HmQ(i9Ѥd50I4aq '&UtF Pr&JMbW`1(v6I& v[-jif)|:<೿Of Tf%RZ{BGN^LKiy5aLψz0Vkt;u5Cvnh:cp5Lk(a3FM.1X",A><& Bɻ ;yUJCֈDkdHJ3PPPО"'6tacpw$z1"jusF' n{FC=Go#} :~cN?e8(&#(J#*c>Ǯ[=&x"A] JiLX30aA\`֍(֡"vy0 pJ}}]E2?5.(9vUD(p Bi5@F&Uۼx ?U;42nǯkVeq4D1] HD1VµUuN(Y-S<I괴%p\ QH"ZR(džd6(%%(L Y"(1HRxo[LD0pnDwov k$J[2: 4-3:@Zd pMPFH d͘ŔԢzg엊PaIIzd9LZrJ>S(>21%tqn{Bń(3(ʷM&2=vN璦sB]HF)9!\&(Te\lա U bC13ZIZ 2h3RN3W*+Iċu!ՙKkN\86;UrV1/pR;03kZk9qWJ? Kt7(vJ3+mðkJYX|cO|)vyج.H]g ыkD\Ί# 0m_P+ؑCEq~v"R>HBV8#j@;rڡW|mz 3[`?-?/./W5`Y/VdtZnT,lU>Fl7b3?o_xvuszsk@˳M8核uu>[? ccV0FVnq`@̳/Ng=&߯ny)'䌓O(8T7^AD]߮/N~,//F0̼C'%N t"#Qx~~X7o9ez]dWJZ#U);{}'| z} _ʽD8|yU$?dH=-F&wd"`ޑ}Қc}̱3+{[_C7-[2#pWnƹj+ॣ0Ž~D/´' ""(Zn~ŭTNPYxY"E錡즜vK~yghInZ?7#W{!ZBA\AJo'şO(&n"-'i=&]b==qL9 z١Vq2a%yԊPOr,U,( WLJCTU)@YΧ"*S.3kz*<LjIKqRcϘҊ68T1K9(%/Z˄ T6naEYg%v"S}ZI34Q٫ ^3uyT :0S2Ap5/¯Xv|8긂Odqo68`SV;>0ֻ E˯V#," A4'Y&A5 YR㾺&]\jo72/mK'~Qhp[WKh@ T6X)Cqݖ1+J"] #+99*܌a<1I2 Z鼐rYbSE[TxJTS%@h`C|b̲ ߵذATP5$9Caݪ:-Bz0XQ" R"!sRȕYR嘖^׀(-׬lR@%`Hb[ a831R,R Z">h&(c8b ry42d{#SRgTP$S8#2em) gR8gBSL"lJm~20C J_*+J/ӊ[`o# TL#S4R;it+[}xmq5zvd~HzL.y^L҇tѹy(ͷOWţsfIe+\)hqNnڇ=q'ךּ5gF?cw~gE5(S1jSfk[3zD es PP^X倾٬(ɢj&=؁ӟ!C7uq$,o"ZB&3Jԛ⩦`Hd:FQ3IB2sRŌʟ>bkR]E&^Ϊ+N \K OHZ"9Aq#d`ϪbP*߫:`TulRPXd ϐʒW.ľ,Ԥ0^-媹R%5Q::IH_杴Pjl_,*ᝪko=!.N^C4M ?ؾ_Ѥ—%U"ygV:.n R E1"Qz8T+pz|Q Ah_J$N#C4!)!z5='?WH3/{e4w("*6CkӔ'T3FF{P7tRLlڎAl$6FD-P!I`!c])dI4=vG'+_ut;DoA'Qv ;q钚`%0s LWK; 麼(Atkh9aZ^Г,^9k z;|fҊT:WBm@lpbm<ә##&އA|_Cѥ "B"oȪ( ӽBDDU(ʄW;SV@gfjj0}aHܻuqIEx"r"/x"x6W/hbuc^ǼL:=Xgl"iw%2zLae6"ֽvI%fcVYHJ1+DƬ!R"Q3EPكX9̃*ʟP#:)~ ᧹]K5JS%iMEGQy2\£^ V^M5'-5.&]|W]?aJ3R8-# =!PIxo7SͯÓ)&\hXL{:Ŧewk(i:>XLzC'BCAbۼi;G'DSD9]B\E}| ݎf/Bz&@Ş "t3l p4V 9VWO2)L2 q(|Mʴ+$PD@3{Xb],,(0CmNɃ%9{ܯHQA e|95ha}?M"ƤR*MT«Vf ݡ`6iuӧblW [pUl_Dc8\W0tICx-89-8#6-Zo,hztM$y`Ӽb~嵥җ.M@-·'EWʞlKۮhiyݾ /GKJY^!a%§ɟ2-PA9n؟*^oI6‹Қ#@f4uǚBo-@Hym_[BZas,VÎY\ځ(\yL I~ԡqiVDHF i CHJWA~̻@ci@d86ʣc*]`<P.2!\bqÛg55VM.2y;3H KL ΠmkFbg=#Ix n{D"5 omNAq}j`ezs-r$;_FyʫWўZ0k(u#u%}:g`9z~D!nwh{#DzhY D"xQi-(BhN=Jq n:44iG3Ӝ7r+1z:, wtE͜v#P{At C\yn2d׸O3Zpik"YЇ\c]4O܍7 &F&sJG(,8Y2)ʄSHz_oy4ͤ'N$-5{dhMAuufdֽ|J6IuӥK3aGlIʷՋݗVk_f~*P]:^y@~mW[0JnNr m!:ԫo%4i"9ѽ|ڸͶKxmEet5QŲo_}لLǵr;r^~DL(&mMʔieףOoP_]i_ ENJnDNm t2*y0(pzh钸RZmu(N%S[@;[Ѱ6ȫVWIDhrNA8b GqY8}s^|\adxJb)~QhB ro$I0tSAiC~r0=cmիv+Tk~B ~]i~}~2f˰h4L*Wz Uf)8GP nvA6mGN.:HF.ei5Rk׋W/޾pͶҶaiԽro\-)}l* z &,UH58`5HEJ%6G2:qٲU“+vĶҠ%j}R "l&@Rm1B &NXd 1a{[Geܧu$1N$ѷ: Kj{SMV5{fЖ&A8ĐU6iC->; KT;DIdՍ(Q;YÝԐv` 3%DFLJ!ABwDG@ I? l_:hYt2CYIJZ_:t1̞[̠%ʤ㼮 URc#tH RE;Z/6߮39;+[ͻA9fF$F Kg *4Xd#3m&*SAR6p2YNB)}ejSi;14+ۂrj0.$돀FZX 1.Zl\)Xb%EHR4^8P0~[\DOȸ( /FbsRfZ8yYjBյW9$S6yLhS;T|0N z[9&|I{L+4TsjQtV?l֫H*Wp=gהft: Z^K?-7NeQv>8_jߠҜNGxX:ϭIGz1vzN~]pgg"\ ެb*eTS=Z!kW3 s\eq6+Yw^t;?yǝr-ηb8ܨTEy182rN#ΗYw->_l\jT\ 7^8]/We*hfxT\\4x4gU>_-`[|Ԉ,sUȢ2RfKOD %!! 4"_WmwmPZ\5+,?}O+6snwq!EwM@>gy<(,4ov#[v5+_l)Qjqz߮y캡NjpwvQd:_q;^ڽw[oDtOQb7Lͩ8F)TagQ1#J6av!W-\jn&[@_f)7.A8tu7ﺕ|1,sYHw$2١5i9-`EO&M xQٟM C z0@`s(~ϤB˹X|lZ|ٟMIZ;[>[,-)RS:fb9Sb+F㚡aULwgݾ՝ah CϺ^'U_ӋTFL%vW_?{K)GκW٪~[忦d NBwxŠd]LjkSI@F_ӕ˼G,i6eT?뾑-}UImea!9[Ň ļZ'`c/oG4ei)zϿ5Xہ%|t:\\LOL^ܐ}Tx7mV~'՘fPZ;FhoՇF!֎vh#=$-,MJ-fgwZ le[*D콲5W2DdBPUHy5t &6s/+l)@ip l1ፖkr@'6+FæumA頙I] `D>=(]s>˶FW`KFy/y˃&Td/r9ϮOLnolyv^wB2G6`jI,P ^yoBc{*t'Vz5^U ɳ9znl¹SSx)Gr~'ڹhx`bm561h'p1vlDFʱ'-)GD - d&2O6< _\O|ϻ!ׯ./HӓE1'*m7"B39E8gF@+32#!/#p@́&.nsjEccpl?G[A|<~j30oyγ&.$ݦ(r&Noq^tZg?7JVr9Fth8t}DgcV{ٸ ~Ǣs(L ۇu]ָ벌..,ol{Y9BΓꑱK^gE,$G5/dVFy;h{C¯U6VYo,Ǔ9R{4(ߧfE켸Ncr0@4?ȗtcW8[i˼DoWj _nz֊ >ej]ܳ,;ggݟ;pʱLY (фgՆDB=mYq30]Ngq>roQQ pnE&p^sy)ZԌ^7) *|鈅ltmt y9?CƙDbYfwۋo2P7=DU6t- N[XIQ` 2v~|YŚBdH3VXr˵ 9$af{IƉ{@'JjK F[soeփ-h3فa+ErkAdA}ø {1aGfr" ڬ$e04pD Zs=eQ VTj`>'$gOI+ɓ 1{¡ BzӘ۳}KϞ^"  k$6yFʢ$[ ɡ=h #JƋ ZG Df"1 31eد4V00`)Ɂ1B"O\r%UބJ)zFkDЉ1IgC=K"&ceƈy^țel !@ԏim NHl=J렍r P?He3<߸0 $`uԄs  &j9p}K0K븇N[uPNkEvTx3$5~+5l@oCH~|j,lV4 SgZ cMk:fY >pOq+X^$DUQb׏%+v߶ߓ+'vA$/ SA4lͣ m˥"b}w>zҼ =QkG,|b"5rX)fL &F]cYJ_V l .{ul,XimAYHPg16Bl1o *Mv[4mԉ".h=oMyȓe>'|Z*/ gyF]<^'KT xE8`urc!62(.)S~&F&:&д(q3!P M&Ԑbc4b7h Dܓys&I -y]2X^̏LF|29 sY+l 3,V)0l+o巷iR`*n?VF6w@-9FNrQs*#?xc8ICarla-2.1/resources/16x16/dialog-warning.svgz000066400000000000000000000115661364475620200210340ustar00rootroot00000000000000]moGI*%..]-lmdR ίRá& ز8&f~gOL~j |2i旋˓g~2Yf1o^'wfnfw7\]Noެ׷޽KaZ,_^n2n立˓՛]77f^C^W׼Jf[^v_^j.gWEJϊ|=}6_~j1p*KYy/Ӗ^-W R7֫RIf}߿/fu;lV[y_fs~S޾i_Y׳'e|l'PNm-bIP |64[\oo˻^7nyif9/\߭4TFX]>{7] S硁fYUzar}vu}.u;=ZL9@B-SǢZUnF0.ή hlMsYtznmΰ*q]zq@?ܔVYiqUM+Zf]?\7'}ժ)wsZkg'ÈƬb5h(>|4Dt|K&rE?Et} C 1@g:;{>*2=ʟ/9ңxtoO acVE[9>#e&O]]8?ň.Wz$_=9aޥ c=#ϖw3a0 V6o' T'#:AOLur~|4<~7LD~>F}NF>]َu\u\ax\3{Fڅc:~uqwӛGv_Y6p7e9}'JIԼ~xy⒂^^._7}9ۗ'o?p<=ˉĘNsSH~zI¸ta/t[8#p$b|YSt#@D-HH  H @fDȰ),zJΊ(S%Q#8u5ԪJLG  \PrA8 +3K VHD"P@Y?bu6%g~gC!EpCѡWdv Mh#`"&@;S JAǒɹGOdwUU!z0# COې++m2?cnG]C.íK'}1*D0@,B* 0K >eẗaIt8cuLAb.GPs%w)%qȴ$M<'u BOi 1@S538pSj{Q(b"(~?xoeD* RO?гԌ M]ȺFSN ŵX8u^(ŗ2(~ 2 e*:{5[ET@HkR"`j&PɁT"Jz*XL)bW#yWaIx$nY! ٝTp8$!7&hV$>.9E6MRq Xa/攋8NJJ5x&Ay4xԻY{2 nn^Py2}_/wofämlˬ-p _Y_'*&o?joΆeg˻/f^rcsQbScVV)_]?@,o˟ f|1o6ҡRg]ՂN )H.&ڞSLē#()XbUR%Lm4Y"&`MZNÓbb'3R?C mzaE O 'yI벘0Ue,ܹqJiFwH$s@is)2),B=!EU-K,L:c,C8=x5 ( ^8 !cf8ůo10qY+u7\H-eUIļ"q&p 6.62Y !KapP@:b(YPR 1 {h"0VYBzPȭ8( Z]P=tAMQ-BmH{ˇ vd28Lɺ9$Rt18s+u#ŬTe ]Q=EL IqPn똃> R'nɢٺږZ;jm ;a$D\dXbQ; *kk)B]m%G!nե&&0"K?Mmf_W.+Bgځ[ +AYk 26K? w82}<׈Rt9"b42VY]șH 1L=PHBsJRRFj[W^Pl7uf|W9T33V({IȰGE9]]\8%r5ts17]{8ՠ90 >;Sxn~N2Uoo>\pYO&+g씍عdar>uc9 'Ņ*ed6arT[Zm*|@3"!9u26"T7Z"@ rdPB r&פtzu¢W"R&8cކalՑG4(G2C8idM c.Ynąz/xY3=)U>YsHJ}ɩUCxf_cB.0<2`N4+6]Qe%4N;T'"NZN)! ;-P)7֨}ArLcBmPz,#zrh WK47JfƤCEHOՓY=iJ(b+3N!\Nv`nפ9$zdlFP_5a͊$nnEۢH亹 jwx[ r]M%[ީgyI}oZǨg<`R~K'#)O'{)dO|2L'#)a >I7 ?!d'Ov?#'_ڷ8Ju~Mh~ bwlHXZ#DtŎ. 2U;TYeih@tR&.lMDYjbo)0&&FrJ t/+:ʴ#tL!jfPpH;'$BƽyىQ3yY32ȃ/9 aa%fBloEs* !ƪ?".&E{Qm tLHf.Q @=1spպ S/dL9bBY nMs\MkH"kt]͊lKpgl-El0 &ʆ-F-vd-WU @ `d.ƨJ.בUFkռdCarla-2.1/resources/16x16/document-new.svgz000066400000000000000000000071641364475620200205360ustar00rootroot00000000000000Zr}|}YW$ vʗM2IަhII )8T"X@8>h4@|Y LdH#2$,d/f8(8ǫߏǃIq췠2;o4u-(K/1ռ,^'~=orϒrȱ}ͨcR|鼺bf\:Iוߥyp2$2)yOwi^,*, :˒AjڂAk7Lj3WX..YuАE 'M~-s2"_&UNe˻lR]LY}&^&T=P.ַ՗JZM?TuSf+$n*\y*NgFZR{ٲao4bU~z<j]҂e}+A7"D98qZ=N[uŢLVEvin Uf4IIƔlxĤTu\-v)/\BF*iVM򕫁Tj"c4Vv*]Wu&wh.4$F I*qEx2jT/A}zX_p v]6XٶmQ1 ւ뎎`bqZl‚Y0PԳH_"'Kd0NH` +MB 7 2!L{c$2ǹ!Z"ёM|(zjZ[j9I"{0>Bڥi6/9 HԍC w^)4Vf*l?U~ Y,NG^E.EEhDeW*RKF;>9pZVAqvt'U#i~׸w@~1Ɯ ] ̅yosad0:s!/ԅD Ʋ!s`1JeK~,N( cve{d;XRiA,`Q%1cŒQkQCJ ~ͣFRz?m*X6%[l/Fg1HouD1٬q[Bq8vOX(-8SA4ca?U{ۇu<}IX>WQ ʛkX|/:MKOfc!^ަW ,AĦH}P_U^̓b]>x>'h*5o+;BB&L^{V^HNdVgK2]CWܬ7ͦ&y\ Mm^.!U'W,)11-ݽ뻿s-?]Sg\8mwi]De].rE"]Y"t&&礪$ojˤjĈו-0&U~G& jIFu .䇶 xqKhQ%7Y/iO3X3@zOUK&"(z 53:X4o MuMt/:ywb U?!nlVI3O߽wagwݼ;{h\r}9l)o Q. #1!$(83$FHVg.x(:t/..wta$̓H={oHa6 w}]$F<4}z'a$/6O^iphbM 3Cr)ZkNǜra_4g梃'h{f2&<"q.}4$9}N6|')H4Ba.9ql }ayT]yZd @o(U]a+珚b/e]sr!J^Dl;%`#!7*F"% 눣oA7ٟz)Msn uѢ0fvͻ'abL8n$HJI$']=yG4ׇO=Rq<>|Œnb`Y븺nlCY$ "MLy[BT4l}F5M;GfSo#I0_s VQď,ϒF껫DwYyd} &4#3RjFU#_LD.w9M$啍P&Q$-߈Q iKjh !!e D(׶WtB k](HgpRn6zrI#|!G5 _8*PB0c;0>Z3֐  %͘@f͐h 6a1+9S@}k!sP&IB7{ʛxżE*$ͳRvRh#)Y]Ö㉡&FpL*]Kcf4@) jš(P5npl&V[v#Rhmzڼh#FVIŌK W6rB+j>wd| cyBl]/vb}LiϷB$͆R n)ީh3ϖ +A|ڽp.1iJX OFB57яDF kt۴GcQn%::/}j/:(F0 \3HI_,(4J8->pJpCab >9LhQQP2{wl &B! zj{uNNGrq9RZ}+q6]q`ʣ>YEZRL[cͩ>Nq':nuTfz$ ^RDJ NiKq -ǍcDV 41SH\p##HCԈܒ*#KkפTDR*axnKARʽ#.@oI_{&Uy` ޶?G*.[ܮir|{c)φ]]Zw5 ^x- vS/rPh/]tRƻa7ւ{NPq(Yg{y3RLۼɆ3<1O 81l}@Carla-2.1/resources/16x16/document-open.svgz000066400000000000000000010425201364475620200207020ustar00rootroot00000000000000Wu&z_s)9ɖ  ps DD_KZ3-昻v_ѵ7'' !zyO}C~??gY+@%j]Aо|80~_e-_~O\/ِ俤C?ީm- !/0ӟ>חOxyb ,6ꗥP]ޯ vyK-ug,V0ŽaQEW?4m+ 0ty߶wG{{UJ>޿O,6yq<&7!/"|4_?dku!J?e'O_?&d? N3CK!l?<0f-#cUCC㧿uM@q!G8is(N_pⶅ@HJ =z?Y6>o?$Nr>]?_X~li|~lgyϭa_.6Oo]a?:~PK~o3ǻX}0סᎦz sq_I/ 3dhWE`6BfMW;^HagF`]\ߺ-wCKN156,YuTVٚe9e{oօ;,YQdG`]8DVqX-?H͋+Sͱ ~!{z1O]Tvr^Rɾ5G}J|ث+ԄH/{~$$dUeh%dG0kҸH?YǏE-Ǖ&?6: >UQdL WϡPd* G.^7hf!Vps5d~(`4pr  tأR?Z!|5i;cWIL|C*m6920=4f $]2Q -j>Vg-XdܞϲS,e0+537D@eT[6%[!)> b&quOȫi0.SUNq"kէO:.k΁+A@u65QV|N:-5~YG\zSW5v`K+]ׁ6YD˨=v֧98 uY#弰콨<./*]8Wx+Fp7ˡH3`B֧0 6!Ү NAL_2*tȶvqX.@%(y(̙;<`r\vPFC@o|Yqt\dŒ5a^S=|ET)h6i g m/62ٕ- &y_'sGt{vԵߝRDHOLf&  U85M4Gaq1P/SU_ x>o\$\%wy>Y؏عVy"HBEʠk#pW#r\q T(:÷MC-L 5ШB>6c [#W9!+#ѰQ:<i̽/g#9l?^ ; _=kq\m]9iBS@єo~>W.IiO;Χ-~ToH~4*i-_ùUQK܎vƘ2lk%SW:o8qg7זJ6ߪ>@C?3_p] O# -:♰_dP4)(fDw8Ȳ Ak":>UX N=:VvIzs*2fУO$Pr. w{z&O%e;a\n&YOYHLyٲiڬyS) ޟ^ LE=IԾi0++0T.Ax,]w&YܐٻB9@6uԲcLSv`xu6IKcʋԄS.# NFQ?'Sy#D4S#LPnd@9YsEЄp!R'\VN)zaEu-wh&t!eSξqڲeqKP - B~eA@,֩d{֊x /C.ﲴagtWI0o W]fEY 'hJ3Kx$ˣ ӾrTd@PZB䵾Di]Q>;QFDM*vV9cF #kƴ'wV u ~.̎k7lzMKP;[6ѯCh;躴g?(9앏P1`Z.,|^h7ȍ;T9_5V' C줦HnNJCE4xYTΙ4Sa .2i0gE`H6(G3A6Cv_+Lh>`)X蹜7֧z%B_PE}mA5NՉQpT4PL+ w&;;0S~hƗ8 E?E_GvMLn,~ ߁fKp.͉crB4J Gƾlis< >;Xg1 u`U)sE\`~toM$l o*`z9j@*m QmaX,BDcd<(hy s/.1j+?00B}=N[uR0S]T̾E PTty]AģK`<G!( *TD* g6R=3çimA|=>Ȼ.d\>v dhx[is#?džh ` \v3ՉN蠶*W7 A'u/`?q!Ɗ.1\,č&)7=*kćW R2^/962x9b@9Ð߇ЅgC=D ͎ѴDv: S_\<'6<,h78tr((hG ֤B Z!\$i Rf'c$ᄹ`4bc_ u|#6V 9VaXֱh*Gh* )oaJ+mD~aI!.秵q,F`fhw1cBnE~FDw"|#uu5]R1D,eR26F@ǾDV<0fZ~֗ŁfW[ysߕyOrAſy$0Q3F6'G  ʏNp9CiS]$xsmf6cg Oe9r63 N+e{Z8=|61,zkXUkuIg"&|`P ضEּEy=>qU߁7~Q!_4pjm&.DB3&ZzYX |/:M~{l-GG#ag.ߩU$N..$a$JyIgrbz0Pݳ}=^& -aoyGmс:Ui=~쥖o|>o/=dYC^i2-9x{hﮚ"]Nu16Ҷntq[eB; y)G7Gy}Kހ:iFlaq}%Y2P]rԙ~]l<;CsAV/FGn8Lt$9)emcA~=%YQ "' 6ZKT)& Cʨ6ikpuڊ;'0 {CD^-)QCE0#)_˃q*Ɇ6|!K#2IWT|Q= Vf,(i=.Ģ5y2 :or"m^m&x.zMZ|k9Mz?xn7`-3#Xh$IY7 \1,*(FVeW&x"[?'RU٘h.84&6L0%]%\÷"B̲2w|.s W&rkyJ/@Y ߜ |\83/q-_fe3nT2ӚӐ@ wQ4D f&s=J,hCCFre)) AvKЎoUU2ˏUB7(/ ,mmoB#p ϶L3^Mm1%dzAd3 +Q1Iw X>Ȝb(jeTmlz{dEY+IŢ~P "Bi.Җ(k:;loYsCKcOWog"/2Pdd<3E(<vW-r =p۾wI B=e˛oPTBQ37?<uL~̊NE _>Yɔj7T2]g{}lPGl}Z6m,H'<ܛ|gZRto\q_۟0AxKKwwRXX?>>L%7|_*{H=*οurSEl1rO0X(|jS5m)拭iMKytefkݞq8-}OCmV0\362ܣX콎$QZىM^lVō lڍt)(W 1쾜z_yak6Z[bm0+1MIb ^QPa=(]m3Ό/gK^鶣lqQ*(|˴Ga{̑-$=H܇C=> jޥw}gjbŨFȐ¸gy+,w{!\k>}/dbN\sDaHED!6#\;H#|ln.I@|ʿ6XOl׫; xBL@?|a h`3]§"^[U keԾQwD-X /T:x)]V>P' [* JNISeMHvhB-m޼NMED W2Ӡ5O#F745 z?p`i8$6JVL|7i(}NNټ:ofozr(>X+)B'pw^}&ިLY"+hvzxs6H]u6U{G~)#e}Ѫ+Y"Wt=}:B),!?\G/7-bSA(qMRD#\&Ry FM[7Z|5f)v8)h `a>a聊`؉]O@F Nzh*o#O٥ X&Rk:cX Sx _r%Ls,17R˸)3^&*ƒ!7}q,d/5ݦ/~X}+\(VϵRCɶ9Z V;km} ^hyYQ0P!pC2$4!j 9\j)Jkqՠta&3z~ͮh:Lyx(i8ax>#9- bCة'.6*̊:-\[. Ѣ)XB~@Z/hzZXA;yJe"fCXSۥvo- fԾh.pȸzY:Ǭ%=科ޖ#z]#q^<FZr➏e0<#C40:!l n"dj<|TU dx/Cmg@~wN#~crr'E)Jj wBҸ|d` OAB@a\ZM(Gʋ _1l7GJ&}&Cx(fYPaɤE&yC;R"C]wY&gH< 4{EAK4wP ˠmdb>Hґ!0 5MHxu=vYowf }ZXB)uL)h.#$DZuC~> q2-(2p+4x\ӨZ%~x7MUM9RQ``anNM]rѫpT=-p_n{]7]tȜ3yY‚-3nsYXJrngϱT2dtbGO?l<r=<s{(m;C؃vhÊ/z5ok]E0J׏,Ƣ/#{7MäDt5ڑ̗v.vo V鑞Y1#a t,ĢP @kxVRBh6 ,`a_~JLB@毒ӜP̽6d{& 2 7a͇F .kB@GY*jE7{Lu=]8ed։t\"!Yݬ2vג'Mxå0T/9+ل8eO p"Ә$r2[jo~`cY5*hoyLj| R_ɮlXy '`!4<Ï4hvq͌?2=>)Dci=.ɦtZ'+[%.$B uU G vG򸦹nMYNZ-(7$)!1y$! <>dM~olDVwIE&>tQuGm(Jӥ}p&KS.aJC7Jj7'q&Y8( -KPV ֈve]cl276ԓ&+Ƴ&ŋ-6B4Rm~9NCx@pB$}ݷ^.*~T4 lQMs#՛*d)PJ2B{=:KND|GB9(Y!YWVҶtiGB ,+\nQ iwp3hjg_C;2gd,H5}` *Ǐp9m̐*֏) 'YT, i!M<5i3S9lȝFB!--ajerU5MBܤ-Q~d;NT()-Y"25 +Z0@1 A Au5ceEmu>W!8rbqcl(Pno.!>~ )BUm=vhT񰣨z _E̱nJC ΰB~!*Ӥ8rc$MG`#X*t"6RP:|Yx̶dsᅂQ(a{۶%$|aH7uF h/E9 ^+Ha)HTO}͐OP \@$U?"(yI+Gx֕"v0VxHJ Ƌi`o`#'n 6 VlUW2݅_ 9ot994T|hyr}+,RwY:=V㋙8<+?1R&Ȩge$T%w|u2AT+) qGP-Q)!'g~X=4x}"O$Æ6$vz++[qw})R󓇣taQԐJjhzYu=1Z_B~XwUHB[7ٜ:=Gף8Z~T8&C~0s4V:z;eХgH_) |x6=k י:UWw-t6"CY֚D w[z~8J]F͊Oʷ.>8^B&hRN+j͝CVy7!I`5'm؉Qr%,jE kg%VυkK/^wqk_taR alu!ݔ w & ȅ1e#si{%"(*hbKQQs^. L'V&Y$\`i:ֆfuם[My~3¹A:ʳ0N8Ƒz 0jKћ"->.|vHEI EeבXhT!-7׹LbL9fzG=Ȼ/c '7{k 91:9}od.S_  v>edXvUTuĺ xsxn!A'lr?n]U`HwYD/AU#oox}o&n2Lح'ʣsB+fRaS,Kȣº ZŹؽGhH'5|w07}Jl{(⦯g{ӎ{@oVHNĮf$=vϫ #MU;\!1</CdћR{ǐjj?EWMKT|Cl_yS»0z6?ѥN64{پ$F2kMFa-/̞Reysss$ 8|(p gw˜ l_oqDIXp~0٥k<*|$ۘd)x7eQm\ .kŀ~L9›ɿ]sm2 -)Ow7F+`+?y8~Wg~YOn@ve`<>žF)T9zrW54[ϛR8A4[AMTe,6~ E 0Z<`dT@Gwd!*f(F9{{;խrTȳ]h7,Ə,R(czlsPx/ՑsS١ΙX@8NGUEx嬅sg;&Lqb#4X8*LJ{_%Лڳ~n:U!4 Y-|>ˮ~(),JAR6YkT@c0ǿ/[Qu>6pDg_] gמ#+~Ȃb/]6'~,&NE2}oV"*)v+W.(kL/KQiM$D.uPOaRVj Nވ\# "e)<{wEFEj3|3MnSiBjV"t ;ܺNC&J 5悔W"MEyn!; *]psn|ثu>K)F"M"74X@﯋+w6RӦT cfwħ|g {2HigϮ&?CdLWbv=>b֘-Z@2|EFʛq07Ā蘶{_\H)U>v=2i.k>&P$qysd[ܐ`B}_.2xB#p%T' i '2)MNJ'+ Vg7%1KğkE3iO)K'T\Q 4zL/n%9(+=<0gRɼ}GPftҧ}ϻ>xA9f>v-NpP1W_r;`.} gMjn[ MM=E$9a ^ Ŗ}?☥g@s2pᬟ}[e3)Kh5x{jDs-2zB톣\ţxMJSp[Fl8M~`[ u/7xtl@q=74|1rHh'ehҧeBx'N!F3.E">%qoŎc=Db>x,="YVYlkSZG4=I;A7s{= _xq,do 1." f /f6)vi9`!>˼vdj$4T5 Fa χ`\"nA~Uǿ$}mK)e41a]9פ0}Bh]ۼ8rA + HWt0bL9`e> :LlÝ1zݴԬGNU:iA)i0&T"Oq.2h٦T4ij[c,I[$%9h29g0g-v>ͼc$PL7!̻SwXAqȶgrulDc -{"(\y{TE!k<5ƙ Orf[`zNO9<|Ug ;0Prb~iy!2ǵ,] >(j:¶1QE^y44B#E#ވ7K+8{WL2#v~"+T+^_ r 6S \2Jsmr]~$ukڇeri<7m4̥@bvOR.cDn[Fm)nsP{%PmJNz7-<վ(<]k{L4[ F`۸T* UDı&phߟ;NZJgL 2k‚kEgV7@Hv(ayIA%VմG|wI}7BÅӓe$S9}̮㝻GG*s^Xis7~bv|i i87az4Mh>*JdbH ~*;❫yZ=9sEUģ~|9tJ$a' f{|3ш;RCХ/4w90A*"xՅ)#]{*<$8 zdv1neAMjyb s HB^=#{E['ڞ8V'/YWmb$9Oo+j=6á + %=ֵ(HkbRx[$ 9\$멺5w.1P@:U>hPԗR[Ic;CSxH2+dR@!u.? p+~>/e3Э%|D+'0L 9)erWx۽drI_ofBZ$ r\`,wh쓸L~migItodVSY;(H}ƕn"Sz)#hj\ŷMc' $ষCܱyzA<"g E똻.L%g[ZuhM\GVɉn++ M jXu*kh/ CG-8R{bMW,-X (TjeU/lky] 9{q(og4.uOwa y_ |Ehb.֚E_V9'UZNOz ^Q򑛼#(>r[Ʈris/-[~Ĺh﹵'s+=H7$;]Ҟy@pkOᣙqĒ\5{Um'|Cɑ%4 $ u"TU5j˪TxE7ӫcLr"jd d1kdi?lI'o<!3pc۬7ik̬P4-A3ikڠAe %\$GWM=®'Sq3K*@XNߝΤm]_~B G=RvO$q{f#_#⟦]{XNڌLW'OWQcq_HӍ^ޘ\dCw_S0bt+Bi4&\›K pCAi!pSpd}ڔ~y6ti_su>uOu⋊,X>٣WFU1t_FNNVq\H;T)Ank45fn{+ͿMt%i >[h7h62B~@cPiTJ"d˛n'mIVû^,jҩy?kΜe-_@r":C[$…ROlv퇐aV|E-=ry8IR~|8#Me $*omJx2CwZT_:2n(+U45!7|\k8SsC&lBw8f?Mà)oRXlj_̻6ŒMm,,2žO9ixl =X+flJA z匴7-|~Q5dSEE@5t׍z, :S'1~HƤZ;IxV8o=B+hKG7p쥠WD;1;),μaIk) f^cj5Ö&gNnԑ|}R]>ҒW|Fx8!4_aDA(e7 ֯d>c.˙/ ːQjMJ۟_y J_/ 6<؞;W*eԎ>W\YP~>sE d[Ys7#])<[Wb'BSڀ|!Z Hn|\skm~qzD/vZaytw0FȟηR ?0Q'S"Yl}ꑙU*MZn9(|9m>F!-kՓD„(FY'/bpMXI]3SU#?RnT.}~%X/'϶џ`)ӴaC0U}?i@>^Ig4+$ySBE$"AϮőy-bЃŞ` io߸~J~  U|xvb+uqVZ` (,wLyʵ!D4VF;F3$M{E~ղN/e\(\C n(J[ wn\fpKSj_ԂyfI 7Sn'Pf@iɂe5"ƿzU=\_wQ?*w`pB;EV<[ IC#Ż"I}1ƴ'I ~_ZU4Xq[Ti={Rp[39Y?T$]6")h'\LEC/k$wfGfD ,P?~fr&O3qhn1e}OH#KF #6'ZY{[ԫl.hˬI˱^3K?2RRF&_&@sldT!&Ŷ0ڿuO~P =BPegB"`ٿrJ2-$ZDMүƐجD#k鉬U0۴5=%=f5THJ)F&e $p@<0lT]? Qeٱx(-o_g_tLNXO=j ֋9Jɭ%|)ґ5Mj!VVہ5|sw_\4^>m~="y y[[J[e5BI ڈa|52R}J%Kӓ$=_+f Β>,dJ3/{}CzIg3LH3&m=&i +.ZD']1ܶ>#R'Ֆdm|Yr+^xV1pPw) I@&ـHP_+cc j%֌tocm7;Ǣh 3_}sX?zߓ%cf?vFև%0)+J0>O>f1{O 4#!8?i}m*2B pߺGB%ܛ|C37?(q qޔ6u#akzBx4}ƸakLS ?sCNǸi:[=bIr-!`".=NITr;.҅M~YQ>Z aKQM-k{^UX0[ұFA_f6i''k%8ξp,̚4;Qњu1WW;nz!dAkVB^ jZK&E`.O0]jfޖb07븹De~GQn 9lT꺂1P$i)ȕ E 4܄bh 0.4齌c~EZ_ߙ̻t3|;Yd8 j)n*PkC{^D _'~Rz''~2!zT*z0$N1Ҵ¾DhϽv-=RI1hg-z+PoW9,wYg,?O&eUUUg_[O^ GXk o+վ " [e< d㫄ɵyӀ@O^5fkD_bULDȁ9ޏߺ%fZY2k{D$YWF1I6gfT,@6`7SNKCovVӍz`ڂiɷk%^QdjԐ_ =@ՈAp.-I't8Bσj# Dq ^:l S*3iotBB՝a5ֽ8)R[;OܧH|Uj@7a><H6tv-뭃j" בtX =zΝU 7sgs"c ;3(~hQcI/v^6o2S>s{<*sB33zMb9Df^wi/z4as2QbXfJac 39 >{MX5;l[TL1uCXk*L8QX8p㜛rVMvqqFjI[pSi%>$wl@aL xCKT>uni2!x?8'cl [RJGPaiV ͗y7Uʮ~ 4E7 qtTX3P[iᐾzA\餛p-+J)r~`nB8Bn~ H6Q{Q}Rag^J-D"jatbpۣ֤O\H#<~c0RNJOtZEY؝-%+N`Ln ,9OzSv6# K'O&Kb֫5_jh qN@P) 86:cPC)="x''{;ȍB$R3Cϓ%&C[Yrր'0[8j8sևת`4;%j_4,(/JT[\RƁE[^=&V_91=0R7Ʊn[© #YVYD%YaSَvz. ^ x4iF1ã?R!lE(}YlƝ{(55d1^Z=rL}3_OAM="}{dppYùL$4!WBvMc0)Ӭ-". e!fڜv@m)^rK@ C㿂1?in\o/}=oh6p3дƄCBJJ槵% U(AʥPPN"(frU}fiuvuwH̾g9<ˤ"o/9|KnH5[N,MB D;t-كH<0?tN8K x6xM1vAFBSX D^rCJQǾGe '^I G('iw#?Z_)b ;^9۠O}'T*-V5mEkLڅR%Q}/dC|hy2C嵶@'6<_H(¨lM;d H5쳚7ь3pkhV;kaL[m@%O񫈤<>J["2KVo٦Ļ1Rdl+O(3֘M`W \.ſAub" VdNgB"Dn}Ǹ_/9jy= nsk@ I~DTqvvSő,RCwdKpXkS27ǟ%YLQHU@Љ`CͼIEDKUq@, wGT7>ڷB2"0ܷkU9)nL6!..#y$G|!H3;>*U8 RY]0Q.VrJ2!;#^Mլt㩔?HZ]$+, LخYLY%!|/J]0[kau-f= ~!<;Me*b#Z`M!;)}~-r885 u"pF\N BFTq@-rAzuk..MbV6sO6Y,y;(͈y UҘ& | F̔WYXH/JjNJvl!^. VCK }s*DD^¯5ߓ%5VoioP;H:dk TO^VH]T| ȝ3~4WMN쒚|i=Dg5%kD=1gFdv+eI14mIdMљ]TEIBFkK'TV0js>YTm_tN)vIalQ 2+tj/{`CJt"=_@6Rmٶ~yO J5Íj%,v6x)e@R/&%Oaҟо5uᣌnt_6Av_fzNE tqDB iy4`{")運PRKl4R-+gd<]"G+p?Bg.y2<"Ja=MA?F4HP| -$qc[ˡ\Pcp%i[Rx"eVPФ r5!bмcdO.f3HyDA=!=NW"*]/{ԟfy$SspGup;q00E6_N%m^7 9F<|'aXZ&@@:F*?STXS ExȀD?S!l!I-kQtLx.>%d[$z=gNV+7s_5oeϠ́f\e+: o4ao&r[.f"O"(߷ܪ|z^8޿M~$,(%&ŶaI`vMɺW\H8baNL7^_ 33&-hm{V rr[UΥ qnFP#鼠8Fd)gJ/1A1Yۘ"_ {1Nd*UR1r {=E۟Vc9Ko1/)`ut0Ʒh 6.)iM?;6,?2üqR@r "# pg>m^m8a"7qe7*kmiot ޴"CR●ڢ!EůB*ri2b O,Y$0,t.4 =GͯnV֏TJ.$'-JSAR?hp֝Hg3 96X|į([P.%U;SZx Dv'pp'B>gv1~wiN֪Iɩq2Z!}JJh٠e?@F 6mWzo 4 $BŔyK\R{/Cj>=7kine-Gjmpm<">:a8_OgZX› 7 y#˴%``v4f<2 Zk4I ߜ'px{.=Qf]B ӹ50.;w,Y\~ 17 |N72Д9]rAL&:j(R!a۪4.2+`xМ`c1QQ0 PQ{UI+p$O!BO(9]N}9zԭ 'o ^n`2nCwn;ShU̥};=*n06Ծ`Y#p*U>NW3h꽛ƚ3]O@E2G~}khgj? {+"KKgK:HsgQMoޘȳZt~V`,MgvWS E?GzWVDĹC^R/̏,PSd'5KCĴgQbC~-7crE\il'z+׆؀S/KBmƽCql($kTdXWR&d6$ Q쬖o^}#3NI#==Fo<%2[ ȇy)'CvH66Y4[eJב]~__VϘ=,bŪ~e bn?z룗Em*wGB ]yIoM>\=rS\'afo(y B`9ߕ9 ޼ =BPxn9$r#]'I+/ϧ-{cL]~ug _届Y@U_?EwVpS S td"g^q`3Cx} oS݊q_vR4Qkks.P;+\]#BA`"\]\c=Ica!vu zhr)*5/Sn"Xr?D]()d,ZB7[-k+ʕ._RQavblxolVULM`fi(Um)b qv3$ޘIu4YcӴaKOy4-+{\}[䒵P'u~~Cu| C$]²[sɸ_;Nm襲:fǠ.h7ܗ|`Z.N`s2 ìQ]r J+I|,4jezuĝւ>M{7:1]^w1yMߑ%(."?fuBIo)P&n% G6kc6I7ȅt6S%2V"(@5-=ySNZ뇋hCZr\HŹu~9)3<~m_T!F}x" ⡇7ʷ)S̔|"!pb4NvZ]㋼>~rLW׈ms|0OH+1;15M>ቖ߄V7Cr\HysD|Nd{sկE0%דLVS}g:~ 7~b)Uώ[~AoLdeSDwʓ:$ۓS8n_+>(YնC-L6W|=h<ʺ[TCהp7>R'qUz'KۗSEA[A(`R{evvW+*,V Q^$T0#p_~|9$ab 4*vq`.v)B !IEظf,rTY ǹ`LVc&FG9>.o>iME-f(Z)ɿ%UѬ|ӑVeWO, x]OӾJ yP?@GP+wr)ꍲ]O ~c+hIOOI1AdL5sX+}[bw``Өtt@Cgٿ2ELnIFNxƣG>V R,1 MpX>+">@_Re(Fו7KMYjqƊ<-i90I,XmC:gO.(<,S& `x2M9ܱ ֢w?_ LP*@n$/L$G-<-\DjjG1_%81*yѕHK`D1S=yد{NδIbGĆn0}˃4]׽.bU+"atNOa! b7@pć: ,[?hd=D\ay{֗o10?Q8{];c1)HOJB1߆Ky1=荪dE8UBXװ+Et@@2'SL{::ǽgʚ@pk,@F^6.xme\_%!}[\r!<¨DsTemRFDAMyD1bP3i,߁ |q˛cFLTI'n'z^Vػ9V4촍NKElD )P~33mPX&ϒXt&DbwEDd`aUҕԾ MAKvTS6_%g-n?իbT4|8@JJM:lf'j ^&p`sԪ )lzANSp$(#PfGJygQL37V׉6h)kkj?Ug1s?"x,DyOE;{nKI|>ufi=!3WBƋD|TyR>CZO5$;UX ;FK'df^s_% ѥF~)ۃ9!CD4x/Kule1i\TZ v2" ?5OpuPsR'MJȿr%S8]ThΏVG<*b]m . lÇ͵"K` G QNYRG|DCdsyTeaMk5#;x?DJ;lTk~ )%QB5mK.<`O6zo!RLdxԷ#01qwH8IN- $A%z^@},I.minDS4B/ΞP21M VB6DpĢxL^>2Du#4~_: tС ;迃oG[cXJ&JMBx­autQqt !\T'O2 }'($kX4EHdtp7JG!B2?)iTߗ`TE\CXVIC ^3bZg4 -qN>R,E]C7X!(??9v$Zrdlvmf\ bQķoMu5 t"MFu%n'B֘3X\YJz{&s h檘{s_5 skZHo91?]‹54|t;Z=NCS.7W5?7vF<%%~~EEC\Z0I.HA邰UC ]6:=*MoR=4e'ٿRѠL݆2I_'c:O*ܮ vjA*4z/{FEq6zshtjm)|Jf򝏬hU;g ikcZ ~Kꠒ{~ol1\|_= bDΞY_I/&6úT4^Ano#=zbЎ1tTP%߅/Oip5/nj//J:AX* l| 2f 0(3BTkS,`t4}ɳ SlĂW+~eH8\b kiTd6Ɯ52\C6K&=fWQi30=&sfa dH>ba8eJ-@#ֿN%>•)\݂ʚ(_&U 4/M׫_Dt8!b_Σ/jQ/x+7nFI:wjmQBKqdGʞEIY=>ƮoFta6v`z!@jW|^ ʓqRz(Hôtw`AP +kX}G4ꢥюcW@P~Vހf諡$v.WژQ43"B}AK58uk~!|B(~.Cְ'f:Y8*-^[71C5A/R3a!bbM>#vl"Ӝ,wG3OnhyQ+/·maxu26{x "{PMu)L_cӉEOA{g)AC- /-^2Lp!Zr&VJzOfC>=G|ބ Rlu;Rc>ovԹC&,eY&tBGY祈kfNl\S\RXTv? Vy2)$+x@w C?EDzNbԉgfַH`|+YE!W9#,D_Y7.WOAA۰kX6M:"X0f@PЌ54FrKWwJx^2pFMBN؈~_o]d~A5~Lc0LA+ Jʭ5 +,~ϋsn.*<[$Zkf]l7}#\bj,:< ~"lӏ:C7& _qY`S%ɦ ̄+D"xLEte \Fեzfށ=GϞ#O4Jٞ5z&āyd^\dҕռMǍl<~57׬߭ڻ4}T,h^}^/j%S;...v9%:PeзUL9Zs{(a{r9u}_Q !*r LIm;nOJpqYNomY*7U!h|GBO|L{P}3O9Qʓ:O<46/)z$zH֒6DUAE{+O6b3er5m ɴ6|@t$&lEG!+gd |VXrDڰ/eS`Vo'U:/52oxPT/?YT IrN✌hDm+ҒK[&os.GPFounޫ] Fo8_/fCO[#fK|V??/# W62u힤o!W Toe@FG?)Dpd4[߮Ϋc=qf\CHGGDS׏J5ᨽ70, ,&`v.VP*?/u`)oL},8{5wd({]%Y OVҘH^NKrK Qn_.k FĘ}ea•}ܑ.z#RRKu.< g7:όcCf{K"2' n~J ZwP+]5$G.LWE`2P+<Z蓩ҕ*.1~|esV'tB2mt=J!CGu]ocHFVne95BPWѦ1:yD%XedNmWkȇȮڷ!Gi(by}(YN*'X?}F2S!TCL277(m34}v֞~`2.&jKt+צqջ'biE6zy9XsCyLgZ5T;9~<|ZSM#C:E}g7Szhz_Sg$¥=*/իÖf39Z[м,4b:m5=0,4񞘩U SI_blưi'[!9'/X%"?b=H?N1v,|Ocxuu"m\G;>&"9 :S~ɩmlBcdhDZ kI2{A.U-kokb-#,) 3']J=8JT#g2hWb3"D8_-'1dɤ$K<?NX/Rӝ9QoƟ%S`*1ݡ,n14[$Ay0-q(C;/M4!C0<3-7YGY842Lik[EqRc8gK% *,:\f,:dر,'ao|Q(e0|ݵI(6uxx|Rs^u#-#4xZɔaCXxn{RItE?Kʑ'YJFF;sƚc;뒏L˦%,(";1ha^9 xoVBU̖&G5e,LQMQXSEd,_Eg8ը ,*hrW,gj`“<=rعQޓ_m.BU=48ϒFKN8ּz㯬poxRO\Eդ9"遇W狋=dW+w8{Ld_܈}HBRô1bԍ(% vF]&e4R]MDVbln2_kI)dF*c9/lްt_ o>[3xpm$ Nݗ ڈlif^p}W |l|"KOA5aydQԘ{xJRp<\?꬈>Tw-3UխҤ 9y@NaNn~bb%$8P*bU$8<"p*- Gk㮏v_l.I&5>YdHm.NPZR7C(@!Z "qAgQnVҏl`$DN {cޅ$G?nwj7ɏy~Ȅ'&6+}2yG7$sO15$[қNӎ)gu%ٟ3SJ׏5mb!7C mţ}_FWFz5z_܈9TˊiXb #^r>=q=,WtIEmuNw9gˌ߄_v<' %w<@kb`>zpZU0_KL/l OP=^e~_~dh8.} pRVW !^_U^xH8F &䨗Jvexx̲GN7IB ,i? ܏m8Az$O+*[?N`eY;J2`EFU`cpY8GX5"$XF1$D Hqޗ'UI +Rt~]xŏ͕x34(6VJr:³z8 ,a \ &9Dj,4\kq;xd+}Wz dzy(RBZ7KX8,V|ɂ_)x~":?}.|#HCBaڣ:-J*n ;wBb`,\j8v7 Q`YkFgꆣ+r}C6Ӽ|hV1Qٱ+g:9 pczmmPÜcu1G#']rFͰ%\hq]DDKzݽ <:Ͽ|}'Ej{9}d?'+sha\<c;thr/g0o[>,ŵjRZB /up]%"5yp 談+^ɱцbV$}# ݀ *q 98̨U;U63s{VʍF0ИyA3u .b*FMʽXqv甋aaba?+ђE#?`l"B 0+c+⯮&ƫ/bh}o;8ֈ68/PU#'Vef: Z:Xcg/L<9x ^G, l:D[K YK/nvP꧅A1H6^ U5KW#UOϋem~ >>BH#@0|c8=0LaULӝyp]T{7PTKoxw{Zܦ7eEh,WlJG@VVlRsq9WCJ .qLwPsٶϑvzD/f/Icڄ)<F{03V~dއOs:|mf~!R>"6]:,c9ߦ  I{}͈yfamhoȂ81&g ]V׊ҁ0Rʇ"a9AxSIʀORoNToLEYt?؉ vPd06Z(C!Wg/;TȅhxHXcs}?=CkOK@7 'O~O̬=#4aa !knn'0C*q&&zs 迺R7BO+Rs6zZ}1"Ƚ7OfIyV;MeGdh[s͗>~coo~wI0]pϚNJ|+ͻ|8Wё;fX pE.|/,oOf9) kR/r nvHScV%(b^?[ 9{9lzuč//OTLGX6cj !flơ7OаћN\9FLzHã q\A7P<(=29W>{1[R SX2:MLD+եE A s rPAmoѯ+Tmf4ʃ)\)R: QZ9.o/(8~!1c ѱ4V&gm0c潤#c;L-*$B+r8Qɿ5nGo__E6N >=zE')H֦ <7~NA40{?#&6RjČ)OFhg*=_d&oPN[Q$C5)66 g:}dlo{zxoHeca@~7r[c7Ґy+ QW .'dx|c_[% 0M0T;לʐk4QXM?'v7xG`W9z ?jXej~V Ev gTd/H^/d6rR3C)&h>@ rǚ4v]Lk0m%PhO `X´1vQ2%K$]ߖoȺL)J()x*3#kL|; {1ت9~ٍU^W9g<mq^jܰ(;uzń͍q-J !U*JN_'ǝVc9 ^qyzΐLi$EM6/z0;2tM]ǣ}i`9*`>ϒAtve__>y+m$c䪉XaTran4a_{5;}-3QFp9M/`re7SN֤Էd$FBŸV c2A[,y.U$sZbPMb _N1vD55xfr|!#ˬO";]=;0#[i{B|+4 } ]=0Di=vP)?J^eGxު.vIC- ]P xB b 'B6.͔oRg[މ$ThIw!* %D4~i3.ȆW0-PhpSXzT(GΕ30JlׯNہ:me)Kfp7rl$|y"Gn:Wu6lRsraMZU3B@tF%vꚃA#l C`/ 7Tg{8)z.iN ljhF\CoK[IJ$liUV[Kk+uwT;\^5F_B78ZM.y(ocC:X+Gׇz[TK&jƕg0+t G+GꯆFǂVKWkCnKS氝tAaE kAa6{Q>o7=2,. qXlV+a'[ GXy~7nd󢹤FXIK>?)PqU'N6z,kk2oȌG=0? biQ9xﴕte%|nz+;Q^ۅs+@ZkR08 ՔZrGkrL:}j'5W* y^ U ){pAIbqwv-1> `Wj04 x0_//6(> [|5@;Wl|5 Pa8T?5Wʯg-Հ%; d$ 7yofI'nNk?:LtǴPw٠B^]m㕜Y5s hUiW7/̌Qٝ"K.$:('H@k9 Mᄋ*y w$9;];JߐYi[SśDT{yRG{"zW\۪^Q_^oل#^x@>.e1.Pv5)[K8GP\ԃŨ@-{$g\`(B qZxϓ5e6֨gNJiFWVQ7Lǿ319n_LCYV=K?Ȱwzo#*3 ]6k/m#>GWKsu](! ~]SD\_>ЏBt \rX捓L@IS\lx8 H&jkjvզaNayϿf[<=Ȳ&CйǴc'E6%k۱o*kaZc6|J^Xօ]㐝%Q ;Gs]6qj. =rr s/{cMAKt3b @dx#a ~>שe5DPh(]nG!F;bO(7oXRۼISUhJswܶ8T ?!GuzSGy%W8hA&:&[6<-#ǿj Myn4=P6U7K=İ_`)[WikNvLľĊf?di~sd?9{I6:$ B'G_FiDŧ}tC ! >/dއ_~| h3r;ѥX(QN˒mt\1yN b{SޮG{U)HQ%h BمK3p\SZ^PVA8Xxp Q78tyFXe4b{BKQT8YҾOp]ӟƤOfhT9'R(kHhFH__vQ>OV`徝E}RK0^!DIDgVUOH*Pd@^ 3xRIBTd_ZTFaZK}8-'POXSu:3J CA\c.%&* H!3|Lh{pA]]^ZXVX}E T&q'J2,F: ]`#2 PXUSmUo$#2<8_-v5''Gh>@z [XqT r EHo ͆,{uXG7D~iʱv(@ys47M"n+C.a$uO&6{$:18+߸P@IgB`9K»6c]Pc'gޔ!l3¨RFc2 ӵ9'e+޴Í^ca8C$R?$ߖG@,+p{6@M왫b=iq2DXKˠ,O i-ɎgԀ J&ݻAw ^TU;1QWlI3brs"svZgE Nl 4*vaQ\QcnAT/`T(]V[E[Up* 34Q@_Eآ4L,FH g>3IJey_T"a6gpq0b "1ΊNM_'LnsgZWh)=|#\LD"F51N>t$oֻnF܆)Xoy3ܛS3 \+i Aq]d$D<_ʁoxPs!~6~!`/n4m߾NNA& \tw^?AMW DfyH343-'FUlMTp(>uu~& _vó[hmqP QWIѯ!Q$7ؽśڤV.zo,IK뀦=:>WspE ⩯7Q'yD机[J ?j3q7X:$~w#԰uRA@a/xKbH5NܱsfCzX Y x,lǯу,M%:7ƿV /CN/TpozLb!2ABBF4M5_8E4Aokޛ |@>ԁ Ŭ%u%?_- a7"jp!w* ܶ[iw^?ڼRdX1ZG2 :DmܻB/H1.ԔXEdP=$=/ذw~m$y/nCqj;RQZE E-kǙ=;g]?=۠c" DYQA+s0/-zVEo{pnۡoi#y-Gwu0a)lw@ =2^xTby5I5> ~mh\[ XoiA`MwGKۻkSp$+a`:7k5kKf|~"nh<7x6`Z" ?ٜ^dfqV|[~F55H zL3;px%PvҲH$o^I74@2Q8u?ZRh;f]YCxak%lŪSbI\cmIa֍JJ`sM8C5ߚz-UQ r$XDȮzRkx;Qo910)/Ii/~_LkkT7 J8+3 UwkҒW\ɡ#m\>09-g[#ɋ@CBTz׋uo'įd<?ӔWqM#=\@H蓞pl="p]R]U\0kM'B+M޻߉;~i|7uizma "eGR)ħ4gkz3_AܯBogu^>܏E?}J{4 4(}.Mc 0`ކn`=ެ-yR ڊ8v〗JU\[W.!f # qѕDRobۑ/]>$9hM$}e5k%HAĚ~Co/aɼaedq V%CС8Rw&Ák~mJʖ{ B2GOa3Xػe[a&Ue뇏46OHEFECHh",s/[10ok@~:BX C™* cR yh}xV^;dR h3%`5Kk! iyv}ₒ,Okx{HwrәU:eD쉜r&5 ,;BMxJt@āog8\;O@BPYgi~,NG}iz-dLvB4]1R2^ywWn*rXۭ>ĺA1HzN4bq Yx\,)GK+8`RoBY+" T5y XSYe,i xҲ?D<6j-ۃX%㯏yLN r@İQYHNgz)d, sW<;@˕ mY":ٸ-f\m6`5 )<BN|Āq7D_!1(;M6Լv$faS^R ASGKoa P/[Lzvĕ[8-p]ǒk~6~9J@x/~ oUyV E,K(gab)v ,<)n>/Pw0;qk"o&Pzz+!-t" +ӳ_W{Hд5qEbM>nx+]PMk"9t( E FU{rى76z-NXɊ=e=w@C`G6}\;)11.3k ?K3 1D MBvDdzLflXolC!K3O~Ȳ:2y'z]U I>fN>oΌmb}g$_/Α݄xk]& ecc޲WD\Bc79K?qmDρ9muwaiݣKPǼtHދEdzmצq%RȬHƝKrNbHDP^8Edrlk>7va%s~5:j>YmT;w a#`'Nm>XUϝ8"xR׆Ä:%or=ާUљ̍NJo^mqVC3`(:^ 5B9#υ^}/a m&(;,bÌ>'Nwu˅| !NM7531N;p]ފ7OȀ,QyBV wi:?۾h`9E]Aի 'X^ƳϴczQR8')(x>9 B F0n呩 &5S1%2IUR%<7Clhy$Tx忯 ="@zT5IM -*~N̈Tf  ؿ␔ G}ǖD۫yx򛧙@I5MD]TƤ$(/w>wrz(.}!9Dmw/31bFJ*S `/#ٍy]zA_pFyT__sP,ѩYdXc7ௌHK#ψP;Sj?ª8+3Gu,czjɣKhRhuQIDoPb~/Io.z4_X L_iCK7 X6ꈘ gOftLzu/n$Eeșzٔnu4xZuP`*uVkJŽXXV,$K}`RS1rm$v.T69r:R_=Oæf:r\v-{Ϫn5o[9f%tHH緈I|\or7&-3b ׶p+0%|˿T>5z=H:/>\GߕK_29hzxGኖVoփqk;XXyelj/zEk)O^ &IF1f0U/h(/׎lq2BEb5=wϚ{Kiڔj2;3%Bo5El=翢BQ&;k/|ȟH5z5JuĤէfSR+l\_T&Keٵ2%¶Qtgl- .ʔ/YGN_q+qҢCJ'VD?SRWt|"3h, |gR~S?@6DW#I}m $q;/Fgs PGPbF;O[pZevB- HfLc5q~m&/dmA2#%rԏMT/']աO(a)$" =?A`g$k3Όqe +M&"RS3EI+׌8i fg{qT4bq#RvX'?+2 u:ְFQZ нHtDHy=:}bu\9M~ۡ."qn4h2r8lje7T/oax*!wLPa#OXUej xр@x ZYNuIhTZPD(XPGf-;?b8 sVŢ$6FSwj˕GcQPfTE|/9o?w;X'`j֭bQ`%žKCFz뇩&3-޳tp>N/c wݘ^4-X>A2'#*xqmĿfт笣WR)xl]0έb\LܑlX 26;r(՘,7oiYvV,CDEbɲǴO:Fe{UV Lyti(PU[7j7kzMY=B˰5J0< vKiWP3I8[CsR@21]cz~zD)RRl4>[KM;?q-/ҷ*)C ڦ+Eum fPk{uf%|~FiǤeaX~GM5Tsq'-ՐNTTJcP8]j+m]s0K8*\U^@+3`1&IWZo4!=F7f;qbfΏዛ| G!gbıesnD_kcX>>A|K5f 7oP܏2^*'>wYT>jQחOSSz+,4~zΟ^y,dk/ {sم6ë́ݡf%Z\}ԡ1 z΄^Xџ-y$ W\ fG6N0ӮaHٚ"VRHd>3%΋1/V~-,l+z'ΐFg_&m&f{atb||, Vc<0'CPab+󋙸(0]|ڇJ_3^J-IY7xV1$fYwS%\-u8,i<ױ&A*G{R;0F2.8OУgS*~I6PWxL~3XD% )=ę2'wӥWS4%?j{[sr.i%_v(K J#ŒTdIPwzя΅YK{jլ`Zygp˧@p_ x+hGv%%t5Weק ʬ?nhœr?Pb.jgQqfٴ9Um:E z`%KNrT{T֢Fe9f1JhX$1>bc/z7%ľ.X|{9S& 0$R֝e?~[#jVҿ AqO~oWT83+֓$61tQO]J5'ގР\>A^Pr!q[B+IWN4@Ot̸( *U#IzvZ2x'"NC2$0 ]ezh?ccEh~gMu+&L AuHֹ 38Ҕu`Y?cQ `rp#cM_J+4xmzt(M!a%A͎;oܔRɌˏ:?jtdhTjzEr%} Y e2Kڱ [\6Hu&ߔ/+"c3jg9 V)|-u7_Iز벮#>=h_/L nu'}%Q)dצ?dNj,+Ʌ!q0腇"y\6Lr %Z%ie_B`jסC8=hj>2#_F3<-(^#%saP9ZZIJjjm ݡ_it.'&6(LS; 5swHpC.lœ4Sǀ!>^ZTJe lo)ޓEmL_j98.1CO81 n!FV]ý.H7\e;CT=H; o t8妶 K5kD+Na%6|4aCC~ ,g%"lRA0u꫃7BgS^x{ ;o.*9NXVFÌ [ pk9Mכ+4Vk;B;2}rs#uҺqle^In&n<~y#m.tj%G8Tijњ]: <"UhCeA-K˧5 O=Mǣ?EP{\xRg][L.2ꏪa9  ] ))K^{$nZ1c Њ f]tS˙뒍7*_GcSe{e=w+}u$瓱B~RVzB8G/o4y^H^V=VE\,D%ǚZ~b\q5l~ni!{l,BGS^}/,a_q$lzAM`:49($ dP }ѭ\騱[j{f-*reqQ%fP6 2iJ6Y*kRQ ƔVbU+-Ϲ={ EB;زORZz}7f?ЭQ%/I"G%H=ihRcnaɟ;hsO͐2 UZ((k1 Ki_^U8S1 ᮛ7hSu}w~!u[xڙBw#oz9NH0c" ~~F[R($.nV’jחb1 h:'EHC!}\`w# oa|!Dt R!rP VYT^)mP?+aX17Q뤦-QZx7?O׶Y_ [{*7qR] -լ$ ve31)riH" +h k@0~Z C|47e~b1D\^9ZBP9`΃NhbU] ҨѪ$Iċ<>er`n;8 w276G,&Ao>a_[gQg|. 6A\ \M}|I pnN"\-mɫ\Q,mpbSVڥɫCA#ߑ/I3:ߑ( )k7AwFnJUyg*CyJ6_v#<,coLKvu \{ ;NA]շPsWqxOzbE|kfXf:ۘ]Je%|W6yI I޵Q ſ~#B־X+y5mzڇ\*y6 b(lXYx _\uZ0G[]2P jGx'ˈop¹_ ;L3Fs'`eJگl$݄="F/:HWu{_+v#DD.Byl?X̱ z.x/#ݲL WCKN=I -_+Zm:CC"Ra޼9<~XIeRjP~$c[µXSK?UIŗu賆|qƚ-=.Yz!{GaE2# c3-q~I4*/R[ZD|.\d}6  $Ӓƀ(H޺t)I%XMw4a kIOO5m ZbcCv/𼁷{kҵ{=h {\.I92p 2(=uKupi}H};PEe:YI8zܷc'^ /hXd/7d1oPLy"|r|l87 p0R5v%م45#6{fE,Vv6>K>H[86h0㴺 '-'_|xWL\4_CuJ.U\}ϾvZMi":qe8o#J/q#\$R8ji2nSawTHH>uZހ٠eq]s5Tt#&,,IJ|:PͲ3nSa{x'R3t&ƾ%E` }.~zK8J1EwUθE.ɭnc쑫sSͱR'#JL=Zo۳+8PQ`&^l]?wme̡cHEKz!dkdT(3G Ã|0}x%)*78ϥoCnd9-<6s[/H{j(̙Nd0v ~2z5zɪ`4 - E^Ib~"}t,#2"!KqXS`"G_Mī붵,|ϥ'F=nnI _mUt|c o{kQA|zc沫h2ۅmbYHBG4&**jϧL+n[ݳ~C^NK5},n7rl\iOoxDmҝ7_1ygA |0M+]KIC:Y)7C|t)bb7[+WPoPeU DRm#=@;&&Khdݱ cđ %l_6Psa<X􂌱{b_ 1F' z?=TWml^4庫Xa 5}XW")'k`2ؘ/2]PH T>==1!ߖ$a̧! H<8w TrW8/mˉڜ/$&;Ji1QZ+ll5ئ`vT+H?U`iQ#c 8pϾC07X"=דuSemnv<r%KҬg5}w9h7HoV7}|t4V' :iL8'1|r JV4ܨ$z)\IyMQ[7ξ6?[n+rt3"!BF~":\t+F-e{K14 kĨv T׬o|N0)^^n5]]J=J> |Ü1ܱ@Lfo$)0_:<9hվ>pS2OA%V<%EP5'9e߼Wgmvw8H_+LQb͖0U*w]IKGo^&Sc4k,,OD0`y5<5:ņaMq;ws^6 ltwqR=cIFo0Xͤ_{krnO 3[A}' D'זrѱx\G&(l Y ݃t}( 7Vr ̑G5l܃҆9@ly~'(^z@V9:c^ؗ>jԾG?fEDh߻"F>AԀ-! @吼o0`f4VwOFU(xto\<*}va,a)5cb/x|q;ftӵ(tW8A=PSxULeg|Gށ»̜C:w ;KkM$_7+|6ͣ(` ϿEySiQf" i!ARc9wKe#@kXWO\: To֐J%cxφ c*C 9k(Ɂl }K?o4aJ٧?$}s湁 pKGX;TWZ,QVC9-ݳO"m2f/␲ ,6 ^y+揦@$K*2eY3x !^QQDB#4%B'7^PX)dKVLB~|\fc*lnP𥘀>s?\+RbX&Qe_.!X$pY)p/>X{ iP:ěFs}\^Ӆr; f U F}㲛g={(d& j@BFtv*f*]`jGWopŽ#YD_w@t5WzQ 6ݙU!I9hVI#/-Ÿ/ ;S=~p`7WTJx4zgP2~L^߀Yd"O-ь\#Z_ABPHzJ xYQ/IƠfӞ@w4U#aPMNʍi.$[qM~|AP@ط&23ԃgD )A鄚&j5IH&Oۤ_7V 쯯>{O&A  6=d<μ]IpT Y%y@,.3ZPșʡoU=p^vBzWWLYW@txgQCHRaԲ; q?˵?˻LPI>%>Oq &'4jbP sws-̬ٗHrdDGʗ)sˬu\11gdHzܒ@fYe)oK,s N c= ݨf}pZV}.q՛Vn9 mB=w:ڢ50+Cfmrb1J*aX 1j jt,\p8a;\ż(L?h1Y;yLYl>A cczCljcJt'rVpl4I -%2- mt$|]~~ۣ|mriI:%<'̟;ʴUwҼ~`vg_b^ +}!59|:34?.ECbm&/ UVC͍!c}WUZ+"?*˗yH˓9w te`8Nb0q/6ekyRM5F3ʼ#K,udvneoZm2XXljM{wԙ3|d||7M7 O daȜ36Gƫ=n_P/5Vh&Rq$R?PQ,\+iYi\`dwlj*쭝.8dHD/`_J&l$jS]4"&/.+M1ʄgAD]F\o<,bfq~[B2o eep&p4Gh^1UO40r}UұLRgɱ[-j=ZV(w:TQ'uI%.WPuT%\b=) pl  HbG)V/t3*:r@W >oå*vjhP>V6m7'6kbh!-^+~>dLUgAƊ#$[oKeqaT=մ{ sۛA׉jt6fu-TTf:ݦAW >i~`Q[ǒ.}˂zgF(9E|_W S IPB"U1@kZ}%cB_tZڣ$;ž㿳K |8&:xYuα3~ ?6U ES7 λʡG"2EW_%J!f>yOS8;wV~9.Gߪ3E01e`|Gl>ָDX/(^:xooh;,ut=s{K'{r
&gh2_ ΍ʼnU17V,ο oHlxSXW@BdWf vdI >bQ1 y/ᇤVJAxqx֜ķ؁̧//pӑFB_>'Av#P>(:>F\p~f6QZCyDt9FZ82i=Q@Po8+w[1d;Ŕ3 ?C[}:& B{`0fƘN_3jO^GFKiF>VG#xV=~0U*1Kw;׵wE杷. :l?L[Z<>YXV<0hNx$B@: ryRlz 3n~uM3f- MY:[)F _ҍ r.h6& `+3ȃ#E`jzq&L hPtr4ÕY0^ KY*q4 %gYҗӦR3iJYSI=:d OͷĕFO 9nο HC5wEECTA?s ~avџg!tsCfuTnS VY`sQh4xwd8GG<㺷c0&f3t/fZhLڣ[॑>׵H. ,/>n. qyS3?֕ngw8Z~ : 4ޢ+:ɭˊ[:*:_nY4dʀP/.؅~]9}{áWA:G+%r{Ukd)oR'84K?Y{(&j#x$ozB)ci(,M1o% UDKK螚@!M9 ܻM4-R%b]"jTװ#Sѝ ν߿e6MHRk\$~H;$@AF/\bWD˯]WtqjTEJ)lad`?~D}9#U:;(j} "{~1wȫ[3R/k+2¤+]-EqkÚ42kJ^H]7-J䜍4CL_~3i }>s~/ߝ^n)=rhep͖:{׻ضmv],4m~!Z7?)1$}o$B u!FNҾs- 2gs|bYڮ_ɛУ=A76fAc7F_ih[4#}3sY|3|Gynlϣ*P kѬ]bcޗ ]zhH5p3hBTnbU0t'N7ćT<ȒJ`Z,qQ; ˅]ZI$w3iOZ"1a)c[鉀dڇn4%h2,ٯ 똗ӝb3Y ƱR)ִ~&:K׽KZ?Ko@70ܪ]%MX X>bY_yI mZAa<Ṟ!a?ÿyh7} n\".w6Q>ћ4æM93 %2t h~t6ˉ:zDD>4;`J@Xu4* P͑~/[:4e 8-6*.ܘ!P֓%_w]ba XgPbX!C$^,ɷ& o CO^*Gu'' ԊWG:ْD|BIT'bUBL? O6X9M o9^{8/M;g* ( IkO$wH!\Y7҅ K_5+kJUxYTeТ [O4jG  ^08ҊQKCI/A*}).dm[ia_յd cepv'ܬPt!A¦gb^AhdYK#85Z`oBϷ7iAaEI+[b[Gs78JL=&us7у[km>֜sÈXkƣ:XM= NS: _ =ĺkn2OD>Wy:ԕ4'otWIqH}^ hYf*ۃ$V{aN4R,w_5AUIHw%i04óUP#M}_2#\~4hVPv?NkΫ:+ 2iTG%H0ڜGM.,6&RYyiu9/;3o@OWV<x79T=#u"Sld6:Ob1=aٮBw2d;˼41MOJ.dh(!ͩ@.>XP񎛏K7/PX2xFcWuH8fɫg*LC6v|BXo?dmuuQ8ZJp6ܙ܍ @'(lVw.l{/zG'o kʬb & >)[K Y;ڣіuҬPP~n"$2l±i/27?o 03R)eEl#UNٱ ExpĬ m%f j("֋l\(4phC zu::pH;(*鄰k'SSWvS;@(ΘۛOlУ^v΍yK IT'DӘR-j5\1Hq` }?K72;Y `ڵ|^yb &c蔭5a)΃xEpsP>!3UxJ'@:XE9j׽6.w%G>:ҧlm֐X>|Pԇh+HEvblXd,Fh*bSHs`iU͸9&&ϽWFiв g gݫ'X$K!g_%ힻKLxB]݂~g):${ʨPN QEm_^dT]NIH}Ww9xorA]|ZGBnEM%7P( ~maz m/m;>`ʐ"Rqu ]É[.%i$tYIe 0VQ }iM' X}ڳ-_j82Fv5RTnlSQKvmpÏ3A6J[zlrMsTh[|zzD\5D!1I\)dЛ\c:I=i(f0j|j+}[VJ<hwZ}WA)wTXh`(~[a{a\]cWT/=:SylxARǧ-Q_Vo;*Aʚz~=ŝz[^[}CJ=x5qD?Ց* h`IgLs6}sH%O74}D%tAS(~K:7w6L_h|:BLaжnSBAV,ς r*K$D[~].uzDI}EZ@h?}:_$5'Hnz8v>!pl4?.vSPzb b}YC$Z_Ի7t|}XiШ A 4v+nX4g km-aIf;թ@G#7D[x zaAt!a7I DjtW߆C4TwnaQhntc|іvhy91 ǭek@ߚ7c40\cB]#Q=4RnҞ{A`H^j"Dž;JzW/VkIĬ\/ 0M<Tv< :^350a+zn]"{ d SF?@' =@Lص*M A>tǶLM% u,{C%lRv8 })I2JXn9"Alt'WvG,_ GȚћ>]qYt0شm/ V$Q'ecqfxco[ GqjSIPXgEL㖯(wz-\InvJk]dj Md'OX "Oz6}!{L#_>4iX3J6jN.-1fo3!pc,ʻf;M"mS̑lta,(6)"[WOM2c)&w7>Jx5!K Z3H6re@T,&ןVD {lD'p;mvKiYXh^Rrc,4CfXuG*% wjA4mZ|@ĸ.˷$_㾾_JhV: +Z95^|~n:.ƒ\\ѳ7,'H R>>HzXhc₡$:^V\q^_}&Cv,M@+ gѶ^ _ZgМn\=W'Jz$f UA:[v7foP1UJnn:]to.N>S"?~kwbZZc Nwo Ma֧ڍh,?PyÏif8btfqI G|zcO\4Z(6|uh .YnHs+[p%waH]KX $pwS&7 D IaQfBfYq;H'叫HYnRM2y_Pcdz\~~loJD˰@#@gە/ʜ6΃ׇx{y D#"E&ISXIA6+&[Ev'GV3 {m#.`G zEuƟHaI6=Dحi(qSn$IQsҋ@ "YDtNKNMß?)X{? fW8$dݥO cE ` sߟeħh*߿ȸ*+(=M(0#gh8~3Q\/SvwFr0D=mFc|Y;ߣ%Dg*]UNROAdC}%/ Ed78|'KX}YgCn↝<q6p{XrƋ$df1J{O}D gb4vY*8ϳ3?2 xY$SaP;LF6v)^Z0%"Mftl1oqz{0`_?ίݽai~[}8f\I>ћ(49<)2)fo\)pUަ#ODkt-J3t]G`D⫈]BG+ !@:x#EJ1>fσm_'c_4s -^V'L%;,I8=&6C;ʧ"nDAHkA㲍GS32wF hv T>s"dﱇ?Hhfb6߇_gcVhb?AޥrVkI)_Ƶ4/_ȸeKW<@v6c- h-0}xhmXJdc#,:򷚩/:R`],[M[܏C ڣbUِqݥimR}`bBZWr1"=4 (jȯĮ?mSW+EfPܗlk" -RGDq;#c$j+a)軔_ZJsM][Χ _8'~0P'o|6*/ҧM^,36 h|o9)[/ h~7/4_a:8<샏ei\`䆦 E rP`/BlÉ5f'r~!PebF_nВH@ߨ\ŝpB781&ky]n'8]τm} hgA4qz~jNֳ<_Eҋǐ,|7wV{0doBL9 ֨Għ7!=fھO_ݐ&b|{ TTùﹳʂp$xՁ)_+E$EYVCPYԮ7{Yr?uPG(}>4n,˙$!.C?C8 z)m96އ ]r.?eUvIY:,* a9c7dialHCg+Ry&p#πoO><{}Q͜sNX6>D0E)u;7ɿa<ׇ)wuUͨa-bv <(ift +o`OXڏ>mR2SS<Kb<Qv%=L"h- QIU/3q\qG֠,'_owUouFc f˦^T/j"5.Eԕt3hHD&Z-5|>6XQW{~'CMRo5 ]uv1s"`ZwsY|ຂ[B ϋ淘SƁՒQg4IStmMGпTò}aA\ukA[1RXd S%ggGE~v>3Ilj Xjt]G Yb:‚DL=Н3e,M.]6BS|b$ dsj| ][Bh2]rimQޮXWuT:{+?`"DCT Y81 4]r1|>Hm-1kKҁRf/L pG:[VG0Tj-gl298UQZg!-ܮodG]*T|'Wwa?"+F~K:kí=t䍥cSjeNFƆHj}g[FOw@z4. BPC^EbpdFm|.rVɫA3OIk{%7gX@rGK}^^ z_2|olVYWܰ8 7> ΋L33_~ ͷ0Ksoψ>/眓y?ŷXahҿCٯF`t|"wh@TOC,+teC$?y\f͍/׷wca^iuΥC 컵~vqtyĒk_ٛ[_ʦ7d2 JdRJZN7 ʜAe(i4PP'M>7[XOx['9## 0%xm&Ո =@*S_M%$OCԓ4وD1?;RpE&(٤/=zc&\nηFre }I6Y&؍l/MM@M`,?ƔslizB7h. y˰9ȖIij\sq&. ۞3TLэn2$pȬCyby%X0\"P~y*u=HQ|ve~9UQj"9㊼wr+5Ҥ wg`.:QtMKY .(i%bQ n/j(,= QA5 㠵D 'd_l&9QH |zwkPMꃃ~@@8 d]l6j{-fx@Esaz dP?yǡܯD4o7}rR t[62$[Rݤ NWe~",Kč@? w7/$VP$'F{3cLH]f뇑}=ڋמpB8YH Bx)xlR>vȆ]Ch#bWWNF1kOYrPʩ=!xqq w/[[]G1}NE;[++/;=U y/^D, Y3}{|'2 FǣKRq=6=^{,v/Vߤh_*gH/4z7h!hj_4K=!v:kNZ"*ΞE1Fr|XRLNV̻Ҿc멡`*QbH |[~k"ןNW\-OI<+yܳ7LqN/s Bp"7ӶrM}پ㾺";v/Z#=xH@<|˾_.! 7sɰ4 Niv4޴><Ț$f0;#ΉCQ5BIuQu%KY6e(˹ovP !`^:xJ;%cGr0I'k{z f[ыb P!`vEOT%:WY7whxcdg]bx*^͜[_944)R* P)5ad >T&s2תqaQ;{?e7ZMޢh@o?!_U=}_L)ݟ1W k.-9oKV&G~l1xK9 $ld}0p׆y_j>s[}K8(9 MP0C2m {lzwO?$ٷfDOX+l#e'j[B<;7S$5O=ZDEF k%˶N dN-3Ќ7/P'ÿ}VY 0dc!8"0i@)yV|OB#~;N2[c.o#s382x=\eL yƋ[B֫!{(`(-%";ˀ̋ +P})xทj#Uj v 65Q8EY-Ky_k>YЭQXS`2K:IX~̕io=2GV1-nqx]oA=]9>)vO絟./UNWt|equڰ,9T#B=D}φgg0vA|! n{=`S>Bp459j|xHVvsqXQC+ɯ_ %IYH!v"zͷ9CH0׈kK"$Ieo1LYkP0Fv>6iqHJ|?j$5r>#nޤyWnG/czhD+m++~EAyN0V{Va<2Q} 3Y;B?.:¸bsML=<~PZZf @&f>l틝_OEL>˫5! _}1{:@b@bނ oﳺ;~ٿC:/A_*ӣB @dsEk?6mz5/Q~˗`͏?5u}{fAts%]NjCîGYg󋁅Lup5`lPִgRl 4fD^ƊUml@NN; fTh7^@KJ84r=w%r|$/S8[i &o6`us)e3y3ӎI8b߀*~!l)I[vc٘zT<K!IA8 /Y@ŷE`&Wamʑ.JZ8 d1[ -?%T}L;L6~z5+D-oRY&;\ՌEwF^fWSZ;gDoE{-ʗ{u$A?[h)` ?KXȬoa>6:1OC6צ{ DG93:ƫF\ņT6૫\| rmGpue#|g چ||Ε%ӳQ@}o 4u's:A{=w Z5DH@o.$&TnafֱC,.{TV<[Kpq|#Fn%4̷#:=uxXBedK ;B~\%$fA1ر;ULl}޵<ն+5STI>X$)A| v{6:bM$ D :X \P$x'RagJIΏ 'Dcsf&6=8 Sy7sd U5q#$R! [^v7CG{\⋾C`~%q:O2*CץGvFbH#Q?i%tpT?glq8 SO4/0:Yos~;?VVR[8^V V qEh¡=:[ drOZN 3#u;6ҷ`w1@nlhݘ;~7-zĿu?38[RxH[-;t2%]9 1+կ6g>KKpӕ_Cp6AV\Vx?t t>o3Uee~l+'@MK5~ղ휁|f .ixs$6dQ2?"z|٘D[!(842=_!=+s}v [}'_ۡe!^ͱb3X6+cѶ=(q'q OA5=u77K.q~PeՌ,pYC\+wPjs(tRW [*nT Bc13W$55:$1 E+V}aM{ήI"M> X88 # 5[Jb5ſ2 uъ#J6fr__g}{ιC߼=%sS DD]Ǒ[}vQѮ%)5:ݒmIzL+/A5sT#ڶnwY,$ޒy.5*.cq}g˄P0J/$u7AeRMFJ|t f0I]FCE1ZЌy up+h>$ڔO,N$9^e,_}#4ewOf4&\%DIO`SMCZGeVeϴ-'^$_NcL]chjqOnk/MtfQ c5>uBG2smV0=E϶堈'7HV02e.~ B 0\P78Z9i~kj!vw-tҙS-Ҭ\0G:P5a1–s13Qmq)_l_/b_`vWnF0S Ma^8 zkcLEIƙl;Љ#E[!`o U |uFnnaAj,2s6oDTZ+ރ]uÀ&SQ (E1kq]%e,\ikhe{o#Q+u}(c[^)j\.矷{FYzjdof$[l{c-"ӨrIgC}$) WU|(,툛_w=LYˉV5Uv]wY[*PRQT' XY \Y̌&@LYe[q(]ڢػt-џ5;`;~ d9E%W[574غ`ߟՂ2Ϡ5 ?eHu5\ӢؘhhX#1UΗ"TCjHK2G&cf}uc=vs^ _Z:xʳ(@YS=J_/.tN\USٵf*VѲi޵s  ?gOENXRiLͦo2Z'KZyu-p^6x CRzU+ق>=6W -o>?fiYwp G0 k{VÉ s22k#qUk&-^;ĭg$-h#@_-R@\bw3WtF⌆3&vScE">f5ټ#BݡŭI6wnsZiXyJr.G5͖Euo1*y}@I7@̓U9Ԫm4( =<e{IXUJ2nջB.sк#mu1jo:<_s>)cLi[_Ћ'nr{k14غjBC:d;\>EDkv<&l[0Hvٓd-40ą]UElb^r0ƃoՃ8BΓ艡eCwdn|0\lor`y:ĎLG%*7XCXqZk݇4PYB,$fMXH H?tw܁B9{l,8 7dV9a7„04'UR B5R/,Nm6 $#brx{񼍇gÕ zO MxYiDu'5 qޞ {䡺3Q_^$Zʓ׳,(k^iG=o(~Oahyoj Cӝfn$0PnqГԭ"J O}[Dm5ߩ|dwS\Grye2?ao1J{:a|^^1M)Npen}xҳ/Y\\ȨX<819'sq9;pS&<0K6W3=WjFJ  =rp5,ɘ"`92)E)Dz*.Ͳί~'=Mx{LܖXz fH|xt7"sjqsA4JK7Cus^; +=/TvQ mɜ=TMiu])~~A|a{Q {qq۵Axo[izL\ :뙥3㙥r;c0fL:Hd۳'Φ"^\U0By[X1߀/ׯ~(0K/NI~@/.c?4%CúhpQ$op?Ʃ{~=38L{c2}=qSqWw_#Lb*өbEo"q1Eޘ>89C?KGp%P^_s+]dPHmepH=oG4Nowq|_0ůMgx|럏om1a>nmL~bnV$~1VB6_ӢA C]|3qo7?#tB?/Ő |H8=|lގ?+g~|p?Vc>SSca>]rn>?` #gYȏ0J4 0&%G> |(ڣgWSѵ> *rg2Mp"lzm|*~P0Mf:+/ӨW?Gg1:&\ÍC MXBcҀ\WC~Ð/nGyJگ.v7qr83/_Sɯ@Mz\W%o?7CWQ)+r m qmscz~>S'#Fh׿ACo¿ IrG/)&зVTC¿Z;!(W ;#I&Mr?y ~Hb7:"?0߸/? Jji(D>#|C~N EhScTѯTG~?~" !?3_?%HBVVpc_rw :T}Tc:H(+$i+ 3 ǘhah7 a=*zưS݊"u8Vv|hc)싋CQwۦG>2ew!#Ah!ʾȓq ĉxUD{C27P|O(G: SGBpߌFRR6 /uneR(o󟏎Go]Cv:bcB6Tzf#v7-(&0#u_}2ء\F?e) I8)sh8l/0F4|ŽqoF;f_[\}g] }źk[yR~c;[?@ޢw늤U?}uEA~E{?Pw%c~_J>xЇo19Ҙ߯+@"r8kW(CvE0LE]os c`8 A|?+@i"?ىӐ?)c6E&0LϋT0E`g{?_`|a'o0~`ǃ#}P}WgtiݎiD/^! ?%_/&G0sӟm  đ~I|~ F))G?`]MYa!( ?|?|W97Oˡțc}iەUcgM|%chDDDe+GQ~'|?5[?9xO^#B#\Sï>GRMȠok$ .F!atՍ[ ߧ#_VO@Bg!/F?7 )g ) iRE{mWY]~]rI{!W;%wS@o9Կ&A|p!z9X*i;#v#J0Ȉ[0`Ϧ[ MqDŏM#M_l"/ Go&aE Ry[=/ܛ}6Y8o{U~OC?14;f_P&½.|`;5U +Y~՜4 #M?m|_o~/+_T,×E2W6G+o?g!~~S(< qꭝ}SY߇M#0%4 WH@$?7p>}?~᫛Ec c_aMӵ#p<f_^/{>_|>}>.×\z}ap d1!!p*P˱ [, dz8}mZҧ97,e`AJ˲/,N[q :gh)nǹ鸳.g`ȱ1.]XOp[ٹ ]ʶw"HXyA@s? B Co2Kxkdo#m#yВU>3+R7r@5A"z/8-&r͞ΖveyDU--Y ͱ'lGXx(?þ zp'}H_,ξkZ7Xܾ=$6<\P:UQYT73/Ii^np(3*rMߊkܪ;' MKgԿ^u\SDU勂7Ses m۝cˈ;r`գ\N[ݺ*Ub6u(W~TqǾ>,95_nzts}S@f9IW:|Z 1 pHD 2O:&\$PX-]`nlqZ`LEG8Wp;-G$D#ѹąy# Fm70ݓ q'pP $c3 A1ǧLs|{?%i3C^ŧ^O[㘨}I^ %K̑$<0 X g4b`YVJu2|Ћt+JFp9cb~>%Iw~ԈyZn{?)[]-3|EP ѩ⹽:sҐaT(>t߃R֊F%je ;Yp}eM)iޞؼK x /]naLrزFC^4k@3-IBU5zʆI9mEݕzyR 04H+Z]?>^+9]M?N#&[POGi`9n?<8T%J0{ҠvuEu}l^-ep#+{MNRNe:sG=PSkD?{ :_JZq˛? (Q!:>O'ԝ~8b=)[YP-L$4Ʊݼ#Wzz@(2ٙWu\ IQp].//OD\Da\Fk`< E R=EY6_UVfDQO0-0Si-+2WgTta =OR<+!툍 Mo#'Wˍ)Ko!lZ4'[;( ٤JAXo`6dn=R^!MX8ѱ^(MV6=FX7)Ƌ.ZNY7dR3@ ӧ$GxI+y8Z@ |FG( .SUdnv0}*gJdo?C+oΏΡ*b[Y7}%-&% s_`&saJeU^/;}Mf 2k,5:}9 ֒GQ+EhOmňi @ m/P1[4rZ^l$1U`zURJNׄgv*6℧?=83]yK09ٽB~h))0"f5v4(yUW=]i1o0<.25K,qmÞx<2f+S}{Jm^v7sHiS,(.Ȓ,p,}ЧE\M@6(pyU7f7/!^y:lclg.@<'g:IΤlt\\fD׳.t䡝\y{~d!4ᐦqDeV/:IGzZZn%kc8AbLm4MV#peAfѴ@6* S7.Vt:hi tIúB%?/qJoK1:S#wGy/vk>PqvbO٢#N뜛)_wdn4J:]'u|<'jz.q#c:mHyc4>@wY'4dܞ&:s-la?s5hlewtܼYI ZfJe $WKK ߆Au<ר;`;kj G`ya,}nGy;Sf g~:;/ut63*{rc:z[)mz:Q@V q@:`k9HYi"dWJ}2h\?1@~UYɢnح+W.RSZ> Yr{M.gl95vكERd zS=`O`k4 eg&j֧_Zd bh]|(%kwI/׮|Uw&\+L*5㪹yz>Hsyj}qGai$z2mⅿgRtMOPuBIg\y Qc1xe}e ^^\^{TfF E?Ne^*_ J&Ar޵h|+e娇2G~nJ`9(j 2H΢`_$vM1UQjҾ,ײEe[O&54 ftWHD 06_87ǻ'EHBZ‹;P0Jm +|?dx]Ĩu76TmbQa1*pGU:ךH HcK!SD~s2ӍR']O+CP j9_+Z*W hW^RY5T։M*x#6߂!HF'ԓ?YJcgF"xN m!eYߕG/V 6Yhmja'=tDm6Ә;i U$8/UNS'} PBNCj @aVM=;+ӥX-폼:Kay)3P/gv4J\+3LbD}/DpTsm*'X ,XqxƋUyAHI :R8m7`zEP.:n?-tSOlZ[6t](i҄>1mn~YY\#dr-VzX2>iD[zl$ WX38g3C!6l՟7]*[$옝'<{l7D̽ NV-0S,d?q <|*lHfZ\=5bw43SzE %V|n %T.- gkfuIneHV *'2^b)7-v+r$ݻ* Rq9x$ODiFܺHp$<'GX> j5߃8"]҂;V w nyj. m-rs3.&~٥R=¤ E6uhY%oƙs:^0:@&4G~nOwf)#"if{$YUZ5D{ӫU'5`Tm_ /$R g蹬uMWwڽ B3S:4e| N}5ecs Y=X FJ/9\45e' vDH,1.[)/:J/j25H >~nIYǞn=zG9=BVrial yM;ːJKeFr{cF g,nU)M;8y oS<ڥ9\x} )>A,Xh@'ǀs6u# ^pW4fהD{x[4N" Πz lSzdzr *, ͳuT=_$<bM_ϟeY6Hɋ4 ttR?\pC'>0|5K!Ϗ,13=3&ԷFm}Uѹp~lv=na2+ u:Bs@sY&F\%.'*_N[F׸^w1P7+[Ӂ+lr {.YĘql 7Iʵh%rllF4$!j3'<[{vp(c ^0ftCGu~^"ӝZ5cӺdr3JWOt!̘qNP ͱu-۹X \WyW /'eM =@jJȔX[R5oi{q#!4-46ۙٚkSm?SnHʏKZƮTRC<8@L$? fJ⫉9 3"\hlAN0.=]Òmg6kR6} >ʠw![jG*3IJ+HD 5'XA H-z{ WC:z۝ѧ]f!ed h4[gD)ZlbP*uH%L&" `{)N5ofd{L\%g~,Bmzv x)'OkKiәKHe l)n#"4VPþ/'#N U%Sv"Ypƅ)d8#Z8e,W?lj%CaDHHZ#nIuIT򂹌axsX+Rg;OϏn:i;FZ. [vw.Kc/xB;W Bݟh>I(j%k;IƑj%o&{t|@3pI&s^lәh U~Po*(i|<\c"s+?I!Ok\JaSzTZzlpvx{?jDаH]]s 6JTm­!vpI\\Jp>]Tqp*4 t .?lif]޲TNt)] $_GDi G`I4A5G١(n2ݦeqp~mz?*zC%)#'ʿinl+.1gfF*1ayK)'cj-ԃM7So*m>cI o+ U#b\7=Xƞ]xR=m&l P[pX@xٞ'Wݕ\2՞]&=.}!3:$rLOs7mm WFˑJW>0!{BƮclvfvMI.QG%.Ͱ $=#Xۤg}۵5;~M%E4%`=`GqAYwul6T-v6"L9;)GlD.Gˣ,N `JhkG5MHElMlZt1eq\%ݑѶ=7Qa_T<J o67Ewp^n3RpOk+qJ3[ 2:u2@u'-пؽD(Lڭͳ\bP i6mwdš?4eV{yX H([cE}K?rh).Є e1>&MxHIzD."HKs+uɇ=$Y?]>fk%䜘05^CC0,1@UW^1׵4~H ėVgƻM35|]Ƹ}.%B.GH( ši =-gOp= !W>ȼ>(>=Teʱ$-v$Ѩ`k ҘBUK\A5=v|6A)4l.R lHc$/" 6өoR,#e @ Le5tOtx*tgxMuNҡ[4Nٌ!M)0i8RPfxkT&ƾt@H⃸,փHD%DTPt⍖xt=FLw8~XIJ/Yyii:eb!"m&AG&e[4d_n% ݭϷ'ѷ69I,Wc npҁ_gYOprOFABFgbn\&XE#cqd LMJX5$/uoE冄bV\LVk<ҫ<$C:ܣ%(xro{l _%hx^8bSE'0Н1Cy+KoIu{sRUfm>7~UOm?qx,Qw3XYq_>J+)P%l{ aDLZ;̯8`"ut,/0d VNSNJD;VZX8d;My4{K_U{w0){)1g!b|O^( j;L $a WUA۞zwcHI ¹z(~ϗ̐ %<d>ٍq;XxCb |*7+yX|0Fw&F򵬭CY,H'2x^8U䄄zkuzB0\"| !V}X,Ȝ\T9E[¤~Gd P ƺ=g/Caxqv̳>Sʇ-Žl/9J )ُ_j0]8E}/оqye[9FƤaPMрN>,!݀C=|Ld7r)a7fG^rF\3eMM@-b(95h V! AMv_UEy $wmlVg=}m$N4|r<ʌ-rzo,5h>ݮػ,*Ǝ ^Q$o 1eu^A"PZ$gil'!sD'| ,CtJfp祒˳n-Af;Ȏ8$L_JFN,&H3ź0k @wCu-B&tr*QoRqKŧL[~7(Ȁ[#|3x 21K]>;YG{i#wE1WŠ1MԨEE3[ggZcbn C%| )Lu e.?;0ȌB>d٨;[nB(;ɷ1(fNFWQ&iAD1JiϠW$s=qɁzqo5۾RRNo=,:OR¾rz![jJ j ^iN8jL`VHM oHO4,PNW~lENI$+4RFB(4$vt=z;cW>@Qg/x: `|_V_xc|óTG+ɞb4>7O'$)bԈGܕY}oGI^``"8#_L%VB?P!Ѧcrs(;́F^ի$^[ѐӚ] mR]щU 9'j?פ&mNއS3 wX Cv{IxQjauCzޱB&A>_3q 4k}^Bz*pۇѷe:k>>5UBJ)ϝ=* ըUwG{ ֺۗ6=/#~+"6c}#˴KEwk0M~wgN .h~^}ɰșC6jN GYoxv~aۭ-Dz ajԗ`g563Tnmp:}9j0dwbnv4 %w W/XS1_f>:ɫXVa1o™|3R{OW8ỳᡛcqX:c {ak;C:qM$ 1ΤN&Bo7$}Z(+<|gz* E{ IflcF$GuuUϗJmyW3Z|#4*jG'rX9XoRG{lZ*1oq30ZEߐ>'`Շ@ꍴw4Տ;V\EwV+pՑ?,ImLb`$, ߀j>D0}e^ނ6AycPǦ(~HgUalhO"JmU'&ҡcq}v<5POE\ROc\)fPb!i2OHaƛU4Cx>"+HjJ10~3ޮK(TփM>M4\$>XID'$K8O4'i$@r6Oo>P"DjoSo2ȠV,oF|}lPI)~p ]ì?M)$C{TV$~Q`W2a`ʇIT6,0vx{ix)gC*q??0NU;ݎ.3vܜl^!wni4`_ K +|mLy(0#:ʇlaH$v)ҝiYR>ǢPӻPhSr#ʞ:|АZȤCg|й/2WMXx Ҏ= ɍ-)A`#x;BGEqZrp3=L7f p$8YHۣ#tOmʆǍ\Sף'KpzPt$o. qd8#PU(/%1FD{)EJ}ꮯ%~ȽRFZ&MkL l,)Ug-+Pez$:m;CG,>ƻ|AN']Z4 y0W` . 6E4G<_\D<Udf:vc-%*]hg 73HEqV`Gl)-&pq/aVEVd6 c!w8GOۉAHBhMޑ{zl~(/UIg/C]7q4>;̶ќ0!JVi6rZ8Fޜ|OEؠ*M%^A%gaEWB~Czm=CNבxEp|*8C-ѹjw3QY%1[8>wRorQa;ri~\4~a#J,!FQ1 o$\]b~@&%GB!eW5*'%V}]4@욤}fE%Ӹ~h/g|Ӓ\ֆ7̴M \9u*t(LGݺ`fUy4rN$;QeUE,~Qdz?c2g(0P3Dǹo(ikMO=-@1.? cd= ccBkN.gBOG}'Η7[ʖ\;.O'9"@7Z/(g,6c3ʻ IM>>6as6rF#9#ѧM: lkGب8Ҍ'Pq'.Lnx܋=EbȧC@6&sj}q:]i+gl3.jyNzk`,R" RT)@Oy2 .C:JSv]CrHdeUkZOG-`y;a{*?إmqOt!ֽ0h P5WȎO&֜Jn_bz| ûR?M/0~+uW® tB)z /eld~wG)qzdZF!VIؽPo(?BnzݬݩNƪL~B7R?g.^?ybzb!i2: 6pFOd>RόMig0L<tmeFK%acLYWg+Y@r!KOѧ3ԢYGf<:\fv \\iH 1j`YJYҩ,Gd֩&xlNFo) 2H O?Qϵ[ #]ׯ&kPWE'QA˶Ֆ1i_=/i1ſbaJ45u~Io.-Ue6.X!SEb6Hh>ן)5P*'&K^gyp^A/{\H M+nf'%VcGզ Fmwf,Klc{gO<b6틔d!7.l$Xl%6dkw?X-j+e"IHYu]u-6-XXBt _+";PtiYA~ә+e81'.!(AGV4𮗮H|ގ~ c3cqEbO`,'$2ixz-iޤ/(ߕ$%bz V^ח\reso=`\ޔC\.'ӼwG..ԃ~=:r4{%Hi|ΛփD)g7<{eJcI@ߨv2N60M8D(eND ^)n kqy =n9M8SGOn(0=^ۑ2T UI_|s (k?Rf=,*ܣ~TEE:۸*,Us1k1/wcۿY腬Z;OFUJ"=پ'%R[l=h ;\Udq(67K6{IuY}!.{ɐdnؼ,0Kx2 ɟ,NORf+WsHk-WҒҭUI֜|!;U\sdz& oY,N5ĎѪ,f]16xAP=%V(I38\1 %Jvq( Mt5@͡wKRGgq1q3t. ˔Ir ۞]Y4J]/oW=:w*ENWb]?r@A{O%D^*cV~Ht沟OJ}OUJuNk$,T`^dU+8[o~7G }VJ, oԗEdlKfxan' Mq(yN!=a&\-bAPy'w"!<+*]:ׂ]{6oN]M]VTj7^17ʗ(h)J681!cu1dWY @aSh챲z;N)OZ` "LF<,I/1g njQ2> Vū0e"f-KR宿gbO8X`>Z'm Gcċ@)[8f|Tn *Fb rƺ-nzw5e'K|CO7d#ҊtPTwTlpr,tE=Gơ7)5E0̣c)5n~֪@#by"2dmؔ&ìY_,#%KNg 9;8 j7;h 5bF uS;|iaDa}O%8 dT4Ot@gAzvM+nsύ<@ I ]xGz/f?bF̞3"-\EXZn9#0nX u0weך_=Jq,}RY8_0c3~CPa1#~fLZ*kwEl1iT+L۱rASoP:ܤO.9:|}>rAP8]vgD|]ߦ:3)#i 9> /sZ8'2u# -g=qW޽$($=&<"pE֣ۺlV߲C^RʥqtU^8Ř@9ݓtX1i~!75?{עU fus&dy[fwCp!$K Ǯ?n E2$9.)ϴq?\7(ȶ'[n<4fG<4~\}Ft1,y:`R|C別HNxbpn8LxR_h9{Xc$-̤^Dwwqt x^j8 0_g4 m`ghi1Gd퍚4q)F,rNףpn+O6l(<'A6TG澘ߩw+ۏ[?Z!Z@^ +z[YGݓ$`/O1fCƵrƦZdoS-Fkޱ>RѾ_@%(gꅢ9{YfAא[rX^1[!K/[V8Gg2Y2uaEL3OK؏ OTx'.UO$=;2uڧ@q-6}"ݸD% `Z%)(O2]:L~VEic p2׈m r'.JK)FOu=$sOTr:iT+bf%}p\)}D8 iQ]1iaMMrǵW3x#UFuRs. a~?. *r eLUԒ6n㽱GWpRBiܮw"faӿonoR(Fy;ougoV"b{nv&l)teƇr!xaUZxN6?z`B/snP-2&f䙲ؑWPž;wpod~⶷RQM i~ 6Ac*$,qcJ'\UwB{byNl^'j(*SWPgIsA py;_|QceU8ItHMӤxls#c̙@ʵ$],MzT^ Gużs#卭oGPOC7tZ$H쨯k&1׉]TXr8OOňD8T_ 28<(.p7=샮<xXV x&Οewo V8722zY׈[I|*Ɵ) P*'KA%]gVۊ]M+O0=d.DJkk߽H{٩JnL~[d<9‚yvm2tѴ-4ݠ{= /1:yt! x.+݄/ G% q{uJYf8ܦɵ9O`)-~cr,>+@ySv7#qw}#sśOFGatq^;'i{[jd;™iPC)a<ĦhuFgDŽ?oH'w@m 3w6ϒ8a68Yǻx,keS>`wI5*Kǚ#d&y c/M7=~n) l h-ps`뚋=!j`=ߺ=͍TD`|;YQln5e^又C{Cnk?âE}وbEPG5%0A#2L##x_]:k.vGiJH^? F{ָ~)X zWP )S>Pȇw`^p$DCX{>c^.ϹjP [?Oz;,[~Eg8ICcrbւ@ 7LҐ4"\HtQŭUyuNs}|v`D@NoJ&`f̆m/% dk=!}x'c[W LNޒ,w { ԭ[b?LA2L7W RXѺ99/~ǹ+#pZn=Z_3+R*B''fV@'ӿF{햌6)3DmHSI%W$Έ0aEgi+kZBEFp1 t9Բ7/leBJ`AþfY苌IƇ.9C-Yԇ@ >tb6)4jєۉlg2?0D'rdYb${0ߟ҅R4\wr`"gDF!ˠ AXڗ_Jxz,;<@WH ^TJjZ gh/_$lL,_I c^d! YzU/Li54_{0 ~ ~ ==UcK_#\$ңJ_dx/ڍjtfK _H5+qxqj &Eb:e14/vW->;Ҷ$ԋ/kpqij YLa{hdJ4#:Go'2TKcz)!@1xţőT341X-$7".C v]*RIFV.6C&`>~>~)Sch ݞ } Ilm%zF: EJjsG@ԖjrKjn>l{q VoU/A]#(*yUb4W|D&@w: <ˉ32޺ʀ|>$If"pk$={jn(N Ѻj ku)Tr ?GOP=?B<+-7G1J>x %& /SmiM&I+Xp>YT"m_tNvOآ)dq2| ]b;8\*]Rm3o͠T;H(Z/2a#`kS6 Db<_"Pz=?&o+Uedt Z?Ie# si6W$L]p0[@ؓ!Y;ml$%>"/2ًqr^VwuFv0 ?_9Nq>s˞w)Q2l !; ^ 3ُ COo3.&osCbF B!M1]ɟQUX;oTNdʌi*8po1ǻC* eeVnQm$Y3BŨ{i%r?:&?sR|I 2g1i]S}Pp][da8TOO|s'CG^u]؁jBD'jU}=p8k)պIE2ɛ-K'g|zAh]r*ʾN[YvK9ow[ QQVonM7YG0oY%aEe}΂3#&{(9TI"IZmB@A|Ig 'XAx#{p;,#^i`Z\L8]ێ wg?!~~dy\'Q+|5{wûo L??}TyǒG7 )F'yVOaXZ&'KZ{VTwǨy L9܇8d'Ij@\cvfsX|6y \oG}\+ɹ/ֲgP%3/2C|: o4gak&r[.f" %͕! )۝[A=3oS6I{$K?J imؿ$obKe>@S^7onlFi]bҚ~wl*Â$=ü91mp q9`#2pg5}ڼ, %q:8DnO*/fNkik"E/ I}C/k'znWY=B _.L>yc O,ID0-t.4Z =_eݤǭ\HH{ ̆n)VϷAR҃~Ϛ^;g:6ySlbl^PC8\1`sr+ "ppGB̔3 V*4\ځj֤ԸT vكVp_?wqi Iyi`zu@ïI"THE~{R0t |ѓ~C@TRꚫ֖ >#BQ z|lC KYx0C2m22ؠ @8;Mv#d oE;y%V%>[n©7n!`۔eEhi!U~ǔSuX 4D^v_󕾦ST(7

,(\U3ũfR*@eR8>R7ET5íܼb\ 4(8^08O0ik tSRn[έATqCyϒV^&Ld7pk;ݏ钃`JUW,#yRڎh,9[y+Ҹ>YS\E1awA|%":[EN+pDO>BN(9]N}9z.vKG $ۂ@~].wFp*E 8To0ǿo+jǬΈ6c’BpweuA+;u4eGJ#cxmكRb0OV>;"L.U4b@-C=W^햯;v;slhQcrP;_!@oG Xh}Iea_d+jKUk,_NHSc'+n{R?E9POeЬMZ~r7D[.k +*[dR`#,xo,4V  +cFa(U$ )FBqVIUu1>'d9MZ%/дVrz萕i0^3>:{#L U 8Dx耤KXXΙ<*WzF^C(缤Srp>'S̠?7(4\_q\sYjoNI0ŸVJZSZj ;K 9}) $ͽwjƔ?rzXi=hG\d E-?x@庛J@ G6k"56IS7-Z rԝOlS_0/NMzגP_.uqv M{{hfmQF?x>򚠏Ct1h"? @o oC) EI:z!:)*IJ8iv$tV_٘ᘇt:F)e:7אjC1~r\HYsT#|Od{2$>c&Yw<ٰ{pz7RX6 ZVA:t\CA=9E:6o?sҾ(#˶/Ki!|xs׃ƣ9yFOQGu_"BpcFed9`ke v_eF*r^)0LGsxeޭI(ot:afтɢh!-*ՠV*}\-Rۦ(&@:,/7]7 c$=xS?l9~OsX+C[0 ^7ŦQşD}eA/kV#ƀF2S=Z0   7aH ¿Ks@1Z׏|7 qdy|Kכ_3gLfwY1 c=1޻@& ` 1ޟPt--磶EH4!5lN"kۯ6] {Brj_iAꓴ2o.wi^U/Jl$@v!ƫ'(ïM^ z1e;z9lJZRL問m< bG0ۯDX {%*= Eh3#P`ѪA3/|w" +˱޳0wa~rpEeqN$ޣިB yd,j~K.gZ?|JMTq;6ہ,UXƽm\L~_&Ŋh!-T,]pPbT7Q\eu8QʺLa~kԔ5GX0W鲼bt b ۗ֠/nyBHA21 XF|M˯e6O;iՈc_N[HkH-BTX0:;LZj$ ˄Y|PzZNQIN3O4,_j) @X>CZOi kygʈ˵Xu+B7XSO'z%#MsJлb%CT?]i VG<Ƚ`=~ @YHjlÇŵɿ"K`GOQN^kxkcr"Dnμ*"7ս "WF|l+oO}T+~ %%'jm7zok|pPO-$A(Z^] 5v.nDS4 ._0+"wp"xDVh62Dy#4‡v_C kv cnf&pY)1KV%1' GFGP~K*{:+wzk11P$"Y4Z׼y:x aH|E^i! _Ŵr0`s"ZN,dV5̎K3R"\)Cbk,WQ3?|;Bm)mRYd Nopum[UP"c6S~MUU{*HR!ƣ:e'y#:|T80jX\ij{'q h*k[5 2sZP̪zA 4p#)<1Uj{j%eNlGFUv\hCIA}ջ,ׂVFr~*L6?Fՙ4fP',zcoXOڣAJr̻ b"cN8Z'Uu"VG~4ZyApAƸl]3w=Ziw7YU W}ltvABꮀ67UjR~ i9g}c?!a&4h^ô5ǧIxA,9p_r1?IUF|X=3rϬbGP 1% qzTi̫wK\.IE)B#vlU ^d[g!8P9o@ @oK3oIc\ɿw6,hM%++O9m&[>@4㔷= ÏǭPcd`5#8*KTpS*\R./ e|lb1 Н~YX(QrQx.e5zAAfe )FR=X DgU18li'őn~1v~u곛?ȟGE 'Aҙ_d: WtJKK3v,xK]!0fa|zUo|1FSʷ 9geO+'[H518@}vD?qk(p#U:t uX(%<>Rr83+bV9}s\`!|୺ypk"L|wv5n@8.>PVEiC [\@>,0)C~=]iˢ^]N#/pIND }@̈́o@Gb UMݲ `Ms}ɜ2eڳCQ?B|Hp%a+ρ3ymJvx|[aۅRoKJpx"`b}?>1<(\{,E=ק,@}łFjv(d碦+'Ohbx`wNLQ2s}=&8/֮ (&ՉבCj.)sLXdn4  ![5R q[*﹠ y-ԝ\CtL`3I31A5dn8xm/SόWyĕy rP}Ú , g)siuP%#dsvMUFkҞF *:Du>ʷX2 kZ8 Uʭe~-L(x}hg4:2`Z0ab}} ˅-gk!Rk[onքvϿ-rP*I'"\'3DX5qsg~ot(Rsg&Xx$1TfJ:mΚ1rYE%_nb{ L!}.*p{9GO5rY.5Փz&Ć?:Ȥ>aqY0y4êoY{x 4S?*T4`zոj/uOrSRP{A;bm=svTT4 gznk]_ Z,`|&{Gt޳ơO qaڻ?ڵ59]ֱğz5sY?Zi(]ajRs'ls "}@(w) 0gq8/ K# яQݎo"H~`I=r1;hn)` zKmOȗĠEasF-XʋIhUX]$vH :|$MG2'&;.XPAh[&N@920~Bp zoÜHdfηGnuDwj]IWŸ@[f,q-h^U/38 Nqssa/}iAt1ǝdLCV~G#pw8@߮EY,/WL[Pphb<â:iQ %VI Eqıxp8|n# (pՔ)GIتaqmz5/bN (A>^ȑIFfG)!Lf8=.`VpqXNnuYJ7zx ̐7C?( J!aV ]1A ͯ>!T,]I_-B@63(byPV/68K!e<K0ݰY6~J3}$ 8+lcEJ_L$!Ǒ8͉rKC{jU^k|c+nUj\,V4M{y? '#T$tGtv̗,ʧ&-?暌w|& 5WM6z.)q9T-O 2 Ѽ߀Ȳ 4k{J3s?)AZ0i3v-Gp2wԼ z_J=ɹQ1k3p6ZM 2sji| lS!JU=>*ۄL~<[w9LgD(nv2o805xsDm ?4l+?mlݦ̴zdǏl]Sw MWx9G:$a "oJB"MYNXɸ]K[]5k (׸0nOYu9O)bN:+auF ;UZGtS7 H/ ːB0t\'Z|)}a$XffŮIz,;0 T9`iW22ZHHdPe fEZӸ ,0~Q͵>}9H5B3զe["։w1gޚSn6.R9Ow8 9<Ao)Ew-S0lw/xyϠ\a&<,q}.>`6E7$Sm9%\%GHi+ӠyHEPؿE,F٭vF*i 9g(d(ҔSy#Ih<+5VSx6 ^1"쿛\ry1O>@$;cz[sb> U Dhy Xtl#BF7 1a6P<Ӭ~QF4qy-zHGKeFkƱo_.8&,ݍpop}R;K6Ay :)h^K {ÿzwgQy[вHÁ^ƌl^KSٱ8I^.~pVP﹍RʛrDHT.' Ꮨ/]Pgal815cZC_IN(b"ƴz4~ob6 3nYiTIs^|iļCrz$h&6Ȍ 6i+p3%q}{IBRy^?3gF=`kNo8!$矛FfXLdn46{3Sbk!G6=TJ52xo`@p̨0 Ǐ[)U>!kU+j2ѳQ8jwa|36Ap6[I1^gwKUV @ ƥ] Y۞^e,0G9'W#G1o4h0[ߍ2 ~ZKezJ .Zf{Qӟ%m8C|.4eLװ`ӡĭVy44{1ǩK.1~=sTV'mB"ү䶚&}HA bqgȿW4Tn6fiZ[jGEdS>aL/g*_iy_aP;'GVYc˿ՓV1zt=UA4_5N~1d#4 oP0ɤuag`L_5>jYɧ\DFX/DM'biE6\=H2E?Dkn(R07? m % 睾Liv2.Q$L\ >݃Rzli&o95IHcO0V|ݴ] L980%f 󇈩TJ*-|Tt^ni@s-2pjBhF~-bl s`A\!~'̏-Ezbӟ1QoƟ+i'_/(^o82Bp~E~Oyj)+L  Ў6F2iC-t3z g5XEA)=֢m{u "(8Ix}LťH+ڠ2UZ%?b ̱oC mVj C ;NxHCoJe?e@0 Vw ㄆw6m?W4C۞D_жqLYIv"-17?d'i,lq)Hl[_;JC  - 񺏰B6~|@||1I5IP<ўӓ >ڱ9Eۿؒ"Š;Ȋzq7B^hC"c A 2^hẗ̇olսھmDL <'xM“QNlRX 9yٺB2SꂋnRX7D0Z$?(Vuxt[b2Z5pQSP%1~$S^yD?"3 2K(py+^G{nd8H[tY=gZ2Lhfq>߉xl<[5&_^n-b1][K_JRףF$,,>KͶQ[XlYsW$&g 4+uT0sG#=_V6b^e *.F 8QܹI~>q~pqt[nA,"Ȉ$rz3W#3 ]>T]%@ }+?=dR3_3H|}/J{C3Ÿ)i1ÌijcliCVK Un`Ue ZScJ"0 㛌ùfe+kS"T3k^L>Ux>/bǃ)P~2MM}i6o?e;Fٗ/m~ /]&&fh'H^ :J:{aF)ocuWmWwՀխkdLGnR?X]kZpX8Y3YdKA JCyJ}qgq7^/tO>U{TBhȝ6'(/hUYI{,SX_{sME^E:_ /^aMlY3A[x!nyt@x!=CVp@)*{K)N0De:/*q]bXjU^xyhA 6ԕhKnȑ/zOh>̲'/t]>iv$˷ |5(v=R'o7Rq,X#*9qn$%ne~tQN(ַQ Ы'2xe,b*%)**Ϟi z%,A%3=K;7( ".YK1Z\f.Y~(ߢqq4RM=|I炑J,Y9\n+jP !)p2H08?`:{Rj:ЭX1>$+ѬXK2uy3 ;8|Pba -`f'(7d:;_cfmmPÞ$k1"G#']!JFr%[Rq]DF%=~ͫ!"uBο|_;*IQjg{°pNvP"yv 0 2^ζiݎei%Yk ߱\Mam܌}H}%&Ӣ5yyDWsцcNمa|  ]6 Yko{c]Y?/UPxmpTqzZW `$?\JMDOr싏H=r0}YXy=9e?^m}? +1s|c~nCӤ!OcT^[ec7]'a sӂҕ-Md~o/1 n ZZ{3DK+ϴg9Hsj0páffqZy L58R 8մR%x[jftGC2JjR^M9 :E$KQ{ҕ8;] UwLR!.ToUl={5$qRǔ%0;mP 9íid,FspcQ2s 4".O_~x*y?ja,^ly}VmU>4E5o.Py"nwt_H8ȸjb'ز7q2qE&Ҍ{1O#cݞX[YqOfkk|/Y??򠃥Hlq.߆ cMHJZ a9@&)ֹ8/?`ie\+OS%ucI8**]H?iwAw<]䮆çna(Sb1Iؿ.sg8_'nr}tb.FXdS[G:i! 離u0 s>[-2_PR$,0'[~tKpY&X=SxQݏ {YPd|a05b{ q>ԯ;Դȃxp+08|^8=fB{OK/N hV#u {WGB-K0ay|;3 b`Ũ|X[+ .tz'5`1sYv*C IZFTǸTq%.,U?[!~-8R6|{AMQJ43,Fi) 07?⫻Aa# _k0;ps`9!i{FvLRd`٪3[s[:f.OYW93>dx']=zB;jwm8nYM[` B5N\li_K2pd'p1RgݠdUWL},<CR9(h8@ _ lhR[ 14: U"D=\!i?)09}Pӳ Y7<*bع@'!"KDꇦ\ȕc͔O~JW)Q<{"?erO!DlnI’I0r"[.(bCa&UI[m {q-x#QLɩ(F,\H¦ɜ#&ODyG#e,gn>Rr0M#6 ^2z\l*B+^Y)]7cؿ+hk(7B71v1mIHp:5_8cc4SVYb*"MÆqH-1ʩURw1X'mje/u#רטp!%1 hS%[nn\"E&pػ?v3o<=' J4&oFZ?IF_\o9_RzS0>ϼ, uu. eN/UY>ٍ)îws3|mtm4Oq!Z `OY\աï楫57f*o/_%뼀 g2mA_d{ C0;Z's" ka^64%9^dY~C_˹,ɹ |EUuDNP&Qm zxW(1t) }xc.4|hL>_ZW76Mc>J^eGpޢw,X%H7TEI@1koC7[%8*upi"Ex;:9F|*+%&?fOmrDdɶ8{z`r$ħ pd+ iұy_!K|q)_WV#/6"*غ[]uf}z<1:@ؿijD^#Ko)xWӵr&ms5ų蛈,D۲bl8镹.]"^NU_OztZl LZ(ubbÛYGq<#7_[Hm,j< .Ks0%k:Inp߹SƠ&޷;f5rrtn0kE7N< 0Fap!M)8ɿAutkҋ DcF8eƖWqwrK{-pj_wU l\&}_2!nhDQΡ~NJ0W&9ꌮboQ.iW4<+hiȿ5F#ZrS^2͘3RJ2퍭z^Y ?'nze2GXQLn1=ce^K)I-/dDkN͠QK|d9EF믲ČYwv=ZӒL+2K@{EQǾϻ */ QDMj gz2.Tam6mWW[oj5M_K4fi[)_/xWa,ڻr,ss*5CR~ '{3PCޜ_M^q^P*p bv&_k+6qI<XUUj%ry/@A!A5]t$&i*~ΣTOt *nF&ZrRkWrfݧ)J@Myh+^F~2+E'w}63H4x^W6F1EUFX^z)xԉӏNبz=h<5oB$bbkCO251fB#vh2gb.O|hnF5FyM3rv%KQHsҝ%G\W!C)믯G@g XQ:wM?6z=&FIg ͹6&a(Mq9ϓתtgy!Y}'7r*I|^f\} v5nWg@8tn?@ׁTRYF; WMb 1Eoԏ9*MZ|G"d3|7ܧ?咝~7.>y&as"CHS<-R՗ԦjuHW `Zxz.žRU}['@;v*^2w U blRkCC !?e%{,X5kt8?k!ԟr3 5ݢ'( HW 4H5 &{s{y YN;җ>Ji_QHVXW7E_SǺQWU(t% }4|ԪRp.z mgx)݆iQ3U|]%[+22 =j0 TabՍ"c𿇘t3LJ"1XQtֽ4x](A_V~'-=|u%7<>`sW`ğOD~ ./|GHW=r0 g m)ЊL VS ]ӈ,;vM%W=HZH~B?G]#/7~|6=}8jYT7aA{;_AcikIӠ`1:'ygA_Hʩ͠ 1KҕXIkjƪ荙5_ͳѡLѯ(j#TB݌Ntze3nX7"l{5iX7faUb9=5FT6z[7o?ws>x!q{Qg*ŋsA (la;#p\zVz+Fb^%YɄC,A[?t7~bш=GiBF;Pێ#8N_T@.y0M/}@ )6+Gg \z$#{'jo+Q0rL>su{k !QفUպiuREL3j~2) R\My%KReA)jh8Y5,5E]Ɠ}7) q&3] JxMTyEN:AVO?g߷F9_{?HqjcjQ!#XJ"L*8%gzr_NӐZTv/WuV+dեsdD{3ŦYrr֣$cEKWG~ kQY#{y[Q\3Nqw&ٰ|}͓%9V g:L ⷆdmG\t$&} w25ٳ%7xR:om?yNؚAx3Xf3ɡA%eZ1Z ;lm@c@QYjnlp#_DQ_*>.yu&ߑG|D,+p{~2W5zX0DtɠO>yWjk-f3jlw}`Rn߂Là@HwLadƖ 18SLNybr3ry&"ZQӅ6GQ${wl*'LIcgYQ8"5îT.`T(]TkEٕs* 4|~ 1EiX z+z̖HXYf|l(MNk9/3t\>ge@;Qbg  {J9[kP:- GsKˇ$ŵրFϊ{e@-Υ@w.YFډ_H,*O }GotkebmzugwlX?o'^pMۄgcJG*_%+WʡG.ֈ.#Xu7 qP21"GsTXo0o%"wPzf 8-xl.p8] ;_ڬNӕ+tI0i+uD*Op 89[3  ?iK:NlG~禮~'vzlXghTr$vM&X'f7xDHҾš9v"MT] c*q9:/.3YPWk6a\'H A#ő΅=.Èt{ ;&$a`CYJ]<,_En5H%xV]n 12tH2,0WL/ [M&ͯ$3ڙ2ޮ|ϓb_`T0/ӓ1^1i64VYuu~mNt)fWed%^Wftz=p<ؿ_xWY(d{nwc~.QY@B˔S,ċ|W};Jb] u9?/D7ꍦiN`HYHI-рPOJWBo-ֺ{Vr*jQs~ISx>VgNkJ{{b|DAI~c0֡s# =\*rY |- ߲*%՟C`-Ǖ%vZ3{ Ws`$,@ jxh.#䷎0`WTD {fWM&lFZ{=}UoG6[[lA"tŦ=d\+/>W| Xwx3;{/u4㣳-C UoT>gfX~'⦈*%pl9eT PVqV9t:iV/IBCuO ~Z*j_n$i>i$_B";N0u _OyS&|#kF_P?ϏQrPkWKbE,Y$j蕼$AԶە!xcrPTDOξ{?)j տ#7WҏNƽMݕBm*. ˲=ܓ,8P߷wU>[}-8 ($Ą[[|7ƞrKDg &#ڄ\jpξ57lM(<xMN뾏{l a ld7<.9UƑ9CY2~~ &cpzݝ-XUoJ,Q sUFs,1G H,b5 \U"kR3!>("Qqb೯JW:[ KQvO_+mҡ_8(hpӛrʼ,+,؟3|GWDծK,Y^nu_tz啶zwݗ.kp&<]ۑ"ڋgÕ;~V1QFET{O}@kMetJ1M^4XtAJ[X(}+&p'Cd@xֆ+mz&բ;R4>p@WzL^{O I' ы-K^{m'n zOd&FA?( H^x1!&I3Ƅ/^TpݮAm@`lOk- ;VYͩL\+D순|&jB; }Mwd=$፤,| ? t| sJ=0hi @1}7m X/batnÃ\;,6xh0v>$#hN"GӘN]L{Z!8fJe `|wsJ6n:.`J_WH1doBcenX:6r0Zs M(Yv)WBXA(fM=R 1ڏkY~nrhCo L0\^/Tّ+o啹b/@MN0^gL& \e7JGʤT<%znCn a7zaz֠f>_A$nDH.+`xJsL  Q%Q`┧v-*)I>MEO4_Cg@BTH*>ndZ2,a΃V ոDžqpp6ac~cmd ^'+# 1 ' 9IO$o%_g\g}|mu@>`AT@.I }˛$PZ~o n=pڥ- 6Pe(Iz P~#Hn &`_E<$CzVCz= 㱽l#P*ǵAټ㯏u,usDbppnP9QC}>'@rK/zWFTX>rC:̗*z.R$ynYT#:XoHB(&+j] 3}>b;FX./DWI)@6[T 6]4S#psoGA2s. ]4%'U <ؑZ u'(bUڴr:&vn!}ɂd1enF{\-=Rb,D"@rr@!ٙi]B|sLDW;Ǒ*ŒnYƫ=PwGUUP&4V/Aobe_/2vFtN}Ɖ^mәUi漄:oGGY$%wW}Jil^"e!v 63ЪI_6>žJbBA0z}=@L׹ MB̴siGWQL@w~my[; 'JIbGGБSA]<^{BK}NJto70 E $T{X 77| ?X#zrn$0to桒-6V贔iL~M,RcrT{2>pĺi U*T ^IxҍT۹ '7ޑp}(=:dskEx♷5> H2%Oa߲L"v;)cfӞM1?a⣿{źX~" ۂ(\0 exFDn_ljĵu%R<)Ž|;F]z=6-X0t:Lojlu !c"NqV!{0b|KKgv $Ʀ_9'|K;J7i;vB!AB-償?uƒ0vzf(Ujz^sƱMR Hj\{mEHs 0-CD42XK,iQ ^r~^|o҂qaxX<͔JUSȎuJZ%3[$֠3wx_ ^}T1(J}0m2}*&ԩ?y6RO$@_PiVS[OaM3UQ=\KXj;J&( )JҸN\AjY9&cp\]l+<7>JHv_S#uCs:qRl_+9ť:-7t`[;Ϯn~뾀)gB/)N5z-kDįe ƶXQp4:nefuuɿFQKA#Q}'bV%;xEl?3"QB,adc"bxŴ ֞Cig("5bu|z<Բ| c8û^>c/NY%<}8`j8O{i?1b_" 2MԸȯ xOΤ0ˤFu/#Krv]cTPdIW_%Ң(3{,Xi ZYg9$gJ(ю@C54/to92?iEeUS\y(ho_jJ|rZj!Z ;6+kv ݯ6Eet/vQJnr%C9 X0|͒wa~:| W݈裾\ '+SmGuL JnRfUjV¯mctw46}jZIOBSGCa|(LK+PHՄf7r _^E 'ZS% h+3 &B,7y8 צj;r_Vh)ҦNeG|S+;=E <6 #QkSZ_NShMezS~ An|z;R5e-#ǚ|BgQJZ GeYNu8z 䃮NZ]#2WO^i))&$kU"e4 uh?:zICw+Uemsfɺ g2GkG벫GݥjgQo@fh0؟2!=5 6Vl Pa)#-~Qog5x:+A.@JB{Ky{wY=)o݋#.".{p"'#9gӄHj-}6_(՟c LQ?~QC>=CB]@۱cL;Iwaobܙ)9iya堯C"Hէ14l yʽ&t3gDm M܄4ֱ :Іx: 2({GyD?}2r70d(>w~.">~:3r8nZ뾨.[t/r~<Ԙ'&(`p')ANa:seo $V*mX F1j/T/NJC>Z/o`1js9irph g~g9bM s_!J\O:'A t_Ӑ0v鍹(^}TښS,rRMqt,yY7~+sl3>yݪ8Õ(K6f6 " .6BJ;7Qsr~*AwU`@ִ@;1oj2IҌB3CO2 [~V`,Ǟnsbb{ڎN׀\yaކæ"?vuG f׉lϯ䪓aS2.Akp"Լ,v;R+i$ d@$H0*O^Ÿ>%YD!$LVimR)ͿwYLO.$~L`%s(*|Yb#'*`6iE, eAgbkFK,8 `0™.9nLE,| h[§Ů_ެ+>|{#Dt*EӁ';-tUbTCMH <fCF9A=~( 3ߢ`Fj**@dX۩&5 PCHH?] 6fױN?^ѹ/Iǁt3yxX@zkJ^;7߸jf֠6ûX(a}VamM+O SlGϒXe3(lF:nVGV"{R=vPe`/nFEڭ R4&4KQ9JˍC~j VǺ`I*ކ1z2KےRZfۛ$(xGI= 7'a3Sy O i5[-:D!#V&zY*ڬzcɥQm>`fr |O=Ľ`3K8Mɐ d+vUOǦKOL6}+#lzH ^As3bmRJ`? sd ֡b.JJ,jayrC3dVi Y|a8 .Xq+*h^Q壿y' 4y*4%wy-XL/.:3`zF$1`17R |!e#V5 KFypWhȬ-=բd#_Eg8d!b#`#_wǡŶw@eޜVI.{̺z]gFTeKe%9Fĺzo}ݱɽ[c|^\Pa.TfĂUPm |Q%"C~FFTo)e_p\[;x. G˓uPS[C΋OR nΥ:+(jK2H;*G075VJKǵط 'ܸ;!XZv1!smkp.F b4S 5nE|w_Y"Z o{óI@`4wv3ڦ 9Ɛ8Kw(9)k6$x< GCy+6ڈV\&= hV/cdQWSWoYޓ{ /GYڔg$/u 5& }Lg="G4tcKrp5](k)%[cHrSR JYe?lC[x +ĹmTKDbchlnspΟ7|^\*8(7"X/1{q *cGi(T9˒ mv[eExڷӒ B)/E䆌Ͷl? Ѕ ,vlY &>Aĵ0ӑ F+-ܙNoފM>wZ7/Y+#g|~֤P_47M97KmLCQD @n1|3^˘?uPe^?-xʶi0e(@OX le-J~4?STRDbS)&ð^{eFn#E{ Isim/1Yi }K{}\R'^@0#,{E<_u4qՎ'ͮ |fG]jT׆Q7UD#L2U;bcRϴd~5pQn%o;/rS{ =n7 E?m)qLiFH! '+gAزƀp+ʃy0(TW]rȸ:,ywf5p?yVӗc fPKW=zBlXBQ~03qy&01+eemz?4t^?$}z- /Dg?P7 ;ԡ@!.ˤg\ # {'ES]0]ɼG.C<ҤL~H~q|CAHY׋z߭%;kޔئy/d-XtDcGxȠڜw/-Ugz23u>_3ú0JM )P%dE1BV@2冀2;ލ9٣y?IϣXr|C ` Փl"KInhBq0}Q_ PZORxR'f#p>aO)x s5 3vXLI3d!춋׆'\{S؆Ǫ&+ \5m+Im[-Y$8Tr`+füLi&,KqA, q6ȇk6;o~  u~wblU:x5%&*f G@^dͱS9sa-R[72oI_RCGi0%:䰀8(~V'JsJOZ fӶҺ=N/Pi+ǁ܁@)M*= Ƹ܄A$. Ct'شr6b mY9, T4l)'Θ ,@NG=X ʓeo /SpϐrDXSCUi2*W'E=j0MxM8}džסy?K0p;SHQ<.R r0؋2GwpXu6a0mٍ⁣m,z7@? >@TX'qH]oS١DԸ؍.S,58? p0 JOq@UEhԬz&$lXfl<}0nqpL]z'Оަ2RwEխcrvJe*oUȯg=mhJ#lauazaJ eat+ϭ񭶾x{z!g.#|93t0KNOe؆ddgȵvW5bv_QkӠoh*r ?1Bœ?1>21HCtA˗,]9:y!5jlW)?IÂ?e_vh< `}o!m!\ªKax~ч 2նD] >!w[t”ڱGK3ӡ WWƆ_JW{E] tfN,rHZ.a 1J yYitg)*wH׬Ls܂\6 r[)e(5iM ]F)g͈;;3͗9bC[_B.6ѩ}t>3bSNϯ9Y9mT^,D?Gi xD>}%}ӃC~{} Zzw,yGyh,;F;GF@I_t=^z1zl+$׺r7u/>|[ 3 `|ݯ^݉:ȂvZ+ ($K4w;ƽN{T*Cd&u;m^EZ/iwhP!BJ=pp::cFVh>-(F8ڛv^ B :3.νMya\~z[ i=߻E٦a --$!M\/Yr_N 2ݳ؁(Gd03Fbg*@=D)MH9 VPjBL=y31aWn˲3_}S Bhp|+%D{kIC G|vњkPP swUt+Ɗ!R_'OڨʔKi뜦u-`nWoo sRiSuSb$*/ f*e c؆[tT6ycv%إ߼Qy&±5Gp Ӝ{N?Z/tXQwcF :Zݙoa]Dd~xʳtS |h2(>A70F4^ކuFuB)J@ۇr4k霅2,k->K|J꿶(,nS)9\)O w;|AWDDPtx..>v 0؄,ȧ\y}[hq`^ڰ~$D7K߹D+b=l'kU ς(9rW{F;zzccT/|M Mp lښ>Z/ YH+ EJR̶"u?`UXjKg`f6"MT( 9; ?DǹlP럾 IL^ ഞ"Pn v 2zQ7?g9xsUN;2yic2 bj ;4!qu1Cd6)O{b{07fdXA‹ *UbnI"6vű.NصLƵF`oHu'Y;QWnj=+S\AKBP>G ge,[~?HDkb{}fڶ+|MGB}ٚuYFd~7=\ޗ4?GYy ;~Br}kxRz+A!͡Iclx{HMEl)Kl*2(NFsr@hˆֹn RSnX4FmV ϵ~ 3jX ;;>X.N r&o 5 Pl3,`!rPG%>Oj@M-1Ԁz}9ڝJ GPr FI6klZۢ0}soa׬n+DO(k@ =ج/A`4qH^AQ\tK,}s6oyV!'%_Y7ahtD>h9WͿl$GG"G)hhvGTYZވcS5#a5>5:Ưi+2,eu5+ď(BoYo'\˅Uۙ[ @.eЋc13UO(d*ZŊ{Ti*㧆A~yJpfEp:)+(3TNg}N76 ۸Pёrw ~7c 1:d I)͊Uh0:8k% OU4jqyp$Fz 3QS/%wk#@o9&._of>%15d[J9Kx%1j0 QG3\'rߓNgR1C{DA s#^5TWZI)Λ9Z,*b s.oҡS '}je%ge;eP3}(8b)׆A$+(i%Ͱm> (`n(J(M{vf, ,ʞXt^ 1:ae"2b݀B<_d }6* Hݨ]PpoU}GSP+#aDON|oKc2)Ȩm³,#ZwC}.9[V.uϽc};(UއO]Cods wla/EKb[Oǂq 2`iރ͹RpJb.†915tko2KXSmSڤ\GέA'*xɏTW$Dlvb\j 1*Gba݆ͨW4B B*@->41; qqɋ k8:B,G2Z>3Crɭ,_į* oſ#:Z7ϟꮗ/TeS 7Jq-p~C Y"V 0RJo}sNǬޔ=L-qeL#3vݒ.!+Gq,l^2?$"~O#gЏ{Eg58(|p?M"Aʃ^^(PQ\zJC@FN^.f*"E^_ϟVтZ#uXYɟ!I !{(< eDpK6kJͿ1 -Ňx64S I$Ap}v2'6.,'E] ?..yOpusnwȠ;[Ej'zDʩ6'5ud/pi6ųFdP"b9hhH(Q} k mw ׵g*/w L/ڣm0-Zy\-9ޱ;(89S&IrUtV1 $cz ]`PM;ѫڙ.?͖Q{Ei+ma"!h@"PM_[]|fZ{DM֠rB'2E,*욕WΫN]*ldyL:'~Gϑr=n'L ŏFK*#dųNeDP d ZoZ^7#?fDz^R^;bsL{sG`hcn@KQQd*ْ|T0|'YS;ėy:9JLfAMc $(&hYh=v-c&%SiQ8z1`|.ReKҳ$c@[?WLN }wGVY6FE+2#f@9y>w#b4L&c7Qǩ{S9%~3ڍt8E~8ߘqv,\Ƀq{ࣼ\h ;[a-yZ*bc4Y- 3 L`˹sQj'-WQ{3_?R\?X+9ؐq$;%=x8H 2M@ 7ʳ?Fζ[ɾH'Q+alJR,B8qL!Ca9X{U< stPf4['ӊ'G&4?%IΈ at[ \Ve|oi5IVT&wa}):i¯T}qs7RD#Z[J@-5Aw a C3CT߯!Hy|1!\>_{N:˺PQpZmѠ;"+YIr9תȓR,c)hs\PT;/UI(GN!v֣aMufR{[ƮW!^P-DY ala20>u7f vRJ. oV  $,/Է6&r˧$_иIkܨyZG`ՐٵtbhO9OEIE2m)LHXD9Իcz'hf[yMex2q}8(9U·e t;Vb(:+ Ξ[{FPyBVJo͒ǓcmBIWp EgcbPA"x"1aLHu)ih:O,d>K&If{\+UcpHB,: mբgNr5x`"ޜ8 7V eܫ[*!@ȺQnDSkr/9y])!1|?o;*R9:Q͍ɕJ'ua2}4} ܓ6yދ:_,ǽv[& b/MwÆnQ4*wX^3[ڬng >=e8I`'HohdԴ*H-kTUz_ .6`𥦤;őf%^<91ٰ,zMe'" ))E0#Yfi^J+ ';ယSip8#Ѿ=>ܺEoՐ͸1ub@b?ָDq$)HZ?GGߧߣzHw&Y繓s QN5ЦÂLfdq~rd,upA$\P"Qȇؤѯ/V->9 BZfA* #^6?Im_-H %O JoFf 'F*s}EEmHF<ߨ&Lpeƅo'eK^ *0|0n,^RĩpOd廽3EÓ,ex*Pj;EMȥE,JCcCڎ!s~&WXCp7B& |z%맛Q09ӌݑPս7g;k" "փ|1HaDezЋ'C⽻ޗ`& ݾwZ5HbP!5W5%*j]"uq27'd@y6N|5ifD* Z֔q:zOKTU;4XWZؒeyǙbo@ D ?)9w,nE)S[^ @ MY1B_ZI3P脘-ML/LW*~R&&ms`/5 ,TkbA!,ʜ $O/e{ -"h ,ioW^j}y,9PUس X`Ҏ&_jtK3 h&} FU94<"X}uRܽo%gC+ lDz,V vG:KTwLѠm͛pd+SHgPiM5E8IPJ]xD'M-a_t׵I.4/>v/ p(ӊ3?>-N?)UZw_~:*ޢ+<ɭ?M]< |ԋup)ݲhω[1_s7,Q/źz]}:áWQ>ģ+ehbƽJ2ٵ^L 7cMYlRzpus nM^w1wN|ֿJP(Xs?KM?42S5 ђBۧ7PHSgn&+um>2!^XS ko<2ܙp,_ݺV70 _YsDt(uE2IĸM ?JhIH4\#ZvkW[bf!N6 vWҗ3|k]@ PNR98ysCbFEYeE~y|O%(nmX}wF VJkb9|88A #VZ1ԒKWI|f>tuNh%+uk$0ٓŇmMBwu2h4j[$uUG I#'i_=VBj~㻷=ئvr\=Q#kBu^=\kK>*;#y4 `LFlgSh$gֳY)]cn%yU Űͪ%\}O <^BM[қXU B+G)97)dr%0}}18[[ ˅>Mv=n>ڇd,o1'Gɴ/ݨty 4eh2(хu #{LQV@w5mߠ-IUNuw+_te:aෲhfUߩ&Ǔo,BXw&~[~a<鹞!c=⁁< >5MT\Evi @>.wa6ћ}CsæM:3 vMKNA hm/'"! tՉivqՀ0w̪ruD@@MoIoCӬ/;P, s#@YOacnĻ0跖ع/7İbȐVijćI5vg >չ𝊍ojOsw?,S#}#:ue-وGUJO_E|ev12+Hm=kŻݴ3[~7o@r'iXsʕus4Y`Oڸm=mo&X_=L\+қXFzj2Te>Hxy.MJ]j]5z%PCNm%Փލo׺GAǪ(#NPqBB/ > LlVyHz.ؚa4WVdاf>PUL }~2ND\+ÔbG/=Rwb CiW/q$wTͷi,]a- /^C01OU_ Vf[Ϭߞ W`&1'u_рnMrdaüvk<J_c:[0%qxV~0`[+~m.(\E[2Mg֥q+bTVƺq3i|+lmφAV5Cx_9NêoWVOJp WYDQ@un;S! /ҟ: 0NM8f7l+ IӏVE%u1{3x\qiCczo%P>|k OؚsnR|exZ{NBh+9أXb uu vI(G*AϬ8^d>erWl> XAK}Li{ 6?Afs"azU+ӳ: 4yp3tUv?)vmS֠9LAt䗉aRj E&DӚJ `@oȿ$>]6'Fa>҅E"Dd;]oVYƺ'rqJ`=o2u=aѿzA=R6|{"qL\뉡/,ۖ@ஔZQls:?I FI~Ifb29E3򏐅7rq5 >e{~c߬p<*4t#+&eZ/ol!W%kKAiJ;XL. /zV)Q;nm-?R]vÓAIKU~ҌneV)z |t` KFcoA?pk?>Vonٱ}ExpkĬ df s5Cxd6.L84![ :-R]yeQItBصHΫz(  NgK6rA/KZ sL[cX@i|xv?XDgmT~Ã&uiO(9$iR)d~23i`|t^y#}У[脭 [hK$2ZS8)c-j?XԤ)xmߡ 7>Q!Ak~h JFyͩ˜#s :'_kX7a65~#Zh^#g^mګb,Xdz;2dAHcqaiVE;:"ǿkϐ\'99R8^5rĿ<  a]3۷sN4 uuەx됌o)AMDu?) b%I W$VD/s4'ꃧ&N1KR)OOYk񘀕˵6z@prX2j.ܡ }mT޶eE'w)ge?Tǐ՝*Q9TK[_Ci;^[TSkUgчHt8iТrہ)F=m|#QhHܚ߱-WWCY&R) yJ纝ӗN0=UZ, > d\(2YL5} $ȄR˳řf63x&枓7h[>VH܁ojaS!ߥ*V:jPaha uW"ߗ\MTm-<<'o{Ӓ.͖s[|oz;O`=Xn*[}E -h=lZ {#A* ,<`slo3H$W4uD%P?Dk؏_6P(+'ۀ—c#X?ɗ(`mZG]GW{]UWNMzFޮUޑ Li= "EČ.{b3Ћbqsm< ^c1. & ߯mLpB(3ੌ  PRib^C^+Hx#\p-OO,Iu(Oub8bjȊ]jC=bk=z$N=CMzWelyOJbFz*k4 0bd6HrDx4@Do͵;#8xryXO_0]N GȊћ6.9٨Vr8a,Z7^%f_Xėn}&I LZk0/nL r&캼vZ/f_i9p%A5O|cƲabՓ@;AS4:w\gHw1 o% }/pRg17qha0ʫMO>DZZNe7_>JLM& g^~}*)PT_0AsUkG+ c, Xƀ3M4b=wxxpِ_YnwR?N[7}Af*k qF% `DMs$"Zp3ͺB k|+Jzi qe,Vwbeyy@SX5x5z׵b`,^%*ͦ=[ݴK~~Hy@Ћ-eVHJ yy0oiFW֭%19t1trW oBUb('7mi5U'ZՒx$aGLKmTP .0~dga&qk''Fd|tY捉Ԉ7!_jxCYfxSȧع!ʿrҞMH1 c.{]D8جc|Pr,,)Vڢa$8m ݐnǵ7Бſ;N0$K طu&E"/ݪFQqO#?!Εf[y楪T@LH @|jT C#?->2%D8uLf^0t;E"=~ǡE~v󠥠'>VQHКVpŌVU}bɑ}'?V~%"u*!^ni޻"px M8u'zA#%d ;^/9oޠ`DK_u<b Fis8ˊ|~SUQ8_KKᄕ<}P2)M00Bgh8,hԆ׊%:? ogXYfZM]$D~ TjbbhXz 2( ǠlkN;w:s+xm'heC+'pqSH}Cf⺕??8k{jrʋUwNY$ ETS'$,2H# ))O2m<{ySEmעo4Dž `j9ԪvS7#1gJx~ScK="Ϫ;ʤl!\mزyE1W@"\U$=%"65gf?E+&Zt6#U11\Ş[C?Og:I` %/K(,O J׳8ȶ& lH5(K ~O B gu)%@SƉ~OX -&_Lbkj޷ [l{/ѻ}C/wʗ~MudQg_t4ieӕ=Bv?~Vs1|XB;2S9.z#m::|$<nF8[tTg̴IWAS @e;D?VNz=4Maf\ŭ G24bX&0F|CEZ? ۸˱i/-1-ݎ1kD7E/L])|Q׾VQ;3e/?uBP&K7yfh>8lϘ"ژZ>Aԇ~Z~FL{>߃.,lu\@-}5j$G+h^_weӗ7ͱb9|kԖ crg9aK8Vgk{~CƆP)Y2(j!ӛT*Ŕ?Ƣҋ34՘!_S>[Tթ0En7p5(|lOB~c'gVoړRN*r iQ~(Jա&A|Ԕtf4 B-'궣E=fF$}՚pHU߭aX#زiS_%; mtK{qj2j?& iLu0,kg% K3;Iۑ9F .k߀,C1uP8O=b $LR)@@M_ a0"xSxӖ@;h3VEaxڝ̠p3Ӵu|̵C@ŏ(Jo pV>_pɮՄfž풸)5悛-{f!i K}x"0DK@/PȲ|\NR̡4ܶmaڍɍROGUz W/p{7Ў3,/oUQégu6xxH^ ZjL(L8KỼ)lNE:RBĺ >"Ln(>6չ$9/1o;:;z<]oO{6hI Zy B>-xq1[N|u QTlWt(.-@:ͯa*sK$di_)$k.heNF((E &l-qJ.Ĝ &њ+ >)T=\qht4=H8|dXlzdKPm^rI :/kl+ϱC  Ct› 2ZTaʹDaZSpbb>(9V~s/&ǽ=ίOC^$1adӸ1$16`g.{X"a>x 8Qq{n]P75ᩗhe 3AT]Ij4X EIi$[6{wJk5Fdb{tkq^ᢘEM = ON>4S%dNY;um׈\5LQ@ i|7m+G_õrzjE0C6 &1 /0 ~CіruuY➺"d7c^9G?x~qc_ͬ 'o9dP:WRU+^ڝ[ Ś/0b8$Q0ΐ#jPԀUeG*/n)\zSɲKfܖDv%3}|Į6W%*_-FIrVoxnF6ظDz⺲WΐOx/ɫ 8,zjxڤr?BvUI{ڦ*.-n|?uz2)'z=@E3{{1Ư'U)%*J:UaO${OS?% Dž8QACV} 7ivg̢wftѢm%e̯3Yj4 |\Kf"ZLв׷̻1GCɮ~))ϔ2/.t.eC݋$1ǭ.b6T N𴦎"{P)e"Չ=>@}M >e:/׏!Ӭ$&oigC:1=0I~ f3bz}\/#T<&_u>{sH7D}vR}{}x[#Gˢ|㞕nCrҨzgKWA);|! fNUǩhb"8ǚ^k5=NVvwDQS X^A3ϗ^5dwqKv!!'PpT?彉a)⸴, LsyP0 omdqFT۞OYg0y,QuJ +3M+cL^t$f0x޹)&6b !^2w£6Vac'R^ok?%Cgi=Ql. MH/0۾Fh+jYnZJE/UꝤ|ԯu?myfF'}&W KHyJ^UziQ00w2In=|T"=F}tGLnط az0lcN r,ܓ~6Gx3 S׌jg "oDk+wgJ1U "ɲvC3r'~ :lMB,o.ݔ8<ݼ1{0 zP%O=S%U}fEA>,+/h]RHW@KfyX)@kdrI;҈y-[:[ ] r|D=;H U5~~Փ0ߜ%e6"Yg_hw~#"`毞=0ɩoyrε_>DHz#`4 |)  2Gz^)I*PۖvLF*6f|`"t] nn`mh4ι˖3W5VQ.Ҧ#-ߩn>vfLTjPRN5wL\g^.G72SB](gf*o_0-QFQe+ Ps˂sw"(m4#Ǽƽ|WjB>q:;\i) ϵ%>%d^ N(|_v?\Jӏ_zިG[RGv"?~+hC ѾJU.4G-4D?~X-}&(;,;>mƬ.ji߲rgƍ׵G넸y4~Aū3@(I,{ˤUi궤T&9:LDbؿzc>87$123҆"V͟XZ7#ԬZy^. e|̝$ͱy_5X5 Xo!"@bh!?T l5HVJhWNPf>o.,@VGO]CV.ǻ#e< TN4XGlS`Ca=M8K2MV8pѐQ.UVСdzw| BbqI2ؙDP#e@SW5| `dע:\Ol JT~:^^&= (0D97Lc~_h0;ܼL<'V?l&$oJQ}˘[}+~޻(٩Pu5UnX)Q1ASKn|Dȏh>֞Q-nMFCjiiO,-cJ4znt\`$sGHh|#GoTB13lWļ9::0 EKjV}a%l<+ɟX lAz_ X8297=\NfIօ ֎/L ._D`^x{\r  k9z@wӕz2;gb7,tQdN:~ĝ0{dzK)ث%ҡua*лWi3FH;di>x}0|jf O7[0Nw04'n*,Vzrn>J.LMI,gd=͍Keo48EtPGxHm4G<kisggтgXڠt/?ltAˆd{5ʭRJ&4yz=c-9pҬWAuA*M~cYe?6zB}v+3֎q+˔ݼܪ& ].S-Bg\6&u4EK<P:Or2DtntVqP#]bQMg4)S-\- WĶT n& Ƞrs*++-=8(szT<5}!a>àΎ/<4/wBld6>Yܯ2OV'<EeV:K4lY kp/(*eIwzaղߙnx ='M{CyٵfSJx G4P+zg6"US%x~$U.P-+.r9kjۓiS_6O΄źjR3jQ('M^ɫc$\>2/?xo VFhX :Zo8n\'RvĤވDYFId'd J E!ѭqnR?PTގyh;H?Z14dN[]Pi6mϮX`fNY6T+da EkFsTH^~2o1z|{<J3W=)/,bvpQ8l4+4MwlW᥉ d7ȴ‘fe= zx&[\,ٯQsʦr*-j~}^m_hz>0V̋O;I1d[~R`7:3d8z5\zR Z@%P?SQ#$( k^u?/+Jw=~'cQ*s]d-"j* @A{Z7SŨ5bl<_@[u}"I5Sh|EQ˺]0Y0˕ZuZQ, f̣@ 1KfrD)J5#6!^̭]$NU:ŭrRz'Ɯ]O-G y&ސ&/تvHe5JT]6?ZRjYm!hz 3!Lmxߛy"Ά+b~ıC\?&sc<<:.wpꃢ,Vぬ6rZ]d#>6$.}.703ҁ$YODcZ0EQmU\d㨶Ȁ?A5&a'HZ傋ICӉj@c U;$h2Zf3JM:rVyXַ,16o{MbVɏFoJyrim0 yrd\hVe 0\=ҕ |3td7r<6"uG|ouY7YNB~ ݪ5'I"R+դO&wcԹ e4 м9%nU\OIR'X*8R,7L,If(m6x zכV.9k[޻OveV La4aK>Zu4Xu>/ĒkhiͮUPk@b6)QvXN4u2z85 {A4b,gC Q G;Q3p8B6J1g7SVd-XUaݽ(?TJn%@ɴ94+L*P.tXDu:`!io iP\K5mbLOR 'lM^O TɺVO<PɦdjO&UsHⷎw̫GdxjF ğp!3kuEVZ! qy[{Rz D]!*z[!Q/{~Spt([@SS(@a7Ch?EDr&O9c9K <7 H6O0ʝgy2]]aۏl),rZkf"3^ 8 LE]  jzxJ e3*5, cAFaeMe/of4#|@ZE`H&"ٟyI;ޥNjL#4hwY*}Mc-af{WrM+5VT]b$  ltMP)ѬWŁI) J>dO\?&\ O #6b*ѝ} 8,+|>zli%$Ɋ|1;V9T?>&3H^J+|ekxTrrұ$F]RxdMUfȃV(f]Uk)]ve^UYfϖjϤT*|X,D#:y2tF5aepSuIb-er,zc:"Qo,5՛*זxL ;M_xT*>8tίr@ Ul)!Ӿ3ub> &p;$XbVjHj4թ?SS:}sSnJI|;蝏Xl]Hb䷫EϻH>앗Tu3[$yy1:o8,ѶؕM+DF"V>Z}mN)4XD/K)dz1 8ۭ'Of#kyClCxrԭES~1L:y"lq%۩JnP##D64ej3nrZ14H?DL'q=D$[ڱMdև[Qa܀Ull gͤ1FX>*C ;eun ?^3a7A52x<2~z)1)f+x1^6(2xc+l吏\((D}ՙ@a]ڲlǥXLmct[=T:3T{mx*yhڷe+.;〜N2`[=C(>ç@=P ~ @rY x!~rHR6fb|o{dž2 j<شBM 3?;Hy-"zM˒tE8^ cIn^n774nT2*V Dž)G}kxIUC9IƜx8Fߡ}ai)v1op|<%#(UCk|}{y=x`Pѥ,wh `m'5RvkHj UI>c|׮L"z1~_;0nkCbۙf cE4XGMVT Oߗ;ݞ)ǾwuoĻ*ƺ=T6* 'X(XTx 0bǻ]Y.A2C\|>t )fQl,esҝ`I- Wp[zB|0L>Fy/U!(\(N;q=P˳Bqt:KLW}?LfpWLSZ (%B0M?]S'>Yu%f Lq}jmxQEjZ S|/}@v3n'Pv0Z"&1P|~}jș׻>Ģ!!aڱ!_ ?j^L^|¢>YvWɹBw)(y;|ĝ?^_o돗2Oَ៽E?kY_3dlg?Ѩ\hS-i6ȏ d hEoOVߡ\~yt x ?oL;e~n\[v>xtve]_DUé<3ϔ/`ՍI}CcXnZȃApqk+;[otōLuӘy<׍iV-]c^ZI@(bߜ7>(~䂚>bge; tLi2]tãԧ`'b?4t(NX/ۋ7!jj ?e#il{.=SiS)vPMgw#P; H(%?Φ?#a s~}Dz!ԁn?lHi2Wϵ7X/ߚ,[_[ :xq~U_4G=_7B(:x"2a\ouu5P=:z 8?MPџ?w߇ᯧ |펖X;;{'6z V85H K-V-K <G>b80S#%JB!2¦!b ”+Ñ}f׵?` aB7+sR]I鿸W9ςw]O`𡯮dtNfٵ J>mH>DL6Mټ&rof%1z'Z6)h>SqvУǎ nv:Mלud>Ɨ^;˜f(FA f0P9+ f"#Xg* !| mhL!~Iy6c2mC\-Aq 3L;ꮏ% A.;whA%1e n*+G 0c^k0+bˣֆUNQ Ia#0c_s)6j.P|Lk:B\6 DwQ/u`ZЁWV{}iyueϣr}es_\{#Sc< |j4W>"u0Q"z.GFL _v_Cyzh9HO2:{b)ht+E |L*,gSHs&&_҄y,AUVGsցD\4_g^>ؤ M 8^h7M-j]l})%)I?34warx77|Q,\{Ln^wP2iTaрf-pu4 $&LQyhܣCNvAń8R#J ''꒝M _.:SٔmtRnE|3wK0Xw/|販nu 9D\mNv[*h-d1Y_u] g<2xw 0*T<~/^KTNOWtمMG_}@en{2P_兟_iy7[nY7/;N)݁*˯TqJCN7P=oKaǪy;sX@*-*3;W2J!]E܄' VtUYѯ?R}׆q}9Џg`.}0t?C>78ŇksR젥Ři^NJtE^^>ߴP\w = Wb.8zi"~o(wEPc܎ PQcH5x|Ѓk_ 3)a4z+迏fBi: tňa"yp2yz` l^|z4N]ۑ 9d?*\#oy'mFp/;ShM/Dž]Ѣ0\~}9v:[U/;nwtG9 |+++/"mP1/ބ`o.(fv=C5֐3|rGf/GS<2{G$}o sLk~< e1 ;05\@\QvMI:n2ר|‹ = TҵvP5.jDj$FkvL.9  )(FO_2l>Sϭkv:}p9XT~:[, }&EaޚJ.ѝ Q&ڌ׍, fƏ` =0и/c9 )ĘgITDo]@f3AȜ2%&LI%=R8pEW`TnLMJyhH 6wA!#̃ aWJuSJͽnXn(GV>C#ld^7 o8akV'+ vV1v /|X:>bHX(:(z]of{ k86 Nk1f;A;`*}˭yZ+z|P[d S署}~^> #leu(SJϷuig@=(S^6tN`\S/5zI~MYLSz=H <<=>{L @٭赼=GVw 3&l[S?ob7o7wVS׻kn=ϯ]@׋&ZoL5.3+޸.`Qzyi5j*k-/x;#^_0tFFkRq tl xo#TXQ}9u`)b$_rSR b=V=2"YL0 &ͅf3w*ʟ=z emQXzqI1D< !`[o@'#0a&9/s)BcSi{߄TX3Yc]T}]%?T ?`kWPabX˿:HJp֮gW`÷_.#ho?U9םqeԎpޝ>70::t"$$&T\:ӱ2`\!`;,4q"SLAgLlG#}~4a@ҔDw0zvڼTܔ F/g` nзHs@;huz[hL k:Xb־ IET'z&X2_3p^LV)׳k-ϟ%ś1fpRzLؼS=PS{>,υ3o sXS'>Ў4O:teh~bIFaZӠ&Q9Qrd Czn(Uc=z@! &U La QR q" YBc s$}ha2">l!Q] vK.2_ fb&ӫ ab7iQe=#*-q|THXO˒f`>;2Ȼru:lF-^ Qzi?Nl:$^yA:yS\f0Z=zL_ƄTcZJKN"eP@m!1/kOO}Pҩbp"a,ʔDVY%Sh;?_'#[:pe|W?,ԱL3,/ /g?=MhC ;~MlTeHqL(t/Kx;}L !Fxx2Ž*AWA`GS a&]0m0QH&=`+G ʵ: kȀ`|;P>@cdNR~?P&Xډ}Ŵx-ЭXq*;!t+^jK]Kp&cZL e٠\ځwn 퇱Y ~4}%PPcA@ zd7IuҧG'@yAŹQC:~k\p>wz5 X!ՖK!zk j#g2CbW%f isqBy'?.ANF)iNN=^Jns.Í> SC? Y0 J@ w*h:Vd09@Luev ?|w#+nQ,-_>G~#ky/wA}$=࠼NF72p MS!w32S'BNPP7j?Kסԫq.0F 66D=R>G^jm E>"A>CB::̡[,o4kR2~) ekӼÊ~sk4ohr12|lP9[{n}^~ S;;k!)Hn~BԖآXʿÂj;is ۢsIw:܅ZK ɵOȣLM%~t  ?ss*j1$$27p굶>dR721HnO۽Z:{p9swzM=eA趕rțPP1~n;V6 BGuj':@- F4-:o: Vs`&XIꇡ@w v|ApCCϗ^C%|wGMt蛿Az`}T#Քn #B2q*gr`ep*j11`nHJ]n|8Z[۝Й8Ɵ` HdC ޯ-JPqTtG 57=ldGu: G>Y`0R@W3˾XG>W pƺ؊ZSxG~E/¾#Ѓ;t^?^76BQѨZ >=h?!BPP =҉{q2)QGc a֯&B|jM(h>FPMb;Û)Y>R4U%!%Ĩ>kJڮBџ1v)?):@a9cםD=)ՙ =iN@)GU2A!sK$M]Kw4uQj֯!p ߉}BL}@ K`ƝON yb^RC5Ց4 zJe4d\NiNm~>{=b=EEaUR]@:{:3 ~'Ov굶G;>+ Hihq}HHO/E f 0#]?n~꽸NU)sK7e2MS{~y_c' j&`鐒9 Zsџ/8b c:B E817_0Bh}f 8(#my^EPv~fŻ{$QA g6wź@>ꄿ5 a.uꥶ̞^Qz s{\1s׵[90-Kr?kL' gNXPgo?A !J5;';U43yGX'`j8&@|'9 Z[{?V!J9q?uY +tZvIXaZ#Tڽ[XϞ_ncZ`c0=e;Rs*z; jԫI5.)z-*?@j";."ҖOvG]}c4L%td'24W&!šGk3?B :>HofCj4D4>Q:/`PuX>aJNL:Yp,#u%!:A4A)o;깮JLBkzr9zI]*UYԴ bǾCNaH:,_^|֌lXlu5kޞy䓦(XǦy>mPX|ڃR](m镝!C9nECLWD)rfFUOT8N^9lQ [Q >_W:YRoUWf0Ͻw&[WO#;('ZiUM 0(&hAQtg.GW'Km ), +~}޾';$,ty"Ky'9|K@?l7}p1<dutmcퟍE{=dubyEW|{~ϬwM+SӞT_i4ԝyt}rVÔf|M7[lǣ?u2=xl^O0Ց/}hx-zwvi[%C͢O>·jlM.W 'Q ܧ/9#&"aas: .ޯC{Sxp-o@Ac{ưN0yaAtb;k8\l}Q?Jto`~g|_)&/4nY:seNɈ-sӿnE9-<:k8TG[ Dƹ>|_X+MAq#ꄾ@(iS܄%Kb1X7A1;I/S)?|N T.˾\99 gɻD'YJnwk\^R߼י?| :6wB<ڻ uyLt @|C/C9Q<O8cp,-r|d֑vTc|"E0olKt)2j%`f13-88bMrcүF+O}y< !͉h ]ltl:F3&4K L^cG|q)H|= qLj Mh G(`f=64BHouHbE۞IDboCT$/.u2'Ufr„v굾gG QH}J&ᄈB[tIVq"* NyKANU9M5Dw>!ŐDB資dq%-24IR#chƒ#0W҉o,q]T+0EGV3Kn33ə_O*.8RsCR+:L(m|y((mD#Mw1D:OG~`v#kmt'CB3Aɝ@D!g!Y[09_ L\~ 5ԧ9"7LsՊnC+`1B/u-$i 0˱!G#>`;']!'6ȣs`w2cwY鵶:!=O!#RwLu)tbh(fOHjrj)_ T9 unhKϽj(LlGc;Q&NW RQBy{3؟йM|] }`vū%j(kmPg8;qq\Ij(qBw)0tIN|Ex' Now.e˜Tk6,w&$ʹ?Y #GKuH:˲C3@3j8fq˾x,k}옘p lO'݉x'=R0Jo^畒SDǛC`M+}g1 7vWs Pmt Åv hvx,뀟oB'^@pHKS@f B4鄄<-$tyP|g/ mDc!c tKK/<218paL+"ImG:CaVB'6~CYC}E.Pp vZ fo`);Z[iRDq2EA]s&LOl8x(9.GCd #47щQHVq`c1MFyVpHLyphmSRwC{^*sN L,$K<Hޜ0>@1 >zLvCF=49G!SmB\4UTi-39!HASeBBYt<Je2ur;5N2eHOGkJP%3L)S(E0;o6)Mc~H/'MvH[nh"hMbH[0% PbJ,*a:w'QtO.+z44CNGQBY4$9 ry{4t鵶`i׼djh{C3#/p+Xmd߀YțdaX ' Qe2nEԢ>+ eL`"V +j0EѷY[T"LW0r=5MJd@CfvsEI4w Y8Xv饶TonYٿ KmmpdZݷ[Vv& OiL$=GRcBoZ-JX (x2bD  0>+[ٶ:EТvࠣTo@(k}2eQd2), u T_̅}ءE} DGoB^?,\l84)E{%2<ԄS!eR"a'4Gme#eC$ ":iP0[M78(k}2ed2% 5wqt~abd߂Qƛd5(PWND$="*`qViu.3J ,G힊őE_G4ہiz+C"jz1vpeX4ٿLht$0FŢɾ(Mhpc)99YaM!dXEβ$ds?UNо48m5D#qUWáE$aCAe] 2ֶL/Nشŏ>cL0e>ۢ`Wބ}rN}SΎ6SչoZ-uzDjqscQ¨Ωa35<ۃPuȯL˚!TV p#l0Pc@7t6f Ln2۽+ O.ÐY [P6+$3/1$}5&>bEGX# J`Q Xy"ђw !ADA72ކS`:`P-O{!Sb`ww6`rvbFnMfDۍ͌aX*CyzæEY@gH ',J[8xNl&&Egħn bм{EG~css(g)fQ۷ r6gqSnBɤ!@;BwΤ+~!90&Vbca(O&v 6I\}=j!][D bF09=:Z[|vL,NBQu0"!h}\02-;IC5 ȔA!iBAXOZ[B}n6~D7!ʉp!"``PcxX\<ŘsVMq_ 7_TNq93&R+ۙ_ SHo!)1ЍL仢>w9w|2$;U"5/}vd wQ5]rPqT_Ϣ1C1YriNy?"U{(S>BT69IQco?vs0t6 5˥׽咽cm!0Ꮰ;1;ܫw/0enSsa<:+ 2; År=bWO b)OT)3Xպ74!@NQn@yg66>XDvΕpV0j @R'pgDt: M+|"j>*9|ћ&krF V.zPF:Pk;bD!vT+I!tRBNhr*ǬIB1w0!aVz+|T Af ,r$ǵ.`91uq.g8u8Ko쮽**7`ݕ+#2"֚t8*U˺O|NU3Ya"ׯkm#n܃qFjo\2L,&fa{4s6f73|w \AHc2yBVCؒ.ٜifXCq ƫz 8ydX+FN#_ %2xS)0p$jŗ@AFq"[6|^5|ϱ0OOwAf7'z埧O|:/?|_?8o|_{݌~||a+bݗ?{Mzt?17˯O_ {??WW`|bb$_^x/ w_;/_֓O_L{˿TV1WwSGAdž|nB$ퟛq:Nl.=;ӻvA&#J_?I[^[ շ}pcxA@?P} IOx;2ʍ2sѻ!`**|OzW)7K Z&8i2VruDZ’,v?M*]O"[j𸼰"lp^vMt-ZI6U.{/Yv[ң 툎ĸ51j2ꪢ}GXD)@T8iʡGlbeh׌V)Ӥ0:pyR9Y(jʄҍĕW;Z@nTv3r*tBKw/kó,5IqR0w0Bit7Rt, 4MjB=^M:Qt]hb]hT| 78O CbSSînq?-5&nQaZwK7#3Y`Q*)~sdG޴j8,a2X>|\(r[7EúITo/BBLC VMu9] eB7GP%nU4/'B/<08 #vtu@ 9+ȿ+V tNZEh#23-$tK'E UEaK<k"R6fb "P4 2.IHל #DnzL9h̸:nF=!!Z$}[)" EWbnkQ%ߪ=% F]u \dMN܆rNu扢 D]DK%>' OnkE4z#YǼ(tCQFձhBM+F" [P89ؑgo W'Q6Hz){!c )Ii=[>+B_G,$|`-jV}{`MexLqD -͸xXPF8v>/+Bjrn.KFŋ(U MlA:bԋǒ#Tw@]NH#sV(/QD.8q &іbGɿ" =y+  r ʋQ`vc#do+E.^EW#bRjk %/bi+.on#4zK*WoC3$Szxޏ.j!wFRN(sUĠgtVt:9'faZË` dޛE1j\ĠPZ 9Y]f $pAV7PMlu3XDhASL1,<2+B >_c]Ԡ,{U&Y,]G4<Ϊ\o5%Ƈ|60`Tϻ_] 1dvElӀXf P6y[ӻjXz}+6Ԡ89$zWM EA1x:b0gʂ*ĨDihs }W.zapɬ GViLviyz).M̑(^A%>d{nDB!]T:*[h0 \P> ڢpG:bda%2 q1u^)ah3A9&KC%GEahaeKm<0נ'E(*j7jt zP!heA1$5BCweDh }M2p:"4a>Y\(Ddʗĕ8*YDHDSfHDgܴzDD^WF x&{(5[٫oBv@t9+^e#Hn(E$ySA9yR\&H *E#zV\~ةDh vl &ļ٬pz -R 7SFQ9->iEM4h~8"F]Ltg:#XԗC9HPU.ZEĚ[Q9ױ hE7}gfpzϋcbD`c"qYsi۲ۖn@oJXYClMw!]'';DEזhc6z1;mϪ ԢÒBch^x>.} ̛S~e3{´d8S}ڤʭy׮~2»/J)#Q}1JWQ8H1z ~~2=WLwoON_+V~+ݗ>}_C??q/o*?o>˯_ˇ_߿ӈ~ûo>}o?~38.Xg_~ögA (wx//>~Pg~˗_xs~&3|}nz_yaO?}/~᧿957?ח>|?r?/??o|Ãn x1|`U;a4< Ŀdo8Pi䌓^r$!1xqMo}z8L$F8pS!E&Ex7iM#ş}-Lt2PfpH q+wX)t'Yߩ^=F ihXwZ9 CAۑ7MFY{gƄ* he"T$Yzxr$>;$: Bdiz9&RCIhm'I>pJa`L/;"#N{6 N4Gՙ /s`'Q{Q9*]fKCȅ2;;PN{|H(C㨑_Ynz+>Q}JGμߴCtR>.a̺4jMHK""Ef|>Bh]h_a9Z,ee r>/)? b2\/gF{et)Ŭzp3W&%*qmiWCbߑjrTC '(F+DDɦ*E|gj[i,jxXת-;PO@0{4͘cDWH"ҙn:BFюR԰$N ;DiՈXdxHo\vd8H6z7Y NJOR7G=N<+G hd1FiSbR8 IJgҍS:ٮqi'u^rrWLG\BKg ]ӏضtYTkhDM$5FwZw4 [D{Gx0m" D`8͕I;}]oZZs~vҵ@ɫJQ+wݖX(4z*أ943hT(is]+G7@ȭru vU0A1A%sg~8-A^@D[t#"xZhOZ$7'[5zl"Mhw$?ss!O&E=0^=b;)}zJi>LZٔ;CYT>G8TQϘSO #*4.݀>3U%T{ d̒MoIkErJD?)A О]x:h6vQiFC@D 7m*]Oa6^1"R8v2!!Zh\o-O@GHϢo-HK7aYwwurT ZK: 6&I65\Gh9-S!6m̳27hh8^i%ƔtLn; %i-7o{2<*g9_ Bg&\XVt=2ƇO9i亦?ce0g<0.b#"m.uAYcܴ͹2]*waplHl'4`؃Y،dJr Y7XjIHwzk*ÝlFT>X/zvjV"ۅ48>Au*|<+lbfD=5WE=ͤٛnv&ӁdLu;+Gm9 p\^JƯR+Oj,,-o pT#ʊn]b6q qsR(ֹ~m&v]ʦsN_yt鰢 ?v/QR 0!iumS:6ҫqɮQG[1x8aF_~2}@5GY,km4lVq"BPM0Dmy0p0YV!_d2q0QHrF4^ EW )YbxnBp@kmE ;+2F{So)t.gKN~"GӴ#hQm36.HL[$SBqMfe+Hn;RM+FâRȊKΚ㦙oK4T?"ϬlkL`KCpl>ex(E 33b1Ro'r }&r zCdˡPG4eĤoTo5>,(-odZԨV *%"FSeO8e[ Jb;bdd'©9ifLǡC_Ϩ[ yK6ɋtdYJvV5R|q,+C106Ao Tzq8kE7o3昐%NPκw=F4WnKr EOaT$ga8(0ӂo(Bl]eLgQXuȥږ^ E7H (e|@Dɦ]С{llRT&5:Ylb^r+SN?}[tOycoihnUuIEWv6K7ᤛmEM7zG#;ckug:`mOUNg@Hc˂}Q6vQmtc4̔ Me^-\>{ד!__%J*9̂%L])q2kĆܯtY\: 9U'Ƿ@'5OTW(뺁;hl5C_#]$5QkϞ}g_jv CAOE;bD;dB_րev_4y`đ18=qrW&t.EFIRb{eu a0 RRjBWr?< $>Lbʹަ9rB9a#*w $u;ĵ 1_c@(؄⅁y*FM~neHzwdU䄔f@#v@w:s]SNA6L@U-RM &D ĕS u^6p`¿-hECW+9}h1C/Hus{6f7E7_ȑa#VX^.*F/=z ٠ % h,_ . .nCĂJ y0D&YPY6V70F]%b\Rb=ZI'N{!ao s)E9a FwӖb@rovtr==,†ϖ&*s2c⯮AWk[ ccԪ~ qΊR~`(4zx7ߌw"L4I9`f.!ByR~^Z4tиt7L_ z%_59֣_AR1Em\{= &K^RS괠.-$P݇EyTA+Y~-7]Df'!?(*t-.CYȸt'%"pd)oc#3Pp3=(V UokM},L)U^!DkzP(5gTQ^]ur鬯w$>lo3T6& }FsUMgm*\Sy>WR%fPR sKDod@x'pdJQz;hB)0vMEwߪ{^+?g|:F7qP^͇nn-+5_z@VF7[? 9z-4o M7i],Cma_}Oyަ毽KOn7gn=09|ݐSj&}QUI6XGWe$b^c9Rڍ)SvwGs.'3 Njٙ.O[WU`Mar3aU6YVYbGz+*8&&x<ξǜt~c- vMb@av\tw#5,;tGzjbJ3&cuq9W/nːc3t#:NdޣPwkQhάa'9? 7|LO,>=7!M5TEsoT)#Mh?fXxE'SiX{5( tMs83wR29 сcMFiUxDˠHyl]iHlRq*tv~[@QӒƃcwGT{ &E=jBz^ E.2xpDC6+45+Eg7ue%M07Z]ɳ_V}4y@*$=`T[SoQvO ;Kr&•swI0(`Ƌ(OP#*JkŢs=nNLF1ڂvKTxlu} 3YK"3$|Qُ.<Đq"S~ɒnBvER.*%n}KT죊nG?(O5q.73]z&c~ l0qirc442`~AqeXXx*V}b2,_ڦ\ZZ<n '9cF :8u }d-֫;DYEmsY^x_|5(xO,#gr I([mӋ~RxΕIHgQ-K&vQy"]I:I9Yx^rxä?o"S鲎B`{!* ^g!q4>hټh/~{XxJѫ!)]/19lc5%{oP+wVben=S?GDqٓVhV8*z<>ZyڢDqTt*eY$-f1o!JuhF/LV7.S)ԨE &Hj ,Ifhtx(Eҽx2ZTȧUsuH[pdBe0N6Z h7C5ܶlHwqmA*[Y{aa(qi6FI"5@X;E µE&v Ga#B8Д:BJO]4{LJH D!̒YR>e0{\IK!Z@ <P2iUv?E1J|pn𜬁N@C*I`b%mIΌ8NqUމ6Cf,4A .-Y*pr)trߩ5Bm\z=B~@vDf`(5:lO'vY_DHXNR!! "s|x(Gc]c-htMwH,J>VB͵S# Fgy>Ʌci5e"#|j膘LOjsG4L3ky CT>Oٱll$UrB?s`W9)ƻB647/ I<#xdW^i.v8e"b`_#3B}'rXm^8jQw]wL"0)}Q,CgI1R@I%%ͦNC|hI{ A*ɚٍK7 bM!灣SXPN4z+kzbG wqVyg EBha*1Lb( zQ^} A̱-+f _B g;NaPR;zd,*Kp%xtIb譭B#{L:TY ƕ+u1@pdd' %ӽ1+b& cxX8WpyE—c8˦,L'f 8;W-BmxNһ`isQiNuvi9)P`S}&ޱ heΊшn ᎌ`=@vҪcܬUOj$ĬB-T> Oil #{:⍨kGr*Dxj4`5R)cS#-@)^{t`U/NǓRPBMkTYga,qϲ]3> Gi);fCׄ0rg5IM|(X*6>!DvNnArVi Yx-O wn2j59XlFA%7cVva'n~`i2ЅLVDHs?񷚠'5kxx42J4$甎zt ߮]_\=E(lY3$ƨ߀ԟd/*~pt:}P(AUl{Fg Q\le2}ӲЛxדu8x:b:8' ~i,1:woetCZȜ.G>ymhq,7w;)]Uɾlo՘ DRSiu3.2m4Ws8L=)xݽ곂,*Ki:dJF j1!A>8$ P`%`B h1IM; jB!{伩 E*oIz7pl`2:fR8U n6|Ѿ85fн:Gc9b3YߖI SzH du%έMiZqdO`FRF샹 Ҏjt9yZtZ -ߎ#3@8(u|rQ:كjtR&gPĵ8FvO:P?uYL:4*W6v<_0mGKQGd%gÊ9ś:>̀딋tx(j I.],+}hh5>RqWqh9* |{0;Nso\Ȯ^$3 s:z( Շ5vd9V_>^b}!jIcֆlS+J $z,棹ZodAۂiwLLw({G~nEOA\?3x]Z7!UȅxR[80/|=$&g?W1s9cgOvpwktl:@54JO"J~erac{ѲS_IG4eZrqP3@nk~ܔ1ӷޱhP4Ad"&c Iy̻skRwsp%j ’-'/{^hdOc4or> !DK6G\ý gt]D}d ׎190W.%IgciI`wn (R|WWcSAzJ1q(slxUqd/^ dh}|454-~6-k?&|1P,[Ȍ ~_X`@ۍC5YD1˹L&fB`jUwk[b*;ޖws8t.-rͬ[&rIм7ӐyyB,iDL~UziF0j||Jh[{E>ẚlѐ\: ;Wyd!M7iHEhʡ.ە.vK\yAMnR/``:5f@tUHq:m`Jy֏:(鈁m8kW$8K%~hxEra+}t]$t;pxhƚv 3G{#fuPBkNΌexVP~)nG~pXڀ1MQmn-?[20dc0,öE^L -?'xGq?i NlmѪkO@FpUcH'  !4cdEAW`Ѩ-Irpt۠cuquUOtm jlCT~/e%mo،2kh5p!t)tԌ2 =֛Jw.#g嶒m(Ibp!QZ{5&Y?/1(&,5uqS^t,5$ iL#;>BM"G7#z:E)Ņk ƞ^-4?U!·Nt̛ AQT3fZiva_Љ#mkĢB#e8AVq )Q(+Oz|;"Iyn-AHzT\o Q;'iϺsͱ/* z@Ap،T%d8yis5璴V_ g9]G ] Q/W-c+̮ +e SB(uM"3QAKLK7+iyE$[)Qa4B9J"4c+sUn"0ҫ!OZmR7śyӆɨ_1]+㮯Dh1t!C,zx֕;>L,)K1`0)lH|3tĈCO̖ ʕ``H!&)z KEHI\N.9*8cbd_O. ݷDڸqfdݦ;oC,E94j7ue#W|<: \E nS!b/[*oVKFXn=.L9k|Q Bc+{ޡָ!͌YChc7ۚ8_1(:MQjzh{Imz!*r+;ϠVNQ#"JKGD5x8:5 >8`=ɨ_{ͅ>t?!h/|1ne3A&䏗ʗΛP?pi]qФut㦯z ո_nF/|;?ϟ~ݏ׻{˧? ?%{zfZxAI9[&go;O_q\}J)y5Cg$Ȅ+Nṯ]pϖOh|Cfhdb5S6~,a/Ws ƚ^l' YݘBQ7S%R !2ZzK/w_o̞9uEL)FquVP?vDm좥aD`xP'4 rrWsiP^ޚ FQf3dEKwׇR-\Ny@mw-BQ}#-OH O{J4˲Bƚ+EL]'-INhWU6Zu2Ow2 .e2 UIYO͘(-BxwƕM2͋EOA܇t!XgM"ЬNଣ}bY)Eh]@8 Z s9,WϮI+x_q*ig'&l8~,ֆI-AUb2Lvdԁdp<%='VQJ5&KZدdaf@dBzLQJ:{R`@ia68xTs2CӦ+w7Ew sH(-ԙgŤm8 2h$_ 9d.I$Ejh4{02L~|m6Q[h%p8ATt,@\#zNL k>%VFFQ4jg±'Q 2`3k$选]4ykJH +ErakWNEA>@0D,@g\3Ҷv$$ULB}G|GDT{Ah]8(Q-B 9ld  S:NnqZ|;3Hof%U7#RҸK3F"'` 1D=Q]Ȩ7MIĬGz0(KN{"(.\]r3dgy3o*w-#}H4nG#E %:CQ[H;,!¥:>8y4Q!P"8_ŀ68 -zl좷`g-`!{; <=\P\mE=fILh|NʼnP\t+ƥ 1Nn]!S `h0V~ɅtlSbDbL|ՙ~\Mv[0͕Y}oĬ+r P}BpN2Q%D~.U$Ya~iU76jL!Zj+):eEmR0?F15- MtlWQ[Xz ߼s}ƣcs*.l Fߢ?Y0uy@q!պ". ;ii88j`LHKGoxOraQ#h.,zv^ߞ Bɫa][`:Ynt)28dcIyS(81,v6Csaqhr?ݰ U>y5$|rPQ8tqQ}lnc)qϖи^Dvn0’8Ca"GF&z{Wֺ2є%0fmuTrӾs%l-$ͅ\( #P!h.;ދqй@>UBސ(5:OEuaƤ*2GBfl}tu8Bڕ=. =8MiZR4sCNb9Lz7-ehjPMY"pZDfjՀX4tZպdAbިa䁊NڜL D^G]8e.,*S"]4ho>-ʗ VXNX#COȋBX#,' .rTEMGq]LE8>(=Lԓ)dwn BnLWCY{  *$[7x2~4.*9:6]\[E{9\$6AWِE8^kOiZiZ0֏?6 h/ToI!Zҫ(/ }/.*6ȃj%*ڴGitNZf) f3Zse XXOM좻|hps譛 D>t,jӢDOZ׶:c kg) TEux:#UK=:OioZwvD>tn3d5h"1~83O-8Auʱ. aִ2G1G6Of$ۉdZ֠6Hq.l!x] C14 y[Sn[|}6}jiSFSA/K#ڦ(ȦمLĕ?:-C\,+iZ]huk1ޥEW v*I)-bڒ0I3N8C(( xuf7ap'd $&lx(4/ǽ XALAL9TYxz7<m" vd8~- ]#| a$oЄZJrYXyp yIq@BU,)ɂ`.6z(/=1jyα>|^دfb݅f8LH+gد^ٓiA XC;z(IL9 !d|kC.4ćFC=ES)Dc6S  4Tot F5GaKhB hcɅ][ʒuQ`v1^ӊvQ]0KZEڭ4y4[jnV63Hs:("p]clD[xU{24wlMoI| J̞CY"1$̭W]dbs5炙RG2H݈EvaQ1PkOE9\-o#󡒠&ɋ o+k7 b '-as~\ݲŌ"UDFwiR嬯مD"3R HV]H.4EuA7W 47Dtוa\SˇW!3-9Λ=G`"ït2pLH ڍXt춵c"dD*xe]oZlz`(nG2BvTn3 vO}<#*cyo vl85֩!tamg3BmGҶj,V/g|v M Q$_s[*p샐(=W.nS>⎙}I2 wG6Ty:6tx͵3O%+2-6]`]s 0ic0|9 +p q4g&3/l:مzEw=ڤhe+H/g?69&BŝqgYmXظ}$Zɦ\ 7@-uiUUV'*9BEu]p2.RLmnk{M-,;7^G˯0' 'QWڿ 5@_*a~lۨ45xIXOddozk2{#M]AgY!3{LAs ?T"Ŗf26m|6:æ6)Z>fsb+N+ZGѨcTmpy_1BC}dxlYkF w#(Fydv]US BK~Ep&%(Sm<{"2.es4ú]MdAMbݨ2lH #TsMnTgN>u0$:osltG.a[? =;e w%Kol1-at CW J+=MÞcFh\zЕDTȦ^.T߾hco}j&ep雾һ ם[kB%2e7@)FYF>\ 9lߡ.ZS#2JF}7'"!6)[7F٨c{B4 )[!AA݃G6 7ofB؈H3'#)+f#?ز8?ƙ\(ŀ\2p7F3. a!+The%:c#Ь켋 tgV[ahaR{P1 HfLM咷nd= 9=upꓘQCCF-م<=Bi8}).h}6tsB4Dqf \-T4J˯GF272*km$.ނ mշ#pzpH)NR<E> :pI v.\ㆨR┴_ {/hm?'מ1ʤIY ne:1ɴ}2+ ! PEF}Pg9cs. H ǀ&ޢ轭-X |Dߺ74(D^є4D~}> Wŧb,J 8ށ8eD@DtNG1(b4oZ<]>'_>]m3d,qF%m\HQX xkMh,A8CC[om%=u4m$' 45GSoxy]LɂtX±s}ݟ2QT>d(\p jϝ1)<hO0FpۊY&,V?w,C(X'AC΃A1 =rKE<~G =ww=l;>06rjC gTҊT __rvT=MsQL5̃)]홣3O TCVşN 8$3ď0b%W/ =#cW,t> c{rA]F\__޹6MJs,֓ @YuM1I!e@%_FL 2͓-q@T2fD+|wP$SPωC"^.9+–W'pO_{\{u_*똫u񻩻[C>=QퟞqG Y>Kǟك6D1“X_Bq^'|mJkh=$,Z;\>żh ֑o6h'aGV:ѱ 덺#}&jhPN  9Dd;@4XE4c"MĎ\Y>c~x))qF#YKJ 7m&l$uW)V=WbQcV; o%Fs}栨t{ApTt=aϰÊJ (FvQn ZH !+9%-J=_$~܋HcNDf")"`(E{Q0 S,C„nS01aSJZ(/ 4T:umpgym՘XtEO*rB7vs-׊VPe5p5vjOi57KX:j>FlEϪHmZ*9f (oE3/!3Iz[iƨ_uBZ;G[zK fI8S?ln_#k5v{iҲsVJ{j5[ B.q$ Ӏ2yE>&lMK #T#Qm4 @IG?VbQኤ>705tNdqJɂ1EN[-C)\)ə∐nDȁ*Sٸy(1 {IiX>n)LRNm2WÇoDo>V3P5n/ͼĴ>s q3'yo>>Pm"w=}7y-e 鬤&pOIMX""X]i?RI"/jA(fmي pHhcD o"ơNݨcZ&5N-57BҢ C1 #l]Ho2V q]Z酾%DWH"tN^ k m׫8k ގо"װ ??Sx%5Eާ5ZBEi&B[]dWn%vTOKVnÈMJyY\%`t84) (4mYUAB.vzxJ5c{]Op= w;$Q" sֹ[E.{M&P7⩞ TǾmפoV*o2ǰZ`LtF%ģ3ڷV9L ׅn@@O$ZA`0!zHHd=([>Tj)iWbQ1>0Pdm좕zFhr\MB{&B);5G!q彑;\:SpJ^:\1K[P2ّo{;*B%794,F:Ǣ"cc;2[|HP$osQ%d~(u2TO2E%;6 „򊅲O-55֋#J׶dqJ=aL+9/򫿗L|_?=o?;?ۇW;xU/楅䔺_n~LgO/g\h7p^d(iax4Sn5+ƯO0>ise\8WM%| ZjG@ҪQG1xǵo} j ~/oTPktqRB+TtKJ( V~Im?=޾QOfq^~HJ9-JfT "gk  Q/7Tۏ˧ ߛ;,?}?}?>{k毟4}\~޽??_ן~gw?w>.~yoY| '.'w/Rv1~{M?牸&bvqPhVӿL4z* JRgM5>i_=<..~d7*xNDz(w6;NOu`&dצ۱.#V%%MJ;OXNXwQ\6вyd- QԕPP,eNX\~ ~BR$ z5WdK-~o3ڏo0Kx(w+K@z~i+\~@g"Y{)~RJ$ }HoF,*[pdDF ֨d}ph,3솎]dL{HӅޤJbvQĮJs 1]> sHVR&見aoFIl) t"Y06Pt䌚=FbZEǬ$ltQBcY(xtd".z+©ոK\.IL=)92*%N`q(PC= B%BJ+]wY #xePg'Һt,BlW9[Q#/MjgfYȴ(`c ;iɨC+$+j;<ǼkIF6vHTL%U3y[s/E(#/]2BA[qwGiµWl !^H"єfA3!Yfun>#tc &!0!CHtX+h e9s'q^lȑ"|W6dh ql%Uy)\Vy ᒌjB R/ ߀jppW_xkc'wV삏"_J7Iŝ=BTH*#HSX  Qw }97mA#-p9rDW]S!! 8Q`ۯe1\# A{\ rZYf#{1dBYC8yO# Pڱ.Bb@G9S.f9%:B='sJo vaUa1*R5;vtȐb@dD2p5#ccHj@ehtTZ4 ^җU/+a4tRFKE/,% f( J!At)17hfXJc"zؐLrC PdC CCp&rX!8?3jزGYrh'̔+C`%8ɽБ7.3:Yt(ǎJ3^('EY]IaPN&a\X6P6Fgv"†t|CQo5?IIC) q5|][XK{`o!]/Q:~>ԽC}*Gh ":C/QQ-DFXsj "-ib]a*DGg_:DzSAů:DKWE4)UV UI3X3 V(xM.MbVrL]Wh%p_Z=b1n EeD\T j4 Cun>OAՒ?yd(l|QKhzhj~P!ƕ夛?)䜗42*pτV/ѭE?2E&c\?*cJN)K R44+-mvKܐ$(%Yac4cy"AP27*IN4; P֠Ny6ǍQ26SјeO7(g }蛁1k"k$ gZ|d?ZQlj+Κi?uؑF8J@apQ:tD޳.rnq35YxIhn|O05-ڻ L*9H6$tYY YY5#3fdzWY;OZsSccFƨcZY9' :i4!QRD{2YGYA|b)oVt"@AR? vcUQOˊȊ;l}3FHhĞWycVE-#T*iqF4eRLb|UZڳ&oƬ)T1H{+ T\|.vNąU`̊F6RJ[>!:Ӣb FvC^| ?15L$ ~A~:&=RIhr 4~IЙ+o,)TAH))H\@M&fiU'-ݔA'\jKC;u`l2 - ? } Bv7b"X%$WQq*\f` BTIH4;f``NeX㑬WMF82qFdďkbǙt `Y3p.Dzd/itV?N[R W8械FI03 e$ YDNfWBen38f jcDۍ=Q`U:xZj*WAPq@NJ 7E,ggu8&2qOx ~9^I]$I'*@PTGN&,' d^Y0mpurW+2| ,+GΨcÐ^M*v?TqPvmG '^M6vQ@k6"x>%Yy V4x\YnXGH?h20Fk&Zw` 0yUs? ^ ƍRfRRQ#4JRnirR(+ kzvFpkg Jlb "} |Ĵ|.zS܎A\3#ok}$.r6NLqq*RfLkgY8q{"kdc*| 蔄OGrY3LYxB&Fm,"aPH Ȩ@@lщp [ 0|2&]Q?^G!mq|a6jӘ?frƬ|lӭ["BnH2D# C.^1نFGl&gWJo<C B )ZWA&tVo_D 146v\qd+$o[#k.y/G== lvR}Y\>J.!?:Tlv'WtH;>Rv *eC0v$f+2a* aYd*m:dUu>>;HiFA0w.8NxDLn*)Ɩɔ=zh ޔG2,)!YϲV'K@8-۽]A$x!pg߸p&RȐdeHv*=$" t-t*6v5npteYwɲw9/=S|ʰ(5V%!K6%zV5fe;/n(Ww*N+jC՘v"q%)hh|E86VZB[MD &S+e뷞 x%veWRa̝G24~MXs/޷ހQ/bC91"ߘ?Di,U/jj 8DHZ{JV5a ,f_K][oA:QFz^8M WS^ mh-P#-( i b4Hgc(roĬapѢ6Id-ϜI}4ۘ3SCf3Wp&A6م۷ba Hu'E1=ۣ'e{;Δ G4H+cEgqnOBjlaNa1kuZ/gJ-aZ R.Ψǖ-HAPOyhm`2<]l3 TN)~.pą$(3Jx3D"` ܧMM8)Yh(JE*cl8f|$ގ-s5P>6,*aDm ƨc>{*)$4Lmv,n3 L S@/H "hߓ6xîpo)_@KKIm֟V.(27S"yUy7cx,uzcUfo]^P9N7/5Qv!P2+HjYx WR dE,.)J_^[aBJ$ J[nphU`ݦ7b&!B2eCeWGF֨'BSF$h`D9{hF.e:Ssj0,Hu@(ہpIqm/@qЉVޱ0)2fl ޖ=I4JP#{Q'ͤ:[y"Lht QJgxgo!mqQkȧDircBY]{Do.4P&{&l }*"7 0xqcfR6ft<ޡ Z;Z?Htd=NyUUD}thP{_sGN'؜]Sf^$o:9N U@ "sWkۣkEF{uzoeZxg37OoQfj!1GG֨ci;f^w|Z Os: Lz8{dmF}s=q9+6j |; rg73.6Z1և"hv"}Ozc)xم[ #E1R%+:ܞjo؈O$RtAU ۛA[FnnoWhߌFWItI?!Yf5+ vF-Mwdv>]};(25I˂YA$Lartg .y8,ߺm,V*uuVp"5=YN:o\r| eh7Dɫӷ.SSa"||!%۷M絀]ؾCHP^Yqd@iЊ鿂6Nop ۷mͭ1"?SBmQ!*3iv7O#">@G |=j.wčNJ*S"#e,n̄w >E|3%2;уbz@4u.;d2f7~VinȘ [Fb#>?N*ɱNdod;`cwS\*)0ԙxf[.dߡz@nKs@KkKuǨ 6ʢ0k0BF܈ipᵤ@z愚=^+ B!?7k/n4[GztBfM lBpY=oa J}i{ 7iL~mG)#HMδ߭afi(RF M:7,X*rݽUI!B>X EFDQP) Y 5e@4Vo8('.^,A=UCLsO$֝ ȏ*,7zQgj/Ϡ!?oB ﴹxZl03 ,6a# QR)* g^hmi6͐bmYiUF &&tũ$m"x4 ՜ ?}?LB©\]np]/SD_7u;<"(W2\+Wcʈ4f`zIew>};}GW?TFirH1x>Y/7ٛ 'f2ݷm XI7@\*fҗHC'!*m0ŨMɒFŶu~=&"CޕqV[6yruX7lڇ4D \ ΰ}]3<}86Vg40mW;d6LsO_B[8c)Pۇ&63{J7*m)⬒{?puآ\>vobSǣ~Aa`Qu+pfS&b}[\>%([y╛"ML'}o2'!_R:.X&E'GJ}6XAˮg_!JԢG?i)T=_FA`d-,ngs56uרns+T*2O kGOR\Fp<HT"<;N>*\\mmB\[,l E˜ujXZ .V ; y#hi d( )`t[^M^* v@@} LB@YpgP:k uڼ%npU%&y7&^! TX$t]V*m :TvjWoˡTQ|,(:$HA4E/sz꩐.^YbuFpMa8I^уY!hX 3jvqYe5G彊;6&@>>$$/Yfu6##Λ@] ߢ8_cG;cY#h4(ԌޗVѾਥG968:uQ7cYȪ@5Ҁ$27FCQ'55V9#J*"IyvEaѡMT=BICT:i敊J6GOWBs= gu]vUduUF`$A";fHW*'yWfg汧uN0Sv4S}$ d$Y;U&;PYX .k(7s4+TLԴB{K{ u^ztX ) ~d=V vqU- ^Ok|3f9+RȣT&H ^e goSELR!-H]\R7 5 NR\nZGJ5g922 :(ovL+Ą2hJz5Tw^ӐR4D2:Kfd ݨ/((Θ:QWOJȭYtʴ)`P acif!ә5TacPJc Y@573!mjx 5{2yP({"izi;ܹdF.= 9e&6Y,KiT),Mi|gYQNs{8t&46-ȣ0>a=6 dSwSzoBNA1EF *.q:p8gAЮL TSorJ:AJa@9PEKAˢ>DJY(IYմeWT9KE T{aܐL*zNYTVhDI96?[l uHHO2{*'TvemߍAˊ(QhbWY@5[܂ړ TA WxaL#|̜\*# yFơћ+U1N&$) Qd4'*gѸnRwna5ɂ#Evt3g5ԛ~ )IRr0"rTň t 9ÅU|<’֖&f'H>5uF=D^E"լRX!#eH70B D`T`F->&YrpճGet8vT4*W.YP09fo!QBɲrV?TYYhJvp@$jiB;'NQh\|U4HZH<5cm+*'~T^ YT@2ϧ_)xr 3~g(ξ5ok0>_|/ϟdǷȟ?I| ?/{8/- 3pk)Wjk@@(^W{OJG=&=2m, z|ągz?_Ua=0҇Zs2s}cߠviU(Ky7) >}[9UpW|Q4ЗJ(YrU7D(Mlo<}jcӅVaWec#T΂ u((+$Y?ߌS ;ۏ˧ ;,?}?}?>{k毟4}\~޽??_ן~g w?w>.~yo.!<w߽.\Lx~o;7;??ʘsyJ+/O^ɦGG~~doᄒOl<_z?͗op+^?}yHC|TR;c:!~?So_'?_|:y jN ]*y>w!&o7eҩf~vj oEyݨr5'/@࣭Zwm{n0^_c<-R0&H/#Wo@ n>j''#* 򚚏ܯ@.C.omuJ[;͛г)fz12B{xMƻzIe!|Vo{pm/-zβWʆeûYN8z>^= .fV!/K^̚|]})*G-)ݴl\9;eÉ2j%g$ aMoV,dEӠG AFĨ{4*}Yx"KcB4:6~ iD>>ѢwI-.m,, csp*Oή&5N [Rr>I̧B{3&NZ>- Jut{%m㡠5; VGuD~V^ȕ|~Fvq lp7&'c=fz)e)": ֎.J,wEG,J>xÆ WDQV)d0J,xk54c]MR}m"\YG y#;NcEe<#(fv'cYfSn +gp)`SǙN^Vg%TmB>M|3,f%6AFOrWцF;Q' S|#v0N JS,:м]}uܭn\\3z>=RtZ+쵧&j~`TL.MWS斧YWϯOP8;fP̂>Mz(VNW|NJQi\ߞ})4lCn'&Z}~VQV T%ca 90Xk?p6 ڢ}R'IƐ}3:N>F\!trַXxdzq8ԩ沞;HǠ҈ +Y\Fg=%q]|R \$Eҩ]rwH%4 T.慲XNheEWSHz>Q#3fXr>Fǂ&!{'QS *$\4i. s钵|W8c-"Ӭ8H.S)MSF(-2Lˋ$ DZ02{ V-O]^qUh} "x(d7ќQÆE>aR{EG5EǴތa"*B7]|x[x!"<"W]b҄!84 Xx@ΧṀz{!7|\%+= :x$$65;X6ϱ|s_Ee}Dpfhgbd=fv:XB)z! ͠!˂E|vXhI=PjWGŏ}?i^$OY"*jLdM^*UqΜFQ9B>y#(;AN4S)/|̹]D} -A!:vX@Q $,ϪNIF-7"D}{ikAT +[lݥyWgOڧ28Jzse`<$=s%}~}Fvi: >tT ,vnKڌ[gHbihBF`Il't1>e#3y[5 >h)Kx^GwfcYVv1(4MQi1uxΪ>Y,&'e7WK!b$PqRd}8$jӂ|RzPb2OHDl:$S5}qb8_B#sG遈]T}dS`P /t+wvla*|uՁ%;/t}$-XƷmL <[FTν3E֨a0$9QkJiiހnް~GP"oSHHVa5>`_ʃ¯ED7寄k>v"}*v7gdEzuWӂv ߴxՠ5Xu~\ݾ*r8HG!Q]5i<A_(xxw&*EiZ/n<<1IJOjSoĨYj鋣BJzΨ_;j^DU,M0ebz.? Q: EDe2A=ԪFyg>(Ir-в4<AOs5?\8vLcn{/\E:~X+HYfhko$So~qF 4B*NϧEgET~Wsʏ};T'j:VU~(PӢ,u%&ge~ 2?u :sD~"?pDlȏ=j~O\LR@495@CQI)6HwMy2?XIE\2'J, cRIP\qn_~;|uVjQNDkڬD2ts1 /ɢb'vGDKn¥rCjڸ\sdE4=Κ.L`-ۻ1 ^ V|7jN. 킓YLp dVv窸$ofiRL} >tt.v68/\HJ+Hu LQ*Ct |V::HfypSg12$sF$4){,?mUωviFi»3 DFw;hʬ*/*FEe_FSG At=ů΋^e1'6N>0p~HK+b/檬A2(RC2Fe)V`3Z3)TXѺNXzaOV| !Y#(UɨQHKQ" %_joPp,KT0 $Hh-yLDQJV}2 Y%uU0n4YZlΨZ*?!1KХwZE/{QFSIr`RcMxVvMRf@@iE`ه52 mM>YWYƏYt12(S"Wo䴑y<,c>TGPZ#b#9#{Hv>Z ՙБ6 ¬dAd0}Tdb@vOΪ"aX Y:-pd 5bbTdo !dV'&qңP0NoIF3&}aT'RkC ;r9N1M j+%(zVq*J@YRL 1PȪ}*1 lI%&2p.IF%cՋatE\+8(N b\˛}bw۠֔qizVA*FR!ucN\DzZ:s,9YÇߌY0F5ܒ!Ц0Xɘf]NժDљ (MAk;XeRNUcvX+Ǩ;N&BEB#'QY?!L(q@l%w7R"hG/QKLzd<6߀F7[JmM WR2ٟbq0^h;-݌<4CPvu$exXbA&yV}ddVypWoNBѡ=BzVd!͎9i蝕:cTm.z' |I C @vrMJ2шb2O^C9gte^Ҳ=U{Qǔ2?YQF3 >LvAh bVkZwՔi0L0>!O 2=I,*iY+J#LikZ[. ȱ%G8~Bz3_50‰ %@틧7`@ ϸ_m@Kȕ>r])"3]dEg ecM aw JO(my?L x^ 7fL㺑,OA~Y52Ondnc=.ߣr; ~uH.\&!.D OdjOHL F[xw|22\XpdqZf|.sH3Hft> Ť!f:}.ukIDamak2ٸمk\#|h%@ Rt֖g VFA)JrIS28+MoF4nk#@bz3֪Ϲg h|:ԣGLKZمj܃$ 2KѣTn4wHG[x(L N-d28E5ߕ4%'6Y/!Z 1nK Q)-T3n&D:w3EA7J(ƙc$9ьq`M Td?~ND8E)B{aA63-nϸk% xhcDQ}fz $kՋP<ޭe(~ 'qB焛T.4>{8j|"F&S{%AőtɢKKEP# 5n8]V &38YY/u#a05\ްV>ZLi;[ASD"ab38!y;n.dnwHa,"]Q\nh!)V7@:zu&l3z\o@I r- Yڥ!8+W欚}Ƶd(Рyt y#"Mk4E L9Nsh. 7prsJPr53`G̴zL=sQˢr7M@-4;Ҳj93Ep '^Uq7F#D~JU ⡍ۜQˁ_˼ㆹ!&qAyDЎq7مv|EOv0 JaF![UTbPb4mD2AS$'C*ԉ@;΋ ߀}x[(ȼRD뤠5ZFCv3ecNyj|@OkeqsD qv cɫ ۩P_S\#}PDaIlcT>hpLH-S*4B3#ё5jv *ؕ*]1% ARsA㌔ 89#Pvq.tc%fJ0ڽEH!C^RZNpzѱ9M/P4qoG݈5$`@0ElU5{3]LI>XS4aqIl<ݱ.+PEӕSʢvԄ @hHվG>#TB+0\Tdq3zYyJƂv(.R4!ZG#kc6Nbn>CL`I?M &b\#Mu"o !#bFDڒ̐k JYf'A!+CGg:(^/0xDԴH})IP'ɺfТO1)SİN[d%ڵjP9NPLJSV |kfɏ襟@Șèa }_}mHd%%ZH_Locews]Տz-W\7H@3u}R/`Z-K F25+ 4z4iM dذdA gsb& ѷ؇L] \!tRŘo;UGp"?P(4n!j]ӧ߾L^Z잤yǟ~x;;<}᧷_~}L(ˉ wO_>_$Eqkgr㻯X~2<\z㗯>w50[O?=?O?)"I4~PjUfp` = ka]FIac .߽ ?= Oc>11$嶆7L]lIK6KƅH9;/wЫhBHe͖$c=t[F 6cI'Px4z$pI[My,X2FUdpLx%P5 (p:ǝ oepyG(28iQLCG淬n䘷g .**](xu:8^\2i|~3DfpsT(*ۼl3R?fo]f> +fz׎6=҄󊹭WÚE|W-TZ!e':ƕCV0I;G܋iHk@O"ilGnp4j6*ige j#ᑳiv،Sa% >NVט,wɻ8ܭlgY9`dMpWuG_P l*y`g.=.G(W7v>D0Z2;+km۫! <e0Wkb2%ב{=<=OpNo(cEUs]55VvW7!I hvv]f.M~%%ejH s\1%Yl ΃u ,}#ѧzU8?Ŧa2jػ#'Q﫭 ;4Eܯ#Zc]y a?Eǐ gXç'|"eY]lN8|>B\_Su\ՐK-Ð$mX+٦a;r#$m`J wHJ)\dgUpm]dל2ŢhPG,nD_Zaw3u2 W$yV緢:n~;~h)QlF?{ fgM]媀͍gu Ne5Š*Aܬp_Fnp8?ܟ8)KҬD\58I4њ*à 9VPOFT =!$ îDVvQ_騹Jh*]mI'/+=BT= 6=R>*=H[25qpǁdEÆoqRsj5MRVNևB$g2vD Q2z`5Wx^ ܟG"$cep}MafcYKӑ" pGp]ʃi4SKxLkP/j@~E^m p+#wiSrBj_CZu9]"U)P$ 4&GOjx+h;|UXb 2ϲDxZIBspAQ$ו.NߏKHn4B[C C2y>UypevꦩWh#M`& p4L=>tDCqZ-c m7^CQK-SEFV)Eql0) wU/{kM ߎZ) /L*m^A4; Z=9&ݏOuOE.m3uwf3Y2e\kW}[}ʯ^QyOu$ß>@|Oo߾O__P?^~f~݋yi.(d򁚩Z0.6{Rz~:@f$ feyP,Gdq[^PוA/57&~->k _@r>.o~Ͽ?/>~3_LvoIB\&.֧1n&')3BÃ}V>}?7(k&] Ԡ%Pn4GJ0{$,`PG +Lֽa1n g"r٥p$G (^y;5 >='-)NßmMa-#NVɈG~5YB2%#ݽ8=5!УIJ`$3|F3 XoTx9@xMH[<*n:y*)#}V)HaOfg쮠+.R"5>Ay*oKqj܄ʤp$,mhf'81R`ڸGG"Ay9tIy2)#uKe&Dhy'Euu[1m'/a\ԞCJ`=tԣ>oX5T/EJ,#FBsI~D箧&ęB?F6?_5RGIQ;R11eCsrVWP5\2y4qOD ɂ5@+8%.:7\v8eFWRx#Sf$|kD x awNO㕀T.iry% E}/zy% .;+0nz#Y.A}[ryg"$~@GYHΒR@4Ϋ00ܘn;6)΄AJo$Ŗ9^qM!͆ӹ)qXR&BAzw2)cgivx')}ko-+,$.O-Ϗ&o(s6G`Hi SSr %Zޕ|aU%]MCz 'ez}R2$JCJO`H\C }"IyɄgׂ8[3\mY3˩o$\8HqF9H!W#9p14ymu5633 !Vqh$C];h6%j] jTEgJB:氮+DF;ɍ`|A 7wnAXE]A26.pz4/_Z8+aI-$ HV?v}$L!#[5[%8mHuS? #7'M%iXOXbkQ 72ȡ8V-9;._l^W; Ӆ1[r3ż<+\ARޡ@ uذ%Z3։f?]AWE[ggv8{X?G1v~{CGqJ_g)܂;>uk[])3B9ɚwY'ԋ?.]Tnw8˩Dsm1!}ԂI_'r)J}/ʓ74,^7wG_;:T>^.TG߹_ܝ~ ʜaqҏUr{Eʳ+| _f|}72h9\?40C/~J}$7NG=g  #??S⏮ e~pP86Klq5`9) Ϛ,Su Elj/)ˣqH9gT/a-AU}1Q>n|4Dט\ kk=7W:~ ~( 8>!-IU;C|D`C<?(=q^O`1(BǸ2)6SG':1#z#Ur_$=mv|KMЗhJ&u]r}.MJy<'4[fRq ]ԇb~Q M_5&Sь?+KcͦuQ.I]"/5<B~oCںd ʤS,q"~~mzwkxrWd=&[`.0ƪ=ʛo.+nJ:{D﹉MffgCp׬K%/{޻C|pڱjHh>AtV}~<W&oϯz i#/,Wɤ`MoUX6?EJrޅ xV\Ba~LǤ/-'l;z/זbV;ӧX'<}آU2(O G.5[p _'kr3kW^̡3`Icj9J5>` ; tThsͲ!.GbC~}k89_ 3sNtt9җs7b=`‰mV&9?ċKZxSB 1p[4BJTco}t}c壝}3jA}L `9u؉^k'(MՇs~:̚k!l'(sY;0L6Y:qa؟#b<^!M0 qv.zb_gK*wY1[V =TܞyCuvƆLJP9 b!7^(v(#yKLgjTro{j}(X}c\&=cNv|^e)Vk<lN ټ a6%W)=A=H I[[M;Bl^?y/Yx(Bb'u[3s [m;^sF9l`ڧTd($رdhB  u~vSjaN6, klZsGY"֜$ҊatI6HvH5ۚK3j/p6>G+J^sQI5!='xESqURfלqk7\w3hQNFs/֬X 9V7+6ΠJ$ŧ8Q\bh7_YQi:H"smWR3I-1|*A)nXi2+6BK+J6$-ݢi#+:{/Zy4>N3QzWKo(;շE | {)YWukQ472J 0E(Ł6iyxm=U/.t7}l7nS@qgRH͔51`qvJ)f h})d_e}AZ%qn9A ~Cj<3zq1t’Cz\yzoB9ad2'/g|f=_Vq`GP=`נPf'unN;D$siSyY}{CRvHA!4~(l6SmF^a)i͕PIaH44lR3e~ (I=v]C"#=iBj,(ҩgygpՂ5۟O7w.h)@ֽy@a476Ȣw"~Ξ};aP=ًfQ1&CQ~Ӭw CL3!~ ||ԃӷbK=tCdك[(j̺8¹4p}/Tvu91C.đOJL:@~XGs,N9h=rtF9ќҲ):ʜ)>p쓟 fdHs|gV<9Js`ˆG,EyK0;Q p 2i{c҉]>}Qt+@Qu!K[)Wi0Ÿk[#N@.,Wo!H\y s2qjbS~ ċ H`ͺi/$]fxX aJfN|yƮ"u_r+4~FSTT_̈H;̢¾pR=aG2HmHa%(alMMiO@_ |g&!ZTEBC^UHC̿d2f!UiΗc~,F_Juzw +Ć"5BxOppX#5]4}5'~4}+ÚC6z \W>k~k8m( ft3=a5?쮍MTRjbtۅf%D٥Pk]a\̚-IDkU WĔ_PC>~p~ "örY3Q ;`+!w ^E`s|rXglM=)[;ҭ^ G~`r'6w;DLD2Ro/f ogrR}ȮH3s"Ps}O:-Z`܊_|ZaU0Ϯm ܕtExRQAru=Y ]YiMy4'DqcPg3zhG ChGc7+2jZ0MQ?`TԾ.KG򣕬m0(:L[(9[ۧTI;'3LHby XYr$6ýVF˹ _klg) S oJA žY=/'Eu_3r~bpJϏ,2e"&6:JBCtRr bI6uՍddד58y@ZX^tnOǺL3Ds`2e8*,6Rvv `N <# +RvUm '[!nmΈAx3R>h AMLOLYg=J-!<$ ÜCkXm ɭؿ=(S؃2YJ>c2peq>f+DJNxH)ERxHNk[8C/%"2h{{ݠԢ0X"X~J*n!<+8G댤8}#PtkgCHo6噼y<N%2RHtfr4Bɘ=̗r.Mb!U&b,H$ S.Y%HIl첝Ȟ8ZT5cI1l.R<udxNX: r?\v`'s2JE7T$}z0_LajMF$.BfřTHO]PI&B~#LՋ̹lk&yZm#io:g]}(?O8 9B |o7_INDR^5'8r\oʜ1`-e]zoapu]{fǵBaߝc6u^` j:񏘹]1IIw巷Vˇ@9-ٻ'lbl=S@G|Bn]{XlF<{XxpiJOCH./+ 3TlF~]YX;yya]4=m<#N|X8#S۔WPHu1 fϹ[lcPR ,O$a@MᬁSs;aM(Hv@Q#ӽ(#?B6yCq#W29=X ߌ~-qY 5qS( va]<ҵ1ygvNthdqu9d|ap.Cn{P{C,ʛI\l"H$II,=L" I/7gk,|PilNŠ;aMbpgs LU;bn1 [ #IB+qVʔ,x]Оt_Y E ɨ{lD?G =$qJcIҬlqR_}qa^_ɣѥ=) y>O%92q#$/3}b9oeYm ?+ۊQ`$k@80Vь4F r!i pjMi&8ta lن\d;PyɇS Sh 40IYm|>g(  Gk#m,K4G4ey H#igHǩݶ3. v;i&c(FszvfsX'k Mg01ׂY}[3Ŝ \gCʜš~;F'FAzć},(>l鼱6¦}0UsJjOMc F*g5+Xq4Ǿ!lM4(nz)2RMO! Fu[5I;eK_8@6Qo刓k M=!6D61nnֆ7 3>-`/ əab"7t} >Xf$ USr\r8O!Tl*Գ9P#%)W ʩE:TFӲ!$4jwn$ht52vcL-׮^>jjzp}J\Ϙ3llPv):< 'llX aTY|Ϥfvؠgl}!lVN1BGC)%;94?pQW!ՄيGC\.f/!n>mC;jC,ёvB| ͵yh$sF+1&J n!w̽ -$+y}BTc`>nQWFLN=Jٞ.\&kMf^G7]9!1_)&-]0NR:rick!: ӓd17^{1MzaԍcB$mugTP >8b)x2u_ "oٸ9<:{ܑ\81חm6-hm2i"9V*vTiPL~,Bb('R=G<C +م}Y_CIz S "aybU0B/88_[úR~Ć}pu_16OU 93\193-u(lPwDgʹ׼s!- PQmD̳8.s5,~Tå3vSSnf:d}N1D#KUي S0.yb{!6,SкaRtt]1*;)"b w!҂I ?ĀņI~%M|LlMI ENDqd \p%flm蠦Bc,A>J@f]Vc!_IF yf8$b7fegm.T p9;[Tѷ><&9n;Il$"nj5Bm;3S\: g,u_3rVp{R=q3g8Dpr_Xy},=?3 a˷˟~]f&;K$kru/mϫPpc7?_ʵ,aUm*@17vm۸8YgҞGκop?7b5 u-R@7 |tݟ^8ȥ* l~%z5|=3}#3 R2)d~6o+vxdCH06\V+Y\n #eޭdhzGg{VN/>2*\l]S@,ŘݝKk7(?kz١66vJ :q/5ow: TO-k91E`c.6mte4ήD ArҬw%I#ޥMn)gq Q](p}3MxMirMGCVQ1a@˙Cտ6|V]h_\YH\ +)Н]mgojQ2+&+aI FyT;Dₛ;0JoT"զ48BgxNM9-}W<`^|7w`R^ـEi'8k>V*A}[3߄Y[ HQ,.8GS xBgC+p@M1H9 X`toxHy;[pg;u %,@׮{oI;$~|QZZpkAWo;ăPMA* gY#$RrowޟhLd\;Rhp(?Κ~qeZ59s¶dM '`N{[R~H}ށG{ɛ+3T}$ Qҁ3k%L=47g:[g?䘸TW|ψȅ]7 {ieG狭mM,eO.ωg/)G{E0M)[9Bˊ E:/?(ywsMXty}Iݫ8\պMq'5S+/k_^F}IHb2RgZX_\Whxd..195:NUvK!X|)-qEvP?ԏk;1 Cs?#̢Q=Q b26w!Ft^~Ʌc_iɣ_Xg#6]0pf4>K}4'BP؛B9 KYH~Njئt;.1BL۹1rj]y '3mc{ԯEaՇ t+P1Cnm6s4Ts /AFv}/|]Hc)Rh)02FlC̥q1EX_-"t!%r_~cγ&?4e+쒀b6kmfeň3bhak&̾l@ٗ~@BgզY4kF s'5mŁ ^_Pxc~nd9-Qۄ\=ZYNؼkPl*s44 t+O\+ɗm!(By$Lwd:%R~Dx А#ϥVd9)DRgd'9A}8|;DwDR sϮM_Uɴ(3W4B}/7$=ڶ"j<ﯥ[IoWIR_ s{Mk ΐυMuDu[3+`2,C9݇-8/\κ|8p¦/!`76#3\ @;4u(kh4xtA[ckqZ1/܌iu>Xu̮2G|]lJ,I׷rOyb=}508ʢECn4yZCUz\3V䊣dJ&"g>  _~c32 ?jHѦ͜-Sp ]ȩ膺}.^`OΫb;~ֵN4 bV?뜔v_J.HCNs&T ^G#<>kO @7_4^{?ׇ?>//_p_~ϼ/?˟/㇟~_'?#o^|>1[~de"%凯 owVdYB"Nplbh妉&c9/-Kw+ tM\sٵU&gƒsD+9[̔' ǖ\gVQgf}z8>5Yb&+1uB崒K_?_?_~q|S@Qyaca" },vs2mB?C s"f?UTm`rY;pcVP9HT.x>TQ";2EO1 T\=r5Hw9[Pa͋)~iu5ے}Ta41^1ϑvrͰoo "jnǙaAU7Ą9D'Y2pH`YYΠz{;;`(MpBx*|Qxu{z(lI!Vͫahac#7=eR bR[B(AG k#Svvƣŭbh#iQAV Z(bE o:yB+sr9'.vX׌<”<'2) ;IS r\>l+n;zj8#ñ se-[VcGOpvq&{p,!W^a5RI?j2"(9pBaʞ"Gu[4-BpoMh;q+v&(+;x@~LYMBpy74 6&ʞ /9k +B8Ir3*) B$y6>)mT3juf6'L8M0@ ףc+JQqaV;%w$,}\Е)od7ysM2LCjiy@ Czf7ˤ+mf- C8pxt_o< +Q.qrdWr#No8Ǡ+-\qS Ashv`.yWؠ 3yv6#U`{X*" \[*1l+Bwobs8ZȞZm|7E[ƠQ&0_}9p+2p -Rr½Qs{\ٔʙ3#]C6v‹pgr~ My)P­OE?Z `F &JnF bUSl~v9>+u(ǀ+IdfA(%L2Ajr+;hQ êq!?Ŗ++iuEHOpl[,q .9t$ZskAWLEk]Q:i9~b25_{[Rf n;t.)> _0C]Y=[n#PRD^,;0VH߭i@p+bь5Qg{A5&4%@;S"/9g}| ")±(;Tg)mS2+L]4U%nKrtJsC*60jC09CɀS2c; g$mS`>{t婐L.9,Ҁ' ֟:T2Ei>2; [jP%gדih&ZT`*8*D9cE?Yߥ)+ ˤC];\X8\rMlE*^LKR`k'+ Y'7}lI,*D }>UmYd%;r]Mv.|Ԃ±r>(ahr$dk&Ts3?CCğMD$ yf]C3dz yKL04іk<*!ݗ.5d">k *KPl҄dre =2\q猕'sXF=MP&,璦$ZST9Si.c68m$?ZPT:_м$`Y~0Jis"òrY(+8fqfwΚY|Squ~,YP^>7y'ەl]Y"1n<9YB!~_VX֤&yoXkзBDg@G{BXѹo?(qz}Vo9,p+Cqi] ( 9 'G8%Gw9/7,@h{G۳k-SP(&'{b-6y}(< dD;SzYhiEzCI 3%  fQtyxb$$~B!)sɏ]²(ˇ,RG%RX٫-9)p bH hӹ#ۃ/M+4tH<2I50 wfgCh-1 ~i\v ]h9dxwM R'otRtm0L FlIYPzXW$ 8eJ@]Aݗdj! "hԾ.@XGc%S,ұ80,ʺkzo17Hb!ZĕW-U(~MQm>͆LJJrGB(BY{GRd}K.>0e*6=Rfg0',iQ[נh`t+ǯ:Ⱦ(0-˰9ʜK&iaW^[vJ(s Gkm ¥:2YK~L@-L;aE?eRΪME8o n-ۂHAZT/S42qU&3-i1doRr¬4G%\:RuCx^ЕtG_[Yvjl{z7T ^)}x|hAco'Ӛ]߬0]7kf hYε Q%vZ'G87F':P(8@-ׯ')'q SS#]ƎBvvp B!|)TԒvZ^uOy!lV+ӂ2J87&ﶴY.-:]wS2 s]4[`N'[hǵQ![7%: #cFlA+c,@jK3NJq `r@ -8Al\RlQ2b#Ǒfg8QB/7<E>h()=TD)^HZzC s.I֋vZw]3&LٓP` /2B=fWE?&RatH$Y$H$zߣDR d5H Զ=Lz`֎ėg~-ش'"L"zQ6s0y i`[-3`[ؽzd>Dsd-Gµ4S7u_rNq~PIXk& b kJCЫZRzHB̩a[ >uߤ*Pگn+A-K M-rh#'kjdT8ctVM; }F; Vj*<I~QR{ Jl=!LCx_5g%L_miqB]}-H ̌sP(JEE+H&($@ =AW.$8wu1qOѹٺgQEJ~ŝdRDYX ?W WU>ePХl.D4,UG,(ZgU%rSxV"Cu[q0_HȐDko2)4@YPP_Q!YT~M|S0`h! PˆNnmoC4R,B5o~FaҢ3cjshۃ/9cF~-a$09~.p,zF0aՂE7DHƢ` d>I\fNH$c?Z+)m±pO1߮Xd},-G4;p6b@Ԡ !ՠnKi@RȚq!>>Ζɓ[ⷾ@5AY'ѿcg`gW(Y7 mk9.o'K0x0!*61i2|xH&=!Y6mIr:osIɺ뵴ܵG d/͏M{)D^41Õ#e9dV8/ INķJvL32F2#Kkqf)&Wf̞Bq>R$JJa 3NfklH0Q9~4ۀ^R \9HO=z3w8_%<0[:ĔH%.T>.d~4_k`.=(׬q-iiJoTg %Sx?36Z99lԴ˖D[5Ž'('&(\%'i.h|ݕ%rnꁎ10g'"XL'ND`\x $\D ́A8 {L(07Zېq6˦'luSLb̈ vjjTe;Ķl9ad %Nဋ ݄:a@9@\px*U$o?}Ҝl-7c i&NCҼfOs_mm;b }QVMՏ-ͫyb>E2`L#&xO4I8_l#RDbY3mw 4ٸxC>dȞS|R,sryb.s [HС->w]`>)}`}hHe?qͮDXgb^Io!U1n&gNVhA`Wu. &6[ KjC poLx0-b5|S ]/Lgπ_ Rr6tѾ\m%s~ v8}\3Icy|hwBqOzGL^TXSx AQ:5KG+pMO?.391.Qpo_~JS޿f(Kķ4' ^(rV5#%;{}㍔y1S.RVH?i% osqe2/p6ܠ;jWr:38EbS:Ll_<:8!kn.{0Viϡ,~a\In;'W K+ū3(7iF$É õc$~e.XRK*$~/_Rz+̢Kr}i/i}qD*5ٹt;I7׉n.OǺ[wVw`e8C,MlD\Ϯ&JY'ױk|a9D_T+ 1]xSyI7Db]$RN<r'[v1a1<@ǣG=ؕA%<9~&5^6cj]Gఫk&67a=hl嘆jb2'F9ōk9lEP,gÍǔیAW_).T`zwwb x~+b)鶝iyU]$YS?}05hr\ǖ`X52!}Kr!Z&LkKL,Fg`˿_~t}|Q?6Sb_/tl9Z/?/_{o__Yɂ?oϙ,>n/߱O~7X/_oˇ'j_ʡ/\+]O~_~/2[?ET~=-idaeIXz s3:ۇ{$B͟)]AW?r1=E'q`S\rܥDtG0a2G9^[to ('6#Wk<27 S[>(\zPDNBXHbwye{w!a2[SiZLL'G{< .nd&I'0W:_* =!ǥF<ڍFṕ`#S$3%)9$ce7\`k,$kdg#>OE/j,z\~UQXW}BFr`P*e.RdPA)De4 ^EZѩ5&z YHtCu;خ 뛓-A,B-&G-$\ zGT5>xZE{H·8K'4t< s T[,Vg@9OLgemm+ ڵ彷&Sࢃ98+.@}? uDС>_Kڒ$NE[Sh'(ՠnKpooMMR"e5䵭IPЩ8M'8pmэ:JN:ܘXL£&Nc00s{*"L);TZu`e+WnɄEw j R|ouH%z3ۀJϭN lb 7"Yd6 sN.GͶd0 dG/`Aݗ*`)K{tT= %ǯ\(Gq8o׻>Fy|*מV Ř5ǰrʿ?_>ׇ?Y~_~ۅ#_~?2?)_aw_|qh]-?Pkh{C`Ϊ, [ž@`ZqIS0M^,M~߭,ɷUr}_{_H$*]H$U{ݏs,v *;w Y=3gJ)) JEJ g4f?Ïker@ᖝh2gVR̢ؔU|>n؟^3ԼݦPvb}΍$7 zc2~,xCNtLߟ>?SӋGNXO׫h A=$=6w 6}S埿rl~y~Kſ>}_suo~cO~{yvZП ~w绿>|݁oypѻ93KJp{i/|0 eC~~׿ׯ/=ϟcuߞ?gο/Ys7}H &(f;W|K݉{?2H XEFTa\pPL-ꄑ|)_KCjqk?7«t,1*Ĉ1z.[ߍj.WJ#hذ t^lrr]{Jz0Ҧ)"cKMS/<[}2'J U8)Uyl>kPq۲f*+Q}9 S{1VE1\rQK ܝ[j+5T[)V)3a ŕ ije =ktM6{nWWKducgoTqYn/tUT vIHQ0LZ[fOVW܅/v`K~Ldo1Y+BK,Z2a6`Rx&`w1YLɝ%%4j梹c un"$9*nܛz.\*xjٶs%Rm,üno[gyYTEv/L',jG BM~FN ki R>AЄو+/w'WZjEeԮͪ5bo ٓωi AdKʖ2̖h/Jl.dMDDn"|RKRnDN_+J}gq2Ж΋9LM\e oJ삱i0n,.bF|d2=ÜYTƮ*̈٨29= QPk"l]jE2649o=I-Lu8*ssqX2mWl.ae+I]fﬗ5U.Bj'SRgMQy ˒e+92y=eUL*ʔ9k ĕQ6?a2iRm# 2B.S[zE-3בfRV"xpQ ^Q3ɛr#[=)&EB&"G ΔJ9 mJv Sff,InB9?OӨ]T)7UB8`2a( R6ߌqm**Mq,l&L*gktܪMKHMC&$^,F"9\ag: AnT&b0?:MuPa *rDEFڼɧ9[a&[MrfHGŚ:4s&_:&XN]|vfU?5S[K'6¥>Xr0X6bE֔Tk',#cOKXZދegΥdiԮьf[lJۖluQm`$1I#U4|?TTj$c[E۲lᒌ6XCrd•X@-sIhlxT)!3ab)KIi$TĹܲgM{ dچX )@ir*D\/v+f1ӹlE8.im+pRMìŏW7n/U©;Tۅx2a>^RĉiPFKa x~ l[k*D&PZ4e7R4:ٶs-'?-`F4wu*gLI-'?V+~HLLoLgY'x L½]1XS{MGi)(m:gЄI9'LpL8t胶Z̐<\B [#3 ƶ0da̦:kl1M2FV"xF8$㧪Sc:]SI"cMd.[=e]q^(aS&,'-B&'/6@0}=̶UVmnnb:ռ++Ckh{n%J}W˖(u+m|4.q#+AhlxqE,X(-@tjcCy\%¿XbV(Ww[N=Wv݂[;ߒĐ5vL>7BE%zF!*qx ;ak ~ާO`RNum1u4'N7S^^|ZҲkQcXkU?$pխX4QZ Mk,ф͑l qOA'[|lK|kjmg,wm0,F PIjŝ z"#WcEɃv/d3!T:#ܹ 3whkZRKZa7- cRM%M6 < !!/$Δ(G }\YD鵇槨}EglŧsLk.F0 W9ی sJ[3-mm - l}j?z WMI~oY)ȨͮgkZ[۬ASĔ:tV6PQ:fpٲrIkZF;|$F6qva&;*={^ì+.IUM]ȱC,`ǎ. `oNsO-4`6Rui5LA>#lesEF -MV-Xq (ve*g 2Q2~զe^4 ŗz.E̱c%`0V6%9T 5穖uh.4`6Vu&`>z KKeӨ]14XRjݼ/X g;u3בqsђ66eW*nՖ2o#^EIu-lFr׫H} CWI\Ss[Ƴn r*ld0I+XecmX9Vq3qn\HI|"stnaHNeˤ]{L7Ũy)^<%v%tBT{ݷBʶ(SsC8hQY$6 -Fyh(L.XFRĺ4rFatPi*bL;LvջtR|XaܝLXb;X^ߝ4L(%`( 58O^mlX)n@t昰h<|7.^An+:פ]{*6TUEŷAH ty/DDAeUr.Jzx33f-E0#t>X+I bT-OTj2z&v2a>R uM86#̵S\*7Zbdcc*ԥ:uIFqpp'6<-67E%6_#ԴsŇ1w_8-If Q{xW@E?,Ums&iXQtg@&ՠv09γu.ܥlY+xg`!10}Wmg۴k13;(1N5%,gnUqJظ +)fB)|%sg"ˊ8=j.n`hQ0CnPwr(#kv$iv 'oBل;1_sef˨6CMuL ،hɧ4ALnO~6tRf1"1򬓎dnզ1ioĩՁw]7 u$KՖJF?*:9ֽ/4Aj S I3H&Mvm0[sF!5Et:KEp;JPK ; p0a%Cjs%AOor{qjN!ﺔqKjПQ{|Xa4y;.b6#ۃ401VAC5(Fa1E9ZFt5؎wܘ2`rnw)3} SSٶs&Rfߡ#&Q(6-==꾂qU֐Tqa. ,TLMp;JnZ4J^v^̄وLڪ;4w̯\bbj-T&t{V< <r[NVvC~Z5t.J +$O}xtCڏlJQF>`wQ%ǯ`lTNt_%_j]dK E726 -^xrS9c*Rf. w3ڬY~5l۹ +:厘^"թhŬ?MhEF CK OU a[rGǓɖJ~2rRYB[&6&ϢBf:̝/2j2̯ӢKv#TQ8dƇ铟=#6tjt[@f"dЗ@UۖT-2>;fY4LHp ,NfOU%qzgr-#fgϏNhLNBHQY 8M^߉ }ʍm /Ƶm(Oz^l۹ Sz+?$c >թҷ-F6gT7SfFM̡p+S"N u-fO#G8jksPSD7 ჋v#uA\ 0ɕަs PUCr9;ۮs@mLg,=Ȝ;9{[B:Y. ;<"7[_zU]̄xaQxɺ y)>ڵY4m͗šw n*N$˴ȣU86Nع cz|Ձi!T[Z-"P9\ۀbDU,iP'%b2 ɛKHlT+.'%jڴksҍFy&Za«#\Ps*M+WaNo) `C`=6T]e :!bǷ 8ƏpK>Mԕf;]TCbrG [&,(V2f--%XdeӦ]Mna*wzl\Ȳ` !J^+܌e*RՉap3 pj"t0 LjҧT@LM&aaʜ_㼘"8 MXũ *M-&lRv-_,[}%L^nm3WO7+Xi>rdn~Jhmsܖ9wI $)k,TP2xLyIuU*V+ M$PFʚl]q!mԮN4m٫^Ù>.D9+Nlڹ z| [f}a$&bZҨ4rt`A] (u19SP阫grx{1*/߮Z7dXb`tAVN"9:ul'c'"2]l@V`6t>u_U l) SJ~U͉yB:w@{)CO{%V@V~O]S&z<33aXܺHN0abB!væ)F뤬O#|Gba6o-3W!S[I/^(z٧]L]w[#eRE(b- -I%-)[T0zNݵhÔM=_sq#ҩPw`4%.'̚6 -=4=)LsdцW7 [VB4o FH)<[B 2;v_h(A lӕYy#MӥoMx[HjBrB#rlN\g' +v)T/p۷lW̊:sFbe㍬-w鲕#ꢫɁWa>TzqKJ)Y`:P [{/dڻ_IP;hIDU!{Ӈb:o'&NovwwW6y#gq:ʶ~Ҧpwlg?u/G,\g?Y_,k0 "uxmu5WjVIC>e?'913sTo+wR[u9żp z(#hY6ɸ361 .k%E Gʩ'Bp:k~7ߵ園S$E1jW.j~ τV\hM6=ꓓf1Zq\3lgSvv+/r\?Mc Y]%U$WA̖%!k-fIdLEA4qL#7TU#ןYhl5r)QPJtX݂KK-$R659dJ䖦5r`/xnj6b vT"T;Bv"'x Pc6x g9Dn6MLs\5ΗNU~ sYprۨMe&LȍZ>(0)} KM$b6옣4~@.:S8M'&!~RW ˖H㎔yF2IpIV$RYܑJgcV5,dVn~YnbE;*s*{Tg1R%q'{Nmz=-ȏM,+'JfU|JLֶp0FĽ|W9I%=C)Vǧ*یT-ݡl0"U7kK&(%RxŇiԮE'sTGБ,(#{ \_%[vƨg %QX@"P܈oˠz5YcޜK NWBf]<#xIx纘rM4hHԘ"f˨Vڨ}+kqO%o$qH[oSqC޺Jm&PűdL R,F+~[eoC&:PavCUy.Ko"[R'.rtګ6U6Q]pX'uxT]=iksP-Jm'_%?t/\oK6ߨ]9'qTؖ$':R"6T1j91E7ڜ|m8nm;WQuo9ƉFsbc$2.$}YK<%e&\ BਙrPuC\(S1q @4jb-skޅL!t '8s+dUkqr mry-TeijA15LJ #].iRvxM`=;:Jnm#%OUkMЀ(Iڲ%ߚVqMC{&O? !7:)&P V$dYkYU4kCULEcVdP0{F70>d, 1\bK'G'Phj-ͩe,@HnMQ i&5.\t?H6ڵ)Ԫ`*(,eCW- USZUefU+o2sLT9 k$J˃mOgն$.lK.GR5T;{OR~棤%~$:pWMv-u|A)T$㇇~JTYb Rҗ{ AXO:ݾnW?+u|:_߿}}z/Ѣ~᧏O_=t߾?~{dN]=C [l_3d !K9*uvU-\=F珌 8>B:s^5+M>j^w#-t]79kfr^m{Ѫe֭MgV5AkSmЗ"x(\kP>8 kٜe%W:c7۾==|xvKwGOߚEA-V_߿?? _D}g]oo_}z~:|vxS{ 0ܱz~ןx_SwukkuLNb וçool.|oxL~/[^h/K( Gw؍tFLHn67?:?=|??c_w>m?O!"-_wVmPP;D`9 F32zdw9eA bK-eYL}c޻;)/__+CD_p%I`'x&񉄻fIcxgBrJ6}{9mV;Y NoE+=_{}1H [O ݤґNne C#/S#?(Z>DkxJ]Av)<w|a{'X]qyckz+02L*>|Kj\kniIܲn(w{ѯ!bpPЫw=rxMw{/[H[laqF0L,vhblzS~J׈I* 6H፜a1Ա1Y0g$&a5>^^ydzx3_IR9 \uoi0bV+M wA߃6`ra5 eڏ4`veJK_rD!D^3>73ӷcߞkoesڥ 5-KfKns;Yb.RX x0N$"$&+{''JPlzb׏mXc7Vޅ- vE8 vK#?wW+,fϑw9ɤcka'?aA:H F8Ǩ1 v]FE,iw'5F~FhtoF]ЏJ?)Gxֲgp&A| {$QʜoxTNK tt"" 1K28F`paRq(,KϠt% HH!DR\KD.1=d7R &˕H"HyGkm߾;9zi 3jq4P &NL2)%D#Q(,k[d"#:xKJ/Y"j%Js S_(6 }X,񦟐ء\{8E%Q+q3O,\пK8-8AG Q,CTu̘~="NrFNlu,mxh QI#\a}@|F{8'.M0EO/n?ut~#CB) /fr_o7Jo[Xk\N%T8:82ȼPz-tpyCPQG`DQ.V.cmAxqǁhHW~oT"w~A8@|!Gk6~px' pgVN{bfԇ, 9H-td=CR@, 0ppFƁ%c;p"\y3l$9g!RD{Nvb.Vw)v`iVo~{uAJ*rSFL^*DD_w:p đBZ.o<"%'J*`t<pKX0 SrQNX LpU5" xB^>򂅌rNe9v[|GN&-h㾺 XѓpTA74 s :2x':0p!ˆfQ֧LZ@sG;rʁ<Al*9,<|x{,żO łڥasr15c G\8X-q.p9@&P`]-2Sq<]kpӶX 8~wC2̇н7&-u{?!#AXǀP L~{ k_*T]zvPAL_3#*jhLMJOUD ޱ#w^uZߟ/>?a];vؙۏz%/T|)D~|.LW8Po|;%+ \S_ڟpM741QWӇ%)gJlB8BЃ[q 7^7n*p[F8}w/I^x^'بvH/]b\w ⭇RgOgE9KSb0ςE@7H\\C\uGq陾 5 "^|dĔ5BjOH ~E'u'dWԾaZ3;d7q^;Tקݫ-cY^&BaaΆ3BɈ=9ӧ5i76C1s~gߝ7`q}[.ڏ|pӶ\CKDwf?/o >|}S%`|/k/G~??ߞ;>|^6Ը=nSuK J%,կvO,??_?=Ɋ/r?_~;<ѿⱵFSl%@iu)P⾪!1B{J#` ]5ñ'Cw_~Or?!>B hU7b~hv]sޛ|Ϻ_5Bn. z:%|W8nL"«A fnbocqPFF=0䬰Ә8;%t2Gmlzt899?f:biEj0q0]K&Zja֠z' bD 21sbhk#]Rf@i*IO$>[2}zRЌ-O˓Մ.[٩ Ƃul|ޏ绿u :'~; ` 7bO5W"KQ2 T:+w~ShN&i~3q%6<6V\ax^1kio-[b8tFcnZK.ƄI Mڨx.щCb57O[Ev`&uч~mS~#g+F}dv[{e/5}ZPz$]=WHz.-}`LŽXAw\ b]Carla-2.1/resources/16x16/document-save-as.svgz000066400000000000000000000222011364475620200212710ustar00rootroot00000000000000}[sIvW~łsL ; o IIuK]P`@QFjWrsNe&~~{ՏO囫?>xrv{\Z?=Y-Vg_r{|:Oww~x_-o`yyw/+/jno~Y]\m —߽y$./ޮ~^]>Â϶/_W/E_mɛWP_ af>zFtI~[~8שkԭϺkaR?|x쳕iWK]6@sUVwtV6nLoIjM?|/mnھ$Z^syS=iOwCzDQ9/]t7|}ÿ~zu_uſ]|zr}vgh5rt-mܜwՇU_N[O8Շw7w޼]}wW'opwB:yny[V67NTS-q]%ۧ ,_^ﺧݳ˻xrvӳHU nMٿݽy_j!OΞ}uE?I@M%6RWCՔnz3 ?,/ti6.߾]]t _ueV dzrw}|۵]7?=tY? \zuJ ŶLjaRuETqkzIM>(p(__" + 0 ,RRr|D==j5PGQGe y:[e'Ԥg4zBMzkso-ˊŭ9n(}^Lʾ `̀b GAn%0l3DRISiZ`c2v슄(_'@ H*?XDKf&Q̇%;O/Ԛij 9iWgH@:#E3,IlpBe_+N)!%d0&!9%":`cPȳk̈7s'FG)9Ҥl[o6Ɩ`*Z/T ǖ`3˝]n$+GJb c20+'(!uyBA &BP)( d*BY5+[(j1rj\ǘ <{:43it+UVX:0q^Li:ll W?mÝ/WumǘsҰP ; GvHil}m4/w8<2-nJqDBI$1A[E톉CDE}58$"aVŘUs#VY%38)¾<|&lEw96]v>"h**(HQ%_lZR\ iJc,@:S!0^L7췳b¾,,ЋоFE2QbsSm̡P(L4LhRvA雂: ؋[5cgq$:Lc-ԆrFPiV*EgM_5F|/5gGmbZ#`p˯5}bzO x0kGOGse_1 qcK.'xw'Q{U{3 N@ `#f)ަ@x),Z'?xpgǃ պ _q;0< j7*J< pw屸TMFXa($Al*AUб\rX3sQ)#c&㐃<k, JfbF">XX/KG8r hxBQOr :VBYdkl^( $l=<>9&1^@"J<6T@m \,"Ƴ0coIً!!!Akh(FDn&N Z-n6=g?H~hgƦUvqF]Œa~vU7M&hQ3;FE8''ԅlLof ŇvQ,ĸ+}w`oHRh9jf -Ԓ ( N[TS:z:l"%t$%}$(Ɏ%fRχӊO ۧ% Zʨ% Z|z[Ѹ3F\.= MeX ) Ι%]Ȣ έtȡ:Yž8X.Dg9zny(%rÑ.gJ9~* &iγoryqzN>xV=@`XD]b𘽚VF1D.ۈ8 #i#@mḆ ;A#cn1ʄwc Mzwф79cܜ":P󐽦/g\9 {d:CrjG,6wq eWfԯÞOwߟq6ysTx)|ST;xC֌h? ӌP=/(`Rݔ0v \"ZGs&!uXEQ}iA΀6ˏ1#2w3l;YPN۩'>c8wFSɼkf䙞vŲM4:h?|'> >`??6} 9=$0}'uN9=jAf):߮kih)8!;xOq9yn۝:!_L ] Be 30ϛ飽F94GG=O4 Nx>w;$=WRA)lLSdbMa Ź@P^'Pu^W3s1!;mk<xA04w0ŭw![&/ ?/ /l3_6?^yx[c]t{7qߞNUw=CO3^x9)wsΝd"={4u{\;#_0ML4#m? 0`VYCu77J-`oXe>%XcH\_f_KDPђOri~iPܸ~29T3;+sLv8d]wdUKAhA*YJnq<%W=~$8HBB[p *9 ;Az$5;r5,/^]fߍ뛫_7sxdZb3'+nzMuBXq*~[~p.t%M^~]M_{y}sT\hB3Zͅi }g\֎݇5k \)S]|AwdZr|{o~71~ltvwg.}t榣U.[Uo]{[W߫{vvoNJY(''>Xs4-] R>*>",@]"Y A, , eM. QIC1  j5YL6ni$XTTM)+^J|YȢ)fPJ2Fv7wx1ZVh Y={I1 J :b&À[V:E( `)^[𠃢αj^[_V]G^~/SulUO0ƒIE6vuhjI JFs1׫^YY<{3-$ Qw&& 'mtέCrRY~K8|/q̡ :VQ)۔,}$F "fڱ ӽP(ml'^][9 ~:Y8a;S %i &D$auC(I0kIlⴍ2AkXLX1*"}ɮyɈᏠBĂQfНtċAoRD!nymyNd@jŒ%`h@"IXQK6@|ʫAB)r@<`WBmy j1oj6M2x6 C.)sѩGaLs. ζؘ-eAB吒I - \yqDi+0|27hA9ڪa:G|>Ƀ}_|Ƨy>A{SJe - OO/BNuQ" Q'My~b\^IaCCׇ I^"৐&{Tp mmJdM" UEQPʢ=v q}\@hSTAi57! t- iK#ڢ!N*y)lўFTx4R/Fk{Dz> ŷ睼vAugc+ݴ=25HD~~jTy\c[L[ω#9*{\ܨpLB`?5z%ِ1Paz_F1bJKh0A`|ȢEśT% ,U 8-O_ Ì}G%0wඉ y-E |#,8[$ϲŹBXbZ:L /4:PeօANEjwSIeP,i %xşT^dbZq/h at\xR "9Bd@X[ WLٚvBR'56M\߆IUMH`+F $i8[x`ribQ;)+J%EILӼ$#%V`Vl( B6ë==j:Qtw_d]Vؐ% [T/m5J {X!zXIzLmT( j $hwS1~#" +Rm'NJjq* %J6+uo{E3`4#C䡎^/Lam*5?/–:=Ixo|SyT a! z߄X&jrDj)Ta4ܴE"H$J[Jjh:odSܸc k}dňUt'X"XGHR"9Lwc J b0 [#J`H1d]T+G)_lF\U0й %w;c&C?() 0.$f:QϚ8V7^L~@譨 s6C "=({j[ zdr&Q4#ut~;Yh຤l!,r,=@!r}Rq5R}Rxb42?3mƆ` 3Aa 6A5A!G8Q$vIR띳o=CXO ( J!%YRshTb"I<PQiqLՌ:Ř<= 6 :i,|:jvۆa p|;Qva>"9ːDM9ؠ)ҖH)K>r#\kʰhp)Ch()ØSM'Rrв|]-Zx[YZr&S%WlSPn ơ0v,[]ZHrK8(&zQ'2Rw@/][?em{u8Q87s8ݭ J(:g obHsST\+zå˯o?ZUkOϻ&f3?Fo}6k䭱E3)T*d {m_4[XC5G qD[ImOrH闏SYO մ1[..d<@ʝI⽣:xn):mGa]ȷ2jNeM3ۑb]J03j̉{\Iޖ[xȆ(jlV+qAY];I37D{FR[P_JI:lnH*Wѯ///ltzYI>{QܡD2U>R[mcX-*|7ٷ}Zw HnóBQT&$( BQeE*SbMauDFQ: J Lʧ"ep>P4S Cɭ+:{B+xO;]0vš"a3X7E\v_9:)繍 Bd1> C_ ưnV[~:bk/h~{;-+y<2/c<⶘T82Cqr~2U9 Q?pO_SM׫,sqtlgӪ`P^7 5+V_ujW)͔6m7˻XJjq?cOWb0Bkv8>mZoZ/_ >~㪘{T~ۂǻbտL.wN]8"mad^۬D\b,׿D*+g#W`Άo<:Nv;\2ћ=8σƼz+Pk{<ėXMӿE!'m?nt|$2 y5.r2B8(.IUa4NQp0|Z&g)۩JL-WNMR80~߬(p+ 0PXa1ߠ0Kaz qד죧y,~cPyE>Nje` 54ch2s؛cM(,@ ώYܖ\ ~߮ZoY_m29s*;1>ZaYKF6~߸2?!cn7JfNҝg+S JiE=;Z&}6YkeG*em1-CIۃ EaScE;>}O}@Mbg`oNtr_璫^QllTrh5Olz>ϊ&bGK"0>}ģٸ s>p;S,ǹ.pyX RWhrДpǦ3 ptdNc{c|5B<~:%AOVi *D*wB\="$jkRZ{^w^w.>b j% d{Nf-gX)TCpQhu! 8z+P9¸.:_.'Lcs/7'd/7Ax]3u;3wy6v:h+GϞ $yb(b>P8罗]A$?O;u 98!²&ʚЊٙ5^OUz[VgB3r0,zeU /wfetYz.;twkWrrF3g@~9Cj`͜A'b9xRSLe0 "A8୔XR}NzȊ" ;.ᒙI%;no֚55vm! 5udH3THؚ*[*{e2^Qk 8iKreB(@BΓ{}Cdv I?NKw*c0˃2Aw‡p# %l'@$"ZI(hC>ǙZvgrwmu㧡64,vhY.Z3%}1 h|]; T=8A=쒡U:8OqvrPVuߍU=!$RFݦ. A<*Yf2ZQAb3jF;ɻR^Lpf:S$E9cR]{z/x>G(K$yFRF;{t]wX%l5Bc^/gvGT#SJ_ۖu@6DdtjH8Z|ic ac.w2??~m12)TWd6?˕1vsŌ47ES^ͪɸXͧEJh*|A+ŵ-)-ˆ7GOFEptT,(w<vu5<F]Np,Ljl3TG /K{$<[hc!D@'+c!=,B(t/ShSی(ͤu@㒪;CHJ˚BϖXcPV9M)ax6%+ U]R$̃z[w`LT^*%S_D3z0hDXD7""K1aњse!t,=1ë^ŗ"r_ZN[QyOGZ!:Js'L6h$n!u_zezlG3("1.HؓRۍ6^dJY>J8f@넲C[RԳcL9(B,&RpF~=CVYT  ̭\F̳@24ЩfArVFl1 #uIŅQ+֜Ј-&VId-g(,Nj-DyK'1Mk\S\r &^AP6.\vg o[Ȓ P6+yd^UeO`z}CR9{yϟvoJҥٸE-ĤD&T)'K/'@(I$*:9!L1#>gTS7ϧX/}S(Qq{rX[ W"D _!|@!ATN(B %eMh0GV)˩D]D*5Hs.;bvP(meV{]#yow #5:5}8#$ݮ(M^2Y_6AJͪ&/Bei2(nV}MR2J{$Ϻ(֡YtO+팵&x)NEg/n"oѼCG9>O4,}bĒoSbq`}e%icq'Վ(h'*Vb NR\R$lIHTHEn&XU]=M$H[>THFl jBD$AiOףD&ٶ MȌ8cyIhrہrSWml2ζ6Dz7+Mn<:1i,/X`bc#0yYـl&JMfJ+dr(ˇ+\.ٚQgG1mW OhfbF=eU+|-gwi&kdNJڃ˰QsD1&bNx]S |Z;m: Zӊ I { 6-2xrƙφ&n^}>3F!!a:ka5jDJ" u/m;5qܮf-EP~EtFY"k  P|l>QYŚf^1{HYH$.zm|7/oyv&1]'%9mP8+slHH9hs^d#h=\W5.:VL}"4Օ`6vsš'g݋K>{y]]ᙺ ÒJ_pCarla-2.1/resources/16x16/edit-clear.svgz000066400000000000000000000765421364475620200201500ustar00rootroot00000000000000YsIv)t5/0ptE3m昈z&o hI]ş Q`BBT{Dt T{"w/}1>~:>|nquxy}}q\-pyџlj/^={~˷ۧOݝO=^>[[X_?_wO:˗onw7O >w~Wo^~tr)=4?ۘ^eiwgwo/:M ~USb~y{k]2">XzˎϾۇ޻X{u}azn_ߜ-/;p{߾|c#^t"\X^~ns~y.|$7xN~+>_~|2h>{/[>=_|y?n]]>nݲ<\.n{m_ݫw,[^ݱ؀y>xG_'|yqk]mY_v]_{YGqOWT{x]z.|7~wqa}麋˻o]v|7^xy]hzO`G>-]/T/\mPq&;A <Zh!xZڦ8P):(j8:Ek#!14yt-<-8h_.,FSAI$ه$\r&=l?rt6y+mR?!F:y>IB#HdŇP<;ՈqbY8$^|Vk'{gNS1b<3;6VSjq^c?b뿑2` l{?TI:t*|JT=@N"d 6:! \fĀRO VmMɶ=W[&KBPCp e nVs! M-븹Fon<ލ.mf*d+!̂WnTt]oNޙl-#A3TPжlǮE%ժf*,}=cej-bn !+YPюJ\zOF܁9CiH6^V(dtuh]`8S˼ -V`Em"dlc3jLwBz>b)s13Ͷc )?Lc+eݢ&] 3 \k$;fvsuςQA[ M{KIb?|qSu7šM`NH4E4mƁ ILI3qyjq% UdNѶFJ b;m/Z \qȰ}_XSj6fsU ti:+5,ްVլ۳vȘUDVlh6C2fT0 (cғ[l^(4LU[mCj gV 13e(ٜSb1/ ۟ M۱cjp gCHSxlN &XI4@ğ|pVT2"HUO+'c&M n:5F{X|Psrc 'y0^9f-1 {{3:a\c@ui^V iIj=klȍK6(qu2/Hr\YxKsXm!k*Wp;;"ڹ6P$ܶ!(ëJ>,L,>aKIݟkS 9YUjmBu(ܞU$6$/$4k| R?`쮒HߺN@dER!!Uݕ_W]cӞD)#-׊+~W1|hQ!>QwER h.r-&Ed9Q6J*4I1nA'(>/W!S q$HZ&r8KT̏{="?2IwAأ ;PT|PFloj9N913ʓcBD}$kI„(lH)A94Ն%F5X|aCϰ+Tek(a PĂB~IrbFmMHƸ 0qJS&ƐV$\\.U}8vEcTCVA`Q!z XIS9y6JӔW ,F:vS) -#0N(7j'jϊa8Ek5QYe}E3r s)ë-^AHbZmʍTl4L:D)IKE'؊/7Q~PX׏`S?rX&M fm7a2:Nc_LT5tOvXi"Ҵu2ԭZ/AmUՈq+MgʔU9)،&Iy2M'|kqpjY *7,3A+/%b"Ӱd4mYjn^ *\MG BD%=7*GBI(b %K `WRjP2AHEEɒi8#YtAveM)>!,%+`9R$,IEa) F >}u\uy _wC1 ]K7q ai1kAShְGl<4>k%xpt~#YHfs*H /QB2+0D+FVU C`Ju'PS|0Tp-([M4H'ˆ :A-^sR!CO`~mwDdҽ ,RDSC0dU$&I/">0r ->)Y ͩ>5|0n?~J}DtfT%9owP,;GO&Z?=cwݏKkGd[O"H?ƣŜ=zxv:dP N(&{zєRJN)}BJy,y[=R6V< DcVi7t yx ~>Nh]ϴtA,s+{hAn/f|1&  SR"9:Bѿ M=YU;c,9iVf[O(oUK*67,e:>=4&)E4=g^`kU[0 x &+40w|fG)>9[qvQ dD@PI< 1(բlV )mkk@D 40DB5Qs#2:d lh|O?BͮWݕzi "mG@$2g@Eds_]Y!+ $`\KX Zopy>7I/MMM[#뛗O%O7ZקJt.<~}u__^W[޼y/77]]_-^}SAyFQUyV)˻^-o;==k#&Ex}GRʪa΄!ĽW/c/Y t,gT(k؇(L_%Zt PbYR)M v Xъg$¡@ߛƪUQRʹm#NgC?W1n-|N_ˍt w__t!5ȅpj CA.r@_87GpBʎ*KrZ nM4Oے#U{ _{"_VGz}?#xMA..2.j~_~U$58QЛRa8TzēDS(jwPnkb i}YW~5_VsZ7`}hFӀR6є+& |WI*+j Cz*u_\4[ęiNwTWp[ ?R^!{ggmA(#v8$gY)j>HTJDPT*-/3VT,ҘBz@)Z2Z}A92&鍥v8hMO)PJq|x>\7:pr4a_g&TwSwgК'H+AZ`T59W4?~x˂Hb{CLj΀vKc=4 fa lld w bAI2 Iկ28 eW(uEkѯg1V#_È)w{tyXYJ@XXŗsi̭~XZ4`c q ~8D) lD(cjpfZw1Z ΰ*PH(z==u{CՙfI6,hKl-@RZ%& ۍ1ZIZ)Z PBKy9m Q\yE7Gn8D?x Đff}V?{WǑ]K Ǿyuyʛ ZW޵$??CRF=fw) RSVUW@%Nwu=N$lJ.l\Cm-#k:!^ @cO>E#\W^VFFbfܜ)8,V LTI+,gD)RƬUK f<^l9C0anXƲ- %xGn.XA̭ Zi ]$2&p4x-ؗ6*G|&NH p׆]-+> 5jMTYe(1if9ŽH)0VVxG%X*CԽuw XJN ”!Ĵag, ``-+ž`E-L,Cׅ| Y׸=ǰ5:]%i0OyP'=ܰ=mwݛ3)s;/# vn)NUhD/I*2"Wa@Z"5/\V 2 Zcx@u4jru/W\/ 2҅FNAŀfh!nutŒqn1j7l>pqc.: UuCmC`3i+D곱M@"  MHyo ,7q7ݕ]fC]MCI P:KNG X_DP Z.()qV;}>7zLrƲ3X߿OrJҊJƵ O~}aMQ2uXVQb_TCQa֠^NG,to5M.gOֈR]O"IIu3ZO I $IH|Ic$IRB\q"I!M IhhDI>;/$y$AG' $%I)XqM' 4FB<Ɠq^cVv NUɆ̧=^)R Qgvli(%)r&,XGχCl&=3Dݳ_peMM8  CkLi_"*K/9}!=h'%Jv> lXq!~u9|wI o=53Z13 >0.BD!;(bR`}΅3]?[ĉ׹~5l'mGQ4%eU 2Kф>*ln }`bzLv紕2X۳S>31>311h %B.Z@>b`L1 n`"ro92Mna0 n} bԸ{2,m MM3jb^|xkTo/m??}ͻ___›_ͷ/~߾! {?L{9˫]h8߼˷W{~''>,G%~{I,XC&*%N0"10<B6.%Sp|b+!S8T=dRCzAP%J{W3e iءLÚ΄uz] L(O2u1L+rsPVt}77 !d$.-8=[0 S^-M7Y_x=:]I q_Bu7z(N0tBu塳~wIV)99S\eVX1)kpy^ P)ؚ' ƹ5d}q Nҗꇗm~~mLgRt(A(!|ܭ rrE8 A\p?Irs@QJ9|Bۼp,6b!ptgk@ξ- q 'lF6^C+:ϵbMZ;TyM]'&n/bL7em@*m "2GƝI?b&M}}w ӄSpC&|Laq /ṖhBW:yVHRksA1%ZCf->.)Vxmtu)SV fSK;fnD {,Ž&Er \E\BYb<FPU#\? lMe}%W#k%#r¢:![wDTgȏZI])ݱKB@⍾ܫzs7/epn*Ce2U;\Z3 -9p!reV 2cD<+Ns) MbySzG?LvGZkʮzfiooqI '듾^Lro !EZ̰&o =,_z֯bيIX1&H7DD v[PDe>_~z*^ f"D&r1zbF-.KoՂSdo9 >aK}l>λ.͹0MH?9;0-ss< )kH  zZO4Q/+fZ7 tq0 [>%@U<=ҵ )F{=~ 7Z޵r2kaP}.X,D#R$#(Кdq&uXVVK 4x@HP±dY?,fOܱ5eg$n DCa6g3]Ah0aɆuh8,^Ю>xp >L0J!P]>.aTIU$D;YPg↽ D*#N3 (&;5|o23wU;`ݫ^wtGZsچ <W:k] !37BPL1(G3xޙSb-uv\r+aLNYܜO;3NĄL=gf\\AeMٌ^TNdKӾ3W5?!U mI<4 J]vh/_ QFد ٙ20EsۍIs8 9?n;N&~w}oRۿxyFzQXj63yv3b 8()Nch0MFk߷k/߮?u/:aSmhOm8«/]K<ő8ب,tlPG0)ilcpV@mrƴ/ YvVbŸ|]r@$VZE&~Щ%Ilt T9YLƒ>j:MLi33M.&T?4>դ< )L2?̟V3*=x^TX[˨'Uo+7M2 @ i&>k])}x|[qn|ޓzD(:B㞥l #BP):"F"Css+uv@Q&vO&Q:t Nv ߷]W@.~")ub|i2!ls.:FpFtep jD;Y1F %>LEH1ڑ@d 2guEmԶ+2l]~Z7j?{佮sQddCNw Ly!*h *3Y$q|w5;D yE xff#y 1 V"qNf&ALKsHtM=5-CpQ33/LS/4H< *W=bq, -pDP {MnRq, XJ pǮ 5i^_!5NWIsTں&o Pi-Z|2 glA+_8˺2|i6$楓r% \u ]!4.֑ĥaQscʥ, N^N,ۈMS,oY!b4MNq16IS}M857t+:=Bt:9+]R-At n谍Ox}m?3ғ'0?,] ƀ", |-^e59&"9K VIU;Q[Үi@w~k܋n[RMa 5n{W_ܕR^-kz]M.&ѥ5PvbO6'5VRb@yvNIP@x܋Jt;.{cݨLVir.]YnɪS[L怨"hpP@6Kv.*91Ln4A4 ʦ5̩wLw%[q&3s*@RO14d>3dPn8EaN#_ܷڈS\쥔@_Og"+S”WK/S^0.q1'J&I_gK[ɛ_{ɾk=/T/(6 Bv NوNUy%{ `8c֥ĭ5tL|{ e M;̍4_N̗YŤuN23DW73D_+{:ZN]uM:7$KZNŭJvUT|%t:KΥ5ݜNq~TS.b'kɹ9%옝btVttt X >@#BbS8qLӺR|m4P/`M瞘Jt ?))_`+…3a5S0e.3m9-1gŽ&<H17`<^;I@*3}Ev]T\*!Y%W-,iW!Y <$82z0Sh4sۜu;@>H jױi#APĥ`TE`a mc?(fY.t-ğ (:rU?:b`qf,I"7_'h;ܵ ( 2If([mAPFGem5^ XJƹ3[Gy'H$NrEXbCR7dUzJ8TX[J!:ӑRf.@ G0qRV򚔆LCghJeSJh:RXy)Jb#Jפs^J #Ie4b1Ru*!ZRl)5cB)vRX/*<3 dTK| & jr J?׻QJ0im*^ 3_DF\TƈvχmJ3 6Z*,z 7˪ijvTʝԨ q5ZTFw6FI>ӭ72s`ŸGQA%q֖23[Q!7~Z,+#3Tq?IRIxQy~CB>G1z{Ygiz >ޭ89'=,͗_·?__S+ )O>=}Ͽ}w~;)}_~.;U;ở~q~|~9wzN_n>dO:i_#4=/M0{v<6 <(FJf *O2P+ $8ZeFjJ`r%&4-凓fʇD)=DǺZ?A}Z(υ9۳QH,*so([ZtIjn23*D'NJ09Q]7ӃvGq\L^ Ύ61 R6>Bz ^ v?{ǑW [ 2=3sp< $L(=[U"f4gݒ2"2#"##/UyAbfy&@hF('Xf,!Lc?-р @{ Z5b i]rĭ VW ԜhPREGYm_a]7zݨw Sqˣ>|̜gkq_]y?E_\~;Htై@ţ/*yTLN"k䌫{({Qh0p"mST54<rzw&3ե>ⵌ`D6xk6ݹcdGep(G16*!ӠP(g a9b Y>b,&>b -mVI:h%PO蔢~;[C7|vL|:eCA494ӤR9I!zҟ'a'EQ1B-d $AԇMf!ʚ8*[&,ɣA>pnbvy.¹CX w Ap=hW3qB}&_Ņ'M~ُeZV& D oO/M/ݾ/|S?Hf柾ݖ$B$D⦈Tb-OGH>So|[ω3oq"|%qۑ[7GD ^N [`V]<_ċ|qTlڟ-ޱL2Pm%6%i5;St@nRhAwTLG!*%)"\so@dԛc m,6A~:=Qv5C9z@XgrӮ1XĈ Da5H֠N}'Fm FfLV9 A6kϰaԥ4CŃnJBRGЕg=UݾYN5ӵ> YsOofxWءj.A{R*3?aZ }?=bݑڎY3$FPL)CJb'_jfk\}E FER*!Moe nmo C/*Yeg.$DxĞxW)ʝA@oQ=먱Y=E BP"DkfvܒGMR:H"8$Mzf9dJG Jn*&Y$w*B sU&om3PZcEIZ@UviPNP#A,L 焲Z j#nhe%Gv`IL=۾wyCsHU BNXyD%XNw,zb/B}R4 uٻK?TRm eȠL)Ӎ➃2B|^\gVS b {M;Fi#uCЎMF4bDĽwP' ytg $WZc*.Zpٳ C-S)DM{wߵyCmf\ o'_D}T5WzߐBriHoƞͲ/WebzՀ &f"|{J=9Dԡ[*}gǯ w52w9!y /lfE\ƅfZD"O,\ -b>~tywtD=ןތ˱߽ljNHׯek0|`^zOQ=ךqcRkuGڲq|~kk&_<ev˗Wv-Z/>4shAyn_~zv˅uᖮ,էhO3Yzd2}=coMܲ}_>w~"f=e/~^N/׻i7^峏uuttŌmHl} =alj3=fF_>| 8u|?\]|zlS1ӛ뮔-#HqqqVÛw7]?n}c۷ov|.-`~,ѤzD%uo|߾y.~3y˅hg*V_!!hYj{jieѫVsFC}{57h]Ó&'_t#gb8ݭreU[۫cpqg٣~2FG\^4Y$s sE&H r2jVZwd T!@ <{ 1s4tϛd>iF B\m`'o"$7tiȜN6aOcܪFT 䀤yev3Qrl'ۙx(R&Uy/,d*' -2bFӮj H'HLHCaLc i{ԥ lٷ@5ZeD$Ql6WrGxuC-jD:[ܔ%u:9|[;ꮑMM# Z{آأ^̹ԙW_ޘV `_$\ζx6ߴ~NKxѧBmCڴ؉wY9A{85+ 5IU\]ߴ*CDqhІs6sdXk^EwXf(+ ۡrڎ68hMM[5A㝧 0#*q ہ@2_fs2.$51d~oWjvpfd;nX`eCgKAɪj";r/"@d1Oc9Z}ċ}>z`#I.6|aA0A(v۞i%q#.X{t̶4ƘOM)Ktb3AptmWM˦#Z"c;)2框'޻o~3eR_|3IMC-ENqdRK61WjUa2 R`~(/Gƍ8ްh% ,`U& Jź+#:=3,w9ܔ&K`Ρ{uО\U KkZٙnp^]ֈnhܯDSO~ˆǧ^Ť̿9v}Ps7?M  L| nef.h -vp\EϏ7:}}m>OؿԠ_|V=]r;au4-'(U6.yXA#}3(yL(s`5̙-c;լvX͞!7;vJ4V,j]\ͯ ѱVb)hkFgw2X7Lsfy-+F+},+<6ya{/<*5>0x4JR\ѷD2>$>$2$ouV:hzu3Q[\-̖`td R@th?]~㹛ٝqP3gZfK J ՁAyU(T #ۑ2Rq[qT`hD>k@ltD7wYo tC|1`YD PJ]/n-8YS@QCR9*H&o(C0zZe)*}j7T,= kA `"Df61J`9RUMZS|DRbGQac(,褝HDUq6Nlܥ3[G9B-ՇN+y :,N $CA$Sصa4S ,ˊ >|TΘ0VՑ4>%i@ĚPBdkh6fAIQSua0>NIeC\:bGt> AmV")jC5zQs>D#pXMeu6Na$2w@R3rDlhޭ_T^9Cb e͢-0ôj", }UY ֈ H[XdXՈt&$+])/DGZ1JaV#2!MT])ҹI ^S2&G[U6,&b&R,[N.0[nJ;xu}n|zKƠH(ݞB")&@*1߻ /x+cʵ]l:xs(ϕi8OPd'aV7_*mI;-"=}@/ wH8n?0p%\=P J ~W\+YVu US4D[۞H.%FsHZaF ꀖAJӯWUX_GyeV!kf  },Ҽ;$6$nV%5=p%jo2( b${M.3"#<܏{r]u)+_|4P/k>RoY@4֬4m[m3ќUqoPAJ+nW֐*LGH^o%O/MPw:*Ç Э:_]b q9,tŔ s]h7[ L{h83D|[Bij IE9j6>:d!r nQP3)*? @C%EނTS <@S蔤) 4HnHX}ynkKwWY xhݤP$w1Vl7adwmV7rgU̧K"n9$BTKu'$j 46D]\rC,NК|CJ)~&EJ`ThڏZJA{D7f'RM*$_0c1rH^B|sA:̰$5 T{ R\E;-Uݑ $P(S4s鈜AO6U9.&A)65cǃ42mCUފͦSl~~r=%߿`K=?#{ȏt;|=塊oX`U`gֵ1XKiUҵ fa3ڄ؊y saYl6Z:E;˘ r7bC(>a+ZAS >C2`pcBUڤ0j>>BB ڰ卫Ģ:Dr0fGJ4q_^ /\}ۗA]5^&yxm/+?hXW^K"oھEWٴ}uMWh꼛nim_g56mJ[5{m*;D_h+ %*{N,~~ W^Kbs QReaZ*$ĩK]ARsdRwRZϥnL,^J݂񿖺 RWͪ\X*u ^ϥn[ uX RW -Y/lD= #"|)uj$R%WTt)Jמݧ*oNTodfb,xZolfA,kBw.1㦼sqy.tMh,WɎ[-E";¹Vi_ҵO5'})it(pZ!ށp&:)̺#jjqJX ^u,) o#<9#ko5 mʃ]wQ@MkÙgjIJNZ#4rA膔{6e-rDA,X03Ɛծ aPPNN0'jLƲdZ73(BE98)dV0%Nhr<7ki_~ f7w$21[?bڬKP*n>ĤJڷ` ۗHޙbvc v:+ڐ@fv ۼzra ?mk>$涣7 m 6ⶡa  6 mBLn -`zX7 t;'-N &w7|'uOp3r; ܆m nG\. n] Blp;|;u.) ]fݴMPYD7A6ѭn/t7F6 ͛:=.'4m 9]ȋ4.ouA覷OzdQK.IoEnz7#6 z=o˻˞pyQ*ea};_JlN7 #V ৾Bݾӷ*):&k=w PكOR){WW㢜^f6FSZH{ctu>@qܒEcV8QBE zKRRTs!h!6--qΡ%9]Lb"[J$Q) `GԐx*8rr`" 9Zs)f/C]5ie*:c(aMdD5DBT!(17 a! (zL5Kx$mu/G4_z0zI*sQ5b;W0lLkCOڋ9O?E_"ɨwתlqQֹl˹R3!1O(<:k'N'rU7D\â]Yt _STC(W T{Tkz߁!!ͮS!&kQ޼Cdeʙ(BU"z }VrzFJma`:Z7 1OB1Fz 9ⓛgg,=,|`QX žX "Ӆx¢\X',x¢_X',ƅE{`.,E E>a(' OX҅|¢M,3ucGHO0 F1hQ U0F{.03c`zc`'8`'0#`a9"cɘdDƸXOdDFȨOd #_d"=X퉌yџ뉌 <Ȩ2^Ș'$#ӃuBJ'pWvOSl]?OBl+y_߁VYA%Vw-7Y#93 #ګFFKf%Zr@b$'Pth팸7G&ъt7(z}4 ;70XobMB7#w2qoF3VE I"3u۾5•3nHZpshʞ9Ҕ8=t:ݬABqψT9jtM/I 6Sl71 A~K3ӧ3 TntUzl' \j0̊Het6E,PlpA+JM#-筛&J]Ȓ4iJjg><;1ϙ(Kz $]"G0*J,!G2nF0U>a2"RŽ4pHd :,s&j%(/7~οڟ.BY;ӵ6pR9<~O9JHI6zPQf.ѻ$^K:ś sK+E~@??bG(5M/G :xi?R2$J+#Dɾ?m24˔B9c[dS[?8#"8Crk#Ct]Yd|MgzP;oIZwi5s!5IWQlh^Cc/Zy[G5De,CS ٣ƫ!AÈr4o3o# (bD64 EFzY7iL7ޥ$rxBz0'S0SO:{wks{K}+l$c{u?|y=?NB?I4`};Qbɣ[#Ǒb٣z~=5+~_?~0'XdP2SZ@X5wlzyFlmdqi/uMp0.*ɛ1͏ pEݾѻ߼d[>^j-vSϔ(s@\~H'ZA+qã6Ga4ϭla\brb]jGț 2":ݐW}WeFM5rʋq{@޹NcW\ĺv\^U24UP Lⵖ:[LnN0&R^16|~#|>cru8x?ŗLC;HZ*FI%14qK᩵*#ddU<4̚*WO\sǬZsJ{4̦9\N1H!5ЩRP#":CP<N)<܆aڣJRCZ G9s i&kZpnGL9utyaaO7emU[eSZ*ܕtx4Ĉ_砮=]ּvbhJ:pxۆ:4&V<+IՔ+˽Saʨ֎Ki, d.p-؛djJB_ho,`i1d,޳`1uքKA+ǥ VGYYg̰Oq2P /3[/?y\I R µ$3}dS!)P:զmM3O-jh4؟ G:MWɴ$u2aʙLѦMBj~ΧxSVo6?@tOM:MgWT<\_ө7LOOJ.Lɳ.UOMr`hū%=2qNXg`6HSB+fsF+Hf򛌦.hS:8IVv:kN rZ5HӶ+i-M9͘iE *54_Zwv+0~x$7Xߕ\{jhH`l+Dz#H9͜V4w62aa%if3'`;-O4I m Ȕ 221l;%2^DKst-3sv?I3dףjAB%[j)j-斮 _ՀvlBD?9>b߬*7%vVdH60Vp,X1=rUm;ӒO8ͩ͝; K% I.u):!$;V.IZ2 (aN~Uen+gU' P fV͒e el\\z-xUr 9!*YrOM&ͦ04_|*{!$ZI~uIfi3}Ѧ{ѷ\ٻgW]W 7V_q볻<.cΰ~-V Z;=^hnڞ/]|mrN߮-=%`;U,p?xԩCr70OUIB49qhr=@(&0lr r0a4;5D7HW9oaAklj14u.L`BlLZ`r uw}I.nߴ~ugo> 7޴e뽋6nl=y\^My_@7f~nm׍vkt4 3걡 .qiSC! %r<Ȟx˸=. .//0M}apHae˄w:e\~cn9m xvwۛ@,NLtAR_}KTX|4I Ѳe[ <}8ܕc>Łݸ` -**D +6?֠K"i;J5Q :dpR+VKRST!ռ- 9UBp2{*#D1yfuX%;0,КqDc^1(Iwce+H#:aD]a)N4Dsl`b A`m;Be1 rVl CNW)DVmHbt[ n6bOr~ondP$$2|2O *מ@E>z C Bا=eYW IԡfHk`Z=@ B֡D֡٣*7PBme WD%9RG JvPp\4d-Q-2\>$=aL PT[i Ծ^4PNP#j& e_{+H i T98'|<&i_SFk&M6i25Sϻ6PˇX  a)]YM  :,-l9>1p;WLFm(T2BSX5H4GmO*%˜%z.{9uHOh$V(6RtzTKTkͅgC \픡T*(9DJ5̠ e , a0G"{ٸM6mz+D"=Q>VT g5La V&0(dM?tٛ:ArXk%}Al#w +5&VDzkq2p{F֍H0M)U tԠm "mN5ӡ? Yso'j=Ut /nUva0boIYAwX̀Ȭkvkӳe$1gn/w՟_fȓ1N^TW3i)byg2ȓVA;yr?6eyS6NMmsIkTr4 vI@'>iO92ܽ m(g`@ANa =kLуF K 3.ZT-c 15̠ WQItrVi%y'ѣTEPJ0gHrF맟4_a#RkSD+zv@JʶSJ8W 6']Uǻ2PkLi|^нQ1do%D1hu1r,+RGlO_a}Acugi{ m8FSa2\l_rxO}|ol͓_>5Q`zvgp--"@D,#*ĭE)bҮJw9l ?!UUhfM<?B$Gk?D{/WS('ROtab\ㅅCU+`\#B"YC ;=gY]e';R˺]mx~*us9V١r SaΆVW,sP sAǫa-!lxL5 6h_VME)588fϩ 9S3bA=d=&aacqE.ŠI͌VpR5b-?l7}U0P=4+QCDaٰTͶ 4&)Q Ia1_Nƒ r>>CW# rTVK@|6K@JYUCbVѻ%{W< 3(S섵 #V>R2skX ^ARʀ!JJ J 5Td-B]:Y4, D'ޣ& S9GИ38T;B4W -8$c:< h}h|xjB7۹A &rDm`2)1&N D%8Lq0L6:330 2$SSpʜڃɼ<6_;iRCd: )\̞V=h `.Rg]eJX@M˪\0&W!f0?j:5P UCQfPRMsAT904{UJE %5"=&k1#׭*Az_2NJ(sr 8sgP1mC ( 2T8ն +<]ł݇F`Fě1WRِbۘ 8Ʃ_N><6WO~&Y&XaE 0E;MiQ$slَ9)`*֍Aoc0{Yܣ(~Fѣ DEdq/\!P2]=:iŲ%&=n4kUA)]aĢD;k%(ް/Qo 5AĜVr:} Be6 E9CԆPhm1r{ P B@V9 xtj1yϣ֓/n_lW:OǸL.-uʹ8Q!./pO}.&qw>mgڎp%MӞv{PⱼTv7=*ܨ{Fܨxmx<$/vS屼$׆(nF$7>܎Fw}lo:Dۓ%ٖܽ% O.KӼ9xɻle&=%:4Z=4ZӼ{ݝ:'|d\!-4@P~vb=Cz2w :&0sp> (Uc$P'Q ukp K bi,-\HLч,5|zCV ёY*Cd$<Kb"K}Vsg)/XyRAp]*ӳ L*r<Þ2s4TrK ,U!KԍlƧҜϝKjK H4: T0{zW1l,}{֧kWKȞ<6X{ѽ5" y'+3*u' !?U% C1zq`0O)OH*i.Dx;7<,r4͞핧 O(SbcY3'geg>sv.@rRO')D=9}&riϝHyB"8T̙٩ٙsSSI=i4vN!52(df]?wvBIhۛ99s";}Vv>EBgL8>+,{LNHYEϝpbs};Cge?wvEgoobw9uɞ.;;s~`1437i"3}Vf>"afdoq.3sSRf]>wv"ag@T? Y1Aijei:(;MuA> 6 3Gu<d`"(t<j@y EST6'?W9״sSщ<%ϝp<5 ΧiiN)9*Q\Dr:lT@Dnq@ٽO ˧ 2 ?E%N1]0ݰ+L4Z&R7HU3ꔽ9fRcu4uQ&4h.XMΚM9i̹i``i439h";sNv:>mㅡlV1m PF_` W$sʖd C%[N ,qL^1־粒{8m]]o@y}.$Wc+z\5Nciz/"M<"iS&': !ZVv {OSv!MIx,5\S(fCIsnZs EXc) I %IQ=0K=!+K]lA;̌Kӡi4MsOe*$?e!=d@)4"<,qo)7q1ץgy~QǏlIѨ.J@+%Ґ@ lJч}楏|q2)-ڍ?^)@VğMq3#2@_@ƻ8a)aҧ꙱Ge^/ eO V13?_?.;}9B  wgyC9ss‚w#dC$`ڔc=/ Ϛg| 1sin gSr?S97{(bOvsG{eOѬܑ/mH 4tÇvDgƞy2'{KL+*OB`ڀ=1 ϰ<3= P0zwP2`Π9Yό9&2l>X|r>̗0g0ޔ!N>3Ky;Ol|xL!ҊDSDH5Fv(38az&(czуcFY=|v!r66%{I^pP/ȢaMbo [&[jXT:OzȄGM^?YCx1^:=K,4uy3^$<:H9}O Cd3Z:#޾шZ-Nj%{1[,41^&%S#k"<殩6>Oo%z${$"Brh )TScp<k9lL~]]U]]]m2.%.AN@L@vxӕahb}$d2[lR',ԤNXbɱ)5(a(^_0ׂFqYcTͰqJkx4a,lX8% %f;WZʧQbP󳳚495.ړEXMb"meom&DSs`(ݤ6D.!ܟ^D:Tm0Z(qf[ B"5xEd@yS h728 =޺M&g1!wsn@&0]dVPW.+t֕@3p204n+2-u/ۺ[5 3~kF t_ t 'F\3k i +SLe r$hp{eyc\ yNNj>V @M]F(6 E#IBil nX3M-?.C~M2? a@\Q̻B .}~&h6 F#{^uLN%glG!w?|@ĪyΖY+h$2]`ahq :.F9ͪQdֺhȕ;BE>/.(x*Ew[E,+-BKB:k$"߈ agUQiR[}'$_;G[h99DWT&"rχbb.(1Q,7HvrH׳P[wcw" R EeSXUsϧ;(mt @ݵN _d![uP"G.L0H"5 "}C S( <>)LgIiʱL3\r46Z(3Qk!E7?d\g/d"k\prc?sI(%O%ƶ NDR;4TuxFT,*]oǖy7آkԴ?[ $ qV(d U6 \%փƳ1R*!vWEWpsEX@~~+,ב,{e]ACPHm.S*bGLD7nkaҕg88K/8oe+nY7ϸm[ȭ,fi hepVs'H8I+w5U^iCKttNL**Ȉ="^_fqOkN/6gASw,7Yb?a;xg !>=f =;A 2HZVzTJS`MNr׆VP ]rR1f ;~;P=aroSoOО0+=L .n0د+w}u*rY[-N;70 00R0 E!j H8{G0)Ai`[uR1uLM6QXۉb{ cfXS}s! >RtAG}EqYԴa\5YεH ,Ddb]DSR+LZ!`T%Fͬh _KF8W',2Kfsɜzӏ6w[&uN-H(rwy͋?ܧn~g]jsս>zf|SwUWA06U2mJSlU5wwo>&i|sjsn{k ίw^}w~_/:,nx%ob~v[~n?9 HRk&`̢30t I26 ThJ j'>,:ΈJUsC69G1͞F@KFe5m# zy2%O\0'ϘlIΦ'[ЃPr;Ƃ! ūWYIHA(gYɦ$[/^l 6f@+[_HW|JNUG^ +F3߄o^˾&qLN52&xLa1K&t zz3OoF}ˠSԯ[lgsh p.=c]?kZȻtc]O:"-?V,&N`XԁiHَS$ *jan.{4i !@̽v&CG PUHzHF,?)ivNEv.#a(nmRLmrðz;ԟ Q0#)v ,6@-nbƓ=n<33@=KrYI)t˄Q,c 9U 3a+d|tBuYÓ@N%8 ~J96(kSo/y_Ooe聕e<{m+@X8Le$AxFdtZBȌS Jy˻ tQ5{݋q:}Ѡ@_<"5!@0j[:wCҲϺ=hs r8r|_cq}R@X $Lvx^ha1 ,`3p@ƣM5+leTy۱",mXVVv]٪rIy4̒,;< ʂ0[nq S/aQ}?ؓM,,ҿ(OFzΈK' b zh%aj#^ZUmΌgfL33 ==6]Ph䁹B&Fˍk73Q9vp6|Tq`xk>:,\5Մo)Hm]PzYaŽ1hRpmelMMW9LՇ43Ԇd;Ls0S _m6=eC_+H{qم|e^^8ogO$}>5oPzLrBxPWVx8E[_#VQв2ތC+}r禙#,N2'I(R\8i`uٴupsQ_59Oڄ Ƥ8>NǟTFPU2 DdI[^ٰdxr9uY laݤjT EL0TzZ EMg SH\OnA?&v~cߘyl7>g8ĹWRðR.0 T1i__7fLpMt-5LYش n?} S1q{#zyUҨtu00ҍ67`Rń/L+!PVtq^?^!!#N(O2il$!@5v:;)a3{s^UV>M,b*oԶr+B!jn%#'{ / BI͡XT09F)ky/sX"g98?kF/+|ݸmqu݂5pq~xջݯ?~|^]ٻyOomr?>6j{];VECZoqz5&j1lg1i;i2Z!ԪrR{{x& 06E-hsh{ Ttk)M$^q>bC"FK>bǯE9/qu _GW/F\ׄ3|UV運Dz\=6 xo;ЍD2Pb@fe'g*BD!;0tp״OXBDSd "9TN?ke{W7$eP΄%ϛNwQډN05ÁSUT}llza ٩ l AgϩI' 6,<)ߞqyq?TXӦJA'bRI7)~L[dXH+GCFkLMm쪪>Qm$Rǝx7Va9qJYD[>)o,+'9I!]< %G0)fڤG‡Ps#,~+p1n2FIaE`Z*oa0tl# 釜" S;xE(Ϗ~9duB+JHFoc٠)U\ƭj+|T{jt6˪ x35=m ;ؠD0M[wʁ܍y3c.cd?7W|݆o}W垏 Kz7׹.s _zo߽>D[ۏtTw m[#UBoOz} ~AQU]RAg'`"g/"3 +#ȘׅNR}DNGA2JTB"w ]?9RǶ4PJ`z5ٴR6j0K>\sW(@Rʧ n7(WDV@bn\̓Q\)4@%c5"(!{& hWnؖm޺t;?tO¶#e 7d˖bbnq\DvPTֆ Yj*fi+DXn\f(J0b=8>'CrP#`}9(n=r0*wŠTUG jg g&Gj@pgPY /T k ~ìjl&Rb4g~D3 zJi/NٖP s}pJBD<,g3im>BN' (A7ڽ( 9= >;1D V,H1΃}U9Yo8\O @,~(oDBor3Mɡ->@Hz+Zq Hœ?7S9n@RxKts~cۯ&OƢ!)*o&"ף}}:|qۼf(hCER@L8Cbe\98;WMyÔ7VOa 2~E@4HAS_}w_gjGLwv饢4H^IZy#st[KU}3~Ġݍ4Lmoی ^0#W@Щ4,ej/T@(|YPWFZ*5%!ud QF2Gi޻` 3Ũ2ZU K]t_d4Ff ,vHMQ>{%'C)̫5 FX,fla [$=kpB!O OLY\N?*$.qH I"~~ `J3l"Zb7: (w$F,rpxng#chm'Q3P[Mot[! zIsiI'yB|OS*r˷>v DӾ1䳜p\5]9α>,.@ݹ0 Ӌs6f/s+\*T9 :Q.G^ʈ|UA,[v%.&IhjtgeBl &R|qXwCYd@׼n4MKV`Zb&rz~%V/ry*|7ln*}/ VPßA"b͢5<ԱηӝyD"/6AX?NթIFbP&I bͤM;iYn(SkH`EL,C Am%k|Da! $+!HWX`f`G"a3*J&ɋ@L/[Q&)J~d9+*7`VUDkWGW4V 8  L$2j&h9„eIiwE`e,ЋS3;J0]UAmxc-/aQ /+aU6diDUdfgt@(TI.żĪVF^* ᲗL4D%NDaN%gf\)¤+нitVAJ1wW FXs9$'LJnðY-sTU$8[PIqκHbf,9/AZucTԤ̹bUgR-#XA`Q$To,r@oC2-X#H=:F.+#r(iEdh=ɂ(I&T[P#JNd(NPJ EJdEz${iHTk#2A#G2d{z$C DYɐl=z$CBYm ֣G2BVjHU=!H/Z֔OS/g.%LJ|R3fO;I+)>a3ÅIK\KIIٔ>N|>C@Ԁ1gy <K˕rZ˰iI^.rvwZ0 rsԆ-aNer}|}Z¾6E_Bѷ*E_GѧRiQ11PtO1E Nu̕2S5%\}^yBi2HQvDybdlZW-.˿iJtq%4\iz:I%VD+qK^Ԭ(!}|Z(s |Z/5yѨ^qf2Txg Nz/T4Jqjz>qf5BHD]urn{Lh۱UlC e2u;`6hBjg6h4m C!srQ!ӽH [$%);o*rIgt~vJnt`>xgή2 H~‡lk^ֆm,w ;JsR!7I2'O,? =cz_Iݩ Oy8;=7|iCFUZ2gVBIj@ $HtEAkDv0L;c񳾃ْv /!c\VfTcYs&wQA΍ǡ ˚̠Jpr1H6&d6&!x07L7k/ь/D]a:K?뚉2.PżX2C!3֏lN7_ɾb˛ ,]0*űx)K>Paq MsK:X{XR{ߡG;u:D`7X283_5TԈV _Kq,u1, $=7Pzvagq1̒8X.^/ՠZ qNtW5b.('-o,w9x5%ڢawx;|۷?o m[܀NT8^tE!|5fb2ha9IҘ9vV56Zj389[itT-_258HJEGHC2TQDAIr){%e4Wl*wSSI'TN*;Yv.d=ZzYuJPlѹ""Ž˄$M{ eW"e i.a]#BHA$K$6l;z8暱tP꥛k-mY7~Of= i@d{z{s0~75- oi"mIX}Rdi`!Z E`e"T!W"0T9H8*֠нl80l'WN0C۝Qsqжm?a 8΅o}S?%!h{r7Ҷ^~7aming+gȲ1u3sX UUERݑGeam݁8byєƺlm"1wfUCb~zbjEadB(э3(XXG wDXb_ K J~ .w 8f o.!5M^MFkGa~]uwehÊLF!;3}P%0Mwrqe&1UL:)@a/gwv,]g7]1 #οSA*&P[YbQ*BfrPbݩj/lwE8W^]ܜPC]5T^Fu-ݶ70ۯ6[tg|?fai]13K۱_Ԏ~c?pgc?8=ԍ~q;ٱ]"^FGmWl7yY^lZ!|">fN ޣ=ƐJ]G"Y 2qc tB(#KsFJgÅwN VJCGYXpN>49)| s e C@U*(4:K`CUZRg(#lΞI xQ Dwea#Dj,lיjstFP2E4ڡdŒK6aWB%W*Dҝ+ǔ3N?,9}4jͳR`6wn8A!ț)93[(qˋ|1]8l2:qyhGj2]U/fwc8<~^tǫuu7ɻwfgGax{,jq:}q|~uƳ˓?/.nh9@ 丩7W_O'EuY]-'`}ܰ^y5r'gL'Ocp^-Y몊1Ɠ\pu"ԥ]ᣮgfpd9YinJ3x5ףq8 &7ق7ͲN^gw=8뢻fWKQPLfףEɛeu2NN>Wd 'U2J5.j4 |OE{r.˥h2ibѺN]k]^,?\d8.fog4>&2S3;;[TZFj޽.dA#=0B)1:F\ LJt_ҭ%0̠֟Hþ̀xvayXOǰl]@/-~JLIPh,݆tKߨDj& a}xbQbw+Ap5 zE5.ލ>,7A7t #zVp$;\V%u@<>u"r!AoF%򄮌dIz0O9736|Bp?FUf Sm{[ԧ3(Ao(!>(fgRœפE]=#yӈtlVn!/>%j›E5vE ?磫EN]8-D`t0@)j-WC,%QISzv/a1qH~xqz{;qxGe# aTe@jH5Ikxy0(r&KOyzTQ|31sPp!fC 6& dR5Cp2EN޳6o9EN0+!('!kBPNJ!z6ɋr1M#,e{` @ɞ=fw,ԧ),WSm)=i0S575`)(* C$w{Hq%ٌkLV7^VY!k$a  @"{jkA i$[D- o *r,T"Sj9nbߤhIG5⭛{noajˠ1Gu{vq͞E-qzlw!xc`t .),݌[l]4Y˞SP\W홊Qq؈hP(J$,@s`-Ԯ#Eɣ!jBhc$ 0 Qt;yZrȏ9l{r* FIkc0&25Ԥі|1$P!1r'YeeMI T엽=4/ B%ɎJ7p%j8!'K!WJSBISĻ/C 1PѰA !t+1E&O݊'<ozD}ÝyDnCq@Q4JsT-R|L5*] S K|uQ;f䔶>$L5YZdݵ}\\hpD ͺP,LzjiI$STWi I`ĻL '}҆mŽek0A}mk0 Jt0u2́P f++ab_ &D=nOe)`b dĚ@ۻQ/bJ{mLe^\&0Vl@l)$cVBnH~;-왷*8qjaTVLPZc;nrfjnPr%F))#FѣAc4xvmP2P{ZCY$[\m|ed1+)4sK%U$: SR 03oTيNCL ޞr`#l[1X!؂850gv NA v'd~rz¬ŧ{yY9Sf吱\]!o!+0+Qo( Jv+" Xju[ :nbz0HV5xxmh a$D~08wMAARĴ}bvX4z˴:X +PۼM6W/!dJ [`QOݣ'j NhO' ɼymG3ƾk{HB?9q EIH_g`CLvܩ.2xwkOEr<8Dimטcg{иsuF_֩AwMJ?P#O zgc3ߎ(=oή.ҽ$1Q̰[eMHꪝ;>wW3Na'uB[1fߟ~ϮG[FKA\$=r,>B>n:yg|!7b)v6;sՑ*>"l4R=msEi ԣn}gh;7ѝytG:2)CQZ0'i5r xF[gmv٬l崓,ضdORMϯոIT{3W?_VWգ}Xیji^zGh^V?|5]6zWh5xk^T'OR_=MMQp0 i۩ 6Em; bmGoUN3 x=7CCFzVW,wmoygz׼^yU Y-x=O]Q?[Ѽ[xeJ屻|&϶ww2e($z 'ԛ<#;};c\;8jd6,Uo>uRw:%tR-gUqURX2벺wӫFpvۢ yEuuzuy}[ԬW/h2Zy?~O{6ՅazvUMƧeڌM/ag~=󓦠żp]eBٻww'=w9-N~Z"Vq^;.o*xZm_C<ɭ<]e&/I`U䖒EGjtYQS[-4M4nz6Hprg[~A?lr3^$C_?L5( >_eFV2f~ӛѼvgncx݅b7wޤ;oLWuue)~~cՁ>FP lٌv6C) )U`LF4eMވ||7m%LR.+`{ w*wL,yzU{_z ]|`0m|L_-y1W,@=N :7 `m+$Q9KH86%Ldj ϩhL!x)=pBݞnC@@­NͿ{&ZغN yQRw<5%m)[wIqA%sDN^akA ]8(6`d5l8.Kܪg7tڢE8xdH1t?[yޓF/FI/1ueA#[&w16mkhKH@<h#N$L2;)>v܂$) m۝P Lk+& F j&KuL:7᭾6Xb`\6=d S;nyҞQ9D @_w<ڞj  -Q6<Y S@;m_w;p`0݄{yn{ fDyCOۅWW?UL?d~lVH`́BH9і^u k@đ[\#0vP?uY8e r x_ֳ{0txƃz3^Lz}X/ppƛj:m/~YO૳h424ջѫp(3}1 b}4>h_\dTͫjY W[դ!?#WS%r H),2bYlbk*ZkGҗG>n\԰W. `,͏oCkiAӼcZ_'z:_9ݜ'`g&g>Lv'ևqXwud. hgˉ&Wf8NOqy\]oECFt&oka2:[Wl:~\GyW-F◑LΫxi|<"Ufx:W"Qm~xB\`S+Vkm--L.}+NXWX3+Ny5/ϯ7n@GgJpڻe'1mi1H,]տi]jX>8oV8C+r <Cc-" [F`&6z<e0c ֛h$=>4W)=Q IR Ov==@R𾧛h:I#O]dRZnTg7 d%(8%.WG_5U67GA<=]W,rm$>fwq>Fe?QK>jR2 Ҵ qO'&xPWy<-~h!>a%lsXO8m0"!Rw3~ik<.f],%4Gփ.+oѲ?1\g/W}j7xӝ#<@9O=;_O]G k'Cou!ZU! 6T {gӈ07ʸɚO݅.ƅłHߥ`N?E|(ckwb,`,ʭc/PN:w'9>~Iԫ!Y|¹d4M.O:PC}~ݰ{2ƥ>30R̐5%W pPm4}4@7$CDګI2dp0Y#DvD\ H'E |[gu/c{$x$w- T~t"S=O3/!!&M Xp_,nv>T_ 6z— eݟ=u6 uE[Bݪ8)A_U먟k FKb1T M}8}?KwUDMMbh;.WjuQ}ԑVQ~}6.umXO47;P}{ /]\ߙwZ?-ͶNOJH.r^'n-dv6g@ǒ3BVMZ-D.-ȊTk~ |^YߔRoot+ss_\(֋70 W:pwϫx:ތwNz|-WobzN;n:9`oC-YHvJݗ*v34f6LJ?jq^4֭wG/Nf|90|9m{VTD=E|WbެTGjX9]SLG"bZY}TU396KY7-6#062:Yd>^5u0xqp<NDhl}ˀy`ܒ86NOQ+!@Rӣ N`z{6df#1sA.A-FPW ˮ[ дy8Rh;ΑZ9eUFJ#$wJݰΌOUsͭ\*nXv9΂g5楕7:e=gAs֎ LNc^֤D6wwC0@n>h0"!M/S5'C@cǨHp[(>q9(6!ON)( ɞpހs'A93Z2ՁQN1Zyzyሖ@<6/|~b['C)Ęv8 il `ogúe=gaԺr`F'9?gٝhl,AγE{2^ р@;mG$Ȩpjimy+5rPk%v%J&@r.(͌&0RAz!re~ 6|@Tk=+l)k9cB\Ff#(V2d'}7@ӖVv<9.cO2ZX8vOq(ceu6kNvԴ&SͮG<e0$r8&38P?DJDْB%JuXȑ`Ds 5 =Mh}V.K|XSaPI;9 S8 ,Zj+xkC<`?! 똴B?&Yc!y.4P2ceLWS,QgbL atP/ gwU\$ݳѕ1r6Rقu9:V)BP1d%TiQBA &ZtjΦ{HT q#%{ L>BZQ1L61*&4 ;\ "Fn: 5)TcmHdJ&qR&,7+ f"(q@n&kT1&k̑؆詆 $']e@/#Q %!Ԩ[9|BQc`=RQߞ ,QI37=^DV}0t%î~ȅ+UY2Z6X1XC?2 d(#h-,O.躤=ŻDG)1i=AC ơ';큆4p$ Obt @5j"G eg,EٲE82/Ǟb c2!ńQ] CrdWmzEaA혒%A`9B"N#gtA8QcZ&J14mٵZEAKB30Yl1=YMec9ĎbH>da2etw޽ |&~\r!3(|8r vY3Zd PVg4;yWu[>fؤ?(ZK>lȂ%S6K1RT&Қ0x  ;eO2|˺8."|4,p(_z'gtw<OcwhZ;Bs0Ac0K^ĀXB/N @[Pt8C:l%֊KT*KcɦX)4INӨ\h-BQP2-͖`&Iz>CYeJglUߑ [l7}8ً2e}.o #zwU?ʭ .MFwՃ<7/1Ƚ|˯R;?4GRCarla-2.1/resources/16x16/list-remove.svgz000066400000000000000000000063351364475620200203760ustar00rootroot00000000000000[ko#7_uXb".8Xn{=궭Yۯj=ش%d35U:dwcf>f\|8b,ggQ84m(rQ}8[,74 ~LU5mW^6ZWh=o]4rl~u[ϻvt\ͫj6cP0>Kͧ}IU~˺ɓ{5Xq-F-F^Wvp_WZ.|]ÜpЙoC[@z=+ǟ?*GZmfnEqS5bZ5-.9e{Luʳ`V*HeF|r9eiGuu-tyۮn_ZGY)~;OEv˛jӸƟjSvθj6mˇǫj1ŧy5.-oM1r?ղnGyڙ+Y9q*}eC_y\vTZ-y(WLnoc{n.dVJM긖Y뢜;?t9WSfG1/mԓb~?]W [ vW}YZmScKS=ks],͇gߡ2|9tCR \PDp@x\g+< {R^K#7&Tm *h"^6{x8 _^z5rֶs掀#|{]:hxw,//Yl+N>k@8,"ŐyR=\ԇz,9`˃IqD./ }(95z}"NSb~QޘfUWES^/y8).e,edSƐ6}йD kώZ73Ny*ǭ}r>cR1&Xn¢w_tuL*r!Z/ m03MG&^*^J5TjЩ\#$'ڪOxO:)1&-QG6p:)6)@m̊_uNNʏݬhFKQZ'^ȷ[BkJ@>b1JkC*x>S`C& f2dž,c4c{ 9HfGz) (v[;AE"dmTݻM^b+󢭾RZ.PoyN Kvowy7 OnrZ'uSiYUʪ6iOzQwz}s]{^%V\t{uxZ=}X U=gV|ݮӺzxxxOg#&#ӳ{]Ռ-'lZIvzj~੏[CSUsDŽHUfH代GO3}\_Sb3F;|{x,S{+r1GKo(Hz"l>m$N]֟j& O[NOgӮNDEY.%_ߏSEX@6ϴf&lgbt7nW4.l'ڕІ?Ugj>_vJi\ޮneƶܔw[7qɮNx};mZM[/?WrQmRmQa&ѢZ9&v/>u]I?#A xWrBQstÆV1FF}Q[-qesA+]8oBtw' [b|Xz/~HOItCKˤ=/ztP:(M0.!'(Qz{81~HВ^t* v R )4!I9f"Ũ偩Ld4A 5&1TD^d$a=?.s$;i;r'ZO\WIvxF῝iqِqQ u!*#mC]{;*a9ݤF-J LrB͠0ƎȚ/*ƽy22h# 1anxlֈ1*g: !D ^!zsOL8$X3H/@ZV6Db{o*H `9"- 9HY=ڿkiȿN3i3LDQʦ(hc ZHVvh-3NFwL r`DtB˞MGg'(C[Or8gS׾]ҳւp`Nz3(:p==Sc;L{蓚SLͤX tdVa"jv})׬>J Ǿ"jL$ .ajѥbR֜44v[ C<'~xL+g1|{ΏWQ4|oQp['+/d% )6Carla-2.1/resources/16x16/media-playback-pause.svgz000066400000000000000000000040061364475620200220770ustar00rootroot00000000000000~uFmedia-playback-pause.svgzk x+03 y|*_%ە|ba%@h%ݯO Hn,{絷?V2ɳKvEyd˹ǩr 8LL,w|_SBmR=:(\kcUgnQQ^,g:i86+gq4wHk8tW:J ⹖<[ ]":.e/Zk"G(>4+tX!V1g)Qv)YcjlW;~ #C @_Q+9(⎘6FpdJ0ҥkmW TG,+O DZ0;F>Q.q%\_LG`ؽNý.*_#PxF@=+S{(򥮪+!]]߈|S7սU:;(ؐР*W"~Ul^nbzU[q$s i#mn}uF /'7tG}4ǒ-K*HM/f}+"Jȭ]UbDOp0aHRR멚L `ʤa$9 h &T %bB(2~s殂`-t?w(VӰoiFL`*.M 9枏ku#,7nH \.֠8u?TŖkT븼y<dd̨Q+ yc0*e7ϐ>FT\VyQ-+ $7ϐຂ+6T fq"O 6T,Ըl?KgQiyxT^{ې:FApY]݆ ׊`.O_yV"g6pSI}H7EמN?%aUى}9#w2Bce", CJQEbªu`#ksw`jA#++?gH߭ D^<5/ا!n^i}~{ylceՎaVGm "Z3F\NTxJ@~+^x23Z&OګufQ͡A{Ykac06 @A$L2pEg& msp0[ I@׭bϻǕ;fʋ"l‡|f< ]Ldnn 跞EZ'K_3*1Lޗ*IOFIw5tZG$Xiӹdseo֫wKwͦᣠnEBRsS̽NKLH[~bJ]NK5g+lM2M2r\t& t`F.լFmK2{EGQ> )g]lDi,VBԩ ]C߈b';(R'lqɉ Hևe*` 0]E/\[FIe?$3tY/y*!v(?03R \s|7,[c~M))CyVG=0 "ohp;.aZ%iEqQ L8ȊrrI:9)JHrn7И.#Hv]Sal]/ӏG@AK; 1 72 T,⭯"QΦ35^xrNP9;0@! 6 VGt1B3C@ϩ}"r@GQ!7= @8إ5aBp= LSϣ#^%5<Carla-2.1/resources/16x16/media-playback-stop.svgz000066400000000000000000000037071364475620200217560ustar00rootroot00000000000000MuFmedia-playback-stop.svgzXoso6S[HB‰{vwwMplߧ#ަӊI@==yRe%"ITNUGyeEn^?/өSZ%.W*6yvJ"*ʥwLY=-p,n#ٖKbOej"kc+STU-8KDm$;0 =L=J 1yy R<+ylA^ p!Z:u w)FI̴fƧ#֪DnwiR TJUmi2wa|>f0af,5k!2{EU>TuAD1@[k%SxRuUb? ֛mʏ! 6%G6x5[ _[]Ep(Ig0Z?2Cjl*0J~3kq:!~TYO?:RFyZuT-F } Cj*'S#{ IHC_\ HM#] `@-0w*aQ˹04Y/7˅"`x6MCX@y|#r|>tkwXЪ#g +lڭ!0>mOX,*8ĐƋނ ބiWx#vҼ*ʖҿ~!|F x%(d4Y "!̉2ʌä֟YT\4RLT0D%pG>LsOg %Hby' ӆoǜ l ډcup^lYV^wΚO3@F5ϘgƁTw~W;/8~\(iX\X.H@ՆjU0^p^?#||L/7mAxicw{lKEHZ}EGEBm*ٶǓܫ4i=bS3 .ƘN+CGdƐT}gqFf&j Kkw\UՂ^s_Ut\\n^?coo SC|s?4SF_s&&kP;칟]WMnF\RGr\(1 aQJjju`6ޙ@h9l!ۗFF[d^Q2Carla-2.1/resources/16x16/media-seek-backward.svgz000066400000000000000000000037071364475620200217100ustar00rootroot00000000000000~uFmedia-seek-backward.svgzYm6_A/51cz^uRV;V,8 -M_߱0$loRv3ysnY"ay\$i޿p۪d'QVbfn?LKIXT.oUr)z8G"*ʅ3&Y=.>, `j3(ޔKbGdb%rY96ߊTؔA}%dƒHT\FI^h R<#9Lj Omtp5:B:wD&-5 i8h%uʩz6M2r]t&3t`F.լZmI2{E{QϷ 3!gYDiX !eTŮkC덼;)48x$CB<0{Yn Wp?zE-\[FIeߪ2t[TBm*QSQ!P T}|5W,Kc ~))CyFG9=0 g"oh;p3.aZ%z6ҊZ%8p&qF u*SrS畐(\E 1NHQY^݇wGAC 1 72TY$K_Eڣ'yr? n {٥otϣ35݈cenݸ>P \7Fkz1e:,o>1j.UW=2$js SW; 0>WW@0( @૫ p`n}r6@9 ) >,/:gAi=zൺz\<(M{ѭ/kӭOEZ>ZL_7/Hn3Y7FJu)$w1^Yz'VtG9 \e?9U!ys }bD& \vE jF#gWR7x>6?͎ 2QUwe)`¬[].s~8ºq4ztҶz~#AD4<{ưUpǾ >c"LwF(zRx?Vq:Oɥ:NMS5GQc:ZTu;22ebuXǣsf&L>j&MDW3_!j=YecQ/ZFI{Q@)Y9)Y! fl9ޝ ߔg3[jhsތ3V-->h6 = ڦ9eRccŸMa'X*,uHF&jKB'OwomO.2U DLcrI'#fb\@;pόTZHVKAI3c˟؅$$fr/0E_úHsE2+ԁ[rxJB_q̈́5FnY k3˪f3&A 裏{:~=ܹRd^'U9Aܢ Yu"J:J#/$r= N- S;t<`GuQr3RZځ]zD8Xh.ç5b^o_ ١y hqIi"Carla-2.1/resources/16x16/media-seek-forward.svgz000066400000000000000000000036501364475620200215730ustar00rootroot00000000000000~uFmedia-seek-forward.svgzY_6ϧؗu-$BxƛdS[TRu6ŀlsyl_K6 cN_ɬgQVi/lm<.4_-/?̸mU2ʓ(+r7ͬJIXTUmv-v8g"*ʕ3f3Y=, `j ,ݕKbGdb#rY96ߋ'TؕI}%d ƒH3U\FY^i R<#9Nj~ /mtp~̀Ns]Hr! sQ"2y6Et=~&r @EZKO s g_[0or#jV|$\WMR`ؽ͢( `O)@Y$s8JH:SqQv'A ^0.9кo ,w~D,+ݢzy-$ h/y*!v(?0}) bY؛H-F`Յ?xS!̼I\F^C 7\D@GN|0WOLOV=iEqQ L8ȊrvI:9k)JHrn7Иn#Hvt}Bm/?><*Aǃv "bndNHG9(~@&եtnın:Rn(o5hjzj7_5k5{kр_\u cOuk Ax 5Q0\fW E\/:GQi=zེ\<*Mo{mkmHE^!V,LiYđܕѣgn)~vUFlWIsI.jsB`ds1; B2@*fʪuL8P] UՌYGwGnn^]C@|4;*D D>:V ץ->nwԣ`Ʀޖnok.1aףGaЂw}-3]9W΀j.o#a^`ur&uj.MDW3A8& A~b%؀Kr2Y! N&vzweַڜ6̉Ub~c+|vp~zߠ}[f56&z/H0~RgF(dd$$́fC?WPS\UUE]1cay tgC/T r>4>*9Z/vW7XZ`pf$OZuWQ_c1NB!E,>'#fb\@;qgF^W-km~{$m ¤`ձ/W@oNmWErjaNZSz1i;5kLl }[(ytJXs7}w|7k%Ҕ'߁@7QeIN&qE "Bʉ`;#/$< ˩}"tR[gG̣. BnF*@^K;pKC f2߽BhH] ۿUCarla-2.1/resources/16x16/network-connect.svgz000066400000000000000000000160551364475620200212500ustar00rootroot00000000000000}uFconnection-established.svgz}[sɕ~qǂsݞp;YOo J-$*,HHn u/O^Nf{|l~>ߛ]O.^A].'7?-fd_.~Y6ҫO6eӚrV.f?ׁPN'eXM/godzõI_Yp|UD>|<_ۇ >k{Pڠu6Av9M/k__Obr\^VJRS/.f˟fGgf'ֵ[囷5bUUpMuK{]lVaX.P?^6V4OȐmX MUR+t[~xߤ^j6e6)\?,+ 벾?6b{ r6!6P_, :K$=N* bF(x (؂,K%Ȟ=o;;Q6Q0#ˆr3hjF6FI{w4J`50@<(> c "5 (m 3Q`aByćfJч4H}{i֐4ALXGHFa;CI3ilA`YZ-!ZW\*biIL>{Qpi ;YN#oO.3T`Q&^=7.2?撍G`)yH;֑>T5u;42b6{A}PhR>)cIG}swdGDt|N3ɆXK)&Kd#l(P"t$)4=7/NFi[Dd 5O{bV~v?D"ȍCmjqHHOk\.]eXL/.o?J}w+?/Ζgr{?/g䇃sJnc% '0x} 5! 㚈+Xs7Ջ[G=qO{VMŜNwyRWgk+,@$MHx% =2ݘ0"6ᒌYil-I-zL NPӱ9sa؀7n pc9=!V@Ů doRo\j;-y>]~\1eYX⻇mwISjb-Oh0EvhJYQYv7Lnl"IJx}p CŊgw [ֻ]b !^@[pQ$C:B DIř&Nk-FeDW2 lcѠk$6=\<le,:Q6[(bBSIƛ|NdgU yI\xlfP$®eg`t g92u"g+1) Ag; ~V h) 3 5Z E|noNR!1'һvY:bނ%Y+\nAplbچk;J1^F{4JÈ1bpmW<0ڮܐ$ tNsY&fzzL'ykݐD¸KHѭ)|j5'Fv<+ °Q|03"Eۆ 8=ऀ|ǒ'å4R|?ˮn"%o2ݯ;~LA?i:Nrvc𐗃#M])DjNJF~ws{z T2wuԊvOD"ۃ V]]cwNlѬ N Z(JupEOe wpE+ލ+õeE(Ű9jH,ED ߀ Kv0 :Mw\8 ąH(fa] Xw'֤H A!Rraf5P.dPbqe`zP. %[CK-a*OKb~K( ^G5 $+Pt-jhB; QAR0JhwFZȅ닻"7Ɠ@PtJ |>c>c?gּxK`MIr1%[[ ,`JGh؞U(<v1<lʀ%-E0"Q,՗I+.ԑ;5lQUYR+k/zߕ{{/gZԶnԶyؼ{-ؼ}N|o^mvZ][6FNW4|I'R45d5w\!HCF n|ۘPۢ&ЄvMhlNFY5oYl̈́h&tzǷUx"xƣ=g3<30iYWw/ (͔'㷯oWTxf&}'oNfrx@566Ͳ?E`}30>c}UR> jx(eM!ng\||=[NO醈k 2鋿߯p?ϛ+MmmZ*N8{]uxyn7*d].g׷߼]eͤYze/M!W-^x1.~]zk-*׏Tޭb)/wy=c׵W[^]gem`"AA6u;Lnڜ7p[og/.c+S?߫ҵ FM8X󳋮p8?dzYi~HW/ M*P"3'\(RsǏP$Lū/n޹#fFTZ y3WuJS& B?V Bj1AB{XCҡ6>bYɚu0oo_K - I?^mw}tR 5'ZTtuil]"܏E!xu&x:,o"sDc/B "t 3 oY:R"w\STO&8OwvXοu|]1S\"Xߢg(n#Rݷ銆)WZ!@!мՌ,`#:#qOc;fgfw[%C,}-lc?<7'ؒ誘au6^2M%'Mλ pd$X2J2y@AIDIcQ\͚2U'V2f)^(H4dx*s̨(f'T*fMXT8ڳcGTX')Dh9C$sMT D'%s$MJZڌ-'%x57Pp, D"-|PЩi"eJދz+ч_Ǘ#`de0-{B2Q.+S5DQD(xtRR5k5Dq\/Z,bK&xk2P\1ŕѩe6h;WPmIL+8eDa3ֆ() Qb(YP[MIaldM ש,]]-PH[r1c(VJKCMY PexezuͤiNʒonY" {%^S;;NgeS&.ٖtky md?Pn>Zk3xZ3Z¦,=f `i0(F3{ =Q[u~3 m)QNH k\#ePҷcѶܞ}xt"xBxOĒ(`bYeQ4K0` G>kJCcU (^^3~/Fրk[ {֖Cy 6s^C4=:Wnw@]րk[ }أGwEPS9{t;~N nMKz}AI+OYfL$\9ڈ\uPD1ZO :yRs"Z.'˜i/P&s#N$ )F&eӌ48䄴!!hA Kq'CBAMeh6;*d jr6}J$`Iӥltե4R #R&\|jh:6U UuĶG F+s6i{%_'rUB3^C|՟0sTekQ`0~ ,r}SAth}`TIQ$RU:SIju +e DrO%kdUdV-$+QUWlTɰ>(bDG)PSZB.'R '}{zD}2"D7ѮIX&Y5v6[Lwflyy4:gۿ;AܿUC[%>M=9'Y2b)}ia̴pqP}=fogsW'UbjOՏSŹXפbֲ GLԋXCrCq簃AT {Ph5EAqR٭NH!1h7f佬lhMx!bO8K ,"n \yx3h,' %ո.JZk[lOSDIǕq k﬉DҁPrCdw~zKdQ'+Ƽ 0W[^P l2n}1N gYr`Cv(IY?+DqX`(#t-skv\}ţHLֽWU.^@d9fX]@&1NfG#/ffPdS" I[*Z6=l dDddd||0[\_]{s?~ۣˋś˃ݯ~_d9>Z~Oْ.m͛j6^ܼ>9~s,;9>\/>,.no!A_/i6]/n.?^w>9m#DDaCy[b~kUn96/9- _L]e"Ӷ"],nOwNnO֚Y!;^:;}JzM_{ۧNf^PN5kzK9aC'elm|4^>}۫]|]\t\vٵ^Wonڮ_~X|v2bv~zv(< ƪODL1K6M)!]Rk^ ?NZ6/l:rS;\55JLX^^- <_[N q޶xy9IοVhnu.OOomǹ^K b?[lMzpFDC6Gi>=1=H[:m8L, ::cnmk?,{ԟ.nZϿ),_ Ci(圱_ݵr@$ys0 o>:'Q1a9qΛ&zʬ no7H&u`!7v< &F?n(ش.`iبY**j#߁qÈ3J*`(aIپ$\=z+Hg N2lT`amm.=r~u? [npOB!& 7wS01/wպWZ]a=yzў,-!v}ehyBZw|i)},yӤgx &v:)`䧣Ӛ=0:@~H@N>!'sW&16& ` L$o戻!% SBL1)MM 2wʦАITdJ>Q鐉s<[ .}$&d&iIAOIH`[iK rPX" Rf"%-E"OǾhwLtbFV1*pb% x LDs)N)!XY!}/1luȾUeO.IeL? n?O ԓKyفKj"fY+{l/aRU]Hfj96sLQR9cCYI9Ff8Df&/~nk,<大܁1#/ ~-O!Mh &0HR].\_vTQ5FT_x@$ns_t0{׌q׌1Kf>OeW?ak۰AI;g[Ql$aqtKZ.mا9coy0utw0(hC#CVh2< Ѷ*R} 3V~O`W5zY n'Zae6b?lfcL?? aВF>"`g&c#Lmtv7/6Sʄx)oM{S޿)d›l{v Ea\'mx\_o$J]PۊWwi7QD}~v@8mmYc"k%DžeÖgY&qoa| w9֓e:)_'Y,vnrdEycQI Q-Ѿ@Gn*z:.IdBsIf fNM_VoEdlD2T!hp-'0 xOAFHr5@zw"EMBn Q=hP{@*1HYuXo(='0dO8L;v bN ,&^J6Fע'PN\m*RCNȚ)qQߍyp`po"E L2X,T^pL"7$2QI@ǁJ|B IzZ3 Dp\o,{:(IҨg. &FQ%Q&աOȉ9aD==;]\OG/ArhQBDxWk_؞Xhd7$2~w77gGc OώnW({NCxKob;1t$R(`N1 .#MaKCbL ΀_<]D aXDi,R\Æ %El,R5H=)0њMezT?mU<P)Ek!n;nqZߌwW5wb<[yiח/N։bHp_yE;9yߝ,"|ˎ[4#R2F5Y|Ԓ4)%{%&ƦLY6Z@8l3*zU"urh'|Le]c ' Eн6p/kaLaã ̉ywѹ(aì%8(]p"PdJL8'q>HΉ -I6d8#X6WesaN$JM頻 M6sm3+Y\X_zA$.I@s='U'-(C/Ҥ&6IJ(kijX⠐5!b@"Lb b-&&ڷvҷERһI2dj 'wBnKuciPRXGרL֠L]O`$t-4_5YdY*2yXju3D9Q@ZEMH)Y5։X"sHv0cv@nQ#k3GHYr*ܵQD@[:lR-X]Y!csNֱ@jZN]$%lM-7jwŵdl?%{Ӈ{FpBxj^BK^<_^h[?<6o?޳L.ÞZz7>zjiTH' 6T-VnW;qƶ ؐ')}-x^`5‰~ߗmE)pc;A?هVo~~?8.KBG蛽^\~>nW0]^kipV*m t2XJ]Y6bލ R|zk@׻ۂ OX%VK]_} {fڽ#ZI@.>#H!3@JεVpB[D"RI˵'ꝸڜ%VM&L`303MT!R'FfE!9Hc_'9O*y10UBƞMK3p NΪY@F%y0d[P'eHXs4*Vk'#A#9!'F'k(ɩd.ˬs@hS3TFZE8՞AUDd83H٣M*uM-wFOFlhٴC#!X%eeli\3'eT62fR7 2zhܔcҦaY''Zߓ7QZrÖIdm/ Ibl%&1IQD["[/Ǜ.u}D`=<栚U [=#/ 3+JsWB]ė4XGTu"UŁ q՜6˂}=yrt vv)6{Dg1L{DXH~/2nǯ^n0$./.5$jxb6h(<ѓ81 ȎܨRYp5 cNfL3\:m 5 {F9K$3D}%{z %@3 %3Sg#Emdu %G u l=I,ߓWD /;a t,UHԋ~#p)}o6A7cof7 cNg˥;px.Z~_rZD)J̗StJk4e[raM+hIC,^s&!ȥJ*9x0Y_v#k#~UJV \1#NN:Q'w',Ԕb)Q(Qza=ֵYTDXFKV:Dq5 Em/HXLK`p7Hbj4y5xPT^Y Du\ԕY&U"̝ZWGJ=h@ ."vGQg3DC9S:eH:ka }N1 !bE( }=j9,FU3|QOJn86ݎ@zI(x{2O{{ZE@"{#FjRN+TQ X&- fIB Yb)t[\Mw!gI1nЊrzѻ8ɇkzD=`0ve vQ Atr;J?xc(cjxP=|0 M\F.cG{*\ T^,90R{.Fv˯ 4w ؈+:aDzDgkLj$Ŀ g=-/N " ԗ@~G9gZj7PhXf!w}O"F5P)API#KAK‘`>ij*t;̗4.as(T~O x=!;R`RPT͇:#I=JS"T"'ܮ¶Ty\i'&L/( WݝpI=AY%xlwFnf2,`6"Mx]E䂷l40]_͝]~΃d? <^'O``D }9=NbzIz2UVBIXli\B_i0% pPx=_ xp^AT'jb^EboHNjj"0^su zvJev| NKp\fQ/vܿ@]~B9>>{uk&CJkn\(篍kq[H㷎bRvn͗Hr1Pn`ydR=[8#,Q=-:Q% T,<5kGɫOiSq7F{}eKHN߲ ȧ׭[>j } nX~-\ $ZlO=];sЊlqP `l^h)ӠotbAv,Nb2NVZ3 />Vz 8oMzMF; GZ llp2(?3 }KYrFK\Z7ޚY9qi~/sˍPjG8%X%wߴ{ml1e:`͏j6ޔF ,u܁CZ_vaz,UU(쫂OճnjUAFMm*$iQI!σu5h׺Pv5kfȒFu9:cN c&dϝqaD-c))5j)eLauB >3D`/ӭGg52.E0!Sx|'U3 n#.gnuN{gLh0|EYZvLk[FP|d^c|Mڣ}38K1H6zW {7htqu{?A"I}H`cNčdHbEȓ۾h{5\ 3p LS}ސ"-=[]x1zYv}#p&/l#%o}P[x$H*ACarla-2.1/resources/16x16/window-close.svgz000066400000000000000000000051051364475620200205340ustar00rootroot00000000000000ko{~rFվ!A JfCIYRitg"codh"һ)Ax:2t}7=eFanfooA06ai>.&?pk'or=@$`fb2شXD˻~˓.Zmb76-9Ad>KOtG6,-iAG+YED1sL@Ǵ A{*7bF8$gM-PP]LR[ `QM|Ǧ?"i6\b^ë8* ^l~({M>ZO9;jM_F&vmfQ P}kD(|OyeϳqmӠxLs<\0+QCeٮ존I'p ]{6`'$pb8 Y9H*[mu/C0y_6>ϱroB r͆yPaV1y2ۺvSV–(=Q,ś U _M'1i idXnmaœU%/r +ϛ[' 5KXbvP?2W )ʹb Re )a`+SD1J)2 `,I>?mib ET_%u%E z5RzHuڨ 7wMX-Y@fx0bF8FSs*ixEZ%ZzRKꠚ;Rٕe(a[xR8KWZE8-Rx,@C6{0Ne), "b 1аAҾL ,1.;!j86IG.@Tg+-)kO^)'!Xc{?4Ih^G 09^,/Zw-xSX>Ԭ񕫦l8_&kܹ#\6sx9bnL/pN:z{q]Wۻ84˜`yhԼTN=o )FPVpWq#9v Cw1sKcF7msRSQW0"F ZMǢWh@Q iF  JERcI>!y!xcLg1.1d!BT1rfAtKaW.6Rv!y'X?ݟ&aiR 1pҋc,He8f$L.=ݯܷcl )߶VNUYټFiη.n^ Ce{8_"gqS%ڭDZ_ FLJ%%2ʖ V;UЙsGG vW68̓[tL3Ҩg(!C)qC_.xessF|{pٞQK fqZ /}==pŸvc0 Ч^ QzVwd>Ax՜3]\1,7Mr;qyZ􃋾ߨM&.$ i{gE"vKmepVn˭ m7YdW:km}7S°Kj4W*2S5Qop\tTg{~=>"Lq=3FM!P͓>E!yi&%"7&k*i]<5FtZΝ)Gv_$z00qql#@?'1Q<p3??$?&R "5]N?V_om|^T@[77ۀ>f3`,^rsMLRu0((j N 5 = #A]8l]]Ǩ?+@Kz3`Cy9>ﻑ}`Ҭ=D z3D N{㧔]E@oEoڻDJV[|qY_0Lv!(3# >o'#F0M(UÈ&%P႐Hhٌ b`b&L ]1 /`fK Pݭ_RHB [ p PH*,Tub-I՚:(`9M_}[Ifu'm>vTEEEO>0ܯAH2QPFPLa*Ҩ9p: %]؟E9m?,e\nU#\_=5 NpU1Carla-2.1/resources/16x16/zoom-fit-best.svgz000066400000000000000000000143201364475620200206200ustar00rootroot00000000000000]ms8+t/Z B7odg25Uۭ;ݧ,Qvl'ɱ_ݤDiJMFx(|l̦/N@N6FŋM/tt4M'ɟ~z_i6,gb9zOW-hKCldhAwk:f~Zg|kkBe3_фW?ዓhFS '/MF@8ˋO'KvFt vi᚜kFYil^H ~˦EsXv6e7YNgwԿRVu9]ŗ,R1֟$֑uv,_l~TvSK*fo.S-hf5%+˓SLyul>O0lyӻK^2'd2wC/r1|xa,ڗU"׉oxP-u i.Q.zY.gHQi衠1'}ϸ3GrMM`S$h",M$pn~$X l-L (ۍQ=bz\QT`NBom e#*  " {(vOSp)_nG͢:ѱf;?^f{D$d\'WJwUkk=1B bK*XMѕLޠGS*Gw0퓅.V1XӘ$hwTQIxhd"Md"MmcLB툺N+9F[W5C`$X`2^Jq{ .դc><<ڨcN{Er5Z}ObѧPbɺWzke}zE)t ѐ0yeR{gb8^Ck<<--DmC Y2эJܑ+PHFg ` AEC> 2Lrb2˹ h7yL8>āw%!3/ŕQwR52uMd?ӆ#n. *"X&ؓ&o_nch}ԸmhKEw;%݃ZcRIZ<+]޿o634՘&h*'`6QXzab9O7y6y@bGו窫OU(Qi'fV 'X ILAxmGvêOj\TpځѱI{~F{zFo^8z$#DbcUkj׷jX wdBa>)kD.n/f=2bAAꉎ`_x4b>q5B8'=mz-Bf ̓jUnK݌V4kQRj2k< @b P@y* [ |o۝1įة |3;n V! $J(ÍXFjW߁#ށ=Qz85 n7Bڷ"dPTvi7VM zèu(] TFʙw{B|]OB.ُb-PO)Fh`5w6cZl$YN%7 Z y:|1&CK kPiƧ D1`1 qr5?@j ap98o#k0$<*p )&Xby-Q!T3װesrU= #sYJ;0yK^sӂs6Ĭ+hh= Wg{ei8fOt@#^# @Бb? :֚v 9C?Ȇѡ M7ǂ?n jqy5څG줰<N$[MEh>t[rwYԫeX4Bd1Pe9_HGXΚ]tt!5 iE C;h`>Gn [xl. Om}s'@3N.kEl%97C1'Ceq}x[Ww:h4vwTݘon=r'o(JsJc1H ͛˷ >s>yYT4{G!(;^>RU^>-R"BwbM)%%MfqYpO|ΖջOT0䷁,E"&YyNCݘ\䀿p|vyɽ˖bTY)wҧM|i6i^|+bvu }0nP)QWLPBP՛ ZJu'O\ehh6GgM[*./'l!MV)/k&p JCo(-|w6/wifUz9|TRSE\E^"m)._*_AI{ץ, r\bM~췔eX`ZU=,}.:o,ZD Oy>OOχ(L OE}+M?GSH⥀yV|&/W)WzUZ?}COW2Ldlh;lq4XhB$nL$:{*P7K$͙JFI`oʜ5KQkUI͈IgoJ ͒w ӛ,#6Jʏ$\}¬mvsxhϰZ-&9l-"`-1:BsY{8rV%CFI.:Y()5ɫN6HF!nkB|a? ä{XSBnG{;Ӂ~#wɰx+,cIH|Z%CJ͒o /_<{yOdDIҙ=sgT0`'AlrV%5#NtUI͈[crV%5!;X Q~.݀2Y WG.jg9Wt{QE1|iA٦ v˒=Xfӎ7n?຀@ <3Ix]$K?DI$q9 W%2A8K'֗1/EBeĢtav{TG8iBTE7ѭH!O7HBpv`Ґ) d(R!# ҡ*Bx"5hՎ4]ȍ g#U-REg-x.|Ko_mn88n`8R Ps{m>e:OAb[Q`EW@PtmE쪪Nܩ*|vc+[!I0(J+ܜ"Ti(SQ`F %W `4#s!ψ 2U+)PؚpDڱzݠa5:OZٮl'2U `bd{aDZ(EV-cW Pŧwhݚ ҧ7&߳j>4ԁ]#LqqhVk Ղ@säVmsJkhOYOEͭ5QQ*QC@] ʠq!s`9^3/4T@@RR-YY䧍" ,i]r MJuшNhQQv[4](gcDl>" (ӜG\ ]Wf\n%dV[` _b+C eRa C/?bW5Carla-2.1/resources/16x16/zoom-in.svgz000066400000000000000000000276621364475620200175260ustar00rootroot00000000000000}i6w mϗq}c"6}ɡnJڿ~3AIUWWi<- D"__>'f{ ɛYrܮ67?~̛Y-7ɇ777wGKd59|rqp}{q˗xNjgQw߽l6~oo7dobL/oWWwnq.(ś2nw:X-/:9/hLˢG@7[߼ɫ[8/U .FzsXGWanW!5z{ l{v / nLf$S0"9ZR,b//`3dӡY}xイ#x9Kflg"J iKͭK7lCۅۻo!Iyt{qiyvw֛$:w[_l~Ln0޻Z\^%a WWTSuc-,%_WzR/.h $/j[%,?QVxk_`X-W?W+nl_wow>l ^xof{3랽po6EyP:q,՗f0r0` 0z#}3Qv P?n-dcVH>{jkzqmLbTZ9OhaLi5g"K/FO?a<6үP*DL"uԵ1W+Bbcǁ.>4]4dd&D *fJmmc}/@H죂FsFpQ B4}\EKЖJ'NL4RNM@3110O&1/~E`5|pi'c>;`[2]% XV!M"&%~SǡZ8ӨT\<ۜJ" 36E4+4zbpñDb;(g! m:?4a&Q6 E:1Ž41|Fu Q|GŔK.gLư|kg(P&W)`Ul [z˻nTbfJ_o?GJ];7agO)[We\\ 6&XZˎ8t}Num,a&upF![GdylZTdQ#/ԱKѹvp$ 3)ǔZ@ EdhXF H3|2sccy aԆ[  q1.fkeer9.Lp# ʌtdN&-g JP'H(%yhM6௄a,a'H&߅B2q,& S'q!?}^o$ciQ{TYd \xr-gǏ80L  C|GAK`ѹ(Tb>+2`J"x:Tp{OT3j(jX,il-P<<^뮃u"hz<8cqG9aK(v )i"ERH?}3׆Յ<& O@ ϮQ~'?W}S&뤉.*.lFn}υd~pY7ƨڹw9cw ͌bD|/4FDGN sRNZqS Ue- L),PyZ%78Q*R%blu 5A&1 yݦ BMQQv>a M}HJ;um}N?-/ՃZaJۍې |L.!x^ ɖMcZgd3&dH%$ ~`vur\{;qU1]j*J1t q*`S1W|6083Y}rhkhzTY=)gc؟SP:ԥu@z z^^06Wx9khN8+QeBXO!Ыt66ž9je+sީF*3 rFV!1J 2Yd,J%;#(: 2 >R#~ p8 6)܍`%7F +hD iP<*<;~FʧOc MkkjEXEi&[v_ͳP pU'~9ϘuXfOHQy* 4TmJ@ؓ! |d' ‹)NrNr-O5^S02hBd1S`kS CN@29JcW[nJh)l(+H@(-rJШ_zenVzGx F!V;<;:={0jApZ!`Ȧb!฿GRt+5XΟEIiʌP,$ӱ?=e +_ի^N#/ci: tՙns1g~b`'A4F'վ2Xwr=`Z0:(5qE4ntN|5`r&MeS\7qUS.y.d!&;A Vw5ejDHDjb#C)nŒfxJe2X #0B 傩EDRe bSYl.!ۥ=v0Ԝ8Lgϵ"=X(X0!^sgG* wРó"gd:BAq)!\Җ T+tGalˁt{  4 -L fނy*vܲ;jw2;r&| pr{Ԁ4!NQ?PJM m~ްiMnÓT'nm٢XX3pRb7=#HٴVr*ŰNV;)ܵ\h{ztnFT"QhcϴXS ZU)uVyJ$@^RD$B " OFj`@ah\)Hk;qte;if;C 0!0HzE2𮜟N$`٩1'ϩ g>d!eDBз,'ėq7hEJ__6t #1 `D 1WCBc`eb5f6p/3Dr ̚1УN:W/ ?C4_ց8+eS-T47օeM2XUNhM :b wIp{M;##T5qPՄڱgL$;A0^J@x>^ ߨ¬(J ][T Z2_ nE?> U?ܩCڌwe)OW) e@]!>gmk2ͨa5*`5 ړ d/Df;|DƁk>"Fݴq$#) %2bNr$^'g:!w 43BkOGH|޺O8 U+AYzE7, #'5OTZ銴z=寥@~Nv헷7Umп!Nr ww֧~'Bb?W ˾yn,.?Em9ٮVǬCșe"q{x(r d'uBfII5JǐǪ*gˮJ lMNB ܬθLEmn y{w ,?ϼ9tg1sVLHy~Hs\%)&'~:Fw:'M5RE@D,gfzsT}sAP늭v͔;`^fzU֣'#-3.>R?K>"rp0Rmz,^<ǣG6zZn cg;Z)rR7f@³ G2:"PEkxsb.2CnΚ9R:>5'r&b".6K͋X>dcL{m3dGN0yImDP׃Cy9=# ʷ'9eoYsmdPJcsRY<ϟ,y|j>ZwL#?ers&GÌmONMYʌ6 p<5urԒ55gM< >l$QGO< 0Up )9*Gz$N}Fuk`淈҇|y0*:ATDe5rI LpT f,w$rB M$Yn=r0r440ʻgh*  2[b`y-'N}xL[hVH|32 ^jDC_.oݹ8!a&a's5#jAL#< !MdyXA0s+$li/,[N?g8)jUӣQ0 t9'K=0ɩd}A3kB =onXDzJM 2f#9'VDv&#~ Bp.pjLE_SE/6}%m;())^F-it?:L<ȣ%4utrvѧHC/:}tO{a;)N%5ak"&K't`uL&=<%t'P:D[N)akR鉒Jq'L+}֥zM,)G _KO\::SziJ5$ O\g]o=t4}hzTdgjxdݩ` ‘ŌcJAǻ8TY|kxWƥڝ qEg7v閟AeOޠL1n"PMStw7Rt[iaj'5U0v0)aLc:v[Kf)v m4\[Q?cQpmn(m 8f+0xdJw@aO ?a;ȃ^4LQlĬM./hØ1԰8\ Ra HBœBS@̝##od2wy,ieD=~AI>B[9*%z{̅%-Y/f*lş̂pp'k $Y^x:n o^?ۼ S c w$! ^ß!X'3o?߱ީEKY.rL ?\gü&N ?'F7RNH $"`#*$"4cĤ}-8zt \ʫy_(@ P6PLz *g_F/|⬄zgY!#`z@ϚH+EA'/ܩ4cn@ĎqXusiϴ L1W&O%X"[0ErTݰ2H`7r^g|J{0X\'ϛw94.nw vJvGAReg%¤Z͟j?k45T t4Fڻ.JPVvyw kݥK}{_{n W L{#4u45&13J_R..{uO/x!:RY{V8L뀫5R4? gBcrϢ}eˆМZX/MUNR%}r^%I!bSBl邰YFV_/7כ?Uaf\ggrJ ǽrү6{P,s* ,pU)9dq$HۛY#)SW~aQc ~ZO?lrow4VX\nSsꭖo.?la\W@ѴLn%]Ghw.y\] ;ą*~="ƑfcF溥CnQ(~Q1Z JV@g~1,pQ8hm ]ӹh+__jJ@tg1һ)SC` |!/~ٽDQ~yégNg}5X!T f(\= 3Th8\UT̊kFx`nlv:CeqtřD޲blC{aZh_B⹻v#L>ӯ15ep8kܙ co)$Z s{;} ~gZ w5)n>\`aܬ0 TZJ-*PegFF6@:IӸqVr Sn/b*U:uB!bW/ra0kqM0$Gra4 cQ:y)yXׯ|8]S:qX]N%wN|{NjiQIq1"M#؊ $#*p {h BD6eHqF!_8孿O wԽ 8*BRv~0TA=: gELQ\=૬Y ݼ2d,^{ epZJ0QcNz8/Ṿ>?f%0 e 4ҊF)J9ZZS4G`n҇/=/c`*x [H2MRofF}bD`OԘ @:#436=9f 1h8+b (m@+H^XƝ,جE׾%D1^;̮q\1.=4%1úc W"cT \e K+Ze<-l ,B)t tDf'dD/2:W18kF8Բ2MQ DaE߂[ rB7퐋Ÿ$̘(7,|AٱZZk8P˽l]Vj0p&QѹTbhzZ,28PjPU~݀t !yiYjXܜ6mp 6 pFCOñ&ZkUsT^h>8ާM6'# 6M˔v/bS#o)hQTFIŔ"g<>*keo#nkBMZ]P3%d ) zE?Fk,}4ڋ~.j u׾ AӸ^>߸[1Hϊs1^R^ ][!)DwvGp"<>8lhŘzU굶*}y9}jc*_u. F>lSN7bj'nɟ?o>xp$~wOL&fvMVguϷ7Wwnv(՛* s }!Wٮ5r0;,-/Xwy/x~ˈċkj~KK$<_WG"fϏC{xIG6?sV͚_ jE\Җ[l8on7jC_nwߓCI[yytwqiyvwuuq{\ݮ60&ZѮz\懕+WTSuuC-,%_/rRx/.h$ݯb%,QVj_0c,vO /m3V/ooo>\ ^o&W{3˖po6UyP:Nlye)_O0B_C`H`tt]tOxր[ {:'"ͿYf=Pțonf$VH+~%")LĜc7džRbt^JQآ.6@{E](U"6VX[lw8zHhMC@SMF`B0ꀩb$цN#*$H5&o4pX-K`0uiamGoY>nqŒ%}ǀQs%6 K>*h$4ֶ6d(jB?.ҘXdDžLW?vReNA#t9&hΈh#2&Ʉ#ůY,' |2gLJZ˰@NHĆa Gqv4*0(BJkKC$5U` ir5\aڲHVsZpd$I+Fn:&x6]lRU ߆>q$m_{-]DJh ܀ZP!-ct8dAH`3aO!9{0 pT졔+Зx8 ךʭ/e@K[W)9jMD=2^ϖryÌЪ/R*ïer}ڿ@hXz9Wm) Ӧ5P@3u4qZ[k@v=C~րCs_z 0 Ux:WO뻝7>O+7,Do4}2rлip*éƁCdTs@)c\PSNX:r;%GEXBozdCpG64- 6a;2bR?N4DP"G5WF2hOîb??SGŵ9`倡 N XUExjF @Y8}8Ӈ8m&r8y n]'us4i׋_ӱ fhԢ S|(R$t.˳z`Sk t 9wh АDI_$ƃzԑDNv?a*v^c7o,agv뵗nS>.=HvxӆL(eSbQLE,N"kXk%D2fP_r$/ŔWL"*b pXę Aa"C-,'J)v4W6F"ǀŒMcEQM 6dj&p,7IdbF6yC§d"Fp؁jIM#CNlL#M 5PCoQ1 1l`8`cJ,+ U X['_OC |_ U}>t~4;풓-slm4~cqmM{9ngBd n}*Xy5y*xX8Z6F9snӵtpkc 6'49iҸ58OAMI65=2<#:vz):51N܉zdf>"V~R Rț!H +ˆX= Ir/A&"bjl 4$p}!S$:F…L> @P #;Х 4"!V>zݱ~̗gdh}Ǚn qd9(P#0J|DAHj"M(/$#  b9u" "덐d,B677*lkoR.exqxyP-S=p0D3 "\EYY)Tϫ.CUA `>@u::򮆕r)[n ae2X c+~= 8vƶdbʉ\&ꓟ6]' tWIuf6t{sm.$UK}#Kfjઝ{3vJ F@c$cŨb CHh90_FTR-MRߟXA'NjCva\P~ (o>)I LQk&f|RjM[lO[`AD" nFaz~zsheOL⒔=u!0smeZ)eb*ض6oM<]`k&-TY}J_<ߔy/nI2y;Q@%8K`hRP6h[}Xm`-]EqZybn\vCAL+zErzݬgbNp\7gݦɄ1( 0pz^G3q BvZBs|І 4=x`Ɯ l~-1Z|kp'(i40'W: [U21 'R%`RD-yj`BM;It4C9u|)dBPS@ @AXe4|SUR?>lRa]r[=zd }`Vjv=Ei6$Hm,ӦI׾<ÿV ɖMX_XgL1h?k'&:#F\T#w|Ui@4b2Tb(cЯx40>954l W钳1)MO(]bRBs@z z^^06Ux9khN8O˄6xBICӝ;r0DZ0s*YT5S@02 P`Hu̔N"c 'Pb(Ay/:'h(ԬgxM5[.=yދtT`S+Ppu$Y+۰,\!`9ڔ KXKSJ)v-una]^/%LUwuf&q`I&9llt0 l+006N5u((]spGHyncT- % դbH-Y9ICbR z'*)SAa4 !0U)! FEıh-7%E6pB T9 %h/yy9CR]v:)9::={0Apj!`ĸ5BqLi=`:.ճ&rt*3]kTu^N`n l Gj"ySkvkY{Zt:0 pF I`9h-ZFi9 jCt'11S[MǓ+$ OJy5֝3TZӎJ - @ji|׳HR;k%ne/Ǹ;z[,0:J"sYNMb!(=[`:t勺ȋA[1OsgN~kV%:3tM˻aZ:ы$H..d<70.^*8 _<`sJ͑@EAf[Ay:Lda_^^33^%ǔJKj,z)9z. ~X#Y<} WCu?&?(BOAcN=4]Oa֮ڳ?F`KNbG,l3Qy֜m5伺H ՐkhTPU]/ɒD;OWE=)pPR>u@GQӯ 0J@g}LI* =O;d=׳[x]| 1V%bBŪOiN}׋y̔2b+`v0N.巃!dāug\+҂Zጥ C5~v~dM[' :<+xFVn9c-yn˩Qͥ(m9@L( `PGzi{5qi6;pcA靟e?ӠsQ>Y^3 _9jgZE yYVXvJ5܁ù0r\pN !qfDT/͉5X >l$QGO< 0UpLx?F::1FBHՅYߢڼo\9q0-ba})(_xS9ATDe5rI LpR f,7$r@ M$Y=r0r50ʻgh* u2[b`y-'}<&-i4+m]gPR/{{5xce_/7S\s0a瓀9uyyNq0Wa9jC*L\eJz<(6[ K?NJ*cj.OfY,ǟ]mbxrə5g _NfOtF5yI[, )  ?kdof5S:gm{;4}M^zI7]zEtɛ1w&p?s=B?m*䩂IUP4L0ɗt`*>dQcʢ:G ҹqO\`ù8jtL$!s_ mVpcx5I]a>q|ӆVQ#&{5[& aJY}.N\wxT803I\71R?G|M?ۇ6 D<\p{8t(gtO@wܓ%^Tk26ɠ tu5!t7t7@ Ppcx"=&vqd5H1>顛5" T?!ŏkQ8'د/FxInKsI`פѣ%ng\;yU bуj.H}4GfܿSR)nTRsJq<&5t[:9ҁ֥{0tt@BPo9IJ*0KX:)G _K\:)w`zTUQ[O2] tF&3"ts*,@pA1'"R~݇bP5OxRvN䆵"ȁL~ݮ<;hl9V JZ_o0!w4Ewcz,Ew\vV&Y|RCc7 IJ4HݮFi[@>[#Sc.o {Z-ۡE`b%f'1a4̾a cjRbCoDsm&,H60#ePb s M. j1wz辑ˈި24l}JVaRmZ&%zmee1`:ԣ_Tw2! %Lgyp*/y lWO!/|-H\^4w{M ab}QUD} cXKSË6\΀yM\O%Wo FApID %lGTHE4cĤ}-8zt \OPB1j9x@z&*s~Z΢s ni Uu(@+Q;ѝ` ܧUep`JZG#]c33\dq9r?{ }y/gjsi \Zaal| *-a HAcN(J[P#M;S#FnܸUk-9 P!ڻك{`1*k[SѫKlEGX/ Z!)B 6 QuMq$Șhn&h~ԾNTt;/?7;2-_ǒwt>bהxN>}_:.Q;'g=H#4e$8UÊhȦlE #Zl0 "DY?R\QNy>udPԃ%& ̧.fDN(YS:31W*k`r+Ӣ6/ 5˨cyE|m1+eF"`Z1~  #<e 4ҊF)J9ZZS4G` nҗ/=.c`*x [H2M?PfF}bD`O1MA!tFhTglzsbpV@z9Q^m @+H;Y3Y"}7(Kb).-*D|b\9, z0iKbx[uC%Ǣ~~W"kT \e MG+Ze4-l ,B)4 tDf'dD/2:U18kJ8Բ2MQ DaE_[ rB7퐋Ÿ$̘(oYRciem,BJC-ʊֳp^I(6'+ uxUoqYE悩0Ao<짨vҩp4+?dIZˠC$V0RO?>D-ST P}Kp%tMI3$y%mlU'L$5tI9g^GFYyMdIb3%KW.V\v"KLɪnZ~5&Lkp#iMPϩĞ_Qcu:5 u\,oNf ;s;\&Wv|HI~|ϱb-0}٪k;w 59y#~ԥA2@ͪ(:>|:w ח懻)?p%i6i2Wv"7t*@+ 0[ZQ QZJ^d-r1AfFCYU@#:#GG0o(oJNyx6IRƐ*ʊֳxTZj')9bw ft:P)Ab"ȫYAa]1J)ՖGbՕHl(?J~f$j4k{RNvR5U{%I-HG|U ؗ$]. QИH-#mWg`"^A= =q2&fl#Ј(>ɪiem,d^Yz:ҋ; ZO wj[l2Jm Ozb]%^"p zd"srD>/̿IWJZ5qU(kzRn^rɌ:?#3 MEz8~_ EUk#P# TqpVԻf b(8ʦRTk1tdDqdjj]P--aa9-&@"S ^QY0L*%>+&nFӲ)=߄1@bcxޕz$I+٫uzxj ţWQ1g.@[N|-FcoX;]=G~Bf?yII]Mly'NuQ%ÇX%Çm<) LU{A> "Hmz#m!uKX!Tp²V 3z^D1)LJA1+a[)Rx&ք=N<O0qlhcZ}\[Ac2!EY8}ÀVQ%05 A6uS1\j19N /MlH,G7`p 0=fr1iSmԌ=4$#bpٮA>j]sNh$OWaH{hg*P`< #݆_Ek5[hvрJG=~6.ߒCarla-2.1/resources/16x16/zoom-out.svgz000066400000000000000000000274521364475620200177240ustar00rootroot00000000000000}iƱw K>fFza[OGX6|ľ`Wf/ɞC~3 P ',|>%fw7v[mnx7qqZlwonwo(e,jys8o.x&+wgQw߽?|n6Adob՟߶q8WMjxwߺV˫d$_}YT_7f⛷?xu^gJZ{EcԈ_o/QU[UFgE~~ò /5ķ?H:fNV귴pX&S{fuXČ1\<7 GbҪY#ab:[RBRsGÛuwǻɗcr3/w1ZoIMruywey}zF%]|&Wq nU_*zw{֒ï?d}Z)4}Omj%,?QVxpݝ_0g,n 0yv׷ݛz}HWpހU̺go4ܛ{{Uv;Npal%~^|=i#g  F c7Лm{q-C-B揯n@tH߇V_onIJ 6')~5")LĜco + SE]umPDlqt܇f aSLI GTHjiSM 4_~xY8լ+hiL^]10M(kp\q+qH%<,Uܔʘs%(aP\X^> $WQA#%@cmh#(Abf>.d"%@FhKz\ o'eQ )`KFk˘'"f  @f哱N0-i.Ò,& w@߿o?jP-iT*aP,C5 6֖ H@k87?-\aڲH6sZpd&I/Fn:&mxX|X^Q3}Iƒ0-CDJh܀ZP!-ct:dAH`3cO!9{0 pT졔+Зx8 ךƭe@K[W)9jMD;2~X庲Ìտ )޿dڿ@hXzTն@i]({]O̴S:f:l5Bn@~րC @0TuYy{ gSiㆅ譔Fb+S/&W "=j8HF-q!H> z |b11 j + C\nרh}KZAR^MOlQȆ籡?h/#&DSM98+"x[yl$Cx#v :"d)=E u0Z5QB 1c;!kt'qrrפRg9/܍6zYNcNB;z+b:6\QZ)(%_D#<˺Vowjy-!sx55-@هd$J'q^w4Уt$:pr Ӏ-}`ʸ16xc9=V>;|@mo?V~{:ߒě6 fF)d-gd.b$'tX[-\łX+,1"x#&+&|)"fQ[;"$W3Qj`9\|L3 x90!E<fl/+Z7h:Vi S3cvQF"3B t>'370hT3 L l 0tfc*ibz)\Θa;;װfQb\!( LR=1(^w=,}%T-38AO>ln%O~KgO7woc-o:b/S"j !S2|:) -l^MV3εqt-X„- M:>]1BC $H~tȥ^ {0=w&Y΀HiՆ<Ԃ<f4@, $5D+>DNJ0fV`,ȵ@C +6*$/@t@_p/6_ (+5HFHDtl80/AhUf̦p_$uu2o8]P:ABq(YCkr(% c @O>A $5.c1I: Åz#$K "nk9<8~ꓟ6]'MtWIuf6t{s}.$ ΀˪Hn7Fupνso`hfd%#{y1bTxbh ׶Z̗$f"<DKnRk-Ak}lh`x Ծs-{OJpSԛĦ 'ԾZӟmX@Qxfi'^gz9;vӡ$e@]gx 3]QeS&bmmvoܼ]?AͧvÛrUW $3E4*yWMZʆ-(Ց*;m7 WԬWlt`;̊~!$x #}pqVmZL"'s^"i"aNI+t ķleb)*O'R%`RD-bn30&ȝ$:E:>T@) u NP W6Xiι}兾z0P+Ai5]z4t6i%PS5/Ӌ6p8i cWkuƄ? Fb3D Ei;2إ].Fhp`\-W\~ DʿR ]qJl` _ cl8. Fx+prtf$1u)e9{#xb)-'^6Jb3S;*9ݩh w_ßs…QgH̅ҴCcvzK(,d@.ʪN$h(ԬgxM5[.L^w"vqLHi*09+Pp u$Y۰,\/%)?)Cs) ѹ(eQԹuyM0U%>ޑ=R:.ǁ&'ఱOKwx9W`[)qCAIﺘkF;B1cTfQj$ϒ2Ӻbf2吻lRD(Paw$ VXG}'so"_HqY9)zLXAu5Ѻ`mV(u| 둰yJj/_S.Li)<1*V_jҿN {6$rzड@x1I)QQw剰kFfRM,f awaHf2QQ)q, jMp- e)eENbB 5Q ֭CJo!>(5j١GgOpF 6^#N5 T[#HʔNz s޾h5)͗?STʘغ-ҽrsucdDž?H8U!6ϻ_͏x,Xbֹ y@fJ5ks r6Dx8Et< B/ $LW`enҚ~WZ'٭h9moL5 R]kZiD>KZ^qO3v:X`tVD粜BPZ[`:t勺zsib=MV9^rd3 kV%:3tM˻NaZ:ы[jqaϙa+MD3Lec/Bf}9rjsbQP Td ndM6׷c҃b&y@V?R%Heۻ?uӗuS+TcRSeQV>)XG̩ayI#U{Lu _)Sl_!mt<*Ϛ]Wgi:yM ʣjPSy}I*Kֳ<>9p6g tF:ӭCIT6GO[6+2%it+x7.V }/wX.u[LQP F&ÍΩlS$l&j%Wօ,dgT<3]6}M:岚u4B"k#kʻwde&z mH)䀐B`j1T9gi[A~viϿ 5'#;sH j3vx6 m\JC7:04Hٸ儎P~~rJ`H>ys-bF5@2]1Q:x2r bx5w9(^G HB jxcBddD^bf]h5:,'΃ZG, _#涺\5 MȃmcT<ԫRSnB7l_I3BT lQOE,,Lu~1gt$ρlZ+BgmbX'扔qwZ.=? cAqo#JijgZU)J*֔`V"x5nZ8 pőPZw1c'9Mۓ }ݐ;!5j{ѧ#$Poݧv[rWLM`QÕ, CWњITZ銴f-篥@}JOöw?oKOP?SU[Vk?ǓrzcmgKD~M>%u@9̷@$REn@D`@B3 "FTY wu0^iiC]h [Hѭ!`.bbw?,/zJ //CIvy$_?H.\$}iT*虈ePrT8Lo/c.jv]ծr l|@jzd̴Kr~R2G=,a[^&˱5<ǑV:~َk|&X8d<y<&ꅲ{K=k?dݝ8ǠOiP9+ZʀTY",QH,%T᜙ 9b}.r '{fDԠ͉uɵXEec(9I{(OL&\ydD:6qʑ 3Ey$Q]9q0-ba}.(_x̪ʩN$QY }M\ ܻ:DB~I[L x$ZFC{~L''/q^K S46.3ߌLy|2h˛g~w.yHuI5:x͈Z<ӈ@`I'L1_Ɨ9mkIudc"T{2sOԄ!\$Rp߷>-^=LL?M#>z&vɟCL" `.m?ʜO3L]iA vv*5td6B:~ϛwt V(Āk3<aC;~ hH=0>须-" ȭarC5ܩuDcDTa틍D_xI2JsN`פKϸ7k@qM\]"y9ЋN^qNuJkSI*yXH }];I/I' $SJ{Tz~ J_t^KGJ-QS$.^ڻRzM0=I3W)E[O2]?#tF&n3"tw*,@ǂpA1'"Rn?NC1UV('Fhq)v}rz\Y']ퟷtϠufqnQbyy();ӛd)ꭋRt05Rtw哚*EwYLOUR1Fb%6Xȭ(ڟ(8Upӌ6n5J*w_B[9*%z{̅%-E/f*lş̂pp'k $Y^x:n o^?ۼ S c w$! ^ß!X'3oߩ޹EKY.rL ?\gü& ?'F7RNH $"`#*$"4cĤ}-8zt \ʫy_(@ P6PLz *^g_F?0X?KY ϲNCG >,5VTN^Sif|0&#Sl#)c ! 6_h1b:ޯLJD a苄唩ֻae y%ZoM+QLej[aIV6rh|X3[\' 7ك*ٟ9IUzhz: zh5Ng&Z8>++I2,~uBvX>]/{]|M`OѬ8ט+9|}N:>gG{\Ћ7Bt2i@J:R7+4 =>|} ?߹ @ Ts*U'6L a:fK.>,0Y|l~OVgYnÛqSwڗɗXVBX(kү.{P,s* .pU)9dq$H׬ډ)+I(ȩ zrMy_㧟s{|w +,>Ssꭖo.?nn`\_n@Ѵ=L~%ol7߰OLɏiW4N|7W'0_xuJǐ 5+F$bj,;\`Yܮ0 TZJ-*vOegFF6@:IӸq+Vr SnW{`1*k[sWΗB9^8BR&d\)0 I-6XMuER |~zݔ ȼxsvWwvKQ}pŮ)mB\qX]N%wN|;NjiQIq1"I#؊ #*p {h ²6eqF!_8OO ԭ 8*BRu~RXA<2 gELQ\=૬YLݼ2d,^{O e0ZJ0Qc.z8/Ṿ>g%0 e 4ҊF)J9ZZS4G`n҇/=/c`*8 [H2MR/fF}bD`OԘNX @:#4CAB ̊H/'+;}AjJ+iq'K{6kQe Q9פEW˴A%H o.bqTtooHx{+W;EsEYm2s 9Kмoz05t"Z0I{Ṳ!ʴ/lLS'xQ@ *tT߷CгM;b1"- 3(M1 _Pjv?V"$?1rh='ᕄbS<ꯤh.?)^l+|<~id b$È𰟢nւ:JE ,0 'giUrV/pZ3XJA,d)F)4n)9Wz= ~1 JC7 KDiYzVXPoBI C1?ܚ<43OL1gn!=9Kb96Ĉ筚q+@ر#NELeI v ho{>Lu(&wIYς(C5ZDPW'8A!hʠzbl7% U)ks hih44>=/hkB{尪YL0 1gJuC}dөa}'x9 m=дLm2Y/&8vvD9nTLi!b}ӛBa^6f;V9L+Դ 5SBΫgPcĺVqGHy+ащ4kUY:;ޣۏAL+Carla-2.1/resources/256x256/000077500000000000000000000000001364475620200153625ustar00rootroot00000000000000Carla-2.1/resources/256x256/carla-control.png000066400000000000000000001001131364475620200206240ustar00rootroot00000000000000PNG  IHDR\rf pHYs B(xIDATxyG}'s-KF-`66 C LM2!0Lgy$7!?& 8`0,Ke[.,]}:Y=W>n*FDXNcR׿O/ Z0hh]tn@g} hZ 3uO}D]/+p@ ೅ڵ&>#EJb{nsTqE2Mg.=(3>-<ϣ6q\y -RQp'.!Hۿv`7@7 wR\yԧ<(Bca1T*J1Pw)3?4襔J[GQdL%\rUҤ !aIch\m X4t ~caGFFQg@/4=Bs vjB uЍЩЧ>uBHJi~@1ƔRq%ԗ1EBD!"d^WBe}_^2@7w~€_K}}!RSJq!Hp !PJ h ! t։s1}ܧ>uJ ɯr yas)119("!D$4 29i^3@'w0 (PDQ$JRhJ)9RNs #D$ S@/<-S(\-@)E};c=Rf + !<"2L@B 1ňb169+;%*XvT79hh c B$:Kc鈔:O^͵d>6U J5)RR*q1ݾ1it}\cܦyYN^9TA^^׼of[sE(fT3JiԴTXRj"!\Q(uZ 1ι`0 CxE}AØCрnݑXiroAxRJ{EQ !|>cdՠ}[;40R j9םL@ c[ i$b]m].0z&-4o7+ ]J˶uSv/JULU3qx$PJIF#@^ Xcce02P/'Kvq@k*9 7=/|q碄g@{N )(bŔ%:fs\);ݵEp]Ov|8@u8ͯc8`T0Ŵ+L3q0)ӦfxqtbϽ>6u領 5(ǣeX@Jud5 Y|)ņ89 tiY'jR!ј Q!#Nsv`Eb-J~$$yFFFhnn0$Nt*wV< C>44AJ%/(EQ_4ǵ%|,0s&fLX3UWʫVahxͮ? 'G@V@KY$)Un>9ұno0H݁?rY[%Y6Z?[ (*/y' 23 '~ B1L׃5A5u"yW':DT2tTvf0/k0|0, !,?`gXS9c+a3HDɲ!QfYn~?KeM} *ϹbC#)`7܉{9 \3b_0a=Hs |'DQ$R*".$)h4;~L 30υn2]vh؅;2^Luf =WJcD =7ẛǹ?nX7^3|DS&!)T-: Suq>5)9dk%ȸp(Y,'1r?rL@ò9N1V&('{uv۴!20@S׏;34dJK8!)e_5'l9M& Ԓ?mM!VHk@{!5|ngt@sUld3ЩJaKɟ1$dr.nIz,) jͮƠkvgk[X3 <=O%c Jʞj 1"3P4&eJ @Έ@L0mϬz^ND}ߌ(s,1nƖިH]7sYFhˀQ pH 5⴦$#yXY7f$ 3M ٱs} 0(yߔJfv t8ҩ9N,#Osl;ɟs_1  ~y%:\d$7iG bc#?xt-@xu3R-@OŶc 8/"ӜŬ'ӯ>Ō[曍7cHlph|67?7:Y44 4›o,_UǠҌ(M:j.T5J{ L>T|5=0  lLʹ7}R6vVIMhk?fbbu̞Tdةae} =_O-( kA\қM족f08K L;ވ1p"8k VN8_ue~gpd$sy4 ЁyffL}SnkSdbIƒu.<);} ݞ)1}Dq Scv~8JqwqMøpb3ß1=33JI)}&Sr6I?vx%/ʘF14VfFmˇӐxq &3 jOܺ;rOM9SW.?2g?d^8B%Hn d4Wj 8t|/̜e m\r⮳1s} ^@K)VJokJ$zKP03|_)aa_eb*MUYxӰHmgΪu8`V1`<ẳ֝)Țl/8NZ,Y>j&kU1k-'Ĕ}xĎddyi.m%޻mcDt/x pb,0&JKRvI sѩaC}Rx(U>n>If=J)666:sv2wnmnI|67bW,k̶*c46a4g:uT”oz>婝 t#Ys2>&l9MHo b>:KfC Ъ ~ۉbOpQ ze ~mpČp7+. GsӄKtDl\JJJt\4q "o]ݢM̚> (&tzB(e]lHH3Q &s*X~e%/-\.] =|4q+VuU׾5[f8B ]qҎ "eqWޙFӱ` G 9o uݗ]E!Ѿvs5ph?T^<!8"gJQi 14ǔk~B 2N@.W#RaJņ{`K 0;;kG\gFAc9_c&œz`6Z36"ԪC$}šfAl=,&(dG Rb(~NKJp1ؐB&LhHgggϝl"+J581 ڍ\ T*YܺX}O}ߞL4ju9VR] O!꛸:> 2#f|Sq6&͚3Gu׌+z. ہ<9>&`ʕ+6CKca5jC$HLwu{}Ӓ{K~gΘ^8c[Qsf|+Q47o\m`hhn"d $k /)e7c xqKcoHB`63k8*}ZFK0uDfJ}9N Hw1 <`邜cGl4@ɭ Sr90 ,>-7r`$ub|9sbg@JÍ%uw05g zͬ)}Z^ <^i /7nq=e&@S̓K.N]`(q(UQ1܇'MCLp3h\[ >ONy)X^ @٩_ Ww*: <tJ~z{u C,W \M/ow^lnnR+8Y"1@%Ľ #X!kqݥ7d[YMw3\<4 ٳ'~mazzRWkSO= .ɩ5P `=v꘺A,@4s1i0\P(nȴq.š9\ *1j.uI)155u*J(˙z_uMlpC2(g3 T?+/1yZ rA'ȌRb;%4l;>-72jXԌt[ft '##Ե@! Ӏ5'BQ[[/ҧeHSxy?6س⮾jvw]%gF ~$`dbz p;Z*(Vo6BsAKx}W"y\|Aifgg{V\^\;2خl~:ݛפRGpI?)#س t4 EF 嘛Cv\'[!ڨY,Hզ(0o.tV@IHҧ>- rv*k3R#Z2 vヌَO}Z.}O惿蹽3HR+5>-']wX(Fp_mS:gAEtdNXjJw Cgrۧ>-'ZA@E@w:ltQ . t?#3.#b6R\F\FTBTA 3ԧܹ]?{tN%oҶ`wMqnX2s1>>+Wbʕ}]s-qLDٳgq9T._j3gAO ֥`cB}ؙcؕR:ncXv-6mڄR:xQR@zJ);pice1~=f֭*n:\uU8v}mE wKCO? &@"l19R 927p߼y36m |>z}~9z+Ư h΢v,Å|O<0 W_3798-[`bb\Xb7cXn>}ST׬Yx/yKb LOOw~8˖-W_a˖-Xv-Ξ='N,I'Ip">/?Ԣv~M ؒuQV,!iq9v؁ 0029-O=9 [[57>0 3(j8{7N}sXq(؁7܀1O@)={{DZsNs=ַ|;1=='xqw-oy OK4tVZ cɟT4U޲E0RRـzE۷[9zW FMxoD!cvFn¦ƙ} ~.]wW*x_G}=mʕ+W'O}/N:xoomo{|'* ~g~Ke˖+^ ]#}6m®]ZelذQzZ5 ʹ"Y(?ڀ3֭[ زw/!ȇ?ʕjp0;;kA^fff0;;jukU۱gݻի{|KH4I)qq@_~10ܾq#G/:@',6 k zX;o}ӋZ#Zn* 8kz wUWh`rrҪ.p%31p 7 CQP1x4oYj]@igy~'~xh3}*8s!Ҟso"SL3X"81l9oGKJ3 g6_)E?5DG> pw!"WVj&Po~~>q^077gkz!P۱(_c4PVm۶ vi!T'8't~3tˁe6yVOD;vW\ p~moz*!TUu zFZ`䮆`~&o^oG6ñzuOF/ꫯN8\zӛބJܓ&G3<cccӢOm(pڗD;( ckyk^0 .p^36 _Ab10"pαvEG?QLMM}{nĵ{??Mߞp x*bݺu{++VcS jc7~}] bu@$RRy`axX%t FE3S~v~' y 7زe NS>ۿ[<8q֯_[b~~zM,J.+'`v 2MsO-rl'k5 RR"" |؀٤+, =σ>~za0MX:x ~~ wv؁k6/_2Ox_ok׮E^>9| }GOկ~5n݊駟g>|_^<8>2ԓFFF}/KF@``wF0Hv0!~DZecRH)3L9k{'k߫T{mU>|mi|_Ɨ˟g?ٞ%8^ї.IٹZl=l u{ѴF|R*lT3 '''-#hw/R @;D X&OW"Qqj _D~:p~e]Y(-Ӓۊ1(-9a:tWq͏sa;!(/cB5!B"spKtן"]ħۃy nMYӁ*)od-?F <-ygX@y\3N>ιkEiFu<cb3_XͷR뮻/7tY9.Y!'GA }Scτs8`J%oKNz6v5iɷCОCiןm7<|GX Wc sssK,~y은 ? nV;' k) C_j9sss%+ * 000JA{jCz5c_J!,^JBɏ4SY=r& ԑֻ'm7!{gς1ya.r.144` zΜP߲J鮛 MJ)3< A@)ZDŨËEb;!Z07k ~mJ tΜ9۷#T0y3C}->kvn@cTI7~R ۇG}jן:1pל?ssØ{K3>N:8Zt~C=,j<8ґFTU;v 1fVF ~+xGp! Ybll̹fӧx1y$0qx[j]#ee/C@,o&qey`# qDcnD^D9 ]`IgK x|߶˙Zw |g011Q+q?3C`#|իOСC뮻022BࡇEA1xJa5A!ַU`Eؼy3+W;N\}չR^c۶mؽ{9OOhRJlݺ/<σ7o3eÇO={fNDZ>O__]w݅w@ JQAj 6d VrZi|Cqw~7T*/n3 oRς?aRM ZHFHHj usZCjؽ{7!{kqcaa ߂nS7ވ'|?80Csss8wj*<>=]Gb00٠g}6wi&+>~8p@w=??v1vtn'| ]:D|ROrP;F XH4j?ug+0] .G_r wcv6| سs6`z:Di)!Xy8k0V|sފO<Ăɓ 6mRf.]ؤi.㦛n-n$ ϐY/+ugKHGoHIȱ˿ n6^ p| :Ç1z0zy yvqe8Y(s,-]ɟjk'zCA&֯_;wbxx[mXr yx*DC A !ZRwtW:pzE{…x099 `sgϞӕW{n}-Ν;gEZyK{gwM |1/ %]HOkLOM̬xt y;v +ԧ7^Vqȑ]|+غu+JǏ# C4uGol{^ᤞ.G 뼰? SͲa9fD/ /^XnVZRZ Kؿ?&&&puJjC O~mtc?<Μ9LyZ ;vhizEO-pxه |G'H3F'[0 qȑK?c r=ߏn-Zsѣ.^Y*PVصk*S177#G`ff睩÷-߿v/VJnWLU2#f>閹ї"җ ^TԀ؀-PJ{ 1!"aZQ:LMMArܗb$`৥ H@27o._KJ~rQ`2k\!wBQ36tb%N x0G Dٕ4CF_:\bFe/t <%C8[e$-ciS.5NM?s_+'s/3в~݂s|O˒~ʂr],EHFJ?݀}rBN[LZj'`o@nN$?僿ݞ+SMyUHw FrL\E!e9I'vRn_$`jܦr|4;>H+~ݗt睋@h{ [ (\ SBGͶ`}r ω !w#L_+ɕBf+ji<|Ü,:j"yvod)W 矿fMzthvvmr;bu(aAB{/,j Z"" =zRWP鼋]^,N#8pUt;rV}z2KKX``!/n9,>e(p❃?n>tP^Z ;NG//}ߧ˃:κ.lQO>tR'3:'f]$`ʜ&vb }ꓦVö=J.%pQvr_ .tvCzF_T'v,]k{z'j_~*J,_BQ̙3=R'_V/˕&&&:Ϝ^I~ܜPqF]|O3%?z9Xـ0MKH~@̺ RH 'ɞj #Yy֭ЂͷSϙ3P fdReg Z9g}pb S}@zVD _RSwu~C~wdm[)>-cdVk'w& 5'/J# fbg} h!ɜo)z=-ԧˊRs <5XQg(NI>C@-:YR ̓V})=ȋl / ڧ˂ 7OfedmZO˔X-3zd{1V'7cӲ Á&mӇMO}ZN'K=ؒ `*$$r|GTBTA H)}̩iHe XT4Â@(?g400 Z ###vzi`ch48wΝ;:}je58;XUO4>>-[`xxXW%AU*lڴ 6mGÇAĈ^g/uן:L;`"l }BgγT–-[0>>nA7Xq4ΝCVC^PB @X:>Q]c۶mشi{9;v6H,dKEw Z2z|shdv^/Z0J$68IkbQY 4Q;s'N`gg ܵ¶m(عs'VZ={,69^2ر֭Ço><Ӆl߾㘙Ç{u2n6\s5Xv-Ξ={72y|vI'IxPz^h~ C Elb7ؼoV> h;guu!.mg7S_"={p0y3֮]!<z73ͥUV vڅ066Z%/y :8+V`Vx_(n?Alڴ ΝÉ'pwcժU8v> ?q~lI&*QA ?%4\d tNńo_t5`qOB!ֽx*Yu8i`##> 8O>6.?3܂1yxGAOT*0::__ƣ>j؏~k֬K^|ANe|Cɓ'?ؿn:_iӦE1+rB]9 -դ%,z># ]Yׯc W=.J|oԧPYAVZbnnVDA\uUXb$~DZWUWaAl n/ ֭%} r ^W8y$/&L)| _H "NN<__c=wi1j璿Wu<qC)'|{c]}*Nfw"/#'`=cXXZ ę3Š;fffPV1??yj5j5a(Bp! q}ʕXr%V]w7{É׼Wڵk ih|O=z!]7t~z?ɟӧ155Q}jEK⡰] /?3( Ri||`a3π { ۲gܜeF+0y`oF0[o\'ObiMz1455zmj7ѣO:/x׻ޅ7> -- /ZUpfmK+W OM27o|#oab~~F#jsz3ǜsrw}x᪫z2"{nܹ^{m{cccؽ{w۲yq\:t.\躾hiϽt.m$C+W C4 AFFaznϋ$}^M^SΖ-[P*0jTx5k,?!"X??q,ДF]z}p=nEKEr?/pB{000r N(p+_0 ^g]P' T3NA!h4)!6oތgbnZ9Vի8z(~w~K˿?Gb۶m=}|_Ǒ#G044]v[nѣG/~җ۷-oy nV|Ɖ'~z|͸ʥH d.+'`)cXKw@!J y o*DEg~ @x~y|O%ƍca~bGEf {Ҥ=ۇxwy'7?(Ο?{p뭷GGAD8y$>O177ln"yMow܁uԩS8p[T9qx_xΆ*C`݃fQfP pv9>e@\qaOg]J%`Ja`jDQ"R J)H ̱97 f0ǽ!Bč@СC͎>c]G=x'{V_x_$ezX);ͩ%d|zʕ̱9wEe ~mC{*c=e}ZD(SRfXۃw@Y'G<[XqZ]vEZsn^T*eVJuE@$cF{c8-*: /J5+ :#j:h=NRORċ䭝90 mÙ>0>&qsss1`Jdb^ |˿qB:LL,QȪ?qe,tB;[-!EF#yk y؀ Xu9>{,0s0c}bDXpWO K A6 h@m| ̟< 66of`wόp*y~0 brXާu'EϬ4]H@6Y_(3h`~~1̬[8o Cj5 rrl]TPT000 k&txTR ,+ uN͋Oi G /HrO={1U.|Ǐy̕J2A bhhL5L<*V;Nږ-v)|'BрR*,Y2MYRJw!u01^貧ˆּ;8j`)`)#)UϺTtYlݺ0֬~<رcX~}bhu4! WVQ۾pπ|%:\}՘3<'ODT*Tɱ1կ͛!~|[߂K_͛7cjj ?SN%FI.'w|v ]H"R~s333|3ǰfVV166̔_^0r> p۱cD7`tlRJױqF;7abb֭Ýwމo|x%#7@Eطo~'pxOFRɭشiSׯo[#$q=' hgWMP'! !0<XJW?0`z^o|ظq#nV;Պ@R w_cfvõn;z0]w!ش RbڵRo~3>@@ܹ(E7[3X7T*8x G033kϞOjRJe՟͛3-x^W(u(Rgggx{ߋo;jC'C|y7bbKY MOO?nV4&&pu_xWS7_*06~RK?~ܮXVq#X5?i/|i|w܁!\=mؾ}:|+={@#(>xK\ն!a߾}뮻Z6V9EuhuY`uHO|jI H|ytMQEԹڟLZ♀@/K;_Ol U ~CWm۶a`2nS܂ N77Q¯@CC"\ ā>O>]{$>yFa;=99i0bh ʸpႽuQ@<͇%?ޕW7 ,NOC}vl޼1;>n 5XU>}4݋gNf|w}w[ \pСD _yfxV9sjnb/|!3h8tP1UR@ h^/lSxꩧSOaŊذa&&&l_TYwnn'N'㬗T*caʕXn]K |H) LS{ oR)?~;V^:@ֵo +Qڿ큺I2S/Vc r> mۆo9^cБ333xEQRcR ϟ?qs=HǏ0*InZtM-ЫO/{qu_ry937'r&9S.V6 :tFGGfggErK hz!0JfggQV9pn /gFFFh4:ËrٞJL2vIo ??/'biRJ;\.w,q$ [arrj}$t`i{S4`[ІW",jFW:u& Ž= 7w9߲i5ӒE>]nn*Ic/K>?>]δ(.Kr MOj~ҚC}¨1L`ešR֛wQ}mOˌSHon:5B.r/ sXʄvO˔Vs -djE{ wDMTx=O}Z>D@J]T5_YbKYfT%KT1 ~Ao8,iJJ3UҁG'jBB@6?(W%@)H9@)EPRV@5w2ߕdD;kdAG 1FWH,N &#D ~EVYS..>Gɋkq['-:0]vDmŠrb T!(h;6iiAX+V# Xr^OQ,)]9Xhc:n(@m)?~F8@q'S qEUTQzHbVl]< 礷#JԶh <0c,G aƼ%V`glg1T`̬sZ Dy6mZSG_"R&*( to^FSKiw@ oq^b&M@PJ pZ\<&šRP)4sLH*2@ON?j ?Mt$`˾n}:y􎝀 eM&e4T(@>IʘP`3H@m*4-_2RSG`BT*4??x)(m\.qum_7>V,Е8b՟ ss2 ԓlmCi!DZݏ$0hJ;UsFaV'b;] J)`7Z92JH%9''cL)u??&7_bQL`c ``8c`:@ 컘:Bf ,fv3?Wn6o+r;YS']lcF:#b?)RA*IR3;T,e@mjLI̳ \3< fpԃ,#J6鎭c3 \= 9b+%<Ng RzcÁrVao+ ӟ7o#N:z^TVS'͑&yk&N;.,fJaرfRX+/b (Tc3մZ,q"DSAw! HU9% A$F.\A1 %("Pe C<榙/ eM* hA+{0A1i 빗(-N ZVX?0 }3B9MMMQ  otJ(X| R_15M >$m}s$TBU~[.cVgj ɗ$D,/,{Q;ܚ .4l[[0mbm5w? .A>zߴ&lA4|EQ4S \,=0FFF^S^gyEιBlcLI)s.tzg QH `<Ø@ MfS)؜r_iFXS7hU,jkKU9kU\&eQ*cǒ?]oe?u ~lڂ?uTS HMήN'& pkUK H)gPZ4~wjd̀ZF<RJ)l> 2e('k g:XiC:VuP-rߑ///X\6j{ɿhH~M(zswbjr?eA E'$?  a4n1j5*Jryx|k_Ν;m8 UBp ͉f&A d8&|졍oT|c[)=b4 i=?J?:{Љ_V$̫[ԭ~c,thZ+T(ydb2>= h/9TRͺYofXJEߧmVdBx!Xkc#%=JjB%A ^qɲ(QTjf?œ5@ Liv!S'oRK~UTT)T*7 ,'{yֆl~z0鶤栥k ~sog\(- ^Jr|O?kf):y&CF;B9OH]Jvt ~ӃHP>uCDQ ] rΥ1 nb޽FQÌK1"h_jCWגyQ4DAcQˍ}&l<@ -sI=Ivb6+Z*9e8Xfm%]ȳϾmy RZy'_N4;;ZI~CE RJI)TPaxDȯVhjL*. 6c4rw[SftFrq( ^}pO>Rnu5mVP8rاR X 2H"ɚL l@$" t"/W/9eS*ξ%RS ~Q\\] ?T0A%`~igȘ?2.^xȧ4AD\FQƦX%G#Q'41jM@A" B*Bzq>(fze# _Pɂ[ٗ)w]?6/6axhH=/|\H:W'V=gϞ̹s_pEDָC#Ũ MX޽rDyl4Rs)LhM~5 o:/FZh>(PA Erz""K~:%K˼^ K!2ZIQ J&DyiAtSB|]Xq(7rMepx7! WVK)#!BDFCz'm @\&Sq`bi0slbyRJ)RJ !d!3b"_U+oӍ#I1|l!Cz~/Tسݣ ?)[vϭS2@5n1,%v dRrF=)F 7g>O_CcR\}3hԉ 0?"R2 CY*$Y_K|MǎniqLJ%eιJa !B!D @l_w",) S8Q%}ʸৢrK+W$enpG?s󗍛?n=eŅdžF&*c+s)S)8jQ "؋s 6`о) !<BJ)SFE&'>LDN"B2skezO}N)(({[z.1)SLce/7y\_E>ȻeͿJEnF C3Ԙ:̖e:1tVcm\rr9%⫩Q) /?KPm̧9%u4m~B1FQyA/9F޽;OK\w^ڹs'CgffaQTBEBX.._vOLK7=X13؂>Jۼ S-v񞭳p,asv9ld ;?ÌqQCႿ y}_RJrT+RZ@{keQ6<<, }&4; ]yI)b"J)Y?^KV{[Z 0 ݦtV zɵVRpZV-ꞫKj ZwN cHpaSS>75< \ɯ !\/gffE3n 9 0f`h7OKxU٧2::ZOMy-ۻU]kŵۈ.G*:;gyz I]HmnŶmǹ I)!bߌDzH)C 0 Ѐ8|W)?Yr{w^sN` J%1RJ0ˈ&PRJzpjjRiʕ%߻ s$[]ypw%w^p+:ĭUִV ~$}y[;j/}. ~Z^#j>2ԳL BP_X(߂_\;?S}j-5SM@$dHhAT*AGR !#AB>h4jgΜf}JQ19B F̩RLiT Z)B0 ]VЕߒ f0CTj(TzHgf~R*qd&8 @r΍/MxQ^7C|gz~C_-h4^0 DEBJ岐RzJ)y0RJ(#"F{DdB0}9 [>3SQt>Y>7 ciՠx Z+(zZ+K416tRaxBJɍ6ELSJ Ѕ9Bp r"b:G ;[>pvIچ!nz6%Tz\s:I#M|4C}?% ъ `Νh(Ð~Qr, R}{yJ)Ϲ+&\S>i!4a=f$?Ml٥4ͺ|~9W)WJ%y4SEX Pڵ_@)ŌYEHRR R o'%P&`EdR݊1 PBSIy']sɵ+ n H)K)3+XRO_-RmRahMwszf- gy2+)_*`Q<.#0RhDdӈU*'pL3J4M#sOXfK #01(^J< ][yv,Fh_sNiF`Lqb.3RDai>cnZZ p>UUsXsk9[ͧztCs/dQ!";b%>#"666T<^)e:}S/liZfslv5lL!->^41y+dv#0f2+V0 tK>-%/&''ޢ[aת>!ހ!pF`}@S+7WRpayJK}Cy\<i}M =l]18Z3fqB1s(C}1 ^&ݔv)m%%cA<X4!Aa}S7^rBVYOljK%gAM=7H2>b8`A%K_i]zt1Ho |Cd*3 `؀O%g -~=>RҢsJ%Z+IENDB`Carla-2.1/resources/256x256/carla.png000066400000000000000000000712121364475620200171550ustar00rootroot00000000000000PNG  IHDR\rf pHYs B(xrO]]]]]]9uRb6!sn^2h,9If@c=: hb˞op@'MQ5&gC8g  6rzt)NٲeJy5 D\xRӮ>ucQdlpOR)bs됁#"Ϋ]i@IH?nذf!朇\/ӣKP0dX4sP!NCcu8h6l :u+sR9s=z !uWyRT ! +#hh@Ft!Ru3g>#2`:z GI(jW_:RJbR@UbP A1TpNAG@#?::Z3ڻKǡA x)e5jdBUS3bXtЫ4TNLL C0MSvء@CF &6( G{H>#SRL&C8{qjH"Q>Zx_.b  aqJUJ1L-5:~R!r> !H>Rzoԧ}}}DAoYV^#Q+G5 !Ҷm BETRxAaI?O1t:-5@~Ǚ@ 0>u|۶> ri:RJ*TJg>#@Lԙ@cc=JBG|\B8:J")"(1&J0 C(055%<& cҲ,J2@R+q_sF|uQurΙeY5L4Mߗv0tI]b?+uf1Am WJ+ 4M>99)jllkLi~_G}qhS34M&Bf]gaQ {/=BS!N@9^J9rJp|W0 T)]fM1W8)+QK s=@Ocv c$네R@zFh 9J!DpB9!cb10 ^.cL(F055MmL 1ho6SF}4M9g !!1CaH)I)c !<3ƈ. xDoToc0ݣ%_)#WF(&@)sNBNRsz뺮sc\1Ju&0==͕4i&$;уh3Ig&/&5ԁǁ^DSH kM0ӹ̀>l=;f+|ۧ+sG3m'O IJ)Q8mۆbT* qLu;Ôدr]"[8n]g9K2 x*"A%\pI">QB$%^eTr|E׌T[1iJ4"le3 B 06 /Yٺ`ZΥĢVNEi_{= PTVIjI=RDwd8q1ԟK޼n?^z8U,2u]\81 1麮%*̻K$.P}/1oF"tU𧤔w/[MPRl[IC\R?%Ʊ7m2惢Mb&5jihbFfB37ʢ껄?q?}9woUKݓs~*NCeYqIa\BA}S9V 7l@&&&˲,s0M7ybciiBH*m_8KFƪvƪsjUU9=<3 c⬀% !$L*9NV oz2B2J 0V3ʪ0<%޵꽄^!UīP(@i0Bi5/˼2^kpw\ \sϤ]u8\TӶ[M.Q(#^(9ezd#^/͂ ]܅puC ^sypz.D83R`e# 3~ H̿գW))e@1VRVԟa!9w pqMt 7 R)NL FN I5\.u~ԶmfY u4_ ro HBJ>5 < S. .dYB˓csu 󖩑x$QUwc)aHrzzZ:#=wbh^P#DRbHǡlְm۰,ٶm2,uM{:ϭ~兏fr@7&ΓWGL.2803:?vTI5[l\z K|-_sv$aY0, 4&dKO&{%0RʲҖR p8eYmܲ,P(j)(@ 0eW]ץޑqΕkI1ܢ!)BHz$λm-&K0 FC~ny[@%.^ːu6^.-c(N> P؏ԗ"ZȈ))ι%(cTjMas|sȆ NN[cBʷT T?x?[L~0m9f܈bHN(`XS )a !Af˷Z^v1z^GL}8p{lp#s>Vl9x8SK sÞVyTBTG5q]fW{ժ>g~ lS|%<#7S8DZKHmt2k\SHz)HMØL]JǀgP?.Ի̻:t)15R@~ZWTaT*?pƋeڪ>3)w7.w+Rg:3_eS }r[sjlwΨ~cD_O 8cs$B V'ppfx(HRu]600Ԁ)VPWE3!<K/\=IPθ_m,xdjV_N $kqKqc'ߩzyVDL~R:%pbp1u/7zU*[S-0؎s=#&Ƒ4MCvm39u LM `a*nf__BP%(c`HWPӍ_ J3¼b0:/r,yʩ錨cxux{0O}iiD'xTi 4b >'II;XgUЮE6alM/$b0_JaJ)-JE)eA)@P!\ׅړ!d @aM;i0 S-Bup񗫍2-7%QD4e(i KZgʹ%9 Wy4B>~Z:GJݐ)xM_f5*蚦<)J Ul^$c31fxҔRG|RUO:0*2V܏M0aN3"zyI95bIF i͎s)I7+mJG?H?)Ac>O 0)?G:"0p\40άiD>BK"NIǍƍ# R+O fIeܫ&aQA0=ycl=SO7y)4t !=5t@x %5L&ClۦRJ+^(oRHKސx.ym e!U'yg$,vJ'1D!AfJ{j 7þ~3I{8jB'e .Nl-a A_3{xURJ8ѥ5 lذn׭۶)*(*JA)5#)zKqkRN/X ~ԍ)fka@mV , ?S ,@m$RAz?7ۈ M I@oKԎW~B@~ͣ?73(!f] ~s=lFx^SNAy rLQjk.Y9CEqu} Id]w]f6<Էɵ7]$wpj{n)𰧀\ sԔo|^g~1Gl&ꘀuk, _KǍVƾsͽF$5[l+ߍz:Նs^ԭ0IaK/a3 :opfo' l}@.LA5&?Nn^-ا055袃oO= 6dE@]T\J@9`͉QiQCRL@jݤӂNA@8̪ xn 19u,OMMݡk(+XUH5YT]l8GBz4HwR8.]Еf|P߇M˲|XzPR4sbR[@F}=lFޡ@ 4]Ӥ4ͫ*c0JH@6UR0oO7 X%C~*o34[z* K.σ@fҕ5)qZI>RR꒎S!( ba<=v)LHأVUuPmQ_èkDQ#Ů 0MBA߮c7.4== yrQ6v 9a˂f|!J) ݕŒcES.O)֮][ @RmjLLL5Ml۷oٳgc˅Aҝ8wxX Ťp@(NSZ~55 b$9w3:Be!Je\e/$ q6_ Fǧ8,7A2hTЬށ=[@.Tju1XعN6dx@BYI4]$ W<dޖp|rN*թ([܈ZB0)%09]\$ ilPk&U)GVFy&YY ̡EbG>Xg2DhPG=O:>6OIc7G=:`Q́X`:I7[Olv@L:Hd)4~ N84Jȯ+FP$>"zԣBЩv tưJjDD^z4 b%`ǨFzB@oaP.D*@= v{ԣNfu::4a%`*B*eY, sض ۶Q. QtP +QI)@k(@.QJ188a 4͙ƄԤSpivݣպ`W`%`uK `Xt),˪: ˶ n:f8q{1DBf3-[:*Ј(wZWQ]tu,?ӧaJOT AL,ZɅ !R),\ÇK/]𑉗/_JǏw~}-G|ՀIV6CWF9uPl2,]F#aK/T@(ż1v-!LMt_[Bpvr\<+044gy@>;NZ ˖-:Gx;/~ؽ{7W4%+UMNG5 VV AIǤJ ghPJf 1ؾ}.\08Nݟ뺰K%ٲ`9t׬u000o[nXkgf_6m֬Y|+׾O1DkQ$fM ~ERUaf:1_ve>:;vHKv/@CJ !~J̕Wb7^@Yt^{-x  nܹرcG>C\馛bŊnl=jy"#`@@J ݁Ԃ̡ZlAݻh^qoy A\F\ E)aAR#Gyk0*ׁݻqIqFlڴu:}#A:Ձ6mڄM67x#n,_T Gߏ͛kp}p> .[>(o=4Mo5\ u]߿s;/rRґ<)UFzFt3.aIhhhK.!#a޽Xa~g?Êmcjj 㘜D$&''!#|Ro|#),y )~os=]v%*|[nų>իW7MuMo—%gdhsooX,bӦM8|0nf{セG3ToaiUmA}/1G!+W!gb,-aJ%LLLX,\.R5`&R4.\\._xuٷ}va-8yX`FFFpԩkxx\L|>䗾%|+_?a<5eWX??C=[S𶷽f_|>xߏ}sMJy3Sq*w3~h h…HӠ.پDJ\"5>* P,Q,Q*P.a6 U,sΑfv:h}7w\h*n\c ܹsÎ;pUWaxxӧO7?0+Nc!/.Ҧbf,uJ@x&+A ,Fy{ض?   PJ]u a…[, 0gpo.]Ǒ7o^{7 Ν !aYսZΝ[SJя~wy'Rl42LTУzC~+3 F~qAPOJ,z% n?(hbRxP`149֮]cz`Da.Ųe˚frD׬YOxo~GRފuARu]x׻ޅc=ÇCO|[E.n+0p`@W6=X3ג2a@Y VH/\۶}_1J%?O1AuʓRbƍp\8P>FFZ롇ڵkqW_1W_}5(kڵ Jjժ~ 6ȑ#{qAqm{1S\4mbcPrY5O 8XqmJ:J-B&Ay`!|sO? ۶qwox[o7 0VZ'|W^ye>aTԍ@1.8JR"Tܚ5@9\ug x~5-ZqPsz6!H{ ={nV\zXb=M6__|nIJep1|8N8ӧgH~5͛7Cyl߾gK.>lCEkٖoiWV/K*Θ[0L_6&IHYMDz\%2LA))R 4A)U>ϝFN5i}*9z衆v'N5?#EG'NSO=PA{U}4x爺0l!PWD50/I4bJ0=cXcz+`ѽRJ*sX!}}}z4:t0.(:6qAFb{zlG\_V>XR!R^tv\TD)mĺ(ςN*)y_LBZ:#`݈PkfL> *Jx[>yWckG)~Zr "yRcZ_v>'144=I l k9p@h$w*"mn(?|l0j{;)W`4ǽ޴JC+kȜeAA,$V\#.!a10,@>lXzs1RG s=q0qFF@tGY闄A'h@x5+8?p!OqLOO OHC__2L1NהӶmcǎ ጌ@d ѣmn8_ut 3;t HCU_ѩS@ԢE=R1: 3 l PL xOO(Xx$?11tI9Q($`R¶m!P*099Yt.Jn 鬎 Xg:sݰ`'Oe]7e>;wb֭ؼyzzQvm7o^~e aO~r\= V’%KpYڵ [nŖ-[|GU+00ۍAL@BGb'N p+0p0~{kע8< ָeQLM1|_=u\w~!2pGQ9e]Oi\~Xb֭[muUY~׾r/"/&̙u>mۆ:&O}kC___6ҩ[ܩ 3:VH8>k^z%H)d8{饐{c⋰ml\\Z6i73g3g02= aU!vB| q044??pq]wM~_yNLԧ|KRJuqmaժUu8'm+jo$z62pT`^IX, UW42g>yr=ߏl6(U~J+ dJ.txN<@hOVwڅ!y&,A@Μgq 7?6*mc> Cp8O>dSbٲed2'?a|CGrUVa˖-J)wUIs\acٲeXhQ]߁[nůگmRn~BΉߥ9 | %[lM7Nma#`{7h?aXb,YJi 8qmۆ?g!m ݺukSB]׭>n mHp]1E,^\6ůZ_,@+_ v܉믿 tO 35;nupQPW' =kT=lق뮻$oBd ׯWg͛8?%8==ӧOT*K'&!dl";Kx K.Gn 7nݻCG܅Bۑ5XRlr !YH)n:y56L&ӔbnI,in:;p|c.@ٳgOkE&oԪU޺7mۆŋ1p!Lc89\)-0,@i^W ҳoݺ%رc5Rbҥx[q" ?I&'', :zIS6Vf!jP;s Dx6+$q\s5AibY=p0s\À!&:CCZu u`ӦMm#Ν;׾6A@Egľ}0yqj B|;Rmm}O]'ԑyRws% 3 LD0۶-(r +Wj"}$BFV*l,x6 wdЉahؾ}{ۖp݋1w)r)lقo9ӧ࢝hCIٶ+{1࿫vLF@wr:P=cǎFDy54P yaܹc/c sw};b3#`ʕf G#Gq~oy[ֆW"%1. Ҭ . hoARJ۷iXp!Ν[9099#Gtl ;wbhh_~y(^,~?\LWϿoo}69s'OD6kî]0w\Y&VkC) Vhf+0-Nvoq}44xeY(ַ 6`5OOOD___AI'Ν;aÆJ@ Ӭ,Ξ=|a哤#8nWȯu]7@:1=lfvN  nG=MDmf'`Mt/tTz4)nA[k mceVMG5d7D8)`-FhvSo9IFx7N|vVMGQg᠛+.{RZ @QA!0Me,pa6l aܹ;V2 ! R8}4zq{TC !'`\'53wnXbr^R z%T^:ҥKtRpqA8p'$$" t*:o !/N.NIidYX>JsNӰJ%X2 ۆ` N_tAL.Z90MVҥKw^>|S]xqpnEw\xvC P'iꥻիA(51,޽cc,XBzwwd2H/HJm]*4н@W<k1M] |%`ѢE3gg _ }8pRFk8 6do Ǿmqj O<۶jeYW|>}sxklnݺ2FvӺVW|t̛7-!Ċ^3Mlgp?כ+˰mL@2 r =;9:_*AjzGn L\s zꩶ6+ ,\?V(puaH8r}Q{7s[(oߎ'x"K.ƍpB}?)\m.V@rl [zjB0Ix ,_7euELOOöm8u9aa0 R),_@qb |w_^ +?r?moEF.Nw [3vᗻ9ǯʯ/!e ,??ѣ8z(.]=y>`zzӌ wz% EYThG_j(蛞ƪe k_v* &''Q(P.QT| @gR0`Y* 4VXL&{¼N8AT(/_b||6gY c͉۷Rܹs|W^o'?+LNNݻWU+__\??ٕ] o>ϡ\߹5:v/mlKLf0<<[`_q|C_R2e)(ɠX,T*\.UYUϊ+`Y sBX2G0 k߾/CO}S3gNQo7}1˲pwYukV\7UHyX:vs% a .(HKNx!J', o K{?:(10PTJ|aٲer,@AΜ=2ՀOO7Mӟ4~RxG=?0<<  ڪ@.;p'>`Y BU - sDs]7)+&?i5uqαd8pgЇp(h+HMO'k|#Piuu]LLLmi?~=jgFBH[ Guj䗁kAƢ.z6AIIzb}p:,ײ@a[Ez"d \TDN/n43NQ$N! guLۃ4"[:yxm#>b(G~uuMtxSf`RB{%(vZ_yNychhz:[R@R a({ s\.0 ?@l|A7(J:u yF7ˁcJ /(heͪOB@ipQ@?LU`}OTQ{s0q\y]j⧤>킿n%`L'ťJBB&.ڴ T*MRHR>44jTt:C+{m MM3|`@szztaks<;1hRp)B0E: qp9N@? "Ʉ2UV1bsO+PgΜi߄T*BԄ%m;q8rU^9ALb4̲ft0bތ tAE:u +Waz<0cHm܈ÇcѢE5S14O@Q_1%!8p<HuGte+%ڛn _~9/_ ڵ 7oƱc`YVZMM ~闰l28iܹO> I֮]e˖a||w͛qYU_k@-ճ@=iI%Ichh' Go|Vıbd2uK~PX@4Jjom\s0Үu\O߈8oaɒ%ڄ!,\_=6mڄǾA'5jʯ ~_G?Q{Xv-nF|[‰'Br100??ҥKkڰhѢmxQ?,Èt02Px&:5o^z%@yL,] Q(`{8v,rr<d2#G`CRڰlRri_:/^VT(wRԩs׷yeH)-¯گa޼yuW%KԆW""ڷb !+`Wv1Y5qIBpb<*=͘ϼ:<jc~9۶xarW9׿2缩RJp|9sш4;ŋ;WA0 '˰:<.첞M@F3-? NwC' m0*@'⋘3g4r ?0'`bΫ_M6aɒ%X~/."eYزe [r9ti 7^c~n }{W  GGG/ˁcx{:.?J).?jW\?#xGo}*NTV;=xm1A[M'r-[@ 'Ñ׽iB a{vt:={_*arrO­{`\5נxU `ݾ8Xv-n|{c ~qFJsR)ߪ_(lٲ:R) oŃm?ݻw~7/_P=\pFz\ibb=<֯_ XHۇ=f/[G}:~:FP9 E\  _%W!ǎÿۿ5V\[o۷oKrhfaf]4׾6T*۠Qi5;;r5m6e"7c#N. "`Ϩtv>z(8X~=H&oxvжmx! cj"/\S=Z3Ne?}0oj LJWԵׂ{2ك͛7dB`llp|ׯ.B›Eu(6m ~{`v즰V}[]Z$R@w6 @mHhnN8M6C6ڵ(Z_D oۆm )mYpLua6 Oĕ%W޼ysS~5"%^|Ep EdYa1001ߟ qYoS`x]C{OUE7_n6{bF*~o;455G}Ve]Ja1~հ&'w(ibfiYd(f2pFF`/^ x|ϳ>K/B(l4z{U~uRC\gϞo @2˴0 ѿ/A?*jOUcC>mۘHRF71\.˲= )rbjþ}k.dYR$n+Fs;Ŭ {ٰE@ }v!_v9R#Z\? ccctk>IA]Lq jа{ϗDpI߇URьg^)gKNPgXQSq&Qf uco`#BBAh3{tP'|w+Fy-& Ghp-Q U*n30Qf uk.C31=l$_.ݝ^U@3F=dp+݌:b fcgУ~r|Nȵl@觎Ip9ʥL N3kD):x\@B"rځj jnT6Չ@f|9TO#PF68oYIډ4^D^t= !+) Lo jwbc7B@a0*BA>#.ˊ?(-n3!蝣~ DS*iQg;FQeݗIw-lQOF|ƿ(_,Ug(e9Bi1amgϞE&APPIQ3Qq: YJȑF(cFHӉȚM&r.Do=I5$[oAsDO0wA,#SKB@U 1i?0 a˶c<8AJ)!BJ) !d2 RCOC *^cjZ8N (;ǸS2zwt 2\=t79!j*P(:6 qijR9>>.eJgPvBm[jCRL T*`H?x#Uj00gN|{9; nԓfD{٠\\Ԃ?8t6yЕ!DxجSla\.rL,R_!s.)(;t^3(YO2!ht'N';O aDHd{ω@ysR0jd r&is@V ~T1ԀR$u;8m2Rc, 4pzc꤃?,?a@H f<; >3`F@JS~2V}F%Lxy\J)MҲT*I˲jfRT]0g݁e__%W@NM#U g1}|u-( p=8wCh&빘@ގ*:$\#jKn]Z3+w4q'pB|"ǥij~>@@e"aRﵶ|y4=60 d6J>"*blkG25@H Jp-KR %ޝ)B0MWÖkN@~~H >Jm[x9iw %> /u?>jGIAN8y@~1vEPeL !1$mӣW cp( ~%{&p~SJR:#,R3s `l[lի78!K)]wA24y|5^v 0,#Fyo1 F mv_/tUgO?/t* m 4Eb;Ha2PJĄdr,<; p9>z&&77 󯶐[b0(tHtJI}nk皈xvP~y<.t-D.^zxREި/q.r5a1VcPt ẮBpB{qjDQ\"HMIűnqt*}*[kZ95K28!L0*PgGx1OBWu]Y*2z -&ۼciCRRJ9!{ulJBr ^cbI:x67 KF(f ѓ[,D^~@JH)BcRʕp;v{-)@Qc\S\ι+pX=:VRhm8_̆H:ҝO'avdDk@km٬|jI'N/n~RBow9J1D)Abʠ8s8C)uکo];q/?"tџ:(êFf)tZ*118#UGJioy%{ (=&`ݝՁsq7νN^;T)#^5}_K)x??}:'q;jls>FW7+-[ J)o"199) J{ܧ@)螣@Ad%%7s08 ITz6+./5o|b!1hGιJ `O)TJz?Lr৕O0Ws[(>5I)42{k?ÜFc:M{qtIXQ\9"B)/͏ʞc˛pcqnWdO':LX_HGGGIP R928a83))uS44!@!1s>!a$"M%q] KH.qrU0}HI>`Ѹ\g3E-MWzFʂa 5 M_ػo2*3(QBT8i8inXtMit:-٣OX@T<@Pe B0W*b:1 B뺔TC#gYjG iDV3gpb:< үTS ^k^uL5{⥿ܻo'EW0lp08Rpot_ P#ɤ9d2mF*bm[1u]R"XJiιɑO!\"!pWH+] ΫG(pv=Sܲ{h<lxX^\WdH,0:):{~aY8=)_?zw>),(3Ɣ PPBT p8eYvRe4Mdz٬bG >"PNBAy&!r麮Kcu]B)%#!1p!w]D^WN%#Br0;sX-aOKT&%B R 0J@eK3J@^#sꕡU.M(a6 (e zzݧ!ڹw(A(p.륽sq:q]p?]Su Lf0V=2/0 0@Mh3(}4z)cBTrH9p8V9'pw\>W@p&!|N2ki,П :3{A/~w?E>g:=6 q]1 -4M>55% $fC.tޖ-[0::*$,.$m4M.1 ' +ېy=r `R @X5(Ip%8p]+!%`3#0 ì)Cܨ26Lƪ׺o]<_%XIT )@5'E{Nb<ۗ/f m=铘]hiG,ee([F{uqu6m<@:?cLEa{_ɧeY²,5]Pj*رcV^M\U$qP\0wasB{{Kr\Im+P= Uf. m@Ta"Sk1p蓃U?n_OKEL=A Yooǵ=>8=&O_D6 ~e#?i]~~dۃ.*`zz\u!80MS 1U.!sG7y}kiB*RB~I;G3s-"$.{-y=q#Z,\#1#tf@'NjrZ3oB8K|-Ha}8 rϏ&7{wQAUQe1 ;q~eSS~տNH";vQ(X,˒"қPa/~9wk8^>\5F5Ш@t{i~8Ucѿ(mKhUof-H.ĉ\5q_ԁ>ǎc,ݢ0F(%qg >S~fA esJ*6cw%8sW}3Ƅ~maer#`MG RHmò,p}1wRJ x$=AO~d(+rrH/IQ1`1`Qy0FU'7kA4e+hGܧjCXгg rZh!Hu~ϣD;RA3sJIbLV&dEz'Ɲ))m?A[Sׄa\YJ2Hߧuf(uIRasu]jY97 08sn2L!BRjҤ2)A1LJɼ< I))XL}O˪b@45@yxɪǙ?%s5ؿuf:}[GfOmf29MRsn!aLIB&`1CJɄcLR1#yͮ)G@c= #/f5x*PJs8W)]UJ{p˲䤈[?cB8m39UҀcԹZcx)j_zMڣ5C>8z5bj[E 8 V u jW}4&qLRua6uJ)gB.MRL_L G|!Ω>+I@o1=Q+TgYl MKzuUDm8ZOxT!Q߲,a0uFl!~i*$B x e:/XG=)A}}&@i۶ tt\c =ੀճCW ~MuBPG2::J j088HDgި)%d2D1> = cz^P (SJն]~O7JA~ :sdu]񉔒 !D >~&i*ۣu&b4jW^ &"D} t: 66@I:C3gCf{}IA@:RJ[t32:=QH|3:i6`F*Gy$¨'   !xG_?Ռ @눦42jtTCTzQ'(`7rv܆Q]o=w4fg cP3(RG=jt ǔ9be||0v^"HEmh'\1AG@cPwt؀y" {ԣsIX++: {LGݤfӰ|;kP2[~]`7ៀ:N"IENDB`Carla-2.1/resources/48x48/000077500000000000000000000000001364475620200152205ustar00rootroot00000000000000Carla-2.1/resources/48x48/canvas.png000066400000000000000000000047501364475620200172070ustar00rootroot00000000000000PNG  IHDR/0# pHYs IDATh͙{lSk;ׯ8qb'6Ɛ1m5Vv6w ikM}VUmҦMk&M[htAP2J _;~^7 $ I{}9Fw%»ᄏi mȲ<n4MCUUUѭ˲ B/Ʊ6*W jIKYN"@!t뽴lhˬ @|>X@Gm @WNJMJ" ArbUt:#Ȝkk@Vg( ƨ`tcXAfc2c 3 ^S _;SA*Vk1p8<(C`4U$Pk|;jlœK3g_h|j%;33# y3`s$Npi9h_m,CNu䳡o+ MӪvZRJ!1~i=s0`0k3eq<[[ZZ$YR0t:Ihٵxޭ?bM0t"Ioz-5KaE_D*tn9c2b[~y7;Ν?1 #|:1& da Jes z3 P|>:Jɽ̓ĭr{{PZZr-N<{al6A|fv'}@mwi ]%A@N3aR|>-7Ɋصѵ\R0x̨i577+\.|N͎ ޙ7@)gtqNxv:jyZ$lZeݞdvaeYi7MUCibh4hrruvva FAeee~x.RQQ~xmpbD4HhJa=(irrR:~\[[, NIBI&M=sq4ZO(XţG@gkЗh˵2Ă E! 3 M@!(jvoVz_! ˫{W$It.3.D IENDB`Carla-2.1/resources/48x48/carla-control.png000066400000000000000000000064331364475620200204740ustar00rootroot00000000000000PNG  IHDR00W pHYs6G IDAThݚ[l]WZsN$SMڔ4i'iq%P Um_f U@}A2xA< @H\2h*@Z jD[czNok}<ϱۭD|֖knUe@HD %cz*P^/z~A$sNZ,v8O$?~x1??o7H@ޛ s0 .2ƄjT38\l{7Ȳl`.,,dUmOOOA;;'={_hQRQEayNESyQ9^>>"9YeigZmmi^y-/ )js)qW(1܏EQs5`& -4+Z\^WQ4|EU5!S S4UJcmi)QlpO昍C]__?< yAYv9 7GΞuc@DD#5#UF#Ô`ë<33Ty"Pň2ZP'(8u@Վ5SSqO8 # "CZSS|E~gȊyMxϙ3gammsq5Ο?Oƍ (]@t'CG)o(}LPS'N׿οw:|؋/Nn~i\}Ggvv(v+\`ﱯT4q{ UXD=( sx Y xx'ٳvp7o ڊ=n5@6 HpZ\N-FL Uz L\DEc< qM\jS;*@:KX oЧ4^n1XnRNiX`׮#ceunz|L'駟W^ԩS<ü;q /ᅬ1\Ond@ʢ^*ER@TGk^;=YKos+!it{YXX@U9y$qLOO$?v:|I2TD?@BōC=Սz뭷Ð5677i۬č7rq+KN(xUA\ҕTYwi~ommU$I'&T.t(饛7˴m._SO=k Νʕ+q̳>믿kTu@dӝPдkΑۜ45RAE9mmm$իW*4vNo}4ZK厁RȒ]k<4-IjMU8U_ePjwqW^UpI¾/" je7>>c@|JC CUɓ3oA$9@Zxg(l1*庼d'U^]9ho* 9UCEuhӧ?V!۷ooN3.mo'x?baE1Q~'\Vu’7[v[۬,I,Ȳ([XR"/=򵵵o..l]2 )9~B6==."5v1fJ"c|πoD$HPmҽ!Xɫg{Z? yLX^U :'izk8~7sn1^Q}rS|쑦o5{x(*Ǯ?}"3~RG{IENDB`Carla-2.1/resources/48x48/carla.png000066400000000000000000000062441364475620200170160ustar00rootroot00000000000000PNG  IHDR00W pHYs䔥; VIDAThݚYyU5G={KY&EKEҫGLڲZC0(#<~1 OF;H@Xb6L١,[ Rpys=Օ.@A꣺U00JB@bqq۶ Ye.^`0f bZqyAUTBem/b X__Ʋ,׶mwjjʻrAAW\.~") &c1!|;RtRV>:BcYpxJ)caة>G-|O'vU;r-_f@ЀƠѸ-4޽D @hJU5 HzDNvQ{6i?g}S{{~x-t_5~ skw/=@~S3W[b-H,+N=j< K^_;(]KĀx^TR>d{mjM܁{ iD7>:eYVEbوޟo0'OS+۽7z?pD|u:;P3ٶ^\\!X,&ljDm_ 01DBeu:JMg6-6b©{2Si)e$ m#1@t 4tzqv2B2qRx,BBcZڶݵ#@ D_KC*C*q>??O6}548`L4P,eO6KHJ[@hK;ȼ Mhxn fSO #D!'yk_? R)xy' իWw\ӧO3??O4eΝ?~T6-d)$H=Bө<47VVr 硎a}u]7nѣb1!S.br9Jvg7Uzo7 qc-ȑ 6=i=c(""D)EXbυ BD$pΝq'6C*/^@S`nnF,E H0  ^tg>9֚, Z[#HpQN:K/Ď;ؿ?o&erY^@&e0X7 ={= I(P/ȇfghMVB8$ vI> eaannrc _~;q l޾1HH  HJZ-2!(UC:|'N/3??Ͼ}peq^y\/3p[hbH뀏`h$b`@o^y$O#{uJ)ɓ'Ng˗eYF~owVVV7H,71_ yM^3&L)..>aXrQO9saڴi:PMϢi\O,w~NN\eNNcGkffCNAn_~ SN/B{k3t{&ӇLR2r}>>Gw PR q, <@*׮]O>;ydP`ǎHh}36)Νv]yj=ݴhԕn+nHDR[omHMMgR q=}t)f]㿯-o| '&#%5.NNngΜd#@z8jC-Zm 32fY*Na΂e8[Uy]qmgMA-ٳ׷ЖF-EyRj26 _?dlIG$ѝCϝeZ`l6+! J)AĨ51N},;smۄQD5[ 3500 (`>bO!^{ARRd2@P0#|K g˘8.PPP8p7n@ss3T*!J_-ZT1Pd˘x/ g+˱_gE"q$''[O:u<գP($v{o@n߾x<(..Fww7! aVZ!33sX|Sa5W^e<{|>_ߩxjL ]Rue>:t/^lƸqp00 'MaďɘuKo }B#W.[L&Scff_, шÇCTR+WDDD4M;;;}Ef;{~xjXVD768}]z]_V+H ۍNV+f3D|]n4{?+px8`be2D*Ueajh@G]C㓓;l@|[[[㶨ERz)\~)Zp6E kkNJ?ϛfY_͝_ܫR%g(ٺ:j%TZ-YM/BMMJX p碢_ 0M؁]0|(%==/)BƦ!,4NCÁ&nDbd0ؼRw>qS+p'P__)K4-,*v*@##J@JVvBcM*ln 11q[[[[V:rB÷,kyT*V#JE+!hniACM\(7oV*W⽃lFlYYYwDJC QQ] {JĩTj0hjmECmH~|zg@)1p>c`|ۍB4#dS~a 4R*V#VC3b[ꫫ\*,xc IZoӦ78W7^z?3`UTT+v#Pۍs~刾NZ-QWSb˻XCA jG?e:VX jܸq۟IAZ(,`XNglNNb(e0lb=c2_x tqJ#>o4?<XJLt|Z8NT$1]` ڬR5(z{dv$P*MD&nY_xxsKXeee~QH/6%  ݻ7+%,l0 NL<sg8U}{-DNn>4Z=xu8v %>XǏw {T. ݍ~[9eʊ##+d0FGREgA@»omᅴLPѣE?.CҔ N'R/ 63LWxd?*)ՕGf.V|pR( \ 9tP_Y^^^]ٺ?䍃N4\+Uزic,:Z YYY~ն\|) 8|V*^&;FJ)mtS^MLk&rϝz淜+###4$$$(H$zmUUU]w/?@IENDB`Carla-2.1/resources/48x48/juce.png000066400000000000000000000063501364475620200166600ustar00rootroot00000000000000PNG  IHDR00WbKGD pHYs B(xtIME%-UP uIDATh޽ytUE?UoK^^򲒄% D,A (hX mAQgve(=lF YBPC !,2#KB A!wkxa3@6_սu[_ h68(%'PC!G )J@l_$'MJ rd'ΜYofOpۮ->#-EE9dcm$C1oYS棔7D!\v FZ1w_ =)IsHLG @)juh: h(o#B|o8H\)fFOvX6犧u5:ϐ6@)|gJ: d˼h tb&08pVU)~g 鯣xݤ ,dl;[اhߴn/o;7i]>  Bk> }7PuRWKP|hB-LS鋉5'hwu@9|PzJ~ͪ*D}jp8~GbIxo=n)?sqa,^g Ijs{gWGFTb> >imp;@a5yv.qO͙o&YRx*c1:eibF+ 3bפ=o \lB 3I8ڳb0G }׃r4EbCy"IwK $M})ix!uy~௘F'dwF!Ө\dD8.+m5T06g̹!s%Fetl6޳Gpc)ZwQ cƬ! BZ[EG>PGR$*$ۋv:HxM )+K֥_ ۊ6<'nHK xZ> (@ O^잇RbfVI8}J!R}a̘I'^#~@G~ BmF_v:i݂ # ~A GJd:_9VA00e-C%j^e<:=RFF}erڿ ƴ0FMX2xl΍y!t@HMi,ύPBE8فqhAː$\yWM7 a,Esrij*Q>O(q?ցR7ysbGyPR#P).^cւ!.7كcޜae]jJk#!G(Q  ni-}(PYӑ HK*o\wSW}Z,txA#ɘ Be2ǀH@d@m'Ґ4$`1DŒ CmhyO $LP(4a=~Obw#mhi^$F{ s)pGwv^~SyQO Z,Nd;@}/MM|xV'_GhcwUq63F@4n EN"8]@?=(WNٶ#hMNVZmaA;)͞z!8%ۄ߆>e@GDD 9SWvUd-V35̄]&*,U(*Oiu9lU_x1 (ſ!lfN, (@zoAJBw$a{ uK??YKbiHIT-r.!(9R[L{=-wk$_KB\PΊ:-Lƛ0uUBlQkƑ3ӻtQk~"}ugD)^.8Iae=cÙvπ.)/ R]?8%=6KW)8~gUj5ŋ;]@bGb -9 [w;a[ U-'l>iHdvM׃7L>~MŽ2vW6cabfBtN Jkv#JGy##¯wL)D~HIdJV2A%hԱE&PՋWoGmD:tI D- c_~[=_@2#$f#COh*u?v\k0/zƠ{˕|Xz_ Ž2VLg`;Wף}5ۇ@YMSK Jsi^N\:Qͩώܨ/xiIZ+eg[{Iv^;%x]Y{u\`4C =py :/41~zs*zw{y\5D&E1,wL|k(fnSx#/֊ނf|_1kLe1G$gL x(2Wφo JKz<6k~PmQR#?&mZtǖ1{4V6T!,q3ptr9E"!Uwtߥ=gzj#J<ڏ9">7gp gp8o?#!)Rδ!LMRd>KIvwU$fe9+8XgƃJU]If}/!Exnm'XћRejZ2fƠ 6P/l׌M(xuv ً'AdF&:TbC]tN{i.Aη] ?׮w ηT&2D&vO&nYVUETZb!*VԪCTԊL8!nLDtjdn>>|מ̙/SXT3u0{Kj:6'Vyᩇ9OrZ^ϱDzXί45ďr_fYn!6;ԟs3(Αl( 40oqAKMgEl˛qLxs%g=sj$?GS,džEĊ{Yui%?ϱ_}_BV?J xJr+r)P.^,ͦh&ڝ2HyVf&eXGk7Y[2jnϗdrb̔zU|lt)Wly,>xø7rAʹyI?;C1{/s.G?+) '~g/o*M.f>B*q>"s5{ck~Q}™OoQW"?kj5?(o[_Z% |-.'T<gSğ1x3A\%gk7dl_+~#;q_XS-w.bo?ֲH#i;ׅ϶{|vl8uy%)q 訳pUS"7Juzlj{rrt: nJVli' s_ƨDn1'>ZFg/@Ҋ6c{lgK ` |& X|#NGǖMq?pҳ's(~ GWH%N4̉%;%L]e estV9lg<-هCQ}/G=aUVW[rns4EqթڌμT?y37V-\u'b]x\ZL'i'Гj]uU WrwYIv~n*Z֋7ѰQu!6AVzMy:0e2#ģ܉v] @M[bG2hǢxWY؇Ey^bLI EW4b[! #xw40={ȗNfŒxn91ʦ<9VsT ؁鿷BiGͥLb9y*W㼭cft6]r-Wb},.ks J>ra}s 菇;9؜3q'cJvdSlG4(WʏXg$bk܊Oě]Uci >O@^&xy)V9=ɥ\l>Ɛ?k\7rrSxѝ#oF~ [6]|='7P4azٺi< D҄=hZtO>ce^{ 9bb$D;'h͇ċ0ؐ$\#b^ﰥɳn)1'ܘey>q2+bC|i9V9{gch)yGu3ћWo'fy0 7cJ|nFFodb'9 FBŵ8yzX+cϕэ75 R"y#]a2w,6onɋvrixBv@>Fv 3#.E3N܈E9:7]Z>~;%fHfs1eƖ4DZwK,J&r6r4.Uv;b5yR}7>13(fԅ1h~{%sr҈+)fAs4\hqFR{ <ךl2a%!]>knvNs'ۚq^SJ\..ih¸q46kdo}o1_ӢX=˳o!\}yxX[F{ԞgVm[˥?5Lu 5䵸zloLbyD͇sL#qoyZލN5';}P][7M7WMq%՚cc69?ws>9 .{r.љ{b;وa؂A, Tl^#. VXk*[Mt^FTmhGW>hs ˜33az]r[K|#c4ML'ѕ_ mjuc>9h>9f4'gױڎ9kXZErNM"ўh\}FWΌ䵘+^~ΉVmю-WXj<bc~A搳 ZM {SUN鯗X~ ,7DëS")y߼xMڧMQ[`^&N2N\]|B>"O~>"j,#Erc}6֘-˹wci\!_;)}SrV)ވqE Qc̎iJ4Yx]Ur2WS)x&nxĚJލŵ*cJl%>*e_Q*j%J͞;h".^(){8xlNnUp,O*Ff/7q+^bA=&ǪOyYƜ_s+ٜK!V(ӺKyQkk6|qñ6b0>Lq0r8{LL!fŽ p1%yS!VPv3xdih=l3ĩʣP|ԩ0dzF\2 b}.ԃ#zehlD.ćBw'D|֫聂u0Wq#R۬fuk#/>bZSѻN[WG)\N<-4juj]ug¶Ļh#Jc9NlzVb}ɤ):bB>-7nv]nBoloL5q5?xc:񁘟ksl}hʫu&ekΨq%^gg,Q 9iz,r<&|1$j|zkLb8Xq(pLnDEJb1TFˆ|7yRrƵ8GF뵲%f7qUiќMA N~ZM[,vs}X{_Nx.;^ck$i&|?N:CȞl [j/^wr9{B.p <`~ĺXo95irs+%[phbx+q9f+|ʋG⫑!>k 1k!Hlsby, ؙ?b7q4nmL"q&>:M䙼j \ʂǶxy'Ins}:)Dhb܌5:܆#{RŊ\|7I/.4HZ%˝қ9q$Ζݲǎrtm<',sp|{ebѺ rOkudy|6id{RǭؒxemI>n\#'X E ٗ|OGԷkE Zc]#F[sxu}4?3rg`E)-QSnۊ6|#Nb~a1XjF&s>cc8Es|-r81?}\P&f1-[%;r]D>'62|mf\^'zr)kEךGuNvPѼ} w|\דȷ ^$Ee@;1 bn8r\g99[buUbKvzDym^MuȏEy04?ZDqLh;u|0Epivbc (@gy/0x/0\D91b%^+j.ODwDKya̤ngLlSi's>x]љ3m{Y>|>>rG#8f"fS,u"vy^ʑ0|r9<أ#WaMVw/yjϏqr!.i&X$NmܒCNk>;lq 3mD-oq!WMus>/2Fb1h#LK"7ځ1wݹr+ _gE>ٱYLgN]]ȹWrCQWs#4Gw5Ǎ%3y9/Z&S(10łh1).Kvf5ysEw7|ijxovN}l ~u-EO;,̥9٬|b&rnUkm(R+ėl)GgjՈGubWlѨ십Jbv\ٮX)s}`}=EҦXSC^ՇO&2Jg1x ꗳCeq ^`i-zǼksyISsvxG9y VNJW,-z1]Jr&|e93[Cb|2/bZ]OlVxNs!OQoƳm9$Ƽs?&e9=[r,VrV*'8fiԮ "`Eyʜj|)7a&xRߑse8/ۺ3bFGguu%O.b--FjDgp;[T\?\]Ѥfӥ8`5jŴX\Y[U?8]or\Ib)>f#֖sd']VJBG=$wUW>z[b'OڕG\^ ZVRԟ3'F1SB&_T{tRs8ot|#^ǎR6\l[^,3ɣ1rV~%}as*̌_Z2Qcq  kӭr1g sC zNl]Wc~q O]<`>ۉy^,u=kN2fº<GMzJz_vxc,WxwvhrυhɳؐcA}'i4Frcr_s;ĭle! 9o7(f|LwZẴ #eķʸ gs +ݬs^M뉩0aA)7;X[| n뱹f+>cXsX8^벵!X ec+9\M|\Fmхo4Ms9 tXg\eڲM9f29Hκ^ `6eNđܞ28J< rISmCH^b6_12H Uۤ,z1jdgnۥ?bEuBIOKm=C_sztu+/{ijw)__Uskf[WOT?eYh.:bܟS%R &^qب-&/ףz9;RF.1{&֕GXS86?EN4&dkL!|ak~gVxD6C898^wlrL 'h9Kr+#q3yd"'{7=|5;Sr;6g!^J̏s9Bqp+:G|fR9g"<1.v@)r~N+uq4:ؐsir@k̫)k9"p,_ȞxXbi,),vW@Q/Ə:B-nbJ܎f:|Mltlbxs g\\":kܝK% u:쨃Զҟ7?7rF>y<\#NM)gc6򺹖KV`--Pw c1.G.>-|p$oE%z=xsiCAn՜߈ uA':=G.#bn5nٮ} 1sj5ȣ1K;KHܯ/O~Ҝ+TbZ|/l6S?3.sf/\yejEe{҈#Y:^5WxIK,3yPM'L>z&w1GW5ZFYL6[fQL}qaְ IFͧ9Ǹ ⩻14Mۮ}:5Ğz^6>-~g,c:c0z?/M?'~oJ_)N߲CZJq,S6_2?~#*:㷁+s]אs-831Ĭ@.9aKݛ0n_ȵ Ďa>y٘M31=x>l}yĈkzRGpVX>Lɭqv9ɹXPtMhL|G&6[PtdM8am- &6˲,[tbG9$~x,#_i8&l2q~Z4;vӦ]Q&%ϳ\Ås-_Ң;쌗;fSUGl5rqX-R-kBh%Z[#rW|3_eŭ|\%7ZlFܷ.~)5,eܸeCnknn91C5Lq)(Un%jS<2ܖ/s cHeV̊yȎxJ6;p? rq>ЕSr#g('18n?9ǽr)9u s}$?ŭ2[d6`ċQ083Rg%Y_r]tbI<.=\Ǔ|XD\q܃ǃz1` ?k<*v.J\J$k/C|3_+q:oyê|ٖ151oqαE6e606m^zp)?q~^ecj,%N@tbkz`81b}s7c3^ldwC,5h3bmGw׷x$e޺do-b{=UR)-u-qƗz5b+y7 t-%y1lcNbg|;\'C벑0Whd'^zℍ1&4󐚏s^`MIo;|n>q'^k܌уٟԸdX Gc*茙j܈y_AˌsyVx'Jp.Rۍ\k'VUsuˎ 9c۟վr+)Ζ1La|Ӊos Gbİ9Ky"ג's^|e5^\m<$:Bs-7Q_0{^ Q)Lj`'ĘiƇtiY}M~8aU~v ^<^7⊯ܧ6Cz$7DžBLeLˁ!h&xN gGG ֓b^"ت7r%zÔ/}'qUŖ|'V/#)7naUN}wK4h&fk"OX}Գa|~\X ə$rsNC8K`ΦFꋸQ]kx+ 2%Qn[Yi7Fľ*8xn#f׹*n]dk>%i^ΫvLj6|g&g'5VcZEv^߰,_XG9D6k񖘝[)*=ma=$gaj8mR?q$O+꩘VObZy6֑y(B,}φ5%q6&4h%grI=imsMEmgS[/<'5',%+I4+Jl5+cXZ/dLOImO(EN܏JUȤXeߒqXۿn1fRĽk/Co)&~?fy?=?x%LA߈eq&-oc찭N"'Eƣ\3W|nX37wHk/H#E?ok=/2_)b*SxwvBL8tvRԥ!6d@휅Gea+[ոnNɍqFbN\EDSJ>ϛyS0;o&Լq;be] P'gxP7%0#llʇxU:9Yٜq'SٞcT@ΎGMƸfSc'qWst/2#qs3'^E!TC+&8In4196ms3Z5xnq%;b=^`'XIj0Zz#QZ\9Cl+i L!7Blš>_t;A܌bC=X[w,)svָIR/@~ćXbrm.'a T%:>u|UbC#~ҪB.R͝\=mSc&^iP,sVF85՘osX<F YC.JEÖX49My55n~+/8-'7gɇ]0ne KaY}ě~5M"1I by7[vW#_Զ8E0qcy1l3ה8W"ԥy|GXn-[~6k`/vakM'Wi@#>jM\lPvb&1V^b4ۤF#8@ڬVewď8mfx8d-f%okir7g3֩ǴXq3M\`Ǽ{cA,Ո,'?UaE~Tױ+5l]|FK`KUbc f;kd^r\Ϗh*|3cXr lϨcf@~$f?^5(gGU=JR*>-%J6C%;ˎXč\JT禄aPݎzU1ٸ *9نĞC(i<%#vSTbFi8nL13;Ӑ_'s0v)㭒NxfJg5̏ p%v{RW+d Ԙ<=.+77h ˗Xy=vp<&kb;;9VZ& ؋]!/o-{unN#z5SN"OzshS75}1IP+b0oEG߰X!4y]|QN}>o6uĠ?ob ګ|U- colzqG_!oc[g6k4bBp ŷ%V旼۵-nLq"GcKsss-4AXOMt!̨ۉ٦Gbro/y8}ƛS#_qz«2qXͬ>kbb9ٛ6q&?iŜ|{i良p!_; l&oǶ7V!:r[X[߹M޳:.c1mz3{6D8#- pLt 4jAǑ8+Zfq0v rGvdّ\#ngbols"+1e_,©f:qXG_OhOr/Lŕaq^ys*..Qr.{]~l*MMhjbO {<屟pш.wU]K858C8s l.;cQdJOzUck|U|KqōSN9h+ˍj1+%o`K5w+Nُq:aVDz\K lXmr]܍J9_#vNt#˭dbU>sk'؜k$ɮl)(՝6 &=e9-n@sڈwE^r.%ƪX>$^|'y-nayG!+цx8y~$?~ 5h%vs0ףǸ` sM! xE>5q,s s^g31+/{b",1q :niܤ6Lj#DK~)XzcwXcV./>U%z=qT܏DlUS>"6y2Y1MK,ՆjCy͎ئ\ݹFͩ1]^RTS؞aO}UGjYzgmY8TVSeuxjb\ g/>̺ k#j\ɞzF՗UIO6֧j܎16؂><:r-̃ 7UrǛz;|N\09|tv4|2+~DOj8hvN{:rUN C?zsp9z zt p#VM-m능xg#إ|ٚ[M %>B=ȧq+O{ rO䢼La|R!2N).rG=E̝qzI'(#:w314\1=Xkx};uAtmȋL|t|@+9jG7RFY'M 38:nkg1[NMlr0ޣ57y2V5o7wN䇘8k+uS#V u:}J<ƻ9w:ښXc x0˱|]=`V#׹=^NrcXf"=Qou^N=ZymcY;0+  v9dV&v1B<~65-yfRI_"-v=5 ys47/Xq:f Ɣ:/zOʼn)|*b(kDŽ9k9P~5Yݦ5\ͧ+W84aA/W&p0wcl*5_xELʢ|n2y7-^nn|4Bnn24#yS%n}5E'#;%㰉Ӕp>q+r /(pxٚbϥMq".`8$w#Q۳`̋D[y%ŧ&?K3pM1=>#8Bٍͭo7ƈR_Kؙ3^M4WEyOŒxqڢxM q-,yXSs9ZhCcV (Osڄ%wSj6̦C3NbܧxgJ)Xbh`znȻ6cAN4┣ܛ{<@)/mvb[ c#4E\%>j'h"Ofr3ۈK015⺒y.F'ޛR>`Woy2<ʽ+Ƈ8FU+-)}JnWA.4)k-5%X_R'2%YK^փc%梉\˄_f(|/ߠuW|GMXґg25|#Yϭn9ϳq s;.xg0aXy9-z W&vjr{Gjwgy(']QrxMqxCчq/g''wP.4b>f/YUrSάo$e+%?;|x+1ڃKF"ǝ%7[:ďD i u9ldzmgKy<2gs=>[LƷ؞ɃSr- U#?Oo\DLej|wT,"'`a^&}e \{L|6w5je6sG_%[ZN}k"|ajF>.Uq9vኡ|M<r5>ʋ܅+sNczF6V@ޏ3Gp^lܼ_yG h!f+1Lg\mX6&1_qhf̉hyHL7뗄z9q>Xn&4@O9+m5.;0qLQ]nc#ٜO3|"ntJ7I4)A>/*՚rdsKֲNݮW9=#Lt\12Ȯ8ZP9i-Cu_r,n7/נݎ|L#^>85sb\u{ !gpv,w+cVJ-1L<1nb8:z*w خc=:K#>hpYFQm6QmAm%fdw Qo=y#֯Zm$Bp:qbE4 AĊ8B*N,,+!Hp!8ĉH22lĊs.'A8G /^/^|s&j@^z^lo(`V~Bأ_KMJu(N*4ffU&3@#]n9XA B97^}@X? UX#R][Hlj!?H1$*}v0FtB &c C=}D^dhRzfٛ$ؿO y$0溂 ωt+W'.C@#yy؏9'[3,Qzwbkx{ÌڈL%4}gQ̋P!RZ8wYs_I\|~ANh:j HQ@f0R"Fyz$>^pCٛ!d[4 UY!G#E \dzܭw x#E>) uM0 6o;UЮ OxCC4pP35ׁt68AF#$h(^3h| Q:~GaU[:a⏁{(3]MyFؠ>/T/׾ > EgAxYdءXE|Z[+9|ЩM jՇs*BqTz $c: B< tl y._Jgcp.B9i! Ar]* 6Pdt U큾KrR8T3 qTd#-k2 _i~~7F#j)nR ,+"иZt"\7E4 GW^r&m a,Cdįp7ht,7j j7#0WUL=xi>Sܥky|:hH߸ $r`8 .#J|\- A-R/A/,'-$DLψӯH }R]Df$Hve)fFtTq9%Z%灟m7e$,.xq7t>L學S`tzIBYNQ1~r"#0~Ь]~uk@hH3̽N-bHF?Iq^@ D9t mX~ʝXG (J%p% $h_if%8~ȍO`1r13\f\1@wrA6ל;BqTdA+Sqe "ЦQx)Ssp:+8 n)q9Lj!HjEie}OCp ]_Q4T7I P?,m]pH^|# 92'J։Ub,;];v=!|%FuSަ 4 Ր6ro$rϸ࡮ Tiqp !D%ktPn>2=s˗@+E-e~H%1S1/lPv zyQ S='ryH)z/{uk<fYX6lOr+;DweTi$/Lu5!G$qS BE䫿2OkOTH'ou"C{jS?5Cd9r>Q31v]lH7(ס8 oH"2B{>@׵sx1:ͪ'uv89 ӌ:tgz'YӤТ'K4۔?=d {`C9m+.8Dfx Iur.HiˁgI.rA+<I! pA30y|w& , Z 4.Ʌ!WF3bθ^PwDW?#E_R-sXfMAMa~Oc'ܭ/Qy@XG;5cV5:ѷ7ebh4VS <9^eEN\s22 ^8@Eo}2p)[<oC_ASB)"n(}t?P}59]E.E,ו`C/A}̻i(P2$?Jv7ă/xW}AhuP/y@Yg>@A9Z5) ~p53蛎 dPn6,9eBHv t T ~)qYh7A {4w)@q s!U!Xvjo5c3@UZuD@ -ͫRx^b%}y>R-h_{ƨ$H.(0C=S(SS9]*sWYUhn<-:bnebN4nw~;EyhܣT6,~3O( pRg \_Uڧ5N/7)XYWߙBB8ccW*ljy)P&5N78 |q@" Onr:y m+r?kPew)sୖ4 Z MS^<:rMk#[s Xc_@G 3sۛ91,Mbep q=hҐA=l }9IID`MwU|4^ j N!pN]ƙx@V1k!;N,^> O6#~ |uiVy`G=gV& ~ו/̿zN&W)ՓBlULqey$b`9f!V8OoJv;p8p!~&A!e!k %ʁBp '| bR घ/7kE&]B; k T=_w3F灶6Ъ =.67#@)x{P k|zÁ ]Ro'Q da 6 ަMO6ЂCpKOiZ/WR^} W2nuPׯZS`ï`NN e?@N;='ff|[P7$8%8/1辏< bƹ%/} ]4P2TOWԪ%i8Sb|g7OyX<8韱b 5  C^}B+0+]v}Q j8s5^lS5'^9!qKK-@IeLmҴ ӕ$#D.n($-~ibґ3H$A< ,"'˹OOT[^ | 㝖ef9"t;(fHQI#:O Zu$hQ?'rN<8-6 $x>i $|wZ$ԇ̹dSA )3k$.O9p"igR[{3O?'7@;P'$W/| Hr 3K)w_ϹtsO/7RԈ+?FԎ[ 3DgumBlE S?_#5MӠBc=0nQť e H$S_`xwc`$ ϿnO_ j'ui :6Hb%z |[-."Z[~T)_@R!~7VMqJvl'赏zIxF45DB 6][PкRIDwf xJ~( g^8sRNA%m(rUlm5`?)gL M"[GR|WMdk2:)j'w>`_п|w9 9 $B{ Dj}B3k^zq /׀z'b\7w9#jku [sN4*iܡԧ{zs@k`%NQ,ďvWn u7d'_n?c_^[_+ T h(rO=9! yȡ:`,ԃ#|VZUOPc+H?]i䇇BGYPjx]eW*:θPlX+I h0 tYh $(d+ ea%a}<JhYi-xVo0 j@Mc(kwiQ;8]dr ۠/G4O'P;^Smz lSk԰tL|wi?-:+/-tPk,+Р6wT PܧOiUZ Hc*t(+_S#w~rO3W{xXCRjj38Ʃ* np4A{qC SL^{,574 l򍷠Fyxs'ء('V[΢GJesO(gO |wTBW=+/ *SbMϽKM/y =A8&ƕpjSk L2:Qx> Hb] =^ \gApg!S`.m3H1ioRڈǔHhxt7t=&'tIpTE 8Q'Q(]NJ|[?,a OСЂHR69%e34 ~O"<z5$+pꄄ/B_<z17邸Rwti0 WGNw~]8uN1((<7C 3)4> I7{c)?c!vA!7 y%qw4cHŤKOVhHaTCL;^5uGBr_cZo  U5 \cW3Ho~ǖ'WqPz7t(?$P8J)W=>5x]s~ #DLgOgrt8\+;=(fBbu>tpT=r19k,$.MCx_3^ރ6  Sϔ_h:}f$# G`A2g5i"8m|17?7NW7lj>j}7c,2U'ոմ*h=߽Ϳw%ɡvN/IUI\'#5=mHro9~'\F ~ :9LFXU^+}u4P.I=)%$y RL-L-E@k>hˑ<84* d\# @afXwzHu_(c, {}f3zc`L ~) c^}//X`$;oj@ i;42A$]w&RGb* PFSL hqA!jO="*eW.WqOD衚#pt\Ct+wY#2ǠyA8!H4i.tg|'LǏ$SO$^i5!}m;я4c3y$P ʎa8W*YI 6z:ڥ1.^_Us [kՠvau6]zDIRM~XHK=VZcnq>x6]%e Ńŧ.*C2wF<>1 X&Ch&)>_^_^|LjYY1 7<Ac5 GlB 0 :r-%!gr]LJ 3N+pFoxQw@_DcPTB^h) DC5r~Y3yOZ7P+Zr 56Bd_ t685W&J|r3ϴ S: A5ou\c^`B|;SY,w`?Ψ@c&8m^`xhP$ z4ՠxڅ,{3ITԧ" Ьwe\ 0 ^N;0*2 Zt+}. ~iP#xs .2x}dsR(]wq/ :\\s[Ĺ؈7 @fl&*8b|/^N`']4 |3wHAQ'z7D{2ءS>B]j tjNH;ϡoDY' ك*/\xx)\Э>* T:"g r\.!R410K"J)EbQw PDj:Sg:%rH0Gpve>28M=b$tNJ-zPSu3o{RʜF ة`9TGAO ^% e|Zn灳ݐ!˪!J ?12Y'u.Gd'n{$I/pK$G NC0C=Q#ꡚ@'aS|Ԕ @ 1IB%C!J' n~$T>"ֹT*׀F$.|K7xnU t%aXPѳ zAʉWe: #=(BGG H P*2 = a[G߻5?N\(NAT@SnMsWZB?Lx|OAsJsW"xq',npq u?x\ m%4ټA o͘N3mO 5>gW!λU kby(V~Z}mutM=1*Z\Z՚&L@xE?,YIENDB`Carla-2.1/resources/bitmaps/background_calf_black.png000066400000000000000000002033771364475620200230420ustar00rootroot00000000000000PNG  IHDRp pHYs  tIME iKIDATxԽے:- JΜ{^}fE R5Qi+^/YDDeٔ^/Iye>ֻsn߽kR)ERJϢ2|k^#y_)i>ϳ,R?A)S~Vq@0Z;sL{+\Le-EY"<wE%$<:*8,KS+~x2a<|>egsk̿{")^yB΋L~yڴ~.e{3kY &hykMR¹)5y|xdK n ^Y%M(y_?})j'ڰQTeJ鲐d S:0KA$"=idZb]ײw?.6/s{{ʊ#E7۝ƣ@<+`JIy U3s{`ϥssNx=!2.ei}Z?f^ 2L>zγw#d#jߧh:f'Zzɬ 4Iy^3s7>ùYu*,RDJZGf,eM1g 8RQ~ZE^Yj{ezee=G8W<>(re) Ʈ@UUNz<ң}g>Y/ĂecEםI{$$GJ@.(kk뫺w|VI|Tq۽Lxz H8-ԞD}<[ó5k߰AZEӼg>?%WQO! mooR={^M5C]yn7ZY}yYd~K"eS9W5p'IRdukխZحmk"/޻aLӶ^$fPʥWaK\a^4}ע|l] GXi䵼NY'׶gVԠ=VDc JRsbcl.Bx9r3b5yR{qwtf#BZ"!۳Yճg qZuYpnȣB姘ŶG84RrZEJ"YH`9:eYgE-t}:Ssy?voiqnh9RYܲ[2׼{ﺓ >(ċjyUW؁z5J,a |,yY=g0Su9ߋ,2˅Jq3{ z4jZo"(g>Y4` 5s5mfT< ͣ;Z&=lo=7)UM{W4W38%}g!"j2[]*"-3Zm6d!En+{JeiR8JzaG-Hɹ,JUS?G͐?-#t (b8Y6mЂ}>~G랟PQ:A=k61cՆsV!5rd; oh}_WR) #64'*VǶ;w2U5uٰF#vFF㵬~<+g ;hyFeE[Z~,Y-ah(ח,k}٣C6,Yیtd=~+*mD2a *#to+޴-X{2{=iVGٱ_Y$yP@qRz^$-jLb!%Y2Pū< k8h:QgiN2Yc^sA1$FxtVC_ZA45,+Z׬אsiJwW r\j4n}@̞m=Ⲕ@y ٰ9Vs-c:{Eopp->Q0^ vq[DKWH |p~aZ> HB ߳FqxMߏZgZ:MU&İ|m-"ޝxzo\MdyІ^>2k@ٕTqXsu'SJUȫu)iR*\oV%+=PID=18xx)v*4ύ#472XV3VQXD?`y/7a;,4^y;NvbOmGa' #\?6ȝnc&q 5\h%ACoPiM93w?Ha̦%hEAVF=OSڴB3f#3g"bu9o[[/ 9Nrhy&m>95 &ӏQ-tij7jUH˥˚ZehT5z aVϪaZ{va9ѳ0qQ]cOsol}_QʂsE *>g;c<{;2C8- z Ŵʜ xǭ?B L(q%SXșHOP\NwsE W0]bbAe>}VE qGV-ްϬ=\HEAI&Y^,I~@,izk7dV]F߹$X'+Au4O]ϊ.x}{}zS4W[Fs4}[Vq-kɻ 29*#tFp#y{oiާvY{`/x"߮b=A p$,>D{ϱD<0}n ;s0#xX#1iT.P,dž Y}Y0޵l$MT"Ȍ)Oy޹3%.2ekqƪ4@gQ9AZ~ѫǨۦL׿H4ijluSbA8BԛHѣ(ᙖ RH 9ھU0_UK \z6gl ЙsњNj1ܞQIV2pM F 8V]\WvU+O멼S6g+Բ|r"7 ˖'ZiTs}6s&]WKk.泈4O9vTJzi_θjߥHb^z*y5uI ϼÃdA?}('(Ne١Bu J r -$*MӴP3~Sjo:Ю5[ FҌD4~@wE0ֳ4IoAb,s.4dYS8s$3jwFmY?EszOJeGZu+2,___`YEQ^@HA)E֠|g7ZKr)=lu̳KQ1ƏlItHA{4n; Ļƛ' rjZe.M$r}2WXDRDdiwju\ ~C?Uʂl݃Rqb{-\9CxyiB#d(::G.pkTc?'n퟈4B~D1fz(f6A02빶ؕs1O\y"ޯmY"RQX^4{wz -7Ћxǹm( B" '#݁^_w mFDlC+x!!4Y0R@-V4F;#X)#k=7q 2E6 xs37jÆ]$"M7gu៙eͳyzF%l#^;KɑR3rMJ+WoD "ZG<.KW繮 {[ ^Ys̘Am8 <,N-pzZ%ᘡ{@>hCQrd$B)GZ=V\,9Y܅r _Dg߈Q{unOP>ޔu*Nd,V/3ܳFYؙ^ 5> 8j"nH 1[wnlg։\}T^ `Ĭ`h"|x6sxPj# M8X-+EQYSH}]@xppq pD9ދ}lxZM2ƲpFn #o1+HH"wnGѢHO_nmY\N"˙ G13y}vm}0(ٕ=?K>Sೖe˲d=O߭VزjZp9æYa؏˹lJ1\qal۱X>NFan?_ 4BEZϠ6ZeI=1/{^K󣩫 yף^")>!z', GW~"v'B-Z'-f?c41>KGpEY.Q|S關M'lw ˴~ [P=ol#a5:.˴>e*lz*āQz^2,RJDkFx&,KD:&2Uo?#1zcN)eFpogQe^ }_cd%9u6tGyVJ\M\?M1ny{/xy /OR%Iz&D}:5{m7joBX?Oz|x_`nzS0ˇq*O!"a~qeaZ/=XijMu0B:3h "kψ"is-ܓ$Yd,Jj.mW\(GB8ГRdfh}wg tHnݤ^ \Q1ϱnyyekCFHߧt_KvKry 4 [QyV~}^[vG[@rydAZUN>5jtZ+c\хJg̍34I.k.j]v,4 d^TUݘ"fwYrxM8+6])>4*CH ?8^!M#B- כYɏ7wb}+doF3CCsJu]syJT/ȟ1e!ɘr<9|/燔LzR#9%7(`rǣL{\f`Pf `zTJ< tNR6>\=!uфop=ͣd }~:w3#7 B/FIdZcK G{ /A|o4WsbB9K–_ [tYZ}wE@4 [Q/oKo ]Ԥ +&jLrWV@,g@fi/PM:~A8O"~h`1=J;'zұǣFw%̌x>! K8J[prE3锺PQR\hj;x35b2-7St܆~Wԅg +qs~mL >^['u-:'s! κ';|W!<"y=#{tg"Mz OIX;3tgXNްh0Ǔwg_sAk4cW]E .˟OI`֍0 FVI|Ȏ"%ɀI`b}"„;oc~n*6{EyI-c,2:j=DlbHR`_H7i'\LU鳜%g07'*Y5{8(緩ð(]Q^<1$JmR2kx;#É~"G;F1ahs[+-&OH t&cFzgY"| Mդ7KD' E a9 kMEokyAO& V9 /JmIb\Ӊ4nW\Z=WԢ5+zBa/g6s*vIeO/M7Ã󦗸ۂq=}Xc*#&P-X߶܂o,|$-dDDn|?2B\ o6f]ھ3d<i{В}׿5 LZ[=0u,}ߓYJY̿w%cP@!6iz5 f`4rp4ΌPIL1sѱS!"7O;G'J)5Smr75u@ڛvrXÍJ2{J}TRl0=pΤoY,}^/XF^SpnOXrQxκL+ ;. z{h{Prw>XV͞_ߟzwJ+乣{X-Tdت(@n[98[0YKwW Kr[ދc'g"O4~n;NU>Bt:|6o/tpƺgo0p?J APZ4J6\+[n\1}w 9f磛@`q%Ѧ5 Ϲd15zG_isy;}[۵yÆZZH(xm!?h:kDo0`H ]ReJ .7Low5 ^3m_R벷#Su|vk~5wbX l9'hU$ָccma_=@"9d&?k+B4I^?KpzO+ڋmM9(&΃>x#GG̵^y6yQ|=e%~nbjćQG#&ilu|Ql>?0p1@--}9g5e0GڽQ۽Ւ +$mܳhS"DҜ]dYi{%^xw:)RTP*[]AaHL0߲9I+$GVau/ژ-%O^2|j#quֹط=| ;i}kc":_ Nソ阬@:~QѲpUsO; Һ!L)œ?ujǗ<_&)CJ"r8-9VFD2L>]_̀h(|.&HX깮X-[M8jkwFE"rV&.E6$F)ĵØYn{ݨr,LXW`oV67Qǒu x E v9z!|r+c8 ]XjJIf %QɌc [X,k9#|+yL| '}4mc $bmnWcgՏ֭(ߕ!])@yeՐnN(y4ͫK$GC$tZ<~>#XF/m!?wkA[Mv`~V]Kgy}FV \>='R U)x8ݽ?:eg= DS5tWWaJ-.*,mEYCz^o~8,RXeGKs4jM3=gRZG٢$"2$i>LZ&Ka WS黥daR{vžC$j50-r%3~~>&okjy30\F>s;6jJgn\;Ne[uos's"G~GKDyf͗KLo{'prO9?ۃUFm:+ia#F{ml'귶G1*ֈ1Uۨ@\vїR8#VZZ-*(Xs/{H DT˪ x8yF]s22x}QH8_#!4Э路zb<ύ,FB[Zh5"yRO6SqE v1P>+5sgϱhϳ ~DS*5{H)ei뇚+$zw^x wѝKԳSXQV*Jgᗬ4 gqZ<~e Ub?#nx#{d׆[bʦe /%UF e#Rrߚdm-f, Ogi}|Yq\h^T>8]xΦ^H;iAIm KۊQF%1"ˍruINqȯdz((SɴE?ZMǐ~' y{?K6 LUQJbog40sn""HY 攒|}}57$ZFTlوxX& em1O ='\1m)N ִ굱d Z"wtdtJT7a$,i"=k?)(O=kWJ_{Ǣ?|աqhna`簦e'֤Át mWalXV֒C;b@>קR ˮCͽO_0/ 0#4^ 3O8,[za|6YpɹN),4K[d"Y)/+{=,JhEޙ^UmlqC>rj mL 6K ڝrev{@E{.۬ \xeO0/Yo'~dǣ`i VQfz}Mfvu=wB; -2ᵞb JDeW:l[Ϙ"iSz80߆>>{B'4u,ƁR (oG$EzM^_xV\&(kM۹̎!:H,ugum=x(t;dYyF~ _ ":XH9Ku0^NDd~̲3 #dEz /t:\DqߕvDmdn{ XA${)eF1mʈuWP-ȼq7*W,宴gzGQ`/cצy${ ݻLDh!,aL7j#Y.͖K܂D0dsz49| Dߍ^S:DwL~]ܢEΰwKyBG>z$yA TMꓳdy<=bphՏ6{wT %cǺW;AƯK(?A#X"/ۢVm|-~oxw*\dOd)'ͅη'J"AOAz#5L>+?[no???W{^o~SZeCVELuCZs_4z盧Xq6J TYSjXXuAkVFN12vl~;fy+ݟo 19MlE18M# 0*U[LNg8<_=l:YcWZF,["rWB<[G?maF̣Gg;E|皯P`k좵`F٠ziv,OY ȂPzX Og=H>s]VhY£]{ƀI"-$Z?m MF-_lt1[:`i3~ӬMxo/A(@>IVnKN%l ڨmxMRu Lk&qLfEeT8#yϵiw;j`2bhgI2׫ZkE`MWM3ZC(9la͉Q>)Y{~ޑ\j*gE3<%ivXLd9}}8Md.|FlV_38:3"LǗQeE]^[H(^)-o~5^Hl++a`X)j;ZMZ4`?)UAs+}QL =-VFRJڪm)yV0uskp wn35~"CX%.L/zH}a^pRxx zi۪N0CWc\/ g } ԺP9mȽ_L[c>,TT k\ _Wr -cw$|TʥMP~X#&cZ8z2MӚ2:Ŕr?w͋j^"bȔ/S=Bh@`S/yP)XmCy^#2`^L]$cmk^;ŹG;e)a|5=KZ ͞ץ81>#$G7Z;GA,G)M , \V(&= )mGe?*>@f6edc%oZ-?5 в%'I}%;#{0[t'«e]^<ճ&fϑ~=;,L#ʪ~HPZ\,o(#mnfpp5"N(K>\{R$ǹkӺ,㘗V36ޓB'xuN7syN:)d)G(O)5Vk7l2p+Rzy;ߐ7Ӵ 1E<ZXypp^:,/"Q&t>8:6B#' M<;r:G#țkaYeY`n.nFU<ˬgs(8;FNpzt0yH˒;ƚ.xkyQcoLhm{T3g0e=+%E LɁԶ #D8=E 9Y蒔 3TNJ s"\VFV(hCMBKRerG@*/MdY--C"z5nB|e1On)Zt0u=R7 4-xc\徳pimgl|Ϻc}4KWJj]?3xoYn =l5,iJ } g N75Bg0 ߚ\<+(vդS)BWke28D)mkcSDn[优cw(gf_!6l (,___|x3*?Gk _H-%BCzbzRpw\圏_ 8ΚCN ,IƮrߣAso QscMPPbte4 nXEd.3Zh 3äʮoL9b"&uo|.|N"k2ڄG#JJ*#e,V^i$ͳK!R<Ȼu,w/7v#gzcnF @Ov1jγBES7XB AR,aF<2[)J;9/N$Kp a5?AIv<_5x-tcǟ 2w NbLRj&ߦAFn-{d,kYdu11ɲC,W1k|nW.̼cei/sZ_, a%h᯼u?3ĔS9è,hSJ_a7{!0n = }\kGekC +G~h=H\gw{m;{> Yx0^Lq nyd?PXYbi -Jgԡp&Ez0sn@q[ˆ.G^nĈop;蟑~DAO 7 K{W⤸&$sMǨ<+ZNg6%a ؍{Y`ҨB4ݯ:!mk,pnYvW9q[kPOMFŮW W(![Wțvφc0­c㶌 Z[dB32~&BO94c r# 8ʜ+o!4QoQu{Q}Gx@+*@֔(`sj35E]0SL^;&>Cz 3psƽQE 6JQ*"uWu`A!ؽeiݿvŎW%fD`&Զ3z͏!Jwx{G՟O%JUuJzwkCD񽨞ѾpxJ-S3: ay z'W[C{7^=oj{# ,???lix<~ {ܢX6+F/qJH>H֑PTCGI -u ׫ 06Nd:Iz.jVzugX0Psܖؿ5ڰzZ'=c(nz U\Y`n^g:Nb (EWi@uWϒ+,54_~Sw/Y As"[,,Յ;m ]70~uNP6=?;6Y1N y% 9r fA:*[rU8QTݛWVFegu#0MME2Yv0'^ʓA(Cޡ[@OOeYҋ\Cp~ľ+ o{eZ ,!l}[L[8N1)/ vP"l?KeYĹ}4N?gHü~/F%6QrM@~ z2ZrϷxipAP^deykw~22NkmPg0^݇ATxr`y<% aUah:qX[dYx~DD{Mҹ35Gy [^auZhW}j^(*%KJ{+zj[[mp=:SSW O `c``]Pdnu2wz)/w4݌cF=oXnKpD2]YQ1%DzQ6"Xq/'5Q6E/%DudY8Rc!^Uzzc[$YZŇzS$4F8!Md9&+I!;0s<& -A֊VbWEHUDȲdyHE^8='wf~$QʣP8Z1EJZXsIۇn Mq<6=$ 5FZ&y )^ws<=1.x42 Ub֛ kO-\>*fkh:'>=, Y-&!ϝ{D&D+D~<Ƿ~L@dP>g3J‹˿s7d AnPϪ6p@)TH-]<&Q٣3)[wf|lu MdU _Rxتse@ʮ!.1oR˲ {J K^밞Ѫgs"W= TGm "s||%ٲRӊN "GkxHNYA y'xN ڼw)Ws#h@.TI,_=')بa~{ ߲`)p\=gu{) oIyڂC \Nln9%YJ/y=; d>A n&"L&rDg4w"y;z?\߰X7'O3i:[QG^[R/F"aw^OO٢!_>nk 8NfQDֻRrOR";"w˂wdIi9HWώrt/RɁRy~\#,4yij<7RIi?v佟ȗޱ/< SOy}ܻ9XOr ZTF! DMP48f wu!W[c>ˑ踞o` lS;d{ gv) 2 I[}}g|Vۅ Wx6xoC#X~voL8 ڠ( FQꔦڂnT/V[BLhNU5ZNQAw-HݏC>-k yΈhWpvkЙg.aީS"y߲,lB_OS.եwn9@H=5OxAQ,1M2v]## bx?2yc=w"F/E|$';examm~ܦ;'rEbW) :s8oG,΢e1hFre5cYJ 2Em 6ڧWHzlP4X_I5%ޏ~^zO^։靠 k?45KkZ"Ҟ?s>o)~yVHzDwq.aG,=L5AȾvϲ魅1?m cҳPa{Z29+=Ⱥ7gLb9|V: !bQ^N~TΰHgе[ [E|fQ Rgʺ򻥅y<7.9Q i6[#B\c c x޸'zo=/~?W>cmZKw#~URdl@ƸJo\ th!wa*D0&՛JVRnOkFk`%6ӥ|u L2=ZK)պn["8f|>k)\:}}}:Q9QD-jT,gQ@A559z1.!{'P=5y ȼ{Zx#} -){.,3|~/EU?ϮjιQz>,\)%l0%_Y?3Oim~4GDnFNS3)zw*h]g`)V@ߕaKU ݙuB q% ~;Y$ýz<% ѽ ma>-w]cwՀJ*%kg*FHUce@=ƅ}FI\JYԍaYf+ϧ5폷Qx69@*Qir`ֻ;pcsqTdD4G^I^|25w (vp P8X8hU;¹8| !ݠ񯗶 ,㱮Z' ?Bىc٨F0[F'Z,/+SBkV<)F?/=A-'m =׽|):zV}:M7 v`[Z$2ZOhۆ|(ecpDb3>eY}QxjI=WU 1}.݆-_,, Gr*,Uгmt86^.ȡAVpGw` g#=naD} Ӂ"#'-}*i]ks4ht4~70|^ d登kc;\Yz _ē0ʳɞ9Tzt-p N)nlwa4FY2Ww^e`k=)}+yά87[pg>+Ul"AAQBi)nSj5`^׺U?FzeyQZlD.+sYm:3m~ {Ĺ>zguˎ[zTv;czXg@Q xۄm— $J<2ҪZ+4dJ)T\wZz`a;râ+.bns%d೑ F'?/mt*9{Z,<}i0FEġ"ƂFagq0bZyO dYQHN4N "K)$sݣAet~|yX kg~ߤ?w:u.Q7҈KD4!D8D<3ƺ+YGbN@0Ǘ۬"puq²֣ 5Lc"14<~Vzm\f4UaC"GkczG˽S@/1mx5>e wa/̝  dm.[|6,|_E!/@@NM4yny__MwfB:Cv<*1NJJ89/:ʨg%gec+7bѽn`&"824~ oF>Im0~P9u ˿4>ۙ0 f;@y>o-[p,ރc  #0y&Ii2V,+5(ͯij9oougs׽Jzm{f<o)9ke܁s,Ö5E/>| !~?km=*_՗w7J#YOpSèYV inA%.#+z$p[YX>ee`?/LJyg{>C ]⟀(J;̞<nܾ*Z*s;-(D4r=,4lbot@)/PmND7^@Ϻp6jpe)%Srf'VsdzU~~ڽ⑮2ugy✍6^ YSDGy5#K:&seBpmMmJ,=h\VSN1EMU oQ~]pBOqnV8pXx$f&]}Wcy饰6+c1{d뽃OYeeY #Vo e1sWE,VGסG̫@ӗ}lq=|*W+d=y<eyFߡ՛ϰui3$z~DX-M -31@-sJBW&z秥+0SO`au0wϓA+6T۴%cΞ`yC ,VzD޳㜂t䵕}:?\T@^$xKaRh+$0')ѻW,;# bע5΂o!p yS 7j pLJ?c#yJe)]= 0%Ҏv޳ l~dvqM퓷x'77qyL'XGDr%ZQaVd̂3 s効oSAFߍD^⹍xT22:7ϡN OĦ)s|\}qU{[s};/3Ͳ+=ZFYBxGb8j' LM#$^,M9ez}YנwfnHX@͚֚V-'N8~Dz񐟟yhԂQ삍py!k%OzsYGDnRRZBJD[)eN!$Zp~ըG{ B5C/24o;+FGƅ&QԅoiN4,}-3mkFBd9Ywarm/=~njŃ7;^.H,N}W#=yXLď-^nG4o]CQ@Vjszy-9 e7[ ]@XoHQV"yVoEDҪy^ۺYxROh)1,Yr^df74;R5 a=~tvlDH< 8q@YS ]8q<h~m {Je4S.A﹓%ȜEN3ڨ,'bter@Q$5M^%zTRv\3Y9m^.dBL4cXZ`0[h;p<~  +. #RTbL=g=}g\^7!JjZmrHI %;z&9{"aJY:",:;?S\zjAhќy1ۋb PaP/Gy۬71֑;D#{t (cq7^. 5@ZmSD4вAStFI{w6=Lqk `GȦRp:/ ۇcl=׬jtuԿ8iVOt%8d͵ R2Qpr(3Ud`A[,{Ԙ.e̕VO-Z tpmeCI#;OPgV-}o+E4:Kg3ZgtpduRf׶fK{z?\,B~Z{g o zZ#b_/>8oӫ $EҜ,E؂lJ4"77dk|]r#t︙G3l]ck( ,e͵;nW7qW$idnF;k0>@l DHFQߝZh@i֋fpg pƆgD<ޅ6[x,yL zjߍ$$#6_z4hTIgHǩ%BJsꈱxMy[(-Eͳ}# u0/A=*V|#n=lHkV~l@l2ϓ^x|v,BG1l?y]-sdE:0wN.2Z ·,n^[(rɻKk0Z:I5/IDhfYb^ÿHK^Ꙫ`s}m|* hu-j2dyu#5f5W`\6ZJ2;N{}aycYDoDsx4BHeGۼXVՔ/JUś^6+kj4&zǗکj"afru qGǨLV94,:3} m2%+c4dO݁Y+33 ` Asq?DZauLc {DzPf!&Lng5\=ts^g+eJI&K}6-f!"ڠ3 -w3C7LwtB55/%F)Y9˝5$`.qyGMMߑIHߕna|Z ta{ ]5_\ܑLg^g`x.Y4@qO^hGs<|/-y>o$hxO4JS\qT˥Unvq{CkGiр_ifMo*ƹfUFk̀A*XK{ַ^#m)=-~Dd+g$, ~EW;S:p=Bγ`Fo`) .$Ikdd1\^M2Yszy ,/q#a;K!tA454`6&Y&Ǯ6!MI+Ww(w"r=zt9g`]Ǚwezp.sn m=9:=^UPGe`/Ǔ ʎJM#)ˊʸoڰ>j ~k^>Q ^{G"r2u.Zr*VC>dCp Bu)3=`]<;!"kE<#a3"yQıde`DrY.KSw̵(6Y"Js/=yu:CaOPtd4nz_+qb% }P[".=W&b7ts;RJ %#$x=(Gqb]kWKmk~yP8>}i͓eYVKco-X[v@ϲ `AOQ>O{|F I"'e1(Ÿ @ypYVT x6/"Ed~̲ⳅVH [ѓ8N=8!=BFE׫YsQ< uNܓF={iD#襽Q+eD2{/dB=hzt?ݢҕ8P3`t1׌oCgL28Cuwmv$2vw.L"R(En_]TIB76Bt]ő񠶖u}ڕ2ٱ,׃ x.Xfng"S6!oM?:v)M!Ki.",2};#iO ۂM\r[.i#<$g+pW/V'|Bo udǔ%Zꆱ֭>mSs Fbao>MGal-O ox'z"X]FB"Q23w$HZP˨ [#;oZ<,z>euv]7A/ ~K8:rւKcn1:3w_3o`s{yw 'hY̳2U-o*YVP*=쥂W!Q&]n`HP8 +Xk= =8ݖ^ -k=`&r[/ n˲ u%ߏ捚4jx`D gھqvwo<7]^Xo>]Ә,[hrjțS<>"ҁ=;Y.9&qG{;}ie/d777ϐvƏRDVg4wuJ%Tx<Wgy^ڧQwXG45gz`TzEY߫*kؗdm;A`u(qG-c|>C iNwOv573ceF;΀㭨YM֤VJ7+=^/K- Z-k"m$dܞ@^SAɑ֮)optE*$38wI)/&=PxIH0Ch0y.bp!OA*YgoWq?O 1õl???"1a t]Z8% L&gF >@$ͳ9zq8;7y?ꢴ t.Eu^^.`<0?ȚwEއt˕|' ^jzi5g*qd9)gV@h Gc} tO}:Jɚ_l]lgyK,gƜQ8qhֺ(xw< w[˪u c,`Y #opIZwi$/ 'S"B!u$\/A>9 O`UM ֥Iub;g{޽٩KWո힫򮟷FY5EV UdWCDzA,w‡{ѣNQFַEz{/xFv,=GpͳY)G}2Xֿ^/h4}wߙs>Psǖ1:§ln %xг|y"Kk!؜z L1xVѾ % vܳ,۠Yj9:#K6M)=ynR;R\x>]̖@B#E7)3k.uCP=(\/h-x0lW7?[XQŧs{Y'h|=ڳ[VTzݛ: c-yμNA4nj@ȖS~<\v3ȟx ~]ԶhT[V+YA yyO&{`y^mP8{g>\5\'~ExSMwuȼkÄƦZe6GBH b>c3C}&I"ժ7҇dY>y"Ͳ' E[Cwa!K=E' Yxc3^2_[yY}___ɴ n?8uz{}Ď@MX(7)eK׿sH{)reZd\7|Ϩ 7Y{M_D/xW^XMhm3ʠ<?* kT) xQ۬G>D$R룤J:瞥pO`}2#` m XGMwU(+3@˕ɗmY-w F8o?yA`DHi4,9Wl30jGݽzxc]1<ïz Q+lBtp?o"kKQrGRXWsYXUG\ eჭ>&>J&kg}0I)>QĈkBE? u90rą˝8=8z @ZEd(uH}{跬jo#.QoUwM\7W+s(H9U`^tiW93?[6:94MGk Al8 mEb,OXMʷ^?pnϕ$ԋtr{ PjšFO$\9C'Fԭ66rz+LR ;gި' W1BOO\?-aE)uyF/gyqHg9֐r٫kRdƣDCQySlT1N,Q!g Re<Wx{>zQh+UX?;G;s7XztY[Qz"^_q /2MVFLV(.4le':jvǟ2צ( Cjcx""_*Z0q}q|Pص_B1jٲ,h*,G-V Ef21oJܫle|>nYm>#@'"aɋ28&ES8^<-(G,Y^Hj(M 4'^pkV$QApgXߙᾏF yGFERl080殄Y >h$4z |cz;1r}8 7Z̑֘`e'w ly߷M&58i[Og?\F_ޚa*B bGd'|QwK筞> }zHb-TZ s#[}X@> \B"RmjfLsX?H|';CVYɿݑEֈC+k"hbL0- }}}5vHXu+)M*<Qwt5لrz}ҨQ8Q,@E DN%^7]|kxE#iΒ%dXќ8c.\mf%Mvg  mxe=-dBx \o_9a?EVs~ dYG &) pD1]hWds_m"^zgEF~T9g 9/?d5L Nr][xȟ;#r#ԼHF|NHD-kJقߕ<4 k%I)$e')Mc8yЀE敔C:ksJQζ; 紥䈬' eŇePR5YilYlhYPJ8Z<s,sm?ԆwgYd"3|3쁜Y =`w4disl67r$ckf7KojZ<ԜH#̓h 쿣_}S'$iKgǼȭtVV`g]"-65+9+g rsATT(rY>KWRqCwXGZW_g몄VֽZ]+הdY(`ޡ,Iy@l/ F|ٹY{%⳼Ńʛ˟ٝqG !+pD>AV%) Y֍7=];]SNT'"JfSA!;;j۝Kg:\sYEu=+d?ɲzę.wFWU>s'Z9M2>? _3xŰt{{0+Sz:V.PuS`YlNa͵ouXg hAp8^4 hb ]ÿE4V0譴%K*YX &`LTpMy MR^=N\(xۆ^a=ƙ%FqQ^u`Qa:ԓLĿEsDeͽ{Ax",AXV:ՇFQ hW@󺕺{i_g~Fvx,\^T+wvd2Gy_5FLi"f9kpP{l߭yzlEq$8S yọ+(h3ӋKPca9r'6nZC)U}ۉ;VEey5QTbYl W@fYZZnd10͢;Ovhv:/W*|lҺZRv{4g\c!FlrX4M:O NJCb@3 p;ɋ owDߍs_s&KuДj)g1nO&daM\"m Ըsx q*X01M^[1+Di@)FV^n"9kk*DxlOk#^_/R{­ xUsO8j,RN|,Y9S/HyKu.5Zι)#RKS"X]4zD]!vn+jk%hyqz@U-ؕ.R>s]2y 6tegFYς.ˬ',U[r걊e}40ѺV#ua-6V#rtS/\&Pnڨ<Sb^{eU>WdF$e)]zM[0raWLo^YCm픊OGiO tZsOm&OO \Nܞh]Z1lP~Q'kds!}F,wB`V>)%VF)(W ^Jβ,2?ڴ^7LiyϺ~YwI78XvFN,}F EZ(r9>B{E.VYY C03M>IςCy=PtzEό=KKYVht $9k0ۋE3+$ĦJ "" {loIÝS<7.C#xI쪰.s}3Qb+n˲!=18bb=Surmi} jz-m)om#%I,~`F)E5B?ko5̍GDtT Wk%Y7+U!eKyHίU`{fXdD$ mKFn3 О;/ز^Kd/އT;F|jXCM+cѾw%?6l-uQ{` ;JDZ ɋYN zg]!412gz}ĆL\7=hdiJ<9yV.o}EaYrqEC8Mkd<MX:if7b~Bx ǧp\/O{ޭz,0'-K^֕Mfz'>@4MZžRZ;OG;b7,k|2-;vMghϔ=Uh$<:Bʁ9G2!Z?o͌; G\!ϪG8#!Wʗmj;{LnVJ[Vߢʸj1wy>FM. Vc?XGUz||?][f y;SU!t;x "3;N!XF9|m`Y<8~s_EaloTpB'X2ߔ,qHPm*9u-y= e~~DxeiS֔3* J ja8Zi#wv~[w -~7lb,bIG~縵FO5wx L6[ňrV`sm'/鑡ۧ^bPr`.9LF>Q iKI|g׿U,hYEzyg;wHF6^ _f,[BR: m k \ޙmqO(IǼ(Teoy$Ӛ5$y(Oz nŧlQД#|+l4,L|{n˿g,/wlʼ}}E840##^yw+F1tHBaF[SzU":KXB*7ٴ`..]#@ES͎(w eYV q]dR-/[ikn(Jyޚ:ӷ>|>\k=G5z}`/EҴD#CK N,:,q"VdE2^# [ɲ(%Z`rREeǶ!a 6rUz(8~@k E7-+b"Y;t7{m.šlM*ߧ E8bM#xqҳnS^|#i\zwX&y^]`>NfKhgiEM'}Ochx"%Ds}<rtZs\ƴVH@6r5Qsa$J\nP'DDG&. =w睿gs8kY䡊s8p{2Yt5N:AcŹQ85bA2;6X굏ɺf1;ikz,m;Rc 1%˜3{A уwd[ߗ1* "eZ{meiAeeZ!Z{5W>'>ļ,#ny`Fy2|%:{x]t|!w=:3 T?{  ;YﴼH= `ܿ3Cb)$ҜXubFyw² ?O3~D-׊JXՅq4+.s5jch,V9UduvS( m?c"=PYWJ0.c2V>})9;Ͻ@=*$0km߼m~Y-OyٮZ#1_^Tz|y>ۜzvkeuD;\QUzG &kިG x6r4%5 "ت_\FgFΕH? \ zEF7ݾQ]+K]Y1 ьۢ"6#+:Z@tUG|Fs8l$ϥxAo> “r`EVN,s;w[b/gd]JU69?t5N`uWF}[hEkZ&2^znpS{5$r"6t;"RgV0~V{zEw/E7K+:VM׺#?QPdtul yn-JIw[ /=Qu"t JY^z^\l߬: 4)ZiK"COiK19$]39dOMRrW~czG9DzR$2U ~ ʏ{VF4e]^^c/9S - ӖB{0W$KXQzk߳|^ŖU 9y=s$ ^@eANKXG-I^FY&{ W?Ru'DzFѨ`tba _Z4ߕSu(yy'δF꥜> .(*K/1EP<\H_"zFziJ)'XLVZ=cجxcd= +#7$CgGW~(w_ ^\Z!ъ]/X!\?VSp뵭ҌYE&Y!7ﰗe VݑzJ$G}m~n볪Xf$)H/؍ u ߭gm`3u{ ĝ(3xIŻ{XO im] Sv\VѹhEEr:vZ׭:{V)R\-Ǎ1ֳz; X{sYrbdft)ya X;J{iSV✼z4jE #H;fiyӽޢk(rVP:!]Ys@]^@HF,`^x j[d<|> hY-ٸ{p|#R(=졇@) ~Ѿ>G.:~65ag-7F#D];=nwcj' |rg=1*r&l?0 x^dQX oZ O/kGj?ÞGZHuͫ?1)Z…2b@,*n$b{&k"y8(Biy\LVw>lH_PQToט9c[}/Be*B]-1ҦxZV},ˎ=͋݉"{*B5nh>6"и;y[uiuq~zD`Xg|*>s=* kٌc=Cr·6DQDj}u ^@K#վd(c˽q=QQH L7L,KY;`>A#>M=ZTxƂB$YGp\k&y-/y|ELʯ9Kn$$I8Q 7ٴsM)PdU"RHɴ+^%XLK3;;{ 5Z}JU#QM:/- Ze%Sl#)S,Z, b崍܏^*`Y`)q,uUpDJ.#/ ">w#fW>d}?Q}{w$`FEڠ#WNhEPGɩo az`{Nюq7 T(sc mpz]\>#X4>ʷkOƖ[k¤y}G4V.Q%] 魽~°,KX䀑Өp?Yz,|˲,g,Z994Mu(sØ0}K[]ox~ccZ፫P(L>Ś鞭}V_xo-uCYSq>5|6G{AoL&O/QO|cȹ˼@c캒Jl\ěZI#l#-RESץVRDl Fs=M!"pP kx&T-Q|l.j?Ki-}\\J[9l--`;"|UNj5,xDR{*Qi:\lcțrGk|YZ0 }<(l4:/(H֏Dc1wE KN)5nTvctޝexp|Q׊J۫ndۻ۫lY6o׫g9B-Xto?7{&gsv$+Σ<ģ^i$Vzwmzw? K( {֏58ގÚMJ?䔱1y'40!b o~NwNX=y!ZDғPyLH#U=@~ :FxGvym{}8#7=dviha*=NxҺ^(xLx9#׌bZJs;Ai}1HpSﯕ\`!WqGg\a&nn0 )?jk,[Aju%3u9b[>-~ 8X%`rN5l4I&AOqlpoAnm,+{͈,7qޏ!I^g}_, B^5WgŖX쑵~_+oN8/dż4ζ}-/ym=0R=V!ESo 1v޹+^ŏn".;Gok9bZzmJ,[mI"Mj==C-x^^,^1g;KI ޻~VecGͤV89V✥چQeL C'gpm3ʤgey֛WxVj3Y2+w^\܍ ;k?Ĭ#RĐȣOeFy/i` [UFgż"Rό㒬ݥwWJr?BB1H-"gS|geHĜRNsl.͡DBMB$&T"r8 lceԤ %Yr>:ʞ R{OA6iC$x0gޔ7Ea'w% xKXW|<{ފչ{,u:vh?lѴ0h 5R#rGԉ#fr-]˜ЅhMh/ YQI=mK fiˊum!fa_]xͳqە2G@b)zEz Z-Pӝ7qJ.XaFX8=Xb%<A6,J78B.("m.Jzy-I")[63ӋE:x/<\ݛ ~}z ڽ~*'/ HH{㨟V '[q/d+ZqГw2w2^]fT9mBG EfEg Sf{amYM  -kY_r%1ELƟ\N/HS@Uo釮yMx.Jg,h#l'wHe%J=aH eg^.wLk#x7(DV"ߨEN$PT$AJC9;#'[}zsUtzN},b,%YJ9K ~ZyFk|-'bi?{3DDM^oaIr1~;J{{msa9֪ d(6,^$qwe8p'c{y-VJ]Û+"WȳСˇN օF!~40~E?z |Z>/jCWڈtߚ+mX׳TOD5;Z?~?>35 IG" bSloy|-k^JQє,8']="Gfʏ(=Ek}6y~SY^kjcg{rŐ+Cx;Ps5s݄ |`^d 5h1v{W% 8h=G0}40DXcg~Z W骲4{ yB +5R,3?,ltI*hYcz/2hl "Aw粼s஺aFB-6bRo=ǂrR$|tU/]7}Ӌ#FڊLj[w\8@:k}SXg`Y.9YW]_ԯ܁b}4 c(+x~3rE!0Rzڕ5j;S,gJi=g.J"Yek-%_˂nDX37_Wa768A- tzf_Q*4"v(xCg,S(Zǘ?4u& NSk@+ 0wSDxW4#Yչt)kxYU1=c淚ۙ;YQ{eQ/<7YwgL+YJ&j7-MN,W?? !0 ¡WgE ׽7z}ȸ΃ܣ_!92!(kZw`3,uЀ)n70Z'rF 3___d,(53N'C^ʎe,lzěC9>v&9[|/ v!ͩOC<ݤxQ¹|>W1'H($KY|  ?5cpNFſ1oo}f01p5_+Z^4hYe *OM`)º78"5S?Eƌ F*^: V HPbѶlu*fjpח<#m٭DM82Ƙ/Qc˻daޥjj|޲DV{m ^Mc)ji@Vz;MnwP#T|)8dYN$"-ry`r+k4Jܨ Y *t!d)}*DXQ^[Ŏ/h2VRyz\u,M7˱ߔGub{U4̨yPfx,k/hS$G@t,m[6Hdi0ez1ՊޤYd>2Vt)z4q"[~~~Y|V3+21JW\@TZL"asch]ex'Ik=Ie47&oe-<#[h9=bSY"ǢvD<+qZ6L=ʲ8~,z&5+ͩ9 S/sYX˪ØQ_)uWƁUM 7+v'< gog*tNTWgJ;z/YxH+GeT#-iق{,oA qx)HeYd{mu!05}:VG|_K:ƶm:v>G[i-Ve5bF6ϳ<σ+]{>iPwg\VG}تֳ^]{N֭V YW/xN?LD?|ҞmmQ@( u u-!SeS&xPex)o!qSRARl{sӗn~֎`M*sQ{ϛ%<\cz+$˭K[&{0b=m0n|g=f3a?*PHOGۭk$:b e1<ky,H4v- 2SGx<$,yٲ]4e׈%a^tX]BI>Tm:+X\k 9C2VѨƿ{w0rrl[0I`k8oF\8ǴuB!+6ZHj~ljŹ q?;W1idTs^Jnml$Rbe%@UBI֪|5tc·{|+ %rxˢx$6(D}':!D-ƈxw:U8=1lz۶k;{JڍݢH.deHIDŽΪ yC ,?dFcy=\Ud2U~ m+p^dK 2o5Z}Wg<1aF.8uiX^T2'pa~" 1@}vϣ; 06(QkToguSo`v2#aO~/) zZRBm<X>ʳRRxnb`֣@ k'^a4zRJGb-'a{qϛ;Bz9PwH 6^_[X ?8D%f*1 S*e/E]MFu8,)Mz-'+;Q뤊[l}'vxGûO@Lh~clXW MUjKSkG.{t?m}$&^;-}X^\{I$9Ԣb̛*V&! hu{ R4Ic0R$VCA%`Bo// ;XrѪz{G~xW\^tj9+ϕnOGgT~"]UF Wu #듣>/R*u SXRgey$Y*}w{V gG 7:t G= QвJt9LVuwZVz$KC#^^&-b-뽛߯B; <Wpoh0~ ? |ι+7qm5&Dzb@7grvAGa L2+~ǎ}Wl<5W~^Q!o<N(}׶B4%\׹Bm=VMiag0'yjF{"o\y-r5lGh~4E^G;ALFw/޲9͍5ۢKaqYf5Xϯǘ˫u6K4uC˜PjyyI5rsGPփd;*y9!EBfUqk瀵Q[*#D`׹5<&:s)U/7J?:rBh*Z=ls7@ε\CF r~: ZOB 5Y4t1[9.~#B3f(g䑈:Z"87z ΒP`k}l1G 8gEB"f5$ ٜR#9OW-gLm6YJ3F8ZvҲawĶʕ]SZAp8ZvGwEdYP< =Ge}¹.f_o1El<4y/(wD˛7I4&UAYYBݲȪ`k?{ď54ܮVP=d9ZuO:z hJgq63H5O$8xnVYX!Ke =KDHOYv쵎?vym8©ir[\ED)d]Isea[|M,K>k<ΈՊal]7oX7d3v]` \U2EE92HZxI2;+AL.ƃf!cײ.V[0, ggW)Qp\$L׀d=:qֽqA, Y'1ut0`^=;TVXrA\r>Pb2Oh i*xEuF[P^$8yYJi TI=:`O#5,_&-~O5w&2q7se\ j^$RY,'[E$ݺ@wjGH"S{ª5E5}>%n۱1dEݙSK|65ÕzW[%[Vl~sS¶E8IרZj[cWvϢijF3szCu. A񤼮<:yv?m8!kͣ7d[\'ȊL ~x&s^P@ʛYUʌ[D 4Mv}w(UƞiD6]NczQak_}ԕPO)Q;%y55( ^D$z-on=|_9l;LmPi!f7Acqp%U4M<8Z8{ۘq1x@i<wW3+ }DGFFc.ʊ*aˆxF]$呒TņG$#~z 5%Eb^=-K':'T[ B:k]67*ur/;q ږzr\ҙ5pC dY2z* ɻNG̺+)~,ClEݎ(LaG FWkGW=,"Kk:#.X밥ݻCS/~\Vhvl+407uw }Ē7ˮ'**݂94iI-z /*8i^ԐU߳}̄iSg,O(@qdሶ.(|ĭS"]L"R,NbEk>fA"oAqNu?g<',ZB [M)Z^xIGzd=.L=BwvGniZwZSZ8ʋ>g٥UxZba:*FXaay߼5Dfv=gi2ì`ٴw '/L,{DEKs]z,8Zy xIK̈X_n%GLX#+EkK^S|<% QD?-!<ϊ<>7 gΖV(;ƙw4 -u5-xe,+! =\x0/'$r*EY9CӴ-Pֶ1IjIP'`9O{x tu'p%X{Y(FK 016~EZqfɨ l)1'( ZRcU7޼y87`I{65| txB+`F2jY0{J;yFw(t^@ըzLd:U-'o Gm0$Y !k'Vz*cC a^IYA\:v_F/֍OMh=k\h+D}7r}9FҸyU)%I[$Wo}k]s噟5b:vMZX+`i#E(CםY B.ӣe?AD1( F-[" |_Jޚ#wOxut-Լk=bΆLӼk_=(7F w[#|#|罱}SRu欕؟!nm՘-DI!ZܢkwJӺ*\#!e.MÃOO 6y{WYh>tJ,L#dYԄoask_훂+#Wr Eᵔ4$s7Zkڲ<`,> zR玕 #6F27xnX];:g#,!z+ Ǿ< 7_=k]ߌ1ux;E~8P1M3ƣk@g; P3 \zF}Y九^eYjLV\QsTvjhm'jp)MeiǣmWG2 *Z&cp, Ÿ92jS.#wns`H(8罨ёh/:4-p){7=gcRj`SɃ'!ly[cZҞSO.s:mph?_v{;AH2!#h6]l Nڼ0I^ϗO]L(x,NRĝKix);muk~<xH\&>zC{LhxdmhȕT%gk8>Ops0;'_߼yH ȅ^V1i]H.q8#tXxSƇN32(ݕK> 16Xp!p^WM`g):ڗ4X}w1]DŸzA-cCzry3_Qu^ }0>ፐ*DqN(2ZVECM "֢ nǵqQcE:Yk󲔚:%cd=-kuR8X.}܋%sN 8Ü|7s]e $wWY߽40 jumbYBXopFn\L!yxhY{jHy ?Y w7x4ԝA>^ΐ`akMg q*>^-F#A-@?ce G} hvgFʳ-3,pݨb0Bjt&EE|<4֑HF5k(.WPY`&-4W]ܖ3ߵ/j/94lQ"E#;EV%ϲs '2+%7D 40E<#! gP1Zxb .;-V8b*הu팿P1bf}o%nwF0s"ktO?LYJ2M9R?'K1MYU{w˥-Lnhw?2N;mEi60Hs^FAT9称-!LenjtZ8}~`y(,գi֖u&hscGx9\o}-F)V7*H]WlXNޱ`< R Cu!*yuWK}S}1]"l:mh7%Ӓ{igo[=}}XDhV|E-S֕I\]ۖ* v}SOc>`bgu&bkK$Nwa(t]K^3B_Z%"FR't"]mŃŃult?E\ۧv+J3! VL]x@6t;{m89b>. x76*?k(N0nZ*A_RRvhp TÓHcA+ԠIDATkDFi::zd7f}b5hlnlDG"݆~O5B<#ǴJq5*OwpI|VW΂$]>T|RKwqђjhtͽcPIΐž,pDEZ[;ĊU^B_+S.66$'U3rD$#WdT)R$H#݀gUcOLQ2s.9۳+?ޞy#7dgޑH,4+UkZh$=&Fr+Җr3Wngxd36Ï`tH[Kcr$YAhQ{D[L)7!}k"$ewWa;k@ Qd }eRn<8uk)W=@"IȽ,]Za"\HSN./h:++bm661h!KE DmRzq.34w$8#hXh(pdf8Ozs6PLQ80D ps&Zׅ'dCX(vC!ڻR*<ƴwI"lF_|;Zc^C6I,й-_7(ؒٶ~YZ![n};2$[ ytG H5wXѼ\7K{.)w{)J"ݎQT;P45"[K]Ɵ}۶5xl/eP6o#pE i40'1]FqP %;bi-糑6'QsK9:/Faڵͦ_) ՜WDRԤ0j/H @7ו"_WRB4IHV];9S)*dݹz,a/ӗeh¶mޢ-KX'.Z{HFE2Uґy .oJWFXnwQ?hdIKuճ8^9gZ:]-/ uĴ6FNqjǴްƝ,|_wvQ}I$pc y"Bnyg-t{u}Q&?<#Z/6l2m65x$p?ߍ&D *am.-Nђk:ŊR\e#c:aR'!\<"-PA5{>%&\X<) z,ʏ;zB뗲WTfm=rG{ ,;zP}8ܗhe{2|#EA Sv7l@ȳueE5Ysgݸj$ (pE`i-Vuc,'<֕|Y* 1GXc$2 #ciH?NK&"~ fi-prϊ׆(L߅) g' i?YQ?q&8}ytYfY\~uz/F[Ac7R~Ͻk?!IIENDB`Carla-2.1/resources/bitmaps/background_calf_blue.png000066400000000000000000010144671364475620200227160ustar00rootroot00000000000000PNG  IHDR6 pHYs  tIME /AcjIDATxdk-[>U5>9 Q! )H!@b;Oxp52.Λm9{y5Fﭷ `@0 "03T(b ff $g`3E1LU v< 3@a5;b cc@L lAK*@  oeo0@PJ)hWCY Z`\Z`ϭHyO TZy"H@o'n,ϩc0B@f:%" L0@Ob} >1E 6 cuѐRA] L 0U Usn:$^Cw1^t*l_o knN@K:ss=ׄ>벢(0@} 䜟gcS@csk3kGD~ܛ zo/1|ԟT>o"|^ gmr#1}R"t*!HzC 1>c1=A!F^k߉/x?!"Ĉ>3@zo(b1%׮*!5:!"D9%9%rmw^9ܿxm"Tt*NajH)à>)aH\;q5ˇ8Ƅ9'Q%{ ![獖O%s5s|1yU)B0߫/ @BD__aڀAɇ}B@:QJBBA@M ɛS TƜ١!!FTCcthc`tn; .i @Bk T'R)m C@rQ@'uE1Ə}W` Ԕymb]T{ǜZf)jY0ۀ$Tl#ps8ǾCu悫5RA ȥ'BRp;7|8`PU( `T+JL(C-&*ʲ@ x"t6*7@YV\aT"fo覨j??T T ̔_ݜOĜѮ WkS1F0c(渠SB?;Ɯ (Qp\'0u]J͸$j1fp?؁jH)"EnJe)cY ֺB)kԉ27ace>'rI1CGǺlܜUeb"H@- bHhaZ9!5,˂`w@AvaC;zHx-5,TYfKDokC- TR B AS!"Bo %%Qk __/@ԜcBΉϝor,JZopBzk}W1~vwSR1) Ų,B(1!8σEѿ &9R9X@8c`Y+g\fs> <6Ppӟq쨵:FcA :`6 CFNLS 0DŽ'@X/4Û ffܠ jP^=`֑҂1SERq ~AŰKY 6LD+,g;YI{lF`5`:a0>)XjqA H<0SaozY 1PK>@cL,["!bsw j mLHP@Ȃ\u`s<溬8"Ak(@MC*RVaʪަX"z; )a (+#^d pd@Cs'{MJk xS AmDWCM ~&ԻA"5L 0(rZ0zg#;lo 灕ӀDCQ 5ƈ9١ֺ`"!" +#հ,ŃPQ~շMowCoM}ӡą.ȳX}1%!`R$O'1^su 4/LĢ.uN1|3ϱ, bA{KF6N@eYljTf3],B0oTlB1c!ƌ8b,%ƄE?) ޝ?P!T0>P0 XС|E0 _!bHj|?ahG st9 ȡ]'WU])!y6j8'QUhAR`o&-˂PKF!;I޸Jlc5١C #Ԃ$ ۲Av֊}Ỷ 풞{v]j]ը bZ7bT)P(Bu->I,Ds8]|0!nc^B)uBy_^kq8Dm_8oeLDA½c(꺠BG`]>"k}x9dR$\ pض_P} LwaڐRa?׶͍ƀxfe"?x!U.[(&ey!`61Z6 Z;C SU$8p91>D-`E,)tVbe&f(@|#]&1gvG ͡H!cע qU4#T2[0wY)PQTa0?g m8+g}1$~F1(69g]0?3+ΦwT$u:!.2(!%bhp g-O%`ɿKѫ Ih0 s _۶S`@ Wɿ*LD%O5 5eD4H! 3v?_X͋5@M Rqߨۆnl)Eƃ}qS__)D]( RI>% ؾcBЯ ~yřD0rsB0Rr#%wIc4,b<ZW\׉u{a ӉR+a{m3GٙIPL9Dq ) ;yA yA!tcτ.uE H$R&` )Gk1F'ь7!JD X_+Y;#8tZ?PeWˊ9Ձ9B(Kƹ_!a1dA )iTKF 1 ?| S|(wV3Aϼ;4vC¡Y;^#RNF`+pHXm"^_`6h1ȩ 0 nzleqse e]ӏ_4^k'N~t;~v@@!c`iyĐ{`.90 DϜ|>l SB +S $w>: "| ɇhZ_؏oĜˊT2֟*p- ߳$v=!`-y)kkBAu޹ggXJf/@^ hHM Fv!%h~tP1#D `_pwL̼?|RF7K`[_JXp~@[Y|ؾ^wv~D;.,^BQJB:r^\Tc>$ '^ 6/u:1PbF5d!d y紪}> )0QYeF) bX c a=o\ U{/@Oj`p1 2%:PROg QD|lG9" AC0q`0D~ UC;/ L2R<sBP6.{UzX<:'d:ESM2ͺbS8PLͶx_n很f<3`ñkg q7m ϲλ oC_AuONm@j譑ӛ3]>k\ Ё fkh²jh$y>tr-7EHv&Po'jB@$D srRʘm`̎#Y!DJ!]'t$K52a+vsu s?F)"vU$C u\:vF]R"KJkB .f1:Id齱3C]V`Ԑ>ޘ:S⽪/v"WCYĔqw/1&朘N1U([u!ASȩpTp?s~wyp@86Y&2vp=n4\_6ƀ!UE@Ft7FɊ1tt 8.sv<3fJfL 7B4P3u"ey8.|FY,,ZP&QӃ'b%Hԫ|S:Reonsry3zP+pR˽EBA AC;r g[yp!: 49Z̄fE-0'% >I Ìs sHmJ"}RYD1 'U1u!焚 |s^as%qgv_G6PSA!TxU;ju$ ,s"Ն$n*jXPˆ9ϥoPH'DAtf ĘSB ,]()b24W>X#ttLf3(X"r9F4a*Ϣ"M\~PZ0f#TE\G)"BB(F8 5&@s)AE`+̍6R)aPOr( X*ɹ^g -+/d\1MVn!s'pD!F$k[|AA#!&BL ~0iR!ԵF_2g^f=טk3ī_AfqJk9Bir yJĈ 0׆Q qv's7JKźm8yQD()=PBHSP i %>`´T(}^>Yc>%ٍb#v6Lz*yrIO5ZC~"?Ic$A]"Uu^#/ I,ڗ3 3ÜN$KBHJJvD/s@ouzihׅy*, @cNQ."DzPi|?`NA0P7뢸Ř7<wi"x{C{zrFTŵ)&,ˊg+y8$t[ruXW(L 2C$XgL*F ֥8Nl IK q"ī[G jFK-\BL9#a&YC01Py@0M83zDLH)AAP` _M?1._#}ZWP4‚Vpⶮϰ 3.$=_%Ajd}0&,>׸ &>s>~1xo11Fd)ԧaVs6B!: }?KpF(RLU zò:߰ }:&,rZ) !$&+grBl#^0FS!D^Xc*>4%s@Ǘ|"g&`_!ϧ%q!:cZed_N> EwNA ,+ RCttyHAܓ }]|8Iq%EHjuq7+#9Y}s8:=Djӆwld*`AF1#lqUAuA*ՙ!PT>} j=L 8zegh9]ΆqZ`Q1?7:.J Ӱnu@x|w5 1!vHQ6!A-_0Wz#(%_r텡j0|1E%St>ڏ|S'JcswE>[1o1%V )hfUEa>QHYh!H٠9^&~Q?;|RY9q*|z ~ VݫVdI1&낔rJΎ8pӀlLBZpƒCf:;"rw;#: nJm#A?sȪc:7(}tl1'ЯE/HC /0sd#/Džh3c!M>]9'1.ec7΋eE e8DG?%WR!КkΉ5Ԕ;$J9N:a")$h½%?K] )e,"ZoT -DSERaBPHLb脩b}},俶\0C0 xT㛵Gt8cCrW%ıԊ8k ~w2dL,s l-K͸\t`V)ݬPFvJŰ, V)@T> %D gX_Zk7oSuATӟ}xzVԻIsmR2GGwaac}7HgXr&?]bz`T">1~469tF7SOot\㵾00_ޗaP^6IK}{ * -%,?D6ۺrN*&niTC g;S !]t6]c@qy~B ooyhƔh!p5̉qAnu5gi l '7eX]Si>,'!ݠx+DKF61/= S=ul1G$O'A0Y,ϯ%x?Bg#xkRܐ bn3ùSs:H=8^Sq\oFvXHhid!?fg1U2I}v'k=ձnDcGv=ζpߐHZ.% |6x#o%D("_h76'cDzn8%FqrRMZ飷 y?²E&F.%1$ƈ;lRl @Bg-q IBo:Cpp!Hx_FiDP;3T;"D\zKE;gFeC!9<>j8\3zڑ|D 퀄CvFt(%‹ԻDԴ:ܦ?_sN4usʘ#|2_ '(r^04jGLſ-FjKH$~XR aVMF݃!Ё7F]1X%߬!uYC1"?&}bMB_7#>Uk=79\ëe]Q];j^ѵ#EƝ"6.7.1)8dd #[-:$%Dōc!g6@PeA)1=ZP?jH %ތ Cj<8h'i`~T}pߛ>{| spbgG rx7ݴ%>;~:||wIWw.pTt7 j:@׎j0.5~ R|2*k&\'R\ѯ$RYC@ׇ1Pԁ3RU1*ZoCQ[Ye@s|tدC9e3ʮr6sJ`^ u5]tB5R0.RLx轣iu6\H[M )EgC H5 SREo:nqOQ,ˊ\HZQ$;zX.TtPE A Tp`v6` W??rdΦ # V)C?_u4%g늘qcпa. )f>B)Lّr偔 b Ŷ}ߑ3Chޤ }Hk8úl81pцVAo0yn'~ڎss~X!]0@!-&ʭAs Չ nJK|Wvn9St0ި]> u,ۊ6G+, Bu}h?@?mݽV)%׿ӺjZ}B<)O\ΓLޘr=~"[mRW#Fbk[0!׊,*kHS1{"iu~+J䀱6%/^Z'3Zk8y۠NV bɄT.6:օtrU(s)63AoI>I#VcϬ`3*/I0tDqBPR?&>TUгv%/r"HCsW K\KEcX7nП`6)'vqQ 1 4"!>.Ժ@Bq3cSObX~J&S,Ɣ\scFMfspjLIUAAS4_d~޶B3`t6r#kYh6!/)>P4yPPRCY>Zx=+&%EBC/Ssݚ^h&?{a pCV?f ^qp*B? >cw?bƉ3X1:uz5~23vʦb E[RS`b?!#fF% 0'E|tw|P|2eHL1m0TZ 0f[lr*T>qn1\* b"ϋϑf(0e\9ƶc R l 1{! kG20P ĈuݞH|Hdeb@$aꅠq_0ljH 8"GL.h׉m]pT*1ebF? 71- Hu5;?7.OiN qq{p𵽰3_~F ERVFL :C1,N~S$sCjXm@nLH¡xRrBV_1#nz὿HrLA&1ׁmY_;ݞVsqkq8EE{@t[ҟNa\@{CEnshfp^oдӗ-{k8"S d1fĤo !g!}&M??w5'%6bYikYmZ/sZ= <\$ >ZϓPVZvKH0n}'e@c'򒐃[EANh<K#Q_M0kMw!4REJn,گq65Ե72 :vՁ*J\ˀj@̋.$S@(ih(%!T.𼚃?g.+B* %gsJbt߭թl+le/^_@hCqY~g^´.f!DE X@wJz2,༎@Y-u1T&Zd^խNZ-7嶐$8|әF(ttR2ZNlLgp.hSxؤja\t @"G*(>c)U?f5[<+fj iPMey$tlRЯ|Dܛo7'Cs~ޛq}/ 5Usf|07W1nxK[/{S.viyQPtjPOuJݔI(uy:3shM mL,xCMSAJ.O}<$tN,ky3ICB(est .}zxygI&]OרD%s$~9`}zLfd1|}}=W99Tv?41@Z7\dabtF`!cNqϚ3p=˲aBl@4e )\ v(>i^PQ S'b8oX1}F3 ==O1 vJ73{ʖۉTk1Hg خ ,hYl&%' oJAL+ny Rg}Kv `ض/ˁTx|y 6!xNBANƨ\ H߽we +WȨʹݲ 4*ԂmD@:0zCʼo9'bº(mPJpEڜ+^/l낼eԔ mLI!Z*YBMx-+r-A&>A"jضտЍگĂs^=XPSCR"l_ו2`ǵ ,ucZ"/𙇚u\ f?#uB7Z_'g(ˊcPŽEk{N5,F M?4*v,0wϢ6PhX /P#"6`sڹ7# MDv%gSəώ4v5,uC|n0sSȏ9&Z-pVRoP.K<5ȪYꜭ}!׊v(`uYXt-m;N̅F|B/qaxZ~O5W~`h1. 8Y}x;LXI<_vc]_ug| /dO"nX)tefuU'һ3~ i "@RD]W2BAO)' qz T5`j!`?φ>M͙ jh[fp{f1hw3}|r|L s`@FƔ#ϝy) M$֧yB|j ]G9\G)3uB|uYhgs3TLGz @] !@.H)8w:@Ǘ(8%aL2#nbBfdZVgmƶp߄,?d@ i F|5:>M7f8>?i rǤmJP#s'FH>L}6[l9s@4Wya.[g La 9p왘'ҿ{C&!19YO}>;<"3p•vCn_@$`iuz5n&p.pnmSzb>=y)#1ξkq#⇠+E߈D38fn+ ̱9#iTȈ:Rwհ9B@ P )c~@"!ׂ9T]ʘ5BFdC6eY* a*m M dF.eo;73/ 3`)h Hlf$Q'PPH R \(3`bf̦ uAN33zg&RcH˭DFJ:JQJ@|sZځR6v8|w|>dn˖BCY]OB x]7%q΍@euY~F}܁1"P ְ|pGĭ*0}cy]w @P1Нa@Ǝ0t"á+͜0swBڏg75BFkLa^k\E>?M+ 摨OIl{hWBߌr)Ȉ2q͝|s"ChΧ!ҟ7%@T 1PRF68](]Ǹ.y}'iSZsdঈBNc.p^h'u/~Z vr& V1aΈ}G"?^S<R (Ĉ "Qjt)0T@W#K@%јLg gn19CM~/s;?/%a3#i)+Ơ/OmSEob0k(:ۣqsNy=Ο)@ uyV} h`%YK.|hu% Q1 7b f RL)O=4 1c.@PZ[ʆiŵ0&x;˄0.{ۇ^Epiq$*r|_-}̀(On.*ɍC6=4`+;D e{qX=7EB@]x[߇C !>pMȤ{D͎"NƔmP6grfH>o^xk]…GH3tX9a?hh9~71u7w-kxoBwCĘTw%1VlJjkYYZ٤wDbekegn`̘P=H?IFg0AyUc n$\HaCx6y9p@Au}OZv^Ր^1'ձ^`q1J$rwt!DƲd$(= N+uws C R\I*$K:6I,Ic Xľօ荐ׯ_1!$ "Tk|hmCP.rurig$r0nnpۧIȹ6߯y0ѱ}qM3qoMfW`21N^Õnfqx "}G0mSx*dݶXp6?NՅԭ wvmJ\ J~qI;`uN@Qh׆7bZ@l4 kAPSB%st u9d.tPsA#.Ikg$zċuTxQǺơfo?%յi*Ic B"8SnIM1oA,=sxw!!ya;{1>_CG9 )cpY+))s!]o.gRBo 9re2[]q-0їqM@-i(6L77[s0b|Vl+0mu3)@b|74D:CR MRi'l7#mWm_i8{Ǩq1")'Ϟ^AwfOiL~@W>jp9-"g}2b cFn"@eݞb$ 5J린M)0{"Ƅ|:B!YxXs*mw3R9sg݀AyYFw7䔟4Ks~9,Ĉ~5lۂjد6 __<.(s-BJWiT$<ńZ ̔İNP7-2 8}rhׅ e-"}?m7́e`_lк^wN0+b q7wBF{1EOڽD'jDܶ)''\a?vV ޱ!u! ы,bDPAQy=o1e|CW>^kB%Gy>/dn'9zm{Ԋ1Gf|Qo[@FäWa\S9cu]8<B>90Lhy:$rqF2CY^a@|u*Iw]HPu[}N۔ϟŷܺ1"n'TQ3ݒ><4plB%!쭸+Ԣ}=+NuC#w?3k^H}ݝ 4hޅ e[IuC,%W>WK梱hC!T0%o y9th9twVw \, $mu\ .Xc(Q"@=1vRP"-X(K68 S1f<uؘ]ynzX b}BabvHSm=I]1@XX擳%T{CJA|w.s.ިUI8q TI'WXⳝr˥Н( 1 utE8Mr. 'Q BOYHKc2V€>=Yd_%ʭ^F4ݳIS%UgJSES A)'$i^>ܡmz<~\Fn05A'K$5w/7F 7tWzނjA!|C15|j ̅BmcO[s;?h$&gC+Sk[1&( %A6RrQ3k板-q%7LW$E62!Yv6jrnPr!{]L/ G\Ȝ̌~Dl>CH TOq\ÓqF R 7q!V;¼Uw D)CH/vkąb>G`X 9p.Fߣތ001 M3G LsZ )a6 xmydrA 1n}9㵾8#J^\|Q0ErzSPrF He)stnVu 8{)sm[qVz 3Z'~jq;ATdBS_ "zTp_/ J@U qSV^Ԗ5g,:R g/ TMPsWuEݯK 4C!X 5Tf !rIȩp&s*}3>:ȥNc1s[\dO?GJIΎRA1z3c-D1ZIb +gb׉E) BPP|,W"dL Ngx;.}'c&f$կV &C>D]MD[ 5Iqs:Bj9ӵ!\+~U >iS>6U~I4ͅ,h!KB.^Xφ+Z߳=F:«ϴ6\3+YhADIBʬ(bF*~M)а7O@BBb6[}u*Kpx 8]pbL" Gx \els+& =)³?]]`Ën1\uYq]'#]b1q54gd-/O<B #bmږy0<Ў2T1=Q,UF9"BiʕpN.If?:WFNF/`q.L3C3;?+A /6Jƽ6aX)AK'uw`"qP(H팧p]gHݒiP a00|-_J@e-Pa}(e@E#\^ )891 )WGG;!Rneb9.]L.Eol:?Ux"J)ٴ pYw+|qC&1?oqТ];RiqfTR]Ln& By+D9'ܺ865'I"MCۤH]>NQJ\xs3sFm?JMO*]UFӥ^M qb /p:~,?Epsu{T92 9yɧ\`=|Hp֓|BWPKH%=3Fan ӏMX,(s[޹5mjBFt.ԇ1,X|ɵGy؝F|%u;V)!JYPJwT9dN/L ĈK@ 8r؟C.@$ ՉPJe4wmut_',Սs Nkqgӓ`6sut'hX^>;'7;q16˲&LdE@V4@t~-s)XSw,M1Ǎop -9|6IPL),A1[`HyX~Jnp1Mk[&~].fI4\hv~9 ̖ TKj6 7d &1AZk\X 9%DuOղpC ġQJq"C%t'~Lݦ^<1weqnka }w.|?Eϐ!aC3<3Kup&+NIr_9!z4(Kt$ XF9; $L!,r#98-/0\J8+z>h-tH9<9ݖ>!`Ʌvg6V^̹ a쩆Nؑ-mV7t@0u`]HQgl ggs'n0mD>NXT;Bډ0\sb]_a[}&Z\+^$J"˺!+Eׯջ(-!Cւj]R?gVb~Hn8< +hvΡLRޛup̈́9v!6.wN!Onp <<2HZ$}s? *a9 gƚܺwC\~Ӧ`z2T{pxMgSU~ۙCGaLsnAK|ǪKdU-!kC>E`fA8~}@Y\oD#?, ~`x;tś:yTo-=:ۅ3y_Ei!?% (pc; RN7t"jpojSVœ2d-%P. tnX_/ 27~ 9nu:\ꎼaem]ّ%eżp5?B^ iNϬ'tLE,zZ7!O'OTq{NZ\ >sJd2K͐ӂ\~ >5oM U%?9FA~HK&Z<j]8Z'ygp4aUkAY2.C; $l>-g? &]`tS'Oյb6M~P5w,Kw $\]GʘQ4 r7}-jTs91Zq |\R;-46W' !'4*ʺN pT0n e?mFxx8}x`ᱚJ}R;=+H 6;I^ 5xPϲn:;>)$ z/72"9;*>"ɶv~5:0mP7Lqp+ SUgX QyZsлmby^=K׹M 7:-QTѯᄊ/DBy0ʀw֘ t:.$e* w˂r0 }P)1D> B01Go2 [RhehBPrDHqrJ9evԆюi(9NX˄;]jcfynYCFf sԑ /$Or43vn_ljQ}.Ĝ|VS\j@] sv1ugOGƌ>cL?PSH`8]FDJ9PrN !hkċ gkQ' pRO@/02jԜJ9o`*(%bebcOI0"{_)'Bk5 pD@-vJ;Ǵ!ᐂ[yOO؉GֲjCSq߃XxI:Qcy5PPc!v3'`$SF~ԫwUcv3w=>#oFͭFOL-ྵϼSd|[jsά?D'kDB25,^eγ-ƔAR3{s>0Cu@EЉ$4=,uH;N# -#\ դSwu7֥T8~=WK]}|#Aai)j؏d RZ2cY7׋uODHu|ƍ37X܀vQ m^՝ ҡ*;ww@SQl|;NNz*~}-db*TmmE*j_W R j^ c/q 9X7I(c(A@H@J_|W tE =\BM <蘮(~fwC6>v]&(PmEpo\xg< Z,*dyZwR ۺ>9G ꛵>vO;Q~}r+߄ ?L OnJ7ؐWJuvIЛƆq7@{O$89Hۥ=dsBHp gBjf`yB@`vljmYquQFnS޷¶nР(/|1oBKqʸyy1L v&f?jn?psašIv_Pj'v9![u*g#O&y _3lkDvӍTcPGuAu]`]p@^rPjAiSFa63(܍)ҫJOZ7E]GT'NM.΋T{xsl!X}*SsA7_㒻 _?P EI!/_aæ=ćiekF )pخHefRT L#'@404O>\kxDeX6#n 9牄(^[;AE:_R|wo!GMn?B~}>]BbB΀"47l lc|DZ+R&;HyndRxa$ c\nµ]rq}_Ŝ]DMRIͥ\K%G,&+1!eA__ FA׎qtv/0q fG ^u6s@@ԁ,eA=s|:ڴXbdg31n0HUxFKŜjyAt\u}ov<Θ? aus)j1gp}OCU~`ޢb)e,SZ> @+7uv5s=9Edz~Ҷ9O}~2&j螡,&N!tw43|2NN$8!@ho=gCM#P\}0{ջ `>;V7Ř㚽# @?ᱭ֫)0Iݖ(1Cc_3 4e>l :7];֭:;`,SN,כaSvCPJ&8(Ɨ]0V\D}Pcy6Z>u5,%J!O(xm/ޑkUFFJ;\rۘȅv\;dH9'vU!3>gl >$}n۝om/ԩC Q\+s|}=L,+v,Hqѱ+Z)fl)|LN3%kI4IBNFF0g9 ) <<r=:%W1jZҟmu~w H+`I(N7Xܖ 2Ϸ;Ŗ*& uɄ_-\S8T,;ly, - 08Vbfޅ$A.+}KjVe'$oNl2&bQDбO:BRD`~cym8@-Cbqx^{sKstdD*K/%^+c-"`58oƴIjjY.O9#j("\! J$J1HT8lj+|Zmjm, ߱p'BDOΓd I~dx}IRt6Gk|. .ov11n8h<Ԓ'.jF/ļIo.*5HAKuueRwM9nEJ3)z[Cģ4ׂqP.w5H1mR~N ݭAMX~h)r^ }-Y֝L 9`;םוv+m>7|{`n;B&9gID#Dܛb@k7ObTĜ]4(p{-n<_s٤48ggsF4zyep}6fph]>nμ5OC@/x2i=c +W)%~Vw}G_ A7Vq0ڠ: zE-wў>I#B|vwιz}.?H{Eֶ EU jlĈ\"7ÒbN!(Y@]Vڦ(pj}*F.dUy}#U^_7Bm6ZaqbeJR>բ R<8muuL졝y a'?ϘѾ)u Oż{'Ras>m swJ2"}.ԢĄTsG.ՇCNɗ۝ c^Gi(аn_ Q{\*yᵽB-:#7I:(8w86n bX"NTDhLs0h.PbEQŋʉw6m! 8dD6'CSMczYvǨ%o)pknoN.EI0$Iqg+SS?'}swe^kzZލܿh>1=&"4;:3Izs>qQvCKhR*sJ4?cz_Y n?2 F ;Z/B`.u#uB]Iq;ω6c&젞csZ BP* k~ϚK13P! _E"yϞ C*9gb+/9я!JEkN!Fc`´ ׺= >.\p]'bhGaJP1g<$=7(e"~Ejtz}z}<<Y0%wL _toš扐 SUA2< 󋣮j螏pc~8!q6?ibY*sb*f"PÊkt ivIX)~wԚavWjU1Ӷ!2(TqRFdTV;Z3)P_a.)&2~5Xj&#YR6/_L mtgWy"Z#RCBSub{¾  ^c>zxs&qAy,]>z[9Un@ka`Y~A 878|DO Ǔ䶋Wk%b ШAy&I\}CPmp yhAPs;XX"v;K@;/uyՃoʦ).Q?PlC Cam/\NճǦ\<,>""u]I8NHo^5bt\_i胆ꑛV` HxU=0:}r\rx^Ka@?|Ψ0>!op͞gFçŬs<6읩gs"H3|=(n7dזC6=wq'gIQK|  ivf+Ҝ}t\ 6h.&yí(Ly|͖ /ZN!{>jJciҦǏ<$Sr538p}n`};1hjRsB tNEr֞#9i.S8OZ3ՙZ6 q,p7V76Z䲢tׯ_څ97f }#8M~ V! hSQB"p]베]׊]7X06~`5P08OeKBc?})Ϊ%y'"ڦ?a_L7m]-A<^5 ĊItCBvwC < nKRs$L9GPD ϩeryA=DS5J" "A>3-wuVyfWo0r>qN/_ˊKAioieHNTOc31c?\\1kyD'aǶ~M }`+cg̽ CqxE!:,DZӛIɿ{0-00T3f{u]qwnS ^SxkDs<eчP`c5^ ᓬAs\'-M?K7Z~`~T3r8}v\> Y"E7 hOj %{Rz Tۊ!0[&\GCʴ;ia]WܾbA"x!PPBflv?Ћ&z`K*-$3z .7[e[p'Ԙ >fd`pA?.piM&"y yuL%GNO~5Z8 Не5xtTHPV8uNfTyɝbFxݝ=\KY}R(]#OՇ-~6| p'eLw-a| dLf` `sk4Sz,d9Qq;9. vGى1bNC @tȘ Κ !Ct6wMBF$OҬS='?"O'DJ'+ 9fǎuYpW8Tڽp\JõAGqx&c ">x||m8Ν͉bPU n דRl'a(bM1Uv(;>:ʺZ~(@GR_?C ſoP7~ǥWgԌ<8vcaaZ 2Wc( ͸O2m}J׵# ]AZHIJ2F*K !D &MJ>._5h^) F.k=LNs4\,+a"4rcbpPw %eRcMۅT2"2Hf&cN&}˲vbm=cY&ÓH3sbp_%NP.pcZ[ AuHHXʂoS" `Pc"$FJdV| ?>]\*ե絹?Ht1 R}jF_auu5ZMC-W۽1X#s1"T'_(\*mQRKFmǟa0 v^zL t혘cn NAiqK)F'0 vac71 KU(.L3D!BtK)"g6CbNTnG:ƞKuxMt${F;v=4kMmB0¾w =fS @Q˓2 ZЎF̭Z@3 ]6l#xu"dRQȉ[vޥDTKo*޳ NJ>6;jYqN,q3舰@DB;;x&(DP _q])K,D0[b~ ʆ2LQ.1&xˍcZG#SK CEo+Ԅx`z OO |-Fǜ__9yĤ_]>$oӁ>>.K; 9 5c)3j(a}_UyH}?[+IeackDt7fCi!?I(MS˒nP6`ҧvfĺN?"Y SWXk^ c{ʘ(gA׎vUla[7!3s<,:tQ/ukBkv*8N< @N;yyDIURFKvIw~|=1DjJ+"mZC=%sD~vu93:h1|u*PRwvIJH!$ Iյ6Qa^nH֯b8? osoЙ>ǎcU+rDyUUxvFtw"h8m'օ6L.v.@pBD :\쵏.P0Ƥ;~zL%x|N# n0|ʼ1k>zsϟ$<])s>_/;mlf(Q%aYyocEoM)E 7dAmIny ` -fCH,-&FUիc:}f˪Vpl nema 4x&n"y" R-[i$#b۴3 ØYEOROs,v~cNq*W\^  9a~.i*@VP寷3L쀧vHVptL/<ϟ@Žy=ϟe#![BMI#nڇ/*dsdt9ZrѼ1L`Ѣ7f|s]a&Ձz3%57\THԔrnFܝ-pH ǫ,~IDAT|!kQ)%;1RNŌհ9g.-M p9بCbp _tYg\+w10~u7DB\8K#upIwE:d0Dq8BҐ#GڥWN+w<˅l4|^y_j3Dܒw7A:?6hJĖ33=.pb@TZqe=W8VX6,7 m"bI\Orhꪌd2॥? ^(Ej -Bı#|-0:Ԕ:|;J0`>Ẹ@ |!Q>YΖrTB h=ջ4ն툁Bzɛu-bpHP1#zwbՅ1-SI Np] Gl)y1O[\Mr~Ưw ժ;dsLTLΫ{'O;\>H@Vrr]+k V T~C^:z6tp>u 6 ЌZ;BL̷Ҍ@@a1X n̕wE9=_"V109>ɢxqZm4O?F;ƨRZa3қ;{|2$%LA  |b?0@ڹ}1? O*E#*R>/\8O3kQz_Bxu΢%'z դ9gDg.Rq^SbRyiٱk_"\_˥Z[ w]cڕNJU|p.sXvG7|F:U=#__6QJb.'oUQWצWLbkQ53e,6f^)d\s3-#ci|?#%&_Xf0g8$HqQ7(O=3lyrT2TQ~* )Te;gѹ~OaY#Cy;Ck=!+߀,\ΆUAECN?W}MqcZ֡RMZK? 2:*S4+qj)>PyL>َFK[^ [.?/5\-ElEpʻi}v~%pIG_uqNvREhi b/(̠#ҨafpU}qts;H#f7<kl:'hTBTn.N8H{T0O b,ׅ+!@xY@~qesqLm&!Fz}9 o͏!F@OdJctؙ(k Pm-F1:p_&KB+jRQYJ̃Q]=jcDP$m]E"4cT%'h1i7K_'%aq&*1$܎VҞahi΂&e׫Ϩ>z}#b:yͧQ!=_I(Cwv[^6y? s(s1,/.uM#;1Gzi#g7 !lyd-ϱPq0BpG6dpUFe3#/Ab/ 7p,jvlZR$R ΋J'7E$q-wx~LjzBDkYyqa 1m G)tK Kz6`z%@R֕u L!9gB:/۴mwGcGyi؎,>^ @;wj0&WLo_nBNZ,͈0= 9sup _P*`=zڞ^rVIpv뛈ܲ3D3F3l&m;!'\hQ/L򜊜3s V+gmrtp^&Btֺ@yL /'h3l-`hɇ6xU[ܳuI=7ř,ke̓8N[A眇85y]Rc Q}R@lbJ\ 1x;ˋ(:Z1vt^B_/ r.z,U$2bu9O/TFFsBÖ7L;11{Ĝ1ZN#wCKN-/f&>l19w(!TjfZe'0TEv Sʅ:;cɍ l>C'ts EaTNiczhẞT>qj>q֕>ç{FWJ B%zr]!!@kC 9!xT qg Չ|a1ԓrܡ}]jrоAJD9/;D[1uJV8'IKE:1 Wm2oyb+rH 4A_q6;su~ xDєwp}Tԋv:6 UrÙ1E11D1G@s],F`N|y0B>4O׋qp<ض 8R zLS^v1eBЁZk.6@z3Y1FBggkw쇅_nxm9C@EHUG~. @%!؋ukq>YB;8KFn}YZp4C3YI-uݕvӤff$O@/2*NXy ZZ$b"XN8 حŕ6 lAJ:ww)g~*IrJ8D);I@3x*Zxv$!:1&7iKg[QF(!X ]DuuSܻ^'.xq(yO1#mIɾa#\q GTw 7'*!|x2jvQBYIgyQM7 gϼ R&"_e"ls4LuĘFFh^gX 4Ifb4d~ !J't³JIΡ`dş͍z-4o;^13z78c"xx7- )Sȅ:+*iMYJҽ,%\[>:$.dqO8yqi 4 x .>$:.ĸ;U ;\'s!h7ENO[,{u)`?F*^Ox=wr=YG⯊޻zw{(oڈIsw~b%}=n^ /Kx_~> VKZb QI3O]ӆsr:rDwF{>ދ : >F9f?p8xdELq@iy^J2Q yL-J]7"쩺;G͢ĭSbN~8Y$Gc?kAm;$IVAKp> {>Pm{ :"iGCp)odʩAaV$ YʶQM5C-') n0/<!$ӱx~?vsҖz]uxv:GqBWd!_NqW=mdFݞ' XqlC9~c8п. |bu{[ =*z GEbm&{.J>]aY.Zoո?,s8.*;Š -mcĜQ[&UELzӘќ7F%ttiky>1l0'M=c:Luٕc/ t>TABll[B sjmVOD'zb%,R9q֑E9lEUKڛѣBΠO!G±pwgx@E([fCw7򾑱TNs,^h]P!Ra!=o'%>d<1?@"PdVRVE ^rNpUmbt;mBo)Sfsb/RL!V ύNfGGC )FS}D]x@_.1#2!:?蜟*bN- _縯&>n"H@Ff -8*!Ƕs(QR·Yq BchϽ 0IfFهƣ7]Uy_e>3ڨcr6Xk-:;\ !%mnh{D"#_ߤg$[gv7q)ec|{i%T0IG')WgIkYyXkUGf!L v`X!h~b`Dz=p>O#ZF);u" !~<(;5Bx{/7烾 :+1Up]/Ogf{Э#njrxe_!z>e9m|r"xwn'Wjo?Kev6qƁ_:ww.rw.xB'SS;R&Cߪ(d"-)&KDٷ9d;zS䴡%OE0!^?|N%} $߿ɠ oӇ|~٘bV)~x=BʷtKM&H>GJmcwZ`R T'ZZ92T^ӖP^A)) [4:z?Gd8HphE)kLfρ:q|縮^\@R- m V3}ۆOCc-ւo_lPR̓ؿ`K-=S?vM4PcU:!PxOCw$Ti.U;A}:Ŋs0}8僜%/~d':: b6* !.& u li `bt ~t.cҕ&^'w/LJ1L4r|gEL{~wP7S2W4hl2%)eRЬS+BktEE!21XaBi0 vmtJc3%M5ڴޗ\!z*l/H9B-$- dk<5Β@Cu"/0z4g>OQщU!zc,pEe4Jf'v*z1&8TWJS,, х{I;vj8 #tދ(c(݋buA C^YԎq|}aVg?AV:mt9M@:A':-ܲZJ VAu\r1b$r'*ܠ0ǃ^-TUNTm:I|IA^|Xpkt.cCkDTOH lQ!t_PywmΖ6O,֎YHK @ 'xg/i(w:b*Gjyuo "*!1-=vG(h y?uv=O#׷8rK< pǾ3-e$i?r1{Gy;jEȄAH`>Œ!^/`8lȰ674djR{1H)Eo6|bM2c%ǘBzƺ@+ G:'r;?5J  ǘ`J?0tRN  xg)A\,C`O,`q!7A3fPQ!ޓ`K| cbΆl7 "bCSPFm.G|^؏V),rw_[(>n\(GD޾P~>2gnȑ|y2‡9&L6ƃ: Yf!^.Bxc8l]0y'~ f]@l:a_XHJL|"+؊$O:OuSW}b6Hf)^8xa4pc.l}KS"QP8vx~8Oǁ0dW'W%8SD9,y[0^`},2x9l8_8/\D1ق$1;<Zk>棛 N s5)&(6 La65Be3b:>#.>[]Rm5nJ;gLt;QJj) 9'2a@+4aV _Q"S!6_t]?sځ \gtzuGy^"@u؏;uǓiYjN)wUj:;Tg'֡7mvu\|1E;Ut5Y,zOI"Tҳ1oWG%x-h.||o<丌*xХ' 2͡j mϏC 5.C4zgq|OgʝRN_Ӷ>J]o3RBvQ S@MILsK;̉Ͽ7DtVTJ<JocKa:9'\em#`=ʻk.E0X7L]|`I$2aňm:P/* [̈99ApvɈ;դS&F sbBm N|}}AC AnF9gaȶmZ9R,Qub1Nƨp,#$..QG[FTbW:Ց8hor1z}jYM0DIVSbDpMAop)\𜓙갑kÖQU)XF-u2 G&bs sЈ9r|4Dgrὧpft۟M$FS1 [OȘ.ƃS@+b[gx~>86>h CI?/7)RhH cL{ Cxs%n{yWpzjwhL:( q떓[u:`b9!F18T;DDL5S*vNK$bPEbNl;WN$Cy9]aNGw? m4ւ5VJ%0r\NUSQ 7ÛKګe=` ǥg|,ci (xJ[A401fSmm[2eH)^BF 7C[o;:-)9m -[bm0MmZ])&lۆ2oߣ> L܋LP2:bY=e&瓏㗱Xւx.|}N6F$ ؂UUl鄘&Zo)_`O`No"&`NQx!xoFAyGKxi2s0Rj0Sow^D/X#0Z3уY.ʼn7M1d4i=/S|5V~,FÜ7xb$sp8Z)erў1?2ud?}pmrrFc;>%{NS3<)iA[ \"M\y Ql18 z4 "PϏ>B~ J;uJ6>/\L}~m N 3!>m>DᜳrSn>; m۾c*Q 1Q7Cj]&0;s+ /Y^<{M*iJ0(e$cRS6L{sj F P^ P8.CiW)ɋevyyB24_d=rZ+\ 9'Ĉ؈p>;jȭrm/ZKX^@ }Myve8WK Eo+;|)RJsb6|L:iz /SX7!8뎻 -w㍊y 9$[Ek VINN5SF2h o{du'cpqaOuEH5u]y0ϹUGu$>0=ѹ;ApIbt &p>B:EbެE?\@6 sB781,R-JrFp@p1廀[tr9B:CD)Q>4usi8|?s6b;ϋBT7-ORKQk5S|b:#?P1xsFL2JtI&sҽ,{2D$K(鼴ܶL8z ,/HXI"@ļhjq!0p!o$ pŶnEk񌌤+&I$aUKkK_TZHSfn@L%TJRyޫ8;±o8Txa*U .Ic7/%H~ ,Tv~*U=lDŽrU^-9͎"ڨ>zzյz#;e-9o,>Pb }xM{f6ŝ2{ga{399sQZ1cg$MO5 O.U胣Ützǥ~$e9qG=-?POBww\fM^Frgx1xx+z8.c79dSa#`~-vĠdťP˅9:&!`w "*fDq}t7l^ "sJhs?)^q҉ѵ~I3~}fFwXXj)_ctg±?p9}䲹OǎCM6vu_Rcȷt "WF==DpoɳM:Q ih8}RH@T499roS;bޱ2ci/eD11@kΉET3ྡȋI1,|DXcT,'fU)%:'\062љ:Xc}Bmr]+yوUV,w5LՎ2 0DŽgD@' 8!?7 쿏,US֓HC( XH_L,;07&;qtOˠQ""Tx[fIʴC@IMz>ʛTx]d a'v')vL^ޙ,v)|mGwd(vģہN躅b=Ku^]4CmG_<۾CD{Mڱ?b=^ 15v HuBwC8;zun{Y8 Xѣ쳾du!bb`N zsjUʅ%t Y|B*4us07x^9S{ahCSS4gy-wdnXrKN|\gq bۑ1*}j9ffEL kb4}C=159iZU1f]" =,?!r )m\b1i:l{[Tg@eyLvׯSjU4%c(Ҿs^iaFAFC+6fb;+V"D&|Y G0n)keiޖq]=[9n\آwD|l4(fT!ZZNXBoSb̘|9eMNx@ƨc !`B}G_ }d VS[cO׉g Cحv,,ޤjw1JtMcQe.I'Æg1B,o8 H{ I1zА7)nD)n^m9F2"D^Ta6$?DVpѻ_/{< PMND π1n䯿)eM"f>3Lq 9c.cE[Ï%=f(Y f;륶h?'p&?d"tQzvC;%1fF;yaՋi{PI8U2:SL޺s }pw\7T1mĤzWrThF9cj=ڔyg9V6MfQF0 KZn$ ;R#GnƜ ۣX(:lP=nLhs >f8Scl#x` jECo @<6P $ǔMƵ=x-bq}6l)_k+UsR *ɠv\ȵ{̶St>wÀip6VZs2eyOx4ܑS[t1Jd#BGLG{CJYl934/S Fgm+Um/0RV?z=e]B!71%_UCO9vyNSQ2j-xB,e*]uC5QXL4RVg=]sXwm'{PQOM2]%ޥ/Y7M9Nའ^s \\G!$3N"<  HGFSmqNN-+Ҷ]'ztmy1ݘ^AǢ!&RC4&:}@ѹ737[/g-B\2+w'[ΘK88/1N K L!"DlןOd_t i#o.U[)sH`I*K)~|tRd*+j%h6TbYxzO-@8u`D($*S:r_:|x@y \l Uok.6;%cn`3ʫ2WĐ'ܤQL; ɔ}]"F(<{#yi&•B@J<9o{u;A2z,uEaZre)cv< EK,Ĉ"&Ds>݀ӷDyCB^Lx8Fj#tsx.A&j/+kf_YR0Ŷo^'>-cBѿKBW0$j;HB-4!ob;:FH9qR> )bQ 6 UDgꄋt{wwgH,"ܣOkmx,Am+D"t(N!6E̔5'$&&w:V|~s"HZA3yX,eϘPE3iRyH{X^uۤoj[ D>sJ:}62A36[5Vސ +m,&h<~T:̮alo^II% NuNH\/t(~I)G@6DG+ɯ)>LU3)náV[mw]__x4Uz|I:,Zcۿ( |t*ca3.mYb]B<0<3q,>޻3Y{ᢇ(LQ)i㪩Ӓ=ϟjȻ'zXs:rz1{hP8\}NНbB${5*)b%7T׈ho8ޚLi@72j؎eUҎvp^eS+.C' 20mr8 -RlTL^U:ؽb &s >T`ǯ|FUmּ[3qQ`{a є -3rESXY$$) 9sRlS]yh햤 ku1m}[XQT| i9y&ۢKE$>M*u4N^"qgu7MFg+JW\{&U\X8c GL{Wu IrܭP2tl9|h4$:9cF&:HWpk їRHo//.;2R_{drg,dqh7 ޔV.lw+Q[|\|okjO(ŗwMCi\ g0ǵߧ2-&fSkS/\典طX/f}{X19{@7cogޅF&M@c,*ĝX{1g} 8+Vq:*NI]X2) wTkQCz؏ŔIZ*!;G\O_eZZC>֧ = ;4U Dݭ2ae\VLwG;:1& 8Y\c`ɤ1%88_Տ̇. j9}0[6-f+mV洡f)+>2}༾)/\şR*w滺i!jn5RbضIfѧ׎=fR(-lH:[4Q/Ԙ2y vU~ /X 5eζӹ_n7SfCw 8_i p<_N\ґ<)'Ň|tU~ 4FcNr#8#%ݿw< TP׉닯ʱJ{$yLtWS>aS:a@6=o8a tNIGJVsbуE1H, ֘2|7@2ӒssպV*__(/IF8Y'0< ~ø0  b!SIQfT0tSYikPmX'bkYLC0EBYp{̯;R] sB@?0Z gRiiq^9|O9B_H{cBykFhu[:/⍽:S)P?!I\!d~BdAݣԯRSFJrNS߈WXMsgN3 ޲Ӧ7u.20 ՑP?8Gwd伥$mjGZb=2ʹ!uLD)GtU޻rѿ^}۲sB$ZGć "**(X⼅YL54@5Ё7-|ct*o L^_!ક7h{gk4t<4b_p\ީ2 mTtk`H˔zawWyb$UBZÐ+qL U M򾌃E]Єu3(wSw+7*-^#dJaHpǜz>ovqyR;mN}x<tZ bȷ=^wcדA'v^|㭐:99BnW){ Lcq1^jAN-Sb>#.L_x/1Js?v kN[CmA2R=gY*V]D?TF |46ևrG/w6.oK1k]K+|x.s]:0dA m4y&ދuᲗ"_bllJACx8 ]8ѩ8n`H_&K.c1'/eڪ٘a Cdr259=7 '&AxPbw {8J#o$8kD96:FubHqxx bɝ;.؏kT\m ~,yl?8Eh1;”#W!v QӲbzqc4O$cBEGQPHssRbFkU۳ǁuPuQ{'&z"AiH+/yh190#> T-o&rrvnM\08z΂mߡ]FŞ^O~`*_9SBG 3E*A[獁LlݺRLRs54x1uܱ!Cue%|,^m;`~eXv7x8w4umnx[@n6&s.|6 "㍖p*n\v5O4X38e{PiG'klv[N\4ksk_+VBYtQkז׽;tZleL1N"j tK~%x:~,nݳh; 8w Ν%+\_1S#羔*29S#Y ~tnX3cނ2*'3*e8'(gA~d9lM1hS"7 Gi=%ChLoc`z$5ʈ[xʽ 7$'UT$12ۉNdQxy־fGH"s ҩ1վ0ъvly|٭^2aL4J 'r={#a@E;}L쏃 -̫#miFXllC\<4ww.6 1P[ew s:!ޱPh?8 1U-Cl˯6)AZ3-?9fN u*}Y.#7Ӎёqn;.ڒGq|ofw}4*By.S\ hZT[sp<+"^OJ+{٬XpVaSԫuqS־B9^~fQqU=1Y KN^a]Pwۨ<΍Ԅ_Hu knC N>\K{GBcw/۷C)!aA>F A{RB2h/9aD1g\'%\Ŋ̲:xs Ʒ4b~$=+a A_ێTR ֺ!-<޸zbL\p+}1 x|TgQJ6EBP&/3s&FIX&NFޘា ڸ3iÊEPFw&(MhGr`5jEHJ`v\׋jF{)xWTnP5s޸#e(x} ),^@k_]Hi6Z% nU^kvcΐ02k=Jy!~‰z5q<;@cC w|EϟT3x42b<=n)zbo.U%a^*V`!t{B; ``6 s(Uwl*}S!cB 0څ6v OE0kL}$*rz I"z"8_;Qd>D!Z*"?1o:X㋇{8`Z sZ4 sX. Pc;pbAV/>Y8>V6qNv!R=yqW|o2rݻщ !b Uf@{7 w۞4*H!Ri,H9#g # WcT W9-zqz>:7^L:cٟk=~[Nqiz> #at7ޠ LY'}ZiQҧݸ瓐/^V9RNZ'o^*-l:Hx >R`#R,!S+wZe%SVe9PO:lU?DYهo >("EtGrJHzNћ`!ߜ3e`m\EDWo gmHs%Fωi}Qᑉz's.r5߿ >xZ'o@tp!. iNDM|TbŎgWM'tɢ9S!,e,!gH"ce=y}Cf0%k wޯwy8ZxA.zaUs5t bcjn!_Y 1=7Uwy¾} gyӁ.Sj>{žgˍ6:eQ?DK8_O Qcfu8L%w= o'3vAYq pLHL+gF٭-(oB{Q8EL"kD^1෯0U߾,u0.xc>J=T;+w~9Җ%% 7Cɿ7* 0;P&'V#[q @s"=NAv多u>:t? 6kp!ڸ":ɦ uP9Wl)!! p{g\x`h& FjT;-c=}vK6S4{@iPc@$3Q)x *n*6Cj%~sI?[u-}t=%z9p'w엑+%Шut0~(#Tɒ/^pOMsv R~-f!<{ǾeU0?ObL\+b}بTqlvlPV1:J wL'Ƞq<<_ߐՇ^B lgT-Y2;cDl6h*0j>C"(C=e`h)eF1?mvW9ٮ]V @D[ڡJԜ*̉pcay䜡CBʧAe GSb :wϹ BLpNq:>CG!$2dp{~gryiѼΕuI[hLH;zhMw։ω,st0> NV(?kVy[M/vEo*'+i49OprG:S81 7TrV h=.Ci$}'ĞV6XWh"x 7L:W6J{~8h٥1-"Fi:%κ|˼8)N'4MlyGiYo2ם:ww!F8jqP֐8[;,EXj %v{oӔw@yP'@Pg " .ie y|4y_N:Go4zz]Mc>@ 2e<_/ [S0Q^cyb;v#V`!d?n[͂, ? [lfӠpvM5.Pz5&V1_nlPbǶ_ESP%2٭봿SAxgfo,b0DPA u[";G^"z|LkGQp"bn|$" MQ坾 ᘜc&Aj8j>()GBb$+퓻|ϥ6z.Sǜ}eAP}<܇tȩ[c b'x W#yKnhSrx8t 0ϰ:)G&xkpޡA ob%*dѯ[C PEpK\d 9o@b)ޗ?ת#z4oꖷR2)+m(ֹUK[4l{+ m-{MsV[jKi|d+nOCm:=kfrZ7*ă3D<&_CW9Qec n.1*<쒦s pK]>d>+ʔot[ ߦR&v@.zMdUO6(|6/Š2o==±DW\A#hbjb׺f|"bg]nwD{4^X 7Tfk7=R,7x_.WFTo3|X){_d(S- 1+G`M`Q㼟AG̺ JJ&Mǎ&M:HRä'ayA$׆Y%ERa[`&6HiS41M7G0S$<1߃S|d~p˄,bDU36~;w:0EC|uQQ)aTr}h m<_*fQN>,:O \|{1s"mt`ʊĔ3&u!dOu06$33?__TNӈ6` c3~

Ek0SkcMY`~b64hsɹlӗ9kyD -",v gTI(6S얶 HZ@?p3\@P1/}mcxRK8oDCMYg-e%1m$yuts~Z`'c is)?@mɵ@fCD:/CҀgS7pqq6 _M[mR;Y3맟e\DLxs^LA$LQ1,U<ä(ݴ?mrA 6N<\LJsgfd-#JcĔFQw8בB"8N 3!۔ 0fMrQݽ7وa4p Ms t.4l.ии4(=vc}gh[ZGio߳Ѐg9i-fsJ0͙Kᓄ{`7 5Ym\g! $EgbmlCXVKtVF==$M5кiWۜ44v3465ݔ`Q;滲 ׸ииx_vR]pŻDS/MI$D'4up*\@ I=ױI/wcSXAf1(աɐPIM߼30!(nZ^A"4lЏ3*G`Jgd8-5ӡieY3MиnN>)ι%L)pJ"8ииnv6Z %pZR (a9p{sjPY|bERd W)4S#U"nC6ܠ$e=t2,|唓CĞ[XkyN nL!.bG좳̏fuK$gLRzĸ3>M%XWBf3>@ 34ČBBB>ZxEMp6"YXLo1=@Xb%[M 7W9>lhOzi.&-|I!sD[֩efNHNH?;Jueuߛג62;=`[$wMY! OxیYlل-Aזt@-t ֈ?LHl3kJ!hkMh^ 4rM P75ha +uy.6o*9BQҊˉPDZ(0{^O8(#czuxW<(KYsF`.4:9Kz mEh :@t#7cÐ:~qEQƅƅ'hPB5P@ !A% Di.;aH&7zPJWZy6q|$arG~@#a^`xPBNEo-Ip~kqmsE򊟿cAaȨxϫ"0L š)J9FO~W)M3Zśy&I/V6TÄt 'C1gs%gXe;TPz !ta&!wD?ógzKe,>)d`hMo @#-r:pa;VŽ[ ,×JHGmhTZG$Vn[;$t_Q \ve` 5[2LlǚDB8lHPϖp{XV&p P^ɷ=?ปMآy]ޥaMa:FjǠ"W^ʧkBs3zBRcY% *KT /4.4.4>@#Sal ͶZ߱ޠAySN)&-bha1äeb;8 œ;Nl^ùc ;B۠y.[tK:&nfԼO~(`vD?P ǠriGlpT ;ҩqso| Ѐ$H״Bi`Pd0f2TDN"as-O" (Ō\EsXMgH_ *BBwQ.@"af}CJRLo߃Ј9 s5gӜ$9$fDF6U?NDcs^yqz])ȻииxF N:F-yH$(W9) Ho؄7&HGrRKMdizF6MI- =RD&. Xɕ3m0X8K8뎤޾z)8hd6f1ib;|D(-W]2ifbSz!T?ȕ vɔt1%snJIf;H*o# &6=.4.4.4>CCJvMc^i@kqn Dc[.j97==RmP6&/<RBg y A#[Qy/rrqy,%dF ٮT4Wर74<7Tl-rv 4<T~zv?REt'4Y  c=g ]e5PMՠииx@ Fb4G(䯼 f!ŨВqdnP Vs|f^x1 W DhLV3YHk"dB8^ց$YvI@sC4y$ n}FC1!(0<2"Ji2n8B 2(Y Z-Fr#0hW ["Tl:"CA|"-07]t M+%/O۔2![D>qL/&œ R`ٝ+P,̱Wos5=G=" Ϧ]=(q. b^7FZɓ&.`\9VͯMqx8dE؛_Ԧ<5i/4.4.4^ak_ByJ2͋L]z8&yZD>]]RRR]nr! jM` tIAØi/ҨUKƾ/em~!JvZiy S+D6 }BC:ǝň"qM & & &tQg:{ow AJgGM28vqq UL*ݪC =qlZ n9.iZ n;#hΜvZNz 7wcf2#4pie\4= +RȜwqJ9WDP QK$g?[Di)IA^xE` ]^h\h\h|;n*lle,T&9EnU(fP(nT>˖[6hx}k,%tA*HP0lkghB#e0 lYi"a<nNl1y2I|FYݦF4]Ɛb Da<1E8 2[$y߻ииeꌑàbR;ֵVQvQp DMƹmq>ݓS{ܦ SSJ[բ=  JGyj˄[2 "JA+I"T\UT#%LVAPD{e3ߺ>ST4 S$A"P>[e wht#Bq&LK;]XnΒ S(ިƆ1z8@"B0pi|qq2 p &vۋ0(ZЅ:}%DWln[ƇB4Zـߖ ,R2MY J!48dYL«@LDiɉ}?pFy5`6hv˜Ca>{{J!ܽXp% OX6~1U/4.4.4>@ *8$!SK+i]-@)aYnwD\Z(H29;46)or T (?ݴ`{";=!-Wi-O8.l9αVnxT6ϱ4ՠ64l=PBCë4:Kxni Ӭ[|q!4 >4 OxYwmlK#m`x8fC*EV ppg9Kҝ1$ʵ̝̱Cn5Xx9hH5Z C0EQ6ZdS1Ei -Eۇ$ wh51aޭ9>?n2BJHG>[74wtD*DS\H^Ag44零ZE`%Dϕ~R1:m`t>{ n?\a֬|sڄt3jC&B*qK0f')h:̛AUmb޶eͯ׹ии Nu1ܔ.ۡ<ɽ9'p8~5`\B~()#LQB 1u4"ɦlhXbDdCJ܀h-V@B{,pP w(fI߽ =*(ɂj285La1b 3zwz`$ &!J*A),ии ^T\E,40h@x%EKq^m5pNIWi*Ps !PmP<IАe^R' pJ] 렳B(@8!%t!I rɦ.t`&W)emPMO$-P$NRI+&B{&̣fl\mV1hJpqq,Ng7\J1g(阩;h(FA$?c•J{jl*.tL4. fF6'YB4pqqԁ~]NoŖQ{M 8kIAyEH]bmۺFIUᡛJ͠+?n: `m.܅mP*g11&  bHtu]_[ga!.4Z@CjG؊h|ߠr jοC1azl4/0'[q3ehMOrܷ>&i%oAJ|"ƒ{5VQ\]$bYYKH!ԯgииxI%49dhqg31A;<ȭ%le^H%gf nH\ lҠ|/[Anҥq"uy;8߇K$߲:<u%Ienu~} zn)@3iK 4Zh~/ɸCv=*~TRpv@9)DCa/4.4.4~z,4=JQ=BSZRpwG_(Y$4{X D[&왰ͯr hSZh׶qw7FF!SW#tK!7~6ٿ`[7lMȽȷEZK69wJ 2C\G 1ИQ~hии ;i \n1^PBBfVR-GAMYvÆ|wL|r  ܧAILl#*w uۤ I o:[q e!es~ oN ;F0E zEBQVVgs,ƍ(UV w5`tw|qq muC8/.h Y SAfY Tq-uMiP DxΨ (KrM, otiHvL~=6z@粋3Q8l9s%6!x@`5'4yidҊ2Kۛp 1^U&Aڀ{>Ƀ$0vߦ!wdZ0i=Ja?0: Whl26!T@&2(S逜b^Фi ;[K5 (4{ll`m3tćF`ïr9e9y̢p Xxd߄2'#/A5ކeل'0꜇"NrGI:AS;/6c\h\h\h|[y ^OP23hž(,]@di!oJS{d K@ Ũsv1<؁c"3MKs5"ٳh[dA" (.'BVh# v@2Āԝ)3Xd#gۚ';B[s;9r06cVeWJP;La0v3I:m"'3Fy()](lhywx!knQ&E7nƇN6`Sw_x iE>8=Y܋RY{3(Tɦ YKgToJlw uŴИUO ;6E52;/4.4.4~&jvaMtYB`RQV I>)p g MIYrHHr Ŝ-6L$pC2UI21&dJPRςLvl 8]H:?g*41LuʖY5͝ËgM2nG&(S sNJ٠J+Osq{?Ta?ӱ{$yD\h\h\hCÀ20W.5\c@{F+ʟHȫ1QW$y1nB>$C?h!V, $s>ұfd X p`Kt@!$8ۚi]m8=u\ز;>$|C5•͌xtV)sW"%75 ߬- xYPfhf!$څ_\h\h\hCI.4PHbci;,?G'L7 WN;,U2~C8iM'y 1. yYg'b'AIi~(f9,,H ?CƤEXH.LQh:ίagi;qg[>G9)lvܝ D `PC֞hHWgǽCvښ_BCr Հ-CrsH+yBCʞ7aˁ~پ/ ЀL;l X: .=Hej*@nAfڥT\=F>4oΡ1XA?hU>c-diUh{-[K{3R!X!s `ޤBBBt.#ڐnͱ$hD:RvD6|i)ۖ%9+nJяq (ױ1E_BBBwBNi vmr>dzlt&bu5@lg;v[;\MV6&/؆Gl߸]m~?HppEۍ&ffC#!Zԙ&NJ܉61xUP(!SFx"M>)J90OUl9?< f3R׳\h\h\h|^$B4J44X๩$ 840܇Wz[s>7܆Ff9wd21wq# ܻtho^p `10!{J=YOhdhRlh}MnLaw{1 6/@q*44vJ"=꧟ޠL64xf0 HM0BϿииxC7)L .9@*M쵑@ʨiuyݥ?̦y9O_IEh $g %[\ɈQRÎt&@8A"Sln|JhZyTIT'MdGtrb`h1F cP1?]~ĄՄ@Hv7ՈݦAB-~աииx@ɹ e«$"؛yoo1p@`s !M Rh(0 r7z&w6yMg얠΄Wg|Y~wţf6^B0iVZז$fd7ܔ5Ԡ 40leuYT1jh~,ииMLؿݭf: ?ﳵJS <՛~i%-5q7O_9|@GB~s7M45~_OMf>U?ÿɸk*#6o߸ ksM!E-Lp#ymHBIGWFO?sP$G11x^WB gX!X^ռ .tV…&4s {r )(^Jar fbPAoɁC+I XUAGRN gA(aZfʦ6 ´ӈ\7IE]KMv懕wM~u/4.4.4^A2>ElnՂÔ#%IwAi'JkW.UF^?Wee$9nN3l*}L 04̵*i#M7h.hK$5i`LQUCZh҇06 ? q t.nv1po>⤖ fm!@y0p Opkl*&b !e`vcF&ڀn[qh~I؎in*t,#D@ڗw b)v(tHL#|fPN}?v[nٌ1Džۗ+FR[ju1&`}`]jm ӢgR$0 q(8҄_] Ј)&<_}ЉК/^N3rBCbJ{2<6Jer$l11ϨR$Y5ɢ]e Ck'X(fB%Ʀve`gM'#Vi͝a6\I!qP֣j1wp%ƹA֐dLOsiށGH3~-2uqq%IwNU`WF Cbt~IK#mR`ND0lFTiPu%7И3OS`ͨqF)RwJm*HV?Mz$@ 7F h;ljBBB4\*6^ DJLK&_w &t 3 Wu-۠[HIAn7~KwΖΨ6\,QPcV*vxYMjTl:p11p &$6@E 4ov@b7Ѧ# yk"ソuՅƅƅ 4( i͖ytqϤC&iD.?Y̦N7mqӪ %AqDϖ" N@ͼ yY6j_"|dy,teB"qc.IW/ukFq['pgst-Bas!^c0 qwKZs4g"S@?@ِI]+˩/4.4.4^A(h6PLBt"h`UݭZ%$p-7HУ.ǀ씟#wSGBbO}[`v6-@h7Boxe%PAMR8@10,`RǑT<e0ذRPmYn}F@>a ѳ¹K ߼ииxnO'4a !ZQ&Mqm@%3,Ɗ0s4g&›z@O?QT.g\-EZW 8(RP̠,yh B Nf2<_NchB7:κ"NBG';aofIB'#]0 B*/̀BBB34H3Ȭ`#J5 N) @e ZwER93V @Y6L8m8  aAÌ*B4B& l5KQOX~yMG0;q6;<,&JiCCc Q_RZs*銶R ܥ;BBB㯂F&hrGt_ qOh4іT%ӥB<T^qBa^n:6~B)2$9u30G&ځohw $2Mv7J[3kmmPCcqoh$>{ - 4ƅƅ;4I st_i%.]TTJڠI/r5(Q,!|Nv5⠒DFc"G; g*s톇f$+ d͎$-mB< :`8$wi̱p0P O~;WGB:=I 9Ca~\ qpqq]Fo*$E ߲gx3&=KMzF»W\K dv+Fx,?秅"ܳbIYϞI6"IT M﹮܇LIŽ[{_ftAE2/6HmU;8Z6Rx10#(050@t0L2͊K& b=G |d[G4%bjzHjsclz!͑I&`O 6$|`3mbkj!XSf̈́А>zWz=K Ǹ:MC*_BBB7!AS~8V%҆Fdnʼn[Q[')ǙEK??;ALmq8MG"up϶MxkƦS}sZG)y瑞I+9i"7?7<6VGysTosĜ{:o$ }gX}s-|7їI.4.4.4ɺC?KIż,氝v^4$…>88)嵊+F4}\תnnBdTBq h 7b\D:t9hS 6e`f8`d= BffCuTGԲAz` W؀GLLs2uܥ]@:Dͮ3kҾE #D\ бDy/4.4.4>A۾;MIsDRϔo^\=9d^<.'#%܈sNlɹ_~߳`X:ˠau$ ־V7-e7aV4Ygy pԅg#NTƏ?Nӛy6)Ӻq~i%PP;@u`m+j @˓G8|~ zqq Y`׷K.j'Yf7 a9wO'R0mPZ% =wEidOM!z(~vѤ1lrkPuK<Չ[ )F6Ѐ:b-HֶT۞ͺAͣ5=}tAf^O̬s%Nj/{3*ЀlSy'䀥7ؐ àz.S+YiPn-$ MXӠʢed3v3?[dAi)eO * ak. iPʥ[5t{K4$Gӱn&.1j ɍ'4$M2ݢZD.4.4.4^!К?kFH%@&9g6  &G'2$ŔҼL:nx·DJ"#n2#Lh v¹HA2rZ `yn8I!q[y̹ LbN)|ޙ4UL.X*֐{fMhP`=_ WhqƦ|?3O&8N+w@ϢucO3-,9XN|8?Rhuo &#^`m&q(:}xP'mw3 xfmoĀڠ:07 =9BBB+).N{NyeYA͖eZa;1hcXٸ)F&iHτG!!S=EX.mq5پG&L@8K9'hȆ/1s]۶{I댔̌6i>"&-ZJ )0Ivi+p,  <ąƅƅ'ht(r.Oqda)jA#㷏4!m┏ozam[&аi;#LH I`Y`R~?3i"f6E~?t4yRfSl4!WqEoY㯔NҌ|Oh6.~)r`;/:tqqL&LX}@#KbZИ IʔMn!.̇-#hlӥ }AٵmP va!(inG$F;;b4cHXaäBd/NRg<HРJR7˶A7~{f<.@"4v2 ߆FM$-⻷,&•8ߟq6ih fvq!ƃT."#mTI}gBůP蜥 71u1~gK@9UI5SA nTlki4RV2hJ[=v-dGr?cPe44v)QKAƅƅ;4vĄ *mIak3W#G~Kf༤zh%AiB1=Gd%xJ(p!]s7}L;`*kB3nbb "DL>:˜RNi!;Hp{RZP@..tΜ46tDù3Ly;}h5AUO ZP)INmĘ4}2 λ/4.4.4ޠ,D]eؓT##9YLndXlI9(2vRܦELKn~l@ 2ivm0AПN ꢕ4= Kx>l\d  5(åEC!b@ 3SCD ⛻\JЀ{yMxp4t]ODCmъL >޽'44 Q_h\h\h|l^n:S6 H(P1>1nF`l *>.74ktȜc3*~f@T! aFV)[ez,hR?%X~qq .x%.4DAhRD"{ ؽzdw+iUrl|~T*@Ϧmt9i%}v3puн03<vKo'1>49{]Iu{A[+ϧ܃B7/GB x^JYE1Tp ByI):c@bh8y8ͺ͖cYԠ moH qPm*\D맱q#AFӱ$$Pqɘ.3x\vepRm$K 6`1G *ӉonlXݺ(F\ ,@=LbRO#,;| B haeZ t&ǝeX/ONscHe:Aʦ ]R63w:μ/4oȹIC9HOW93[B{L/IGr7:||$9se;MC,r#rTė$,D&|5Lr-pqq=hdy,b3z[qy[l_XI;2`k*{6%j8[2FO4wj̨ M7OJZHTA~PKŖ{Vbd1쇘7@$y}ʙk~Y L܄Ј`7CPxFUJtsAl0#!=?dƅƅ;4Hr j?_<z01U<:s2w?0'4q#&8NCnzR"AUp%,w|G*4HΣYʹ)6G^fPa~a9vx]K yEJ~Z0(ȟ+u/4.4.4!K[M(hwSMZ 3EL2㠼vؙʭϸ|cCLjblhb6jbbZv]I-74$fslkfbq(oq]kk2D}+7aϷs"4RfjN%;:CB#GOi8-ʻ^9ƅƅ;4N@.vMf79c7 y~$s>zăv6a|o ok lSL?lv3zR3oc}OsyնE]h\h/BJ1iɫ_}s4Q]1yMrLvSZP,-Mc@oA@$楞J4RsAns ϹVLhfmv5M HT&9BVdɈƈKڕٜ3q'J $@3A/mmRFs)S#! 4Mc2t"U,-:k({24"n sWSBBBE -h(uKu3#Fb!kA&(N٩!S(6dk3.62= e HA07e@ 1 kb,Ŧ䚎(5} )hI:Г=7pqq ^,,&j ӡT<[ 3Qta7CC 1>KBiq&5Z q([mKe *K 44]HXƟM&` |U |n|2vKϧIfnc]\=6B)MpU\~"&4HAEC%RfԨTQ ry@iރiwqq ђbj2O N^wX:E$}s#åIl6(lC pܘH`Py7gȴ92 Spn{_4(똍<ژl<Jk!7w {6Ni K8BAsyn4#sON1f>xI S2e$Ix~4&V&2B^9W;ȅƅƅ 4,WF2G#DIB[B?HZ3 Ex |?1,Y\a&Ff ]6]oB3cD=;2A84)IrMQącd۳B+3C;n-^h| #&] l]+̄p ]2mM󷏴QZ` whlj26(q֞#hhHҍ͖]0,-!Ő0!aTίҾ_b6~B!* LMz[!͌ϦЈ ES&J%j,/T4HJ@FVl1 iJAiV<#|F R[dq@FD'(iGGg(!3PqN=mr.4.4.4ޡnHlLJ((kAx  m)r`wX/;AoS  Q 0L AW1-;O4C-OC[ u"b؎/PON.)E`K^B'(kVYHd$z,sN>zJ|r7i07w!ig;q&V2;Sڹݗl3pd[e +qIMGT!2=Q2e;iv |fvƅƅ'hwm%$4IVBssrVߛ׍VUG~$BLms)oJ:n%XS$Z`nfblcZ n0-ѳ 3A#WOjOF)<8ӠHnhs~ B @#_eL+nxi@KِA {42 6kQ,J΍o̸)v,aK A\`XzHQ@cE 7P2v-&`.OIX,suKy !:jZFė-@ J N| NzeE,h蛈+ejq<=S\sS~4wVgĹa!`B*{- Kq[ 0*vEACgfUBA) ߂Ď.!t&ch&/&\Xn )ټb)ӷO$I&CDoh$(%f"'|9c(vC# h ߦL ] h{Y68I$4'4m9䏜[f*ЀJG`ЈI񷓌:L=Nrvrp @[$J؃>g51GHXd4e՘T.4.4.4^aS)+t+ a6|e7It/>I u[eo*YJcFTiP8)k)ǧX'1IfdрM!MƠ81L1)ԉ|T6 HYʗYWM;f$Ɓ&E'9m!ӷmzA|ZȖΐ HthtHEȢCK`§8ʊ97'iIAmQv%4F86G||FC._* 5̔5KBBBM'M,죟g#s>n_y%|;It?iL{;s﫟4|۳ywkZ|ރf@ot{i%owúи8U-P§*ip,ĺ:p X^J|k)3]th\[HL7>R`vH2zϑⴸ6:}n͔|1M_E|ۡP0& kXz#P.jY='AtIJy{' 8$όoy>1nr)j5eOfρ;M(< b@ Ȍ05•$gܐoߡtc;'T='IY~'Q|C2)CMLZ4La*cRM6ampل3ۊ:}Ǻ4 +}FM fии ʽ[y64m' "$3R?@lPAdpxDj-% b%ƖxK}H4BhXT]$! v<641<\jh` A= -4 Y[`Xu%[s f^<"]h\h\h|ƿsM-+ɠjxpiR$s@t 4JEViuazN8.&jQL#H;_@tEKL2ɘ-ɬ a/ی@0Q쒷{5% *0ГՒXv Dƅƅ;4/t5RW ρ,WѬ.4~!3ADLYe& :đo"̡а\6WԈ/%4$5]Zm0ιg;'؜RPH0`ze?0h"]:U4K\eVi܉<-['u>ݚGrٽ4´*Pc]h\h\hCۿw7@ 6Dxi3o^ñ)sf6ݍIMP`(;hZWx#"D?}!m`v'7-Os69P y(({'~}sz~^{{}΅ƅƅ+4?~b; @ +  πpK r-n c9l"6y125d s,bL (" S*FsIvq0T ':v;DZX]XG2 4|qGX :!i$%D ubb~)-w騺VR e$g whGC1 !k6 l74`hs;;ƲE~_ d`1aI% Ygv9c)[ ×-"nsLz^]a.3| ="ͲQ.T |<9*yp#Ci-P!G`LJNeE$Q&X/40d%6LH)Р8׆ "44(0I<JbR|3 3o d9 l2& 4lFyDaBР!CMj4&b l7ٴ Od۴'rīmɷ~J xLO}sZ)Ȍ];}ZlBnW/nWҤGwJOۆԙؖp`y,E@F 69٦cʼn4*۷̙9 V3E҆w醧$$Pcjgp :(:䒡<; 40zڠ'A TMB!,빷4Gqv/ wh?hPLzElR, 0p_$fq %i<0"%HRbBI:L NˋW\O*8˩>i]$srR5 ="s)"C䦛0q=w&AK}Ɣ$ 2- A@XTĶ[6;Ή&3ΦA ((h  ڴs2 šĖz1,=[;0ՙ `:lzBNRɲ= \h\h\hC?//7f^}Hl^JsUfG2id~'0a;`웬Dn!g)4zLɸ=D.382ks &&-ar-VR-M$s34(Ⱥz1R d ˃WPoZB`@IhEl νݞ ܧI-ۙ Wh_W_4\F4(y4'̇[/lKsI-KH$Jֳ'&X4 ɜmh0#!6ga%Ǩ̻ ҭI|[uҿِUBׄ2o=ÛBa1냣JI}] Wh7w?'?$zCr~ t>w~ !VaNgikhoMl.}-(@s|Ȗ=G1S+.I5u~7dN$HrM`zg"؀WwI}rLRlF7y)pJ la>Nvޞu&9:$0>ииx??//_mm/R^r!~u W:v=DM9+sBT+ۀOop90UR% mcr^QL6r挩[6`1 д!eD׸c%edf;08>D0QF3f(1#Ӭg]py 8XS  yZx" _ϿwRmԷyFE=ih9PNٚMG'-Ѯ^X(ReI赁&nj8bo ѡG![[Ah;wt581t # ~ (D#ۙgg0F`u8a,֡ 0<{Hytqq1mRqyYu.< 4N{L # DzЖAih (2a1S?KKږa."msccBPhˍ!u4҂oC 7of)qCmsi EtqF2`F_:9<~ڀ%y%c)w?o f1FTTGFn׾º$`>V<7?&$nNai B fơóhHcHiPe~l *fOjVWC$NhicB6_G!:ҖBUʗ443'gŵq/69%+Auqq O g6JntNA {ڴAUvvCon8]e~rƢJ S,aR]d[Vʖx9[r=w%n5un80|!>*vJK{=qnYvA  s F pKV BDagIgYʗb !wg%q`BV̸cLInn2e}wM/eЛm,Jdz.~baox\?庤7 {V2ěpUr5ۊ|0",ܬIz!7dxnF&hgL?Av;@FlzÎozXxvM䃍r{nXps16 1#QwdugavRf!ʷ& p.bN$&;}iu\aE*N~c5GNUgn%kIn)KNr{lKM?[eUK o5*4H6"Ѱ0 K=gpxx%9cjf|k\:J #=' +{ҙgw:0_rB!H_Z4 s'5CtnԀIENDB`Carla-2.1/resources/bitmaps/button_calf1.png000066400000000000000000000027211364475620200211510ustar00rootroot00000000000000PNG  IHDRI}+ pHYs B(xtIME '_ECpIDATXYێ6 =t3-cJ޺bOTfsSt/+X0ܫh _p n44Y+LҠ!`wehWfQx1h(4^œHEY#DL>A|) v(\M8HI+>B3Y S(o+MAk( 9J[^K)vẮ)*P#oSȢ2ԩ``T(dcCCx51D2#P:E2|_oX9T0 ,ApQs X}AݸXXGtf<*mlx(S^I8|HG`tF W6|ϝ9NdYn7|u?{yϬ~TkRœD˲֩~W2 H4}\)OT_ r &sҲ,xyy)=^|/\lSQ_aX+P(VYyqvzZ`0Wҋ5_4%Hұ*%\WDI)f;b D 7p RxrP1ZjcDV=YtVڔFf^MqY 4%ܴj5-J굮v@ 6KL?JAn;1ϡ(h%b}]:ʣ׵y ~z}=j}`.!LTi]BȾ=xkzH =֪=G.X8k*(>Re@4CFoX2sz X Np$uDxE vvq ~]wEW 5f ױ.J2ٻTJ?(<[_Dk/ձT:H3n&g-մ"9i ݶNx&ft ݕhl UvOD&GYp{_ך_M£>4Q wf|F 2 MĽ,B] 8j/ p^׽m b`ju!> ɎIWjq?i7/QLv>q>ۯ7Tߏa@Gp+3D؉`?Xۦ(`利?Z1ؔ|tGK}K4~V;뱒!mi(1Hr$GP _0Ucpm 3ٿxj?R6yn^/tFlIENDB`Carla-2.1/resources/bitmaps/button_calf1_down.png000066400000000000000000000027141364475620200222020ustar00rootroot00000000000000PNG  IHDRI}+ pHYs B(xtIME 1&akIDATXYK6ӋN9}.SDŽD,0?$W٩Hf=R~ ooL4ޖ^z-`h5Pk/VozV۶okԛڶ>꼓 (}5dJ_Ks뗗Eߖ >Aa>kAnߟN~Ƕ (" N7a0zD%Buj [䕨*UzEBD;_]1yo8'k\e IUh*SԞ!9@Bԑ#MaҡxM2ϖR|q]R+ӻ~5@VN-(=D{L!5IՀ1owntd?jILfó,6ᢢ@0i3ΏyN7P$1)t,m7J?A+ >40e}R)S3`v=/ٮ/9j>uSGNc)EΌ(?p7k4M+O;4^)y^8;,b=NмB%`u 4<.:ljܶ0Ffh@ؿuӆ t+uHɸH?͏aH( \p]>ӮJIغt =(6ӨvΟpIƳ1Gˬ $3۲$ PsG9Tv=͛k |(t4NQ>_J$]^4[gGh ,/Xvtٸ2H$8$Xʜr7n/K 5FOIQG3lJV=gg}*6Ķa#Q7~cܲlmɻEv}]$Eg!i=|bDk`5dsd" 7g#'$ݞssӏĵ 'IPw*+${Gyt SN'q/yCJIENDB`Carla-2.1/resources/bitmaps/button_calf1_hover.png000066400000000000000000000030421364475620200223510ustar00rootroot00000000000000PNG  IHDRI}+ pHYs B(xtIME 8,M6IDATX͙v6 ?N۴b{$i˖  HN;SC" '*O||>_'+LR۳dG'{2YTѳXje־7+` kO}+[smSb$ 3 uL^9$Gȣ'<2rH] x\֟(*UT*gP͛QTWPAQ~+hƺ,* ZSM(H$/ĢH-*'Es61PA}2%U_jUED JJ3SIA@BCj˲pgtP]IUh*Ths Dն0gH@FP6@Uc5cK)1ܸs0)B yϐDI*+S ( $UcӻI;z/T?:ߘ{sW:-x<$*6]jTu~G E& |.uo &Z79cB1,hRJtv#=0//֪':8j}4JHF 'q sk)idiQ @J===MJ2۔WlI!É}FcS-!8G ԁk 04xPiuԥ(15jc|Ar$wCdÃ,pH37bsnj1f ,8Z#x!H":[E Zq6# .EI+urǽO(S5J WX:6 $rٰi&aS k"j֧N4~2IcJˋ&͎J99Cl1)7K6㑹xHD^L&=5x -V5d$[cd̓Ipd&(XsB&US%)!m)aChoKnNr?PĻLTQ+HvUA2䮗yt5S?:2XI8{1,U͒Cs;} ݪ[IHɸH?ݏ)=@)S=t[ 논mvժdx)mϐ` ԫ=}u>WP6GY Ф%uIXPaj H(VHwpqaѯr4j>=H}J*o(yFEd*w_wǹ#Ԉ-iIENDB`Carla-2.1/resources/bitmaps/button_calf2.png000066400000000000000000000027411364475620200211540ustar00rootroot00000000000000PNG  IHDRI}+ pHYs B(xtIME . zSMIDATXYKn$E}QSdكdYg{$[p` [*0 UVWwgfe4%ٕ߈/iA@D*Gwkڎ&,'= p}3T1,ս8fgea`""LIkQwD}!gH~ hfX0J?<'wۙ2J!V8PX!(Xc?`lAd/S/8LkIU_>U %[mA"g ,}*HIR ʩm`ۅ <QjE >ZbI P"ڪe-ƾݓ$6M3v%(X4 x@aD)xUQ^c=^㹻3FEO b'TVf='h캺zL7oW )ﴘ4A 󘘁{K\_g !AN =~$z8jA'Mp(Xa}YLqJ$y} +(kߎf2 yq6x)xc+\׀p677'%F+(Àe!{g)&k<#`yUYMZBlgI f-#=,{{EhdipyyiiA Owqptq6ecVxVϽmBy& __6Az얰<+}>rG<??ee t ޔ+ov钼&G">'Q(jL=;f 4O%SLZHZmg74drYú8-q\_X}H{krD_OxRΧ+:z`5 l?+6Q[Pg̈́214{D|dBm++ՋqȮ4l%o D OgR7#imFef||ZXLzmWnhfk?tdH1l :??Y+4oˁ/ d,@$j }unW0"L(vƺ\N)F "ܐ##S϶IENDB`Carla-2.1/resources/bitmaps/button_calf2_down.png000066400000000000000000000027631364475620200222070ustar00rootroot00000000000000PNG  IHDRI}+ pHYs B(xtIME 99IDATXY$E 7wҊ`Z- 1x r$#"%bnk4=e]vu임 ~쪲?\jGf@ @CI]NMAT 6Py0Z΅(sg<2AJ ͎KR@HSrdXQ3_OkskLkuXfp,e0lJg7tsk ;3Nc134ivU *Odj(`˕לC4¡_^ 3QaQ)5hx :1VZ g9PRa@^ ȖPl8&@stAV:@$.IT=ÄȬX0|\59קv;seSz)j; ; FJ0Nb'${}Y&a%x;CUd˲R@)9kЁ =gx4v\ՓS‹E:8H~ ^7ҝI(%q?{KF2!p@犒5/6q>jX$%'zqK@%ޝKֲvk{7m^n6.9}}eɩbQ&? ҷaȵ#{< r,5rnF!M)*"`窞fsz`v/SO;ézc\Gh|Jk;m;g=b;k. 1-gܻf+'!.$oC Rz~Uym ms>%ݛ_c㈖ijYycfl?)] biLS7,`OdW jK bU[Ig TwV&EOg,-xhn5NJ 4i~_{9d)mQ@z*#?K3ZŤ${d-ayX;= xRͧ;z`% BV]1ڂ:kጡw9,O `($Pf +.qȞ4lM"5M>$yS#͈AZImKQ<7W֤Zś {+bn A^ GO*ɍ`oO4{OhVmg@H<x`ܼ'뛭|д6}'Z0<.Q_i\!wEAmDmhh{/˸#\w 94YgF'ZSɩVT? I*UQ%ZnƵvϾ}h9e|*ҫMXs` VUJT@W($rH% ʸZhi%˸*} ׺,'SF!" Ơ ihqRXUWuoP*,dF{JE}R8[iw|@\RxFHXm JCB/tB`d)j\FO:!H)嵉8!J~"6Ơ2@4+ z*P1\_ RTEʦA&n VFk^R 3H; \s+7c.S[h=Z!B- WE0oW"-Ѝ@2' H62M)aɞ!a7;dP>|pAZQ+[r)ysBly~ ߻v4Mݼߨѣ^j+Lۉ7J=MA;:aJ 豿N,&so'WUCS,o ftHO3He?QTB=j78%ywksu3A< S3nok$Ҕ0nׁTNd[JԶCb+4=;f8MRo}HS O0sԛ>)I {ú8큅Ҟ-)U-'w̋Fզ{ZiFwO4z 04l1llP%]iY 2GȜn `O2H|Ɗ[x# ۓH_{b p O \֥\oEH{W9)J-yY(OiJxuI=ۜU"s[$0Γl,ˍV4=`_b@ jȯTF7 )(WU@ /r@Njl϶e3b/mg i2^5+d1m*ƽ@c%|y{bcwP,Fu~G;hhhFFF G?yyyRRR N H:&U+\,\-]*Y'T #MGD H $O(W__^!O:@'W-\ %QF>=A !J &Ulll J̴|||ˋ J IttsN=oop M F 6; Kxxxnooiiihihihihhiihhhiiijjkjjijighh C 2< A K"P,\,]-^+[ !O F@0 D L"Q%T+[-],]*Z'W$S BD pHYs B(xIDAT(c``ddbfaecd -%-#+', DjjjjrZ :z*** l UT UUML-,-,,,mlll v5app<||q@ 4,!B+2***:&6.6>!1)99%5-6..(ΐ/(,**.)I8ˁPU]S][uuu jl3Zҭmmm Ё:3M{z{z{'N8w> 4YgiӦϘ1mf3M=}֬sΛϰ`0Zxe#V\͚׮[݆ 7nڼfVm>>w߹K/6nwٻ/kˁ #L9zݱ@gSdx?;ڵ/wIENDB`Carla-2.1/resources/bitmaps/button_calf3_down.png000066400000000000000000000016261364475620200222050ustar00rootroot00000000000000PNG  IHDRu}PLTE%/59=AEKMQSUWOMI=93/+715񵶶;駧3WWW===?hhhGGGyyyRRRSKE?71 #39M__^lll̴|||7ttsoop-)xyytuulmmihhghhhhghghhgggghghgyEGCm'Q#zq pHYs B(xIDAT(c``ddbfaecn.^>~6VA!a"Bbb@JLTTLL\JJJZFVNITARRREA *` & f8%35`cix]\=<=}\]|~ @@tP0ADDD$D펎̀v 1Ń@HddJJNIMIMMKHLMLOLM,9y윜ܼ| S[PWTP"TjepVUUC|UuMm]}}ucCSC}CCuc]cu5.<ǽҶwi8cVM0%vfzO\1风Bn iV+ozm]ۮ .쫇${!āe#jj6,;@ʳ-ug]jꓑEeڍu vnt.S<-ʓ0o=WJSVi(7{o>OW:AIENDB`Carla-2.1/resources/bitmaps/button_distrho-white.png000066400000000000000000000007151364475620200227560ustar00rootroot00000000000000PNG  IHDRn pHYs+IDAT(ϵMK[QƝ$%)Z ",Hҁ_$"f7TJFl^^ΆuxF,, aM#Cw*-op6mcȈxyL[\ar ܱ싑q8Vdɭ,/eFn΃, 7\DÞBӡ3j!֝jUi*5Uv5ZPon^tT:4Ѵ+upkm:CL5,gj3RifLaeY>-E*`XeɍPXWs>.m:2Qh92}sl _tPGԦd[s.#u멍zu\Doxf)/g°IENDB`Carla-2.1/resources/bitmaps/button_distrho_down-black.png000066400000000000000000000013371364475620200237420ustar00rootroot00000000000000PNG  IHDRj qPLTE                GtRNS@fbKGDH pHYs+tIME -8IIDATӭKa- (h/ IJ,wTdB~qFQY{q>)X?jk*޶g"56ֺuM yJuzE@DSzg@\Eh2Wⴻvw"-#&lc6O|y\ޑ[ }W*\}Wa=w6,]IENDB`Carla-2.1/resources/bitmaps/button_distrho_down-white.png000066400000000000000000000015401364475620200240020ustar00rootroot00000000000000PNG  IHDRj tPLTE8'rtRNSss^_~~\>+\&'r"9"r8;)*;)*⿇8s#9s&^>+^~^_slJF pHYs+IDATӝS@PF@łbXޅ$ O|;;=|RPXT\RZV^ULuM&03 > 1p4JMRsŌִfGgw G)n[^>: m;h|Ta?>A?MӂgYsn>Hr O,*5댇I٥0'xq5B1ET *<s}.-Vm{,/ǷV‘65C~cuڨeȆ붵u&9Vكxmkɰ0v7y(u%Oax3bߧw|SWra/&O$ҸZgALq#ٓ;X]Y^PC>RcRagpAIENDB`Carla-2.1/resources/bitmaps/button_edit_down-black.png000066400000000000000000000007511364475620200232120ustar00rootroot00000000000000PNG  IHDRj PLTEӸtRNS@fbKGDH pHYs+tIME &H~IDATc``db*ŽU˕06aAw!TQ !!*," )_KM\$奎n6>{c0p ` zxa G' 4vIENDB`Carla-2.1/resources/bitmaps/button_edit_down-white.png000066400000000000000000000010601364475620200232500ustar00rootroot00000000000000PNG  IHDRj PLTEEtRNSu$*Tt(1Ɇd:~`~a[U%XlË2@] pHYs+IDATӭE1 Д&vztdT/x,ptv{(,+0cXX>s^^P#l##l#PP^^s>X>s: :bbZ pHYs+IDATӝGS0{5@(CJB 6v3Šu ˾fF(MeS^**rjZ ==Y]wE%|'ZD$B6ep(Xl4N4@J$3MN:=Krw5 @^0xRhWUSIJ[j{'3*px||b 鳄R"})u-=W|}#R,s6sMy|xf~x}+zg_~:ޕIENDB`Carla-2.1/resources/bitmaps/button_gui_hover-black.png000066400000000000000000000015411364475620200232230ustar00rootroot00000000000000PNG  IHDRj PLTEFHtRNS@fbKGDH pHYs+tIME /0*IDATc` s q1AKHJI+( (54utuu4F&ff&SMmlmLn: ?T00H#8$ 3c ) Pi@Pc2s@ܼ%eUe5ںƦԆp[{GgbWCwwCWbg\IY!L6}”Y@<{N\ 5-p,\d>RIENDB`Carla-2.1/resources/bitmaps/button_gui_hover-white.png000066400000000000000000000020631364475620200232670ustar00rootroot00000000000000PNG  IHDRj PLTEcbbcbbcbbcbbcbbVSSPKKQLLXTTcbbcbbXUU`^^cbbcbbXTTVRRWSSZVVa__[XXcbba``ROONIITQQ][[][[[XX]YY]YY`]]_]]ZVVXVVb``cbb][[OJJSNNXTT\XX_[[a]]c__d``XUU`^^YVVXSSb^^eaagddjffjggb^^`]]cbb[WWfbbjggiggliinkklhhfbbcaacbbcbb][[YVV^YYieeiffcbbcbbliiollmiic``a__OKKQMM_[[eaajffcbbpmmokkkgg_[[ZVVcbbKGGQNNXUU`[[ebbiggcbbollkhhXTTollZVV[XXd``jffjggljjqmmnjjdaab```__]YYc__hddliiljjjhhkhhnkkpmmhddZWWZVV`\\iffmjjnkkeaaa__^\\RNNWSS]ZZb^^gddjgg]ZZURRSOOYVV`^^a__c^^eaadaac```]]]YY\YYbaaZXX^ZZ^ZZ`]]b``^[[[XXWTT\YYGFtRNS(G,Y1YPㄘP`_Ǒ_:l/l>L2l_ő_℘PY`C pHYs+=IDATc` фYX98YX\<|B|"\Q1q I)iY99yE%Ae1*2C#9cS3ss3S KV:6fvvfNV`AW7w]O/oo_?π@WkPfHhX8"ȨWpl\|BbRr HgJ_ZRbB,Du:BuPu+쬐\y9E`.).)-+(ƴ榴ƖVU;:{zzUa?a١SN>c,1X37d?E7! O~IENDB`Carla-2.1/resources/bitmaps/button_off.png000066400000000000000000000010721364475620200207330ustar00rootroot00000000000000PNG  IHDRj PLTE^RW!!pWz%%jf%%''}K ((r!!&&f ''kq$$jT!!##rUi$$''""n##a$$^py%%))((,,,,))++++++**))''++n4tRNSD9r sY2mF"0uW% D8G$$Tp*gD pHYs.#.#x?vIDATӭ0 и *(+ B0>ۗ93)O VB n7 Jbon",9FM-%l;j;TZe%c6<>!GY.0>gb1{2VA]bjpPoT>VAchVy[\aw}KiOIeMv}~Y|^5J8[~_ejekQqUiozIeMhm}LjP`f\aPpTtzKiOk<<# 3NLD gb>÷;m'/Wjyzw"1Av$nxm .1q zI&pDK8  TeQL 7DdCV%lHZ7 n0 &7y&#A $V 4Gp4M1K5Xݡ?   E :*[9C :6:;Oj !#""f/VHW"POm23y]_2" (( (( ((EF3Y'l v v v hb/ 0Y/ qL , 1z05!',!AJOޞ5pe#h (( ((v vnD "_6 LADSPA ...     /`gimp-text-layerD(text "LADSPA\nDSSI") (font "DejaVu Sans Bold") (font-size 19.000000) (font-size-unit pixels) (hinting yes) (autohint yes) (antialias yes) (language "en-us") (base-direction ltr) (color (color-rgb 0.000000 0.000000 0.000000)) (justify center) (box-mode fixed) (box-width 95.000000) (box-height 54.000000) (box-unit pixels) 6_6N_6b                        ]                      A                        ]                      A                        ]                      At޵x {Ҧt tUY tftj tt(D tnH!t%tt? t)Kt$f tA:t)< tt E tCt$ t St&B  Өth߮ \?V +m޵u 1tn \޵x {Ҧt{ҦtYtjt(D D t%t??t$f$ft)<)<t E Et$t&BBth߮߮V޵u 1tn 1tn @|           |           |           |Ζ HUtyftjDtgnH!tjCty)KEA:͓tCt St Өt\?t+mtttttttttttttt/6 New Layer     ^,6ee64NVEc6O9:V;<~<<=cOOOOsLLKf[L99C887u 6332A1L998u665> 2110//J776443 O00//Si.-I6554I221_ ..-;1,G4433100/2 {,,+0E221//..- =+**)`C00/R--,,K ))(C..-++*e''&5A--,,.))(w.%%$o?++*^''&8$$##=))(%%$O""!><''&2$##"a"  :&%%$ m""!!(68$$##  <I 7""! 9JX5   |k C4 }*V53~ E370| U%m/| ch.{ S"M ,z ?1   *m !;  zs(Bd     '     ? &   w+   $     *w "   M   ]8  ;#""! &r =<<=V;:O9c6@Ec6O9:V;<~<<=l[[[[YzVVUndUEENDCCB{ A>>==K;UEED~BAA@I <<;:99UCCB??> W::998]p77SAA@@R==>=;;::9< 65549O=<<;9887 E4332gM::9Z665S 2110L887443l//.<I665722110|6--,sG443d0//.?++*E22110--,V))(CC0//.8++*e)''&B.--, r))((.%%$%<@++* ''&&%B##"M&=))( ?$$#P!! [;''& ""!"o%H9%%$$# ! -Y:8#""! I99"6!   X)o"4 fk1~ V%P0| A3.o %>{u,De  *   A ( z,    '   +y   $       M "    ]8   <$##"! &r =<<=V;:O9c6@Ec6O9:V;<~<<=l[[[[YzVVUndUEENDCCB{ A>>==K;UEED~BAA@I <<;:99UCCB??> W::998]p77SAA@@R==>=;;::9< 65549O=<<;9887 E4332gM::9Z665S 2110L887443l//.<I665722110|6--,sG443d0//.?++*E22110--,V))(CC0//.8++*e)''&B.--, r))((.%%$%<@++* ''&&%B##"M&=))( ?$$#P!! [;''& ""!"o%H9%%$$# ! -Y:8#""! I99"6!   X)o"4 fk1~ V%P0| A3.o %>{u,De  *   A ( z,    '   +y   $       M "    ]8   <$##"! &r =<<=V;:O9c6@3{56.̔9 f:;6ș<}<<ϙ=șۙșƙԙ șșƙ șƙ 㙙șƙޙ șƙ șƙ™ ٙșƙ șƙșƙ͙ϙșƙșƙșƙיřșƙ șƙ șƙ șƙ șƙ řיșƙ șƙ șƙ ϙ͙șƙ șƙ 陙șˣ Ùșߙ ș ߙ șę șꙙ ș ՙ șϙ ș󚙺 șę ̙=<}<6<; ˇ:.̔963{5Hbst"t} H" O d8 y V|w" |w" d|w" |w!|wn |x110X|w//6|w%--3|w,++N|wesw{̻i))|w%R{-  1\ɼ}''g|w7 ʿzgn(%%J|wH =Λ}7$##:|w h2͙%""!D|w'0[  g|xJ\Q$h\|wjω/]KN|w xƳE,|w*$|.|wWɬ1|w{3M6 |w (`\ |w Pҳđ' |w zO''n|w Z|w =#   Y|x mB   X|w vb|w 0 |w RD # 2 |x"'|w"|x"|w"|x"|w"|w"|w |w |wj {w Vq" V~qvvp O &eҏ 00.M17124G`rs"s} I O c8 x V|x" |w" d|w" |w!|xɲu |wı;;`|w998@|w%7766=|w±544U|xo221|w !7j=/$ ,?lά0//l|w K  ѐ0--Q|w ] M߭=++@|w Fީ,))I|w8?`''&l|w _o_2ya%%$|w ! =nO##"R|wR %!! 1|w <9ً 2|x lڽ5|x@^8 |w :n,^ |x dآ3& |w ^'**)p|x "Β (]|x Oʿ/(Z|w  Q)  Y|w ʇ*»c|w AIJ$* |w eT)0 '@ |w /3* |w   |w"|w"|w"|w"|w"|w!&& |xx |w! {x  Vp!! T~qvvwk  O &e  ҏ 01001    <=~Kevwwxwwxw wxww} L" O h; | V{" {" d{" {!{ѽu {̼;;`{998@{*7766={ɻ544U{o221{"*9O˻SE:5"5BT~ڼ0//l{" c## ܤ0--Q{#""t `麠=++@{"2[趥,))I{P*R`''&l{"wp Ga%%${ &7"+Q~O##"R{+ 3d#! );!! 1{#"SN"#"2{#' 5{7Tq8 {#QA^ {"zH< { #o<**)p{ ":ܡ"=]{ #eD>üZ{ !%d?  Y{ #2ژ?c{ $W;@̷ { $zi-?̮F%-=T {"%2')DHA {#"!#"!! "# {"{"{"{"{"{" &=AA {" 1 {!""! |!" " Vt%!"!"" Yuzz{n!"!" " O )i/"!!"" ҏ 45445#""!""      !"" 0!"!""1!"!""2 ""4  ˮ{3 (" *$ .̗! #" " 6" }" ! ɨ c᪙ 3da aXGaa^ u zՙ|A:Niv -\љ,evp0MTޙiq._J={ I 頙 !SԜ ?d    gə A Sә  |ә D  ә C ͙   F vX NCT <3YA """""W { } 6e  N lcWXXW]O . O Oˮ{3 O0c1 2{4e/tr^C.}3(UC("Z/_/_`񣪵`sTB;;CToǸ_R *f`( d_ ;` ɹ` =RyFYp͵_3Π_ZM 7t_6,KZ:Kr_6'j`1g_ѭ^Z_ӽ _ _Q _uѻ _`ɴ ` @oǽ ` 9iķ ` 1ð _E _'v _>] _ v~@ _ky_Ƶ@nmy_HWahpu}ytnhaR: 01577=@ELQUZ_dlpuw_  _/_/_/_/_/_/_$%%&_Q4V_lloa02'_&' ,`|{zB'FOqvvs))<00/0 0/.#K5  S ܹG /sr^A}3.TC.!Z/`/``˾`eRJKSd`c 8y`7  +t`  J` ` Gfcx`>ڰsnW#E` C;ZiD$U ` C3#  {`=q ! `ڵh  i`˷!  `ϻ% `_κ" ` &ʸ% ` #lIJ" ` KzԿ# ` *GzҾ" `  ?Ӹ# ` Vϕ ` 5Ć# `Nm ` ꆐO* `ȡ+ `P`WgryyqaI)GHKMMRUY`chnrv}` #&''&$!   `      `/`/`/`/`/`&&U`Nκg `j`a_l n_ɱ y?DO ^tvvs)~< [*00.# Z%P E ;,wxw wxwxwwxwwxwxw wxwwubF.8 YG%^/c/c cǼcud]]euct0  $McK ##"#"@c'&"%]c ʴưc Zʟxɜ}cQ༃h384Zc$VP4m{Vj~ʤpEz]ђu`#^; ǵX{fzu ނjPe0xHi75況1JsP L ֭6BonPyV#%>]ګG3401~nw?AS'/ k?ыo۵p·j707s}"?чⵋX&iwHW ,D"Xׅ|)DuOyյ&6c eS[OـdCh{EZ$h fߗ4wǬ>^ aբ qv5_Rtfev0)ȃq93x3#R=Tj[ YgfXNyT a51y;y,e]vS-u4LP- \s[b?r|=ޱZASVx];?G9mTBnÞnA.dK%} 0-VBi > 4r`MgeqDޕJ\ 釐peG)dj!nB@flg=/\96{>ʹڈ;ꂿ#H/y>9v7;6k0N$i2Ncoy/o[`ع2z= j3>HdY-|%f{:j{=I)>8k L5't'{Y#i*&Ejge>[Q3Xcy#0_D#{S^O3$y'|uFPt2 jHu DYu0Zԑl f?0닗X}0k ̶rM/A prTӾWKYcS=P רpu=LU[c2Ri;^*ocjРk^+Z+9gTw&S{5fvI?h&VF7u#DF,j^v+; d[_3Ãa]ck @fѬ ̦rg7ʎgu##]^sݘ{~vg}X^{~3#6^{'Yxf0_ylF{Tq1;n`!=e{lL'ZÌ|{k+'7i lF[|H75xRF|dcW\|lxKq aX![ٌ$xPW^ы6|/ Pc/l.A& +hPiQPcTfN5HutFUoejλzС6LΏ-$jF@7>>2j@<ވP :t@@u| vAV:tС1gօPc1@{;V/85hHC 7vBؘW""o%uXm5^ U,Es.fߖN$FӽgϞ}|ܹ]+ j*o uKP%F"L7r]v{ .dCe㙒ABtt4Rm:\}դIYFԛJL<ٵvP;nOy,ˇak&D;U!:ZG|cمXnu=L2fKN z70rҥ?Ã5kֈ7o2v/vuӮ]ۻHOqCl߃h!vUi#+a#/j@:IRn=ȑv׉ӧIn3&j;C 6(fz+6-,RJ]}諉;wiʕz*jfN7HΚ5 OPWB$5$q M]P?0x;˓V%E)HDFVx= mpbóeeBrɑDZeVwEA<!<8Jy(AwC_2r-\$e4PL AF# GZZAHA ;l= R@Uܓk=;X]`o\#\,ZwfT#uCx:QTZ|iigM7UVT,VkG5HYwc$k߾,sZ5BÇ`񥥥UUk ӳgsw`vBݱ(@HCQF9z":).pqpORyh>c*Cli#P_hcAw%ڇ!3khw TDQA)χze(Gp8 +z1eJ*l޶-8uӼymںCsWxxU#~yejnN(0O{ G+7bN\KJXYb !`4<}.m뗟}+'n1"i D+ejF>2'Ţ6wΛ{{vIB]ڐ+Ӛkjl&6zzRL?>5iǎx/&b׬_7cʔ _==(u={t lГ*RجV.qq?ݻ);cj٥}#!D ,B3tu)qsϬ cJҢ'S2n,>tvPBPTR6E"8~|iY-,@TT$ܜ `}rͻmDp D$@A <@>Ak( /ęmÂxUsI_T=9e9`ֈ dhK̮2ެEPkԥr!iBXYj] ]K2>p˰aڴ)/(GFmܫ!D|LXƅ }4wܑ ;yTG.KE|iq̯%IKq,o^ rhǎ.^HdJAEVM)dnc`7r|>pm7cm7ؘ H8Xq;4p2zkh,<-&f kH(bܽP\lwHHL:5m?^ipKQg sUUEp~:ۡ=Cn+x7- Wվ+:b萔@ֺ-VW21l82)B)B)L8{㿹-l [! /2%؎MCo}Dׁ`ّ JJ`ED p"BBL(*O>=.fSV˭Bâ \,I/k;;gϛɑGs1e$<< EE A)Uh( Uwe݁!>#خ4r9lIeN{<8s* E_(!b\c52)a 3:{?Pw]sD"> HGnݺ]JMK蓌lMJU"ٸuk¢0`҄ uĬYW^=DV*IbNNYG)D-IPm="AFFEb=nPJUeaQGGGmX̿@MJz'&&("- xѭc[uyHxXBBíSm0`CF -8.l%dit]]@B80OXs;R9gAzO-ADQ U?n7~MX#!$6vWPpڳ$=aw8SO=(nr4z\.5~ijAMV}c}NE"uH<{Ԩ2瓑drr7^)j=5А{3]j8[xhhҒ ѱfЗ;%sJ U ճBUS&ϥAc+gxcll < 1G@Aa2!88a!$2,Q!d46dL[YXbq$WXN;7)񰤻]N$_gSnB?IA]R<ǩ!+T0]s pe= ~hffx L[_d.T/~/㴏Bu>GT3X~`Lǘ@]u蔦&~Ǻ%FZۃ/ɤ.<8mZƢ%Kn:}I'$N8xMbo-Æ Pgrrr%%!MAA47/U]F'm8Y SPyܢX(BX顇Na҂9<{}q)A``@pA0J3EP@G8 r[K)i+.f{Z!I_A4mB!w)6q?.)l$fg  jR?O=:@/Ci}X/c/P$pGF;vNQWbժVOgH ^/piɨGi7>Hҡ޽9v yT4p`}&䡅` ^XY1[44DfkfK <̼CTHз+=!;;[$}Sq@]}kK=v-֙'{s[ۆ Ӧ߇FA"fj H#B 2W@Jh{{! 2@CCQo@$نe"hnDG3@aF1RD}D:[ҪN`߁+++&NfٲyWI'*={„Owzk_ӷn(:MA%%-YB4VP PEQp-˸5W9Bp` [V/CXe|tڝr/yZ2sl?p^z#Kɬ& jC ۥ,['t/\O)m@yN3˞SӰ:ďJ%iRX)fICoܼݹsg{`AzhJŋQkO׷oOPmE dS؝NJ5dK]<-+!s[v 4RZ SX’~@AKY٧ygaDdddN]n.8.8Nnp8&euTT:K\Q*J Lꢍn\kq3ַ<|xqL999mk)w݆ zt{=Ow+͚={]GZLLL wjkV `7Ȇ.7[u}Nb)hҢ [)U%1n7ypd}#:8H9tR!!&AZͧEz  9?+g7|y7|/4&&td~֣`r"HL;Zߌ'^- u G'PکGoߘ8վ}4:bwߞp^BXqxK\[R!~BeHܺ}#Wj yRdO4pOLaIw^[3r:;x&&(! ?`x믟^ׯ3w޼Mklg7_OPRRJ={hUP:plކdC}!x @$_̋WLiXXӟ,ج6yyU¢"S[@Bdfa^~ r1/լ-++~;XӓDQDOea_\J]%]m$I*"DI$I ?\?(= ek0u ؠ.O_c0 nhdl{U'Z"QqaaaaCfxvjjsC?6kVZGeNsM$b΅<'q;N9FRONJg>Wr( (B$b 2Ҍ~^RgJt3SK\|4bFԒ($g3$Ä*3(E snRJSvPJ 9s_ Di&*5'vHPQQ!zQQQHSKEE!^-^ԩS} {ƍlF$|}d25qҰR&!-'<_.(i(`0PJ)JKHYi܊ s+,wa_tGυ 2L ٸ+t,)# J IJf'/"iNlߘX` ʥ~*r K+"Bvjz:ܮmeO I3o kl2 -%Gtx1..>SW\ycm!C:uhmGthlk?X a*/y1?> fs\:{YHpFJ_J0!JAF"T[ /޳iQdY]ktawV[2y@v@OsAƳ kEymGeu媏G$B2RkC$@ӧhWkS`=(ܧ}ݷ>=|.;_̌~TlSLIim&LBT '^dw:+S̙dPRRՖCD @VDnE72a0L.ڙ\ ((@D',fl,e @a1թʑ:LJ[uG2i&rϵal4J,^׭]ݷ> 7uH_`?Z#4 X 4\\4`^X1MVjuk#+ʓfbd#iD#,M|X}mfs={DO?mJ2}Dz?#&IimRv'\8@HLx6=8b_$(Xxq/g8`@V9fJi]GSu"xݳ^sMxO$ۦM׹n3fHsڵkW6eʔF7<ۺGkK39Լ$I'JuT* LxllZRRRw]?¢E.v>zM:>t\M"i4-E~][2&I9694"IK%UYVsyFΏn3o42}(*]|Vjy!zmZ2DCi)d9s&_~}> gΜ ڌ$]""a0CID8ŀgU{ 7eur!M}C#%9-7D9 O<jx!}1_>'xJAXXh~@xҨ&TGh1j8f%RS4̙3١3g :;9lҌ>t@@VQJ@SeUvv*|)^wx(Tv/| Q 1Gz|:>69PJ@Al83+W ћn̘1ju]kX:u32<\LH%D"] F ڛ0Us)3j鐝U;Su-q }OcoX(nVߡT'v̞={1c͛7'$$܅r<;XQQaEIMBବ}r/4 $RoVTB  zՍ@]B;ocJDNhj",G<[ZZ.%%E' +cǎjҤI׬Y#Mr%&OZvGv'qc޽С&X #*, X=YX[q#Zkjl^Hԓ"9FiktW\sBr,v)ʒu"8 `ڵkA6{s_{nm۶7oy6{uX!/R)GB*qZ3R#xiڐgER;`=V|^ZleX`xN"n] `!pPnPc@]~vnBxudRtU3|uZ+%lq)忊p'\Yʟ23>Ҿ^0 t (m~.LƗePv'i<'W(w՞S{)thv#&-oMA@E~T|8oOkcr|T pt:T>a2J)8BTv\kޓ-:HG0|d?[L2TWЁ A2hE Ogl/m[XuJD*\$hS3ҜCF{Xadg;Epğ)" < BHm3.٘6QZ*cD.fZI8X$xu%t^QοFV:8)x&irȤ0sz #wq ÆjY_^ >s9gKСC:tСCGDUIENDB`Carla-2.1/resources/bitmaps/carla_about_white.png000066400000000000000000000314311364475620200222440ustar00rootroot00000000000000PNG  IHDReglbKGD pHYs  tIME !&tEXtCommentCreated with GIMPW IDATx}yxTE[w @Xe" .*2.(:?oQeQQQ D!(&ʾ=;!! dOz{GWKӝtVxiH׽v[:UСC:tСC:tСC:tСC:tСC:tСC:tСC:tСC:tСC:tСC:tСC Dd"D$ekQ;" {9È "rr"ߨ/m#"Z"J$"By&Qlk,[+FDXv"z>DTNDK( }uh,FDkLDkh'eѧDrM#h\ !9YZs"BDUDA:\D4͐xXDQ7jːeNߦ>ywzO&"ZΆ#OmD4w!ߏtLz^z-Y6e5:"ɴ&ex.^j2u&9!hY"ygDfsVpig}3Z"ru|`Є DTMD[lz 䱊J=yQ4'>]۫{3#M"il|0Ȯh9RGc[YITy"lD?GoD>qo&HWMD'E/Q}:!Pn,!Y#Ґ(_ipǬ{T+VV6"h]KYrtEW}ĕOD DDI%>|'<|^-h#!"Gm۬Q}DvX=<"b-坡'ɞ8yl㶊r"YU_r{ͼ4fkl"J1.)u$E<ՠr"D4z]MDxwxŝWQ8ho/Wsj?wW~[$"#$8@DjHVI-iEDgy|Vd(wg M|'Gh}CD؅.)eeIY-G:GDD x"Kt<6㙇D6Ћdx6XK~o>0y֜q(GNG;&, Kӟ#6V~e U3Mc7(Ԓ/pk$g]zw)SqHކ_HD6":>Ɵφ{I/x>x8T>ŸDMX:-n~1;}/pOFy"YtS9.o)"ʯgdn4akl겜"*"zljX'z{8OY6r&fp.RQDƍ~ʳI,<%E~j^Ǹ͋PORfl+.xtv39"*p2$W(.qc?3^7B\~ϲg+>^ok9i_n^ėSSS47W3E"$|:C=*\}ys|I]<^N$&~N5"Z^a&)ED"R_l˙hLDs_nuA4u=O+mW6<(p/>xq~BDs}K"jyv-v&U ¢V֡D&s՜VҡCGm$2;ӵc Hz@қ@G=D<p+cRo&:t&Wo&}MD7NV:tСQgօA w"3X7ƌ;>.c;ڰkxTR%kޜN$&kfΜ%11 G ]l_p l6|G.]l)Zyz#zi0k|N$|q]wZr7ǥ0asժUC< sO7|ĹE&fh*v1cQ-i<Vo,ӭ[E7 {'ZقT}" .7o\RްaѣG&k֬,dee"=HJjoՐ?"t^9o D.y[ ^S\\L{Ϥ{Ӊɓ'oIn5*zےP$6+\.&Qs jK9d Aoˆ!:ufҥ='U!EpO7.H+:\>6m {(S}.L~ԕJ??+?PGjw]Ues %R[hW Z%鯌l#BeNCƘOp. ϻyGcVG یQA{C1cƌ ,lY2GPv^ј¢+,}tBcF&2cF8b2Yv8VоN0JwI,KaWw{@ \|v]Fr;(1V`&XOs~pxoao?  0bk:vNLLܣSC8Y:/)"Lޓ7--V\ "sQZR0d2!**⑐&TQAAض3.fK(IAFZZiN"y1Li= ["biOl$tz+8#g]h:yfTqY#&{xԩmvϝ{U͜k-n/;^3`.z!.l9އ&:rCؘߞ++e@mǨ1;M͟VTV N*t}q&WDT\X2@$BU%WaG\/t:Vh0"d"X[+Xs :FsփV/^ s;D1vA{$2*[rX'"K#=///; 暒ꪪ`Fի{5HΟ7n>Z5BC3ܼb 5e+WݣG3g4`@YSϔun47Y5H};6 NTU,I)'w cP m2j8١Ƣ :É۱Oy"U`A`DA`L`DN kHaDԵޅf$p1K,?nQW|1ɟ}޽XYՁd χ<+ TUt <)'͛JKKC;qd?͚uM7G{EDD^6"1[lVVgX,Xm6r8L%bYy*1w2c|$}j1"ivK_Ռ"<߇2I'u dNH\k:^hO>kf]$kIvmڔ?双~ްgC٧OTin9vzhQ]NSE<6?qӪltsqԟ^_07<"|$$$Ad $BEȲI Id$ y"i9_ t)p&#b+*b 2t!^|7[lltye/FArpOFvm}z(0 0d 2L2L ( &BCC$"e0Ћ{`[3u9`fu'c4 }5qK+Dt5ܛF\03vԒxTX먱mƧ6o:4m٪U$#"9vSv)e҈dYvw=`47~g M–-_s}k-32aÊ?# GDML  Bd22 H:cއ6$O CTh\=|EFF0"BUiY8 6rೂEA.*<1VHjW"'7;݇n`GS6,]֡C2D*T]7E!(*& cGm.L "ڋz 7^a7^Gqc "k7֯dy$jD4d}K9n~0nkvW ӼcgZ?ޛtŊ! bt%%uSOAnΝnUЯ_vDD%d|m#n˯nNZ|,}ða;OVg:̙n|1l=FDP@2ۄl'eAP/@\/=[QrMú Նm{PRV,#:< #44%մh#95Ҳ94ȰOÌs>2 bcĩL~CEq)GII_ @DƠI Tw]fc~/Ϋ,+/:aw~Aީc#=KKbͨڌۅكiD4_&1{= \՘ǖbRF/c= ZYHŧ5 tܽk׳|M))=C$6mj_\R5n\z]<6mکe˗VTFB`5ފ$8r"\ڡ{1@Epݥ2Ci4b]Aå!1lTǁjwqj`4v^&Z %NzOR 5* ?%1+=zlv{G.]_fͰj`=ލB#O<_BD9OVZoJ^QfU.])!jdĦ9Wj J",4<.SB5",Z)(&&^ 2XxkdFnYZ%lKgQb ȧqػg?Ν?P 1eA Bxh EtD(L tAjqs#Ucvu"J9t8a0ݹ8u")450a2/B7y([*Qv} X8TzއPNN. U{fL"ϳvޭ^Ch ?;>r ~ ^7i-XDICk{%ԅ'Mʞ` C/Iۤչx`zf5kM$JBUMhnX^V:LYnHi %jA]P]lY'lSR_zidԽ{sMh(N?^2zru9#ЩKLL d , nՊ"( 1Pm\eeVMكM~t9ycA`PTN"*DmRcX8)i-[&Um"6m~[[۱po>~Hd Nxܸ:F^u HUI 1vlhNJKJްN׮OQU⊯ZW N'{GoܱsgOIn19MciERQ떯pfed0AAJT"0V!lOsm7Ўm΂=g60-#>[|?LBHH Dq0 rY,E/KL$00VVQI{ٲCgn%3.]r)nTN* Oll3Z; ֤ƌcܘc^:{0xxKT#ٳ͕UU!$ =ǍwScٳ#GtI[nIԇzhg 0 q B0̱ͷ/騿3ٚ( SXf rlۻ>ye^icWwwZGH6e_9qdĦ7cCh;1zpf2PPlx~c1(Bg ϳkJ*+[ػc@Q GQH̙V\&Ht4Tn'EԇH$Ia_QK:!UůwwբEKvNGx _{F6n܄C󎌈~7~mV%LZUVV͂ FN"TbęsWVozquwvuM/ a{No\?a,5BVp؊eIYxp2-axvr8N8].8]N7!( e|EUQeR^w]|/""'' nW<}~a-uFK&&_Fj5|w_aCUWשS'3}<01̙h&:"it:T %`lʩ#G#9=r+i v"JOJZӭKkb9sb<{5]ѻ71+puIDATiTsU";Yq=;q# $c%(<+G_G 4?߿/vJ1cœN'\^D 0&[Xr p0Ij EU"4J'߂De_w#GHj¶LMM혓Kjž1x=;eeeҤSo;zh#$$[?7/Փn%gw7|Y7i_d ؝.)%&*^9v1mgk Nc=)9y@1Ȓw(.* SwtMW!Ը t?> AWmwKK,kwdddՄq_zuzffOh{ }啓k>}|fΚ5i!?##wފU߯~-$ % @EH9IYeFǜi%)8΅be(BeHQtYOM+D^cvD/T~Ӳ,;| {@uu˯vҨܒݶm[ooɺ<0)((,(,7$Ħ,_N'_!YPEE9}o`Jf0Q!dYfAt4#[Z%ظSM" `0 44_[sV,{0u ] +Q!},ыDNDDJDѳDdjle}I-p?p׵Cd{r/b1Զ ȴi5j{|OQjQN$9ٜYU}hg?T_ZB 6O 3oۥ dIA! ,8Dy5)^4-nmhoe7L0_ZL Rk$[@ܤhu_ض\6zD3]MqY^KOԆ[=2iRZrJJ/m|JKKC&%/_Qڕݺ2xpddfowفNF, [Tݯ/kl?EHܮAqgT[m]?yzSYGu܇yE )=~TlX`hhD^~>_v&;;2g< ˏ){o߰pdaB" "T[,(YHDOJDł ~ DL4Hj;! @UUY/U ::gĂ_x$=zz15#̟d24ÂҰR9BSUX4ӏ ~I%VTX/(;7,h4UW*RZmU[~ֵcg;9r $g+ 2w(NMϗU`0@%"Ν+Fmز.1,|K>K+(. n5T$ _YTa]&"IDֹr$F&L$-qDS]MѪ"|xE9p} V"Ar6oܸA˖]==>P!OԸĿ7{f>?cgWxhێU˯n0hmJI|vv>>Y0/jv,"2!t옑L޲d0h4@` NEnfCEy XnN.ҳrn(.? D& 1% F(BE$1Ya2n_v&ScewHcgrusğ}L'1޷1O7[Co `Μ9cJHHM%K^]kx0x܎;[c1h=E&Ki:/+J},|9ÿ9$j=qidW;uz@ :LL6m)=UQ{mNmvb=U`[a A$1KUeGe.GdbXkVB$|`75u5e[m0d{І't7 :sNsrbȏQcĉiЄ0)/%eV(Jl}IVZfDAgSj `2 *,N6 , C K%@ 0g:aW!BC$RoVD$MyDC6u_Uz`wϙ3'iK38$أֶH$MB&L~;<@;8$dZ/W[&?L}JsiD-C|.XlsHx'3A^OZ|n6,388Xmm_ki?Q5{wxypcfc_b=sBm@|Mֺ;VD$f112c k4n8HCj_rL2%>k׮bĉ~\Go+2k&A-L@ ?-ߤSԘ8 ;˒P'?um<=o޼s6M \{I}(鸜DL4-;o VO:R G> : ȁQQEnC 7Fl 2v0CkMe-/]Uf!qZ yǏ۷YC6#YtӰHOK ނ;uU;3 #ƘF{uC# 5ؿy:7on@nn9]#0AZ\Noy ʯ"Y x=D0c91̹1+J WH^ YI#NIK_3WS4Ϙ1c3VJ $y㼵ѤV\'NC!BN0#;ǽH̸2YHIQۥDra0}_u]V\)Mr)&L\jmmV',"*ꞽz>ھ}&2nCtx8LUxnn`.Յ"Ko@'=8c8ݼ.1] M?*++녨8G*Vc͜9KbbbQ9y涳fr8 hv:s޽y`IM9TVcr5r2ۃ y6vBD"*`9X/ _|19Pl6jEܺ0$]'}:ߩ#F,퀭/ VE$[*\d Bؚr1N,_alYd6 #vK=<`^m6@ߎCGqma:]"|V /ڙf*XA6;U8o-bj~5#;#о2ysW[t"ѡXذn0~ q\1|{* *M7\qlR{2JD,h}#r7.CF[caZ &?SD4D!(maN׉6P^`XlgSXX$.v\y$ tcMq(AwT9;h$ª#e8Uw_dp* BE?J%tСC:tСBIENDB`Carla-2.1/resources/bitmaps/credits.txt000066400000000000000000000005061364475620200202570ustar00rootroot00000000000000The pixmaps in this folder were made by falkTX and nieee, with the exception of: canvas/* - OpenOctave style/* - Qt (from Fusion theme) *calf* - Calf Studio Gear dial_{11,12}* - OpenAV led_* - Image-Line (need to find a good replacement, suggestions welcome!) rack_interior_* - OpenOctave Carla-2.1/resources/bitmaps/dial_03.png000066400000000000000000000033701364475620200200040ustar00rootroot00000000000000PNG  IHDR"":G pHYs.#.#x?vtIME% ?IDATXWKGS3vb9@ւ $.p N\p̕H !W喐!Ba (GuWsz/嘺tT?FFL$BMӌ֦xJ[)#)H)s!@L:M$``ǘ1fZeBhfn9>R$EQ%;W43pZc/FcZ-bC!=CDhųM?of3IFƘoqpkZҘx`B@QgniV0!|~4(IoYk)FUU 9B4M"RJ(E `WJsqlsF2|}8`<u0< m8}1`f8P5q(1m1e:88 iI@Juekk$yQP5ʲą K8 EBBlmmٳ "LSH)R D\]ƱMsN66?LW(C4/3 "m !y~>1L0wDEe[}s=9wHMcW'kq @4pի{s"AHx) R~N;> sd+8nǻ=宪peoƘ%*zg=Dą[q=;={֯lnn^SJ^|wvD UUh4$ bSkEjm۵ Nt| 1P5BX$XcLb `tHk}IJ33HFkxΗ`w#trdp8~!0 %jƘBFEq&uuL[k-ڶ3CH(.TLNS3k-Bw-'EƉ_1CI'Q4BYEC)x R#yᱎW>VjBXf^#b)nxm['~vDUѺi~v+X^$E[y!)SR"ϗ'yHǾM(`fm1}u}q5MIQy#ރD( Z%#m0sz i47B RJ<|Ȯe8-o Olȼmw^Hܾ}!'sբ(`E }նuZEQZk3Ǐƚ6E[I<;Wn8Ƕ!"2Ƽ ! !N'D 5eY[cfeQQ?gNmiyFDâg51ǁ,s3Zo޽{WXk/I)4M:iw9*cf,͢(ZM].˲}Ƒڳei~8rp).eLJӬY۳:B͍ۙL]׿gwʪ0R$EQ%;W43pZc/FcZ-bC!=CDhųM?of3IFƘoqpkZҘx`B@QgniV0!|~4(IoYk)FUU 9B4M"RJ(E `WJsqlsF2|}8`<u0< m8}1`f8P5q(1m1e:88 iI@Juekk$yQP5ʲą K8 EBBlmmٳ "LSH)R D\]ƱMsN66?LW(C4/3 "m !y~>1L0wDEe[}s=9wHMcW'kq @4pի{s"AHx) R~N;> sd+8nǻ=宪peoƘ%*zg=Dą[q=;={֯lnn^SJ^|wvD UUh4$ bSkEjm۵ Nt| 1P5BX$XcLb `tHk}IJ33HFkxΗ`w#trdp8~!0 %jƘBFEq&uuL[k-ڶ3CH(.TLNS3k-Bw-'EƉ_1CI'Q4BYEC)x R#yᱎW>VjBXf^#b)nxm['~vDUѺi~v+X^$E[y!)SR"ϗ'yHǾM(`fm1}u}q5MIQy#ރD( Z%#m0sz i47B RJ<|Ȯe8-o Olȼmw^Hܾ}!'sբ(`E }նuZEQZk3Ǐƚ6E[I<;Wn8Ƕ!"2Ƽ ! !N'D 5eY[cfeQQ?gNmiyFDâg51ǁ,s3Zo޽{WXk/I)4M:iw9*cf,͢(ZM].˲}Ƒڳei~8rp).eLJӬY۳:B͍ۙL]׿gwʪ0 $ J"nι/oll|u0<4M=)%,]RBb^wXiU!, cB]yZtZFEq>SBH)խ)%R8<<{Xk7'WP`QhBYRJm!zК޽#ewʲ:@@)k퇔R`f}ÃV ߥfKפnߺ=eYLDFkNeYt=wD4\ƫ 3XͭO(Cԡ9Aq/!5!YQ&"H)ZJe/rXcdYz9( GDC`fwXԬ " h8iiƯ"k"1Zf>]|_euƯ8%Ĕ@DKtR ZkZ;5~01:wB/@f @#Xl'''-uYyγ_51H)u1_m۟'fcp||r뵥q6=BO4{ιmAY^u%}5"2?i{<[ι{Q &sν@/N*jR u]yy.K[y k ˲;RΚ-cau_߬i?>E^u;MӼy+|3/RC4o}{)G1G)8˺F(f+NJ}x2<4ƌs[OZ۶MUU-RƀT46FKh4UJ )Ƨ!ӦmzxՔ=*DzQ9 w3 {tIENDB`Carla-2.1/resources/bitmaps/dial_04d.png000066400000000000000000000026451364475620200201550ustar00rootroot00000000000000PNG  IHDRr ߔ pHYs.#.#x?vtIME)ٗDIDATHŖoHƿS/Ww4$fj$^11b H,aĂ-b +6ix 5B$4&εˮsXdznB`]GcssCP3WTnbnQrc"uZ{?483Ẫ.@%]粗Ͳ"ceZm4M;"ތ19@}jZ"Z^)KAq߹Z롈ј@iٷ $ J"nι/oll|u0<4M=)%,]RBb^wXiU!, cB]yZtZFEq>SBH)խ)%R8<<{Xk7'WP`QhBYRJm!zК޽#ewʲ:@@)k퇔R`f}ÃV ߥfKפnߺ=eYLDFkNeYt=wD4\ƫ 3XͭO(Cԡ9Aq/!5!YQ&"H)ZJe/rXcdYz9( GDC`fwXԬ " h8iiƯ"k"1Zf>]|_euƯ8%Ĕ@DKtR ZkZ;5~01:wB/@f @#Xl'''-uYyγ_51H)u1_m۟'fcp||r뵥q6=BO4{ιmAY^u%}5"2?i{<[ι{Q &sν@/N*jR u]yy.K[y k ˲;RΚ-cau_߬i?>E^u;MӼy+|3/RC4o}{)G1G)8˺F(f+NJ}x2<4ƌs[OZ۶MUU-RƀT46FKh4UJ )Ƨ!ӦmzxՔ=*DzQ9 w3 {tIENDB`Carla-2.1/resources/bitmaps/dial_06.png000066400000000000000000000017531364475620200200120ustar00rootroot00000000000000PNG  IHDRUPLTE@@@66655?TTreeXXu888???225OOk̯hhjjQQk115339gghhiiii++1447hhffkk!333777PPl﫫ffJJd[[feegg..9\\zeeSSo⫫^^Ⱥ߈YYvQQm44= (SSmIIc==@kkeeQQQݍooii===::>SSnӛKKe<<YQ:£5.ohp+1M"mEu*^x%z?UŊ`L0/C!~ `A,˾ Ѹ8BhHeZhfA5L6 SxweMVyN4KQ%NYV8)n4-{R!*z0be nln>m}xɓӳ-$!bO/׷/e[LXIENDB`Carla-2.1/resources/bitmaps/dial_06d.png000066400000000000000000000017531364475620200201560ustar00rootroot00000000000000PNG  IHDRUPLTE@@@66655?TTreeXXu888???225OOk̯hhjjQQk115339gghhiiii++1447hhffkk!333777PPl﫫ffJJd[[feegg..9\\zeeSSo⫫^^Ⱥ߈YYvQQm44= (SSmIIc==@kkeeQQQݍooii===::>SSnӛKKe<<YQ:£5.ohp+1M"mEu*^x%z?UŊ`L0/C!~ `A,˾ Ѹ8BhHeZhfA5L6 SxweMVyN4KQ%NYV8)n4-{R!*z0be nln>m}xɓӳ-$!bO/׷/e[LXIENDB`Carla-2.1/resources/bitmaps/dial_07.png000066400000000000000000000276741364475620200200250ustar00rootroot00000000000000PNG  IHDR ((nQ pHYs  tIME+ vz\/[IDATxyXe?w?+  jW.Y[3Mcid،Yc53մh-NkqJ,S+20,\@8p$裏>裏>裏>;|\7|>-m-˚+)JW7hl4:T˂+Pm@mH 2ׁiMV5^_=.!!AAIIcG}G}G}G}~_bA.Z x}%¾`. esp ΆA!ܚUBٽ_g[ }B߉qIPV>K}֨ "N7<wWEtpKz}s}G}G}G}"lnm;Fd Uغ_8:ai!++ ,C4D"Ԡ k׬`EM{=, 0GУQ.]ѫWO?}?%zG}G}G}}O7:}'1yA}&+D|]` ߬^O朎={clV2G}w2^tX?EYOԠ~,;R4̸?u+}'{N裏>裏>裏>~[LLFa* |ƟuƟuz^555㏱yf*,DԶQ@q]x"{<ȖҥK?<裏>裏>裏> .z㙰w =1~!裏>裏>N̷i+ffZ~[Pʊi4šJ[l[ߢ>裏>裏>G|Z<'%%nN8UR0:p۶C!=- uuu$ @UUx< x=z kWD#T)xJT\{jJNnKqƲ }G}G}+[)p,NėΨ=hkCxWp6GEǯ>C̢D|OGzbI᫪$I|B$I¿/o`PHmx0rH!}`Xp!:,!}bÆ Xd N;4!}O?4> 3 7|3,BNW^nݺM6B\Ŝ9s0zh :9r>hhh$I8p>Q;}2=\C߉*BW)0}7.il}f?G}G}G}r_@1## ࢺX ]J$GqzAnZ8peh| h^o3eYFmѣdE]2H B5Ok 07Zދ>裏>裏>ZX~Y3iK(//wNpìwq8pjkkilܸڵgYlقwyB^޽{ѣG!}b4 ;wҧ:^xM6Eaxꩧ0c H$OUUB!lݺƍgoE|^+V!u],X\r dY_|-[S z 6laÄ , -‘#G'/_Fnݐ'϶mx<GX_l/C鶏;ߗ_!:d2E&}r8{ zbkWf裏>裏>W쓛npc!ˀz& =8y,˂eYͮ7 4aYlL8M˂i$d$_f͚`08>裏>裏>a}J߉`]x;w"!1幘9z( mڴ %%%l}݇!}@uZ %%%B[nؼy3An:)u] [lgY:wba}a@u߱Ç#>>^X_UU<>ضmz-֭[a}W^ѣ}oO>BL֭[|r!ϲ,aΜ9BlFqq1>Ca} ˲о+胄mN7d" w"`"}G}G} S ++(c>| Ar]tuW_P(۶.\mQU# 6G"o(  mf ^4 8\S=SO4jԨ7|3B}G}G}B 7-V>=|-#g'CRRE7eBʰh"mxq) <3(((Bܣj|Xj iP>zGAYYrss@0͛m x<?~|J$c׮]SUEEE޽;҄56m>]ױsN'( xꩧ0yd!}}v܉>[H<ѣ:t 4M,Xgφ(`ӦM(**y'u] cƍ6l"ulP%EwWЪO?>裏>裏>a}066Mqϝwx<4 ,7X4*+9vx<?<pdBUV)2G}G}G}EwۓW__/oZh_I#iBe!}> p>]ѹsg9_c')x<ѣN;4<,K8i֭u놗^zIH,0`Lۅ#P^^41cຮ8̘1hTH۷/&L ϲ,p ֗_~YXi5k.a}W^Azz^za…/ƈ#o@@H_Ә6m>4QZZ , 7nm9r>˲#??|pwu=\S8_ӇΝ &}ӟP\\ 0mXx15P(sB^ C(_l e]'.裏>裏>Oh_Sbr$9UUH#GF0v,222D|>M IR3m0M;~EY*RRR0|p{<- q % / @裏>裏%Ҩ0L_0PW? i:222 IKa}mڴwߍgy󥧧cȑp{/Bp$̞=… c8E5gUU 麎 \_XeY7o>}ooH>˲ХK\x `ĉB\ŢEЫW/yBpףgφiB7x#LD@$ŋqmu򣸸 k;ށ^qA~~C%>裏>)={t]gMM u$ wOh׮4MC p'vdcu]hx u FEUc꺎c޽()!@T!I ]I裏>裏>NZsaM?w`}<uѥK ߚ@vP^^/عs'w+OuuYXf }Yt4MC\\ ~,_#FhvbNKSN8r'qiiiB\E~~~eh>qjv "D_裏>裏g&<h4C4a}III2d$I9r$TUW^^ߏ?_Hm۸1x`\zzB>ߎDyB =x 4ʧ( TUƍvZL<w}Gj}յݸ~c?A!}G}GIS&WWW+ cd˂rMviEQ( <K˲8N/$Ihժ4MmۨC$IjvLUb:t[? qd( ײ޽ۦM:G}G}-Ŷ;^g0|ȩ(oG$I/zz?gϞ5D5>{:t@a۶04L6 {ł 0ba|a̘1CVVP>EQz1`0 |M۵kWAa}G}G}G}麨֭[wEСC1h !}$9s&ٳs#0o裏>kAiZp8ѕeD`jd!C֬"..ڵCvv6Zj0 ILDCC!V])2 ÀG0cȐ!H ,I Jr H>裏>ZЗ`Uȓ48p@ S/lٲE8_ӽ^CהӦME]$/..r>}G}G}G} }Ǐ9#{Xlf͚'_'x ηb \p(//ǂ о}{|cƍ[1vXlڴI(߱[UU{6*K.=la!|d})£g⯛,裏>裯}im۹e(G޽{E$Ie6;f? {A$A8FV bbGʫ ]סidY,ԩz]`2$YA4&}G}ׂ`+(mӶ3+RK">>=z@vvp7x?8Eq";;[ߔ)SpcʕXl0ea|Uuqΐe((Tׅ`$Ŏ{4 a  11;v@mm-(,˂G\\\lUU(Jᱏ,BRHqz躾>裏>N%J| =vM$_Z4飏>裏>裏>裏>?׺uk}3fE]$϶m`Μ9رp ~HMMENNa0>۶kB}AF5 Wt3wB U $o>򩪪*&۪ x, ^?4$I}b]vHII;i:w |}RSSevq(JR0裏>;}hP -=hoʔ)p]7v>3E <سg1a?k&it;vl_/}G}G}G}G}G}-_,/;;;v쀮B,ºuкukdff"%%4!u]wy /$ l6q+/7{>+飏>;|;&}uUC4mV ڶh4:(ݻw-V)C$xq]9Zm*裏>;|@yy9݋r\|ŐeY_NNjkk~۷oow~諫Ftp]gn6qa|MǮ;hE;TU.~ǎ_裏>裏>裏>裏>裏>;}au/4v|g6zH`0O?Wq;oUieY?mۢm۶@rr0$sG}Su]eY0%xJlĞ={`vh&TCC" `jkkQXX\m Ro (8l> BuG}~8رcRSS }غu+Q\\Gy鿼o9oo۪ +b'B4###@UUi-:NߠAG$'LG}G}G}G}G}G}w\aÆ S9nYpkrMQ}qq/`xwgϞ؉vލ3ggϞٳ'Fߙp`<*_WSS{{N;K}|i,˟u3@,H2lB ˲`6"BLӄ$I|֭[QYYN:Ŏ{e[XuW_A + lIzG䫪WVV_|۷СC_+V( ϟ^z {`6rss1ex^TWWPuvmCY؅iXzuJYm-f>裏>裏>裏>裏>裏>裏-n0|a㗖[n֭[#//'9N͎o+`&F)S`СV\L4 YYYWߑ#GO/'Ou4m .Ux}J\xx<, ehlFvGD @UUL޽{Q__,@4(EQb+++'ATU$}hu*NkhhW]]_|SNFQXXKu֘7o0[RRcϞ=83PPPP("ӵpr9e^2\xطo:t耩SCm[(_,?,jݲtpoȄO>裏>裏>裏>裏>裏>裏>?׹sg`ڴi}@p}///6mBii)֮]j|ذaƎv3ڶmOv| s/Cuz/QQQ+ƍ(G}oU6mߵk>\Y亨Ć pꩧ6[Et$I0 ,0 hXÇc׮]8t222UMcTVWÒ$T54e!9.ߩ뺤s}P$ ꫯPRR<|~!,X3gO>0.]˗cذa(B1}t$''cׯɏΝ;c֬Y۷/LD4m_ z3p Dk`Æ >|xlB_'G}G}G}G}G}G}G}G}?ӗ.,cÆ Bn̝;.'`e株`9r mwߍ7'QXX(eee6lfΜK.@@_aa!,Y{}mV^s_|@{T]UZZ 5lpeQUŖ-[пϭ[B4EaMӠ:(\ׅeY8hӦ i$I;## HxU(8 xAupB,Z`P(ߺup)ҾC͛q嗣wޱ'{A}}=x.ܼ3m)[p!Zn+mǎp-[|r ) }G}G}G}G}G}G}G}+((gH= 6Pd|x'QYY YM:'Oƒ%KpmaÐZ! %E|۷矏+C-܂`0(o׮]Xhn&{}qbĈAQ>W]uU"+;)l\SN91G}{sX=i4Mk BB2˲D.Q[[Tܹ Q/Imh@mLjjM\\/''g7T+K믏'{DZvZ̝;]tM$H|^7{l8b>3m ^36 m;vhmQ_G}G}G}G}G}G}G}G}?+zTF$!|7oxpW"99z-Q]cvo׮]1|ݻ <ٸuVp O~;u](++ɓ|HO< 7iڑ̬̿řmCnhlFqXQzjm>7n_W̝;鉚AתBӴX10M3w۶qAZ {kjRDlMg񬪪ZS~>,͛;(gϞ8sMpRq8V^3fK.iv*H'oo)G}G}G}G}G}G}G}G}ײ}H4Xg]HI[̧:OZ|Q^^۷7zF7E}:u5\~:uBff0]K/?3gb_G+&MNP90q|>]꫰m 7+N$)9*TU$IMFG͵kqpwf&>޳>;0eG}xG'VqboXb/cAwn>d ߤ>裏>裏>裏>裏>裏>裏>裏>裏>1|{ΡG|SNR~EEE};,C9s&***ߟ`5*.Edj4z5 1f64M4.PZZ^z 5`@uwy^YE!%ϲ. L>裏>裏>裏>裏>裏>裏>裏>裏>?Ϸ d/8ުM]UZ'˲Ν;SOmm5\'SN`;պzuu}~غZĊ: PU[ oVQو[ա fdgf&_;vl8O[>-Bg\1ߢˡqG}G}G}G}G}G}G}G}G}>zuLAԹ}j*k̘1^ i±mڵ uiii4 a@UWPFQD"ض ˲`6:m۶aUFH :74mb"} >x6io[Ϊ=Z {9G}G}G}G}G}G}G}G}G}%#9A49 m?{ I߄>#{UB + Y$K%qqq(((@׮]ѽ{wdee5Euu5ك6lC`>/|>|~\IFߏnnݺfP|E}G}G}G}G}G}G}G}G}G}Ҿ,ąk'}'|-[@eȒ E!Ri> ֭ !IB矣4ۈz4 .|' 裏>裏>裏>裏>裏>裏>裏>裏>裏>Ol(z|>U7nܱdɒ%I2dY$)V18\ׅGoG( <^oXH07|nݺ%H>裏>裏>裏>裏>裏>裏>裏>裏>裏>I?}饗fFnVԺPRd(rCRdȲ\4$ 5yi4UnP5 CUUG}G}G}G}G}G}G}G}G}G}b~R1D]4-W_裏[v[ELWϓ?2dcǎ ~( xFG裏>裏>裏>裏>裏>裏>裏>裏>裏>裏>1}?@ر}vR%Q$EeEQUUUIeGUU[UUG僲,z/F}G}G}G}G}G}G}G}G}G}{gIENDB`Carla-2.1/resources/bitmaps/dial_07d.png000066400000000000000000000066671364475620200201700ustar00rootroot00000000000000PNG  IHDR((m pHYs  tIME.;ķ= VIDATXík]yuߗs<ͣ`._ AaE PB$Uҋ"#BJ~E6(?@U QRWsn{Z1xLK:lֳ}M%}ιBU19s1Kcs~Z?NˬC-B?BtRJV[k :B)ғBrܻBAqclNḵc}!cڊsf85F)BsPkA_ƞuggg!䜵C`@nttE{tJa1iBV*ОBD!Z R8%t'}}}#g1jk=Dʜij1c@sF8=0k>1rOO{ 4M1'1i,Ai@U*JA$ @9~.}8)c+U$C& sW^힞K? r11!B)l>s`q #%<C۷R!E1;;~XĒBh3h)A$QorcӦMό`SSIJr0c Anr * |GhkkC暟o#G`$Ơy`#<l]vY磏>OsWjU NJZ W%WF\^X9yPJ]hkkq#"LM%)jG1?bݺ'm}>{Մ+GERk݇O>iSeJ) 0MS$Ic Z[[~zPpj| PQ ?v5[-[}t`>J"4 [׵۷mw¹s`Y#sW<8$IvCRJ\~PBwA-#0?oذaˋ/&PoqNJD EXӃڅ(@)t1$Isi\v^;wۡcxQ7N衇Z2@ݥR<.b J?R<!A6@@4/nÖ~9ԂRXA `ݱ=o:A$ۋn"( kH-Z#Me@)ضm<2MQcPB8|7nذRYσ}<<|mmmիya14*1!ys%Pa ݬ>cS؎bX#jPX~tuuev af9q5r=BȲy0D}6l@($hrMq/\BlBUZG)BZPk[bYI)> ֬YdZkqUoR 0D>Gٜab֭h+4@NMLlTJ5s!5l`.&+AB@)sl|>ILMM!"j5Zf6"%Rʬ(Xv-6mڄ^( [8RJj% s Mk.R.Ckk+P*2 Bafp1BV1J]/|sΙspy2+\bspαfttt`ll B\zpq:D? (Z XvƐ'K)Ź7eIT.lD\c O͛o B>b1l<1!%q cK)穔򹫮*t-:D1ZZRd1`ejC#)* fggqI={Z-W^y q)qYK Z[ۛR(OI.$V q!q]BdQk6r(ILLL`aaGK%rhiiyP(y8 ctt===`,m@ yB,k(saddgHCd >cll \]m[ -<xzzzⶶ,y={~O~(cE(d XnAAZN`cݻ/KRw=Mҿ Ń0 J(% H%7Z(a˧1| ?yꩧN?)狐RF((Y4zKux׮]|^<}c!MO<ć=Z J)8c i-|oKaNIENDB`Carla-2.1/resources/bitmaps/dial_08.png000066400000000000000000000314401364475620200200100ustar00rootroot00000000000000PNG  IHDR ((nQ pHYs  tIME+0.2IDATxwtUU?鷧BHB0'> 3 :6~A)Gl#?Ti*ГHB &#JTybݳrv^y~ >[ 6۝kHEQZIȲ, IdKKdH˲|ȲvܹD}G}G}G}G}G}G}G}G}G}wrEQ.V%SE۲,ݲ|]l>M,(բ(Pe*h,k$u͛7F}G}G}G}G}G}G}G}G}G}9s ݊\.IReYm `U;!eeA,$Iedd!!˲}S裏>裏>裏>裏>裏OYhcl';: ';k3CG}G}G}G}G_|?Yrδm{m˲ d  Aػ MOA}`"+j45% @Fۆ(emr!777SK,_}G}G}G}GqL_ N!j>QB & jc#Yt@Gt)~E#zkPV&@X&}mg@Ѡe(DG}G}G}G}V 2Mi@kawcX.`4BSݣhZ0U$$^SVV6IzرG}G}G}G}w|LsOQ2͔آ;vwoT2lYi!رXáxs|6̇O% j%0]}/XdHD|#JG}G}G}G}[}*P<}ee~R2G=!] ֤ -; q7 4I-P $4D ҕ+Wvɷ=Z;G}G}G}GOs; w">QeL?V~}'޸x  [ k;}" 0Zx_]5/W`+{;}dT(=3,_2DӤD|nծbт}'⋆⏈xS裏>裏>裏>裏澎vgf,=")v0Ogڙ((yiQ( "jjjP]]˖co`t4]P e!iPc1lB֭[_|qω}G}G}G}'O`]0}'EXjW yw> 9}Z/Yپw>I6 vKߩ QPXgӷc F`עQ;|^6h4Jx}5h!eB\0z@ݿ ꮍb'Sf@} /4;Q+3`ǢG}G}G}(&%%]zz,#󶹐=nWc;?vzӢ|X~=/]idpE#\PСC,xG}G}G}]Ar9o}4>FS=, zaK+3 4"}'[1h4Rc-\_~w<>_ g}iO \L@`_X }{z{S!n>裏>裏>裏'$--L۶;F^{yP ?_$444@HYri-wit\HKKC׮]ѩcG"TA\i}'uaÆeYfтG}G}G}>UߕS'I|)nWPPI,MPPS};_86mǑTWWCx<GAᅬv;7g[LēO>#F8'I8Yfa̘1ɲUVᥗ^gH‹/> {vO4}0 M7݄Ν;#++ˑ>۶1m45 @CC,X#F4  5:h `ȏ9D͐w",r?V|w<  |KS ]؅{;U}5P>裏>裏>;}Ŝ7+)~jsa3wqA鍪fip-a 4Mk׮m;wBLE"$ 17o) _߿k֬1>裏>裏>;E}1hĊ6,w}O:AH5UZ6qј (J} )8_qõ8x jjjfm֑>0a|'(..vo@qm-{g tՑ>۶d(;ҧ*x YYYIMSL ɲP(7suO4lݺNn0`rrrm3g5\Qݻwc޼y裏>裏>;}bsgm_l  py֐ `jPTWWò,q Àa-77]aL|>L0NdÀ(iD ^lٲ~>裏>裏>|+>E!=a5oBD,n7p-.H3qœP]]u֡Ա>41{l:çi`P\矪Xx1JKKΝ;cv +V@uGlFnݰa @QRRXiPUr0 |>9wIIIUWWr97oF+V`YwyFr|ѣ#}cƍxWi#}a`ӦM6m^oQH޴F#|ic} bo`$2FC=bCEK/>L@ Td?>裏>裏> ///Eh4zg$^ 6 6ҋ&!@Ea&LD,ٶ( F38eAFE#z<`箝O˲~GR>裏>裏>Zw">UP>_ yzƷaX_yy9y. |PB!ȑ ۴\dpyfGK.ظqcc'LDAAlXiƾ}s\wϩ}_}}=c}G^^c}_ر>]ױfߑ>X~=Hmۘ?>FH;w..R\. @CC̙뮻 |1>4q̜9ٶr-(++k>ڡ2({KmQ } Xzc}-d'gC{BDtҳ;ߦ#zNj@3飏>裏>>dY kdjW؜P CQ EQZ !4WV6WO\.Ǝ=z@m=^XK! RŋHtAG}G}Gc}I|Ɉy'>Yn:x( 6mڄ?IN)Reeeuݑ>8NL2X̑>۶ѧO?ޱ>0pwرT,X>]qWkq϶m;v[n5kc}pWbٶ;>ϑv;֧:v܉c:g֬Y41bG s=޽{xmq/GqPTT8i{1~xk;_˶"v'`PRRM>L;w.6mH_s BM>%/# X$XtGd؃Kawա/}G}G}9\DzCh6u %/b|k999Fjj*<4M(5o7eDQ,aÐrA5 Q[{\.G}G}ZAmhWD| >]FNNA}£>W^yC0~1eG(r/-- SNE߾}1k֬.N5y睇N:_tO4{HJJBYY#}`wO$L::urOoۜnݺб>۶ѽ{wXBV3 ^7~͉>'?}>YXдqOUU <ر>(..F~3 =u=z<' @Ʊݻw###&Lp϶m̙3ݺu9H_uu5ObԩPQ>w ]ѯ_? `ܹѪU&_]|m;"?}uKLq؁4NaC;>裏>?蓊rm.b^v/Ky,_̘xڶm EQ 2,ˊ7 m )) ,ömBl(IRSUUk**Pg7B(Bh6: 0`\pxϞ=裏>裏>C0ubƍW'|mCm;q>S੫Č{B۶mQVV?ؾ};t(3f -[CHMMMOU/`8p^}U >Ŏ95Gaaa@ 8eYڵ+Zn Hmݻ7~#}eAenڱ>e>'/G}Gu=~}X ڵ(aȐ!>Lj# ˲#}eeez袋3MӧOqv;_5xbƌ|M()BO?4> 4}uO$Ȳ5k`8q"ځҏ!tZ/R!V[׏w8Н/#?[J}G}G'JtV]]]X/=)6.CFVVEipHOOG~~>222ziAmۈFqp Т ۍ"xe!ɶ$dW *r}G}Gߏ^E"ض ߎϡm] Sj9/2TUuOQ >ÕW^R'C ! >}`ݻ7nvB!G4MCFF~itMÎnddd`={6|{UWȱLtѱ/G}G}G_}PUձ;/vOe̜9_~9<| oq#==qrvmҥ ͛^z9'2֭[n ,Q(uUHʿJ:~m\z5$I,w`MˑHzu#|-d8}G}GߏDEQZ;#| )^nݺEţF @۶m8RuDQhEz2d‚J؀(a=Ś%G}G}"{Z<}G۷/nV|PU51>QD} F*B֭sb޽5j^~eGEaoĆ  + Dˆ!CZŭފ%K`С5_+±@ ={:G}G}G}G/''Ѿcw0ꫯqbӦMcРA$r:k*Pi 書PVV3g]v򩪊5kѣnݺ&_U)jTv| __QQQX_*+GMAyG}G}ɊißڴeŻ3~D Emf D"HIIA(mseBQQQXXnݺa׊hA,H}G}9/#)) ]vE~~~|n/!X,B.] 2>QdYD@^ЫW/A8p fS|1b 6 iB4lF^^} _裏>裏>裏>裏>RSS1c}{.j$'';;`ҥ3f }Q¶&+++7lذeaʔ)e,۶mCcc#&Ok VF[h;KEg/G}Gc|eYV =Lo @YҚ!55۶mC0D,azeY$I裏>Ni_uoG Ƣ<6YYYw/ bٲe9s&b dggp=-Cm"7ߌo;wʕ+c %%\r ._'b&%4飏>裏>裏>裏>תU+GL+辏_|eؚL1m48WYY3<ԩz MӚ|sC<ixPUUJB!̞=1Wf@m!%G}G)eYlN7Ə5A1Ѷm[ddd`۶mP۷m[D=G'331QDetI_4M>$b1B!$'';7i$ض__ԗ g쫸oByy9JJJ0~n+,Cw|WPPOG}G}G}G}G}> +t/??۶m?du@ו>0b j Ȁ$Iٶ /EoFoXԍGmmm1>裏˧7!n 6Fl-- 7ğibhhh$Iػw/׷?i eYhTUjKYA}G*m(++CEEpWBE:u`0zغu|SNm1mò_Wb&e xA4Ml,'.~۸rT_B>裏>裏>裏>裏>裏>NbiGUA Rb 񩪊s:4tT߇M 񙦉~ 㫯r0 G6mЦM ==1c5A5裏>ɪ(V=rKs(//i##QhH B4 `K.Eqq1ڴiY)j555Hte!AU Ym۶!33~1> 7nDII JJJ";;V`knƸo„ PAmm-\.c|W,]34hPD"lA_$)Gw裏>裏>裏>裏>裏>裏_gDPw( ;O?ϝ:[ґ%d|%IŽ;4D"ػw/>wto޽ꪫPTT"{ns5F¹H }555@.]Zvߏ/}wdEQ QB4+ ڌ=aǫ$Q0 H$P(]!<|>qFTUU0ݣ(?ڶC JLA"p_jG䫮uoϞ=?vaС\o&V\ I[nk0MŘ4in7>LWsB{쁮XdI|S|ni"'6sbM>À`G}G}G}G}G}G}H=ĐEjb}8x;6~[O<7bƍرcz,iY0 ̿[o>|8&MC:Ʒh" .@^^^uGB}􉪪7,T;>5d<.^*AףphPuuuu(uشi F`&,˂mۨ–-[e9?R^jsI,~Y_CC+//_jkk[oᢋ.O1n8L4 DVVVb|Cc4W=X7|N; < }]tQӧcڴi9r$`Fb|eP6,}- ,\Y }OסBMG}G}G}G}G}G}w{) F#}'4Mo'Oƣ>GyWѽ~q-RK%׫W/[ovÇ;ʗJ=s>&߶.{ g \-܂#Gb0 _cc#fϞC| G_~t}?UU FWAXmְj*D"xd(B0Dcc#(,tiEAQaî]}vő͕۶mC0(Ceo5'⫭u˖-so+V8 ׿'NDYYjjj㫭ŸqkK.=n@FFF|ECMFemVZaÆah۶mחy<].Xʪ*裏>裏>裏>裏>裏>裏>裏>kpP4KkYW\1c8׺uks=Xv-nV7DN;x|>(:<կ~`0ߖ-[g~5k꾛͛7Fڵk+ضmc/#>YUՏz=rΝbu 6_~Κݸq#EAN$A4(PUX m0 466²,adee!-- @|'Fr Ipg$i6mڄYfaΜ9XO<."-ѾZ<3X~=zt=~|=O"##i&wp?J܁o֬Yhժt]W޽;pY۾bv1Y>B1|0Dӄ-G}G}G}G}G}G}G}9W_ß x _?l I+.. /*(ɓ1qDK7NG?y k]tnF :s~c|vœ9sp]waܸq-#Jr-0|o}6m$I۷ח_|IZ%ωY;+BC-^]={8/cڴi'EWM6cmFF"ض2AdffbXt)hM=ss,x:u~w/ӧNj{|r{СC|pKKK xꩧv[L>'N ˲g'̷v9~a F[:ל U='`Xh}Ś|H}G}G}G}G}G}G}G}7?Bcn%zX]~|. 7tӛ|D?BЛÇ+Sر#~a[ػw/c|F~~>fϞ7;h\.\~xGgL8p/Ǎ7ވ޽{ߟ(J}n^w}PGq{4K,A6mxfO½bDEQ b,P%^Lfvj۶a&:ŋn7 IB4RTuYeYVs|UUU?>z!_QQƍb["\aHp{w^iOrss϶(Ntʼn u.y0r~(ϖ_Cwi0<\t>裏>裏>裏>裏>裏>裏>裏>;_Re)G;ߧPS>}_NOEAaaad'/{Adt;ƃ>tN;4\uUn|O3g֨صkכar;@ؿG rXy'.]>-0͠#[sE$I-۶h4;w⍷Fa [U, /qUU+sss7wL߭CIn+Vcҥ-DaY,oBc=!bXd }?g۰$iBi"(G}G}G}G}G}G}G}G}ї_c=CL@U~P&!ޏXӠR}(:׾}{WjۂoF\>fɓO3-/!?x!̩O<2{7z .Dcc#,\A*J]כpoá- UsrP=:òߴ`.@ЗN~!L:}kh㥏>裏>裏>裏>裏>裏>裏>裏>裏8Eaǧ%1 ~u;C&j(~c=/^8=޻bbi96=mcLvÇ*Zn EQidee,C$i0 i7oƒŋŐAUUEhd?6{֬\.^/o }%oٲ$ʦ 5EY>裏>裏>裏>裏>裏>裏>裏>裏>Rw<>; UUPJA;dѢx|7CU6_Z>.Ydĉm'^xʺ% (²-c֭E8FRR*%(QYY]va…ضmdYCVZ*r[Bߏ6mD.SrmrbP,>裏>裏>裏>裏>裏>裏>裏>裏>ϧHQNW5r^cA_xiիW$JDQ($(ox裏>裏>裏>裏>裏>裏>裏>裏>裏>~ oO {3~#H"$!H"DQ6p B( YBedgg/x衇V;>裏>裏>裏>裏>裏>裏>裏>裏>裏>;9|O!-Zt,}͛ef 'rR $A(5UXYie9x<׿}Xr?G}G}G}G}G}G}G}G}G}G}d"^me $طv+t] E$A5Q!MG $I:iA+>裏>裏>裏>裏>裏>裏>裏>裏>裏>YG@SUUHQ_tnllmF'6H4HOOrȐ!;FznIi >裏>裏>裏>裏>裏>裏>裏>裏>裏>;#֭[۪:RTA$Q%IdYQ-YMY-QvO>裏>裏>裏>裏>裏>裏>裏>裏>裏>s[Y':#IENDB`Carla-2.1/resources/bitmaps/dial_08d.png000066400000000000000000000066671364475620200201710ustar00rootroot00000000000000PNG  IHDR((m pHYs  tIME.;ķ= VIDATXík]yuߗs<ͣ`._ AaE PB$Uҋ"#BJ~E6(?@U QRWsn{Z1xLK:lֳ}M%}ιBU19s1Kcs~Z?NˬC-B?BtRJV[k :B)ғBrܻBAqclNḵc}!cڊsf85F)BsPkA_ƞuggg!䜵C`@nttE{tJa1iBV*ОBD!Z R8%t'}}}#g1jk=Dʜij1c@sF8=0k>1rOO{ 4M1'1i,Ai@U*JA$ @9~.}8)c+U$C& sW^힞K? r11!B)l>s`q #%<C۷R!E1;;~XĒBh3h)A$QorcӦMό`SSIJr0c Anr * |GhkkC暟o#G`$Ơy`#<l]vY磏>OsWjU NJZ W%WF\^X9yPJ]hkkq#"LM%)jG1?bݺ'm}>{Մ+GERk݇O>iSeJ) 0MS$Ic Z[[~zPpj| PQ ?v5[-[}t`>J"4 [׵۷mw¹s`Y#sW<8$IvCRJ\~PBwA-#0?oذaˋ/&PoqNJD EXӃڅ(@)t1$Isi\v^;wۡcxQ7N衇Z2@ݥR<.b J?R<!A6@@4/nÖ~9ԂRXA `ݱ=o:A$ۋn"( kH-Z#Me@)ضm<2MQcPB8|7nذRYσ}<<|mmmիya14*1!ys%Pa ݬ>cS؎bX#jPX~tuuev af9q5r=BȲy0D}6l@($hrMq/\BlBUZG)BZPk[bYI)> ֬YdZkqUoR 0D>Gٜab֭h+4@NMLlTJ5s!5l`.&+AB@)sl|>ILMM!"j5Zf6"%Rʬ(Xv-6mڄ^( [8RJj% s Mk.R.Ckk+P*2 Bafp1BV1J]/|sΙspy2+\bspαfttt`ll B\zpq:D? (Z XvƐ'K)Ź7eIT.lD\c O͛o B>b1l<1!%q cK)穔򹫮*t-:D1ZZRd1`ejC#)* fggqI={Z-W^y q)qYK Z[ۛR(OI.$V q!q]BdQk6r(ILLL`aaGK%rhiiyP(y8 ctt===`,m@ yB,k(saddgHCd >cll \]m[ -<xzzzⶶ,y={~O~(cE(d XnAAZN`cݻ/KRw=Mҿ Ń0 J(% H%7Z(a˧1| ?yꩧN?)狐RF((Y4zKux׮]|^<}c!MO<ć=Z J)8c i-|oKaNIENDB`Carla-2.1/resources/bitmaps/dial_09.png000066400000000000000000000275441364475620200200230ustar00rootroot00000000000000PNG  IHDR ((nQ pHYs  tIME, __/IDATxytU?dʠ2Uh RőVPřjZ 20h@Bn;G̕#k6׺+ܻ9瓽9pf;DӴh$)Xsyע>裏>裏>裏>裏>裏>裏>裏>裏>裏>N/3DӴ5MKeut'@'uϐ$) )r,4M ݻ>裏>裏>裏>裏>裏>裏>裏>裏>裏>S](J8ծ^ @@n~{U(k^,vC:v({)))/Htqś7o:>裏>裏>裏>裏>ۧ(BmO_C|I~;HBvHC}G}G}G}G}EsC\ ;s=$)U2oHV|X<q0'φ$ "rϫП Nˎfxz:`F C*jTIY潆}G}G}G}'H<>e~?$mWW|| } y<$ Z}0">PεskOI} .dI>裏>裏>裏>N3#)ڶնTp;,8'@.2 YQmQ{`m8F葍ڟQTT;(|ԨQW5裏>裏>裏>裏>|j7iױkOU*À|5$P.}vT{_J5g;u:!,G}G}G}G}O wm~˲fIIiݫ\fPg$n4yυHՕ@|2sa '` 90V<_۷̏ wG}G}G})J{7la_y7}m>(PTLC>MNgYpemCkq6f} 2`]4S,Mnt]D~S4~q }G}G}G}">t@۶mϑtipO\Qe͋MAgns#K>4 p(-XeppX,h 0 u<عs򪪪 v:{G}G}G}}OkB.>@_C| %l\N}3MtLOϧ,ȲL}T_i)ֿ֭#_oH;U L%7uHtǥ!h>裏>裏>裏蓾BBB4Eѿ aO[u%,V] 6F?zHNNwr۱z.DMP==(y<;y S!z}vڥ}:>裏>裏>裏@j( k;/U4?FAߩjjj}#FG}G}5̷v-MQ.Ngۨx.裏>裏>裏+񜜜|B=R\ nО_TUUA$(UUx`F=Arr2:w-3-%ނfX[:iJ/ߡce˖<裏>裏>WSg1 m{h}3NŧB!nO3} -\O _ii)$I'IUVg6}Q BϞ=;eM6B[nAǎ&u]L>CEjjp>›o H$Ip95>׾=5P4}Zyxw;m{ۅ)B|BlF||<>+϶mTVV u}WQQDa}"77͚59EQ|]v %K`ٲe,? s+V@ZZ>aáy5ħ*xa8cwP,#%裏>裏>W%({e(r]w8Ǿu}p7gạPZZzi, mƌ }#񶾰A{ qIP$u폋sG}G}G>} 28^8yk00v\w(--EMMоm۶@XmX` 9]ױzj;b(--}ņ `>uѵkWرCXeYh۶-]q1!}e}gH>߉J$$$+--A wFn݄ ЧOa}୷СCW_}w}ݻwg&vڅW^ya, >}:~>۶;w Yߘ1H,X>E_C|a@r]@kOV裏>裏>OxYYYMEVYYy{֐}cО190bm{ҝ檪BuÇ>WWWg@Zm~O?{n2dH>裏>裏>}aB[$ET|~?H6-SO ͛ EQvjjjPXX Gx3<>O8_F>}P>u( |>V^>}@4|Bu?~qqqؾ};RRRТE |%K`ԨQ+|P]]+O,OUUSNh޼rޗ_~>]ױw^@Ϟ=^q}gػw/F)^{5tgq>41w\L:.`۶mń og-/ {رcѮ];|pǏǬY0uT 3M_}\xh޼p>qP^^?֭w.Blق;PH8_8| egDf-T}fTG}G}G> L giJcžx<4 ,׃X42+9y<5 g )D衵p;i d^PQ't}G}G}SU8mW]]-/>,ٳirssdȲ,O4C(Χ:ڶm(s8s,|cǎر#/_.Oe}0M{ BQQLÆ 1ydDQ!}⬳ѣY;999o 3MSL_/u][HOO׵kW̟?_X\{4h>u1sL!}u/g&ߏQF , [lm˲ϢgϞ B3g.RtE8_MKfѣѪU+| qw#//ajK-ZBZMMM{wȃ&!4P;|G(*}G}G} KPl/uT] cjkuddd ==III|0 AzZun{o(#2TUEJJ }8v=x't }G}GSUHo<~>PQ>$ _|񅰾4a}_~ ''{gYx$'' 3Mݻw}W |e]vꪫ}HII1c k׮袋bƌӧN Mӄ@yy9fΜ 4ѻwo|h"{hڴp˃Ňݲ^C߯@$B}G}wZ.]dۥ|},Xf¾'f-[iPUĶl MӐUU.jjjFEec꺎VZȁ}(( fKVAmw9,;vlYaaa<}G}Gi`y<0|;b=p]ڵ뺍u$ -[DQQ`޽ԩ^P>]1b[K,Av퐔$O4ǣO>8r^y 4ގ96m㈏G||p>qйsg4o~_Hٳgdh>qjr "DZ_裏>裏g&<h4VZA4a}߿?$IUQ ;$ Cٽրqh-ۍAUU@ b;v D."H lvC$ϥaPХKw;n~޼26mxԨE裏>裏F=7B!( KU:;iiiP^WH_ii)&L'b̘1ʧi  `ѢEХK ;묳zj<yŒD)<Xt)*++ck1cF uQ]]-.~:;vLX_qq1TU'B}G}G}rl}۷GΝs"%%EH$I(..W_aÆ +**̙31qD̙3'-OQlݺ/q7 㫋p8~˗/_W|uQWPT_C؎$P\SI2E>裏>'k4 vS~S]0Ѽyz^hٲ%ѤII`&"H ]ea#..>/vNߏ#ꗟ"4t2daaaaG}G_#daŅm_y pQ1|05 `ph޼9{= ~;}./++ -1tPKB4M|rرcps~Xf   .>.r\s5qg qG}G}G}7j(\r%:uŋcʔ)|~?rss?=+oٲe+PTTsUVBt]ǖ-[p=`ضmP㷴Cl&B*^|>!IB1\@V裏>裏Fɶm ϶iE'~jm(I 2\׭ ":tpPM4AMMM>/uAeȲ6mڠk׮8ж0 )³UU}>裏>kD,Cq8 @N*^z%$$$s'.w> EQp9`ڴi7~x\pXj/^*?^=z@0đ#Gb⫋cmas]YYYBD_裏>裏>裏>裏_җ$oB.bL2Bz-]#FC=$+߰c8ɓ'oWÇjL8Q(dž p IV5M裏>裯|8mP>\B߈ojI@ $# "²,~ǾVU@YYY<jf[HMR \:裏>k`{.꺐U9-|T\r%?OD>> n:̝;%%%ذaӅz뭸[~lܸB4i&M¤Ibkqqq"5~飏>裏>裏>裏>״iS}'O5\#϶mӧOG֭ .@jj*:t耞={0 a|mFII QSS 2:@mթWnQX+q*$E$KG}V>UUUufv0yx^P$)vD˖-|hm^kD1uTDB奷?;iaG}h4$&&6OUaz<>ˊƏuc{bׯ_?СCѣ꿛nk&n[n_/}G}G}G}G}G}µ^+/;;u]HeYذa6mL@QZ_s]&LwK $ 2WQ8㠙 NĊ_裏>N/A@*Cm7ĞӶmDQTUUAQ;W~Ѿ.=">|EEEk!˲0:  ~?8>ӄl۵>UC4뺘:uju]KHڧn˲\la.M`o\CXƉuH$p8*0 A]999hѢTU%|_+//G)3 Z+!XuG}~8Gjj*}Gصk򐗗z 鿼(ì*+IM33f 4MCzz:222PQQ#oӦMx:t(c(C.]ХKt={) *M Car>|:uۙ(_WS5MdY ҁ( 0M3%Y2Mema4MHχ@ ڵ %%%hӦMlGYOº/@NNLu>N'_ii)~pBhժ  oƍXl6nEQk׮^}Uض?^eeeuk}ɲPXX4f͚z󯮔(> ۶ 7~'B}G}G}G}G}G}G}:E(Ã>(l5o<vڅ]va߾}ѣG(% 6oϞ=a& cVZ;YYYWǑO/'Ou4mc GB޷NXz JJJ qqTVV" !0M궋D ,0MFnn.PSSH$h4 ۶8\EII >/'X2IiӦ;Eqe}UUUw!<***.ý+n޼^z)ƏG"--q|!ϟ UPRR gq|IX;w7c L>C AVV,jiBlpt=f}>裏>裏>裏>裏>裏>裏>/ٶmbĉx衇0gΜo|wi8k0ףGl۶ K.EΝQVV&/##>|8."ܹ'H8$0d曰,' ,ÇOA|UUU~p}'^/ü~8-;5"2&kjj Q]]H$q֐6 ,0 h, 8p݋.3??%Vf=<w{u]/?_EE[NH6l 3`ܸq(**Byy0 \zxW1i$u]BG||EAqI >C 8'ND˖-w}0}G}G}G}G}G}G}G}L_vv61B(_q]wa֭ѬYZ_Y,IBi$/*CUF=CssE0'wϟoŋcСغu!_F~~wǯ__>Uz9dPriD{ Î;лw~ڵ CEQ`@4躎h4 uaY8BҐ M I>rR^qV Eq'Turss1|,\qqqB6l؀Gy]v(RRR`vJ[QEϟM4X}ݺuC(=kB!ȶ WU]_裏>裏>裏>裏>裏>裏>裏>裏_>}R*B̀,CQFGII dY7qD7/"^@UתU+\ve1`u]w,\ӟp饗֏Fnôi0hР㷑}Pz|3<ŭJ'oEхeC)]pg"'''1o@mi:lݖup8 uQTT`0Tݻk߈꿼?eeqߧI&}:t8?[oᥗ^Œ3bɉ}Y_fBvb+/99$7DM:j77.&$!.VZH$ۺTD_]6/2}G}G}G}G}G}G}G}GdKۅy<r-h֬YoZTKlgff6o> ^uǃ+sAaa!ƍM| xp7gϞG|2hv<3+8vPρzT5k֠ ea͘7of͚nݺ@AsUUc`p]i"  {o݆"kYxSU /pu_AA,Yx fץK<#w}7TVfx<\'%'⫨eY'/s\H %Y1i$A|ЪUoƷ^oڴioK.Ů]o7p|Ilڴ~|.Aqرc[J ;G sn{+`6=;#VY0u@UU!IIF ݼ8~84c1EE΄=lܴ)6n}qO}G}G}G}G}G}G}G}G}bfr2i6m֯qB!(nKOOߏf͚ ;3puס >Ν[zuΝoml˽0gbXv- z:Љ.RQzH$cOP~ɭ+-g@WL0ařeu}~Wc5XvmgYV\"CmhUA5>裏>裏>裏>裏>裏>裏>裏>裏>w裏>裏>裏>裏>裏>裏>裏>裏>'rBL~ՎH9닝yְa|;ar=nWX0ƁPVV]Ѽysh03((0lۆeYmؽ{7֬^h4/wC4Tv9->x<>v䓠^/His|o- }G}G}G}G}G}G}G}G}G}6#Ѯ躎H-zk֬)7n\&Mm^mX mJȊE:={P^ 'eJF"ʕ+UV2?ۈ&#ӟ4E%V'Whq裏>裏>裏>裏>裏>裏>裏>裏>裏>裏_җ̦M$.{}wA鯼ʎM6'+ dY,P,|HLLDǎ8Ha߾}(//G00 ^/|>^/4M7_􄄄{}G}G}G}G}G}G}G}G}G}'=>-[⋯IdȲ;-IR,cq u> ՊĶz裏>裏>裏>裏>裏>裏>裏>裏>O`C˗O;s\@8I$Hd)4 A7tCס*|>~JG}G}G}G}G}G}G}G}G}G}O1UWUŋn\udUEdY"ɐ 3->7 .f{<JG}G}G}G}G}G}G}G}G}G}~4A6mm I^x/nziC ,CUH_?W~MVTj-099i6f̘4EQwIB <裏>裏>裏>裏>裏>裏>裏>裏>裏>OLOJP<e%VWWWXQwiVǵ[(fz $Yf߿Ç~WQca,IR裏>裏>裏>裏>裏>裏>裏>裏>裏>裏>1}?+AĶgϞQ%I$EeEQUUUIeGUU[UUGc,z/:>裏>裏>裏>裏>裏>裏>裏>裏>裏>hAXN?IENDB`Carla-2.1/resources/bitmaps/dial_09d.png000066400000000000000000000066671364475620200201720ustar00rootroot00000000000000PNG  IHDR((m pHYs  tIME.;ķ= VIDATXík]yuߗs<ͣ`._ AaE PB$Uҋ"#BJ~E6(?@U QRWsn{Z1xLK:lֳ}M%}ιBU19s1Kcs~Z?NˬC-B?BtRJV[k :B)ғBrܻBAqclNḵc}!cڊsf85F)BsPkA_ƞuggg!䜵C`@nttE{tJa1iBV*ОBD!Z R8%t'}}}#g1jk=Dʜij1c@sF8=0k>1rOO{ 4M1'1i,Ai@U*JA$ @9~.}8)c+U$C& sW^힞K? r11!B)l>s`q #%<C۷R!E1;;~XĒBh3h)A$QorcӦMό`SSIJr0c Anr * |GhkkC暟o#G`$Ơy`#<l]vY磏>OsWjU NJZ W%WF\^X9yPJ]hkkq#"LM%)jG1?bݺ'm}>{Մ+GERk݇O>iSeJ) 0MS$Ic Z[[~zPpj| PQ ?v5[-[}t`>J"4 [׵۷mw¹s`Y#sW<8$IvCRJ\~PBwA-#0?oذaˋ/&PoqNJD EXӃڅ(@)t1$Isi\v^;wۡcxQ7N衇Z2@ݥR<.b J?R<!A6@@4/nÖ~9ԂRXA `ݱ=o:A$ۋn"( kH-Z#Me@)ضm<2MQcPB8|7nذRYσ}<<|mmmիya14*1!ys%Pa ݬ>cS؎bX#jPX~tuuev af9q5r=BȲy0D}6l@($hrMq/\BlBUZG)BZPk[bYI)> ֬YdZkqUoR 0D>Gٜab֭h+4@NMLlTJ5s!5l`.&+AB@)sl|>ILMM!"j5Zf6"%Rʬ(Xv-6mڄ^( [8RJj% s Mk.R.Ckk+P*2 Bafp1BV1J]/|sΙspy2+\bspαfttt`ll B\zpq:D? (Z XvƐ'K)Ź7eIT.lD\c O͛o B>b1l<1!%q cK)穔򹫮*t-:D1ZZRd1`ejC#)* fggqI={Z-W^y q)qYK Z[ۛR(OI.$V q!q]BdQk6r(ILLL`aaGK%rhiiyP(y8 ctt===`,m@ yB,k(saddgHCd >cll \]m[ -<xzzzⶶ,y={~O~(cE(d XnAAZN`cݻ/KRw=Mҿ Ń0 J(% H%7Z(a˧1| ?yꩧN?)狐RF((Y4zKux׮]|^<}c!MO<ć=Z J)8c i-|oKaNIENDB`Carla-2.1/resources/bitmaps/dial_09s.png000066400000000000000000000073271364475620200202030ustar00rootroot00000000000000PNG  IHDR((m pHYs  tIME 96lvIDATXíXipUe~{]l@ d_!!j (M N`P3.؛Xݥ4-vT$A4& Il&]:?¹KkުS7:<c8l˲ !c 9'0Ƙc:cL~SSSwه|}B !(iiy-GIQJ{(nw92c̯i[oN!}<4,˺,ucA} crlX@Az/cSSSHKKK%ۘ} cc~a[b";U/$k~vz#Oѧ}=0T?vpή".rSSӅڟ~ 1 caYiƦ g*l hJ^eK`NfLyz׎;61QYYE`fiO—Z"5~ ̻V˛ I=!h v#˓[ЪV;4F"-;x@ҥKZQQ!'MTu]H23Ysɣ/ÜϠS,T`qQ6nI?E"Zwm<>w,3^7n\S_eT$$$}uuu$TC#-H 5s֢'+o|) ,* ǐ=`^ i5Ʒ=|72088Bcp@p8I&07 jg>z˗~t*,*RVVyȑQ5/shR$W wK U7h`Fu}T4XbnT ,[Ȧ:X9}?pΧ^9 eYA˲*/ fi/>zzzb^}Aua6dUPt&dz4.999>XyCִncկ!~dg]" 0 X˲p!I<OH$M3Ɛ 6]!G6C\D9sd…۷/Bn4 H [@t] 7BIp8 tٻ6+++1҂{aM9q:(ay555-X9)HvkT~? #CBVV233EQ 2 k^6s Cڻ@C&ހ .pAּuz9ӽg͚222,ӳu`ͧYAa,[T cp8pqj%!>B؋Bt2ׇg'Kp&[ p8=ė "˰Ls$I8Yb\_G??N_p9Gnn.RSS!&Ly uv%o@ʟOGc,˜Kd?OҠGFI_0*Ckk+f̘Áo8>﹣Íy<$ɠvj㿗-{/w6([TUE4E$ BdYF0޽{QRR1cƀs'_@[@J`vmFB)IB6"z#z;5_#B4M!v 'ODWWcڬA49FxC<+I%I2uڱ= `?̒y0K߬p8be3h3jLu遦itT!bMffWWЈ9 nR#<3$I+.@]VrH_:-ܹs」dN;!,4Oh4 ]ߏf!++k BLn׫o=Js[ȥ&=?S={`̘1PG/DZ7rdiqۋ\~2OЧ#2z8j;\W-!;չ[  m>+7๋عs' @ww7x8[mFEzdjUUq ;ӄ{88ŋgʲ- H44iҤU0tAA8{ڠf,Y$I~x\tkOoɭ0'NEJ fDQ̟?.+ؑa39=0<Ķb|?JBWn1JvlbD犊TMӞ`QSS+kh;h8nܹҎ!oa~$F1YG1*"Hk0 {jj*! ?#1W_ڸ5QkmgӦMˏ=zyǎ5$c,Xw(c`PJ(^/fϞ#'''ނ ~?:::ݍN:t}}}%N EQX)9Xv"-))8"o|7 *`R{LQ$&&x<  Ci{F5+y F _С(ʪ#G4lٲ-Bl+H4G pW}9dYV׭[xQQQ~FxwWȺ'-U}9a_QP@A`a!.\@%p! _^333Oz.kaݻwO߶m[#C9{MRF((1H] p{y[oM߯: ø_˕$i!c,(19Rjr ιI)v:ew}\{iIENDB`Carla-2.1/resources/bitmaps/dial_10.png000066400000000000000000000400161364475620200200000ustar00rootroot00000000000000PNG  IHDR ((nQ pHYs  tIME,"C?IDATxwte63Z$DAAEeEt˲+Ȯs kU,A$ԩO}3$d񐓄]'wv=òa$% (r'` x4%8S.|#G>|#G>|#G>|#G>|#׼|$VV<[ijiݲǥx/y~$I[].ǣPiG۷or#G>|#G>|#G>|#G>|#G>| ]Ahg߲+a)\R_}7C`qU(KSRRj*if͚/ܩ>?pK8ӄqxpG n_vpQa|UXϏYG>||gx%`G>|#_sQ#G>|;|G>|#ߙ|Xz?ŧʾc5&:m6%e ,+dZn7LERUSݐ~3 a 髅0yaIoXFFF+/ZhIt>H, b0x@TU_X q|OCx01m`,[ QU!m3,|l@8Ȗpj )xG>I}? G>|#|G>|#-?|#_et$gɞS.nc0M=_:v? o?z6 Hq|]0_Sw c݊yppLQou,UTLA`8节Ӌ޴aC ʛFxQa֓$ )2 T3+T ! ;Ww^;g37{b8g oC)+M6G>|M;w:SƗ|#G>}G>|#-?|cؗљm_\}:t=.}E_ϋ`3o=P ՟v}rJ>F? W#a8u].։SCu68i<ۍ{AWKPf-4Y`!lC0 T ("$=ν Feddlܿqٝ  E) ",^w8˄>@(ڍ4h: Aa=6`YC}dݩ^a|ޔFxCˠ W(DMp#|,pG=0v0ewbF_~0az~?|?42D]GK>|#w>#G>|疏G>1[w> ~&ǿgwa<1_C8VȞ~~{x=8mw0FO WcWRx2 auxc_U߻RN|Z&?t:g0Tò1= PSQzqxx=^~# /[!(j!l$UU6m维gϞ8>x40O ѥCdddyHP(l/˱?A^eYQ_ngYpUVRv}2aq>#G>|疏G_.\pn}eo#nq=_d-ƍ˜8.d8Of[Ĉɓ5XPfݏ.ƨQ~ 졐 gW iT6}ʏ\ݡiZO[ AiAs80O:B!v8N$&&p4^ضmXek@ۡ  ]*4wYΝ[͚5kWQ_ÇoXd pA (F}&|B:ήohKEi]Ɵ!|-;{ c lZžq~񭁊Ͽ@I>cm|-Ge/G>|#_c=#G>|}Z|1dBh6 ͺ,Kς>k!=v5LId8G0V# 6s>VLj*cmEX 911˲C!iu5( Wĉ@A͆_ظq#6 YYQX^Y h4E^׵[ك J[vm‹9xए۩^6 ZS .D}ҹ30-u>}]Gq&Ν;kaذaLa޼y2dHC;|:.2E7߁텰q1[ۻ܁}~~nAG |;6?nx߄+o=8GL>/G>|#i|Z|#G>5QkK,v}>^@ `jv|'J@q&\|چ݄nԤD6|ׯ I l5Zp\8_onI xב6m0EfB8Fǎ}Cn|NgWoa瑜yAu{?@EQk.u]0  ٣UőEhA!8w߯߯_mk׮W BWoap矏{&OFYY}v| o߾[ GH*ui|d|>׏I,]Vu=~\yLt]GUU^|E >999E/EfCnn.cP|7oppU*>7> aj|k澟~B%G>|;Ge/G>|#_c=>w|WA(9̞ϛU|~Eo CslϿMKjqƱ۳N~kkk!I>UUsΐe9, SNEVVEߢE I ]vAu1EeY},Ptݷ~I;9%I0l6pCމQ]] 0 "qEvwn PU5eݺv(Iغ?xM-xT3''_Sg"L pͰa?n?>Á%K 55999u,c=0 J p EhZ|>#ڵco郶m2^z {F.]a߿?>UUeL:W_}5F}v 2η~5L5 g=s)o0!(A|Sl0xx;/. [ Ȧe;?/w6X?_|#GS}Z|#G>5QkKQ0. |8kgʃ9>55^Gk<80~pv}Ymٲ _:}Y!!!9a8۶mCQQtœ/2aǎgy躎;v`L8Áp%0E\X:@fff(p,Cu55U˅ky<h À >nYt]a,+qI0pid !,E8x%Q|#%G>|kײǗsz9=mx{E{O ZyBoc=3̿˗cxǶm0wɚO\wu={6Bs9r$TVV2 .7oFMM >޽;lق@ 0 dffb޽ ÀAyyc *SS5 "ܺWN,˰l$24 wqNu'g#͆ ]- p .\X ˜G|4 7HtV>˲Oc?+߻7,I$pfΜv1, > \.>8vFɤOu,\Dbb">]o ??=z`g{=f~-M3l^ylݺc.2^R"EQNz _^ WA: _e0?VbŪK>|#Ge/G>|#_c=R@<6}S?:mb6}ZG0E柿  $I$-_ [>8 KSNxױc&}6 _2$ ݺuCn駟2y^w֭[Ǥ\..b3ǃ[n2, iiixG麎>}੧U},PLBW !%\蔛ݣcu8P$IC;^x(HII.C"W8 ѲJCm\LBWs<N|N'F]u'_=7h $b% Zn 4ɲ0 x4MW_nYܹ3nff}Xv-~ϲ,lݺ/"L|PYY|o߾'}߂C<%cӦM8q"v{o_z`(+E_RRRAp4.LNv7ԑ`eSlK΅w./G>|#_c=#G>|}Zr \.X]9x|6=auoawRSSa9NaȐ!0MӧOG `Η\L4 s̉q%nDŽ uVTWW3̿ѣG]v8W_!C0QFUV,B^<>4Ou4~+Oɰ,+aHG=!I\.DQi0M ˲ I ",B 8嶏 DOʲ",.BP< B`̘1˲r*++o8 !Ixжm_w(._Q8/[ܟ|>M >UUѾ}{HĬfaĈlL\p)S`0avIߑSX[[[3gbҥxѡC:B&|QVV qK CeB޻?9juM_Kv~-__|#G>|#G>5'4*+oD 8@8 73 A58o-eBؽx X={bnq\޽;f̘}gϞe$Ix<8q14!I.Y QѺukf}XZk>F/¥ACx:0۷y$ n#99ڵCJJ N'Eq, p8 'u tFO{ B6Mx- IzZIF|!@u`l/''NIb,q<|xg׽{wݛY(6mn&8|a˖-o}23MfGdee8;^ eryqގ4 ~)nFO->P~,_Ge/G>|#sk|G>|#e{Aw"{SqЛۡ>91DNNO|/>L9j RSSQ^^aÆaΜ9e  h~O>$t;sE\\s\> mڴCv`ʔ)1c<s4hzŬ/%%.i|;W}?^`0ؑ LQj֭[78hxжm[kQi<E~OӉ.< 6sx z(,ih}4/0<4|#Z/==iߨQ裏"))I_||<c„ ]t}%pPnfj11~xaڴih߾}\ e hQUUO>'OƇ~0BhYy l߄Th$BQc{&G>|}Z|#G>5gs̴NІ݌rx١>y!_7|3}]3>233+]v̙ÔO$x^Ѷm[dee1̿$G>'JC4 0yW]z)DQPwyXQFQQ  @ IIY!"dY$IOnSN{kjN\BE񫈏8(~?ydgg7gϞr%T, |#www3+pw2[x1~i 27t VKk?@B=}ǡw!"|:_ۡp}kZ??|#G_Ge/G>|#_ ID2BÊOE(xarssѫW/deewnm ,?iӦaȑL޽{wިűct:E_ZZ>EQG>|k.Oe7M3+p&8Ih8 DKZQ\.$$$`ݨuN'Z&DQ 8:wo6o, $eٲ,/ Q!Lip4/33i& Q G>]s5!Iҩm+`+9JEqL|xǐlBQ:yl JɁ _~R `ƌg?/G>|#/ײǗ|#G>|UA89_ܹ0ЫҺ5[ {p8HMMEVpUWEW[]wuؼy36l؀wyo&233c VG}#Gȑ#: È}~gXnnG>|kn>V( e%p\scEQ(h۶-RRR{nH,8NEDtߧ]f& $Aץ*]n7UV- ^ G>|M2 }7/++ K,9ot]NJ+ @:ߎ%(xZ_Szy.3^R($8zc}|#G>|te/G>|䋁M'}Gs,G1or}gΐ߀PZZbܹGfj#???{6#az~#G>57dY6QS8biu\ À|۷/l6a& :$%AED|R8 ) TUm2q|ԗbՉ G>|䋥Oe+ _HY1Zm=c(⼽{OYp8?4 'OFRRڴi\s5g?|#|te/G>|䋁oHԫ΃eYR=zeeex!BDbÍLeYkig/r A|#G>򑯙^eY6x/8.yX< 8eE_ ( jkkxbmڴ(ypYQ8(R"2">H7ôL8bS$qBIO|#G>}w#n<#M|#Oŧ{8vZPU(6Ut#BX0K 7b˖-عs'v܉_~iiirJ8{y>fO Ph8qb bLa>X_#G>|(IfK7OgYعg4M4M0 P@88\.b˖-(--EN{yeY8XP8E(ɲlF}i(((h2ߑ#G s<#G>|ɷo=|#ǔ˲lH^ UW^Sk֠Auu5 0Q[[ M rH\.<MpQlݺEEEPUaDo^ZZ5[P 5M i}>ت`Av؁'|x|#G>@~vQp,aرcg9ۍ3F(%p.oL|#F ٳg㭷b*O?w?aӦML_ߏ3fѣ-r!G>ײǗ|#wf_qq1^}U~|k֬)Speaɯ` cWAy㡨7ܹsѹsg̙3 o: G>|#-e255uiu ("lVB( G8iu'.n( $I躎j_QQro_|8] z3gƌ竂zm:5oر9s&ƌQ]a\*V 0G#G>DY ž8˂X~=foX!EHY*,˂0M`HLL$I8/XjUEÁ8 ^1t8EQ>evh' Y, i`Æ oAm8 ݎ86 |#G>5{Wۻ6񭩂wۈ[1lN7{n&vm8gFm~q;vX\{={6`ԩuoe$>fnݺa5'eY8Iߖ-[ IvʔOUU{Xl^|E'޲1sL <}eYM?FOqՀ^#{1sLD_&Lq@8}ڨoܹc~ϐ_s_G\_|#G^{ɓ="Ur0 *`Y|B=z"&# IRdyK2 ,Z޽{`2A$<2$&.x<]ɓ=/7C9]x;_EP *B AK>|#}ZZTT:|m r[[*CCZl6? 99ׯg&?0zhtӦMC=PRR)SW_ŤIcC̬P(z K/￟e͚5q"m4|Ǘ|MSU,3 Xv-ʜ>(|I$$$0ۼy3Ox 0Q_uu5MUU1mڴx_yyyh۶-^}UL<yyy[k> päI`& 8oM[\n_1bk_Ǟ=Pk>|#G>57Ij223f >?P#vZ>CEEt]?IE1 ˲ QQQ]vb(66K/Q+#_A|B4hѢ__ i6C|#Gײ7&48#i;ri3ohu ߞ={̯k׮xP\\e`ٰb G.]0aիZqqqׯ^x2=z|W_}y1??/>˲m۶b髬`(KZr@a_<9Y3{wQ\\d׿y1g͚B^a<2dYӧOǣ>^z':!|~{Էa\.591cƴ84CmF|fPw1&E1 " bݷ+Ps:#- 22|tԨQiW/h:Xj_ܷyf,XU<Î֭+#v|#G>E񍉯t?rVɦ`3r#z [b? BPJ@C:z+z01u~;JJJ[CErr2}]+G-[.Blذeee)))Xr%μȧ( ̙/M6 L>>X~=^Ûod[t)}Q&աCp}v1cDQdWQQ/ / +VW\\_f <3W_EZZj^scmҋ)l{,qn_=_XvN-;_|t_|#G>ӦMeٟ=SUpJZ F>&[d8ƾ}`|9j )qqo~3]和5ix/ J,^ŋb>j&W l+ z|#Gײ7>Kggy[!ؾpFWKD0"dco5/ƾ,\x̭_0~xуEE;yKn7 /&9cg^1)={bΝ?~cʊ]5_rr2#99|M=zbͷa\x Ɋoɒ%4hP;Ʊ;w.j1-ܹs1qDlؾuwD}ɓq\_{ ŋ1|pK v&t{/ ao~/h|G>|#G^ur; *|-Ge/oRtYPB T[>G( U}ώoZ|w4ފ/=SO$t֭a~:u3~ [Ȳ 4k׮]%_>}}v&Ν;L>$%%_yy9~ݻwo,֮]A68,^W^y%s4M(ѣG3OO=zĶ?;='౨?Ά,˱O}Q9[?ic?*}#pZv}|tYG>|#|w^p>|pǀ WX9pDS!*lcC>v v [$IP3 0 TUUaUXbeAeMIFDd1mͶ>55uO8Quirߏ Ȳ|۷oǢ q<FiBed&']J v:G>|#Z__5hͰ<>+v΃_Ѩ$G6Q{H62Kcow gr@vv6\.@Q?Á*oߞyeemܸУG߲eː;2VZ/)))g?7]vYe7p@dee.}EGQgp` KP{Ngs>f_ͅdNsD}!8ϱq~l}te/G>|#E\{ǿ{<E`2ѲPY\U[n#..p())gaC9m<- M6pG}߮;ˆ4a2 ӲP~vڅ*^_MM izLqqqaSNݻ7/??L.;vײǗ|#G>򑯱ǝo?oXzRH| `0y7SЯgO$'vCTTUq1l/.H% 薅t8+)Av0iҤ8Q |6zJײu8Czvq***o>-+CM08I<ŧ&p]w|#G>3>-{|GKHMEM_R*H:^Oq=Iț4V~cO~ =! y/C1lq%#n*>o&j3͇lH~ۗk_tNND]Dxtҙ_^Wxߟ oA1Sݷ.냗$yӃd~Gw3 ,wf>|#GG>|#Z/Lmcڵkw3{GAQTvC%CZ7MT&hğ3$  a{b" Ǟ2x<?ݺuKv\Os:ٳgdqb CA縨4q, * [,Q_Xee蚖))#G>|礏G>{uh_-{=q.z7ownoM'= +gc]pHi!6|p0$]v̅kٻx2?F_}}akv6++FHyNkloG?!ʊxY;wkJSmxu)VreIT6fs|#];gƗ|#G>򑯱/!觟~zKmmmGLWUq˂瑨(Q5M4Y.7*50C,BǤ$d$%@YZǣW׮|Ut:_9~g <*, 6i:†>++!) IIPM.G>|#y?|k#Zx?cc]8A7'Cmӹa~,Q@ׇA.ccU}G"7U'U1R| ݊}98}6;P~lpX~#G>|rCEQ{.]lZ02I8)Ihrh0Py PPU))Hpqq葙 qf\ql,+E<@ |ZBӉÕHOL$G>|#?|#Nyp(=_B {0nP0ft[ _P0/}߷wٝz!f0{)Ӟs(FDw%h錆" ra{.?i4̏% Q awB44v}-|#GA~#G>|G(իa8.w9nݺ[ê:V! vEM8WU@$Mӆ<<$AO;&.e!i:]+2DQDbbG>|#~G|#G>O-/ KJG 3Gv®u:ao*XD~_C\Vs!i>\^Ha?7|#L}t|#G>5U; ,F$/|7ouMjZFA4"}.}#Fp9N Eq\/G>|#G>|#G>|#G>|#G>|c?PصkW[Y q (")!q_#4|#G>|#G>|#G>|#G>|#Ǟ)FO_IENDB`Carla-2.1/resources/bitmaps/dial_10d.png000066400000000000000000000070441364475620200201500ustar00rootroot00000000000000PNG  IHDR((m pHYs  tIME2{ IDATXí{\}ǿ}3;;۱Bj/3!4Jjkm?LBH'M)Bd2r+بŽ{Bd[kιA`-R0Q)|TkZ F8B7ϦMV$|?[s9"kClV)qXΡYj\k[[^G0!a ؓ=;sӦMo~3`sAp)x <0cOShCyiJ ?pTA88'?3[ZZH.`Tkr+qh# C ApXcccسgܲoQ}RDH0KV̙3gO?O\Bpsnn=~ V)1\5s&X48ZBc<(0 zU?{6*N@&Lkh(=zy曻vqJsM&j X裰Z#MSs i$I`A[[.K9 ,M!U_[.Ydώ;ҋ_WUC8!e?Rc.cB8}%I4HJys ݇j V(PBN~`%o.חqwNJ4ML{/֠Rz1$Iru41ιu!VX;o1R fJ'9=s79q+efdȦ)Gf2R<!.lh/IӴ 85<;WG!RJXƍ3 Ejj-Xq8Ƃtuu A@)!!(5F_@)bb 2q !Pǎ[2@,XK)ֹ?AFTP( ͢ӧOGKK |߇R 9ГϛPJrf̘~&q7K)R a""abҥ5H) G_jBjYȍ`)ŝ˗sTR 8 ,NOkq1KS MA,ho?/PJ4!=R8J)#GpM79<:GLjJZ J)eXp!9}2΁q0Ԑ\RJh5Mw ؀1Z ZkB2 k. c֬Y徜U:pqxZB oPJi!v( i `yMj(P.IXkq D&8}4*P,!hY#7}.zIQdcR)Xgg^5ha9G811["bZ rjq7%iyBÔJ%=zDTjv8ؿ?E3sT `c\JEn;|(\Jv>ں۶lAT3.W,&wu!ةSغ{7 )|GKK%Jq xiZzVZ)?*r@)CCIɄ4^ζ60JO)\;gwᩧ:~g*؈m۶ƘoBZ}ُy$!\D㚞TFG1ЎVRLh߲j՟x]wu2(~B_OmR'hVW_}ϫVRεt3&p&=ѱgҥVZ gSJ=Os~ѷطo )m6B2Jι/3J^z4 IENDB`Carla-2.1/resources/bitmaps/dial_11.png000066400000000000000000002154561364475620200200150ustar00rootroot00000000000000PNG  IHDR  :IDATxwt׵ Iu"wv\P2mDZ$7unw%%E.*V% m| 1w-.f2|cu]?8RJ!ڄ-B׷m`8ݡp#7 <}aٱc{% vR.">]R>um0t/ ! Xj !0 ۷|a1Y)e#Pe=*fO8@}}Rƀ(m۶)4 |?PD?jiiYDJ? ;u8ǾNR>b鶖_СC/B|]_NB\X>L0Gh}(%!R Bܼ2ٺ `ǎ; ø Hà\j---+۷*u+9)単#~Ut]5g*h=э7رc'0Ǻ; PL4Tp[BixmmgUUϰ`==%EQW nߵwރn$g2\dmw;8\Qe0r d`0'LFmOJFs nGrNz<^BJ)R+|íb.\`uK1 c5#G7xPx4֣%1WoZ3EQ%MH$躁!gpa돋ѹZe۹BEyN]]v`u"\*UϏ?<-;1CCЭl6̜iԳ3!h_=zt?!ĥV.B܉y&[mə¿#m7ebۊ?B>Zq%ǎ+PG? ׊`KK˽P;g]]SS(!\}Bv5:?ܯڿ477o9_/q)M!(Hu6$_޹sgOGxrBRfH}}w˹_O"G y| S+d<>(E6p=s*?CWi{(BVNgr2q[{Q ]d&rW>S])Ů؋$Gh1P(4QJJss;vkD7p <)XsԔK؇e5pX|gݹ%~ۄS;MK )>u@KK˕ЅT71u41~V]t&J"<>Sw<>x|d7U`4$X>`]ExR >3 c"r}@HdqMMd||~ .jS5Vps\Rlppf2x"Z ^YC >V.>| |2:"q/E-=f} _DukL}d89A4zd{>0]k7F4֔#8x|x|J*.O>X6C]͔%Ʒ|>ϛ0 $qq %mHfu$?Rw9 (ĹAڶh O [܃1K41L>.mH|敚;:RF 24ҦV>>:8{~;KuF0r*[ZѺjCz!GLNO<>x|(Lede@#}e?@e>`gVDw o]5~٣r(| ށ}\ \lI?x@̦ws;tzsʯN|X|@qk_^vGcjbXn_W՚s ;Sk'u~c 5Dپ U嫺$)AP`0bU 1Uy|ޒ<>x|(J񁑲ߠxCp= fAIlOK\:@>; Yd;ә| ɘ(yV^)d|8=uZA~|<.fbBj!'hWlN1,(E@*'#|p¿;fU (Qmux_?\B)W`pǵl>Б7x|JS>0 ~8љsL8 |vQS)>0:g"t _]udG ^`!phb[>p g@+/Qro>cVB=MI[.є-Eyv : \R,0X3kڵ.]~o9с:2Ю/'O)x|<>PROQ9H )gr+1W79tN/F; #2,Dr*P8SS|ZGxBfۗ^F֐:\Nt'i/v}78qDƺPCh+!S9Y}g/NLHI`s3U_2$а~M*G\rqe=@z|wr/?ІvaQZw-$ wx|Jr2>3F L$ H)I0enG G^_`URLG HPym(|($@x#֣wPO]!v Da:O4СCB\#l޾}0_?CʀoG81+G` Ќ;IDy՟$rT^>pɪǛ:~>yI[ +}Cm?S%x|J8@|4t|0dxY8$\d@oV f5`I_@To*,C2y |)9:F+ FSfINuW)}Nѧ, (<)НrNN9+: 0&rƟp_e(1g +3L XN]mao<>POry|<>4DH>0zp|sJsp,6YEg4-(BԿq^pIdtxQY(氡Q˵݋q'û8;ҿO?a"'vfH(SSʀQ=LT ?|ԡXW|W~̦  _i:-+ϟ\><>x|E BN^B9`<0d#I2KQ~> AQH&Hp'f[ XŒ RT姨ƩȌ^QU`+ē.g*x1*#t;V?帠<&xr$+X.W%OWƶv(gP[؆D}KK7P =  3*R_!x|(܎ri)@_z2@Τ$p*ӀHJ||@62"8 i O}Tu r1.Й\:qF8ȻeEO >yH֡UQ'apCj Em|[xE'hm+HDݜ=U{*ѣ !ZuvRjWuW>xd|rt|1z|qe ?!<<>x|@|qdCxǓHjFTHN@2BIU!O'n.[C.cYIF}*UJ>su)X]k R?J5_jDU}}r nF %"s ݭ#~yΒ9 K9@Xu\O"r%$;{jlA}c.wR^Z|P⏽f.o[!Oz_<>x|x>09Szș!9ɑO9oer2>2V #1JTWs|Ub Xnٌ۟ GZVT_pk][p\8@() D'> Iby~pK̷gL o#퉫Y|`4RjQZws;hr1]qTE@؟J{jgUCnV`^CO*!x|<>P<h`Ʃ=d#H F!d$H( |&\+hVˀ̚r\2ߕ#k tېlF MxIUВM6#ٌ&|lb/ۊ+BXq jʈw+P3$ =L>`3V#\}lORJON ڭӖ5Xh\z_\ٶtx|0Bpd#~ Ehs4zss|@Ne~j1`(:$$[Hj3v0&qљ4a|঺Q'T%PN v ؎`BwļS#!6@v|)'cХX 0OKVEY|`pU䉤$0@{28@90D3(,Sy@{FO8V}ﺊV-[7<>x|lO~@? d>0ėd_?4Һ5̿'n:j(!G:U[.Q~#~ >(Ēb-9^_CeU+]"ઃC|sSCD EQ^U#3{"hr۟.`9b ߟH*SO kv%+)gЮ(-^KۖnjG|@6⧍ !PHR V28Z?dj} i !0d/Z; T>ps]ۑB@aHjDm^"$QhH=H끳u_\$vO,>`b`$)/}bi>@:60z M*?dkcͳBA>S׮0_7 aG Uo{e" ݝBsI|{#&N# d_O|@94ޠi@A7(f!|tn|XJ(B{@G-Փ/=&^>P#"su ==,>pKtl*?7g*X?o"@nr/uuu>p֕O* x|<>;)=qUq}]6BIo\4\_1aL0I@Hɹq@6 hT* :A@C4|@ RO7l:yQe=q~5){? P!a{R9'<)Sz*x^>3!~j 0*?E[fh/k#|`Z׽ZѺjx|t1#},vs<ĝgT7$ 'ޱ3eGZ]?*2_!;`]ƣ׍u`.I Ǻ5}l' 'n2!oGᭌ KqC^>o+kpڤXj?/g5zԨ@N1[&Oy!Q@|ɁuC4ЊlL.+Y_p/z|ޗ<>x|IWC7 m?> v!C]er3;>А~N>UN${QAZTy$> |h;r) 8B"8`0I08u` A|C1nw}2$>p0)>+B@˅q!mpҳ@+7EKڂj /ֵ7j`)+пWĕu~7;x˓Uu>p+_^xԻ<>x|@L_3඲FG'1ď|'s= [lCujZKRչ`<'H$0PN" 8n_+@SE?$iÀ_0%'(HR XWd? ǰna8@uCĤ8/"(I]otQxZYWNt<ǕNڟpCiul>/T*@1z?g9ؒPG=<3=<C]5漨U"@ b1D^:r6@܃v: %XHxk<>x|{\VJ8,?0LBgXb )|~ vtDŽg#rm6֭$KCg>(0 -U#98>t|GauY@N 18aa@=_DfO|::s؀yEEqƠr:"8CFCUQX#kd#}q>vRn&s+;N fsxK Ԕƾy]cUl_?T }eʛ?и= z~㫮.wnC:<>S<>CƗFuT!m> I} |UG> k\WGS}}T)0F8i`^쵡X#.*3RE*x`<A35JkUH]" 7LFb$?F2Xcu4HE5t3r[U>0 f޷~S #8 {KQ`_Vu8o(p2? {rfSX2E==- a}8jz*x^>С+Ξ@^>0se#Gƅ-w|`cWax<<>x|7~uXh?9nc@N>GU $^$#xט'"B(eC(b]Ve> |>)yx,`}  SɉXU f_ D:ēlv=+g bb.//$TqE?$S)|,X|$O6hkvNN$EVi> FTAWYw9IGI| fu|`wձ 2ֺ}Y|@BW `l/=(rf GWPdYd*/he#;>?K׮5$I*U_pيeO* x|0@M~u_ϣjmҿ*R優FUdYUWW/J`kKK˨|| -`5 /9WA!Eɩ|M`'~5ٴ7.M g+8v\"[Ap&YK,v4OWvX9ssv(`,0ւ ",n`pc|@PH{C3A[cC>)[$q(>%j̾cA X6x0ۢ"ԱpyE K<>긞 Dt@X?ܤ:qqT3xILpw__"hx| UCXNi^> g7YVjNrLbt4:n@B*w~3d|bI|`1!}q!1]^Hga lj#<+!T0+c,1`)TNNElIAʲ/9XJ3ey;w'2J`+0d ZBN ,줆8d>b h=ޟ*Q_pS0*Oؑz; '$}e W|֗R<>O8lcj5Rk:z~3? &ŮT= !%,>J_+rPeo橄wth40xg0x /~!ѵɞUT%R@P&|ݨs|qY 318,EYT^nٍ:ニG)R8d|,k0HyC(b$e,Y!}4~ ҕ\SM7A!v'ğ6lPjkk֧Oץӧ㭭S(`UMY |zuw(Eـ/ǖoQlhԮ|@AϔMI]-ؠZ}vĔ U C WNp/RY c6)~!HTӁ~T6"P8 uDpTH"xX4Ð]xb>#tX'|ɿK*0~3)17Oi r?40 Kam| AE Gl[cʻuiStd\޶_S%x|wv_%M^m"ƮAѝ5 $VZ59Qxakhbw!2Ñ]r* fɫ2|@QYl1b>נe:s;a}-|`C3NF- #hRgG&&D s9/`ǟyBR(iCl:D9j:/  `ld$:FiX&X<|l.$+wǘQ´:R8OQ75({' vCEf-k[/<>;bH{@͈Ӌ|@̙@Q~>cȀ'4-f\H)Bc?To(ޯ.&Nlr@ϣj_?5)> >FCҀBFFPХ=4]X|`Son5SIԿTQ祎|TM,#RBAp:81t&ILT❊[\V&nRͧJEa9߹Hssn`5+U ˟p)\y*s 7^ `:uOjsyC !te/W_@j x@kX/*KFeS|@"RʝQ0. R7HO-nGΝRv]zO|@Ю7$ɊƥmK{Ozk׵ԌЀrӾR;)D^B\yFT675 <60H3uHAX@k C4};Bp r:W c9FBC5x-QCkh ̔CVrۂ:_ӈ6̖38OI)jɇ!Uy3 Vud$ f"Й1L>0GFk^1H8t &z2m.ճm6|~LI[HQZ]uf]Ǩ\ ,+@(hr2|@̔oF!Y*L>Xq汱d> /P´:Rʼn*.`YeYVCOEtN 7 ?j7^; __`7<>Sl7^yH}l;ZU>{/\:2!*__qCơƎCB h̕3b+b[?0i}^|^AS 'Y>wV6,x(^hM*b>Oɣ'`-P2~p|$g9([T.Cb?kH0G6pA3V"s!*s+DR 3W6pY|w3K :dQ}ϿӀiPlK(v@@Es+St.B"-&ɗ?Z ,C}B΁ykՕSҶ-ßpI=Ci ؕ@<}x|NT- T}- Hܫ52q_N}p},TAh&;ŠԁHIYAU~ @`a݀Q%RvF?S>b4wc $ӈ0_$W|``??6\OnZ^1-,g2AdxK>Y<.G|O|7in> ev}X=4ˑm}IlX7ѳN0]|iq({K>۟P:jMA#曩t>`NX@/b@{~w|F`B=`No9qmnnv{™Rkk~=(<ӧχg  PߎhbI_jO@H'@ u4_WW༢f xb\:~@Td B6pAR-|z]W%L.u9 wMfkGh;- 8[-l=CߊgS+e'\74\J$9 A'E3gL?bs- 7\<(gry@R6nԂ4_@-4B pэ| 8VbF2d>0̗=aQn"泥d>Ka'"t,>cD?0,`U}q>SQ$A9HIUWU+6x| @'>3lmCa[\]>𤚳Ң+T ?4~#fVA> A Ta1A}}_h rjyLsƅIvPȍʃr:+uo!0"q.CzrOt~,.ey4.|@60ɷ e >rTx~khO%zOP%zd"η%fgm0 ĸcV\c''ɵxh ;#a p]_ D?@!,AEoZEo|*_,`'p#p7̣@FN>[R| 6UGA{)"p6"e92=nT`OP"ͺz% \ٺr,M:dFVjkkoT__R]]zk_nП&L ~+IÇPWW=NR_ck:6]~!oj ?MEjr?0gA}&#JIh|B ->IT]4@p%oWyJ:~>0@P$uH44L)O8<`l*=2E@ѽsl 5|`@c? ?c~&gb=_?g/$֟#=ETa PɃ RBTJD>a>,ZJ$˭?Eb_b6m[(G@nmb9B{@-{) 8.{}@@"0 *N{sHSsTµ1Y*g|`2|:jEuQx*:]ybOymTCo߾'mmm kjj> ή;c?Z5 NoY#&=]]̝R=i[Z|PC`- h.v#q?0ԯ t)gͻ džf l/,3:r'Ԍ۬*zxM|G39Jqϙ?d}AEm)k>< B\XUْbsK^/_0b" r ɇrn\O:wl  Ѹ k&O$7ѳ@oӻ3e FRh@򷖑fVyQ_`)|- J>2B_8h^b?P̳@gr1]qsgW$z*W>ogBY0̯9wBr׬677Xk_:*4!dy1z% <46c_*nFImΟT=e{ < Pqwr$V* uo|j+(7I)l-1c_L^k.`/%Q`UfHEęDk/$P4l)$򶽁E1ȫ8l!mF=p=׬>91ce>=7x>,1 |`6q=$T_«| +}H1?!'%񁤵.TB{-?IXME)X<|"xuaQ'#k" d`FO 1;#BH!qh 6WTխ/jwh]4a>ӊOd-B "|ק|ĶF/4T߰^Kf cw!9>–bY|J*`~ E;nS %jݰX l`|cO(LB'-<~*#?: H~ QY?4F|X%X9p.1%%9U82yJNYJۆ`09|jOP?0$J\7Sp߰+Z_p֗O*!x| kS &fޫ/8~@hg %9*:;N3Н76&\%;R~qcj.Ԅpbq@zN8}?l\ †xY憎?=gʎE;1 ՠd3oMuToXRM4p3v"\,2]+oI;Y|`.и0WY졠+X;8]I͵f$զer3,>ЁJOp>kq io\Y:>1,5ݎ~r+a.fH-a Ub50 ln;rdKCKY@KD"ӕJ)AUƯu]@]8"|`RL>0>-3W 򁍉/~=>S%d& $׎0 nLJJc{B%; UNt 7B$0XsB| ؚFU>A/6Xuֽa|N@JTKjĿmzg_YD{9 xt|1ˣy̱GgȀb-3@ C]i u?(֙/'Hǔ?UdV[:t<to MU->#\$`nkPnQ>WsYU>p0)>4Ge@~psBSXY|Īv}@Y|ԅX3@8)aW$F*_~i{xQ~ }}sL&LaO|CTu ~a f.:>>>.g;&d롡G4YEF΅q}<,  1'UxaNrFb vƔ^xpjl(Rma>иA?ᴕijD epV\f}|Z".sC1M|i_[m ;G_Xؖe/& (!'xzkB;`WBocģHzu])H/8$pw 1;KNb?-"K$<,mCUq;~~zPr.Y|@7D/ns fso9_/mJ1 F9.Te +P_"ݶ)JeO8ȧx|`]&:w0*O &!ݪ05qGW<>SeO'x`\U IL^^~P\;|6UPWSF `A*)r0os^N6PT{|-1se7^.PЕ,jM{kQ>3vY| Gsݸeݭ~QD|Z5F?p7]ly+DIX|@&$qv䖒S1])g}Opp !2j=P>D&\ZkWq say@kRRj}p+[:~zEXQA>p_YxԻH sh(yՋꟛ7\2Z% O =57J} eD܋n\~P{0oHW'L8& }oL'$vOف@A̱H5?w\QZCC ]9JFC)˫:\S5t~ "ӕ"O5 r%ԏzx\gJЍP~9/jH@X29~f;W ]cP⏽-$ "=>S7לpoމΧ{ %2$mV{|E#$ R^Gg?%,\j/8$Z?.k'0/Θ0E|`υǂ/i٫Bg uwWZ3l>/tޯqOCqlowlH\oԙ,> 1ya H].>]wer]~J[q%vl>!oh6겿|-O)7?*W Ӳj`D5 |q}a~G'WDtvRdYm37U&UUTY_w6@ܭ$B '|`Et'1>'O+t;UO9 W{J\%r˺~m )z܀%C5}9H3ONY|vWgD vT8^Uj@ l9, ~ )n2Ѥ=q48'UO폽Q)w&9eӹ a5|G4.\:j%q/ԡ^3uMV=H-v3|`Хv}ƨU!9l@Ir@!>Jr_8 /HDD1R*I>onԹԼ4s|ʹ S-vkE9d7 f;b_pN"7|{YO:oV)`KIbskiy:W) HfVTZV}|nT&|LSWu<'|P|x|^dP/ޗc󉿮m5B|]g ~9VTG >|`2 .iZM/M\7r:Q^ev!Bqg_oքBp]wnݾ}3 i]]Ƃ?I,pa1*؍S' &֏RH˗Nk؟l|Vlj)n3)7 7F՗.ZH^T~OnkH04n> ]$o&h*t_I>Ops1\|*~kαtF5iԺC>`)L2V`_Y7ѳ112{/"*.Sr[UO|@go )֔'@/:^5O?.g|%F6V;`_? 9J z\]6g=0|ࠡ]'+Y_0sy ^}'O|`!ǭP>;ܟjöj^)gPaI_ch}'єj5W񁏂h[ӡ^UHRT>`b#p+,j}\-Ƥho'r2>0hGc}Nnק]0Ir9C ֌CY'_# ~U~ӟ[,%bpl,u(Ȫ/h 6@aք wZw}ݧrtꂅHްFTʸ3RL )I3 ](5mc)!$s> x;9%2f| 4qY@kT"?|~}U$L>P0;uSb!+ET^>0se#Gƅ]RA>H $~|mR?'O7]?Оk/Л|gӒ [۟&W_Ezk/z:n{~ί{1xҺxG%w#h{wȀ=M!*Ϛדּbo8:OKN{үI~0)#ALkejxtkݜ/BL7&ԗ /nײsNkG EOTQxܦ5& X`=Lp3|`u{p@BWeo/n'b?X_@,x޺{Ʃ.ǐ?`GP'7npX_ Xn=!ݹ=ɒ taM6|fa wUd/ؗEf,90ru}6?;GXawN)$?y2*X=<&EzniT4xb|/?a.nNNluA˅+-&@IS%o` 64ys=|H$>*I4,ɩr9DA>`b2lPWM_I"BT.s:(B~z|y&>|oplA?aLS6+ t 'X'/` 4ht\CG nfa( w| OYM17|!zI%nT| Hw|`k HHW`l_3zP/H +ڿP{(xdgBY0*]v!IRV-[xTf5j |vO{C <u~`?;*}+Q}kcǯ(xaWpOȍ1Gc!;9/tw[xzGmo]6}y"W07G7*4M91ލ)Wa&;,~w @ LxX P⴮Kt9?cϋ'SԤ[9/' ?p}pYΓ ƅ.X`0+ UY1n@հb-Lf!CL2%ۂ3 S$o[wϑk7٭?p)Ym7.|@1FxRT3D~E p:Vp7~JR&0u > <7{){m*ֿ ?`T4u#®RA>!}7KC]蒠bwGbkh 's ͬKX?@O<6.|QU VwK6=?9:&4o\fb~*7K%gwe_":aHqs;tE&0D{w&g~qu1亱] ^ h$]1uOG$Ϫ/Y$j ȟ03 OҎHeTƃ'4ݓs$9tOXk񁖨̼\KZP˟PqؿRduh9Q}W>@*?`eƇn访9 p2o`~| B{*U 0@c}* >|%`/Pl*OaT&ȏڍh/h5MUOS%O ]Pֈ@n:UyP?w 7ϦwN\mF_OZu2㏙Nd#C%g Pm1u6¸IAEGlFimhkku~0b $hږw`T09#?<:Rsšc[?`bvg|<,K:Y%N9$_@ 3xY&/OU vNBj[b˗옝wo g:/P䷭ XI'՚ʛ?0W>`ID<>u^0NNv~7o'Ժ~|@Q>k?褾z2~wߐ.|tk=1`v(d*um"(<Dɩ2 BhiH_Z>0Dh'>jĔwOL:qzGk/nka\[ >&|^CO*$Wϥw :yNm'o{oԇWZÕןp֯w*\~ /,h!!K"U0ZÊlN3!Kf7S_*Wf􏜌kW-ɟY#<.EdMzՅˣFBᕌ- _87;.nOteߩ'H벭Qxa:`T@ jޘ;syTN/4pO?O%: kL9'DպsiAٺ{@7NYxmI_`82`YNqo`xX?$9Yei` |b.`7t?P>b|"qCJ72R|,Ƭr|׾2}Y{Y\<>S.WOmjۂ5w{*[׏Snm|]ʛ?P9{?vzoq3coRpRu0"b~ɽh>e'oGyfbpa*+SWh/O D7 0?$Q;ك0lw.>KSԣd*$H_p9 U)BJ `+NP!!ГQS|`_Dd?ЯR T~k=r| vh7Z~w9; <>S.WNfֶ́)e{Хz iss5O zz:ts|S6`SLD֋yʗ?p;SGI@n"K'g}E\Kxjqp0CBM3ԙT)fq$no1BN7 @Q%X|g}uf>humD6$e[jaZ5U G2([2V ӟ ڭӖY@<B(o%̾X׿z=<$˦7$cG4ӫ'h I)Nme/x.'h͗h[#gqz؟E꺏sFp{_qݿ:mVa\l_ll+J:@NeipN9@2#.谾p/\h3t,> l>`7mOEȌ2_S@L nȍ,->t<lrTS{:5(FY|`4F%O.@]8"Q| PizC mГJ5x3Y5ؚ͇#~q>Ьjn}@?A};+a=gVOHޗ,>h}T#BT؞POyDO (/D7A9 h|\8 HH gpp ,1>J07|С^5}y$;v=Hh>0w|诙;Ni5oo> ."_y7Ej`1&qOSغ{C C)|ᱡYvO:o(7n*; s\,>`!G3` em5O8ΰs7LuL>|O:Z7kJPF}A|FoDK >k>i=.\;Ȭ/x~ e/PT* _pɍ'> 2*O8sybJ9Qqjnȱ|㡝=pPcX߭NJ >5;k|չ#|>AB K?}WBOcY_i WI)bjFD59\R[Oq%T,n@W(*榌ҀzpQVػ%8m֊?-q,\rLxh0y#Y_c_Ӎj591 V/3 xt|-OhK >|ZICGϧ~ Lf/P!wԅ]n}嬙.J MO:? Y|'L„{Q ʗpH].?T H?!h W9jQ|%̳@E S|irՉ=QUġ1monv(xb|袰"3,ʛ?0&gl|}ViH!'0b>[>>ЈҺ >-͙ ^\-v>J;B2.?X2JS*<6.Q$06S/Zͪ* %o`uc/SV`y.@#q*k#Uwo'  ^K7L6pdؽ M7 '4;r;|i6bqw"R GO8Q |d7 N (H:@Єsf:!{'?r >`/T$t!hOt7$pwITaW>P;@zY3PQYږ<>S/9'Jj&ݐTdxwTӣ &@~+ӟЖ.aHCAy~C 颦s^P[Jj#\ 9W͟%evZSU\g|єUX\RDֶW~yt|fps>:9|w+.fn[/.|p  s:0koh uo81tPq(r㊎א3g(|-HZБ?a,=/n+9p9+X.|YC=cExW> r`U7au0&OL J_PL>PDZ7 il$V@*ZE@koX>D@i+ݿ/h +;fW<`]W2Kۖi`:WYDޕ/)#OҬV`*Zŕ#NM>(d +?*4.''O(WK&ܖ)Pʣ5!jfi/+|"HB (w@\R&4SprIǎt8"jcKLpC}_k`;D36IRW_qmm}s<=hbZʘTo/g;`W#uz_xjGp<&Eˣsdwj]@.BOhuk-¨!"[c⬼T[3 {l7\\( .4ppԿ -=`d7n@?M:'A'3`+??O訿!Ta;@`Kd$Kg\R9~.UgR># oB[@|8yޅ[%|`m3!+hr@@.>+@02@EF;d@|Iu7\Ӯ]U3xA>[jfNL?'O(kUIC+t~fE̟Z1;X3>CCP>>p߸)D@RM>aB}T0qMf12O̾tx;8 6vΐe_GFK@R*_""O֞#X e_`Dޏ_pyt\֙n\e~quo#c @K X ; g](Lsݹl/LsĘ. ƅf8'Lgպ|6 ⨳[N>PQYôXq4|`tidǽ'%!}Ite`2.81E&D槠7a[U>iU|`6Pp@R|C|@ RV4|% JƯ%@eZ vRaT,X?o"@~n4kQZX^}'O.T$Qe.I[xPCM6"/en>0`懃Hey *R|quښA9%/8J -12ϯ2{QI܍!v{(8`sT]jnlU[_>bI|)„Av+r7sPk._Ew@.?K}Ĩ8DY\ Fk8 P(:9K1d\?y2&sԿ`/PsπT#0P 7L@ϘjƱ`,tRl]Oπ~32~ p| Xw-Oy_F{Q~'|`/60(Y|y 2n)/{P|`oG@/2ՕSҶÃQd7\89af D.]~o9HUiԼ!()1:Ƞ.!s0=w?W·G''_;<+\>>ϳΩwH +hD0J8y17?СzDԅՉ '::x{dPXBKt]`Сys<8dD䖨M|ir:W# :I>)_Zd퍃˾":|WT}dV@)Bcb)WR(oui+>𤚳 %o^yd_^qwF[3I8?&WnꮿaJb0rD՗>X08@2uN@?r橄kq[.B (Iz ^Z|55d*tdZWDPg>P}|s> ?OdE}1qDs$5u׫my;>Hpm.f1R>>?ڪc,|@!*@\< ?'Oys92|ICMV]l\*ve '~+8x|ӧ\֟KWb?_GhȠ_AŤҼ>ι֧(7?!tOooC0냁 Y&>'4$$" Tߐq)hX3!()Ỏ%Q2vĕu;>~NiݾV(9dc̷oC6OܒrPoiXy+T` U'DwnGyjqpRП)mOΜ"'J)/3z4g eCׇja7 0uu.¦ xxlh6r*a`5ݦwj>0> TH͢B|`Ϭ/h\eأS 4LgM@4f@N63"H9.H)$K>ñ߀mOt\ E@Ԯ/UGK Feg?aM%˟pX'^œZ/C <BO*%k/$9- EړlfM+歌<4ۅ<2>G߯'(WEf=XuZ\ $*o<3CPt]'c/d$ԏގ~6|lDi '$.>:x{D@߰+>MO- .ş@o ~|љ2AS> nqpy}@fMWi1h,r<^__ ZZZ~mbdԂQ-4C. SFkbR9WHg`d#8a!ĕ:1cozBA>4>ӗwS֑[ē][` f}s]ӨcʇtN (,|``]_?g^0(P_0Hk{ն| h*ecg9لr7'<._ke>4V/pS_% }'\8)a; T}/JɵU!j|@@toBD-23K(;BWψ|`{LI\~?Ie#{k f~`6S(>v9/;4_a-ݗTJ)y>1E eZʏ }SvcӼ_D ^\Y_6^`pfƽW=>.nZ] Xv/I-\f 9 Ezc>P%Yo8%:m WNTA>0gb:~֘L7|@rFw{Z|߲0TYD If{wOۿ`?y"9zA!rOCAW>-`Js Ԍ?=w|@'ݿ`D(9,6N@b,S̗b6N?K͑H)|hu[,>H:H%.1BV렂| a[%@MG1TUfή? >'+O?Pzx+: X} jU9 52A[T* aHӔD:Ɔfkq@ yOY(AZ1%۟P{dWV_0g\L>@/T?!]{;p{Ӻ#Z%i#(`cԷCUodw9c^E;gmk|}&Wؗh[ۮxK{ yߓb?"ަtY[z1]aܠ}᰾`5Qv^X|`Swԥ\ܭ+ eπ|q3E+;נ'E,Ӻ*߶'P759u +{b|`{Ӷ֫KKr*'X74؝p`7&Y|@\ᡤ ؓbş00'Xw։< $^*yߺiW,I/x2X|R@|XuR/"ΊQdT$ؖQ_P}H?r?qTޮ/؞_[|`x% XպbKk}w}ej mB30$L]3QB}\{!#%~n$uQϼ0>uQ"tlDU&ƞ:./pkL]_ݘ@j\`gR >:ԫ><:η/1$?UTcB4]ݑո2*Kb6%xlB͸#f@L>ܡ}s/<#> ASV5N5[ugyׇ yC1ՋWu81ӨEX5.v4oZBq?p~PꝧaZ0Y C+\v3±I|)<>|@ߟuUg> HL<90 7vr,>?aRw҇"8"?/ٖ|Q}D2П &b.{jFBgN@<<欣 U&%tƞ$U62O*Ub>_|voB7f@,Vz$좐d2uya,z —*#> O]) vw7'Hpld=5'x~khK2W#IDATA.".#v> |yԙ1ڱ\R2ngMX ]YpN ,n|bNp[R+. 6[uD"H}rnwVY|JF@}zO g@KPeI+ٿYYd}+[W'OkUՊԄB:~* )[{W:(nتuPWh\ӿLJ>*LFpck\O6&ӎJOF'|v%"d|/\:T3տTolHR5\,Z2:D6[ Z#|fUqU_4!x<}N6;Kl׃Y_О`47>dԻq@-m>So:wEٱl7bd|l 7S_2WՃAΖ~>ÆG/ @pwĂ.}yfm1KZg:rK`/H/7!; g53.&W0;3,> &Ǐ> |Hy f[%JIe뫎̩(R|"{? /h1|iyrJx<Ǫ.Ǹ"҄ѝ e]B' /k}KBP~\q)D}o__jGsnYr j,gqw۴_i'HS| }gJGlQ6Uuto9~ݟ-ɩTҠڨVsGkp˟p<@!Dk}Y%HN<0'۟9 .gї']9 &:_`+TU0vD_|$Q/ww^jl|UWq'FbX@kק`UMnbK痭14zV[  E]408Ժ75bN>%`y_FNayv,>4%{OT ]Tu0&v޿R8:\X|XrߺN:&|@7˲,pbR&sU0$i2,>|"OQ(/?PJWh].Oz_[!ǩB^*]"lnוU}yr}~O${-ɯ|Bg. Uк][M+:j㩌Ʀv)50:63|cߍ~;|l>qLQ|kMQuU§:sIjL9 uϷ nRq#%zOx/9󪓍 < dqotOp? ?ۓ: @/b~߃miyq}?9PJMF  V0J3_| `3>uFZA;-n[*6Ƽ;sSITOcL1ը(-0"s8+ \󁩄1 =7'x5\r-v݅ܳ!se#C!| ׁhΧ,>R@D m8k!aiu[_|0wPe74&&';_ ttq4(78 ki>P%==[cʻAȊ7ܝTSR7S_j3Ϝ;!*͉,>5%u>pKO*! ?S|نаb J$APҡjoX K̟p[jGAnpϙՓ %9nu_`ksL][_yy[Ro8{| >%~| 4sVz~#E{/ #>ekZ2W|`с %,U ֪I(s]-U\>"h "7:NZ3c@@R$|v聤m=}cBGu70Z*&}$`)#؋@HS]ll$BCV}A\Q0E7Lڇ|,M@RY fg,[_2\̠#L Qh| 0^Y_puw]Yn|4J)|n| .͚ @7y?#ZDh |@LrCB T Dѓ/0[u/ 9g_R+? &O-.=4")` %'!i3jkIeN?ž=R6ƩHfT)c)4GS (f%ʗ>tIk1n[ 69|l­qY+;\LNh# Pd} ?#qNy@]`5w%5'x@ч)fr'B}c@n`.B~`ݙ߰(>-!(w`4*k68L>օ2ɏ L>۝K|OgxP&>_>YY 3zzY|lH^u^X7D3X >P׮n}imT<>Sʵ?/hҘG5>)RCuoҷNrQDH}A'3*C1j|W\Oa'0EY| `#|T ih3k E`:LF!RhY| bWл7a3l l6ج3 3O(>G9Tb.>07|`&2(:?D*_RA] ~/@|@Ej#up|R(!6X/H[;|luDڟp_._ke1| \_ 1{;3mLd^lz$RcSBBB1@B$m[xH/4HHCل$ЋM]m13Ue缾H-溯9}G[5oT5 TU"O+k**@tvTGWEf"k3O58 XO~Gq/ؚZm)@5 _ -D5gHֵ(7_pY'K5iIL|`xs$+iqY'.)ܦ$ eM] E2fab"Z{Yǁ qN+)~p:ZzqUmۺ ŀ+/tAQO-Jvz~[ [5Q[[si F'嚘ط+ơ+Rxvp.05))HMMM;f&d; ~rgC%p1mXY| .GKI.G+'sb@{$.nY>c`A h,Y3~[FYpX8!؇YUf /4?=$0LIH.4}>3h}gY{Q$l ĴU<6(tk50-j]@v`Xa "Cm0ۿ$j3x vT+Ҫ qD^qU cY XT h&|龽7*u+N|`$D/8||:=*j‹' 6C[3to*~8BM] e?-jc[?O~ҪKMKV78oM#\z*.VIަz4WRύ+\R:uqd󬞾/cH .u ^*~"?lLd"&ܓiA@YϬW]zi Mwl5( I2ݪTyYeD3IFl?3px R^Y4φO;sFknmwoÍG'S0yz^aK-;WL+T5_}>K _ EN>]1|2˩~@>0/h6s BGkk5օls/_nE~sϞ\Ӱь_vk<kknL9|n*Xj_bX"$Z:EoDjF?`lZyݼAUZ{x=~]q[Qc PR-g I}gi#ijJu|3/h͓GR. L>iw9WTz RD}|n;@E³:>,'WstԿxEޟZg  MD20K>|4P洉?a~KǴ4* `U Hws)?!!Ljb &|z6'gp^ܐj"D'iyg-e~Im`垚꾩☋ }~O^a%-.`skPPS FҸ~[x^clʈt':76ҲV'!팦ihOCF7Xڙ3*5.&W5i>uRa.m%] Ԭ]Ѻqͳp't^Gb34?+u(Hw?n䦹OpQ`+OnK =~ "T Vݸ"ҮF;DQ*~>:Yr|Fgعx iFp |llv-$9@j5_;6jIe߀p 0~Br'*=԰ h ǸG!P1>_>j>Vyɬ(_IՀ`ti>V~?$KvTknhӪ`,>i!|2YgiOV:T7 Ag7`Iʈ>G&}Iҳ&M(,ΜXcФc~AXs3|ĴB 7;p6G'3ș[uKF17_79{Jb4IseL@}ؿ> F]$#<,|$MV'6n\@I0̝!^GH8iqͱ6뿵`yq| pZj+,t5' 8.jT 6m м! @vh`قO#|x2\=|C|ÿ]QIy:>Po`J  ]+|`>4@o9f0PC7V h^?ނ>n$w-TN?ГSۡWstԿxE=_p"0+3 dbe\Nj z+/z7I~AW^qi(he w@1؟^o֥&L/k{\l>Ь~x-1-A}o&dӜ%;SbaSV?y5õk#\+xH vdTЗHv~n jj\;GL{^~83?siG a.Zؼ_AO%M~A6sX@mhZ:#¶r 󁍓Ӈ=.6c@w Oe}>Ѝ5#Z|>n$gK8>l>h*şK/]I> F+[xV-uH AzF{xlAoO|R,\Ҹ/ ßɖ )C\jlSk:Ud+Ս#0+_-6oHh J|7\êH  g3 L?@d vD:>@`=ܨN>P#j A?h,jzm>Ѝ׳[T>pNT@/g@H8(3%V7y)0~f`J`\:ȦYKl%]'c|,dd!Nc>Url> PyALo^~=__0{z0䤹v #2?oy gEjAnǜt6aۭ.}>tTyE|VdNAgdWoMJOҗ[eȜWud|+Y~ԕ7f c<1Dy#&'Qٳ/?Z|Jl8akY_ ܾX6Pö.cwP$%%u 555W)t' +cn~@s 'J8ٌ@|Vw|Hg o@l9{F\|E}| :+3$b%ŵ6/%>19Hu7`x<$~=>@!梡FlLa(0l-4Y$0cxlKJgA;O;H#@|t-/Wu5:>()1)o3G`0P]|.`t؎gTqItvTGWEu pd6^MO$f}, 0^\Ȧ4ׂ$yɸIgA;jTwsx=q^>}AUa0q@_ Q~,򛺋/Ȇ|i?-3 zv 7, r%A};R2őA_ c͓~ngִ-Mi-@ TX 6dW e3 9)i7fsWU!5p2)?)l#^4~_K?``={bXU ?G97~?|@>1,Ph9';k:@?D׼y L;;l:^ż;+׹I~na)6B2sc0/Liي_lMK &l ʻS@d Bi]PPn*I.>m>@ qo`u!XB)z~Q5`x>PD Km܂DQXi9j~6<ق| z6WD;(u>to/>p<u0gjv/8|t:ڧ%(0#,X' Sjqɑ(~:PnmI?@d?p!nHLV_oP@ XL7'7%0vrĊd@wo-UȂ^>p_A|`DtkvI>)}*i gY-U9;];mˆb~VaHׯmO&mq? 6anm`T!sFXg,+3} O u\!Oз᫩'ӟ<@"vNvQ ࠏQ¾`r>՚ds]0NIecU}{3 j~ǯA`ϯ*0>d0~@'t#z߬ Ʈ, <@a[|\6\ĺX +l2| g]|\>=6̏j0&[B'/8bC Ԩ7q%=$: jTlRPs (!9(n1 h0f57$|$a[Bo,9N?`мnY>0b]'!AV8h(}hb@pN E?pJh|:WGDK5` >|FS6F~#35@QMVaD;:'j#1u[}O#6 #4'd^*,)Tnub ; ƶ}_ט*//#|@-ץnhKfmܧ:rA7}S1WTS?p>3%0E{r~4GT xϫNr'hŽoj7W TV¤V;az[aOO8ҭ= ZM6ͻA^{lK{F@w^yThZe?Tܙ7I)u-4ƹܖn oF~`B 9/'plsPt5lnr-{ZM ǜ?jrre= !èF`j ?5wT 6R>V)k>Zro4OK5B;ҊQsn.{k\[5o&ߐ2v ķB@oA]ǃ҃юoDPxQ׷:r:<'E~ `û3Zɹ~nZx0Ɉ1͕-Pʓ /U-c6ߙ>XV5_PMaI!F J1ɯ6_R:ظp/D2:_ nW֫~$gJX{Vrp\QO/# e/&T>>|!1x+ qژ~d>͛i\4X@v+0ѫ|`KT_oMJ0\ \Ѐt޺0ƈTNb%9W⓪큮P^Ux5gY~Gb'$XN/H/o|'=8J&}?0վo82ODq%{5><~I096R*P|>0Icu @$G@>[?Pkwcn>S a!A7ZOТ7F'h݈# O<| /]Uy*p47ɖF784| R 2ab@tOT- ׶Z@DW^qC%ޗټE]Xn̏ s|ڼSA%:@Guu *4pb]6~rMu^ ">v@ZjzJ%[TxU X0!6/0T- ,nuи4KOJsdwٽ)>: N%yO_*?วFtU`xW{ maV_8`[gŁW#i\6(j .\޴T'kǹh7I)]-Ta\F*gn%  =29q:E93FZ"Qb~/M6@WnW(|=58> w\NN7z r\\Ɍ+qi۠<ȳ`W\T%+a.ΰ%6'Uwbs^]M.]ѹ\F'c4)XB^0 oCG-)[Qo/ ҭ|CSո~N߀Wd+B Ma S`-Y&xt`Xtf~4rp?`&ORcO ֬#9cB|g X6/W*a_%ϒ}@9RB|%lF,$6otΓ~2#':{߳ 1h~> 1Җ{Z@|dOtN|ڙdu{JIQSsGޜPlMw-9ނ>hWõ:ア'\3>!sk,  2Q*;/pl ܕo{\Uvo=E6C?p??@&!̫`g\q-?8¡ qTkxG͘~j`lG{dQO3dvQHׯ7&z5LV /(ܞS{"l˫PK֚ؒ݃W 8 NBqElː px/mkyƌIPɔ @: M}6p$R8v&Wsx\oQNFʹ(lIs-j lۻ9bc2,9%}PW p>@|@l=6o.:߹!>pq:<:>kaq6, T*}WЛ|'n ɟj삂eP >5HI4Hq, ^3y=q>@ujrh>#@S7n$8 ![(ntl|UZkD0P L>lFG:>M>Q6@N|D}Ԇ j$语mz\|b+*=}%}kn|X!<,>0ܥyO@討|agLL`h"54P=`Fa dߦa:n `@Hhؒ?! =Rghx#UOšμѿJ<I\Q)/VD1ͽfK]xbb$RcKVo}E}o{U,볜|h]wIL+{ja7"WipD`ٖ.ٗ=O-Y:ԥ>g ɁGa ؜znK{) 1=j9 7 Ja: 39a >Z|;f(vM|~4 ޝ]8@+ r+Vy$nr:2E=,W2VHds}݃Y6psbSk{4x$XKm~5bg{H: W PpԪ0hT0OZ^I1_Y~B1@8;~X l%yRR'P|/m)#u x <ޮ'zdLQ s1 ~ȴxlDU4|zL|eѳl*G>l戀h7 4ҽxۅ3 c'"OTIJmހB0l.(8ЃGGЪO84Aڇ4W&xwU<n( QQQk<ذSuw;]9>>%>1heA`ߵ:4ϴdN5:Qu$6?pM+t2m `@7u~LJsY\o: ==F9h2yO7 rEu5]OΟ&VR=f7&z5\Vy)M/ r&(I3[a%Nܝnj['ɓ| -ekt"lN8 JIt'\bLMFe|:%!vg:`71#G}a),藪u󸟧/\Hx?"f *\qVP @Ήs2vsFX||4,9œL]ctjk p0 _Kd+BWgS1_#|6àq0N;9^"hqۀP/@@x䠥șJ|VɎ k_>RX#98|@e |XWy|"| ,@T9м~@1E}in"0ȣ~`ī9:_b/&p )@c ZjC޹ ݋6tŖ tL:KMGnTF CX~?aiМ/ -Gˆ{̅ [Cd꬈+!||Tc`\pOFvM{\Rz?m># N^qZ^>X֞C?|AF/BJ]'2*TmM&\| a@1`wYm#inךq1}68/, 8Z7_ǫ9<>۰@7N]cG 'ݵ;_|VǀЃ7-M@<fc\ k%_25_gn090 @邻rm@5w_X|@-0x)dT>ޜ'A|SY|wivÛd3@J w6/=|+\!w%EP \']M1 gA6xׂU`%h~S0[P}N#8Z?|`K~Ftb ׬QVgYv8討1g>]&Y^A\Fv&E~-ŏJؖ\?pfzB¤~.>T'`"߈ey;HY]Α:@Ph.y=-&(8B촟+cG85Sj>pY !0&}:}|IqHׯR=p/a9igU:)?cH.~AZ)>eSF@I.p~x؇Yoz @?=d0eR?<^`Iw7~@R#C|p%C%g?p> +ݜhPU4?`l/g#B| F"(fa."$RTậ )LΊ\0@IuA?o #=0cg ^P| hJJRwؿp;@&pw Bx!>"[y`f!\?rT%l>@I : '#h~E6XTpMrPm|rE +̻)/H+Fkl?ap7]QIx=@Vt|VT'g.&N_! 7 o`Σɔ8YG3|ATokc}%›Ta2|bdË k|anA8g75~6S{8? &!~?2ˡ8 ߉T?`=N]szD?P' {͢( rgDlPhtmkTϘnN?p** ?> 0 /Lp2حM@'C] u`C~{hr_p:]P;^ZV[s. 9qc`p,=a:xik `0p/T܁z$Rr2*] z%n f@68{a` 3Q`b-f B0.]8?Yy`"J>#Jlo=30|౫SJ|k8 z7.~@L!Z lC?V k| = 7)>:ڡ:8Cgg8`Xo$0BZU^Syc7oN\ @p/GDH`>\o>WP+5R)j|ny64OhX gl}_:1pOa}%}'/e9?PJ|0Yhd Y`F_rਏ[7$i"/I"~"|A=>pϭ[xNJ<@ N-vss|:>@Ԑ@i{4^sΫ/'| c> ]p6PfHPY7_O> n;*t-EG\3 ÚF 8LY,KKrl|I'a2F62aPr1@>[tN@)ʱUvUg03@0:q~T@!(v#}ɤB:1󁷁GQϚ$T" "8ŏ~>$i|@ `;>Ѕk´b}D}Tj [kn&I'z .-S~A@GuT{U+< dO&`5AF@I ޜdK+[q̑ +ZqaQ3.ښ :4@ k*=UIe1Rzk:Q2-}/n@'D_G}%3B?OFoQ8R1>ܞori|4ϲAlsaۭb_I|<-)6UOʑ`,(D *Lo<`8 .ɭ\y ˊk qܣ7\Q=_ЇWQ؜ZC0mt2EcHpx$j 3 s @ 7Ɓ` }Nz0@T_+ ƅs R0Il:s=sN&@: >{{J e 78S@ 1hď@9} (>629=bA7p`؋[p3JY?p @ `yq<и%@C DKC r\Mh7.߰]/PM@dIܪT|?XP-VyEoOtw:A(tVQ8|cW %(m{~TE$v/s xegj/Q_҂?!OX~1VnX~iG( :cϲm蹱F=+<S~ۧ۳ }-a0 J^ l>pI "-lϐY>Ԟn?[ie%YWsv*6/_0p?p.џtEIDd ]OŅZz'ܚếOx6SCSķt!o 9 @Nx@ς_9;8 ]l}(y6je~AX3`>A  :ҭg f?j8C@p@p ttM 8|V+o=aQBpxTP|.|pwA/PcY_plbߙL*S?J>P`?Axn4'0'Id0;7/"}R;7C5hB||ЯҎLxOC~|bh5j&<z tXQBfLsU TQ|cg߆PlZY0~[4nY 誊]׿U h.OHQ 8e6#S5DۼnA~`c&%)>ßva]w%; ʂ\I5T?n41@N?P;2pw -NjOcؘ~d7p{;U:)?oHw }/]2 6-75r&'LwQ\VW.1U鋬`ԗos^V 1F ^D]?y+5_p.k}}b ixSB ~ :C6&GRD}Wn|O?[ݐC2tp5Mʂ_k<>x` 7c+BIʬׯp>B^ D4AEr  G^s )4 3P~i * Cqq`8!|CDylPN881'<:e8]pD1'8,>g4X|4׀h ! ɼwcןLCyџoi;|ڃU:va|::VTf ׽@7!e #WBp-t>>ڈjUډ K?aS=SD.u(U*)Q4>b@swzF_ނ6gt~#v pߝSՔ:~ 2UwˆD>(Z$4ßp׌]T&͋0ڐpCDo(O(;`^U*qC93F+׍xBx5e%|6Mt-a rވWs7L[D.紫q>p*P-Q1|0I>"#m-ISbыń>q0A0>k~AXY f  )+aykP:>0}a 5$m1ԣ~^xJBu|~Ì881PtN?Wqp8!TcA>`X|@,V>Nba&1񣫞>K@LCmi~ ?Ϡ..[e}u'&%BA:ア'$L(i/AܭVT%`H☄&@!,c]x o_7<䎖&3rOq1KNAYd~I?p:x kFmOA qv*W8G`rٖ. AF}Jb;W|+ͳl>+E:_)ݼF'g5X|YC1_~=6_g>fgMuc.7Ai‚ݡ='r+ \ON]ؒZljO/Ơ|umO~z}E}(]iOO->P>VVxVkN |$}A }@}`)6)M7̘DAL>p;PI_Eh:V<7l p6j(C+^{k3<3 3C)8@(5JN, `|H?30/` .EZ"k L@|om(/P E?mhuPXPJOWta':@GuT;TT_NkgDd@PGh#$4w\s)~"jc['43 *LLM5M2h$!²y5EMhlJw1_p^1e*;pa3 n.cAwGG|@g/X}`\HӤ*!/ vA.@< \&a ؒ&0ȥ?F r2nIߥ674DZ8r+=_p Zhp{X`ӟ0:WG:mO,0@d -l>PGJ3{@З6ijˆ A7PЭBsÕR:h|@t1@t*!pNx EJ@ V>@k߶`)<\VZ7_`*W= ts N?!VPWÌ&DI?5:ks{f@R{O \OؿL᎙{Amx7oTJ@zo;6/O:cE?_ar *9}}`c+;3~[4nZ( }C ^+Y_ TѼ?e Vn!7U9[}+,F5[).6:kۍm5['7^=r0_=.oFN>7HZeUXY:HVp1z R~:(ksXR}ToH%`67؜1T Q?6s :(M{˜#˰ h<f~|oZo`DbE~S? 8_%O?r9 eBBԮtOex4Uįj\A4ξB|@bCG2y6_0 @"D0$Y6 [84 ʋtkvEʁi:_S1 h|]>0T-MTx#F)` 5drˎxsC|AssXOt8p 3'쨎jz$܋uH c  T.wO!ݵCH tP-c67R=ӓEB(H['Г>4_1ͽfK] ~L;R)aO>3 { E̞x*2>H~yӹ'E,,Xӵ)~!p{>$,U3~KDҸ~m^1H֞3S4vsN*.Xbsxs`}S32Hݤ q1c}_W lt+x:cԗނ4]+=DcP=_ژ ljz+XQ,@[lS>Q|`٥vsB u|eo@c$YIf"17 09*&Ato\5`V|"DrȽ&u>0[,|N#Wx|/` WՁv}wЎiŨ) v'tş>$K`۳}q2_gc@?aGuT{TTGf#X{QP5 |AYn|9Z$S'ɒqTu H'h@ Ze"kdbdË k$X?ѽf[]J|\R7mX{(p>`Bwc8?`amDQJ, C.# #>D2+iZ?weQ⤙64U[z`jǞ//+=`['%L(C8_`~/M|AQž/sO_՟/MsosmEcț]B pQ` m7_'1@'|>̔$ PtYʯ(WI.`&ϧpzi[[I"dR:-ԩ,&7 Nv r/h/R6|=7#) x(3QWuaQxЈo_Dg3| K.dYNIj8j$Q}l>"#ş0|[-Y>$Xh %;[P[kƪE>Pcm>Wt@va`W?aGuT{T{n % 2q77 %SD}4"',U*~pI˲fd /vB֡r4_pA'!>@~ި`Vzl;\1_1's ߋwٵe7 rE~pO-,h)?Cu͠k.E2fI,'!fTESpSwvYg8^j`b`m7S=c/8._]B| %%]8E ڊ<\[s=c עdp 1hjP$+X|Nf;E[]o6/GB=xBy}A<С/h`H߁aj^?Y7`Jxq *"'Ubس# :Xs `2 $ w"L 3B( rUD؊sE,>cv'ϼBYp?b`Oܜ^Q?vī9:_:(Qx<6)Vgu=qfG$ml$*Ч?.vE@o/hB?P #0Td5fFr˨LUi4pظ+~`}^ >="賓\~\{i֔{ѵsl WrGW0UJkK888 =OƪX^>@Ҟ ]3 Ӝ4oX+DLjښӕW,>p4(<]{N'|Q.e Hwߘ?ue%=椻gܾ'!$~lmgu'지?pB('E;?xC[- Y6]]>_HN /]9͓EJl 8al>@<15|&&E @%.Be8A",7aA\nOrjREQBx|@L`䦊li6 A1 @gA ]@̺ B^aLAxgmzT+ǃ|K?EW R`/x/uxxKI91FRBS:>ĵ|<| E2FnJiM?YP1>|v=԰ G?:ڧ'B=)cđ_,H _`]O~@$쇑 *85A'Y ]8 W /mrI-;WPT(4aIwhryn(ױ' '/fM'2>G=a~'"'GA_vW{"/p|ǭ\4ꇲ z| `sYyN/❱6EEue.߰Oݔ# //wP {Y;Qi֦yn#{EK?_ K~4ȭWs'#~ { r]m³An_[֜@W)>@D~E#$oq\bBp}LXvy^9 Ca_@m>P7_,j1[FZ: ^"uPq 2.L->@P^pDxfl5/`k.".(.\"*YSDXO t l,(.2@RX0 @@oCR#c`c2|D<7Fo `K!z7>}OxWa|Je Df NYB218B6!9 0_0T }v/ux~O>a_O:cEu pb:zgp CM}OD׼$"Elٟ%TlU~Ԅ)}mM/Q\>|FTz c'M_җԛ/8vM9rfg> >T /('LCγXYSsDs!]/8v͚<XnP'^qz=HI}'<v.Lwnj/@L.E1^g/g@ wِdۦs I AS?`mNqUv9@n!>=c p{ۂ́& Xٚ4[/?@uH4_w\FN)Ss}q5B ^́>Q?J<`<0e.B@ߠۨ/'Z@#zB? ՍhT `F O]eԔ4գI>y0 |9 |mVB{LYdd@gЏX6/yv~,3oOdWS 7T(t@Y`8vϜe>Gc5W xGiK #[4sC]_P u49D)N ‹ș0iV;߰ImKӟs}M] {&8F|`>K@a|ǻ]5p0>mcIᾢ>v>y,>Ps[ڲ9TYZy.b[|"4_SN]ԉ, ք}5sk `k`Y8( GI.Y ӠH X20E5 |(8Q\éZ_bdĨRA0 `0 I OP$$*x|ANi8 `8\Tгa|]9aбP0 ^ 7N([h"\tݻZBr -#e?"z\c~} + Ak kOttTGCEO dK1Sn4Wv~KGGoxQyu9?"bucAU|e Erikz-pb Y˹M|4vsA3X%/)x{Ok2[Y碌o,jE?p 6_ : p+>gww,,Ws{ў/%V~ChCV\4 BpUFK||:\Uf|t͢AF'w䴸ՙ7tq$|`*D/l)H3}EiH SJ:+ Q e0|@rc#y1 HŖ/A/ej WW,|`>L7a4.MzS;ϲp _~3)cUS09&>' -Fa4x.ib'p*L@vkAnѱ^uah"C, UW7|S#~`+%VK~ڦ|c~El@vtTGWEu ,V{:6Lt_ e:Ho󐝨^"_4 RofzB¤~6EԇԿjEx Hu0ڣ |H0m|x0Ym^|b+!|t=Z-!{ //'b>}',0lO|A=1}&7S=KssVs|`D!TS;bmKJ\V^i oN!V$Z|K45l+/8+o?@ ~r[ZdnovaXrAa|M $x7+g}/TRLޛh[?(*Җ\9?"ϥQ?a@h:MpMYLC٪ϓI/lGP؏J lGVpxJL>U|3 l0xZ_J:%9C$m2ԛ:,*2`r*?=ZI?#|tsST|`+!"n u_}\,>= W`rCֱ֟lq+;a @M#MDe FWt[+u]JteVƱx˂1M45p` )_.\C *!iv7t>Q*CUƹ86ՓkJAixuqYHkY?pNԨÃ{[9_МR*i"߰Kco_>p&VD 9oCvpg l3@gЏg1xoOb/?8@$o4i8䵾 7ySF|`뤄\% K' @:u-,>p-|c{_߶ SdvSdQ?wzR]C #4_ |r$r>p tp]hq^G@fp yU ig~!tPs1SVu 4 ,\f E SM=ϩx鈭< "S("W,XMi:@vï&_IAX w  P>, +\ba+!H5^ch Ey: (Y\S#+ePg~r A2iP:f MC'B  A`H?fTi{Ѐr[b q 㛠86`hkt B#8ڟF]*%W=ЄiE|_\Z>&|A?a|AGuu PpG+T~S6U/`vQ{-enȻ O"'ܞ& y?p.oJ`Z|IrqoQ?\gܷ^qz3ճtK}NtWI>5M~n5HeUks8[?Oҧ[{`sFBP)]Iq1}vAiÅa{ +_G?~u~Ot- O7|ķ\`t {M@Fdz;PC3jf361u?@`V9(AYA6BlTH X l.NA6X9>C,Y69xGl1nJ1U^;c^L/&P0I8ju5a* a+5wu6 Ǻ S&R웁$Y|[0 7R̫Ia|!tshsp Ba|xh i7>PcX{0>Qu+j>_̑)cCl>`E7v{~4W}%mlK35:˾-^BS~h &rqJޞ^=ʭ.|óAj"Ų^TedA0@?_[*4N=`aH޲(A v,Z>a\b R{OUVgPI}Vr*ݴ~ M~n^ ǵf"g|~צ4ӍӇ=\[!rgHY-qs&8~a7Bl>g~~۟85$lδQ}NOh ٜZZ@'!Ҷ $C^6 i4 Z*{ ?8@QDJ >1f 7AŏLwO؞ Az p<`AEPhZ1jJ-d)$_-_t`AhW_g=o9_ޚ bM{JA*1|AJ4O/討j|yJ3 !C$$1(3? x7O#'T hTP߶4O7$(|%U|[%5{Z5#R'( rG/NuTP!@6{FWjX܋gQ?p<~`%GN>p.d2i(B_Nq pgLۀ|!~Ԟlؘ~d]$M- ']~~?^Tb*홞] g`ab%.WNp2׊s ڗ~yʲb\ ?#j8K}xe}7'u bhtƚ/-CޜZ@'~img.{XA|r׮2#}ڍx|8lDH| đ|53S/~ET}P@3lIV9, /92[>& X"8xB6t\ml kp>قq?|`%T, 5s 촵BOTSd ~X(4/,l`sf 1@3Ԝ/0˚/FԒ-x[1AÇl~scxLt&p96)@dnPjzK*zR$c; q!dΓ\ f|1pպȻ pn]k Ad ,;]=qFa4IdO!o:ڧb/2"e. α7'S]xI%BA+S>qQ.`)@n02|k*=UÄskD wKȖ.޽!*m7_RIvA+ @?Wg`%;~'R qT5>.L?+pW| ̟ЀD{rqYզtEo~, 0չMAhNYe"N9,(dl@IҬ?!#fw"TnD$M&~Po_6#tb@ⵀiw% g!p]j”*Aլ|C01+ =E|`c{0W~qA厕4'-3{8]X~|o])yLv&kH3QU ; Y"8@1?}lIqlK3e˛|f|X"ߺ˺7L>S3747_`x镦4],>@v1@~`Iw}0 p}Du͎(ZC7]x=^zķ\ 0 ק9 9/psnnW5Q h%\|'$x<]?WDZ?@)H]|t%*lE󘙽}B bpȲ6##y%I?,ǰjm@}Lxo\=0>#/:a;ٌ#d el 4xgH{ ?ulw``9Bp lds_l 8a| ^B&k1v`ؾZZҝ7&P |+x#`u3s{ P( r_4 L7Y?قd+Jr!>p>3S:C0e~n~?ò6+'#a )18qCnvhVk]4Mu^Hß:+j>p4,EH2 0/ zNad0-l71~K4nj ڙ u,o_^7/p6+D3Ǽ#^ȆTyĄpǮ$#ͳ{r6Ռ%6g, @&'EӬ y ~ݾ#y_&7tsLܢr/(g cܐ^1HԞ .(ܞ/ؔzn^stG`ao0ɢ>I>9#!c3ܷ bK$Qu LBZ4WvOg9mOX4O`y0DX=ZjFD zS&gJZܵ#\@FkE4qT9(`hб"t  ;D",f;6 b,tna E|Q6@.Yv ,j9iag;S_c J]m>Pk4/_$;`3NW_pM9}} zn K lS?@?|A6;犂{*R ]W/r3SZ弁>p4Ŭx=I}!bMi^Aj~"kxgß r]mU,aKhx uJxe%ǃu{ Ot--|t+i ‡}/d< 6/IX|'@@Yz' Pdڝg|F7&k5fٟk{@$*S`ߌ))g,@tEȟ!' (69%FHG->H1 V>@A0*r\̋~J>@ f!t/h7eyLu| 1KAkԝ/ђ+h{ z:\1 * E̳ "`aYܳeAaosp A;M:rKBɭ8[ Pi< g?PC 6z>@V [ 40j<hfOX8~|ŨKAwU:8 A@ڟ9_0/eX@vUI ]膛y1Ulⵀ&''d#%%evw?WQUlj%CRi#tƸ6)iIK Z< ׌O$kb7rK1c"^@c~J%\fwW^"Kԇ Ҭ.y@Ye*)N>p>CX7d Iu&=8j$;ieC$Y`׌ Otn5H]=r*H%9F@[ @C}#3 >_g'P8XV[s*`$'2v =ß/]ǥW!B`a%3{l-3kм =6@6+/6}b@RȾj0> ų xw߳?MIϏv(,a;1L,{> Џ["0T9<*Ju@OgDžY V}k[`?d?ĩUCx@Kو+>OJb@AV44 m$ 꽠ٍ;@GdB>&qcS?@@JOBwn]>8^ xgkOJ-- _z`]j”dA[҈?!g /)5&>tAMIS=7.s\ r+tQ~>}mjL;{!>|CA?_PND hL?PJԼ=/#yˊ&7V%? {& 2p6^?,QHE]ks.tӼf >/x]'}`Q+Xk)Vи>?5 (_P 7gAn߼6/X٠9_C0 v'Ļ] 6 tZ lfsx$y.ip 3ֱ, $QDohn, Y3/eCf0>V| Klns3ؠ 0>|-_@;l.e-`WJhZH.!`"kI` H<2K-~yEx4V <0u%Pʫ݈O@Kg0a l%ejtk{lџeGg< `W' 6S'0| >$قY?j֯7m?ᬃ8ų_!bf>Q*cS-lpܡ|C(ɻwm,`$؏R$}Z *u|T^BMWLV|`Ɲ]RQpG4ٰn")[.јӼ [ ߉L? =r5/ +V|[V)Tn5%}ݣ470Fg4fd9gK*wWsN>5H9E5%%W.v~A/AT~][#-˩7E5Ea{j_ f /N۵bo_R_? 1rTi4?8_!BOocsH~ G(!4E-}JH@$*1D!TL>h G"'t$PKK >@8iKseTe T.Jpͺi霴otϭ`*6`/?@@ <`YS"p#,NOR?aL[s x Y[cN>:ysu뇢3/sE0|@us*\Uh .M+F=_JB@0I= {M ßǨo?!و+օ" VT%TiEq'ds ٫wkLX[Oq[Q=|6 f >hoZڂAa _#?UeTYXt?W,t'@Iɀ)@.hݛ;hKh+> ؘvSӾ>UU~pI. =$|f@j"b ᑘ JupG]ae wJ d@?wr1٬dQG~7^E%D5@213=\PipI?3kZ|={polZ7&z5DRw[|l90v% 47]~n^AXW?c\i3 惻) +Arǽѝ4Uϧ&tKe~iC =/Wsx׵S@96(SO"O/ 1h|@.g#BP\Gނ>v.f_[k*{_ոfSmN ' }`D%tsa,oVjcIԾn̑9$7JC|L" 0 *ֲHive ' 0rlCuup!]^FOR v.b@?9XA>$v ލ3( H6'jӨ?aY5[)Y2( [{Qh ߚ%ENQ59UxBwsglw|o?X<#pX1xM>x/ LY;2=;0:OLzlz}>p Q <` rm>PFmOh ~se>HpN៙ڊL1▏Q}ig3DlH#_G Ȏzs>_nD$쇽E&D_Pq'+hkz52_>*`[]p>P{3i[ɲv]7Kd3|qbwc^pOD:Q8g~y˻gr`j|)zV6Lt kOˑ3O˚85žT񶚺otl>L !]m#6w47I^ٚ/8  2 GVy<k'dܾ', C  ܮV\v~\4 r l>3(v{|~R綴esG5+pmpxht5{z>6,js`^#+m`Tc~ɲH!=_`խ{BzTK_5[s?9_X9 8`h rQd \n4gpSs $$6i`3b^k|L'z7?]b/ 9+QA! PvgZ}$cddj uSWhx${<_ }@+ j؂K!Uk: ^lf/a3pNG +I('$91p>d ct]hyyq9 UfoY{ݞz ZvTG]:ҧSIENDB`Carla-2.1/resources/bitmaps/dial_11d.png000066400000000000000000000011231364475620200201410ustar00rootroot00000000000000PNG  IHDR s pHYs  IDATH?KQG{f 9,6AYRX$YTR-1`&`a\R%DBd-ݹ)FfI_30\CXUf2v/-oҾ%;s>D> GoM< |; ܼhM>FNP<?Q* }և .HJr ** eQQy 숊m n=x9/*rJRT֯[J%Qiqth-iХVꢲUQc7V`jMX[SZALآ5cIp83f~ޟ+jh {VP?-gn6` 1`mDi,hY0`Ff.&-FVAU)k.vuy}ǾnP'|26'URy-䅂]F'~VkI,߻q- *9' ߩx͉e ? Jtajŵǰ^lʓ7 %ճfNKNW+1w$UIdHP M6'7|^S=,⯎hw3akqtu6y,Pm|gROT6r&*`nY//$X!~1Pf7x'_!7:[kQeˡ ;l~GCTf!U &J9YE+|Ö\ՐbaP#)~Ai q4w 2BX!xU(勤t -7KmcoB"#9mڟdnwZpbLyca[j|Gd`*zR\Pp(s4FYMC~'2/KOZ<}4-flq="v :sϔ͞'saUG\NV?CF%B.U2)/X՟ϻ{O8f9YsFtEFp;,ICQN4!|U(#qыoZ*:NPش%xd8 ?1N[&GJr=52MtyZ=_8 'a5IENDB`Carla-2.1/resources/bitmaps/dial_12.png000066400000000000000000002147331364475620200200130ustar00rootroot00000000000000PNG  IHDR  : pHYs  tIME $m9IDATx{|e$mRZΊAEų뺻V0˪, o]AawUSZʩx9M!#3I0wǣt2ܓL~z]q,c )Ϸ9Bl9t-/|?yy$h=@gpܳTotZ} @v;QPpa0Z*ˮ֚4th.r eݭ55k5wZXg*O*>K>rP}!Al % {* ֚q;`-,|({$w4a_,P $pt'*]g|Df7WP Oy5G,!d`kW'2K6YPYIT!*99M%inUYN ( i<P?/xʚ[SSC^QАG$>((Oi}szY @#(}t{w|RD+or/l0.d4;r ϿG$=\ptIjF0 >`|M>0n S"sT0(X[ 2 *))EV !Q{UR"iY7(r:o ~+^;(r:AE@,?[UVIq+0!#;GQY+/nT~h@ڢo]*i.ӯ>6Dw"_ss/}t>h %q<,r K~%Xa_ɕǗmN}!~%%qF; >`|0@w)ӋV#嵽V FC?3L˰4"FK{a ^ wKUY7zZ+*QQ|aί,-!D@Eٶ **w.z\>0bΜ555un1,ѣރ=J[j8~^qW\f -V#~ s?+xOlwvפ8t6_mkJM>[ӉI|#b >`|X^~FJ@qEEV9lex D@5jjj`d؜q=X^ޗl*IÞ>E%٪u| 8Sw(MBV+t8zm|hժ"SpU]pw|dNrB&$c;G$>H8P\Roo^yNj5 <Ȳ{9J#id$?"Y=@;CXlvp0ˆ |0 >=5g9K$ݫ|pś>F<i` [s=ˆ} $/9@ȲD$@ѪUkjjpV# YC|DL|>Ptxİw B^'ݕHꮢ6-m}„ۨ$GXV} ?_tF翵Nj>;GUTWnjlZaC~9d5 hbSӝ*\a@;C8 ۅzaD >`|~a>PfP*IPI%C'X@iN o',kԞP?L%ib*IV龻9⋧g}I5JcG GT>}yάѣ`Ŗ|>;{ptׯ!z ߯|%0ˆ |0 >->PtI (r:'bj܎DB;P)!VI>;Q>apֺJJzz\>P\Qm{@9.'_e- мғ dw]%% %5GD@Ygmw5eRIڭàMᣝӧ'b%s]BJ,3۝e/;VQ-Z|Ylܹd7PQ ಳ:^pP_*`#0 >`|/n>0n o_JK(w@qEE)t ^ENx%T/` k Nz~Iq=):ツaVe?[rƏvܹgـG|q~̻|kaaof.Uee?va5"r /|v'&^o˂˗|MOTo}d5 ;vZ,vLX[el\R[G tG/0/}şF0 >`|| tz(P"Pz=Lh@5\ Jx|D%"3x_QI:C{|@T>6x0_{_(PG|BVLp#ygsQlZl1a\S+",0^ |Ϸ1lgCei9|̆Ոܕ&Κ92(gu[&{WlK >|0 >X^>ՠj*I|x͚\~@aW$ &L%K.I0`"˨$wKXԩ5| 3a0*A< `aُXzww5w,iipYCN 1RD=2^?3aBڨn~;W[@2qxD ~>iRk6YyPn"bCa|Yß0Y0'0 >`| a>0p2W+ O0\ .A{G@,>0p2d&SQSlq "3xMii ^[,o*+KwlZ]>7i]ndMp8 ˊ8@gT_`;gͪ4O$ #[Z&}ɯ٨ 8}YkM>%=8 LI~PWw[J W[ `#0 >`|D.siӎiݮẌu"s tBMMxYI@eQ@XP:ꬹ{ (SQ, ֹh;}*)^g:χp~BX6Ռ~%Ŧ݉u}.1k,V=A;хy&%s"E-љ0MM{'7u:l~sBUby'bK~@~<0k̘wؙcSn<|ҥN6 00 >`$+*Ҩ m>Pt Jǀ1TG, d 1΃9>:a?ܧ~GEq$IAnb2mV~`xJ^,8 0eQ]UVH <Xʂ`wX{|xBc'2YE|MO/1{j<*Hy!/Tn߾7?68sԨ.׮d6W?@!X,ZѨ_`|0 >0X^n#,;0̩ūW< aH*bɜw(F%)!é,gع6-͛sH8,nJR`D8a/Ƚ"mPH։8JeasH: F>ed z&]H|`(;'O߽F#2pw="%|@EπeSTX$@)/0F* >`|0@|̧tq'{WTX Bg3Ai`H',>efҿO?};46bd@E3~<Bӈ8Aw ;Ex~Ag$ C{SI|uu+P ,op/>~zu ':&mРwATƁ|3ee 1{=xt߿Ty!/Tbv@Z>P:K~ꫫ3Fz|0 >`@qE/{ D> !Ai_@_*ʄosGl7n=J r5B| L8aG݄R/9JOʈMÑ8 ,YcxaTO;*)Iʙ1~hڽ{KHXw.|g-$،l̝*65fiYxDBH?0/T~7|%}uuF#0 >`|@qEOE1@6(!,{|d”!Ntf֘1 ,;^8@8H80ti^Fn4wT9|VeL =q'+`>v;,YكCo|1oƁh| (9sT :Ot?=v۷'CQ[\v/XS_mk0w0 >`hba2 0iTn Fj5e ;FE 4\|p>7e3@Ȩ$U+)B|r'50c9BZri~فtT9ρ7|R{-=8P~T1T|p =݁.|m*ೳG7RkIF]A>` ?d֭_&mIF~Fz|0 >`A\NXpc"p-->U؆atzNwcSlz EK@(zlCDVM?Ԯ|]nRWRA}>L$et-kBHmmJjcǞ߾wA%I<˖mn##z= >`|0ҿZ,^8( @QmLV՛ٺ']@.ܾg\Z)ҭ0zz$ e ](HZZ8²@E1KXd#%:g|v(D>oiD])x>Z,A”.[֮YYF>j<*<􎡒@UUX,Ǎ;Uml<>hm=Ÿp0"a|0Op990#喃ӻB>>²_ou2fN?J˄xٯwrQPp >0ee| BJw#lt~zߘRxs @&( D %(Sp*˦Q\bV ukj tQK(Y?UW=~ z|uu8'.cg1TD ^m4528%T>C? >`0 >`29ig2͝4i$ JR-zbUn&+:f}bϿ2zNR7P[|XE !C:g@h@)kɓE\_>+`ۼ+E￟)Ĥ!> y'UUm׿nF}]+}uuƍ.|RR`_mWge M hm]A2G"8fOmһ.ӟu>p]WaD >`|LgⲲr99`>e} ,{98(=Bc&2%nt/0lL@?~9j' |ѝl$.FOT^}QhT3LTd,-Ua At ?@ҝyCX~߬~Z\{#_b~m_.E?иkXh+AB_]ݵVMхd  ~3}#͜9^[<}:X|)#Qw\xL>p|z* $Ĝ<% zß#z= >`|0կ.4̹McNTSUVv*br"* ~_?_+\JXENg fJn=a3B+1ʟVjpp0n|@joJ C%A?&SkX}eqEERI:*`ZX[].s~٧"Kz ^~$2 -{p4ةwry.| mwT.+gSdz:Sk 3;v%q]|S|O|#z= >`|? >eev;ìm>@κ묅ה ^{ sMh^Ge}4eeH@{lN7!a׻;W#`8n,t̲T<ɴUUk.lPWYZzAAeeo@iPgG!SIrvK?@  xg\ TF A_Hѕ0<DTS* swȢx!>0Ueem#~rcC9 ,{ `}fSK'/Tb2՟0k̘c;vP">hoRSF0 >`}y6ɿ*"?1: 16ˀ67p/AN²_zdt \d_J4 utC{l9/rbPY J!"z}#{==?/}i\P",jF#._NX~IGDeJS{x2:EJot+*X~APߣyAi{w C{ |@Hp>6-"L?"&ಲIu~pzQ@{{={@/8df_]00 >kI  V܌ƒN%J9((?8ZSsf4>. pM{)bdL .pyvqF̞ͽ8jdKMMM&b*;@vݨsjޑ ?\L͑##\@  Bp>$e8W/zLKK1IJ1-G>8e xg3M7#mJTsD~ 5|@hl F̞=h0LHo߾>imlggcm_%|  #HE|0O(+Hȑ]cҨ|@jkk!V5J$dw=|wH%iSUYُ@L>@%iaL<8D8쌢UAF²w!C\%%҄+͌< D: J7RYdܹ_dAh3wnV0J 2t~0@FA_Ϝ,46| %p>Jm~ % @J|#R0 >F23SL0VDxA긬nL>, @%_y%]lll 9Med2.|`YL_s6["{2(",,+jw򤃳Z 9+\LfNѪU,5QbYg;bətRt5p#ⷮ8yt_Se9V*W_(X7@(0)rw;|akG"$)PdP@k^K8 2\=S Y|47oa_pMBSS?˦X,r&N۲d6PAx!> -h#HE|0@ C벌%FxXss@Fss:#yyUd,-MPA+Q2nŊ KKaَ|(=Bw73`ZBX#9%d(Ǩ |rbyZ . 0W߰Lñwbyep=lbpa늜G8WI;>/X^NXF2n(O8+:C0D'$_qUYY[ñ6Pz;+W?!˪V1+KKW\Q/܈@D"r}h|v5C? Q( @"7] ;/H-`Rv5<%]SR_R_PhFß#R0 >d3<KdA>\R*)Mha-,|Las[fd=NX >qbΧ&Of"L,/zOpXj͹ >{[YjAlP~iZӁ|!&Jn,-n²w g 0GhhgѪU9&wyyAp 棏<%s"Jn _HM}CS@/RR… >`|~&Oh3Yz={*شqoJJN&@ >r|d.+-T9s'HVȂp$㬳WCoq+tGWv9VQQ `&BYQQ\[j5k k:6s~K˘}ūW_DeF²%rZX؇ʲz! 3HYyy[\Ӧmt8(U $9Υk ӁÇVFc(Ø͹@PIGUeiaGhZN\J%[|*H5mWCTFXQ"HR+'ԲuUY7Äan" s^HDoؿ "#7 R+n OH%I6# #/x l#MA}Cw$YkOu :رco?a}jTOF0 >`ex| 22|v _|;6ZMM\v ]Ai_a]p͜y_w8gg\^UVIVG6-qȜv@0{EV>aJs2:7L23&,G?!3f"F3h!ӸsM**.~p 1Сt8#Rljҍa_ɞG,>^$0`z>Ifsk ;{~A{*ಳSP P0w0OucD-^\K~lCZ'R?䲳3Ng8lCH?P|8Wǽ]eZtTQtNLF"񯼒l@lja7)Ssx|"Y0@g>rͪ?ҵ7FHŊU*HK]@?jw\YZaY(U BNAE'>qC.|P&ө$*0PIɫEN簸MEW>q?*,}NQgTw|bei雄 `hKsZ'#w4~FB@UYY ǧ]j}[ >7o^x}Ĉ9sTQں@y߉߾d6qgj1BDjSBcc·Z)|SWtz$ځ|)A@[z|+ΘmfԼPz m#6\}**n# $(mV.]qE(_jܻM@Z*ENzZ&,G/@iq6WTBJ54W:SI*AÔ>zL<BqI#P'L@S)=`>@em5@a?=]Dgo8bܱ=ո6> Ip\&9lzcB?pW_$qF0@oALf\rR5o߷$]`+͹Ղ۽=>7w#䥗tTϿ;>'Zt,?0|֬[k4977*v$~LP^#CU.r:/n"Uv׃Nx꩑Ptj[h@ש|@x֩/t8Z_0fnH#UJn;8BRt.*J#Fڢ8" =B**o^=AO$ 2 yT7TWt}.q"PB@F<7B|JR_C?^p,T ܩG G(-A[T*SN]хXR>ppٲvERa@r@eeH?s'HE˖mnaD >`|pE֡C~?^-eY²^>'g>k.I|`)|9aY#< nbF9V%~@jooCF}hժ_tf, ? e 8@FuASEV͛X^ޝNĭ_@;*IWݺ@kW:˖8 y2kPIsac&b{ejJҬ0!åTu P*s*+DeV }))|J2yN<ؑ~#O?bx%)U={FF^(ЕȂrۧݡҢ=@ @2GBHK#R_ppٲ0ˆT >K}W.R{7`̙;7mru }I~|* !4LaYEV=A; })*뷳r{͑#9DL>ULx7i@B&0saԍӛ7Kh$H^o\ODH8|yԴ>JRO讬?d֭Z[oWf[|`mB}0H9pVicٵ&A_m-@^*I״}jn8n'(|N 64l1'H<gqҿ6%O?0wͶ!T=D%Ѫ<LJ ˾Qf͘ 1&6=@ SI[ѪUm8<X?zף,o50 \1覛d+OuuB0l< J%?d U/XB9!p|#R0@@={)#: {Y?0crˀq-LZzi\ =s6ǝYPP|'g>dr7u:kY?VSSBx~*zfHA5kjlCt'ru%lVqؠt"J+ Wv ǝ,JJcAS6*I bx/^VF!OurIV;g/z*u/o>h,t7LhoWhjX_eot{moܧOjJR?_oj*Ki~wjk_ >`0@B귺\Lccbc<Nk=r)ņ nwа_p3ed@X! SJ99Y6Yb6 ?x\Փ|/~N=Ρ\gg% 5|JC7CB}QiYe_*Zj_?0s-6ĦERnNӰL ,?!>uҿҿ+V²+SP!z}Cu,j~AX'^,StŋD"7L~HV:W:SY^WUF> b٫mXpD"Ѕ QE1!"0+^H|jхT:y2 VF" IRX򁏓|JMqx!]9?A* ͛⫭T (c(>S)/75ݖC˗0F0tuoOu;vb@Ɛ!,]mGڀnyw >k֋ 8LfX:*IԜx{|@MUYg$]Bǔ+`!i|@ ێGH?(~:u]é+.;P>lF=݁.|`_m.ೲ<􎡒b@ ͷ4ϻ >`|KNBl#F|W嗽\w'>}3h<Ǐ_L9/ H%ʕ>$nƘ ,+`<)3M5@lnToZX,+Zjp"Т( 򁦦 W@R\r@ D:[?qPLX ]Uu?:E',/r@hj:o޼S~v婑TE t _|qaYaTfP;w1ىBWBPWG۰pRjC #`-5 I(,kKWII(P].|rGRA~P(}{ h6,-Gf6P ØMۖ> W2/PT+N*!]@R ،7@vϞ䫫|VБO>9do;JR | gu[2x6_`4.}i߾GĆu{|:t'漼+dA')Scs~@Xd~Lq4aT4t8/510YTZp+0}byyBxLWf-{7tM+W aمf[D|VX={|~UYN B%b }ڸRR8SO' lrcX&<uNxՠoUO]$,X|bJJ>( U5k²#I JzC۷N$HR^ )=^@!2 HC)M?a80LX[eHO_|ȋ/|#Ri6cDNwU_[}Z]J@>`9r3=n?ǒxdzsC<6NFs>1<`j3M>f]n&,RIj&f{.!"J[Vj mmT/\tx6;q@׫ ĦO=Jc(x69z;&2qtޘENgB#1[bSS'RxUR"&<'C|o m*)EsENgNt \]i[kJc+Sx&NL!7驮fk? M]6dy߾u[>+ֳ/|ܧ!۰aW^ck6i逞ǵpK@zlZlQYR~`Ĝ9 zυ_=_@ZɓQ?0pZ,,^|?ՇDС! o^(a*)i'?SOlZ}7*+@x@u4MM#ҷߠ !C|on?R$'⊊33r0^kcWI*iTu5ѥ!˪Bs5m]p=u7zZY|ZklsuPI|m׿n& $D DoOC=M1d?x.|3}#͜9*ǎX'Y²/TK߾{1ed9jnkW2_OeAVb[|zOWaDbv{9pڏ7 J/C/򁯾]%,{~+] (a>0pBa6n;eefsswih?q>`-,k2yUk\Rt;s^ʂokx߼y_g>f>@XuP *۵ 8]O |6bĭVڭ,qݾxbO\%%(] *3Q#"839\ ϟV"xKY,44μ8|0>SO8eGiENyz;23ߎD*/b@z7+w{m]YZ lօ"@}*(r:F1A 6|P@|XE_ɩ_ I5.nޯo6`;aO̙BS^ಲ1{vB;Z":z_':뷏ɹlb9rQwee\Q{H W:8x~ 0Fn| f>rԔ">Bc#v n޼yg]7n O( E a͚@-B.*r:>,Ͽ ~}1׍0<]O'/,YkΌ ޯ@|zQ?|NkUtx͚z;~-^륒{7>~|@q@ȘA%%H sU0{! $9tO?*)9 J{YtH~@hhxe5k lcoYJ%*}>PUVM~x.o%|Ғb>Z@O!&+=ՁX}~Xe}ٸ.oF?;}aD񁟱:uv*wxc=O;nϿ EƯ~+Lӧ?8_Uy'׀\j 0"#a 0kڏPFyOg̉\4dz![8|@6[.=st?( j @zL{UTnAz wXwBXvB'9ל_kCGm!lA>й~AQท~0T|@9Uh!yeu{VFW+5'TTCmCtȑVJ PFBXzZ?0@~D4XEǠT^;,-ۅEBtSI$t KN}CQ< @-dmPotlZڔ{:FT(O2`ٔsٷfsk JI~~ em4 0"-.=}N66c\vٴ3Oo zeK~wCۥ֬Y#|{\?pjOl">dK:D͛7˂=yN>;{1&u| ^z .]&,FFY|msa@p߇jN4=4²!O ,SQSk |`S9l wRPP_\to: Lp@DbJzGO(|`܊\VOU?׭WT;+v9_p| IEeDA#&ಳ״i0UM"3N|(m#Gд B}@6Jt,T4J0O+_?))q0Y|R){1|,KZ#~@5CfϿ"]1cر;up/Xd0ˆT|e__=yWU#\a;g^/_Rg Pڍii ͦzQb9ge ˺, 1[|iMj ;vnML&?$,)a>պu/^2N^JSZ֡~{{W/\X v;QQ|Zc2DX~A~8m5BesߟdBcs~lVP=uJ m#~lVsGdd.T!d`Z+ROo޼iBB*A>| } gCpo?o8`#~1{4omm{ǎ; ˓ OWr6Yд{7=2es߾w+v #=yrSO/x 1"a>0pƩ ("&S[[JX W//8l[ W{MM%*,4BW5qC--W/\aTp:_0Pk':T>૭Vp(RKCk32^pñ{JV\QO(46VJBE=䶶vbu(# o+Џ.VwbE%zZ?R=>Ru @k²T>qkCI{PYV_"~:' zo߾>iRk6_r{=ԏTXdF>kV 1~ߴw={⩪_l/|{bs3  < ս]y=v? ݟesLN*l]ھQpedRA~͑#!F$}Q^b5PIz꧛!ٳ/1(.=*+;Phv9\?p_g>Ļ#KXV!.6s-a#o-U|^xtTB 818xPI놨 ՠ^ z:4~ ZQUVvӕVUn2?aFgx^o5.fc| :C>@L&;ϟPT ՃhT3 0k (|8Qa|@[Ͼ}#AROH@{EEXLX[el<.~PE~ Y0'?}>0pb>|*YTFt펵Ir MV9ρ8q# w':l>?C6.`,M>} p۽ܧ_ F}|ݺ# nwа_p3ed@X! SJ99Y"͝wT/\85w &֡KFxVZ|pٲrp4AS:I}c )V;z @%i3(*@ch' 񁪲6~ x>f} LkXABtD0Ь0ݩ_)eիόMY ~$7,' X(.A'P6|@$e8~@еm2Ǒݡވ?Av"m46liiǍ~۶x|(|Z0ˆOYn!ma9?F|qGL&fuo(0 4(!u^t$RG C_ |Ej2;u 0"sr/ &FzE>@П_L>PF?35iCH? 9Yhl fg S?p?3q-[Hfg @ >`OŒwR^0\?>?;D_vΡO?HVkq/hkᇛ'O۾]~U{YY,Pe D~ZkjZO G2`=]6xp gt^?$2`K*ןWp(>;]YQ|~)d|w/!Jf15T>tFA? x<;4-RIѭ{X!1;$XWWwWJ?ÇotWTiD<oh6߯aa(jExtj q ˆz(Й:t^>9%9Z;D~eJ.;[pİ8n2m:v&\iֺQt> I>WI2jXlNX?~*֛{Xs@ƣsA>d ׼g( (77~}Cs߾D>{H?XƟP B0[?૫ij*a>>|֬ &XK~<pYYh9pT׬>f$~"²wV%IpӿH?' {״iIV0Fү߽y=yrL…ÆS,n4>~ħa-B]݃- T4)IYv8(,_tׂ̎F@pTt9s4߫E?"BΊٟX^AH?p^_2<}PIIL~A'@9"aak2aٸ|@K@ҳ^ Ŧz*ً8q v>RP".!Z;pٚ P gbtoǬ"3[F]:@(I?J4*&²TJ| p[!>@`ٔoγK'5ĦPoD _| \?ee O$al~~Z0%|ҥ 0">k0%7ƍՒ+f̸IO#}^}]Y:N(>2n-h9tۀ_`˻lP? z;D' V5:^S"?I呅$i.cЯ؃ Dm#Hh4>_FgRvϞԁ̚+qIO/X<]S?0@j -haD*B?a&Y/$,;S _~=z%l"PIW_ jH~*.;U6=aYo ^ p; MMa9MvT:53ˀxvKlQa;Lc܋XQIrPIwiw+MM:7 &$QB=>7 {G/P:]?2 Ueej->Z%A۽#n~Pެ̉ZvMG|Vy@;7K 2;~>BrL=:TSSq*#͇ fNH S BZ]FH P /}G!`~tH/ٟ0;wlO5Ȃ$ ;ڋJY%7eϗZ%K6#HE K$]BLONmܸSlhQ>`-,c|vp>pL~uf"T@޽6*'&ڬѣU>(ҁ iO9b)*46`-"#fEV:GڠA6rh߹.|6v{ݿ=dE|;("a>QPn 4+Ɉ>¼woizJU+t²eA):ug…M@c~*"N K; -MB kCuBaht:?h|/~ ^oAߝ1 }պ;X F_}V<0P_s"(;,;@XVTт^'tnȢx!>0mE)/H4h}J>;{xjB=H… F"t]Y8{ԯ Nٜz;v|ӣ#νpB5$ʕ>̿pWEE\>Q {ň99ᅣ5At@llaLV@z:+n(" J"@RΥtsHlhN"5܉lZ[9"7Ut87v~@Z|R?ByF;|`yP? nqB >SIåX{h#Asb˩ {b7TAH-1gOl`F !|)=]?!QΝ#~ 'g 0P)~`׮|V00YU?L]iԣ5] eY|`ǎ}½=Eŋ?0ˆ rڿ:*IJx>pzmbc㑞e9@ƯB}e; @]nVK]tO?`0I fd3sP?yMR\w^ M5D'>0A>yoAxtfs.Ȃ@׷S4*&7&,C~:Z8.% 2B}*SRI{Dg/p6s禀x*` )/P' B#HIs` ϟCX m}w~ǎO{!Yva.|$ >'HDaYJMG7V@x$8e pu[_(SX-/I^ s>XLVkfO%E?P\Q6~>7RuƭTwDӹܕG[|q׮M|nd |uuEBCY bt#qBAh''T$i=#~%K⻸c=Oxs|P?{to&B- ȡC}5u z@oY?X,vM"/B]~,gUh"+z ?T~Ո! ,ۢ@ vm@[B\ y|;R*˼vAR22I~IHBOu *p\&Yc߱C3^ݪ~ۗd5|x$Ox34L ~BCÖ'E' |r>'ge4>@~1 (5WUD0lWyyw/^T*r/-$, |=|ysn޴#.+2)*46,zWKEV]B,>Vpl_/ӧiٜZ,ǎ~ޭ_ ߭ޯ_|#z=t>|=1.PȦePJ)VɓwX#<2Z7c:A~} PQL.0YrYY dA30ɢF(D̰8e 6ci~ָ,46͂.]*R+*X*}`m(EHřKw~{x,²zfa~ ,77o^lB4]To2} whƲ?zi<@!aX5xx/s(,CpZKzD>д{wIxOG# ԕ\ff>л4Dfs!y-b/ vc j !zy~sFH.t8فp>0_0&"kQoH@HM}5scu>@E1_#G0w9!dPJA_}M*Cೳ"~UUhˤ\i^8*ˬҁ%`،/ .|^0 -gNO?k-53|VKvoV/ZeHV $T?0^"ޘ>/65t 1Xz '񹹿Qyec`ZYJGXtp:b%hx#@Y@lJQ [V5*/ ,ۀILLFj?l$%KKO#R|`Ĝ9z '0L˵~D_vΡW?HV,ɓQY00b21oEG~ە+ |@w}3,1G~rr3fmE'"UԘ TY*I!")SHFA˖~FƔ,zOIj/~#RQF__’--űWbD3A\Ėϟev@H0J=|u|@s&6ZnJL,/Ox7Ɣk0f ,;,8եG@]?u4P~k| 3srґîAVeYuP TtXqЁ >B<&j]1T.~9w'@wO{mU S?/}^x9lZBj F*t?8Ujop0b2Y@eQV^~fc%M6sbggpWV6|[ɫ_`=~VًWm_|0n d9on`-uU$6u?8キ;B^0ڲ| /HT.=g>o_ĩo1*n`;{%>;"@_tA'EHatv=R㹰z¸eC LJ\&O|&*˻" .cV/\ CUeeu^[?3z PYڂպt&DGL TDŽiF\>@z}Bky9/O+r3GXO$fJY^HV}W9#믫'bzeP~/BC!}d팳ޣ^CWTRkfo{o5 M,??PT1<1<ߐ9|_eAXl((X0P-Zw.}#恤/Xlu[Z&m<*ck|BF*#e kP@Sf> z<%!HF̞= @hl^H( x |@k(Vs lpУX^>"c\ȑ)x; ²JMDo_z:`(0#48^Y*)iײ],~AMMpb)0>?tnT?HU~v_|.>0b4m Rgu(PI:.|ss7ϛ 1&fdƼf~g]>egfZt0.Bb|`)ZXz8@~{ew5{T jqE+652=o?l~+L'Nl?P_(r:D.Zߛ{NB'N|/-ӧ8|yL"3!/hB H5ĥad"|~ $Ok~@ʣ0EKn$VVfH\{ms@|YKhAxzn|LPVȄ6e dKF99c:@ʻUp4z}D>ٿ:u%Gs}C֎GߧZd*u%ok]uLP@k4M:Pglֺc l C@|s0> IMN/@wj4ۄ&K?_PAwz Z>ppٲ_ W* (]": 7mzW? yjR0(% w5*7߉N|@jm}/VWT-N-o_I7.{D_hdYy N}'?![KXF~gkM*|`̙+^[li⊊, *)itf]d/|,tJEhRu)Sog JQk'@L+,]|",qN 7ҳ-"[F>йm>ЍJ@jjߪLe~Al;S?ee>oY?3~ɺ[S0lK @ >`O2K=a{4H q׮O7QA'ɓwK? 9/2 ?;u7-U'{i9|5kaj1]( /8A d yy)-ǫo6y ;*`=| ~<'5_SQ*".> 46VV/X JoP}-ḈwQ502a6Gvu7r}r&| 2ޏڈ|/B~&lإ".PL]_@mTkN,cF/c+OlU?7@5CAPeZhTC|@Ɏɀ~dқFe'/8a| Tk޳gz۟PKjowz  VeD~A~H S_"e[ F"te@`"#eeM:1gm`9<²q۽Ҳȋ/|Gf5dGWL\?~ASAm&=W\ux~A矏wqmTrN1֮/>)g] ;{ϟ \=9EVz?K7l@>E8.<~@ԩ ]QG_}^k|@|Qĭc*I2BzlCh|)_r>E?_' R_ޞf#HEo᫫d6U[ZSu_#̙JXv@B}.k#/3ƔR"|jlr / pB3hIlj:xֳiiiV ǭXatHe+@ n6*I=xq̫eI%)W[ky3dAH,-ޓ'9 Ƅa$,+YCH&hm%599C}tZP/D?->?Tp>&vqE @Oh+_|`#L o]/p B+<_az\@o4>pBP}zVDf3|nw^K,k4~u~w<8TFm"j=N0ep*Jt1s5/*j>T@z>$n9QmT3LdJȟ0PIzU!> |*+EЉ/ӛ7z$j$H^ -zw7"+a U|@hj~ %O+KQ~AeeuP?U>Kn >`'Hmm7SY0PlΠR* |/ \N{ h7_0۔>Z~Y}JM?粲^O}'%"jY#,6g„=j}CLLVk!eXF&v~n60 ͋VoEO>kܵE| Xw/4_(SQgeU<4k<߁]qx+!+B36cFo߇[-- }^PW6;ƘOr:7ԑ_=*L]nb&2i<̗,^l23GԴ_Oj^=ZcE{mD>=uưwuyY~יqO43䫕/VyD,>%!>GTYW>`2@] 'A*l,-ݧc ~_; =P}Q϶TY!(t8t:DoPW^oUt/~ -mpJß#Rt=a^@ z<Bӧ_+#ˊ'--Gvuxb9/nU@F|F̞}~)+|Vp*ˌj=Kjk2 w<'[:lʕe?[Z}?&ĦG,^Z`{dDže4RB=O,/?RGm#G.՞_0w>f>eQyawHϿ{{byP'*\Ӧ-@a3fĦ CO㷺\ aِ !:&~f{\ݘX8_AMьҢ5_L,/Ox+E{md>p͉=P+Oޕ0̕J.3SHB?ӒD> P3EW> |@5a__S}oT3L]|@ti<6):+4:}t& 7t"v3<% aYWT󁪪jIelg-AƝ߶d6 ,u>p#HEoon+p\OHeaO=S0#c63&nşPljw䥗l`#/$R@ veˢͽhh8(',΁ŋ,"ͳo߹bslZϹ>;{,O?{v{d'5%MXq{־Mw[?S-*66z~aūW",8k1uρݮ&74ʢ8zB]Y*ˏA+TC#LeA){,ХX^n0[Y@|uI?`Z_]v= qoU>^~2+@a $8I#." f.3s ;Wb@l(JD*3 tm~{15!jjjn!c?,-Y1f}CժK?PtfPY5l։LAs{z&^*+;o|@|ZzB58,z 9² *IT G| G̉MMch%[ZMzw7b T>>  ,T>aD B?af[M/0v_ - |KXvj};|`)lZ>'x|@.~ufY@5D{-*Y߰ hj:"c,w]wݗo޳gTjRE^-&szӦW5uVjݺU@%òX,H$zڴ/&+ìa0,] G9-ƍy>T`ƌ{ƕ7_jkE ><#ν>&,RMhh8źi dKepMZ~ mW~ ÜrF1^ m< x5uj5 O:d9"^}>AY͏ TbpeEN2k%YN| 0/4t%d2(pJMMI?Kqho>h,͖p/H ~ =݁.|`ܹ I_oHeњ/Hh~, -_W[ `#Op)k"&-w{$1 >,Kvk\VV hDY^3Bo_~cZܟ>W[;ɹن!t<B9~fu}z"ii۸ 7+.| ++x$VP}1 .۵ Fg5pܟbG z| 8*2X*)>f]ʂn>=uwPJ#F}|x36luQy0A@?L*IO4DVIN1<zU!>@%8Ͼ}cq#9|-OomQF>6haz@C@`ԼyzXg1 T 7t8?(+d0}4^tC|N΢ίƿJ:g:^f5}h ׫LX2 ? `kڴ)A],!*Jqy Wުt86٬ ,#4 A%% UPPW{z*QQy`(|"~NCC]0> ˇ@l)m |t}jk|'(c(>S/H?aSm)/8|aD*B?b3pөO,RI:&|ssKz~Yn!/ CF=C?#ZQ;0G_L838,g,wǎZ,`=OJ،_Dmy4mT[~|neꨊ*Ii.-65m4߽杝_eزnj٠6N%w=}Q=| ~w\>ԸsX̜B[z/;qw qXݰk2̙3ү߃;o]vmf !32a{uʍl5`N@fX 7o^"ҍ|(ƕTTVv~]D>ٿƠ@ kg@H;UeeQbS0VyjkAAq6TD]Tfo~A0PZ$qu׵jܼQy0wC?J*+;c$z:N|>ȫFR}wz ss|ȸ;;15,%[%)yPnup>O) 2 $SIPY>% y}]29mn}џ8 Ħ#/^(>#/ tBXIlj:$X,y_'ٳG>ߝ >+kX88ԁ q׮66 vi9d.X0NRh?~_W_e2 `B]-zn˖Z7ۺe?2dw|`Y/K~@.^ wի/ad-kGBpSOuSIzCXJMӧ*bz%g(&c*=UYrԫ & ,BFvӨ(>B(}XEᯉ^}SDrkƂϞߙ {m&d$, n!@XeWĭՊ P[]JSxGZh(i Aljk[˦, VAْ#`2gs&g&dBռ+dyr&9sm>p݆|Mѷm)*I`!"/w8#bq䖕= @7T;y] ,#Fcn itg*|e|@Qb0/(_YPP}X |dP0> /P81h_%1|@Oϟ Zo}-rA>S|>!@nniYVoDŜ_ Or)M*QtRUŔ$tC{n.-xe4:/PEQ]gMM}Kٲ[ xUEE:yw4_*i'79m_=PzyN%\یX~dŊ_E-po^=S!T$bJ!:[\yYȘ#9OU7sm;Msۺ|s))R5pUUY<ǎ [ PYn=k~DXV/tk6[?MlhwZHO-? Gz'!`l.(..|W=B0̻ Gm>_ԛҳ <|3|A`ߏicaTU'+ : 0n Oݠtޞ9sڴh@HȟД1VnY~}ꢊĞ9s:\|5)%;;&FuS>W'[hqFAUD{aM ՚YvEDv8.Ɗs@5TU d9df#| ?u$=-,l44zV?D[*k4/DSb/  0ɌĪSS Kj=))/(t?(t.-`ȳYkxV;G<;I=eZ˜/d=PljťݡCsV,[\T 8ml6.V~m~_N)]+lLt{E~͟/S~7kGvyxѢiYC{Կescvv&o ᨨZ6+/O־GC >xv~ Ըm>PIzg@3f: 8 1ҋjTΞM{|':c}y? D^7oRf.ˌ7+g^啭+xErX' HvDVg|^@g|`W^(V[b=_ ;{v7߰z*sqnqWWpdlIYU2| }LRBfEC>Je.>-Gpţ^k?KV')vUQ~|E?MM5۽KMyyI{xH> 9oʟpi$uȐ Ec (k-W p -Ur.|XV2m 9RV{Mjɒ5 X6MF=B :o^o'U'XJK/N4h)3aـrօd<&y{1e p̘͛m$+~-t.55 D}wҥ*TQ@\Rto8`*k6OhXر_Sr?@e-%,@%(_FUu9Zb5x(3 0}+ 6F}۽=>H~ o^CvŅ'r @D14_@)]] N?SbCC{^@oVT|Pz#+nI⊿~[Xqr ,ЦsN6Epey䚤K:'|ä3>!ݛ& ՞9sf𷿍ԻL"'ERn0@?]Uɰ.*-ohoqUU[ 曍(Gr:**ZMyᅧ@]߫o7n 3 |_o4/*k?!&,kRRF++CC{jS|CYnu_zioJL8ajk7П\j_]/^T0"s~}5>0;typ8*/Z^WO|>TWx3p5رJRSHHl (gϞPgΜӟ>}A>?C'#V\cE)W\|y׮51&B4YjfUFt!==f@YTQ\=L*fj+@VkL]Cey)²V̜}H>tWXBҴ`rhpa(P5l`*7ϔ mևWCs ?9ztǙ:V7 44trڿvi?5I] ²0L5+`yo|>7~iVE?y4IN)=='" 6o6n_?]Ke{=VtiTgͣ/#{ocSoT?`1b`],{gcŲ\zҰp/74w8Kŋߖ\(:ԷC 7B 67|_rm#D?lW䕗_J%i-|Ч PJ[νMN_}5.&duc2ۺ R?Y,2Jل6 Dǫ/͟ԯ߃V%r3YyС1INMنO;{vő Z M>7n~$EEemj}2bėv~z_TMVGqGe@0>|饿5&Uo9T/]Z  ~~O@llUdɵ]m<0c'~nWÌr=Zo h8{jRiF5ޕ{̆ v{~]Ҥ|.‹ǡŋ J+ j|qWWD/IsnbL"D~7׎r'0J%y!PZ}%B?`2 Ssr|қ4o=_ ,:2.heTUWo^,(p@/?@x~eE~/ |f+ hpF> ~@d˻k/I9򴽢b_"wa1󁚒mbcjVo]؊9@zg,;GE{)3sw 8矟J6۸Yr5˖oQ~Aqhw

pLx>TE'Ξ}PԞy3_c$srG$+/gmŋX&H["pv!# ..˫n؂ }A/\mcf#sNovos \soܸl<պ,K+㫗.M%gkoĠkko)) Ax/<\D}$6PWu`؂B:_WnY*A٤R>zM|?KlT6) T0pu^~}H?<@*'6 1[X1" }7ԯ_ ƗL2<\ JWΞ eh/m-ǭZ  (^Я-}$<+p>@XVHc~nY(!=} w`][Uj(7E@$ , `U̙Q 9WYP$@S}`dX_0j+04_½ݽ6 C -,vV,d ˾] h? #}K/88TŞUEE|zG*fp`²&P*nܴ ]@…3 XF# <s=Z%som+Q(^IEY?0-(bccldOm=gUT0{?Jɥ)l90@]Gj篫[,[*;AUKD5=嗇!##O!9y4'/y@/۟..S4#ky?23 %kk7D&`r]]tx@cEŷ鹹!3&ܿq$ZtNH%৞4p`\SR00Z;"Tr8ITsH4{j+Y0q:dL.5 @',.Ү<&[DNx{NI AF wݺ\!= @!E.9y׌ƭZx!>pxѢ +/H%i ;ᡳg"/9S|@ӟPkDE!*I?E˯k@C5WHn1M#L%n(3gΉ] "@_aeiPr6p|B n>G75G1a"?-|@ |TQ,(XCsؤ:0`!f y*%KvVo]؊ywܽ f8.RPEqQI:Kfy y9a UQ0/ye$.W-u=]C{6!=6)6T_@mu*#1VNgvo`>'oJi|`ϦNf>Y{(UKDꝳpPk~`i2lض-|Qtv5%%C|2;omW?] rm5˖'ݓB}q> m34> {/}d<ܕ}w| P_#|h%9Y[h|1Cg]:[|Ri0rX]?@^%H"k}3@郺}Z;}:aNƿVtB|KhF"wҟiqo~aG1'B"и;޹slS|KK ]B79Bw>z  @pk+$!ٳ S(o3|';~l',Z@~ Ϫ`|p_eAAa #r?wHQX$?cƚ͗q^Ywp[)P|  [u@ҥ{@oVOTLcWL>}/U<0C4?@Uu)3scC 3f6@~|áZ,o_? 'UY~j1-@\co"߿M#G_ݸU8ٳcd>.-jkVuQ#˗Gu2j׻FL-V+ޏ?._$D5S)= Sft]o?9d\wݧYeͬt9@x@R è=aVW̜Y!>]/(IUu͞9sM**h)IeAɼV̜y*#@PrgDcp> =zL?v~  ] N?`2 }]22V~ϡ| Q́^>[+AF@hۓ/|g&t,1F3_@Ej .h,K C;%L? :ժ׻ S^SR:q+/j`|[ۘ/x*U5}{H.ѣoDpUQQЬ ؑ#-pkܽ{s u/ 3Ǐ,IJ!N^ aBB><̙a`5<%BXv]Ō 5;;Sw8Gޯ,(3Ӗ~`!&^]\EK /dCQ F>_:/H9 ]))YMssL}e/ B~^os8|yv~fglDYh͍5t޼Bff?s,[-0>Plپ@}soR#C| ?ظ+8|ۢ0L%yuA4U!66TUsʹI~@TZj!,{;(Bh_( 4)G0oI!,; pKc>}*JV| ^@)l,(IΤ"0Є nE?^A&3gN5QiB~tr@u&ϏFK $bƌ#,F>JqFZҝ(vOcV|MJ`'-r=O#ü6?p $=^BX@Q?']|zm}_ Vh8wɑ+:=OZȲ*20vO5VT˸OF ;v^*L}l3<`gѢx{i$NT"VxGt8˰a`/`L{+NF@CP?d$@^yy_MUa\r23dPUJDD8²UkN@h ^@^y9 Eɣz(LU5J oG~:bp c䖕 0Jҭ҃_b'[ ~Fa7`؀ !PP.h8௄a>9(vo`!.*I=s 51@| | G'>dɖ^>[9袢TNe2&%QߩTQ2x 6XFEXXF! tT%G/3n>@R|>v'4|"66V6)/ɗ^S…lj]]7t~]P'_ziwQ 6Xrr0;bE\׊,xTHOCG!C^56כ2|È@Cø{Ym |` Z?OTs 8_`))ނ/0v'ҟP/M?x%khaa  ,[mm|XiAIn@Hy# @cc3xu4"waDӋ Np0|M~'B+>lq $J66%>?}˵ $ˈ1CN*-0 &( J![@⫇ |e@|Jhhw;V[?qH>Aу@=%ڃLwP\r=_ g zzzb/_F֤da44zRSSV 4f>YB0m# @W>Hʺ 7|!;Aڸv F+ͥV@;ݴXgC84{0fs|͖3l+#bA뱿ttՑ|u̘3ޟ3,|x{@oVOTbSS*0PSS4ef~ye-'hT|FsMٙ?͜v[J. *IVo|￿|/LFjd{U\W^6}H5(hS?pv:dUA%inUQQgf|C`=$ s~7wo8bv | *nx@MIZ%SE1 #Нl;8m1J͏%ҟ%ܟВ3+Oh**:b;bcғ.X 447i`GOve=TQ;s _|6_k~K ^k l*j{>QE/a˻:_>ZYB c6'SE.|`/Ý|1mϟ+.X,h|^ K2TйC> 9Zq/  w>~sX)MJ/**;_[9իmޓ'S %,~@0&ΤK/`SOa$%-lTQ:p͋\Yޥt_?y*CUEE_#ÊϷƉg4,ÆR|ٜz7o kk_?\sͼ9_D^EM?40,xZ~@JOCg'w[ۖjܹ|+XoT Ejɒ#n ņ,ٖ`M:mȸTUoВo/p8*#եbSS%pde&m;^o~@ I/ZmS0 :uox<%aQE BF){Ba:GUuqW䕗SI AU5(gA.W~C}`uWG%Nvr?sD0>n(~ XJ (=ḃW\v?)YY % ӒoT'pA0#® @H?W^FKI tG6Qa@BG#H:*Ĥ!hk dVx<^? /<8+n<?!Ő~?4_#| g@@oVUis|-aL@)RI:G_I_!_?uHz/ZsMVzڼۦ}2Ur:kd{mS.pϥݥɛ7u[n wEUQQTpJahfUT0{?xn@O4 ]xݔ9uuuqx|>W]!ò? 7TE+5>gǚ8lH? \'rȊ?0l5ᨨZ\+W-IJZmHE%c> :/b⋇y5D֤e?pj_[{W7 Q&a,MS߾|05]zM AHZGA tDZ+T8(ac~3C è-|khp %,{*Q"' ZLj||/c6wư@|A@@[lj?(V{!~@'*!@?a/ٟ0PWwɄ1F*褢=U7}`# Yp&_E;_ 57V߹-Ȟ;w2XhiI)=Pn\~[ EFz7p!ɛ7_|1Fr8frO-|n_n@7?*IOה-J]S~נeKS:/Дۄʲ'PWDͲeq]+>_JovxOZG;@?x[Ւ%[pf]? 9X髯[rr }ܥ>}V i7cV`H69?B xOZf&lݣ|W93zdWz]. 2! \w}Xᕷ~0>pF۝T7^tq*aY* ':#6 |g@Y޽=O⨢$/!gFg˞zV Ix/?L<vƠ->` |E=O,d] {>#TFO큆^>[u+Vߙ3w?a@E7U23?PX81N )Ŧ>|A|*JgGh`_ BȆeB'.׮5yJ>65UpDUQ䓭DYp(؞tE?|C:;L#04 6ʫY=˔}v?]/íaNc7 Z -,??ظjɒ+W6 ??,P;ݭj  t=uj?^2F,@@|A4Wʒ986_6F3<ߨEK6{//ӟp#v6)hQde~HQ%w=`| u''lܵ`znll`A}&Mo˯ټS>|ApK.8))O[9KmbSӽT1+>)4>gFo(pT%CͻXjD3_ \ǵ| y5~ "P 6ĉ+y嬽"G ~ƧOw=s:j;pr~TE U4HN6Wҹ~ GWϼɟP>!@HNU:,\x:hnN|1R-5%%Îc2! ˗;{i| 2pha\jvuG~Q?*ؤ|OAlR| JKS?`| ?@&q|=>mz.C>}E2| &&/(k9/>w`8JXžK/Vlp\: :>@ +aDABi?jܽ%=uymBzd0bҥ&8Šԭ5reee5wv$Sdx1.;//<1_?,Cܟfs:k6_#|I>;_[S|̤| Xv(!/|} , 6D[tdŊN1;ZRS/oY qOhW~F'̘?ŸpvpVF|qtT|ݪTuqqTjˑ:R5: -_XGS>6zݟʲ'0hGְW Ëlܦ0#6O^x<8_0ngo:|aG1C7chպ6-`|A7+W+ (>|Å@&^mF‹v/T[,lJJ&:x|! B|s] VlOArO#"xPBX(5J'Z 7pStTͪ(* '9(ߟ@X֯V{@xTaSS%R/h>p`$R@xa69ËD#A~G 5@$%^>[uA+^?wn䁐 @Ke U-̍ /Ю|gA/X't:no_@t@ȟjHn8=ZD@}#G~ݾSkJJ^xpݟP|)l!'Yf[IX6:%'-*.V-YFz S |@E&l kko))v[}y" 4>O>_`N-_iu$aݟP7A>}AmeaǏ4Ŧl}c~/n^_^ϴ[R_[+SUAx@gE^ PEQR~DW6d~ _~VEԩ%\?Y zX;3!>`?a~7kW_S=6nܹƝ;:x,]VoDŬ鱗|-+) ,{UI:`O8p4bəMX9j֟v/9|y4>pY/8FEqNՒ%cZ_`0!D(>Gټј_E95l*"66>z٨o[7Ut8v@QZ$/<\z 't: 5fn$YV(>_^͟/Xv_/oE77o/zaG{0j-`ނa  Yc~A…3B `PNeHts$  OPލ]|N+<9A0#, JTU}=PIJa<&%mUJ(`Oaon]>ab"@^[ 1 WuH˜gXfh~_# =?~_3w$'_b;]Ndxwj?^1Bv²CP&\?sψ  6XDww-x:_@x|y*ʃUEE_ƴv"9GC²}&NΨG#隆zv_022np좢ΚG#dM~ :C~*nxoᷕoXx-mZ @ +we+Ovs…$o~?awq   ՟KM 082p~ݵ PYh2@Ca|.~ˈU@HyG[LX&ON8l iL #w\U,OxAS8$P?}\֓e*a(!U,(8I~P(-~:6iGr TU@}̙sζORt@C7o 9*;< ^@cTS/>0.-mg -g؂cyY.düKGWPE ~VoHt0ajѻ^C~e&Eҥ~g [v?//ϗ }&'_ӡvN1*W-YEL UQ|i{} dC0,[O~|>Bgp))w >_ӟL޼۾}џ0P_*ʓxTQֆ0__ؑ+^dgjekR a D5_Q|/ZӅJ{54[sbP*>p<@П_[6ۚ`؂3CGEVxGlr> #nUv }&<ߐr9qT/L! ?aܖ anÄ L}\Jyl ;_! FBw˝yh <(==s49/O]T$ ϧrPd!AХ,rD?@00/xnA.^RG$ ;9paپ? M}mQ}y~'PfgO)g ڄ ?_maap/P@?az?b7ϟJo ,F~I^Zp¡٤ySBrU).o='OR~gI7janIUן=S~>_pDv6M~EVYlj]׿Qt3Q-`ܪUn[X~ñU-UY^c/7:WE@Q$Ժu?A6QU}Foc:Փ5A|f1@u ?|II߉l^D5z@o }OOW%0C $B@e٭J7%r~ ye$OQMII|e Ƞ0OrPV/]񁵦~~ #pN&6)U]O7obpsVݑkJJ~4mŋ1׿!{<W=Dc˸Sozs*m̛1pw-"}yMȸ\WU>p`683k6_qv ;v|dfیn `Y?awB|[@?a|pÉn~ 4_Г0ԩhugs \?;sfCU&I.5#-w=]qRgΜy[n/ $;,"mZ:i-+;F& SS1smfi%6_ %#XQ{ee͠@ aR?!:`C|~0 %JDJ8@D2+TQ, 4>3.Y*IJ!%TQPJOhwҩ(0w1Ħ2MIJ![u+|(Ft/@Y3TQ6']|_ IJ/bԟ*,݇@{ݖ?!(vOxJϪvĴkoCF64UY,w abc;ꧢ'noUhx:|Ü REYcZ T=g=jU\z!=7Է[_UEE/Xi'}I6#˗.W^h = #h))͟?v~ְӦVE x$Q~XR ..~?QCoNJoŒ@lJam` {Խnn(kk2TUO2 gC&%LA1$]tQL@!=&N dLr^xkfOeٽ-Ѽܘ_߁H0zadAU?],\L-+;P;i%PUBr."ddL II1QϢr#QF>@鷾sVq$038>RGSU ` lI0$t, HÂFSYE3w2-|Z1J8m ׯ,,7l_}6)"lΰqXq6nKllŦӷ9' zŸz*s+W&ϝAej²C(RQظz҄Ϡ+٬lRңn &vp8@/9/Z#GB|ﶒn}_Mc,'Zxz1> &fϪ`gw6MX6a|kPweAɎt!=0b{An]=*ʿ !C0a| ˓b(/J &%x[uW>ٳgp@6_wͼܹQe'EZiӨ('9hcYsۓJK ˎ0 N!T}²[.+/OtUW_xy@}K{Ke6=OذcG?a/걊}SE1F@el5Pma'׌I? X'[|dŊt?C~c6^$=H7_*MMݔtE++93Yvc~U%p*ɓEHO(bSNPdՒ%y4>'f F5_hœ^xX 6H/0OXx۲˰a dgB$s6_tQ>_ʟpi|AD]jv.ZaRSqWMII3\>_f 72&cnW|ܚ\("҇q9r߅(>G@zO|$ou~_0W3/P*YF 6-꿪&O:มut/UQC:wtQp\pTO3-+J$"?m`BT#9 nՂsbee uEPUs9Ǿ}^\d{dCׅL0$bnc:뭒v5Ge 47OG=s4׮51&DPz@?bXva%KaA/퇪hi䒙3QE~e(&_zi xomwEFki.$IzmؾVO({Ij?{v)Ж@b?!^>[|A.q aL$%1v&]z 'ԮgihϷtk˱?hom<ݩ~@vO Y#" &o̟ͥ9_௭}٨0n*M%jœ X?uԩtF[,Wo@Cܚi[_CfסCvЛhmRssnH?`ݜ#p BFtSc0RSR=IIka7L$8C6%% -,ߠG/Gt8aTq|oȘ|B\zs=a|B A0fRڨQ1)gt>>ѣC $`[w|N=st9*0²T[M|$,`nYiP/qW̘qE@p`*9m*k9yI4ZX<`@wWr$A7 f8gUQ+kka3p= 555޽-pvӦ79mJPhpq(^o07#(&WQEi_D**'Ozvd2D2 23"⯭2Zb9kd0KvcoqKTQJԂ tJh9/OMvL < W_=5٤{VoT&,{#(hew$_~ /6~>_E5_@,:UhnFތ7@rNhq<ChW+>&.-S{riϞQ(ֻhK>*O֔-UQ|Է5XFR/PE-64<|AaCBzk]UU?jdgjە@ K%%k oM^0PYMM_cM2[kJJ|h<+V ;aoA|ã+WJ r.ZPN%,m|@z[ 9W@/0VdzQh=YlJJ4E?H#b'<;0ߐ,l@Yqfni"aY%1|,!vNT0T r5*O\C!7([V\)y3Rg~@|饽 (N0LB?RSܹ9*ۡ$b*[VN{ 0JR)_ayE#b]@{[Vv%VT|*h?\gfnI{`$ËMg=CX5u +ͣo7q((}0 #՚ܪŋjJsU~ޣ5%%z {zHXv08Tj p0V&9ySž.  ! eYC۽|#(1yΑwǴc0AQ#77II>}~=p4:dhɥj&o̟߲_|`'(}*Zߨŋ+>Zjm/hlb0n,xTHO>_Va[z&绺+|zղ} #<(!wN-X0Zw2DEtd/Î#<ڑث²n[0p:T'rD~ࡅC `῵Tby"8- 'U)|eMӧbި?ɥu?HJ Q0p# +oAyƲ+A?eӀ L2$m-+{+wݺ[qW,Ep<"B&}疕}Hx6 j/`@,V`#}t WZ|]M*-}?n )|ATє6mcSECUW-^occtnKbUEQ*IF>p z@oVT\` 5z/Sf榄 7^&9JD_pPx~e]g7k:((B[}BG/t>`AxP%|ĥ~6jW~@ Rv9f o>%Ug#^~y* 6[. رF  OՔtEV [պ"p8T-^|qHkFU9T/]\l7uO[[ ˲(zdwb,Λ7Կ.²mA>}Qn85˖C(?y@[X0 ʘF?&²4*(\6s4²A@K@HXVP{|Cf+-0@ڨQ/e~S| 00 %s^].7|0Lr~k $7¿:b ]?O0 ,anYIɑM޼r#A>0:gΜMeaOsʞ+/OiرcoHU4\{9WYPT;ԏ7k: #T>]'^*570?(d0(! OATQ.B0GY[3efSEa |૪ŋ'K}²o^{Ε+fpL;GkJJލmۥSf&Ϧ|Ry]@@ȟPHO_]|_Wp9J 'ꉊʒ߹spp²TQtSE9`Kg gAX[U=bIDAT,#M~qb }&f[å^ OPEfgcA|`#Əx5l7ZGmkǟmݺZ[ `g@`ђ_`o~ <^SR,‡MtּM.|m5%%OH?[,7de?_DΞ <H~fٲ}Ot':K&^G/[t8Y)YYaVLts$a|@r~Մz*c~c6 .W͟=~^ vBzzFZz0̵1ptR/"}l@ ģ ,[[V,sٯ"?_"iG I~z(ee{!PUK|vi7REY[V$r t~ocb9 3fTU>@ 2n>wݺE up3-+ 0(-SU-]u.ᘥpJmq%B_(lrP?(>[V6>B&jAH`_Oy גuQxq^ڶ]wij~HH7 D0PɕfuF_i*9%z?aoVW| P_*I0-QB? 9eʕcv?p ofۺ/M1JUoi??0aUt:(χټ6vwF76RrVTjс?>rdnT|`ܪUv+o௭wu> ݏ'408_'ضye0vn'ζ 9_>z"&~ xş7.~@vBG͖pHdqVk|@|\W Xta@Q>-++va7K$@x@UB%ܲee_DU &3?Gp^ranYym7h| ?PE9=^Q={<`"XJu~o|HmPc_λcYCZYP|-O,ǼC:=S?c2m 'L~`Ri0C d&O߶svDcB7&:TcL_Rmx>hUkuQ~T$$߰"?%²u[ _D{xu}ۭ=ȘLk Fr~աa 6dS߾!\wf!=}Lg9x{wPUbcy{Vt0vdO%0dJJWzOa']|-,&%(òUu` SQ|jɒ/ё~`_І~*JyƵ4:ݳ;4_W^:[,5P_0Q#@` o $k;)f>%yoO2De$ݓdb| ҟPoZdk ,FX"+ "oC @ k-{ˠ<0ݛo(OAlR| z+Mv:6Kռ2Ȧd2 b@!2`['/0<tǤ1  f}.6[yh;wF, TUo/`@taz,TQ~:ֱǏ$啗 ]\6셶hICr2)~eA&5F_p@ܲ{GVr8O_LҠAR ؤXWE~r߀Ai)8[V6 8uՋ1c>mZKYc!OU vǞŋs]?@UVΞ!:A #||c5%% ee%}'"\5_}u`8P-9;uQ? ]UUOKH? :$=ŋ(>[F> :ۓ.H| 'g>vqd -,|ȔZ)YYЛh9/s S ;ht|CB² ˲v=_{ޯ1Aww8b;bcc:Bh^?O(2<4w]Pө 3g1n՟4efn+b q2eCx b'7e>h2$m-+[֤}[? et?~>Ou뮉jgťx pJ{ ֽr_~mӞ?r*f,k'۽!i`d<|"?_,(x t෹--+0n?` P|o 0%5N D!V|@E{c]"G@c'T? ?|Aߟ)/.;t]MXO}>󚒒5]]䕗P n44 B?hX(>P_xEUvK_>ԯT)Q_`tT)YYpTx>dxAVuuce~bS 7jmDc#_}u'ܒtE?DꞬY,YVסCtV7O^́`~\/n6fnU /?@(WDHOv>>! 3H<>>~X-|`C!>Mv BHW Q!=ܲˣ9" b7 `]nY#W^.@Sp>@ AݷRlUH>|9shq(][VvkmTl'vLb[PQ~TO|l$,;-TU_g "@;kܵkW5ɗXnjq.ufg)S>aj *{ZUTOh ';w\YP_zO5*?ӷ 7q6v\JU2IIgxG_6>|=$*57/W]ue|@%OX_OIPn-~1(?J Zݡ]']*$wP\l%gPa) "~OmBҍ;w3~E\JD7z0̵n/kw^>[q9իm{ qf xTQXGu$tϏvbS;=KK{3 %OGa|Er:(>߇ḩS!gUT0~8YSsVyN5GCJ ;@QOYp(BFz@}OTQt?bE\ZL|?𯪢(aw)3^ O(66N:|x@cEŷi#FO8n#IlRRV 5VG (Wr:'Vt^e?({t>?we˶D5+W=4tB%ܟp؂3u> 9ݑ_p@?!1>gN+LAIZ; :_@$ 8 k/y)C>}W$x?ؤpB~ |Ø@)S PzØLbr莹ɔP1axA'AEyI1,xUT7?JҚIwxYPUu2$h̙vX % ohocHq@jjY?P1s(BOr $jqu3^jjj0F,"k̈g[GuY+)疕>34Q>nsnݏ@K9;( ̙0jⱌ |@~X?(`.*gaG@i0ee-rDq)Ѝ| L|A /&,X 8Qka;J&pi Lg#i)S֭d']k~bcc>guuoE||@/P'K9P mc,\=, V@gC MǓ@uq'nNCG ӷBτËUXC{JS߾?NFϯE y˿5K?eذOOh/ IENDB`Carla-2.1/resources/bitmaps/dial_12d.png000066400000000000000000000011231364475620200201420ustar00rootroot00000000000000PNG  IHDR s pHYs  IDATH?KQG{f 9,6AYRX$YTR-1`&`a\R%DBd-ݹ)FfI_30\CXUf2v/-oҾ%;s>D> GoM< |; ܼhM>FNP<?Q* }և .HJr ** eQQy 숊m n=x9/*rJRT֯[J%Qiqth-iХVꢲUQc7V`jMX[SZALآ5cIp83f~ޟ+jh {VP?-gn6` 1`mDi,hY0`Ff.&-FVAU)k.tΒCE=O!%Ns<%;t̒ &-4FU}[oeeHJJKߐFTϩNꋛ5(+ufQ/7Vj]<꓿jVՖd^CHZWS`̃KS_^8keǶܚʾK>MƷAFօǤœ8V y|@l56x^e#AWWTIc+6:jL C1TpgɡZݫ_I q73tgP+uy^RG~]OdWq zeO:L}q}HKΏ5tQA O\O[]v/ ݞF!.p6|;پ26fպdx;jvS) `P"A+')a S%>GoS IyǶ{6‰Z4֌v7-45ԓge ~40<Ş`<>^@0T ^+U_ӡX|<έP|a村^;lfWee,xR^ '9`ޅ%; jV/uqW3:6@n=h>ޔ~{1K:|3> 'X]Q: %3R|%~S{Qr{Y2A01|P [SaܪO fOo@MW9=\,#qmmmm6T!߲,)@zSY9һwp `zN=X@,XX4͑`}p/8'+@dߏ)2 GT$2 j$-?tƤ{%=o/"͑.>`>$q|h7X?.>pG;>`t@ X&{`?CNقo7䐧{nNQ?Тz=%Ͷ>O~`t@1S9jZskƻFL&rJs eP@ Aj|Ov@NiP4>eڔ>M?pp>`Yu@fn`2@__έגaLj.ӳݹ2$S[L8z*5 g[|X|4zTEcaʗ@b"qeezeSM^?PV9yo 1T@~]ӇҰK[⦪Y%Y߭@ْAƍ64ZBjdzT3x||:ظ.@Z]WjG̎XSe|ڹ49էW۠#~LH7\Bڮ LSz&Rq9oS =} ҭVb0>!nU'f\~?:ߊ' y H7 #\FvA2A#;3iԚ5(>iǀd@V4roe{d`+7@2 9ttFq=KGMƨ+F>pSgБl->0H':voB4Q>`©-hД8ݶ}Vcf Hx,Z@=|}{R)fkw4񁀧Ӗ`Zi/ j|Ouxl6Z)iob$x|O08mfd@KzR3@\e܅.X |`+Q*{`p{> GPf~v]v WS~`IeK ?24>РfZH,<׀x@"w/zJnٸd}~dUW$ L;VVY>= y f[y2=+>`ӁLrq(`[} ̽V~ATrMwp0+PǴ-~Xٓ6v;X 7.`m<>zwḫjƻR3; d q-Bv~0=eT;8A/ 8jQϵQWḳ o odZyz wlP϶mòMW׵Duaz/2Mwox/`聺@B\Ѝ~`9΁-^v/iossFF|">6 }oot+<Z_;@Nr :Qlk]|lI%Mܜ,XmZqЪ}=Ş*IS칦:0w֧7}C>[(s& :+>)[Fqx[ 7I] YcɷY<Z<#K;¦f3:+lh$! F:,U?PGŇ Ѷ#K@Vpa=F^R]Ak Sݫu\dJYێnJ&tK>EفVgN|dRdXMwn Y@loP>c;:Iu.ҽ9"ICk4k%~H w8WW|N},@z@|6@݁C:kRck"Q>pφwu rGn>>?H䎗Ac.-O՟a>35̓UwF+nWg|`'\m `pjQs !۶׳䅈NZH.QD*)|W-|0ZͭF>p_u>j9m{k:6>P܁aC3k}UhѳfnRK=|Y3}*Vof4l| &"{Ӷ59SSaIP?{l0ʗN-[L7)>PV95CƩSyvvr'L 4ѳ#ZhVZ 850q8$vL qu{IKD%"GNY{Hhg^z/ A?pFYa%<ebreU3k{m6|5>.,X88ɩjƚu P+7=Af r}̆x`6c+l|$kn[~cP[k`g?YzWC˔I_Ms,5aHCO{}# ;7}Z Sbn>p>P >pس[*E_%RvL_!1>`4>A%{NmaOe'ϒU 8>`J4@| 6>{>Lu[?3M|`5.0L5Ff>:#6C? eɷXtZ:/5X|@XLzbe/j1.Xj Z 2`hŇ>;ON-e#k |(KK[5daO>ЯՓd%쑜@#fZWLvT'0@o=v|՞U6 0.d#T9hUWٔć@{6^E#p`XHc+<Ş_iwA~ypXn jpuU=U| '59QBxP'+TC? o ~M;XցVv9 3k"xׯv7Ҝ_Ζ_Eҝ_0S-Og}iT8F!z a_ |t$a.>p+K> ,*3L>+>p*|Z @K HE6>d@g9<Ş/<Ş&[>p`u[?+|`4uGΈ$_Ms>p;Gr> ok?3OܝέLx^-v@V݁_z*]T $HN-2@h"P|~ [gV~fo~8$+cT?[0.0ډ[ fC,HXYu|`)H\AFmc tՌw|:&/CcgtS R6ϮVK[aH{~AbNGc#@y`ȑjk)%5؃B@䰆OJݹ$g_2ߧ#_ܒ~>@Ŀ:2 w|VpOL>H'V=-$ Og{~/~"ܙ~ c|||`P6GFϰ|O %|iԯmИ2ϰ[~V)~k bOS)~ g󹭽^jn}F*] *07#`q@6c)o޳`~YA>xZ{>+Uv5ݝ[!CDX|;|9x L>;=r  aigAѫU(/eJ(J,!A>pB p|0wtOXljSd \#@'eSpBm*/OI!OITP"7$ˠ_KvЁls^n0˪+QP4`yK2zhVO=8Ҥ'quɀNhd01J4x@KnWJ?P'Mw_j4Jtwގ2_@z6]>>l0";~7X &!.i>)lEO@lL`m`5O: v#V?<> ^$p<]%cɖ))Xw {-S2zKr&"jtZގx0G[?;|`<4w>Ͽ5ZA/G / s;Y7n޳Sk #ABh,{`fhJA?Lf0a=ߓ )> f@5OX#{-`~AYaEdzѶpiJA?PD L(3l`j ґ_[|?yd1C'@(]̀x }eGgoa~+{!y cm/xGX(>oin >a_9hG[xx͝@l^|`jnm*ۤf㼂ȧ1A#_yp:[-ml3|Y2|5MC˩vUHG~`êPsG*]8Ի ʝ#h*B9!|,Ya\og_Z|2_ ;tLޒEO@ @ֱBfaP77x6]|X8&`v{oX3۵pXkPHBf/?@WT{r|@, ֗ȹ\-Z|}L`)A)Q>@04a@B+>>}^kc^i- @f@&z/d-zI>p/LQjս^P>0G=3LNP sI!Hٟ0>d',I~,%ԋƤŇ&6@|QF X~AGp(q8232ȎdE2il x֠ͫ㥪o,Lݟpw2=uSh؀-x4ǛU3߬MS1|Gdpb!!‚v]Ҵ7~\ZeO5G&刀.55@ x ៧j/l|`{r3K#/'|%VI{@v(D' d Yj97FQ>̓U|9ڄ҅Ӄ~$e O>>?HG;2_Uwwk}'[s>_(.Af>:#6Ў4V_fF\>p9#ַ!][a>_תgs+dHދH~@^R}`.0m$ NJO+)_zL*|@ىD |(H"A#E>P?Х~|Q92pg[ kj( ),Pk #f̀ j@#ODYPz~nq, S@ڹo%tڇ9eENS@䏮N{Qda:*J6 M>,X{[fsY՟;}5 F_=5~$>턯ntvjao_g4Q/]*0~Gu|5͛"nb[~M {|y [se[닾Hs g}D(`΢VL>tۭKмqKP|zkLB<5XJX!L:_@$R^koSX!bcygF5O4LdHE"X؞5г y$/dWQf 4 E4iϫ3b3 @2.y?e)c%9Vɨpdlg@:s_5dj6>|7 ,>0zUI@|`vlۋZ[լ׶$iSۛͲ#`cBm|n/=$avwG !y0i<lflN%r/;Cy `L:XWfں7@A-mv~&>bC|jl2Uüvz)0Ƞhnai#6IO< }g Fz.꾖fb"._MFϚ Ty 91FW#ed65["G~~ν%V31|`ʭlJp>+|@G]8|;3=P;|`!Kn-W!>m苟eɠaڢ ?mnʈ~'#jY4.> nd)g0ԯoА~fk>8>2xKr @I\D-ְQ>` Q>pV 6 -aE0 rXX=̚>мx |B<> s+dHء[b< PW?3չ$YL|7Y`?P7}IREvy-<` B(A@jw}<#獝 v5_җ6scOc,CD?V>@] I>>}a˗O3NDT?qb|E6t8u@;AhR7"&^%Au*/[@ηie!7%u j`in4&'x g`c H.t12֯XuHk3`ܘ{|8 ^Q}6>n7uH~A~@񁖄Ň琦$!va:=̖/=v0P Q p1` ’%G_X5+'0w'F?p{Q† }@\̲ū0w1c-h~=4{0{5@,AP jI8f =zєbH#u5ìS-HԒ樁hjFdP|*Uwx_B Ww 6SStݫMy`ֶ~$ݝ#V?Ф@p;>`s^,@HX9-|g*'F[*D  `_54gA߿3_;s|# a^ϓ34>#c9=QWCLBK>0tфtٞb7ޒ+n_EZ"E> /g ?>0|'Ŷx8 |pP S1U>0T|@<ϒ;<U|J mM, @&8'o(N \C>/D_׫}g0@8:Џ4dddI"?Оca7^7Dg О(+*`4~;{1^g)e `#8\8)~Aʗ h8`9CiP|qKf}CGYRP  rkK?Pg F`,L5?(wmM5v-:$U8|5 xӚS^Awa> #\<^ii և7#OQqxa!ʜbߔ~'#|P?/Lw>󾚦X>`kwAdV&=[~v+,@lO[3/E_%Rdg/oLrG@ ^6|_wv|hs_șFB<McXb9i>`ݢo|6>@2|wj6蒖}=0Tuwo7| L}3]Eo-|R3Q~|<>p< 2.C\ggbA>Ŀh~(/ݝ[!C|?_Z ^Yx-Gx#˟L@l~ /;)}{լ@9NZ|\?l1?܏C &)&',YsaWa֠="`8z" )ޡM7="*b@bvh vΆUu+餉d? V ]`E;ȡ﬚rZ6U8 hشnWTp_*6L>y5}n_MFuCp#}[fsNȠAn|Dlp^w@  h׀ɬ_Wf% rP~Pn٥<(]>2zEԟGB4:f&^a|K~XF+ +鸩yC}J|>||> p >c~emη"Xhc+M`>6XӽYP}NЎ|&> 9 Q>C.)gCe0:|4U6>pB>&X  /,>pl<>x^ 1?->pz%>GU}C A@ F9~J(^j#O߫tA2y;>'@L >ӡO}祻soI+ԧ8l8qMM?h~^ dD?peIKB>EfB?[ۗ_?)h|3F4*X.b͊7|`oBDuTS# | ֞?p:nNF|hLuI܅,ߩ=Fkjn<,ʶo& ?@]kcJ=^L:2`)i+1OXߤy/0Y)>7`u)>дVi./>#|PVMhӳKwVȐF~/ >v|KL/ |O8.e'9 _ Ks;<ФCF6 riZ*|@> Gw+o\ҽ=€XӭCM.eCX@l/=@>lav \ V&VfHRBRYr+L>b @A[y"48m&D~0 bsլW~LrkfZy)|#`ZSjb էX Rմ9QM?Pi(6eKni 6ᧈl [|$"|Bm,.twn9[}|5ȫ2[l 6Vӓ>`uX-ɝv/=(X+4 3GtQhI7h_p6*s' ^) 8J7"uuU @ߪ GW |h~G<>G?{-Kl)vDgA֝~ \h }]͍=Rx@6@?-z S?pr<>p96+tĒ^Ƕ"h0/xCѰe+|Db|`G4\rɄ!@E+pv m[ |p̠sFz4m>Kʗwqլdnﲊw^H`PW@]o(:a&3 !l! 0:u'Mߔ.PcO05o>QюlF"g'Od瀩e#GBbUqd.V_MF[CF-v~x@K tS`D~Xj+8?ݝ+>0\:Y[+O/(*ԑlua*u5&h.]tpw| _W|sϑ>  b3>^K~8|R 94{T(>`z>pXZTcq% /6'_HuN}|`*b@UP|i\E]}N?-4JD'8Wa.C|@ /޳cKvM?$;"y59eL >j/gs+H| k{th,=X4y<~0$jZ6DوX5륭voo$hoߔrc AԽ,Ż Q/`CM/C#8* PiGdliɆt UOR?`}Qԛ>"OX'O"gNtuY(Oв?!9doK2;f~31|ӚmmWu.L>R 67~a@4`qd5l ybdJ?(?gd 1^;>0+|`$t}HK?yyȶm @G@?!G$s?1X(xh[$y>p4bnH\;I>p  @;6-NQ| CY"Q>椉 `n?;T<ǰ17a> 9tlU|R#6gjt|>ƕ.<0Sx7l92|>at|mp| uU /%ݾ苴D*|` "V?Тd@$D%>^7 {Z G㈎G+ 8.[7ԥA?xx4v(QoBx|`;>k?cC\]s|v|;@`jsf+ܐ.>Pd:Ce0Gm,3ψ#C$@\΁[>4|Is#8Q@oa1 Xބy@X%4G/GsIChnYY]U3V&| H ,4FAom+ڔh@T{4W)u~@l3txmO._zܥI{0d( 2l7d8tA՘KSVkE2.ңN7d- ,Qt\2vn.8@`/p_V<8sĎk m@w|3@L yU~;r1tw-ɟR>܍~@6.M?05af7~6˰f>0?nE5P|>@_,#E>`x_"|~ކ7L@sO9{ -biLClT VSyěHVr*zxs>J?`~ZqiUP|:!QB~$xV;>pwu, H1 =0A΂,G"|`>ڶg V*>osbiO&l'O?p…qqU$5{6>`b'3RP^oK|$,>s8  ="g>b kigN@v?9< _1 d.`lB(U>} }-(<` $dnN}5 =FS?@B8 l bF=L“@,^Ľ˔߭!Q=H/ ,00@"GTr aԧxrֻ'<_L̮-?Į lS @ "n0gX+'lM&pG?hl:W<ݿ X jAZ6<]`ٹ"1~礻sp|>uVA0_ٟ0a)u|q;ֽ f{?E|`_6$}ܐ18| Ԭ"zв ~`&gǾ鸭'|jh@A_0M?|-]`E4?y$0<P*|67~-Y>0}r>(Q>p%|4K?-xL3x(hd\ S?aiWz_ۘ)>L}#>Pz ݝGf9ϡ!T̈́|< @Oާ5Uۜ?apڹ/H.BΙ55f Dԭ ж= cCnwp"i4N' &MOG0J˖Vh?pM4-45Zi9Y+#v![ 2FX6?#>`@E'˦9ض7i Ô.U$$;ts ֲ4}vl>@G֫';>vjm?Kw|H U3ii6~ZNLqJp=h_ l|!8 'T u R#҃Aw~v 5 cF?0S|,sI ga& {XJMnދs@FW nJM΁[ח_? h3FOVIAK?XBpĺ:L"a. b7q{|`bZ|.,呈'%I@!*99‰M>`]7G~I$ěށy; `giGAX=}'b ƪY~:U28~Gc\z¥e+U h }ް{`AC)$#Ե r@p*Z *uWPD%A{ h&d0~Uqgzоn9E@hm,,D[E}09Q]a8uIZ<>U3#0*¡Uz.aHyN!~,ًߎP}õsoA,}bt&W$=U DVi(߶9d|~W:W|b1|jAP U~$2_͎vpk87n⇷$ϰ>hup:w}&Sd 57%>0S2z $hW@(ҝ`Vx \@/A& QAc[t4)񁿶_7F}#?AK#CN)==C|`*ECe0Q>0#| |$3vY5ֵڲ ,>pD<>`=ݝ[!C0Ii &{' 8fMa5355?|Yynpd 徲#z5i?.仭+S8@a:qk\[Ph0l(߰l/YⳭOQh"4F/ W}F! ǀk4M^;=Յ<af=W 0oe140ƙbSlFKOW5Tu6*s^P䟩(_vơ=~ c `6uG) n@!ejU33m^J3s 5>vhf d$=ȁy&XOa#}-@B|*4癨~l|#O6j!/PR‘_hyEؑ&dB?p τROU S _m|{|`w@nYF |'`SUXmx[\Rn]BG>6-ۛ7IY?0 S]mE]Ng?x|P~d|ߔX0@ ?ڦSܮ|Os4*ro<sm5Z'Ȃ<|i'KZH}CcLS/e0-KQ =`ʽt2y S>p'T_w"E{hy Gl#p2m}NOqλU7'g (tA#Б!\Vyf@4LJU3M.(^(>p cu(e#0z@?"GU3R 0JNt2Mu`mmS.Ⴡxs l`p|FݪYb/Ƞ _٢@2Uf1eۙKO |0`Giᰬd=_`B% "g>taLuގ k*8/uImtY^p\N7?(ё9n8d _| ;>pEe9YF|` }Sv 2O? ='0L({~c{p:>pLa@CW|pD@ U>`J?P |,&XL> .jie;r LgA;lܮ}{xN|({GK>S*YʁZH3/X:gd4ދg4~HB{\i1|pb5cCCN)_t=4hvFQlܫ2ok}GoOB,]cp)i8Z@bڹԣѰC 6@x@x_-94d$T0wpՌnjI@x2>qtbvx}Kn7x߃Suv Cگ|'~l=ȹ2>)y $e:'%/մ]5[|q?Ҍ@@!k @]/ @8It&->i@~X;TEV G 9dXB|" *)KC>?`5Rm| :$ 0ϸ UF-Eژ&*ݝ+0f;l|`]W|CoIޥl/"-"0(]? >PH\;0->q(l- PwzfJ~|@*>`L:i6&"V?,L+m=kvN?!.N,̮R| ț6ϥ 4+JYdșiKf01/|`:q#SIh+ͥ(`)nsij78T|&՛NCd.nPÞ@inGmYpڹ+<ŹG#֌' =5xKO`3fC9>5k\@r@zPx,X%J-hk<=` ^pW}?0;jNНb>ͬ-M3/VW<[<5 Z1Ţ&۠|Y^MG,(IxH !-.LPr<7iiCH r@wv>@ t{=$(Dģ:``}Xj/ 7 \-&eovt 0LtTvpdzA>pk7|'s{YF*|`o7bBpg|jwrZ`΅yW N)ـq9| 5$ī8fYjh$直a@<$ (ǞO5'#\ui۳<@;O#f=cUVmY+Dxؙ9Iw^*g ?m|t'{¾mFJ?}rAcC6Ιȣ": 0sm' ;t6m]igO*r <ۑ_@a?+^zⓇ&7o@ N! S* 8"+' &<ꯏ 4# GCǀ C :Lu3 9KB{JMX,a_,ʖ6<NB8O THh+t҄uZX=+XqY@.`o-jCVXY`U*Pً?$\fLkh7 Z~&` ?/X 57zßвmo_,|1X }2չJFo;Si25T>nM?P:z N@$ i/Ӄty6>p['|`m苟e >{lb ,ץ&D ?j[+ <@_0qbJV?`!6%8Ö_X2eG?!.5@k|/8 >4,>`tV xvv_:bZuڕ`:hryy >L|f˲iͼ1&k#@H#N*OX0iɣ9dQ4ito۶-oXYzN+o;-[]S")e9Ց#p!V?UJ Mo6̱ZaTЁ.-BrzKo?yX6ho;lIoTW,O>J?0a_@Ƹ%Og $ x- jҜO'7缣bA9o"G΅@c`hYSYd5B\5jo|@4] Z@+ =1>NdլS_u _ٲ?YX5㙤)f v}b=5&=o2Q jU~A}Gׇ.iҬR 򁠝<ƻ>m"g^Zz]YƩR<>C_!>`zV߰e `bC2%}|/~~,rJƘ"wV/@76x:%wv#| y2SoHH_2|Z biCIKI RhkWlKRٖ~h~`59r_P lx`pYmK/ `Z|5?'kp֠PcȐAmM^jwƀߑȓ8҅eӝE܎zga rd|{ޒX`پ:H;Ql[Y&->}p`>ph6 bg@x};UESU3V$}#>8Rc1y9]{q{ox( " <2agg~ڲ|}CP|h|`#|[`MYic'XVyǤe=ʣv14s 04wrmen= dm?#]@<9oGB\?abՇs^^H"V!zF)먚3+8jO|:iI m:8a 4Zv/|i~ria)tƱdy YO'}P| @&rLSp^GF/z 6B_4 )nrx3G|`V,F^W!> O10 g/3K|n`|e@?p %&OHWr@_<#@XӟЮ74~}X?@kFrD;+ AM_ ŚyIA> 58bc6>L~AU,j0 %:kkmng|| tYZ8YV?О\r~2ZxNc6>0(m&=ϽmIgvl$;Q'5olpg^e-[;t [TD6+z vd5p'hyl3'>rFB_Y|`6Ivj{@.ia ٠`Y婧/;WK{Ɲo.a; =@/}~[9%- 2 -G ;s\+ WQf #q{LC9!"4*d&^4l{ʖV @$Z4>t}ժ+[+[BW Z-9Oeg$WS.HAN>zi(FU3jȑ7ptKH% Yv˷WW<7i H!fEğ!8!{+xf3̮H6=`V|[e)`<TWJ΍/QmоyPHh z S?yjҰr|5u>yڐtߖC*DG>`h& -x)Ny XkrF_=inz 󂶣~@nS.ɑ/3?`ԗR+ϑ xkȄ,yL4)>P-ɿ$E_%Rc썘9Ktw٠[oGp* ,,t5=y":TMB{'\73Y|%iMKIǓl58JH`g;+> /2;M}os]:\E]v>>0ޙ/Ԍ6!#u%t,'<ښb0{sso>y?-` F/;UD'u4rI ;bM[} Htm?pW`]_ AR9&Zfsh}ej0˰lGnNuQ'^ v/HeX²/_vƐ @N!d@%`P:p t|-[r˦S@B{UY="wp͎uh܃.*-uP$_Vy1CM8>XA TFÇt9/^F=  *L& 0:v3e , ͷTq"o4T='Yp)zD8 .`@/z7#U3xlx$"0`2Ʋdm;?")U)D [|? ڧBaN|@WSQ|}۾PB}Hds¼@yP7_X|  35-x H |Պ3_5_s@oj`ȗI/Pwd3NNDz@ ;>pv&s)2R*(Ҙ P ]6hI|86gDe?\h~A*ګ]q@mHJ?0z 3?i ^ :<&8 >phsl|@{>M94_CA]ZJ~QuFl!:r^Gמ'Ye,,{؈Y|@g:ryM) T|Y1 چIhϚK<[Ro(Yv=Zџeue'_1eGC@Q6}r˕2p?k>aaοUv{EP|J G[OW+V?xot%ۖY@ˬWo)_:#UO:;(P| /zn];gF$򮬚,>@P[XoHƟ0X>`|na4P|0 ?,9Ç"?F_MFZLÙ.n\)/5_$i@$"}I-)<@wF>`vWK?r.f[jJ0 ;d{?7~h#>-=$}5 j/"-~ R|m|L(i{f~AZW) ;| ?5o؝ ȟ "xL?0ڝY.>pM? Q~@ʆTg`~K17~3>OXpgqѺ/_~Ks{|3b N ' 7eӏJϘhq'Ksh7Kye.}uB:Dޑv昒ag_R]E~F,"&< r=t໧?Q!7"*ZضO#K@Ҧp֝)AxVGzmy_]a4cbuŲY^@rppZdz~12/p`_|X gXSajEKH~`L~[:|}M+ʠ{!z3] 5YWF-0ʼW߀v@(KYȲyA|ҧ-"X99_ 8P=ɰ 5TVW?L t&*684dz6>`lP i~lk! Evu*'F[%PVұ>;g @ MG>`4Y^[8|`=U5sz\@BS7 gxs={#uf;κ-o6.giַ:jR9P핶s|`6`^5R| ]|`>LH" N'gV6ļ_9(EޑgrXR!Isg| *쎯X8e#?i$HAgASU3 :+l|Vs|5uQC)kZ`W?PzʯSưP}e@]xK:͑? ,Gᡤ([2ٸچHh \ bκA;?;A--9INs+d3=^5moYwAY ӧ]ldݷvӛRxRzm Z^80Bʞ~zZy }~ю=$B;c? nޘ8ۑ~On[o:r/ߠjSʀjzI6?S8-nMKukd P]OOJh Qx|^ѵs~eQk"Ik]L)Ȋ6_;\ Cv!a&ta"IKT?D`l@BEe0  |Z!q>`FgCaO}oh5]&G vu}W?鞪u:@ A"|;>0uB:Oqٞ5ޒn_EZ">'fyboEK?6>pm(h~HQ%,Q@k0&XI&XI_=SXm@Q?3Uul+z>s9lsdCmQ'T8d9 |/HxI7W|`O\>0r^A7|O_+Is{d K@t7tvf"tqْ/쉠ZoR҈d+ ǨѲ lշWkN|G m$4]-809oEpm`B#O='!~,XYж5Tyr=(2*8b `N 4O4=Sp`|+w.9x,,:"O,0{k֕[bRp?LV0<{nKP>Pd.;~mV=H˹ݓ14egNO[|b@ğ;O}K~׀_3ـ p ]$jc-?prH~7 d@Ч^,!s%R/@ `η.y³2/.6\3^/pZ|/ |LC  )_l o@Btߖ#PGKD&@=x._.!>`b5;ne9^"|@wYEW{ ǟ| 6oĆc=f~WSߗ_?чYh!!vg:liӭh[hF~{MOXLJ|fv&Ihw]|JY'EVU mý׍9ϮWh׽t\`W+SH o8<{xe۔5߅6юۇ^R& ֵ80GN.҄ B9Hslg#k.ߖ yF ,$Mz6F 'Qjn`ҸzO+OѲEs-SseyQْ L>+zh0มi.k>Or Pagl"U~='k > 3Tx,z!uNoTVy@y.>"g޽jK6(ڶ5 XoP]U fP`yHhüS˜h}6FOnb}#!$|7?y>) =`p96wڹ˷p!2(dwKYYIek{ r٥`ꋋt˗=ϜznLALB.zО|ۼ'Sy#hd @ iL.5#Z-'ho[| ;{E| ֬ou]dY40VL|@\BO1Bړ(]8‰Eӌ66@`^?p]CI3 QO$qP|e8 >0u#'g{"MH iNsU(>𰭾aG>@Z`av$Mk3ێ=>P|f|G?P4|6? Amۿ'~,@Y<`͙'X£Ik'B34?,Ї>_<@f~ÅԞ ) DKS-jkoT]QǑw0@'+JR8?{DkqVkNyO[ǧ\6Ptք`'##w6Xp˲R fiA* t}s~2I A\PtvP'^ǁPy.XГ,UW,DU$򮮚D|MX|s#\m}RP S58esNfE=ŗ׽֙|9tѴ <35-p1_͟dՓ3?Pt U uFV6X*_o7_S[\>vP@5`y7|V[?pH苟e@l~AΚcUg*`)'>!7j]y:hXU鼳yî]:4Tdh㯭{|vս;B -9,uhO/S:XZomi]5T߶)Xq M!`8,p{Bm ܿQH!9 ]I,~d3@E+&,F#,䠺<)eS<_͞τ3\@|gY-)y4@uHȻ4dtųF: ;ؠHޒsFhRvo$olҚ-[23eef~ F͟|#GB Zzg! ]3iqB_yKlYahpnmT=nMAj7q 0^1 oy3U=gc@0:Y6_]tVJaqoΓIf6:ކ˟X6rFRz+Hhod(Rg~mX]|9Y-UL>']Z;TW,[xm>5g]VdƱt|l| F|SoeG-d Xy9^puIzN(ۢ=x:Df҅~`dLBWS)c ,)0 ; l | o,]?` I~UTu$in3>a_`}~?x$IE~5sēچ<{fֶmyw?>P~ݵ~`巺e zS\ߔ/$}N?D39I,̺2U X> _fpk.DB@xp}!MkSQև|&Yph>JdF/8 Pƻ֬F̀PUQTf|>@Zh1heIxo4ʖyAPP5ȑ{sSVyoSrB4xS?@0 ކU3 yh=rƌTAB( G̡M|fGnKmX=gsm9lYg'?vAM ɜ7ti'֓sҁ:rFRj}NT|K6y;G@8X;w{!5dohM'/;7ZfOI"wQ42 RZ˷&(fzh!tضdL6t*D$g‘yhFC6jlo{9+#8Ўb`%|'|*2w gS2_Pt #@vyArq o #|R[~A"|˞Iw}ÃIK@_"|@7,~>@W4nsq J8w 004:tC)tBnhg|b|͟01>01c {Pao]  Ǜ ׍ 5@CywF =[W~t}kPp >0rޔIB:8p4ߖUN\n,Pvǿvzh ʲ%RDT? ҸYWx^l cnP*g PUEwo#K^ з 4CܗMC\ ^lõsj!Gmfַ@в%g|ThYbZ{JjӪ5=w´_LZ<#);X>@#Ki~s*YNk='y>`a,ABi2tz~$UYE"gT@~*,f&LJ킥zmG)Nia'4nh>`( o y7s`:Ȁ+Sl۰}|pkԟ0u] S|$wu_孼Ûp=!>𤯦t}H͟0s|`'֡~AhDU lmjt$fW+7~P}rqC?N@?`.I>9aWG p`w`5iG|w,ߺC[2! MtoWVx.cf[g%* ׉y$)~Im9u`5ܲ_: u*g{K O;QW6_2(f9M#u A_JrM> ,>y~k\o/dS{pbY-fi̋{" ne&DzL_[ %l/P뱖{}êY`#^0i--[24ArWxyQW7ڹK?IDATW1:@M|"i#w _PۣAYs|TW<dgթ\7*8/{DAZ,r_j};ءf(Oێ>4P-KD vYy9:"v֔3^̇c{ 6>Pw Txܻ1Qtn|EB -R ᩬ[ҼA~> R| Uzh?(R#)ll!byZ &6>@$υ{hk`s.F_nvL ןPJstL X|99b릝M>`(Lfw,&K?@zv o2`N3>>?H"~ oL~X|&[MB<>Pp`^|؃ ֚:t(5;n6= Q>Љ~aLB,7a>0^v 0vm ! >#9><*GüEg(=QϺ,J?xޙ/pjAI=8ON諏(w `6 59.%{i_UVHv̋kM!xhoS~\@<9W|7\r Z(FZbs`ׇrdtz[),?ߘ-&xHYufQg9  hWlaՌǂF@%SQV9'iH_n/@,J՝m\5@)+!w kzo,Gd=km%u>Q>"۶OMa:XpIUH%:l+؃{AWJQ%0 Hf># _@iw:q;e-~A|>P{#| .a)`tjfUe2?=_Qko *6艖.?q.f:3`grӇx]h;[#90&a篭KӚZz_6}5?ݚL> yYi"ݕ3Hx5[ޘxYؖ_0Yݥ?a%ui#l-;qtMK8%ɞ!;YޒtQÜ`68jv]y¼3mߚuB;>@qCI ,7&39I׽R|V2_Y2]fß^nP51s07A|@DV8rs~s| ^W% ))m L P5}um5pb@tWV9TvEX4~D d>9rn`[f/eE| n0/tqՌhVj4 ҨT~jY7vyu/џ掭IY+> i/!Dk9xR pt|kLZ&F@!H#}e%Bլ%ȽHD6OD[/4z= 3{`S K cgW5m9`#R6.L>J$|@L?*5EB[曧>c@,9oʬt/%+ Yo\f}+j0ދ\m5=m2 ;/H3/苟o(>ן0|atZN 炲IU֦q:7/X+ο%{f/Ї&G=]ca |㚇Hؽ]lYyBW@|9,!"s ter ro]UBQ>'lc\?-fsup:4g*0rnRbG_τ3K&9)y0_Ȏz>oްC\+!3A_o_ Yȡy Y|݁䔎:Ñ@`W蛍w9M}+_z!wo>@Yj=No>P51 ˖_&scٹp1}m5770`$km[u ?jǣm*/ATe( =rWWx,VJ3_%Yu(4V|'ɣzUdpKd d?ծ8dEvȹ;ku76$8Y ~A@ER ,DB9 SAgvRꟿ_%Jj| ?Cz`H `@p/y3.<*%םD"V? >,>Ц[kj&S0daQ}RZ_W|hu \7/Pܑlͷu |F>6*?le&S=}|/~^;>p(;V@T=#M5_T֡ ٶQe6#ZC>0ڰMA6,> ¿%~c>ȡby\MO.zDv ]uu>Ae0k`ޏв^gUoYY6> X!tY 3_Fl5ڲ/Z8x CNd Xײ#k`+ʟ0"oݟ02뎞,_2oMl;@,~2;5,(\ hz#ʟ<$A??4'D`':{"|a/]sxp~if6㓝|"=΂@"hgQRAU3v?vE6dzރH}CKpYB5ʟ<&ଔ|rl -o$"Zov/I,$Qj#/`;d)^|a,/mj#a_K/~@|&C _<4XRkVHo[(>`7_g,>5L?Pՙ~Y ^_id" pM?ז;_Ûyg}|>p'|Y`GsѮ~$1FŘ:X'iڡPG=jlD9J?lB8_m;7?X9;_qbyB|`˧kku.2e*r{HF֧.?0Yշv^ ܯ%d:bgѰ՚;4ռ0;sҺO b_0=,S'[\o͟\08I4P )!+lz 8Ԡ=W#wIspԨ5>Y%/ Q|3"{Bm뭧7BZbmN9=6> 'g WGT|po6M^aD@6`B;N û$Y/j$DتUUU32$sH $V! HYWZ[mӮz/06uYb L!8HkL]~ 9pՌ޲ͷ*8xsNr| _l]GU-<;0SS$@"o!Fd_[ +z ?adL6tӪoh͝<_m8z\:W| 0IZ Akk 53_g2_`#`, Mʟ%>w`Z۟(p)ؽ{}|/߉v׶4iC~=_P#r;1^N8w?ϭY:Fk|r: :m|HL{ ǎ7>hWn"ݳbIG28>Z@[ᯭKD?yZv_CO֕uY>U| 3>sɪ8r> dk%Mw$e Xa~ 7fzKwv>anMsHmʗ]p?_p X.HkJ8XGn]'7 jIx:.P\|뀶*/ L>yߨHZs('pT ?)O: ox3<<Ս/v{oQ˗?8]l7;O9v_uV&TQ@p-W',(#-:[!)GMB `9coN,g&ӽlL̆LTW~ͩxէhe>16l(>qR.bS9Y9EOswQ$'O09+.@v K ;T >?tWUt=~t=|C_h nB7{Io4# lKN#^ QkI|7dԉȔ3\: _ T3½,,DōL% }eOؑ~_>088H>IHt˩o}jqD3>L®8t9MVr&5=M/8S {B k,]ɜ["O|`̪Ԇw-St}zWmP3DAβn_{a0*{-/iLgK,B(5C"_yxQ6ꟷ>+D~'ƣ:uw'_:u#QC/$ل/\7r.kud(" .r /h͟pe_Zl'5odͥ=ˎV֞s;B >[1CTz~u3^`XD/r+DG >'46%Us/صҫ"м~?0~S~~@q7F I?`/a~D#n| kqH j-$s;/(zMݝMKtA&8wg\ͅTi kz Y ͚y>&5Xu4r|  PP  ~@M j *=L9P&PUO~+i^|!SL~ ? j.}c_(}ϴZJ>hԬI1<|a>p8~ >caU Jk;.Z]w^׻4%[ߟ𮺃v*%~B͚EOX@fs==SE9zJ8X6Ik[-ƬA&}“ `ze7o$wTO B@dVHJ$)P22OVeyq}Hw;WsBZE3;""A;ȞPyy:kQ]90/_8h?oy賗,.ϗVFNy:G++mn<Y4S3$X b̸ >SfFPwS&%Tl ANa2?ɟZZy_n)ϛI|d~@ѯuca/FJ&>]H{؈1QSJ> 0+`kU+Vu?Gƺ@*]|iIGx{~f;t'l>+s:qŊR4՟:jBP9nOO(|t?QWƀ1/"cK)R;>@$d n.kF:lB?SQ8 {JS] n}&0; E?` rn@a gE-ո~ O8xO>) "-_j$.ݭ jP$jˊd[?^>0s.#~e=@E#]k |Rݡ\|ʍc7Z/ vX('vqRNT)հ[*>h~AÏKVo 2OK{B?p $Ž}!ܔPA!L}{'f`{ʆ6o @`' Ss !N˶_ ܤ?L8|]6vɞ| @-? ^L%n>5QodvPO.#\ã!D2ψ|/0oK)g].%QPQWZkۣbZ v{ŨT/KjĚX۲w: ?`K?0jjr.`sS^bg/.Dp!!X{S;ELF>}rR '_0 NF).'SpuQ<; w73z8?#(a7tua= ;q. uh}QE] n%Jh4Bs:x @!g\jt<% @Bo< RS_'<|:H' <uU{,] >x8GFW/H3 = 㹦T~Xhuv:>0xҙg)ٸݞ@SY-> AQ |ktF?0p yԦ}wܹSnTHH{+Vgt{G-lfoWHޯ~5"B1 OrXTWnTw{EvIā~ P4d# a#ޱOV@e l-smucxhuE3ƞSEV'mnS,1GJ7ͭ96zh&Ws}83SC;Ūe>j0*f7d>0_T* N~B5|@wpOx_ɒ{ZVy;yIQn?'|3qwAIl-I1/H7H_krj췜4MiMLs@* |ƞӡ?! <| 5X̟JUS>I \#&\t!K?pWˀY 0pSso!V?P2r+ |$U?p&eA܆WE} gBޤEƦџ0d> Vh@XI*'^ћZPsCIhIp[U3@TyK7TV@8DNEܟM>#I?|`KE' a?!ZU{9Q+oxwc/~AΒJ@Iōm/¹ޞJ^%}a#B^RJ v-ee}ZzcRgd9GQkDلbPdZ4q5O J_f[u+G  <ʓ֎*U?G!Oؑ~`}"( 1[8M;+;'Ӳ|/f\pZ@Xy[) ԛ-`O_u4 j5@hv~XE,wq0f|?+$-?zU׋$iz un`Ќ迎H/l!3K`9)pp`ٓ#|`,7Ufn>;B@a#) ?P@&֡zQңv#ݜY'B% TI)} yyسXsBy?T%AB3ic5$, ܴqBvu~"r&,%LaD\<Ь-NprƤXuU\7,>r `< ,?z)85G):u1m>`(6&FLA&boG?pIwS&*Ϗ@G:mg_ps[SHVe mcU%"QG*6[z[C 6`: "΂ ER> {Fܟ0.HpI't?Bwx:?Ќ4mj8l۟98SiGhA@۪ S^l5Q@)24 ?1 gQP}d(q ]ݹx >@ tIL58Dl@͚d3 |'J+>p_ jܖhCŸ0) -.>s{~~6!9K~[Մ'd>TT=h$082D1"V\d|OH:/uj)!v̼1>ޗ7ė,>NRd 8WX?PwI[ E~֗nY_mz+,4{_U$s(:3) bDo[髩-m̪[NUx 3MMn_&%?!J )6{I;j>S!qbq> @W她DJR-g@r4[A6nz|@j@ J&VN] |@b>) F<@K}knߢueg^f+_DOUɛ5 >P{sy MИ0fj @c-[ߖ=/}[ѼT>o$>5G #Ftև?N$2\Lm`{א`q=p?!0pO/P`>3pTV 6M{ >_nrx.НG?!& ]/Aw  Q ~PpapI (H%Yoi4U}C ӣ{I|UgMmU[^l \U ]xR _C?K'L|f\\S)$D0MZoZa$7\]ۖ~cimՇ.v|ci6WکBi ٘&>02W9j[ zvE)/42ծoΉ$]+7f 0.V-gd8ȒIh濋', {|,խj~ zQ ڙ'/h C"w=(_35/Gh%56wkGs Ba{1y2s`w*WE;a3}C5;rn+|o_?03<iGi]?EEQҳSm'5m7k}_֮H&, λ\ʐ@w-z$Tڛ?L~؎)C7y|"™ሒ)|rOsř'1f|^=wU\b 3/ AWBOa7rf؆'Pr օHLWOhe^ Bq|&pqWL| M&se)_@$"T  .+rRf;I @~/PS/?`*"iiZK?,O6j0jض`:kI В3"/DZ[&V.8*j,4?>Rp[ae{>PU}>91t!ϻfk7^Ư+ol/8x>Px9*dr* Hn+fq_`SNy|$"ٹMFd[PHU[MV [O(|@+7W;<F@ޗ7~͟w\c/sk l;IK9HfY/i-k.; +3vo_8lV~ 4-?XA;~ huE3.>S,jbU^m+6kuډ$>`ZT&\ǣ[~{JUv6 |%B?Xulǖ﷫&vv3QG?`/8!5k7X$`LgOgA@Vy޽9$m5h"/$ 2g,{t<@0 j f;oh$,͜ >DQ"!_  Zgϰ`:$ev$BIp@αDn#2y>ܙ'(7TnV$rvF;t; Gtp;7"9C" >%9?N{A;Jл.t/69"G(ܟ0LN6x5ɨ,SǦCb7t$xXuzXm?>f@\WOx_X'63V]ӵc^u]cZ12 (pO|CUI<Ԑ(@ |J$eМ-'Ibg /ceXR5h5f#ց9%ݚ؉b@\:#$K'< &s'72l#_uS2+]PuݗIN'hس15Zt{l/&oMVO$fs{[?_X>g<0@?pL5O,7bWKsFKm>0< @7*KxU#u5^N4sS,r*M {Vzlş~uڎ-{Fi֤$B*?eTtMPS3a/h?0j~5[ hfK g/~K~A;m Zt3K_w5u(w60;*!"~PJb㸱gh!R˛Q[!@8BB97KBZ4= Bw UZ{FCd".` ώx   MgmmX|'޳׌%A~Ar-tÔghƥǥsp &% Dby$-{]oЬ9J+@/ %m cC |ke2V@™i8t5`Ox_XzȍѽpS? oݡ q樽D~A<ً~AW=U%w*[!5Z'%$듛?>P4s*5ZJ֠հ#ayLW/ɇ|BطrTZnǬAj.!@µzmוe ߏ/^(L+"j}}*B(Ẃkiw}!L͵״:D٢dLdv[JᄷsVٌvKN+g#׍2t'*.%ƽh'"$%@XZ~-H j"' kYN'4"@@9c >d),>;@ry#$|[z?J?o,v(/oLd9= Ҫx?+Bx}Cc;!ow|*?a  p8v!@ O{0v$`t=='^J–|@Q]F67 t ;M]p@ьz$Z\L8E "VI?s ӥ:/+\=79ď7 GVC;jޱ#_|f\2Hj*nrxz-S»j;t~gYM '23wx ջs<<ԞrAόF40O d/Tp 7VR8PJyOvon pL׿uk;}`㍌^$V̈́ {ej*Bj'ra&>@)L&=w >POn+[N[| ~qht.=s6`AT@K $A^_@6ZL"Gnv;E.B yUQXgX!=|$f/rF}tRF-կv:zO3hJ(M|,>@׉mc->a61giO P~O>@sH߂pH| i/ %+%vwh?qR_POHU)sR/B͗|23%\uO T;>tY57 2>9c9T|@/ A)CM~7UZz']_t'D?ز7MxR~Asg\Bq>Pykx:#.jZl]@өT> q>@;%JYБ\`2@ת;:}qG9?ahGX+}E񍓆*R|J dg^$?(3XcE@ X|$#ΙfH:pv $EܟP望u~D$ aNY5%Ht^BΘܴC⚓J HDt۠ې|dHP/8CtoUMzn9/;E3.I~U4(KR v!87׈Q߰ @~->-I?T  WGͺk4/eéJHxW}EueD5Tr@+%8H_sn2o&=KFo2V6‰DΥXH`;@qHKNJB?Ǫ:#3*=!o\ٯ@F];B?ཹiY5OY2hz9凒 `?-u Pޜʫv8ky@\՘oYn+`KU0+"{j|YH?e*٪oUo ;3dqx_?_X/MQ;ܟ0ʙ'Tr/`<s@J}CRD0G w?ZUƌ8s3Ќ0q:zTBto U$iқR1+3Ncv>ӂblRfm{kzޘ (H?'º{ &`F'kB?.y IC\pmWw!`Qe}-ﺞ@7 H0!n/v=aeK›2cUs8%b՟n- njq$Pd\n*=ז""Ÿ𮚃/4S&78sZv9mD~>w2|)Ij\U(& S~bъAD cjh13>ZT}J\X g'o;zmABZ2/sH~/@_ Ww_0T~):72P|$c<7NFR~A>kG@ԌzP;|'d@+ZNLc@4 p'[V,>GwB\ZWBG|4zw /-؟:IGCm*j?3`ګ~g@@^GQSZ]j'҄49:6L÷ND(|YH;ot{v\It@PϘ| Js 04c%<'N  d$"8#5e LTdw| ͸ЌLqe 9cVEss-ZѸ򷻜;.X \o/Β%݉vguT&d%“Hdɩ"M㉯uZ7dVG#qx?qI>;g>z炘ƚ8#oJ L=9`iY~-T>1%`Mv0.ڲ8r)}5UPyu~?a~|@L՘mY˭~̪ywXžpCcs5,~E mUw_~0LS JZzRk6~C\v^nk|h.Lʐ|ljg%$y{RFs>(-ѷ~Ū6t? ̃5=ot. X. ш!:{J?( }#BdevИU$8B ɮQiym=|mH'ds17|*~mW8q>İ/$DI *2u"4kY3J&.qYߐhYoV: *( Xoh8mnmObA(`M_ |@ CT0~AHo}X[o7i@z%sadµ|/{IҔ_]IeK?B\@X>9X3~=U}[C2Wޞq@90/ е@|DžgܡdKݬ[FON$ʘf%PRJ N'N/\cxorr~A^g|hF;|4g4vPP:qxgm]Ÿ @~ ܟpݛ?nϒ@w⧴lpf_Ȓ1XH/pֽcjg4Em{9>CzCxt(T<p5#Z @|*lBv(5O>:rS7-^}ƍ#3M{IU{l4e_)CqAywUwx^ Zٮ9Z*`|zaK8v8+.^&/H1C X|@oЪ~> 7ӿû[HVP3z= I.?!IX|t_`|s츹?BaGmugn0'ܶ~ >Ι;mH8R'm7ʰrHH8 f__SULF,>@g ՟SG$O)7s66Z~ߛ~d>PނOWi [ؤt Fo)|`wVMZ-xtu'5d? O/c5P>gz=>c,G/1;ZQsgƱD )1ꢟ|.~e'"UJ3gp)pPZapB*s 7W3o-^H\oOɰ5jXg~<3kWi 7.޶*P~1-@\[_Jb7>X:o?fd?׃^_Lף@+ ,8ANpkZd7_lr,L;V@|9qsĈ'׹Bܩ4E]ĴMd5O9fjzN<%DS̐gGwBЧRh"hV5I׊ŗ_57|`[3K\jǚ581-{3d:0GTR$>`f]\,lR/ ,޹ Y| ynr BSzIrQCϔ $~w L'~?v(Ǵ|6 mX#jyEc=f45W9  ^PK$ͥ~@H$?e xDmg):qq>P*]p Ԯ YU3e!w8; Ox/%ˮ_iJ3rBN3>`v_b5gz$~(7-5qFܳj~0=ɘBC"꫎fIjp]D+ fd`CD2 wa DR]b"S:fdi %Mh݄f]|͢]|$H?C@#!RpP1v 3UQ@ ֛J*>0 !ʹFoxjL/,Hi/`3--Ze^*H-|p¥_2{^Mh"D& ۪a*Pi{;?NڑK z'(G+|'7D/~i蠾ŧtPm[`|S_Zsk_` 3@֌`һo!ǬǙa»k})G{ E\vJVo2:-}ڪor=3s`APyo~dLM3ܲxuKbt]~л.eXԌAzkc8:]I ;S9ú7QG|7a},%mo>A njM?` 4-sЛBHs HE]kKpx*Q*T^6Zl~A"aXj-SK_PXS4EQo%<=|`B^/h2;ȯs?8ڇJd7f @umB$RDW*w[_to94n))wG%B?7~AyY]°@"JRp$ K"_ܗse5"XP B:2gtܡ@%]>`o4 >jX-8zy )f=/N 1t @ ZmE}Ow]$| cq@JC~A|S@2xb#$G<樉m6UU4{wiuMjVPyU G"kKigoU7z G4,?0>s`>+I?6#ʤ:ُY >S=fƤI9B͡|%jku7{+薟%Q~q-ZuEp=<D\K:E~ͫQ; D{_-S YB?v|lc8%շͻϳfcUWDMȎ Q)J?!&2I^m@hc>`Y薄 p/j&sXpˡȎLR2C]~ 2 KŶ@g]^&0CltL`'{kX @z/ *?)/~tu.Ľ#~dOgOSl}ՉC^^Xے4E-u~_֒lyͯ:iohKme+>pъGU$/)g1#zwX9r4ku}~9ͫnޞm/M΢M._IX;Z 8'TS8P3po-Nc ?LU!~̪jpK ޞpYw~ U+jR~Al[SwDo  ę|5;״:}Y٢7.1d Jʫ^z6X?0d%D`Q3e^1xnߜzׯx{ fLt*G|bD~ْ7P9վ&:_Ϲ97gI-x[`~'$zl9{ v%\I `^WB&mΞH3B+ %hq׹60uW+,lpd_4wu`RO$_ oY~DZe^2V H~$e'<//\ޘ=`^D )e1#4VMdyZл]N=*%GZxrzC᧊_MKOt q @"IxrrQUGSw|LxwiI0I1CZ~8S6ρcVMVyL 7~Py3>0f<~7Otům~xW?a/h@lWgo4[StuޜJsH޿;v7`9"oR~AR}w,?r8ӒjIm B]Ko7;Ox;| 2F3#%+U~ ^¥ϝEP k8#ݹs_Ĉ:@p۾fͰyqj!iR9Mpa\dFp!tDVYGgRnH@5 !FWI: ]A!6%PZs"CLZ|h5w(=J/ޥ!o\?ڮ_5]W! Xd"%Gbd>7?%:( F*:/.\ ʇS%EfF*~d|hW㔀 Vp3.\a͕}͎nL,9ޮ<5s$Bձ5Y.Uq*zC _ =Sr~o 7u _{^-&9ZUPG7黸F>Rj+\ .&*V~Ae >y7POqNpkZWլnikjoP u䪏Qj@~ _0ݧz i,be _u?=`e{?PW {kuEӮ檧7f_7s LM?77 {i!vXV:EOǣWN bɀ@ yWl>l4#G_HzMB6 -@`mF8!=f\C!K^3ת?ሥʴ*Z}j]ZDn3[`anD8㣅 ~6%iO(5Whe)ȹ3u~~`%Vd{ n"UDdf|/%aH땼x:#:>ٲm1]f_$ %  PtB}ӋY>@  E׻_pP|lP3p3mn#߲N<D >E3N? 4E?RlC`_|[ >8t4a]-@$di/`DihW?Uq۠f|c)Vx8G7ej/~4In n{~vi~M9J7}u79j{폾A `ϖm~iS"Q[ߦ-u7f{{g 5FV l G,IdB$dsH?!RThV}ϟTx}C.ⲅ/4j2'7Xu|Gݘf$T?{RhEdGVg G$ʽ={> } ߿I ǬgYw$v_~_p`+FyYt3&Yğ#~Ņq>09wK90ygIcV͓k~AbTR I|D}莲\k8[,勵/hjbG)N~@9_t_h":Q2ۼfZ>7UnN=_x2zXJY9 " ,]DE8L@ZR(Fy|f7Sm EBbY~p̏' >`ID2->`n,>`Gx.&D$&$ޚCX|Sva+ ? Q3)t[O#?}\5?@4/lQWktwڭh̨*;;9$v( Mq>5DEӯγ `!f@B?j53q@2xO8hڕi/V@X!r@J~ o,~Xt@/֩j|Ui1~|p#\fk.8P9\7cL3kƾQ-?F z1APz{&7>Ud˷~H%89UdId٧4hIVs=3NEQ6\t|C$n#T< _iu|'~53FW3c5E 5S(huꃥ_Po>z_,zΪz[j| ,e\7K$@ypKS ^螤#FNr9p=|Y$ӮukC&_1#lgF#H&A֘U3s]sXYI|U> Dja,+]B롫57'9~/R޸~t Db>-->@[r@K4Kj?tV(,@ ['_7D+7zqjy> ¥K{ڦKlGVV]d7$0C+>ŮI+;R*D[? pV8> ͈*Y4r( %+(U$C` /H_q>`V>pAVAVŀiW|mFPhIvlyկ@(҃~~E*ma>p8~Y  = 43ohvw\~#VR cRŸM)h_ț.;[/=EUjOZ| s-ۥ5ZmÏ}-pmݪOx3Nkh jakAM(3\Vf 8JXW}޴rI9Xz2%["ĵIsڴc& kfT@^ W/Pslr @jN^6Xٜ|b6Yj{#hLR<x}C |ťRhu^t5Ѹx %q2$~ _k .y] رsEl.L|U4O ?j/p>RqֳL:0#jFߘfP_y cQw@$6!nO:'M%%X5GD0'Z73n*/&ߚۊf(Qbb6ݵk\` 3=vĆ0rEG Xz㹀21n`  @:h@ŸЌvb!YO t7/hH-ng0<] > *8$#h>ZҘ_3ym[?d{>@J4hl{6uz5u,>`v(|џjj@8/,\7h

~9uݮHUrJd6 !wľ:.u[QkgAh]=RIK>h#@nr;8Cv'GdyJ^nfnIi)J?1M9zN "=3L5Z`;o hkKvSʾA {YAmMfb IN䚸 Z{Bǣos} su4dJ,O˦B`D(D>DHظe<|} qy|#6Ή.A|.qk0w?vWB<ȕsσidn57/Wo~WX݊CLAۃVg?'%@8;$\ve?3,43 8x)xfyPg@KQd|% Y`4 rHЗd2Y7 E\ ̔_ NN;횷˃)wӏ߂LLLHH J)ۥB U2 J} S[RK 3+4z 'O ߍG@tu\'B| ܝn{bwK?_(WK > Xc6e|c_Uo!,~ !?w[p9*Wt9l΂1# Adyi݀V\M7}(o?Atǂ(d Є\r=_#^ NeՉ L^(|S.\됉3u2A=^/^Q+-߶| (ݲR_CW78#r紂IOm ib4kl9{ZRV^K !^0h5cyH[ 8g9pZm7˂% 40Wi7xF<" b qEA߉;ᙡ`̣v SΔZ雠L=d[ P& Hiq#m@jH _`ef3 rDk-s\A&9 =YO\nD7A8! 6\΅`X-v L;,40WyL0-)ЗyGGӲ]!oj1= RWr5>b7jrHC_yR@}Oq ̲8DGrQ#pqoǿBkd2[!s!S1S[2#3A*Z}Q2*ՍZD ! @|4\#w0F0V5wko7# ׍kA4! Qhl<ҭo'@]PWOKQQG1)챐l|jaa xp%sޜeP<(ve=+' PCtplb3ge ʻ @Hݬ`ӃIpߞ {KY,9!O`hi3:@1RGEIHA*窠Ok %Ŋ38>KeN胠;t n" 2JEW X0.ĉ9Oɽ%%&=(/k\0WlL/Aj 2O=ڂۺ' Ǔu]k|? ~? _ , |'#|ڟ__7J ieNNt6&6?KowQ|tY!yqDQ($%YR w*k 8Hp~m q@`pm]G $KJK1WJ2r _TK|:IzoNߍ^AV s LlZ`l,n F]aإ oYP/(dp j9ZK48yJ]7/]y y}B_=3ɺȼRgc.RWCh8*''9n ᐰh e} Ÿ!$>q$ 'VCp!x6V3 {&m!hQ pI7&5+_Z M8M.EAI 䔜۵< Zi l{OC~EF9|?ďGMw?|uί_7`2MS U%))hycFyC{I"@{/Ї}PF[9.|@5Kc0VIuzGꍩwWW^a$TBp>YAZY7CW5A*s3-l#y_{}L3si]ˎ3EjWf}}{߻]dK1)<'kd!F;Z;w#*,ѓ!tЃ ('] 0Z׺KH.hi*71' cW+n(Xp[Xo?4 AŠV\ e3emal NB/9?DӃ)`5v쭦:Po. }/9. A 8R 䬤@DQy:_Jv}m;XŞ=ƻtݷeFEś >ZA|x 4@؀{-wt_x(y:[^Q*o}O0׀뤥.e$7(_s" Y>yo? "H;#R1ςB( $@k@j-ZB: eu.i$HTkA& GJ5 /Ppe{G~:3X.I#0M{:cv ‰O(3I X Bhp48 )06FZ8Ʒ|үWUr@~q2M^|L.^E(GR%@Js| V2,EJ@UֲUb&~ H5ڂ*Кr`*Ϳ, ~ ezOvztTy@~oi!A>WeA *щIkYc@i;r R"2AE, d~71N7=KJxGưA/>w G-7Q'|G{ Iǃ@Hwx_fICz.?w\U`ʯ,(;qbCE/RrgdzD=`2KV@rl^!.W??CDE g|8Kt>m~&2y v=@ۘU&f՗ XO~" ,Y<+|`6M-`ci :´3!2x=O'Ap>o} n?7dV9 MzTߌ}U-lK^P /|FBp.-?GyX‘6qbb -H!^ @r]H2ᆰgx9]= 13Ҍb:,[d33__kYB42mNqU]r\Y'|庂k' gN\tڥp3NYt^&փog;[!JEyQLI 1gr1Dǣ3QR)kZjgl6c2hwWS erHѓYn`,ӴyB 6 W:Ou~~ŵkBxt&ezVm9B?]1=fZ@e :\jV:JkҒ?1ݭv ֛Jd$5_n-#fv=LmJ$(!-)}f:t F]oڱ`^1wo  !<<lAIp"8Yjb_Y:Odf{2- lݧGAqd =`Z  HsY.n qx~ۭ}f.%~ k4(c|-ݦ L $@1P)z'}@i) MY@jI{`8?_*TCF;v!~fvfk]}wXh`u#d/ lV@C'!=4Qǃ Gya=em'0G#7Wu9.0c$W~8 W0/*6140, A` KCB<* :S Y}^gBbt(*[ֱN};轿q|=10yE惜H%ЪZO&ԙ.05.}D} ߛk K? q&}m_{h[2A&Cz}.s> 7̿Ճ$R y]`h#f@>1 *o|,oBV<5~G"7qޜy83R fA\<^"92_FH/ ^o{(?q"6ٙ= JƐ~".3qx8 2W|1_Ƈ A2R()df3Gaj! &] SKEqt"G_(rLgg~/O$5)  ~-_C W"fIKڴL5sYNRM`)Dmx>hZ'$ę^ ׃ie0=X{1`pS2`?lC@OIY2AJK>:/釠iC3"^vu`^H,Xb tN'?kz O/CtOT1j4!tVS-ʘ^d,MI#zNo&5m- 4 8 R d-S hڱڕ5U {5v\[ފfE› GA~RU ފ`mĂPxCafi镶7[ƿOs|AG[fҮ{do9߀62 irXb>J;\%WyYޔY k_AB)+W9A?㽯x̊3RK̈́d: fϾ&%^4 9s4Q `09Z$ؔ-%t530t6Bo*4TH';_o f̅`p}z9]7{g\ȚRf*o3`3;6E5 M5ctYw d :9$z\f7 g-I; ^dYK9fκ~]͏F/3RTE@HȼSڔ3!صg žA 0Sfm ޮI>r\. \J.pu+,qZz4y=kF=^^NA*- j:lnPC0-<A`tp-%`}aHVH>̅wë́0슐\(9E s!lV /pS>a\,fNmio46Ӵ@ JPJ9QFQ`oHLGP03bn_K@@[]!^/`WfU ^n X `:qƀWwzx ^y}~d^e.mO*=K")xDt/Sip#l`C>eז]a0ZgMD"qW4/cw7MU0/7mKa f:V0V)y@vwt tAkk$[ANO@7SO>uv3d8P?=x\3Y%Mڙ*Yٝ)є`7; .]s[_p\qpc/o[\&ROc2-cK; 3ѐ~9arMmhM`I[5{7=vf- `Q0A_k<t ZC0-JP ̛fYF:ЧK+2V #HQMGlc*X%:O[@6O $|2]ɓ`y?'ĕ?+r;1In8'y:SGr'{5]~M׀i 2V^О eT'*O.*K;+A6|+_WyW~9@Q9]Jo @}F׃,LU<( RZfV3wԐ˴>h-̀46Y*cJDn#d1П,[)RFE`L?[ t%d| 5ۀ췿@߮ "̓[|a0ݴZVhYVYڃTў%sAk_ f׃d: drFI=H?|\ TxA/`WۣܔU9Y tx.$O%HJJN`w2`ڡ>0&a"0B-Jk|$_S4`d.@ |C`@Jyps:qy} ,u4--zLcfVlc0O&0_Mdžׇm  ~e?3Q룠 s:U@`2e*ȷ^< 2 [;L,moiS$KBp*h y'o{Ȯc!:]uHoNN-銐:* `C /_/;-;W F.Rץ楦Cڧ++Ahb8#8Kƥo7!uwABڥk@Bރ\w\sۅ;r IDAT 3.]~q'>g4Bl v@ddo*Jg)ܐs&'(2(Ƞ"3hܓEC(R"!enܪ) [N]*b%J'%ddnHJtMıpcŒbȪU"Sn 0O@WcЛ͏fh}i-At< A:z zQ LGB)RJm ,Z\fY3p߻. xdDˣP8HT2"RRS "[j?d|Q~JARY {dFgz@jcP0Qxua@j_*?u-( _,7ʿ'?ț}iå^pË{.~ Qcۤ;~+ :, KA+d% <ঠJPmj0m*WVՊz4Kj6yK@$eH0䴾@ސ,NVC0'$N$u%HQ O5<.vtp|X>&$CNٿAr_2'+ = •b{Lq\YL jYREjHЮrBfRK K{3dЍ) 1#.t9:@ؼpK-MA=ް{.pym  +l4VY@֫Ɇv,>-ԓ&en4;͏[Vr '@Mjvi)׃leH"{@imLSfʁntH+FzCåpǶキqP&4Fp+b7= ~o>eִUM?_m~a"!q =;$['LԀp} >8Z A>آ-:,6SAЙ.뻤A<;~7 EnPÔ\ʥ!jujCfUfcuԄhG&z2g̤@;>ǀ9I}c Z/ȴ ?I=]̣ Hz|>:lS o0lnG~+y|!)0 MZY_~gx.@/E5t_PK VڠhO2/%dԓPAG> ,tH_;5#A eҰF >RJ3+= e Ad]_BE}a>v E`۳(氩 iN HU)-u@ZISR\\$8fr髃e*h#-j:Abxb"xlw+T?xςSX>8y"öAo+C` ł25AY<|m )+$:S(K0zj^25t| dtjX›ßï 5ɠ; wCk >sNf&G #d4җu5!%vjP8.4 \^pG@(]+,+g7o{ 2P`O/yYy K#.KVy\:v\ o]杁ݙC`}uS[!Gͣj9.7I 7˃rK:Yǃiz^`/v20 3 P3T]S-@?WDY׀<<,-2 B";<Uv :@jLJ# ;/ l~" d7ޘ}&κكf󳿄F9AN5y%ޜ gXvnv[ȉ^ Y& Y kIdH䆓A0(.p~0%8!@93sCNv9"<9/f~vז?]ĉ9r& $%>_J?n_ٗW!k_7Cj\/*ѷQh%d>@y&7323?d>Lt. Lh_DM22m S1M%O@@Ha:E?r"x@k,W; |sW7sguB<2:C\7::P@T@'R@oKcI'Pfrc ֜1+  G@ٹٷAo"ٕ ;&_gL7s l0UZS}XӃ H __:0m}huT6*xs\dt&s233B453#!DqOg-v 7 _q1d@hFH_&Ba=!]#ojր"F^w}·pVEHMKlkg`?%oTmuȄh(hRnM}3y|AaYQq(X_X2Ľ>`EہaҐH%"NSz1suuv.GC;h$ L{J-wt> ]i |>+@_`fH'/!y FslF3Y)3)_ ~wA^AS! f{]@9~ (J$2,4 hW4 h-0'yMSt9h~fRV~]}q2(An$-dIoʜ87W? ^kr{KzwP2͙ g&F}Ǝ?2z7ӧ )0n\@G)%UZ\_h)}P/uz^kLwtvQĂsfWU4loz֏u]Ut$pp?*xi>Rt~t~σooA&cdNm ~RSZ嵔S`Nf;H)#1m(kAMyDjOCxUX3 Gv sR6#5mWk z\_Y)$sYf 2^6Lm&dqVȽ*0W󷂛g;dlJX>Ѝ;7 eiC{< @>XOM̃pXKA08S>e{3:K|a=R S>4Ms_G:^Љ JE)<*e+…  ZUg~H~4`kآASDK!HnKVBX.5l_ ]A./hk-6w`6&~G޼۠:MIB_vZmJt6o+@#k|2D^4#ǐ(XaW"TV|J "9/%>X~aXPtMtYV[ÔC\0-a}eo>V?0&~0G2^?۾eq\ w [ \m̀+>4p:nM7Q{1eM>G7N~7G ir.|G1 z|!AzTɶLa}JJK]0L a(BTAl+3 ?K^ @C-O-UAK;%9slS[&xl} j1y\uhC}P[eςl_UGvk e$d!sugyt4Rѩ2dxkzྋG !>Ck6܃kC;Cdvf?ˤ35!!30 2e*g8u)zEoD r1Z'Bc溗nHR^K/ݷQ̗; /}<0M SsaHuK=z`^j0졠ͅZP0(F]\ y^jq=f"H}R}FJJ?]*r~@U9k $B<(đcs;q#ײV+k 2\CMqnا&`e;  5^li0*;e=@+&HK%W@h#J6*Vi%LGOEL 8sx>Xߔ{i aoyp\ + .߃x+o)G ɓ*df/6`Ƙ:qݮ{iFU~t@Kd|/2W>}6AOK3!QK%pN7fLkХLYWt3zJςI_d@X),\N >;NπI hB#m,50M iH^-yPnY*՘4>Y K R\fҞ@j/]vK-y%(2ȥ"W 8_0Roej KCx*`jujAwycjҚ-7jyл&@ZIS)) K~ WbЗ5d$-@n:'Bp">ĭyZ/|7[>q+3E!=,3+҃rg玄HK_+j`8 ,cE68|O6"c͎GSSMhW&oIِ9 qøPWu@j}RR/9D%)e]W aAgF*I !ᕰ2b@p1<`IE æi=3\ZH2-f7AIO9kNOGN_З $`t`mmՂ]f!5#;,BցԎ!j1 HKTTTuHx< c_74y0rsMZBNCfA< q!o]LQm\$3Wہ]@CyT&yDA<_%r+_ 2/g悫9 u `Jp* yь;Nvۢuk^Y`vf4)@ ZHn: GvQk]` 1)os=D3mҷÕwpe\kRK#Ѓ)~ޖ^\'5C7L3H{Q0ǀ̗ Ey σFؓXީ@jͮUVMK.oP8u# 1.V,lVRRS o] 3 KP&,I{氹lS1&]@b@0WPa kdREj;e;? N=lJE,6lcAE49.$%Ag喻:-@Ӫ`f|ݨ@RZY%%^&;.` qqoLWL? | 0W2[_@S:SG|?qAn1 Vyi||QR /?U0wA6)W,:zߍ Vr$!Iav}Auf>_5]`>4/N`c=A*H 8dbK[Ikgm Z~5&ϛ.w@jiMwyaY_ I i)R/>/8{(I^ɠOj tnI=vW!/d>gA6Js4WC䠔?l7v::SρŽ{G-堏>9ԖWAj*T>eRF {-z5{n+nbu<>QX~ͯHY.0Ihgcr^ڃl{Ƶqc!## rquwm} %Pȿoˀ*U󓚓/q}%uk Q6gu.klOȗȟA.(-ao`NY0Ls ZT )$+%Č@${LMS N152N^M,n?b2sY%i2A&ʗ #C(pu_"/ޗ_ '? !;n y]GVFr?p#lv ss".d(p?1NOcz3t2g``o;n7W >cievGsH -@wIC|i_wȭvBt$xwt3]jUЦrR<q}!0+!tw ܗ2=Uw|L C9qo wy!\Tb3~v~ AnpnuP#avW'BrjdKH IMaYUO'[BXT~6Zw?[CfY>jAn/Kw`6ٓ#}χ-`߲w 4\]l.l[ʹ-%`U&#^n"yG:]g O{rDVV]i˟\.te5dzdeN vɂ  43T-$4q)} 'fB!y9i[qr;$%g$?ĩn><`^0>vPӞ`G> a@p?,L'Cv2Y!On+!hJ6mPv9~>?2]} ~kʂwv[QktI3wKp|_W_gˁ6^A&ȔG= =|T' IDAT222!=/ϐ22S._>nW<-l'" F@a\FɌ|]!s5LL*sZ.M ?wwo:C ^\|;u7MM'R(OuyGE7!}[fyf.}4nwN*Zi7Օr<]90>X* CH[ʟ{ ? q@A41pF /oGO2^0S_C}\(e΃ܬ=&rJvscXе/|  YЗՌ[!2pKC.urO'  B8'\~A 'xA; L'3Ȇ`"s<fils27.E H!Ird9H0R]izk`qL}  [~1t>b 8d se,Rg0AM |(U/d@A_w]G3;4Ddtң22oCfUz}_4rOToQ_~~qxduqW^t?qNWǣy4b+q9߀65:ܼm@kj=ZEJ>]vW*9`Qw(8x.@'؇l#{؅{t2@Wϲt$ACrv:96P_7,msYōfjpQpAU"5x_VB[ *XABXbAW]&ǃ`2" "f1ȿzJV6 (tt/h>mE@';_ <$MyAN<{i9dgn2L^hЖYo~Ŭ0_y|`j/?>'HT?}BE7?$${Ʀ:ABla?^4!|!ldo 0>XEurF~`ƙ4k0g: sNaZH.KEف-N;޶m]D>}Ov'Wݐڜj5u9lwYf>5#ַ`f\Qg ͥ<rӜ*uo &? ïR@!_׆!nj7}6:EQ1vmapCCb) _C\' j%m^&2` 3כ㠢Oi {yҦGgkV4HvЕ:K;y堽_kaLYSu=AWn-o ɜzݿC`ʛ}p(pՁ;?cS[@?yWk~v},3߂ՍZ$G"y<zұsd>RK!8>E-?J\ 9)]@.~Tr$!٠y5ׁm2|p{p_!"x6Pm NA e|RTHg>b*\nx!9oD_)(5;>c:[!$΄+12JFf"[@'$YlЯm0f%hV</; Q{ʞS5{@Ig9o^uK}CrH~i(WK xU0}:/@J~r |d>( x |]?_'n;q`\ qi<sE\||FvgH~)+I.Oyh==[e|u޺Y^uo@/ @Ե̏A x;Afz>ʙzp_nsAZHRJ3zqmSt5=%&N@\<Ww{ IA;.ĕękIMցԁ*H-5 3!h[σ1~y_fP> {8Ҟڜ}@^DW!w!vǽqǸY\ lkOV^4U"<$UMv]4 Ѱh(COx }`R\p_ہeLI äT#ePh+H}/>b)H,@W,N{4:hnAԝi<:Zǁ&M%wu %[l&1J2\A3ެ6<,# 5_IMXbyB?,Z0 vԟܛܒ\ uaঠv ۶ c]W@34#m}A %Lު[wEnz_:BSv~;X+cH[Y"c@4}$!`<'uA:?mro #])k$VsXFq 3. }t\0yL; rXVn'MpylxpG<,%%zY3`ښf4~siA!Nbk}.R+`ff C]=4#@nLr@c8h-Iΐ=1- h C n֯E sqG [ r?dMwܜùe!53!%*UV]=p+$Wo Z88 q{~wU,2SFHkd Q u$dȧeHWyJڂTjR ,0_ɿqxW$[~(;+x3lK WmsG nwڀ<} G3*}arU@I' c #AIO L=si.ˠ/_O l}^"T*kW"1dH r_ޏ!(8 Y+^Z 01:Qa7m-veǃs٤T4j`>9g?S˔5@T}cw+RXJ9w:6Kw@DQ0S$}p٬_O ~_◀_?W'ՁUL7}^.g~hۯ _rxL @xWX.ZhHMݜzeynȓ'VeoFYeBrlWYHhLmŵV7-K_k'X<^}ybwEuW+E u8O^fc`;ڀ: \/ؽ ! 4WWVۥ|)Ԑץ-l/eЄ?ɏӿAT'~-f 38s>S.Wf4_o@( <Fw7K lz{@\~K&,BRtN`BsE@Rkn sUԝw7W~7Ԍ@{0[!Q(qw$wAe9gnMu(빬lܓ,ےe5!놬Y?z3cS5O<5 o gR39 9;!wo W!/9 mO|v3wy'9_AjLj~jqf֕u]=ϋw腸XfHVqڀn$_@nRJdioCRX';_Y[ài.wH+48ڶ}|{╼?w{i,S'} Qh fZeZCHhRHO/Nρ7AnA# wWn"@tt ~E[!/ww|Gă7\^p}|SͿDIgЉf {AkJ˂b`*ٛ50-m'sTt.9/"a,`p8.|;k`s6ӎ %)@kifv]A a9+!:lw4zs~` ڂj?yش t24烿f@C`Yw|"0j#r !1{AslO;lAlw 7fkzT4hF+lKd җ/vXS KYp3))??n^C4q.d>T$jzTR8O_rh?W7mw{u0&eg:Mր89#A7 Kz \>7~0w&ɷra'!M怷_VE[{m C.Ad0E{n=lϠq)`>n-,H<(/OВ! ytA&D@OgQg& o*2zd|*@}=_  ѵjF jq_ŏ[% LI+q۸#DFm'!Ϗ@8~2~ on]?/+@ Jq)FS֖ĺė!>Y%qQ/ <A_׎L:E;dHVmYA+fN9 ?g+Oz >oyfPwu^}~7!>Gq~ߎS $7d<22k2ZkօtӹsM ˞̽`\Fg|/[-znD[@ei/!Ƿ._=!>ꎹE>wXJZSѦZ;C3tnн )%EA DA{$SnrTh Lcs) a0$ 7A.:1 &K%>Tdא,a2.I*<SS!2u.WEi[ `\5LI`>2cLO0;&,Ǽ~v}ӎ; knW4-d _!s\kh/IE0TZR><'{S{7T"C25R)T$)yV(hJIJfI"d=k}=/zs=+-ivbBlMCh2+YOs渏ݣU/ށ,|#Oo.C~*D3 . / @0gXQVxDK&]3>_jHK@P=( *B03̎1gp=ֱ92 >0$AjeHH*>P^7is0̍`~І nnS/*=ud]`vip+Wn {vv8q'&pO`' | N[pհm 5{ Ղ47&|5Q$f%NB!=Nn3t @p87>-3p'T3̧\v !?!1㒭g XX 2kilF3y]?hX$ОF4*|U $! 265 /=q$$&nɥ 2Д^F?GCPkّJP]›0GlIq(ٖX\ҽv}T0Vϸ?63LM$s6]c@oы(sG zv<,Q; GFm cڂFR-sPUpgxTG0'd}s}*Ⱦ2/d8C+gB/d Ye߳?^YMY|:ym$. IDATI$<A?ֵ{ko/;Z:`070ѺQ?D&V + >h4(32ْePqҕΤ^̩L)depI)d ָ 2\Hh7@y L"e633{`jȾf4E"HDR D%K.Q~gANs\_wRǩ!U!eSg sIjjH өU4Ɏ(L|̇`e0%as0J70>L SD`0c [$[ftI1u՞`OL-l[-im VԿώ߃h:.seWiP\vIl-9$%R2f(Y]@IE(yPtshCѼPT6)堠KSd%P|mſC钚%Wɘ}œ@qP<J_-T6үt3(dq(T6.+5} P}$%/IU ?`{:whatuh.y JY4 {n3 ʣLޡ)Q^c:ȷ4C{h\lc"HYFǷ |-35&Wv({s (VlPjۡ0Yت2(-8Ë?%K(@iIiR;;!Lee@LICԲO>̣G <JxS@c:g_s .뛱 ~/+d;@jilg .M+r ]Umm{ ƚ`.3WV`30@{h+CyK&-/PIѱz3Nv=(=ҭ=WCxk`x?M]u:B׏=e-ʭ:Ty41-.Ppovo!IwM N&b'`7 :Tgg2Ao&A/w <$ԓ&d< =Aj ҂K$:}࿌?տi?+4/h} f9_m[m+`'a1rR{mv{n ̳ /򝬔ٚ rÁe RYD."en6DJC ^:q5ݗv=VNQ9п<1m-)4}@?].TúA9t52CjP}}gV+x"u@~5$%.i+<+,Y>yKUnBNRa28p (W8(&@32\dޭcAkB`E+0b0tsimѬ2AW9e|o1ׁ7X\4'rJިIy_Gd0A/-}K\_ "U!Zz6Se,xB<"GX0LKvҮ5.ɓ i$#Ȼ|Ԑ*Ct#uo 3t!2M"wp-č>vMǁYej@~%ŽKy 4`ϮZsYm69eNI˴Hi)!dЇ eG3ķw 0ߙU@-wҨCt1{q+ ` _mq\/@jlޏAfCfOf+IIa~f > 0̆pJj8 h aS K4D=Á'OœlWL lfYnbK@0 `)_7:i+You`vٔA+>XvW͵Ʈ]#l6h9ȝ% @Z dLi A5z-&Swԟd3\+o/ [P"W?`W㭐ْ~v-NU}-~ =zYv 0/G]`_u44#@/,35uATV?i6D} ҕ! Oqc/}xZ -[XskWGPMz3%n R (}3$j^঻{ݻt>`2fvgG'x) ӑ J[Ya0A"ɗ:$#ǥWpl~Z~Eg&}/xp|{ 57~/:Dks\-R~;hVry.3tޯπ?d)@ʅx,yWyxV-RA'AH7v(>dwM-&h$n_Qn ҵ3 6]Gla &D+ CR4fKwAZ_;?ȏ| +V=&͂Do,vw7 0 &cwر`#ksvLT/j7鳺/|,˫ uyhN"'r:J{݀R 0H. vCx* sO /pIxP|0Mv`Hp\v)tIH9d0@I^R~}{ 1|yηVҐ/og B׀Y  GC4:)c~ nt# ~q'w2]2o~Ow`0xo2&ui=_[m)JɠU]Gt/ Yk{t];'df"%ZsN k ~*_V\9j~W5uܢ`.3a $'DM9Aj. ;kX3y]"Dւ;S}iTw-ЫeQGkȥR_ZPߊ;9l<Ï/B-^pofot>UқJ{@x"PvgƲzl3żC^jt.z`3DF`6rd\3y]烞zr_!1P] )v8X| 0S%Abc;lL]?G1;s[ffgCfdxW!.~1wBt4*CI} )W!,*f;+S d(AW`}f 5-V~Y,'ޣ Ue 7`m R{Ľ ?vPMd.7A^f$At̖gA{Cd[*pM]GW ja>؁T.F2yAD~JX ɿ_&?ʼn(1 |Ƃihm@V뿚 C}/_ߋv\ |/ks,`)pZoAVK4i$q5'}5 XW_o|Ɵx]d:dL6? :AV wc <drco2}v`Mc:P +0A| 3v]L2L+󢫣6 4VT<5i8'{ASu v\VgT20Cz9O]k# v7s.O*[ś > aWEÐnVֹ//߁d2 6% NE\SR )6Xv~mekj*`mЇ4(PwЏe< >@ޔO9,@vE {u>RNJRg($%7%W9jv`jQsS'O-svGHLJH44U QxpKn A16: hv“ћT Ȥ!]mRxAXшh D…j\\wѶwūO7]uy0lh'o '\Vh]j7AboI 3))W/$_NN j螴Yg6`zOX[J-UK{ЊM%=GN4=[)c@j+ V֟A>:nY&7[62^uE =,+%̂puiO1d̀;;vsk隃mf,`ȫrf4t<oWNZMO amr<a)] g\6֮j>UTɯr] Y7gݐ&'C~`x1 fnjԵ[d~0Mnf=ti~fdҍ /R )?A*/II 0'3A!`p(9t ;/{_/x{xf<6~QD? x;›? ?sgf ׆Cq^6˴L>of 9}KzdFf&ep+9a:DG7A6vY,sVyTsa0x; 0ׂ!aCb|DWp9.}薁}n~2:* ɕ2\ɗ2z* sY'߀fyG  E2_m tы~+  B!3:*\VϿ忂̦̊9`"s SݴsyAΗr_D& C3T498Lݮσfi$ ST_`%{es\e([zci3D6,PBM`R0bC>[`=i-Sw`7p0S:dܪOGtH(2I_ƀ,e@rD~-LRiW 34q Ҳ^Y-vvk zV:Zoj!&HDKcBs\sw+70= EF z]+l2sRazBm[˽Dy~ ^"2 ~5Ss`;ml1>h\tNT2/gҝ_Yele'_@*ʢS`N#᝙P6lzwoR^?\o wxB$)h7n:z?XsiY96ZqT@hW--̳`^Үf S[L?, ԂYL L_snɾhf[dχd=z&@YS@-YYِ::RR;R'oddQ2гzRO8}Zs7[Wۖ`^9Yn[$8ߥ Lps!417 $%$NBDyHITLAbڑlS[l+y 4u H;9*#@7uݦI.-`&܃~9Loo}|Ir1NH1Ygkꠧȝ,,&ItH kX 2M^f1 wW #Ao;_hߒE!?0(=]q^|9W+hI75<S^3KK,elVҏm?oxn<&2+ z<<sVӿA%}t鿠gtZuz)Rԫ@ b IDAT s2-闩Q25?=;; }I[Y_(YVC(Z͐=3}Qߨ6=/x||r^.};%v-hf3&L'S$A56i+`FQwYkQ7 lm;rԒf|vi?ĕvɚ y yO < RRsR3 p鬽#$ * ɊRHܚ/Rפ.O&!uMurP l`7CYwnUdKStɗ@]WH|LvP.8 `ʹ8d9 8 - ^eۢw Bts8*;O[5!$!s9Dö$"+ @LL< 1lxn4 t9(iQ nEC_doapj;>}LgL~: T{ _lvtu"0h=πԗ4uOÏ!~71~w7^5FP/ltT K! 1,d\'Oѿ_l|I\QI8mh B 'e^a ؛up\9WX3Œmյ.ȇHYf& -H& ,03m3A2o[T !HŮB^}f9d6 &94_Ohsl=ec<+_@!D9%>k!==Qz]T$(~a oK^N&]37 +U_e@`Mʽ>D!Sbm2$lb}b$k%?In͐)y]H^l Q6ܙ\\7gd<}v1s &a u'XDpFnvܹxpgz̾.F(W!{o5$% 6n)'AjH;4Ųo]#AB tV7s)JO@.ǹ~.|a|1px@zӛޠ5EpwA- ZBʼnup+O0c6;t7ɸ\aMx UjʦC)|2g2P HB0_ݟ5[(7H 8E@s0Ml_[ +:8C<տ= -^AgLJ_@SQ:nS+E/yA37BɷK!. py2G!/}4J/_(biSza9P6liًPVZV,'ҳswťCץ;KBiAi~Pֱlpz6d|@ztfRfdZf.\-O)jj@P) *Bײ@85j웼A_p-0{=kuE3L`yC^`Afv#WLf3DRZ^j9 r+躃l_.R4 հN]uɯԸ5D`OBDz]ًo1`[ ]#09&e2z妑 2J@o~PY&/u~K [ ZI+kc[bp+pرǮ-[GnlT%CL(]RBOxOxDⵐ9n-6 nn.`Ot14sb=}={@kimZ]땠e<C\Q!wAyfb=) ?հVMZ59um&z(A֑~ԖTn׭7Vlj٦Ղhy6]jN )/F7`LAR:V!v1%`Iv8vGNn6>=}#YPڹ͒;!}m(%; "dά WUpq/up7g@: Tje'٧@[ =Y`!Bߟ@u&+^MS$Ld}My<[= >s3 /.~䲾-}:@*5$ @@SNr<$N nYa L T*:b33*)=@rY K7`>"X 2yWVXqKJ~NLJ</w >gLP_;/_woP.])ZC#@Eˋ+C%SJCiZ!=}e<> 3O7$y)xL\+f2Y'@I+khۂ&V. 0)Yz#t;Wu]d2K4H$*DR$4ddFl}u}>psk=f Cf5iڕZTj*Sd:Y>A)num0lA ibYkˁLA >IAؒXXRHNQ0Ҕ4Y|+ 2[e<g #Q%4$z ś [v~d7owd$R\cRxO~1 =LgN‰y;U6,HZN/@&3|B) 2a`:p1ۖrS'j6GEAazTS'Yn7VmFv3~b{]jvYF ]r̒_@z9r8 ʳ@'GAK+JE Au SO?F?ɝ^{BrX#hDoF#5jD :hD H>}X0yf8#t.չSe =Rǁ?>o> |N&9DC-:CE4s,?[4dou-]poe0M]s fy)wmggf`VG0:oη=6Re:Sč΁=bww x]p!iz=dx4b؆~?b$;| v*µnttt6KeR$6;3Bx2A''ۓC3yAy|6Zj$H>| ONԂ66oN&&Cs' <>nhUt8a:<dXRϥ@zozo $M!ɾm~HKJԅTTR5/CtGG 5ZLm[> Y!@q!%W6;^[n42Mc05>EԔ(0J 7|!%7l'ЏYlw+2! 5ZF)9ԶR>lHw`)v,h?4E)LO}36i?ޟ!B(a0?-6;ΐ^^^ U[w!%kArjX/tpjکOm"RDAhL0Mndm0AwF-Y):X5ТZJ\k1A[i{Ls֤sϸ!xUu ( !|dbec {)V/ׇˉMW6AKZj{o тE?|%> |Q$D_GG=~X>?ޏS] >ӫ/}o ?,ՓMۀ d0 *y ?Y u >r?Yγ $DL j[ 倎|_n2p1g¶1~EK[_—y_>wYU +˩/@oO | dH;8mh ZCq;mf?'wU:eVJ+S *`%%0:^^5+͓`5f٦A^=Q轨ڤʦZgFi--4PX ~/;L`x .?SQ>ȓ0!ё莨DˢGG`3_u4f𢬖1~ٯ?=]{\;wGx;>f t]? m:_Sz"/.=3Wt<c&\w7Ġ0p#`e*sA{: # '}?A[kiWr>(1OP@f2 c}eH=Fi?Y Ӥ -><|`?IwdqF0v 1&o/嫃/2fu`jƁii+%!] > d, lt\ЃzHJCݩԀ\ǿeC~QW_@9dX1\zX zh/[yAt)ʌ]Af,Lr+ALᨽ9f^T)c_|e*Awd-N*Q)!:m )j5 ?ו`3bj+.V[ AI;9(vnۂcضʺ4ZC `S00M3'.f,RNjd RBJkqy@ wTޡzg/nfeB{/<˂AHLLܐ F&.tMjx3@:߬]?wGws3p|*PXfc`$}Sld%pbGOvbz9kQcHO ɪɪLuIԜxHULJTttKHNJԯM cah9w~Ѝ~(g@#r9,7IsCnLk]lG{/jKں`jZd?O_?DfD-x'iNC*_3A6FDd d}W3Lұ /I)_Crb:)%酐:<5ҩtHMM \ pA6* '9M:HNIm`e/x2%2} @bwYH| ANPn;:ܦ/|cWbO&`6%V"ȫ 9'ڌ6@[h9- ׁ6Ѵ&Ae6ȣع`z0 k; l;V>r _{Zp8HJ,&b N#N :h> u8O*:tЃvSe& L^tVYolLs˾mϾ $_MNբZEMps (oa@dY \ H\aVǀg4MSR$>: IDATGO>0oGMOL ғ>`mf߂%WtTÐW)ox'p˅6b?ܚ|bnAcjv}>&׶l&ֶCv=d.=.t.D|:un]1 i t=>s njcEj5U-g[@|eppK6Ay *]]'e0j0l&-zި-A3ݪ54tn`tv1 oY K| Yl&ohe2F~i`{pCxأڐXDC"6 2g사+3_d C3 2}M ~%~%~b&8dCX؇k ěǫBP.8,` 2BMw#"~TnJ:4j!~ohNBoйr9KY4>OWrZ/AR`'vKy;2St,4?d`֘K,qzA\SL4Y.ΗN\w߀Cȧ@u+?M,:! !u9JA#lԯW%f;T@ސ):EO_f5߃|*{2Zj0'v*ZVk2~_x!QMҷB:#}: ,DSAh`,C :Vjs (qw".fdmdzYdiVYu4@֝YŲNA̧3 C+2~2r ь 8Mb:ě*jA87};_Rwu,:{Indl>00&AepmA50b~' $.fہ7ǻ~qIYЖZG̖I2M2@\}{E Hr@W) !*Վ$بQT7jp[$yi`2;`ѢZ !үTT3 Nap7Is#0M~g#+?3H%IPtUo׾M[STRG. +A2(C~uL7ξ&aѤh~q^d 7!,}|^^_V e~7,5f?f9z@_e: X(d#p? A8lV!Hݙ?u/ã*2`Y':0MM&5.+ CJЄЫ]źt%ہrݠjO+f}wԣrE!M* ZlO@4*~ T~ HN7S ɓ ПI|~?.-i Wb2$[K@$W?@>J_wo!TvHH *CɅAt_ǷfВWê-&[&߃p[,9OjsTn$a2 Ԕ6U=`~3Ǡ=.]U6Sd|-w 0?f12KHТzZLOdȋs #u`> n]e+Ft7X?)0@jUj|jp~-$K LX1<ɉ)+!x *7p4Yƙ" HSm]!QA?@: $WJEU*fiAi-=ep3i F7 jz6|ݴ6w[5CƞĆU/ dLM< k2f̭eF+3 >BP8$x1w6IWjRzHtSV-Ŵ=&y\wNbvWàZ_߂ /N%_HNB(\E3_`s,rcs9~6AF$Xffց~,) Z@ h X $-(Hyi* ke!/G?hU-σflq^0i=us' `*DF@rS`*M&LM~# azDl] )m=~hF^eZ]%h&5,!\n w)a55u}sR? Sfie}NvEߐx2=~'$*%2!cvbXZH h 2$@Ĵ8kߐ+1&1^CBDĽ#!O@lF,r/X&W՝tU5s/yKWH`F!/~>w=e߷++Fku a9"'}2Vz1A i9u EwDy|s7b4ڿ ap~Yҁ<S;K%ЇUtXI cH(X$'y 4SV|o{4+ZM 89+/`v1;r75 5!Vjx Hb>..SSk Y•WWNA^^9sf̀K[/%/piNBR9)\r+ʌ+l+Cg;5 "UҷۥBx,&!6 B,Z6H[/O`Fֶm:Ğ=n;B}@0! $8S?3+v {,sԬAjJQdH6"Ri!wԽz Ng+Wy|s@H Lǐqk L-q)<'ݭ%dK;cC tc}\g{LaBT_ Ӥ z@?ֹ`z()O/hi=U0 L}0?f4 WЛ / vSs/^k@,g`sl{b[3{rkNp\g!x=4Z#`n3uM9ۖ hS]>/t,ROџu%W:Gb6?83 0`Z(xp+L0?kLvj% ;Q*Qbbٱva0ۇ `sls`>+m9Y+kk3 RSJ%k8Uy \\2 7Q+'2̽pCm+[Wť$:NǁKn;swwwNr3.t"p_nCS5C_!X,`c# {\Q]G\oa;^q+!t b[8bbMc!~8G| rc'bAw7Pf$r^'e%}:JcLOm1M6ݫe0-ؓ n&Bi{n퀠l廋`f;rTW0%0-0͏ [ ȿԻrvƦ}x);>pl33G@Af8ػ-hC=׀t|џAk mZDh0=6LM !g aSZ]cA~סZr)HOJLv=gChj!HHT> 'ຸ&O %w -o T'|+k@PQځ\ rJdm0hi@^ $&{vu #5#7vT>VRfkw`!?# \yvBt/B0kw;@o0͠/B엚2 T҆s٨;dl4AKBCC.zR$ۦbF 嫀 Qpn8m7/Lޔ/~_׃2r+u 0V eb$ iց|$3|I9*ɿUNA3\OP  ]aGJ!),Ag,z~p[]+cCXt4Ċ*r!<-e 6k̿?|{sNIQJAi9!I1f(÷̄ EJ! 4 :: {Ľkk]וgYmۙ`ڃfamie rc+V Kcy `V?ҕG U`Ĭ~ߞRK*%Af.^Oro$xW3˾bZ.ԙz3,c2!ѻ r+r In}v=d~}rSrs@nohPGsrC!wF(@n{X$jZB1ȮΖdAQ܋kMaV Z]"jj̭̫\p`HGh7إ`YV^w lSo^٫Z["i e Q/ \)sthuZ fRH-cJw4)j6?OhN|E?EWF@yp qr9prTDց=f7I`wviz{=4#`vzmY*ީ0t _ɇ2tyBFHp00 M9dA(ixAfPUT a?C̟S/{doMAw+y_xs1Ef'(1H,@>2X #Zg ytOw*mz󼻽!:se7 EɵɝvC<$4VpsBc./N3¨ ٨?*C_ $^ K 2\m-/A?Ї v֑ =dL;nhxTܴܓ )M$ 2j .Z/߀L߼Bb:Ht_ 9L SlV[ fiFZ$+ɫ`I,๝[c(&) RC<Ë|RQ/@vNnQ&%5]=GτSrSJ_.{l)mP J*UJk6(-JTUJA:e͠{]eϲJeUlmYRvJ(%tPaҭP~~zžckf LMD p pW$%]!z :zsF?}͆P 6vEA Aj U͝<AAP-ak £a*@0(`~s0?AGȽ ,_!E֎ΎB(ג*p6>(J,jй\S9B3Lf%zu?w̲̾Ð7:[^c2/tt_o_ͿvxC[l[6{6`-2]?ݻrqKp/%/'@Z?ݺjs֚SS8}v _z.5Ғ^>P:o01f 4Ajk )LIޣw4u< z@6k6Fw:V^_+f Xbz7{{=5y'O*$ :U΂ٿ z>^πNr$ ae~}ھk[m;զ` V~_dhA魦H12'6T&P@{@Bd*/|ߐ J.Wo@j] Uw6= = f^,qticA\ ܞ,Jրe{߽n7xHޥ>*p/p7!YK|ߎ2vHK΄u4v)3bͯ`ϳwI@ޖ92 t9 NjI п4igJMe0)56]3!f.HL? JH> Jz:=앶mZ^]e&v !J7t6n jAԘH=~#?uw;p?7mi*T3l)ԳhP*OeSQpzk~صt!5ٟ@|0.Q\džwwAs<ap;!^pCnQg'Rnn`z03g` Q;g!.z4o+,,™Qݨdo~Qsww23oE7sfM)JOŸM41@Zy@Wrn%!l'A2H)%@ !6QƙsüGHJL# !}(}f ^/6lH֧ӟIqviy`&9ht3H;@Hu?p:M@6wc?RW,VrAk R'SS`-RB^.sf;'s5=3]U~%LMifezy w4zHXO^ r`"cy~3ß%`.Sd 2Mo=nwB޷>ԣ_/Z2if.sA PfN!z8B s,2A{hs&hS obT$̶] 6 һlg#kAvy<vww:ءvxu5='`/ ì@z:=@#:,C2 J3if^in.uG7ޠt h?i+k@Ƃtn}iV^05lW#l) -iIW#d;}Œ9m RU n)69_n8h mL/E& 2QBZO+hE ${d-ğğǛ!' b>Spj5jx -lnq5΁*+*WxUod>{*H.oom3 L#m6eu`y`zvf?h mԑd̗ ҅3 f~ 5.z1<}Koȫ m:HzodLwNt.p9Wҿtx@&I '!d,NO >]^ y#zuI~ , .u!35otYy'5ҹlAl]j4_PPN І \kIxS$qI}u/B`(vm@d)P֜nƁ.' p]ʥn L؝|`%K h$>ی_f;jPWq?>'C4&n*%Д|.ʓ׌O[@|iφ8!>*߄u­y ?`SX(Q rrKsB.>Qh8$UI ¤YRbpg^n8;/9*еk4񐞖n*VYN&_sSR{[iosiz m`*0Iv4BIdL@r!R*Cs^+%@Oe`>;!5$UʁYc2_'#<L 6AMK+AP< qat~4ruҍR ̾-dcٔmv}>kGAi' E%+|"ԫS\lYjj1HW];cCnY>h ¤O uI6RW9zdi7Sz`n7ǀVkc;Ў^ I:`]C5/~D@ސ Yn {!V37p--v'Np' TUR|!H:dWvы2^FǛaOe,`w%jgLw̌3׆m w%ڔKIENDB`Carla-2.1/resources/bitmaps/style/000077500000000000000000000000001364475620200172205ustar00rootroot00000000000000Carla-2.1/resources/bitmaps/style/arrow.png000066400000000000000000000004051364475620200210570ustar00rootroot00000000000000PNG  IHDR QeBPLTEwrCtRNS8,! uxq۶ pHYsJ+GIDATMY+\)dVCT; |MaI=iP郐cl#μgTj׽Q IENDB`Carla-2.1/resources/bitmaps/style/groupbox.png000066400000000000000000000004321364475620200215720ustar00rootroot00000000000000PNG  IHDRb&e pHYs  IDATX!@7C!YrH$r&D{+ %%E -ΒgC"`6\LG0&J:6y_"8דvT4ۄ y^&`~A#)4B B#)4B B#)4B B#=(9숒#Fi]C)ZǏ.9$ռWgwk*&LIENDB`Carla-2.1/resources/cursors/000077500000000000000000000000001364475620200161215ustar00rootroot00000000000000Carla-2.1/resources/cursors/cut-black.png000066400000000000000000000015371364475620200205020ustar00rootroot00000000000000PNG  IHDRJ~sgAMA a cHRMz&u0`:pQ<bKGD#2 pHYsmtIME 0-IDAT8ˍ]HQ9zBtLrl16(*/a B/FxQAH]E.0( ,/\Z1&},\5{t6]>s"oщ@{ @ g41ċ̌fMt?zR(%k}I![+4zRb=rf,D߄5N}8 qͨJH\7@TPBP;a ,6|Q̷ΊL"l&}5>;2u/yG@s+UcY5(.|1qJ ]d4e!M + ʖ]o@RIf(Ӝ&1G[z,ekӭ?U܀MɃ_-O{Lr]kF@%vojPTɍY};l9Xߛ=WN>^| Q%{WrnE\ ۆm N-@[c8&B6Y%tEXtdate:create2018-10-01T12:08:48+05:00fw~%tEXtdate:modify2018-10-01T12:08:48+05:00tEXtSoftwarewww.inkscape.org<IENDB`Carla-2.1/resources/cursors/cut-white.png000066400000000000000000000025511364475620200205430ustar00rootroot00000000000000PNG  IHDRw=gAMA a cHRMz&u0`:pQ<bKGDC pHYs+tIME 1,3IDATHǭ[LU?gv]wv\l j)Q"(^*ABh*J"FMc &1A}1n̈:BH,IIOhJ, 'DdUa[[&VNҒ͘76|)$tiiKEp57ɓ165 |QY:0D[Rj!G1KKx?k^~,X,I"\ڮH^b2㛶 Jiiǹcc}MɎ`?^Ш ~296"Jt_pO^^CKIrL 򾰰LD"#= . 4-VƜ%tEXtdate:create2018-10-01T12:08:49+05:00|%tEXtdate:modify2018-10-01T12:08:49+05:00vtEXtSoftwarewww.inkscape.org<IENDB`Carla-2.1/resources/cursors/src/000077500000000000000000000000001364475620200167105ustar00rootroot00000000000000Carla-2.1/resources/cursors/src/cut.svg000066400000000000000000000157731364475620200202410ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/cursors/src/zoom-area.svg000066400000000000000000000175421364475620200213340ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/cursors/src/zoom-generic.svg000066400000000000000000000146271364475620200220410ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/cursors/src/zoom-in.svg000066400000000000000000000202101364475620200210140ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/cursors/src/zoom-out.svg000066400000000000000000000167151364475620200212340ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/cursors/update-pixmaps.sh000077500000000000000000000022641364475620200214250ustar00rootroot00000000000000#!/bin/sh svgfiles="src/zoom-area.svg src/zoom-generic.svg src/zoom-in.svg src/zoom-out.svg src/cut.svg" filter=Gaussian for svgfile in ${svgfiles} ; do filename=${svgfile/%.svg/} # Imagemagick with rsvg support convert -background none -density 1200 \ -define filter:blur=0.75 -filter ${filter} -resize 24x24 \ "${filename}.svg" "${filename}-black.png" convert -background none \ -resize 384x384 \ -channel red -negate \ -channel green -negate \ -channel blue -negate \ -define filter:blur=0.75 -filter ${filter} -resize 24x24 \ "${filename}.svg" "${filename}-white.png" # Imagemagick without rsvg support #rsvg-convert -w 24 -h 24 "${filename}.svg" "${filename}-black-hd.png" #convert \ # -channel red -negate \ # -channel green -negate \ # -channel blue -negate "${filename}-black-hd.png" "${filename}-white-hd.png" #convert -filter Sinc -background none -density 1200 -resize 24x24 "${filename}-black-hd.png" "${filename}-black.png" #convert -filter Sinc -background none -density 1200 -resize 24x24 "${filename}-white-hd.png" "${filename}-white.png" mv -f "${filename}-black.png" "${filename}-white.png" ./ done Carla-2.1/resources/cursors/zoom-area-black.png000066400000000000000000000015621364475620200215770ustar00rootroot00000000000000PNG  IHDRJ~sgAMA a cHRMz&u0`:pQ<bKGD#2 pHYsmtIME ,@A@IDAT8ˍMHTQ7c>^HEEbn6(A&M(HBm(R,#Qyɐ ́d3;mRms8p{.#@6%*, Tc$Ҁ=!Au7+ (-r m ?wU˼˲'r„o)!]f^}FpOok"{K\ibٓ8W!9J3eQ) ZND6}/-^XQ&l.ni@BKTwο{L\yے 7Ԟq?/^H@N^:y&l3WJ*|wvD mhħ}X[d8fO_g yr5(Pu>yN- p!K[fG#behÝ?_oT5A ~FeDw {W@v ;@b1?!_Gv"5X(@jU1-v p!}Y lSŘν mԳ`/ќ8l$o`g)%tEXtdate:create2018-10-01T12:08:44+05:00j %tEXtdate:modify2018-10-01T12:08:44+05:007tEXtSoftwarewww.inkscape.org<IENDB`Carla-2.1/resources/cursors/zoom-area-white.png000066400000000000000000000026651364475620200216500ustar00rootroot00000000000000PNG  IHDRw=gAMA a cHRMz&u0`:pQ<bKGDC pHYs+tIME -pIDATHǝ]lUǟ9=/]G[>XŰ(؅L0&\B@>L;.\, ba00I(KAm2uڵtm9^t$'yO^`is5UϘLæ" %cZTo45t0i+ڴiohkpӢEo34r@3puEb:OVk/p{ JџG]/kn~ϵ|y>+p8>HB3g.p8v,(*Z-PD -t}s.NB}6)5AB6Ɣv_L~ԩVZ) FaF#wcjiS$@=tb.)[k&g;<d>(PJR̙UFPpp']"=b\ьX(2P)sG8xbx67DPn/&w ڋ<+ d?LŔ)U<J/v:D,/oD&o~]_C#MBGfX}]F8 P.^@$ yDV1(d2fa÷iHKp8RPK'u}Bu 10G(bٜYql֭/&!R;;W+&rMLIF:6sڊW\^25qB+^U޾ԤQ*CR2~7Z ( J=w!ΝbѝDl2sG",^yЊe--DÓLe2R&}0;)%۶}q4Frl՜"n-?౔i)SQr!P 'l@)R&$b9M^2MTUzWJK '`6 r^^R]wkOO#!JJCD"]e>ߞLBzYԗ,7&fvbK]϶<~u_v&{_g"3/)ɒSC#1%VkܽwP-IĪbn{;VK bE.ɢ*Tw- I; +u:^ur!ƥĆTdix7Q$1<3}7*\,?)5 Bg/w?*f`8ck!%tEXtdate:create2018-10-01T12:08:45+05:00%tEXtdate:modify2018-10-01T12:08:45+05:00v@tEXtSoftwarewww.inkscape.org<IENDB`Carla-2.1/resources/cursors/zoom-generic-white.png000066400000000000000000000023701364475620200223450ustar00rootroot00000000000000PNG  IHDRw=gAMA a cHRMz&u0`:pQ<bKGDC pHYs+tIME .l!mIDATHǽOH\W9qꟙ)1gRM H4ƍH!]daB$)d%l颤. i%ؖ&8UjØ3V'Ϙ̼{O϶VgFw|<`/> Jʴ ac! °LM-,~dg$p6;h(-};8Pl0 HH$z?,9LfdvW08^ssMH"XfVG,/pP{{ݑuɻFeeoRk|QVvQG D4׿2^z@jDRBGRۿDQJ15RQ=7FRfYs"X^\0;Y:u ș/E?%0;,Y"6+ @Qon@$`ŵ{͸. xQ2Hc| @(" wugBV>&ej*?20@kVcwW9V͛#J=y y>':=h9 V ;\=)Exo+'RNut^zz"nw2s BUյҥ΃|_KKQI(xc̖?E^TjKoO-Ѣe~Bg{=&QYB*~ǖK*QJ=й5f꠹ im蔦ռ- U^3:wrn.:2?pmt:jJ2(d]<$AN',kѣOzm-J!=GDOe3"ORlifV%tEXtdate:create2018-10-01T12:08:46+05:006 #%tEXtdate:modify2018-10-01T12:08:46+05:00GtEXtSoftwarewww.inkscape.org<IENDB`Carla-2.1/resources/cursors/zoom-in-black.png000066400000000000000000000015621364475620200212750ustar00rootroot00000000000000PNG  IHDRJ~sgAMA a cHRMz&u0`:pQ<bKGD#2 pHYsmtIME .l!m@IDAT8ˍMhao$%ШD6A+M$/w/9ZfhODC- Cz`SٶՀ5(mTwnͼ3Sw͛mU4Ⱦ\(SL8ƯzDe0vgj4|7|ɨj%. 4WX,d"3F62,1,f[b qA @E_Vu+x *T0H0ۃ70Cj 4X<ɞ+>++FPWKB7m?{@Ws}&@`Es}YslAT0P tev汅흅0e`B \p#*~ pj٠4<;zvڹXIޣ(Ȍ. +0FT^;n՝8ݷ]w Ĺ.H ##E9y+I WܤuOüzOTW̐; ?>3J=X]t4q\ ntd+ l@3tq'ኗ5%@S=%C{vLP0%tEXtdate:create2018-10-01T12:08:46+05:006 #%tEXtdate:modify2018-10-01T12:08:46+05:00GtEXtSoftwarewww.inkscape.org<IENDB`Carla-2.1/resources/cursors/zoom-in-white.png000066400000000000000000000026551364475620200213450ustar00rootroot00000000000000PNG  IHDRw=gAMA a cHRMz&u0`:pQ<bKGDC pHYs+tIME /wIDATHǝlSUǿ^ [&102,Ju,&  h a!1ǔ¢&A qC~ 6:d[XGF۵GAhKINnr9{r 笒) JzYG@DZJ+TpTj Pl5*+{aykw.l̹A)JB2Q'SJJ紶wѢ':Itj`Y+릦H8ٿXz,v+zOTT?xI0a)Y>;],vkY R(HV0x"r9L1'4֤I74:F J<Y />2ҥ14pS{Fy۷LU02 Y9 mw˲*38\=7&G/0UyK̹f:S~ ҹ4Ĕ8$S|>WYd]uR9B5" ^ZVK~LǷ=n$tuطRuXgUNH/@B0j*n`@m7*gsu14K?>yqZmg4^4NW'W ^yõ#[E,a. =uOKHnI:%3ӏuT&)gϗ;A-HkH'? O@eH,L6!CjAWNH8ɌU/[, ź Ev-Hވ;I%tEXtdate:create2018-10-01T12:08:47+05:00%tEXtdate:modify2018-10-01T12:08:47+05:00߿+tEXtSoftwarewww.inkscape.org<IENDB`Carla-2.1/resources/cursors/zoom-out-white.png000066400000000000000000000025341364475620200215420ustar00rootroot00000000000000PNG  IHDRw=gAMA a cHRMz&u0`:pQ<bKGDC pHYs+tIME 0&IDATHǝ_lUǿ~%csqCaT0AL6ѐH41HHL faȃApnYxmEF_ ]Civ'9/w7?lqԷBa@0_DdZǮLM]H&/% feۏK<ի=؀H.@Кg6opX%#I@g֬ƚ5-'O"f{b|?_aCop_E@EEKظs_UT\UR"r3)KJV>[O?~Xl|yE@lsNx;89xq"I#bPcDqo~$O K0  # "ba*HYk#uZt{E4DR΋_]hua:7D s= SeeO协)swu$Y^ήh}`pxy{΍ =? ) bHH$r Ϭ@ȥԜم2X9]$P[55tY{J/-}n`_ȊHe(+"x^oʽ{ƌRvxi200zq́1D{wjikk}>cW@;e5X^oS{oכ(%yiwDRlgҭx@d#@_#sdCܴ;t_Н;cT1w_ @Q3Wˬgno nNL ]wv/11@"ZRٕ(0XOXȘ1fF_>:ɀ0D ,1QÜ߽Y\^^Uַ^XoK 4ٰAdY˪wo2&EС˭{w篬f.Fڵ{BZZ>r>P4g!}~&'G/eBn\aa+Xy00I$&: GDR ,W> W$ԕ7~Ӳ(ƃf^RvW!bEz%tEXtdate:create2018-10-01T12:08:48+05:00fw~%tEXtdate:modify2018-10-01T12:08:48+05:00tEXtSoftwarewww.inkscape.org<IENDB`Carla-2.1/resources/fonts/000077500000000000000000000000001364475620200155525ustar00rootroot00000000000000Carla-2.1/resources/fonts/uranium.ttf000066400000000000000000001073641364475620200177640ustar00rootroot00000000000000@OS/2UsaVPCLTB뵲@6cmapr̦u8cvt !aPfpgm3O<glyfegXhdmx(v}Hheadvx6hhea $hmtxvQokernJ|loca-5Ljmaxp( name?57 .postpnhs7prep8h9&B!j !cx  B! j       Copyright by dustBUST Fonts 2001.Copyright by dustBUST Fonts 2001.UraniumUraniumRegularRegularUraniumUraniumdustBUST UraniumdustBUST UraniumVersion 1.0Version 1.0UraniumUranium@,vE %E#ah#h`D- ,,XXZ]@ EhDEhDEhDEhDEhDF+F+EhDEhDQ9LV@ @ Fv/7?@@Fv/7/@         Fv/7?@         Fv/7?@@Fv/7?@         Fv/7?@@Fv/7/>?@fA>BBCD.DEEFDFGHInJ.K,K,LLMN"NOOOPQRSlT~UvV~WXYYZ[b[\6\\]t^\_B``aabcXddefhfhgXQ  ,X,,,X,,@@X,@@@@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~ overscoremu1middot!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~ "  "!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~-C4F4FJ0Fj0L4?L7#LT.LaP7TJKTjKc4f4fJ0fj0l4?l7#lT.lap7r4rJ rj t4t7#tT>                                                                                                                                                                                                        MMMAPMACR@ L8dL  ` uUranium 7URAR00>>222222222222222222222222222222222222>>>000888>>>>>>???===[H;fK7fK7RA4<<<000LLnn//VJJJQQQeeefff@@@`K;aH6C1$3(;;;88C݊ooocc666OOOPPPKKKFFF_L=`J;7-';;;000ss??x@@@PPPaaa]]]LLLdM8+ ;;;888%%%$$($$(003336336336336<9:@<;655333<<<;;;+++**.**/226559559559448448559558666>>>000""$666;;;;;;===:::dMeM>>22211211266799:99:99:88988899:99::::>>>(0` 333++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++333+++ """!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!""" +++ "/8>@AAAAAAAAAAAAAAAAAAAAAAAAAA@>8/"  4 Z---445667;=?EFGMNPXXX]^^\\\Y[[XYYVXXUXXPSSIMNCGIB>EGEIKKPQPUVSXXLPPEHI=AA7:;123,.0(*+%&' "# $&& #Z4  <+++9:::<<9>=9?>:.=9.<8-;8,97,86+75*65)54)43(22'12'01&/0%./%-/$,.#*-#*,")-!(+ (, (+'*'+&)&)%)%($)*02DHH9<<4 "Z./16?<3E>3D?3C>2B>1A<1@<0?;/>:/=9.<9-:8-97,86,76+65+54*43)23)12(01'/0'.0&-/%,.%,-$+.#*,"*-"*, ),!)-',&*%*%($)079MRS(((\" """/ !#.125G@5G@4F@6GB6GC7GB6FB6DB5CA4B@4A?3@?2??2=>1==0<=0;GL>FL>FL=DKG8>F6 $'1:87JA8KE@QMHMMIKMJLNKMOKMOKMOKLOKLOJLNJLNJLNJLNJLNJKNJKNJKNJKNJKNJKNJKNJKMIJMIJMIJMIJMIJMIJMIJMHILGHJCEH,4:"+/&*%);BCJMM>$$$333+++###@ #%0:89LC;NFEUUFGHDDF39B$-2 ),%*RJL[ZGIJ,,,:::::::::::::::::::::::::::000CI)&&&EFH:@H(/4!)-'+:ABIMMA!!!++++++!!!A"$0:7:PE>RKL\\GIJ++...2,,,GGGNNN;;;EEEOOO:::BBBQQQ;;;000CI)&&&EFH;AK(/4"*,'+:@AHMMA!!!++++++!!!A"$0:8;QF?SKL]]GIJ''-;;gQQPP;;k//9,,,TTT~~~ZZZwwwZZZ///>B+{{`vAPAPAP;H&&&FFI:AJ*06"*, (+:@AGLLA!!!++++++!!!A $0;7;RG@TLM^]GIJ;;d99n""",,,iiiSSSiiiYYYaaa[[[000CI)o&&&FFI?FIIA!!!++++++!!!A #0;7>VIBXOOa_HIJ;;n<EL+38&,/#*-8>?EIIA!!!++++++!!!A#/<7>WJCYOOb`HIJ))4PPNN22A,,,:::XXXnnn\\\QQQwwwbbb:::000*D*&&&FGI>EM,58&-0$+.8=?EHIA!!!++++++!!!A!/;8?YKCZPPc`HIK !00=22@$$&,,,:::::::::::::::::::::::::::000*G*&&&FGI?FN-69'/0%-/8=?CGHA!!!++++++!!!A!0<8@ZLD\QPc`HJK,,,:::::::::::::::::::::::::::000)I)&&&FGI?GO.7:(01%./8=?CGGA!!!++++++!!!A!/;7A[LE]RQeaHJK,,,<<<<<<<<<<<<<<<<<<<<<<<<<<<1112@2#########---&&&FGI@HO.8:)12&/07<=BFGA!!!++++++!!!A!/<8A\ME^SRfbHJK###########################FGIAIO/9:)23'016<=AEFA!!!++++++!!!A /<8B]NE_SRgcJKLEFFFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGFFGEEFJJKAJP0:;*43(226<=AEEA!!!++++++!!!A /<8C_OF`TRgcIJKGHJAKQ1;<+54(336<=AEEA!!!++++++!!!A0<8E`PGaTSicHJK'''333333333333333333333333333***///333333333333333333333333###FGIBLR1<=,65)435<<@CCA!!!++++++!!!A0<8GaRIbUTjdHJK,,,:::::::::::::::::::::::::::000CI)&&&FGICMR2>>,76*545<<>CCA!!!++++++!!!A1<9IbSKcWVjeHJK))+,,/,,,FFFLLL:::DDDNNN;;;BBBOOO<<<000CI)&&&FHIDNR3?>,97*755;<>BBA!!!++++++!!!A1;9LcUNdYWkgHJK&&+;;eOOLL==k..7,,,SSS~~~YYYwwwZZZ///=A+ww^sAPAPAP;H&&&FHIDOS4@?-:7+865;;=AAA!!!++++++!!!A2<9NdWPeZYlhHJK;;b~~99m!!!,,,kkkTTTkkkZZZbbbYYY000CI)o&&&GHIEOT4A@.;8,964;;=AAA!!!++++++!!!A2<9PdXRf\[miIJK))+jj}}}xxxNN77A,,,:::999::::::999::::::999:::000BH*j&&&GHIEQT5BA.<9-:74;;<@@A!!!++++++!!!A2;9SeZTf]\mjIJK**/vvvrrrbb99F,,,:::HHHnnnLLLmmmWWWdddaaa:::0000?0)))&&&GHJERU6DB/>:-;84;:;>>A!!!++++++!!!A2;:Uf[Vg__nkIKL<>{%%',,,:::uuu:::wwwrrrkkksss::::::000)I)&&&GHJFRV6EB0?;.=93::;=>A!!!++++++!!!A3;:Wg]Xh``nmIKL**6UUQQ33C,,,:::XXXnnn\\\QQQwwwbbb:::000*E*&&&GHJGSV7EC1@;/>:3:::==A!!!++++++!!!A4;;Zh^ZibbonIKL!!#11@33D%%(,,,:::::::::::::::::::::::::::000*F*&&&GHJHUW8FD1A<0?:3::8<=A!!!++++++!!!A4;:\i`]jbepoIKL,,,:::::::::::::::::::::::::::000)I)&&&GHJHVW8HE2C=0@;3:98;<A!!!++++++###@5;;^ja^jdeppIKL,,,:::::::::::::::::::::::::::0000?0 ***&&&GHJGUW8HD3D>1B<3:97;;@!!!+++333$$$>5;;akc`keepmIJK&&&&&&&&&&&&&&&&&&&&&&&&&&& ########################FHHETS8ID5E@2C=2:97:;>$$$3333338-23bkdbleeokNPPIJKJKLJKLJKLIKLIKLIKLIKLIKLIJLHJKHJKHJKHJKHJKHJKHJKHJKHJKHJKHJKHJKHIKHIKHIKHIKHIKGIJFHIILLARN8ID4E?3D>2773678333"""/"&ckecleclgenkfpneppeqqdqpbpnaom_ol]nk\mjZliYlgWlfVkfUieTidThdSgcSfcSfbRebQcaQb`Pb`Pa`O`_O_^M]^K[[HXWBSP;MH7JB4F@3D>145/02/""" "Z#EJIdleclebkeakf`ke^ke[jcYibWh`Vg_Tf^Qe\Od[McZLcYJcWHbVGaUF_TF^TE]SD\RD[QCZQBXPBWOAWO@VO@UN@TM?SL=PJ;NF8LC6IA5H@,53/23"""\" 4!$)IMKelebkdakc_ia]ha[h`Yg_Vf]Te\RdZPcYNbWKaVIaTG`SE`QC_PB^OB]NA[N@ZM?YL?XK>WK=VJ=TI4>;/55(++#$&=  4](((000224356556669<=>EFGNPPXXX]]]\\\Y[[XYYVXXUXXPSSIMNBGIB>EGEILKPQPVVRWWLPPEHH=AA78:123,..()*"#%]4  "/8>@AAAAAAAAAAAAAAAAAAAAAAAAAA@>8/" +++ """!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!""" +++333++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++333( 333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333+++$$$$$$                                                                              $$$$$$+++333+++            +++333333$$$     $$$333+++ """"#%'()))**********************************************************************)))('%#"""" +++333$$$   $).1479:;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;:9741.)$   $$$333333  !'/5;@EILNOPQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRQPONLIE@;5/'! 333+++ &/7?HOV[`ekmnoooop p p p !!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p !!p !!p !!p !!p p p p p pppppppppppp p p p p p p !!p !!p !!p p p p pppppppppppppppoooonmke`[VOH?7/& +++333 "+5?JTa+++4558:;;<==>?=?A>?A>@BCDFHIKLMOQRSUVWYZ[^_`bcdghhlllqqqqrrqqqpppoppnoomoolnnlnnkmmjllillhkkgkkfjjfiidhhaef]bcZ_`V\^TY[PVYMSVJPTFMQCJO@GLCJNFMQHOSKRVNUXQWZTZ\V]_Y`a\bc_efahhekkekkagg^cc[``W\\TXYPTUMQQIMMFIJBFG?BC;?@8;<69:478256034.12,.0+,.)+,'(*%&(#$&!"$ " !#$&'&()$%&aTJ?5+" +++  #.9ER_000:;;;;<;<=<=>=>?=>@=?A>?A>@BCDFGHJLMOPQSUVWYZ[]^_bcdggglllpppqrrqqqpppoppnoomoolnnlnnkmmjllillhkkgkkfjjfiidhhaef^bcZ_`W\^TY[QVYMSVJPTGMRCJOAGLCJNELPHOSKRUNUXQWZSZ\V]_Y_a\bc^efahhdjjekkagg^cc[``W\]TXYPUUMQQINNFIJBFG?BC;?@8;<69:478256034.12-/0+,.)+,')*%&(#%&!"$ " !#$&(*,-.12357.01_RF9.# $$$ #/;JX###|666::;:;;;<=<=><=?=>?=>@=?A>?A>@BBDFGHJKMNPQSTUVYZ[]^_bcdgggkkkppprrrqqqpqqoppnoomoolnnlnnkmmjllillhkkgkkgjjfiidhhaef^bc[_aW\^TY\QVYNSWJPTGMRCJOAGLBINELPHOSKRUMTWQWZSZ\V]_Y_a[bc^efaghdjjekkagg^dd[``W\]TYYPUUMRRINNFJKBFG?CD;?@8;<69:478356034/12-/0+-.)+,')*%&(#%&!#% " "$&()+,.123578;<8<=&'(}XJ</# +++ !-;K\...999::::;<;<<<<=;>>7?=6@=5?=4@=4?=4?=5@>6A?8C@8CA:EB;EC=GD>GE?IG@IGBKIBLJBKIAKIAJH@IH@IH?HG?HG>GG>GF>FF=FE>4<>3;=2:<08;/8:.69.69/7908:18;19;29;3:<3:=4;=5<>6=?7=@6>@7>A6=@4<>3:<29;17:068.57-46,25*14)03(/2'-0&-0%,/%+/$+.#*,"),!(+!(* &)&)%($(#'#& %('*,-013577:;<@A@DE7;;\K<." +++ +9I\111888999:;;;;<9=<5@<1B<1B<1A<0A;0@;0@;0?;/?:/>:/>:/>9.=9.=9.<9.<8-;8-;8-;8-:7,:7,97,96,86+86+86+75+75*65*64*54*54)44)43)43(33(33(22(22'12'11'11'01&01&/0&/0&.0%./%-/%-/%-/$,.$,.$+.$+.#*-#*-#*-#*-"*-"*-")-")-!)+!(+!(+!(+ (+ (+ '+'+'+'+'+'+'*'*')&)&)&)%)%)%)%)%)$)$)$) '+/247:;:/>9.=9.=9.<9.<8-;8-;8-;8-:7,:7,97,96,86+86+86+75+75*65*65*54*54)54)43)43(33(33(22(22'12'11'11'01&01&/0&/0&.0%.0%-/%-/%-/$,.$,.$+.$+.#+-#*-#*-#*-"*-"*-")-"),!(+!(+!(+!(+ (+ (+ '+ '+'+'+'+'*'*'*')&)&)%)%)%)%)%)%)$)$)$)%)*03ABXF5& $$$!/?R !|0124458989<;5C=3D>2D=2C=2C=2B<1B<1B<1A<1A;0@;0@;0?;/?:/?:/>:/>9.=9.=9.<9.<8-;8-;8-;8-:7,:7,97,96,86+86+86+75+75*65*65*54*54)54)43)43)33(33(22(22'12'11'11'01&01&/0&/0&.0%.0%./%-/%-/$,.$,.$+.$+.#+-#*-#*-#*-"*-"*-")-"),!(,!(+!(+!(+ (+ (+ '+ '+'+'+'*'*'*'*')&)&)%)%)%)%)%)%)%)$)$($(#*.<@BEIIJOOMRS-//R?/!+++ '8J_+,.0124668984C=3E>3E>3D>2D=2C=2C=2C=1B<1B<1A<1A;0@;0@;0?;0?:/?:/>:/>9.=9.=9.<9.<8-;8-;8-;8-:7,:7,97,96,86+86+86+75+75*65*65*54*54)54)43)43)33(33(22(22'12'11'11'01&01&/0&/0&.0%.0%./%-/%-/$,.$,.$+.$+.#+-#*-#*-#*-"*-"*-")-"),!(,!(+!(+!(+ (+ (+ (+ '+'+'+'+'*'*'*')&)%)%)%)%)%)%)%)%($($($(#+/EIIINNNSTMRRaJ8( +++   /@T$%'-/00234666?;4F?3F?3E>3E>3D>2D=2C>3D>3D>2C=2B=2A=2A<1@<1@<1@<1@;0@;0?;0?;/>:/>:/=:/=9.=9.<9.<9.;8-;8-:8-:7-97,97,97,86,86+76+76+65+65*65*54*54*44)44)33)33)33(22(22(12'12'01'01'/1&/1&/0&.0&.0%-/%-/%,/%,/$,.$+.$+.$+.#+.#+.#*.#*-")-"),"),"),!),!),!),!(, (, (, (+ (+(+(+(*'*&*%*%)%)%)%)%)%($($($(29;INNMRSSXXEIIT@/  333 %5Ha(*--/10343874G?4F?4F?3F?3E>4F?4E?3D>3C?3D>3D>2C>2C>3C>3C=2B=2B=2A=2A<1A<1@<1@<1?;0?;0>;0>:/>:/=:/=:/<9.<9.;9.;9.:8-:8-:8-97-97,87,87,76,76+76+65+65+55*55*44*44*44)34)33)23(23(12(12(02'02'01'/1'/1&.0&.0&-0&-0%-/%,/%,/%,/$,/$,/$+/$+.#+.#*-#*-#*-"*-"*-"*-")-!)-!)-!),"), (, (, )+ (+&*&*&*%*%)%)%)%($($(%*BHIMRSRWXV[[bH5% 333+++ *;O!")+.,.00345C=5G@4G?4F?4F@4G@4E?4F?4E@4F@5E@5E@5FA4E@4E@5DA5D@4C@4C@4C@4C?3C?3B?3B?3A>2A>2@>2@=1@=1?=1?=1><0><0=<0=<0<;/<;/<;/;:/;:.::.::.:9.99-99-88-88-78,78,67,67,67+57+56+46+46+35+35+25*25*24*14*14)03)03)03)/3(/2(.2(.2(.2'.2'.2'-2'-1&-1&,0&,0&,0%,0%,0%,0%+0$+0#*0#+/#+/!*.!*. ), '+'+&+&*&*%)%)%)%($)$)'/3MRSRWXW]]8;;O;* +++$$$ .@V"%')+-,/11545H@5H@5G@4G@5G@5FA5GA5GA6GA6GB6GB7IC8HC8HD8HD8GD8FD8FD7ED7ED7ED7EC6EC6DC6DC6CB5CB5BB5BA4BA4AA4AA4@@3@@3?@3?@3??2>?2>?2=>2=>1<>1<>1<=1;=0;=0:<0:<09B4>B4>A4=A4=A329>29>18>18=18=17=07=06=06=06=/6=/6=/5=/5<.5<.4;.4;.4;-4;-4;-4:,3:,39+29)16(/5&.3%-1#,/!)-'+'+&*%*%)%)%)%)$)9?BQVWV\\QVV[E1" $$$ """#4I`$'*(*-,/13?;6IA5IA6IA6H@6HA6HB7IC9JE:KHNK?NMAPNAPOBPPCQQBPQBPQCPQCPQBOPBOPBOPBNOANOANOANOAMNAMNAMNALNALN@KN@KN@JM?JM?IM?IM?IL>IL>IL>HK>HK=GK=GK=GJ=FJF8>E8=E8=E8=E7=E7=E7-4:+28(05%.2#+/!)-&+&+&*%)%)%)%)%)29;QVWU[[TYY`I4#"""  %7Le%(+(*-,/14A<6JA6IA6JB6IA7JC8ID9KE;LG=NJAQOCRQETTGTWIVXJWYJWZKW[JWZKW[KW[KW[JWZJVZJVZJUZIUZITZITZITYITYITYISYISXHRXHRXHRWHRWGQWGQWGQWGPWGPWGOVGOVFOVFOVFOUFNUENUEMUEMTELTDLTDLTDLTDLTDKTDKSDJSDJSCIRCIRCIRBIRBIQBHQBHQAGQAGQAGQAGQAGPAFPAFPAFP@FP@FP@EP@EO?EO?DO?DN>DN=CM,39'05%.3#,/!),'*&*%*%)%)%)%).58QVWU[[X^^eL7% 333'8Ml$'*(*-,.04C=6JA6JA7IA6JC8JC:LE;LH=NJCROFSRJUWLWZOZ]PZ_R[`R[aS\aS\bR[aR[aR[aR[aR[aRZaRZaRZ`QZ`QZ`QZ`QY_PY_PY_PX_PX_PX_PX_PW_PW_OW_OV_OV_OV_OV_OU_OU^OU^OU^OU]OU]NU]NT]NT]NT]NT]NT\NS\NS\MR\MR[MR[MR[LR[LQ[LQ[LP[LPZLPZLPZKOZKOZKOZKOZJOZJOZJOZJOZJOZJOZJNZJNZJNYJNYJNYIMXHLVFJUDIRAEO>CK:?F4:@,3:(06$-2"+/ (+'+%*&)%)%)%)+36PUVU[[X^^lM8'333333(:On$'*'*,,.04C=6KB7KB7KB8KD8KE;MF=OJAQNHRQMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMFHJ07>+29&.3#+/!*- (+'*&)%)%)%)+46PUVUZZX^^ nO:(333333 );Pn#'*'*,+.04C=7KB7LC7KB8KC:LF7LB8LC7LC9LD:NG>OKASPFUUMWXMMM555$$$MMMIKN8>H07?+28&.2"+/ (,(+')&)&)&),36OTUTYYY__ oQ;) 333333 *<Qo#'*'),+.05C>7LC8LB8LC8MF;NG?QKCSQHXXOXZMMM555$$$MMMJLO:@K39B,3:'.3$,/ (,(,'*')&)&)+35OTUTYYX^^ oQ<* 333333 *<Rp#&)'),+-/5D>8LC8LC9ND9LF8MC9LC9NE:NG=OIASNEVSL[[R[^MMM555GGGCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCEEE+++777AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFF $$$MMMLMQ>DO6=E/5<)/5%,0!). (,'*'*'*'),35NSTSXXX^^ pR<* 333333 *<Rp"%)&)+*,/5E>8MC9MC:NE:NG>QJASNGWUL[\S[^MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;:::@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3=?4666888DDD!!!$$$MMMMNRAFP7=F/6<*06&,1!). (-'+'*'*'*,36MRSSXXW]] pR<* 333333 *<Rp"%)&)+*,/5D>8ND9MC:NE;OG=QKBTNHXVM\]S[_MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMMMNRAFQ7=E07=)15&-1"). (-'+'*'*'*,36MRSRWXW]] pR<* 333333 *<Rp"%)%(+*,/5E>9ND9ND:NE;OG>RKBTOGYUN]^T\`MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMMMNRBFR8>F17=)15&-1"*.!(-'+'+'+'++36MRSRWXV\\ pR<* 333333 *<Rp"%(%(+*,.5E?9OD:ND:OF;OG>RKCUOGYVN]^T\`MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMMMNRBGR8>F17=*15&-1"*.!)- '+'+'+'+,36MQRRWXV\\ pR<* 333333 *<Rp"%(%(+*,.5F?9OE:OD;OF;PH>RKCUOHYVN]_T\`MMM555DDD::::::999;;;999666::::::::::::999;;;999555999:::::::::999;;;;;;555888:::>>>000;;;=>6DDD!!!$$$MMMMNRBGR8?G17=*15&-1"*.!)- (+ '+'+'+,35MQRQVWV\\ pR<* 333333 *<Rp"%(%(+)+.6F?9PE:OE;PFSKCVPHYVO^_T\`MMM555 111CCC???,,,DDD:::BBBzzz{{{kkkNNN555::::::???mmmoooXXX666999:::;;;\\\sss```;;;888>>>000;;;=>6DDD!!!$$$MMMMORBGS9?G18>*15&-1#*.!)- (+ (+ '+'+,35LQQQVWU[[ pR<* 333333 *<Rp!$(%(+)+.5F>:PE:PE;PG>>000;;;=>6DDD!!!$$$MMMMORBHS9?H28>*26&-1#*.")- (+ (+ (+ '+,35LQQPUVU[[ pR<* 333333 *<Rp!$($'*)+.5F?:QE;PE;QG>>DDDVVV|||lll888FFFppp>>>:::tttIII;;;000;;;998+5+5+5+5+5+5+5"          DDD!!!$$$MMMMORBHS9?H18?+26&.2#*.")-!(+ (+ (+ (+,25LQQPUVU[[ pR<* 333333 *<Rp $'$'*(+-6F?:QF;QE6DDD!!!$$$MMMMORCHS9?H18?+27'.2#+/")-!(+!(+ (+ (+,35KPPPUVUZZ pR<* 333333 *<Rp $'#'*(+-6G?;QF;QF>>ddd>>>999|||fffBBB>>>000;;;=>6DDD!!!$$$MMMMORCHS:?H18?+37'.3$+0"*.!(+!(+!(+ (+,35KPPOTUUZZ pR<* 333333 *<Rp $'#'*(*-6G@;RF>>000;;;=>6DDD!!!$$$MMMMOSCHS:?H28?+37'/3$+0#*/!),!(+!(+!(+,35JOOOTUTYY pR<* 333333 *<Rp #'#'*(*-6H@;RG>>000;;;=>6DDD!!!$$$MMMMOSCIT:?H28?,37'/3$,0#+/")-!),!(+!(+,35JOOOTUTYY pR<* 333333 *<Rp #'#&)(+-7G?;SGTJ@VMDYRJ\XP``U^aMMM555RRW''~yyy{{{++iKKyIIJDDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMMMOSDIT:@I28?,37(/3%,0#+/"*-")-!),!)+,34JOONSTTYY pR<* 333333 *<Rp#&#&)'+,7H@TJAWMDYRJ]YP``U^aMMM555\\\tttlllnnnxxxGGf77[[`DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMMMOSDIT;@I29@,37(/3%,0$+/"*-"*-")-!),,34INNNSTSXX pR<* 333333 *<Rp#&"%)'+,6H@TKAWMEZRJ]YPaaU^aMMM555&&&WW[..ooo^^^ffftttWWc''hhlDDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;:::DH0DH0DH0DH0DH0DH0DH0775555555555555555555555555555555555555777DDD!!!$$$MMMMOSDIT;AI39@-38(/3%,0$+/#*-"*-"*-")--36INNMRSSXX pR<* 333333 *<Rp#&"%)&),6H@TI>UKAWNEZRK^YPaaU^aMMM555YYYsssjjjlllwwwYYt44ZZ_DDD:::::::::::::::xxxGGG:::SSSDDD:::;;;~~~SSS:::::::::>>>000;;;:<:qqqqqqqqqqqqqP&&&&&&&&&&&&&&&&&&---DDD!!!$$$MMMMOSDJT;AI3:@-38)04%-0$+/#*-#*-"*-"*--36HMMMRSRWX pR<* 333333 *<Rp"&"%)&),7H@UJ?UKAWNE[SK^YQbaU^aMMM555NNS$$}wwwyyyDD}FFwIIIDDD::::::::::::aaa@@@hhhjjjOOO:::^^^ddd:::::::::>>>000;;;6>6DDD!!!$$$MMMMOSDJT;BI3:@-48)04&-1$,/#*-#*-#*-"*--36HMMMRSRWX pR<* 333333 *<Rp"&"%(&),7IA=UH=UH>UJ?VLBWNE[SK^YQbbU_aMMM555BBE44p&&[[l666DDD::::::::::::JJJ:::::::::::::::hhhKKK<<<::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMMOSDKT;BI4;A-48)14&-1%,0#+-#*-#*-#*-,35HMMMQRRWX pR<* 333333 *<Rp"%"%(&),7IA=VI>UH?VJ?VLBXOF[SK^YQcbU_bMMM555***SSVaa22}``cDDD:::::::::FFF:::::::::;;;^^^bbb:::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMNOSDKU;CI4;A.59)14&.1%,0$+.#+-#*-#*--35GLLMQRQVW pR<* 333333 *<Rp"%!$(&),7IA=VI>VI?VJ@WLBXOF[TK_YQcbU`bMMM555==?DD`DD bbf///DDD::::::::::::HHH::::::oooPPP::::::MMM;;;::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMNPSEKU;CJ4WI>VI?WK@WLCYOF[TK_ZQcbU`bMMM555MMQ<>>000;;;6>6DDD!!!$$$MMMNPSEKUWJ?WI?WK@XMCYPG\TK_ZQcbV`bMMM555 DDHNNX%%|MM{{__1166u^^a??ADDD::::::::::::;;;NNN::::::yyybbb:::<<<^^^:::::::::>>>000;;;7=7yDDD!!!$$$MMMNPSEKUXJ?WJ@XK@XMCZPG\UL`ZQcbV`bMMM555111RRUUUWII_99n>>kPP`]]]RRV(((DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;7:7``````````]DDD!!!$$$MMMNPSELVXJ?XJ@XLAYMCZPG]UL`[RdbV`bMMM555&&&222??A<<=000"""DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMNPSFLV=DK5=B/7:+46'03&/1%-/%-/$,/$,.-46EJJKPPOTU pR<* 333333 *<Rp $ $'$)+8JB?XJ?XJ@YLAYND[PG]ULa[RdcV`bMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMNPSFMV=DK6>B/7:+46(13&/2%./%-/%-/$,/-46EJJJOOOTUpR<* 333333 *<Rp $ #'$)+8JB?YK@YK@YLAZND[QH^ULa[RecV`bMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMNPSFMV=EK6>B08;+57(13'02&.0%./%-/%-/-46EJJJOONSTpR<* 333333 *<Rp $ #'$(*8KB?YK@YKAZMAZND\QH^VMb[RecVabMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMNPSFMV=EL6>B08;,57(24'02&/0&.0%./%-/-46EIIJOONSTpR<* 333333 *<Rp $#&$(*8KB@ZK@YKAZMB[OE\QH_VMb\SecVabMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMNPSFMV>FL6>C09;,57)24'13&/0&/0&.0%./-46EIIINNNSTpR<* 333333 *<Rp$#&#&*8LB@ZL@ZKAZMB[OE]RI_VMb\SedWabMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;8>8 DDD!!!$$$MMMNPTFNV>FL7?C09<,67)24(13&01&/0&/0&.0-56DHIINNMRSpR<* 333333 *<Rp$#&#'*8LB@[L@ZLB[MB[OE]RI`VNb\SfdWacMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::DDD!!!$$$MMMNQTFNW>GM7?C1:<,68)34(23'01&01&/0&/0.56DHIHMMMRSpR<* 333333 *<Rp$"&#'*8LC@[L@[LB[NB[OE^RI`VNc]TfdWbcMMM555===========================================================================>>>&&&///==================================================================@@@$$$MMMNQTGOW>GM7@D1:<-78)35(23'11'01&01&/0.56DHIHMMMQRpR<* 333333 *<Rp#"&#')8LCA\M@[LB\NB[PF^RIaVNc]TgeWbcMMM555$$$MMMNQTGOW?GM8@D1;=-78*45(24'11'11'01&01.56CGHHMMMQRpR<* 333333 *<Rp#"%#')8MCA\MA\MB\NB\PF^SJaVNd]TgeWbdMMM555$$$MMMOQTGPX?GM8AD2;=-89*45)34'12'11'11'01-56CGHGLLMQRpR<* 333333 *<Rp#"%"&)8MCA]MA\MC]NB\PF_SJaWOd]TheWbdMMMCCC777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777;;;MMMNPTHPX?HM8AD2<=.89*56)34(22(22'11'11.56BFGGLLLQQpR<* 333333 *<Rp#"%"&)9MCA]MA]MC]NC]QF_SJbWOe^TheT[\MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOHPX?HM8BE2<=.99+56)45(22(22(22'11.66BFGFKKLQQpR<* 333333 *<Rp#!%"&)9MCB^NA]MC^NC]QG`TJbWOe^TheV`bMMMJJJEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGGGMMMOPSHPY?IM8BE2=>.99+66*45(33(22(22(22.67BFGFKKLQQpR<* 333333 *<Rp"!%!&(:MDB^NB^ND^NC^QG`TKcXOe^TheWcdMMM555$$$MMMOQTHPY?IN8CE3=>.::+66*55)33(33(22(22.67AEFFKKKPPpR<* 333333 *<Rp" $!&(:NDC^OB^ND_OD^QGaTKcXPf^TheWcdMMM555$$$MMMOQTIQY?IN8CF3>>/::+77*55)43)33(33(22.66AEFEJJKPPpR<* 333333 *<Rp" $!$(;NDD_OC^OD_OD_RHaTKcXPf^UifXddMMM555$$$MMMOQTIQY@JN8CF3>?/::,77*66)43)43)33(33.76@DEEJJJOOpR<* 333333 *<Rp" $!$(;NDE_PD_OE_PD_RHbUKcXPg^UifXddMMM555BBB????????????????????????????????????????????????????????????????????????@@@)))333??????????????????????????????????????????????????????????????????CCC$$$MMMOQTIRY@JN9DF3>?/:;,87+66)54)44)43)33.77@DEEJJJOOpR<* 333333 *<Rp" $!$(;NEF_PE_PF`PE_SHbUKdYPg_UjfXddMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::DDD!!!$$$MMMORTIRY@KO9DG3>?/;;,88+76*54)54)44)43/67@DEEIIJOOpR<* 333333 *<Rp! $ $'>>000;;;=>6DDD!!!$$$MMMORTIRYAKO9EG3>@0;;,98+77*64*54)54)44/77?CDEIIINNpR<* 333333 *<Rp!$ $'>>000;;;=>6DDD!!!$$$MMMORTIRZAKO:EG3?@0;;-98+87*65*64*54)54.77?CDDHIINNpR<* 333333 *<Rp!$#'=OFH`RG`RHaRH`TJcWMeZQh`VkgYddMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMMORTISZAKP:EG4?@0<;-99,87+75*65*64*54.87>BCDHIHMMpR<* 333333 *<Rp!$#'>OFIaSH`RIaSIaUKcWNe[Rh`WkhYddMMM555DDD::::::999:::666777::::::::::::999999888666999:::::::::888999:::555999:::>>>000;;;=>6DDD!!!$$$MMMORTJSZALP:EH4@@1<;-:9,98+75+75*65*64/87>BCDHIHMMpR<* 333333 *<Rp!#$'>OGJaSIaSJbSIaVLdXOe[ShaWkhYdeMMM555+++;;;888%%%DDD:::AAAssszzziiiIII555::::::???ccc~~~mmmTTT555999:::;;;TTTqqq]]]888888>>>000;;;=>6DDD!!!$$$MMMORUJT[BLP:FH4@@1=;.:9,98+86+75+75*65/87>BCCGHHMMpR<* 333333 *<Rp #$&>OGKbTJaSKbTJbVLdYPf\TibXkhYdeMMM555+++XX]kkllln]]qbbqqqrmmpSSV!!!DDD@@@zzzjjjJJJ666:::sss~~~nnnXXX555:::VVVrrrbbb666>>>000;;;=>6DDD!!!$$$MMMORUJT[BMQ;FH4A@1=<.;9-98+86+86+75+75/88=ABCGHGLLpR<* 333333 *<Rp #$&?OGLbUKbTLbTKbWMeYQf]TibYliZdfMMM555BBDffh==z$$$$00q&&p{$$TTwllo666DDDTTT{{{kkk777EEEooo<<<888sssGGG<<<000;;;9983>3>3>3>3>3>3>.8.8.8.8.8.8.8.8.8.8.8!(DDD!!!$$$MMMORUJT[BMQ;GI5A@1><.;:-:8,86+86+86+75/87=ABBFGGLLpR<* 333333 *<Rp #$&@PHLbULbUMcULbWNeYQg]UicZliZefMMM555TTXWWi""SSrrxbbkDDKn33nnsEEFDDD]]]{{{;;;LLLCCC<<6DDD!!!$$$MMMORUKU[BMQ;GI5BA2><.<:-:9,96,86+86+86/87=ABBFGFKKpR<* 333333 *<Rp #"&@PHMcVMbUNcVMcXOeYRg^UjcZlj[efMMM555<<=XXf##\\c66Z$$qqs+++DDDOOO999@@@ccc>>>888YYYCCC>>>000;;;=>6DDD!!!$$$MMMORUKU[CNQ;HI5BA2?=/<:-;9,97,96,86+86/98<@ABFGFKKpR<* 333333 *<Rp ""&APHNcVMcVNcVNcYPeZSg^VjcZmj[efMMM555&&&__a""llr((gCC}bbfDDD999jjjHHH999:::TTTmmmZZZ999:::III{{{;;;>>>000;;;=>6DDD!!!$$$MMMORUKU[CNQ>>000;;;=>6DDD!!!$$$MMMPRUKU[COQ>>000;;;=>6DDD!!!$$$MMMPRUKV\COQ;.<:-;8-:7,:7,97/98>>000;;;=>6DDD!!!$$$MMMPRUKV\COR=II6DB3@>0>;/=:-;8-;8-:7,:7/98>>000;;;;;:MV&MV&MV&MV&MV&MV&MV&12.////////////////////////////////////333DDD!!!$$$MMMPRUKW\COR=JJ7DB3A>0??@DEEIIpR<* 333333 *<Rp!!%CQJSeYRdYReYRe\Tf]Vi`Zlf^nl\fhMMM555YYYsssiiilllvvvYYs22[[aDDD:::::::::::::::NNNyyyeee::::::===hhh{{{OOO:::::::::PPPyyykkk<<<:::::::::>>>000;;;:<:fffffffffffff#K#******************///DDD!!!$$$MMMPSULW\CPR=JJ7EC4A>0?;.<9.<8-;8-;8098;>??CDEIIpR<* 333333 *<Rp! %DQJSeZSeYSeZSe\Ug^WiaZlf_nm]fhMMM555PPU""~~~~wwwxxxFF}EExIIJDDD::::::::::::sss:::}}}::::::::::::>>>000;;;6>6DDD!!!$$$MMMPSULW]DPR=KJ7EC4B?1?;.=9.<9.<8-;80:9:=>?CDDHIpR<* 333333 *<Rp! %DQKTeZSeZTfZTe]Vg^Xjb[lg`nm]fhMMM555CCG33r))YYl777DDD::::::::::::WWW::::::rrr:::::::::WWWCCCAAA::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMPSULW]DQS>KJ7FC4B?1@=0>;.=9.=9.<9.<80:9:=>>BCDHIpR<* 333333 *<Rp! %EQKUf[TeZTf[Uf]Wg_Yjb\lg`nm^fhMMM555,,,RRW""gg//ccf DDD:::::::::DDD::::::::::::SSSyyy```:::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMPSULX]DQS>KK8FC4C?1@=0?9.=9.=9.<90:8:=>>BCCGHpR<* 333333 *<Rp! $FQKVf\Uf[Uf[Vf]Wh_Zjc]lg`on^fhMMM555@@CAAbPP``f444DDD:::::::::===???::::::\\\EEE:::UUU:::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMPSUMX^DRS>KK8GD5C@1A=0?:/>9.=9.=90:99<=>BCCGHpR<* 333333 *<Rp  $FRLWf\Vf\Vg\Vf]Xh`[kc^lhaon^giMMM555OOS77k;;!!QQiKKNDDD::::::::::::;;;PPPTTTttt::::::@@@<<>>000;;;6>6DDD!!!$$$MMMPSUMY^ERT>LK8GD5D@2A>0@:/>:/>9.=90;99<==ABCGHpR<* 333333 *<Rp $FRLXg]Wg\Wg]Wg^Yia[kd^mhboo^giMMM555###HHLKKZ$$[[mm:://z]]aDDGDDD::::::::::::IIIrrr:::<<>>000;;;6=6DDD!!!$$$MMMPSUMY^EST>LL8HD5D@2A>1@=/?:/>:/>:/>90;98;<=ABBFGpR<* 333333 *<Rp $GQLYg]Xg]Xh]Xg_Yia\ke_micpo_gjMMM555777TTUQQYBBc44r88pJJdYY]WWZ---DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;8:8PPPPPPPPPPMDDD!!!$$$MMMPSVMY^EST>ML9HE6E@2A>1@=0?;/?:/?:/>:1;98;<<@ABFGpR<* 333333 *<Rp $GRLYg^Yg]Yh^Yh_Zib\ke`njcpp`gjMMM555***777CCGAAC555(((DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMPSVMZ^FST>ML9IE6EA3B>1@=0@;0?;/?:/?:0;98;<<@ABFGpR<* 333333 *<Rp #HRMZh^Zh^Zh^Zh`[jb]kfanjdqp`gjMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMPSVMZ^FSU?NM9IE6FA3B?2A=0@;0@;0?;/?:0<97:;<@AAEFpR<* 333333 *<Rp#HSN[h_Zh^[i_[h`\jc^lfankeqp`hjMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMMPSVMZ^FSU?NM:IF6FA3C?2A>1A;0@;0@;0?;1<97:;>>000;;;6>6DDD!!!$$$MMMPTVNZ_FTU?NM:IF7GB3C?2B>1A<1A;0@;0@;1<969:>>000;;;6>6DDD!!!$$$MMMPSVMZ^GTV?OM:IF7GB4D@2B>1B<1A<1A;0@;1<969:>>000;;;6=6DDD!!!$$$MMMPSVN[]FTU?NM:KF7HB4D@3C?1B<1B<1A<1A;0<969:;>?@DEoQ<* 333333 );Qo"KSO_ja^ia^ja^jd^jdamhcolfqqahjMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::DDD!!!$$$MMMPSUN[^ETT@OM:JF7HB4E@3C?2C=1B<1B<1A<1=958:;>??CDoQ;) 333333 );Pn"KSP`jb_ja`jb_jc`lealgdolfqpagjMMM555BBB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@AAA)))000<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@@@$$$MMMOSUMZ]ETS?OM:KF7GB4F@3D?2C=2C=1B<1B<1=958::=>?CDnP;) 333333(:On"KTP`jc`jb`jb_jd`keamhcokfqqaghMMM555$$$MMMOSTJY[DSR?OL9JF7HC5F@4D@2D=2C=2C=1B<1=9479:=>>BCnO:(333333'8Ml"LTPakcakd`jb`kc`kebmgdojfpn`fhMMM555$$$MMMNRSIWWCSP>NK:KF6HB4F@4D?3D>2D=2C=2C=1=9479:=>>BClM8'333 %7Le"JPMbkdbldakdakeakfblgcnidom_eeMMMAAA444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444888MMMMQRFUUARN=NJ9JE7IB4F@4F?3D>3D>2D=2C=1=94799<=>BCeL7%  """#4I`!DJHckdclebldbkebkeblgcmidnj^edMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMLPPDTR?PL;MH8JD7HB5G@4F?3E>3D>3D>2D=1;84689<=;?@`I4#""" $$$ "1E[!9??dleckdbkdakdbkeblecmhdmibkh^ed_ff`fhahiahkbhkbhlbhkbilbhlahlahl`hk`hk`hk`hk`gj_gj^gj^gj^gj]gi]fi]fh\fh\fh\fh[fh[fh[fh[fg[fgZefZefZefYefYdfYdfYdfYdfYdfYdfYdeYceYceYceYceXceXbeXbdXbdXbdXbdXbdWbdWadWadW`dW`dW`dW`cW`cW`cW`cW`cW`cV_cV_bV_bV^bV^bV^bV^bU]bU]aT]`S\^R[]OY[MWWKUUFSQAQN=OI:LF7ID6IA4F@4F@3E>3E>3D>3D>0964688;<9=>[E1" $$$$$$ .@V!#(+eledleckdclecleckfclgcmhdmifolfongqpgqqhrrhrsgrtgrtgrsgrsfrreqreqreqqdqqcqpbqpbpobpoapo`po`on_om_om^om]om]nl\nl\nk[mj[mjZmjYmjYliXliXliXlhXkhXkhXkhWjhWjhWjhWjgVigVigVigVhfUhfUgfUgeUgeUgeUgeUfeTfeTeeTeeTedSedSddSdcSdcSccSccSbcSbcRbcRbbRbbRabQabQ`aP`aQ_aO_`N^^M\\IZZGWVEURARN=OK;LG9KE8JB5HB5G@4F@4F?3E>3E>3E>/334688;<488V@. $$$+++ *;O $TZVeleemfckebkedleclfblfcmhcmienkeokdnldomdpmdpmdomcomcpmbomaolaolank`nk_mk^mj]mj]mi]mi\mh[mhZlgYlgYlgXkfXkfWkeVjeVjdUjdTicTicSicSibRibRhbQhaQgaQgaQgaPf`Pf`Pe`Pe_Pe_Pe_Pe_Pd^Od^Oc^Oc^Nb^Nb^Nb^Na]Ma]Ma]Ma]M`\L`\L_\L_[L_[L^[L^[L]ZL]ZK]ZK]ZK]ZK\ZJ\YIZXIZXHYWGXVFWTEVRBTP@RM>QJ1?:.123578;<+--O;* +++333 %5Ha #*/1djdelfemfckeckedlebleblfcmgbmgcmhbmhblhalhamh`lh`mh`mh_mg^lg]lf]lf\ke[kdZkdZjdYjdYjcXicWibVibUhaUhaTh`Sg_Sg_Rg^Rg^Qg^Pg^Of]Nf\Mf\Me[Le[Ld[LdZLdZLcZLcZKbYKbYKaYKaXJaXJ`XJ`XJ`WI`WI_WI_WH^WH^WH^WH]VG]VG\VG\VG[UF[UF[UFZTFZTEZTEZTEYSEYSEYSEXSEXREWRDWQCUQCVPBTOATO@SM>QK=PJ;NG:ME8KD7KC6JA6H@5HA4G@4G?4F?4E>+//-0135769:bH5% 333   /@T""%BGFflfelgdleckeckeckebleblealf`leakf`le`lf_ke^ke]je]jd\jd[jcZicZibYibXhaWh`Wh`Vg_Ug_Ug^Tf^Sf]Rf]Qe\Qe\Pe[OdZNdZMdZMcZLcYLcYKcXJcWIcWIbVHbVHaVGaUGaUG`UG`UF_TF_TF^TF^SE^SE]SE]SE\RD\RD[RD[RCZQCZQCZQCYPBYPBXPBXPBWOAWOAWOAWOAWO@VO@VO@UN@UN@UN@TN@TM@SM?SL?RK>RJ>QK=QJUL>UL>TL>TK=TK=TK=SJ=SJ=SJ=RJ=RI=QHVJ>UJ>UJ>TI=TI=TI=SI=SHVJ>VJ>UI>UI=TI=TI=THXJ>WJ>WJ>WI=VI=VI=UH=UH=LOMRWSV\WX^YX^YW^YV^XV^XU^XU]XT]WS]WS]WS]WT^XT_XU`YVaZVb[Wc\Xe]Ye]Yf_Zg_[h`Zh_Yh^Xg^Wg]Wf]Ve\Ue\Te[Sd[RdZRdZQcYPcXOcXNbWMaVL`UJ_TH^SG]RG\QE[PDYOCXOAWMAVM@VLAVMAWMBVNCWNDWNDXODYOEYPFZPFZQG[QG[RH[RGZQFYPEXODVNBUMASL@RJ?QI>PH=NF5C=2?:/96*..&()$&'"#% "#! "\K<." +++$$$ #/<JX$&))+.,.0134577::;===<>=====>>=>?=?>=>?=?@>?@>@A=?A>@B?ACDFHHJLNOPRSTWXY[\]_`adeehiimmnqqqqqqpqqoppoppnoomnnlnnkmmjmmillillhkkgjjfjjeiicgg_de\abY^_V[]RXZOUXLRVIOSFLQBINAHLDKOFMQIPTLSVOVYRX[T[]W^`Z`b]cd_ffbiiekkcii`ff]bcY^_V[[RWWOTTKPPHLMDHIAEF>AB:=>7:;589467245023.01,./*,-(*+&(*$&'"$&!"XJ</#   #.9FR`$&'+-//01234667::::;;;;;;<<;<=<==<=><>?=>?=?@=?A>@A?ACCEGHJLMNPRSTVWX[\]_`acddhiilmmqqqqrrpqqpppoppnoomoolnnkmmjmmjllillhkkgjjfjjeiicgg`de\abY^`V[]SX[OUXLRVIOSFLQCJNAHLCJOFMQIPSLSVNUXRX[T[]W]_Z`b\cd_ffbhiekkdjj`ff]bcY^_V[[SXXOTTLPQHLMEIJAEF>AB:=>7:;69:467246023.02,./*,.(*+&(*%&( !#aRF9.# +++ "+5?JTb%%&-..3347779:::::::;:;<;;<;<=<=>=>?=?@=?A>@A>@BCEGHIKMNPQRSVWXZ[\_`acddhiilmmqqqqrrqqqpppoppnoomoolnnkmmkmmjllillhkkgjjfjjeiicgg`de]bcY^`V\^SX[PVYLRVIPSFLQCJNAHLCJOFMQIPSKRVNUXQXZT[]W]_Z`b\cd_efbhiekkdjjagg]bcZ__V[[SXXPTULPQIMMEIJBEF>AB;>?7:;69:478246034.02+-/(*,%&( !"bTJ?5+" ++++++ &/7@HOV[`ekmnooooppppppppp p p p !!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p!!!p !!p !!p !!p !!p p p p p pppppppppppp p p p p p p !!p !!p !!p p p p pppppppoooonmke`[VOH@8/& ++++++  !(/5;@EILNOPQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRQPONLIE@;5/(! +++333$$$   %*.1479:;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;:9741.*%   333+++ """"#%'()))**********************************************************************)))('%#"""" +++333$$$     $$$333333+++            +++333+++$$$$$$                                                                              $$$$$$+++333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333??PNG  IHDR\rf IDATxyGy7̝}4H#%[%ˋ `?pN{ 9'~!L0KHIyCcY@א6f,"Zlbr.T}tUuUw;wffsvWWWW< C$91H"F RdIrR'''y\ 8tAO> f :O% ѵ}% BM/oXq `66}-]^W*&![$mfܲ,& q hXFZJen>ZyBd2j[_#{mA|'A~ANrh€"I2J3BmMMM4)r׺:.-bO.HO \ @91F٬. @хq:o 6A*)tsBB2!0gPk}h٬%n9c1(c̲m[ B eQ}/A@MS_G'MAĶ" RPJyL,+@v P`5 ,XI4J~c]?O%\ loq@ 4C*?VV}}f2[jz!˲ƘM)cpmmBs,J),+O)q$F}bBʽt"EZXa"-¬YGMnk{<=AZrt IQ-MoL4ڼ}ji?ӳn[ n n3^ +1t?Јp}! (r_ ϲ@Zm3۶i d٠spBw<+ؾ۶m;Xq.A˲B͋",7mDDW qZVlrOFuvvZb 9rsl斌cm .@8#)F72R㲱.ĮwnQߙzsQuvMz]X/ZƆ/vlcy~0_L{ !Vgg'fffŘ ğ}$k 򛜜TcrOKoM)uB%]6ڸF-jQJ EU!cqXNY7~❣07,M) -B@w:& `pPx&> ƃ+%Gԡ׼`Sǩ<*]4"IFhO86!4cM%@6O!܋mY'qoLx#r@pPT"?[DWmф!YU 2Uϻs> ACAp۶eر p-j[EJӬz!+ }E]׵2%BrB!9J0lQ2OJ-,`;6zz׍Baqg]q R5Zp.Lc* >\;7t㚪ρv0jZTmɹB$<[e*-jsLEyV'cFyԑ楤MIxZ*"jTSc^5@2!=RrUG.;XqB+@i~<m@WW/<.‰㕮i@6mjJ%y- v&\u,>!y[fl'= ǀeQJ,B,9&le+1b 8i4K`?i5Vv6xc$y4 Me?* ũ#S]u8E\_"#'l|c}hD ;\2#ٺu+ժZS,eiڬ>KscY \gl F֌͗&6{}:&#290#AnCzj\ʽXA O8DB8[K7Eek^qݛyX*G/(7lD)*qnl$(1 VɪɈ 8X:; Ag_@cW6+3[LAl}QkkVUv-0P =r^jorM)u(jR&`k)mQNj]P8 & 8gbiR2L0lqJiJAh~qkB:crWB1m8|ڥkiinR;jv66jtqBwMͯ$mAL/Y5;3vbhuv4坰 gOa\.-*{91P'2T[Nz):CbJ˱Yʃߑin`xWڞCZJO).%IMxh†ߑ8yC"P-0-dܗcRY8DcTE1-.֐dcDz4544y^㚿PGPPNGԇpb쇿YRxv( `d[iJ)lRB@$DWo]%4Ez:߈pt-Kq4+mۖfy R- @r " ~q8 &JѸ+Y@?nX?|uG ?4ףA<M O?1O^ #Qq/)':&%Vo#)a3?0@vosəl~CB4GtlPdr629&Bs#`p<Bd2rY^*cc萦Q J hnXL"\8fCKn4TZ DAOiO#O)W?2~A& -H;#*Gkh䏮!b׍iK2n͟dȒdSBF 7h$NjbuY$愃p9eawA=TPճWd䦓_'SU|~T.?+ȵIztOz{{Ւ}+2SҔ1FzzzHRRR/mAt,_i$+V$#$?՞+ b r i - ]ih]>|yiH?NPADi$"rXm -kQfZr>/-rPݯV$6])W1.Q\| TA~1[Prayrp"٠\ dl':黜r(2y +bT:6܊8GV ڻ[brr,niKE\צl >r k7[\ ==5R?t5* ,y-%f1QJ'?]H# ox^5cq%,t?y.O-K?OdJ!nuiy"Sl/VjZ VVO[qƵopzxg:SA(0kI+6!H]-Fre!@vbܝ # P(QH uuJuZq_,PKI*K B@!FhO{ܸLF7]/0Ԩȟ,L)I;1 ^?Rwk"z,s1A@Pk AќzJt)d={7 5%8Lr],˵zq^M۸}WE!\=rHV.f^39,ιET\hN-s(k{"6*%T-0AUeSҰ!@hI4߸{c^QNHk5"͐7$̧WˬI׈OӼR ZfXҬ}RT*4jۊE Fcʉ9/jJZRaQ3O|^n\D uY~zт$! T6X4r```=_ܘ_W ^YXDWq f1䲹?/I6-8m@Ҥ(q!gT\.a*lFZŮ] VGPO!Y{{192alXb>~2, >\ע51b7[ 4 `-oSh7l4hz>ʧSP[Kۋ4'Ox0Kt5kpbFC?[}}}]_8pvލ|;^|9\tE$8_я~?66pI<#G,17x=< _`;"(7E ysRs'(ذaAAי3{ EW vo/}8W+|AF5@zieԝbZ?j@"z WׯW_~<$ҏ$WDsXBZZcf^|1NG8a1>^\\s y̻iѣq1>7@yr?#޽(ollK_w]xܨ?~;2>a ,pv"S0sBj߾Po|J3334""J\ׅm/{V_#~= ǎaG?Uq\}M_;D>ǧ>)o>|K_0nvvZ:t(A~xնmx{ރq|M/_>hS|Ek4Ll3ڦ.1:: BںO~[o뺘0998jݍw[nAfzystvvb˖-We/þ} nJ<(x^Ҏ?QlݺncccXr%>ņ<_ 1 @ڵkAA8ƞ|NWK \.c||V$%0==Ra\xzM 6 $Vl߮TiDOO/rpW7 u]x+^||}իlJ}_th?eJm:pOC:㋇D_ar9P</+PVqe@GvdP(yk_ ͢gq8K/ml2uyӧOe_{{w ۶7p}[oUIA5mԂA5K,HM~KAbPJid< F^Rlx[.&''Q*033eT*#J),R!ja/W׾===šCق! "|r>}W>t>۶mÛ&|āk.Shblf+is.Ԝ #-͟lƚ?#O? |3JrB112ŢJ/˸K`Y6]q A\ӧnݺyrVZUW؜>}s/npӰolyH@loLā@8jn aRJ_TPVQ. ! I[#V*pqWvr\jpO>,xzիy2]EZU[:+JjtttӃpJ)t{011|ؼyqnv<3T[);5<g?YtttSs:;;}HY m,}HB :I!&e@0{ \.۶AAωy,u]Cx??, m2`ll GEqx=#w$CCa%/"w/|O?4q@elLi97 @=ÓsuC\Ԕt6bBjk4H:'ٗԚɗx'\ ǜlx _~.ի{Nw y 8 .@=2Fa?.L&a޽<.9v ܶQ.~7@@[]Vك;vWzAӦMp7cxgߏ}DR1COoźuj*c޽رco߮O/v4y"̕ɑ/$z1t*DH6t J%?~<\Ks0?@/T*m[Ec4u 1?<\{,P A{Ωɂ ȋ* r.baƍ7uU2X鮻7ވJݻw7n=ڵ |>P:|C 7:G4Y4[mc$ 1BRO6lx9W(`=O\{v( Dgg'ݍ.O ׾5OcXDى嗃{Tj硿' '*X~ nR'>) KsU曱nݺDw<AFDCOߚk;k/)MUoTJ%>|2=J?1ʕ ~a<( Q/I!pq|ů~+tx6= n8s-@&j'| ~ fqW!O 7oƵ^k_V/@/S|*//ˆWUl޼٨Ës䯱ҙ@# F/p2O ܻw/ݍ^rxӧtv܉/yKeLJXx?.a،aU/!>@zjttt pwb͚5ZR`ݺuؾ}B)TJ @??]=lFXz5FFFeǎ;7몵^X_\i}KB?}i0Foߎ堹|3F뿐/`= ܂#u^1Z RC?~v£>y06>nYfT;vc \r[;~%/u]r9˲P*rDB;#ԝ"XICڵ2&''/~{u]=, \ Hx!O jRP"M0-亀sA\qׂ 8`clĥbΝկ~Ԑ`XĩSP.TIl=t V(o yS mcttTioW_}5ۗur̄o;_!c2*^4a9ƍ7)tttq> X -82xU< v1>>Gy\s :::p1nv@](\a8S,x -rp߱cǼѣ8kČC9affF-lRKh蟩)!^͛Sˡtv7u= %gH#|/͗/׃`T[ٯ0Z`c#SSS/\uUDyJr%:}zzyo۰[7q#y~ѣ{7XqBJ%twwӟ=;9bbBwuAwwH F-#;]O/o5vK~4t`Bb,-"Nm#89p]>(FFFi&tvvbfZ֭}N=3TU.8`B о}O,nYߏ3g@M韓'O@ؾ};?NR}6mN-]^Zk4g%0isM/@GѣGoppqPYҘ>|{iZײ,A|;x^7^*pAnY~cڵ( j^x)G÷mz뭳V6GC;Ga;Spha"U.ҍh8xsq cٲeFoSSSxZoqg/Ky\7m۶4-~i8qB!Q{bٲeذaCݮGZ^Ck~hۋ>NL}N4Ո$6kp:?Ǟ={u9ŊxO}ԗ0  I@S c b\\drr> pQQIbIzZ7͂1\H>AX^&&&R`Yl[H|[;h0F#g~w?Z,RF 68`<"z3ɯg#NRm3D_ h-9? V ;e[*ɯ$^Zh ~aZ';xꩧm5`ժUQz@~ΑHNyA4(K4| :V/ӷqV!^ k"}(XNs6 Jm,RΒr6g'k˃6+oqp h V4?B#>FiC}4pRP S~]\=ߐΫx4J}clA湓YXRN? ! ?WQVu5˲P,k.#|%fffQ|>;wb||blot1 ;5ȯi>N8qd28R$W>o_\hKs"nnP"uF_|3yhc1^IoZ^YY48L&L& .\E-vK1IP/'Ә_䑀*gYE <=iDzeե&jSNԩS8sL{6"Kj:pr2i+>7J&ccc%& 0::QAmˠAN_96`p^ ATMg* WީVw8zNB\FR`/ˡۋ8֭[Q߿n^SםZ ?Rviyj? nЫW0ɟ3^ļ088.DR} Vۇ3g14.CnrdQD 9駟򧟆ԅb|:dYlڴ ˖-î]Zn PJqW`Æ Ɓ{nxg]N9y>wޥ깃O~nX \kjFACG;b .###ӧqΝ<\>y䆇:pRv4AtuQxq{Ū_OĕW]wy&d~<#_z''*|'."|߯^\FcccGo;٣ 0:: p"^4N~VM jQ$z _y`!+†_Bp݇?[䆇.2J"fffP*.8+ׇs ?by?)hW]uU|ߌa|ӟ6{/++^ ~ѣ~`tM&&&(}/8x{c=}xǚzO7b7%7FjǓj.\x =z֬|3g099)LMMarrLMMX,"`Xʕ:/ Bq饗ι׿Gŏַy^ƮT*jhVZ[DZcjkUC}yh~ p6`|y_ ϓn:PJ/7,_FV8313g`zz:*ʟ oY]@5k;:Ǒf|r۷#nzzJqo~p7/q5k{mJ}_ܨן1ZjA@@}!?Iʋ 888{!ϜATBTB\FR<AsBUo˗ömر|6,FiJ}}شiS\@رckaY w]T*qضmmv܉}sؿ?(lQqir6O# 9g{G1/ڎ/086lp]SSS(J 22<σ !(, u]pT^8?G^* bhhhĚtwwݍ6oތm۶a˖-җ8~8&&&*zhk-v'`qg6t `޽ ?Y'@XTB@Z2x^ e AE"z!@X48!Xj:zرcx衇w _Wq뭷8+ۘK~>; /UpOfΉ EVn033jjZ'{RQ6Wn/0yu{.uX)#۷oǦMpӃ۷Z? +x^q\-AjbO֠*@ܯUznFFFwgΜ׿u~W ׼5"_V.[nUW]8os/)'`Z!\]ydYBs8L+^rxZ:(t Z˲PVS<^ODqh"{4A .p!|>|_ŏ~#:t֭ë_jpWW;>q?Q(uV\y8t~> ֯_7Mزe ~_ȑ#e]7^=h̒͟rw~ 7L&Au X}?I`)tG$$m۰meAUVL?3= orttt4^:x{nqpmOs=8}snlٲ}k9ѣGַbr?0n6\{Ʊcǰo>|ݻT)yg\wYP7 pTz)HH`{sd2@C~psc0r_~@2~ xel|u ?<>5sΝ;sg_4#״TBo/wuhnp^ R 7"ng)׉>&''Ắ򣟯 vBHS@lvss7y~=xHoxm s >͹#P&Iϫob/&q!dhS+m 珂V֧r,a5lM+,)'`=3t&i|@-8 InJ)X@4#cmiUsflӌf0ҬVBhyD㾬4+43# X0KӻqmmS>dDddfdVչʌfA4ʼ`r8<bހKs_wpm*Sѣ#*M2WN T.PNV`o˥hTh8" (0 (rWY Ocʕ+Ȳ ҬWhF'௹Z'םp"d' _,.aw@KK8t8v l?gGn`?E^|EdY#++E3xfqZeL@4M_T4݀h-opevvvx{zwG\3??I@k^xHS@~3[dqzƘu z3P<ɕ+W@D0]@eX^^FE~ߑ<籰 ظD۸!c?O"ZkF#h+ے J&楔r)3߻R7%zQ9k4_+WF:`曁W^z?xqmU}g`Ǖo%k!xg@!~by;X^^S.W_ũS; IVO\ZZW8qYass?яOORpĉX]]Źsp)Qmoi]ף@m?ԼxY__*=<3򷿍locii %vP}?K ^b%H)oiso~c'~™ΝP"~wq[pQzO=?bc=__C8{,~~ O<~,C9S)%Jne8x8zph &^{ 06|~~eܲ;VW6zD_ݭD,C?#~n]d?'O//c45J)o&q`f>I*n9oK|wܱ2|,e:{:\ˁ}^.~SU\|Dz"F/S}+++/..biiİio|~X)|fy /"x~J)¯… Y Z09r??^peկ~`A~~w _oX\\}7 ʞb; h 2U7ٳgq}/ᮧF!g;>Vu$ N>?w>[g~w~?R r RxKKx177  ȓ'Oٳ(V->no| ~'?/2OGkkkxgOk_[9_:ڼ׃rJce8` XG৞ɟ@֓O>W_}~&oa}}^_8Cl~s~Ν;R ?~a<䓐R_:xV+@)^[[[8qD^>hw~wp9|_]wPJ0(}iwX{ ,_%T_ă>ѣxGq=zo?c_"VO>,\-×ݞ6p"nGV Dwy/2u(wGy/r&`0pq#NLy ~{lRDoi4zU>_ dCmWKƒ>ۏ>spcǰqmXV\K*4ᅬO Hf ?3PKK "?NڕSLk 7剨Y0By Smey䑆DQdy17ݥg7/Bn׃U!{?y,,,`u=X:{ oc/c/i ck(p9\pwN89cadh{g3gʕ+R&SO=/~c5.\P#}8qQ/_{y-Ϡq…/s^N#Qh@4M/_Ƒ#Gpѣn_$`fĥKp%8OI?q1z뭝ŋPJU.S?s|_ֺ5U,//w'eg?~|WeX|o5'*Q L:9.k`&`)/N4]f*LP" k[=Χ\cUVXQ-?hA:j1`kBް42ŒCl|إ3v{]SiTcI9u`3/1$3f h>2Bܐ8 BYvK0-K\N> _sAYo`0X8[>Jp̺˗/7®^zC"8^MU˶\YM q괚x*p!c 0]P:@`X~tv\^y* @ہ;`]`f5S=i IDATuO<(<Xqu3 W)>X;`&3~5.._\tYeK]olTJ +*# g$A ܷ ˬgfrUJZnZ vNw*vK7O PxYORJ+V p֕4fm֬ZU{~7<@] `kM,ȥ7s״ *h  Zq 6$ b2v\rlQ&Tn-7`uk Sc+I{u?&biːBAQ<3ML3ߍ>iPօ&/,s1,M&]KV94}`fdY>"gdUIc MS\zڲ&";BX sfla6mb/Y6 hhW6 `"1¬d⺆3 @kWqZc N-m <ж=hFp63- E%ZfUdS ޒ]. q2i )歭e۝ ]?2l`fm_Pi:sEqAf/M~ c06׵ZC>~BȜ\)M[󭝍;ⶰ:= ݐaSk2%h{~Z2f/f7o c(ymiLMuat lـ@SM_ߘB.LSA%rf?{JHW}jX;`LPz^+@4ę 0vN܌<2Se߿*f89[i-h(EhPkD 6]4M XݰBpBE!Fћa"J)B(ϿV3H [™NW, 󄂍WȎ PiۗSA5< Co嗽a"uTLf6]ܞ):N7덴}^vmO%-]/,s?LӞeRTqB66Vy yuN݀FZP̼8/`ysT {"\ 35 d!2C&1 7u?- 땧6[Ww "oK睴{4)?I; SOHȵ7r|z‹x 9:Y[׭qs;;;$Ie5n^!{'OtӁWWWynnΚd؛+&eVC l:=0Z&[i3b- *&\>>?pnIyul-Cy bd0Ϧ[CF] YÄZ\|76H j pv"U*pIzK/X\qyhY7 ȅ'12gw#B6RBi͛JRg aTؿ} e; Vc.su<ǯ-Z[h&{wுF7Yke`שP{()v| 4eAxn~A(2j'vggo;;M"R-PY$IȜK)@pi{nu7VD9G)b,q_y!47^Ez1tǛE;I1^y [A? T⁁?oͬCA7N ͬYQnPz/4[| K^:zK6^d@ND934MuǺ] l%^ᐄz88\EQd}9|4^zXW_'@O ` O/e!'72Qo2UZ$9tk Vc}<߷t kt<𙑽kbqHܶҥw_ 8`PQk}a@ ~%ȕWoEЈ'(CK޻(;8㤅XCcOe0{Ns-UEU' !MK++azggG'I«9 ؊&3g8"ׇȲ(Ʌ2 Ȇe2Q;蜂jh\Q5hGa1!ےAK36mLըӁQAv19qlDؕq\ -[?I@fojCw-xna Z7̜1sFDA!]t[8sLR͵Vl7ur_Jw;7׻IqPx-[ v]s~g"h`\of%GR9 P-M llO 8v-z ҋBd2^E夔Z)K[i#F1ZkSAgYf'92s=CzW 3< P"ScD Pa2\j]@C9 Szs %i;MޏDM?ŷQ D@yYEQwvv:8Qq[w:"m~PZ|2!D*HGy^EJ@/` ^]\s6'?2} 8k=iTM0_9v<<Ι޺tFQN-2B(՚b6Iz=zggG !Te:sȄ:ghk{$b%\B L`lQ͕qoI_K on׋! h/p}@; nkϑ!M18Z<MoD137!Mi_n^A{i ߳P_||Y0 ^:|,9|M+ [̜;_J|?f_kӧODz}}]GQF2죔R+@1g,GX2 &{kvJ+v@@#n<^ F}Rl>x[_ `vu]̀"n4?666^#WN+r)RHEQ^fO+ n:PJ)HkuEJk*˲L!H i>'QIRq^J7[TD,:_+@LἧL„mg?Jk{+9abj r?{bah?Iz7a4JϿ|2@j?̜k8Ue*I̮oOLѝ]Ihk!p8R<˲\JI)3ujL~Օo1 ͚S BZG=p,j+AђIxGƪ=W <߼E&q}f[p@ ¡ұy)&<+@)^=JM81sN23ˇáu[_2ڮ(T&̄2ZB<eeyś Zi@׊ ~ٰk0&73(QFWkT*Zc9Z _w44,HHQHR@XJ&PJoefJ)FZQER*M$F*I|ssSqoǦ*>Fqִi8Ry$<ϩpwȲ;O|>I1XATSv:!lD>Ix>A&ܼ@D"a΅(APZV{z05h5 UBCuMK}55&n[jjݻFe|Mɢ"`¼`!g[G`Ɲfsi q9{ 6ɼX+S\n[}??(O`?NQbc+BJ )H`ߢ{{燯淕R ]5(<Ϣ(\3O?!+5sV>}'Oy$`گ`0$'IxzkkGGZ'-; &..)c~R');NQu5/1=]Wo+Rǯ^M?X֛D4sfI)}֩R*(3qM$ND{ą@ dp{t繝@@BǤ"$@DE+f"Zksayy;r "@U_h^K-;vTq*- s>U}uD;Bի[Y];bboEQk~\Jk~nh[)NzpE5lnnb0(gY8훃ao c7.4dccG")Dў}-4ڼǨ19>9At+Z}u NLOgWc/VJ]++k 33O9(UJeYeuqk^%3gɓ'YnH<֚Fܒ@'N8{A+ݑt]lSr<^CG!:y`W"Si)v7M z: 7J+RO̪ RJ7՗2TRJi` [@F%)$=J)- h4ڹ|="z&KN)bIH( 5F72Y:knS5]2OCwHC*IqXg`]i̫hRz 9I 2e\\\Yu?0!Kш!eY&RbqqQi*bfKBJI\m f600]sQ=V\+"*6-W:M2z*Iew ~` #5eY&DR)%54$iE ҞK) L3.P~%u&3F8\Vk["CdvRlk ?$6։HYooll(;Է$S]$'OhDy#MSe`f2~y^'-2cwEZka΅%{g_4a=f5?b4L@y% [u54MRHm8"_~S|. TD$[J)RJ XZZ"k(֚} doqCD0IAeK@zv/ QGGQN>vI hD`}d-fvaL~_p`D C$wo&3qBW5 8MSGx8I)6v~`%K'O$>|䓁`f'K{FBխO=U@/Uw./,,0n>~`$Ay#s7b`4>13---.|:kZ~~Rw&3%Vր=歼 yɮ=' zk>$z!>K`-9K@ viԭW+++o5ߘ>p:"p>  $B2fk}YIDAT+ܡx>!{kZm"`2Y@Ab# rh+ 3i#)gj|+F㉠~^!&8f2idF^vo>~:/NFa"/ [r1\+ȁA5#wv"pQ& L( k|+לOt@LRظu .BgR$,{̇ JNaIENDB`Carla-2.1/resources/ico/carla-control.rc000066400000000000000000000000341364475620200202560ustar00rootroot00000000000000id ICON "carla-control.ico" Carla-2.1/resources/ico/carla.icns000066400000000000000000005673351364475620200171560ustar00rootroot00000000000000icnsics#H??ics8AGkeGۉ٬ۉۈڬ܈ڬ܈܈k鬏kVk݂ێ݈ނe܏މis32ď ~rdzI+3@?@820[zA]0BLJPzlaPc_ PzG6!  (c+ ++*CO! h. )U-EOCk0 KSQcVn4 %A'SYMts5'!%,-,5GI w9!33/a{z5< 6|=IZL!> CKWdX}A!(!FJAwE $U+   ?U8KnZMf>Eh  &CA!    ",,-% #&*U-EOM)KSQcZR--&A'SYNxb0(!%,-+8KD!4"334" 747|=IZV: DKWd[lO> "(!FJBirC %FG #C#A(#s8mk cd cdbd cd ICN#????????????????????????????????????????????????icl8୭_;AAeeAA;::::ee^:::eeee_AGGGGGkkkkkke_eGkkkkkkkk^eGڬ_eG^eGۏ^eۏ^ekV]ľۏ^ekVۏ^ek܏^ek܏^ek^ek^ek^ekk^ek^ek^ek۬V]^ek]V^e^eݳ^eݳ^eۈ޳^e܏޳X_e܏޳߉4_eeeee_^^^^ee^^^e_X୭il32 (tlZbwmipqi+Iͼ͸Ʒ] ľ8IéwSҩ'!"$*++'++,%atSͩ! :9:99:."aqUȦ!@; >D7:=9/  anW£"y]]Zokpc,  akY6*GVfRZ\-$_hZ.x%YZVT\Z- !_e\ <{o3{o~mn,  ^}b ^#!?=>0"]{^`#,%&%&!\x[a84541231auXc&!. ')(()*$[rUe#!;9;;:<0 #ZpRg!)la$EN=AG94.'[Ddyrmlky,jce|unvsv|{4(fjS@G_tVQuoQOM'7`TC3&,D7:=82 &%U;'%]D]Zokpb/l&%V=(/w%GVfRZ[/K*%X>*+~Z#YZVT\Y0ʀ'%Z@+%.bU){o~mm/vtQ#%\ B,&!?= 3!%]D-&,%?C:&$_E.;45412 3.--/06+`G/)!.(9<8)%bI0&!;9;;:;3(%dI1%"UK EN=AG;1׺"&%eK2'yW_\rxo/v&%gM30w&@NPDJL0R.*%iO5)gJ!olngtj/̀&%kP5%"BUX:0NZA&    &58" 09(   0 0%&'.*./-(5 % :9::9;.($6 %2. >D7:=9/ &%7 %]D]Zokpc,&%; /w%GVfRZ[.70*%= +~Z#YZVT\Y/'%!> %.bU){o~mm/abC#%"@  &!?= 2ە"%$D &, %:>>?7&$%E ;454123016+'G )!. ')(()*)%(I &!;9;;:<0 (%*L%"UK EN=AG-K\E)   l8mk  ?xy@ee ?? yzxy ?? ce?xx?  it32g    * *      k 3d~ytptz{vY0 ^ J» L o  3{üŻŽ8  Z  HĿĿS  qQe sBX s /z? ue~~Ŗ7<{:~~|¾X  d̀"~}|zΡ  'rΆ6%~}|{z̾7 Dy΀҂}|{zxo  *W}΁ʹ}{zzxԗ  ^~Ѻ`UWXWXWVWVUTQw|{yyxxէ   eѺWF>DKw~|zyxwvײ  gһZ>.Lz~{yxwwuطgҼZ>/L|~{ywwvtٸhҼZ>03#(10./L~}zxwvutٷ iȀѼZ>C?D/9D@C /L}zwvutsڷ iǀѼZ>@:@.87)@ /L|ywuttrڸ iǀлZ>@:@.84A /L{yvttsq۸ iƀлZ>@:@.84 A /L{xutsrpۺiκZ>@:@.84 A /LzwusrrpܺjͺZ>@:@.84 A /Lzwtrrqoܺ jÀ͹Z> &0772(@:99:99:@.84 A /L~yvsrqpnݺl̸Y> ,FWfmni^M2@::97=<7:@?:@.85 A /L~~xusqponݺm˷Y>2?cpK@:8TZvC[t_9=U[]8ctV8:@.84 A /L~|wtqoonl޼JmɶY>5_ſοpA@9HP476?sAâqD]6@.84 A /L~{wsponmk߼JmȵY>#Rʷ˷d(@8RF8:9:cCQ.8oŒ3@.84 A /L}{vrpnmlk߼JnǵY>6fϴəxC@9C]147]jGI2~r_2@.84 A /L}zurommlj n;ƴY>Gx޿zz{X@:6w}ilGJ2~xhē2@.84 A /L}yuqnmlkiJnŴY>Nնvlluyd"@::9g];tpd?k@6\V?pZ7@.89"!/@ /L}ytpnlkji,oųY>!Sҳrccrr~k%@:6557:67:7::8895668:@.7Qҷvllvjg#@:@.85#A /L|wroljjig2o²Y>J{zzĨ_\@::8458:8558: 9547::@.84 A /L|~wqnkjihf p9m˶nnG@:6JlfD6::6Cb^K7::8;cmS79@.84 A /L{~vqmkihgf p$Z˹̌Ym)@6ašM67O\78A˰o7@.84 A /L{}upmjhhge o;l€T~|F?@|99ަn@2ȶkB=.84 A /L{|uolihgfdJoY>Hqb^~UFk~ulfgvxO =R}j9>pD7xL<.85 A /Lz|tnkhffdcpY> 2Ulx}|s]7@:}nQ58xqY75cu`:>.84 A /Lz{snjgfedbpY> );DE=,@8EtyiP788=m{mV:8:9c|p[?6@.84 A /LzzsmifedcarY>@:88=:59::87<;68::96<<77:@.84 A /Lyyrlhfdcb` rY>@:99:99:99:@.84 A /Lyyqkheccb` sY>@:@.84 A /Lyxpkgdcba_sX>@:@.84"A /Lywpjfdba`^sX>B<B/8>59A /Lxwoiecaa`^tX>;>=?(2?>;/Lxvoheba__] tX>/Lxumhdb__^\tX>/Lxumgca_^][uX>0Lxtlfc`^^][uUH?DLutlfb_^]\ZuPMPOKo~skea_]\[Y uVF7@Lu~sjda^\\[XwX>.Lw}rjc`][[YWxX>/Lv|qhb_\ZZYV xX>589&-875/Lv|phb^[ZYXVzX>C>C/9A:9:;=C /Lv{oha][YXWVzX>@:@.85   &@ /Lvzoga]ZXXWTzX>@:@.84A /Luznf`\YXWVT{X>@:@.84 A /Ltynf`[YWVUS{X>@:@.84 A /Mtyme_[XVVTR{X>@:@.84 A /Mtxmd_ZWVUTQ|X> -:?@<0!@:89:99:@.84 A /Mtxld^YVUTSQ|X> 4N_oyzreV;@::88FE8:9DB9:@.85 A /Mtwkc]XVTSRP|X>!C`ijlN$@:8G=6569:761}4656::@.84 A /Mtvkb\XUSSROJ|X>EiŦuS!@99FLiBem<=_gi9pb9:@.84 A /Msvja\WTSRQO'}X>:eàsG@8JL686?{y|AʜfC|e6@.84 A /Msuia[VTRQPN }=X>&UƳȽh-@8QG8:9;pDM-;|č3@.84 A /Msui`ZUSQPOMJ~X>9i̱ʟ{G@9@d15H{ܽxwzZ@:6sd}FJ2}ryƐ2@.84!A /Mrtg^XTQPOMJI~W>OԵuijtwf#@::8Z~S9fcY>`?8UP!Sѳrddrq~k%@:7448:6467:6::78:5467:@.8;+*+.5@ /Mrrf]WSPMLJH,W>Pҷxnnxhf"@:@.84!A /Mrre]VQNLKIF2W>Ixç}}Ơ^Y@::6457:7566: 85569:@.84 A /Mqqe\UPMKIHEJW>6k˹cs~C@:6W{M6::6MuoW7::7Cv`;8@.84 A /Mqpd[TOKIHGDJW>"W~˾}^i&@5m£V66\ȶ{f78Hɶz9?.84 A /MqpcZSNJHGECJW>5g̷oXy??D::ڥpC2ų`D=.84 A /MqobYQMIGFDAW>Alz\gzL<\y=?êK9ȴ\kT<.84 A /MpnaXPLHFEC@W>N{g8<~mB6uI<.85 A /Mp~m`VOJGDCB>W> *Jcrz{viQ-@8{kL57l~oS66Zr[9?.84 A /Mo}l^UNIECB@>W> "/671$@9>fpaJ69^qeO88:7WqhT;7@.84 A /Mo|k^SLHDBA@<W>@:858769::968859: 67958:@.84 A /Mn|j\RKGCA@>;W>@:9:9:9:@.84 A /Mn{h\RJFB@?=:W>@:@.84A /Mmyh[PIDA>=;8W>@:@.86  %A /MlxfYOHC?=<:7W>B<B.9?89:<:96W>7;<&/=;<8/MisaULE@=:985V>/Mgo_SJD?<9873 V>/Mdj\PHB=;8752 V@1MaeWME@<97540SHCBCGM[^SJB>:7543/^Y\]^]\[\[Z[[ZYXXWUTQXWMF@;86431.%}zwrlf^WOGB=975320-  ~~}|&{zyywvuutrqnkgb\UOHC>:75321/-  |~~}}|{{yxwwvuuttssrqqppon'mmkjihgffecb`^\YUQLGC?;864200.- * r~ ~~}|{zzyxvvuuttsrrqqpoonmmlk4jiihhgfeedccbba`^]\[ZYXWUTRPNLHEA>:86420/.*?  V|}||}}|}| {zzyxwwvuutssrqpoonnmlkkjjihhgfeeddcb2a``_^]]\\[ZYXVUTSRQPONLKIHFDA?<:76420/.-%b~ .}|{zy`xxwwvuuttsrrqqpoonmmlkkjiihggfeeddcbba``_^]]\[[ZYYXWWVUUSRQPONLKJIHGFECB@?=:975420/.-+)? z{zfyyxxwwvvuttsrrqpponnmllkjjihhgffeedcbbaa`__^]]\[[ZYYXWWVUUTSRQPONLKJIHGFDCBA@?=<:9765320/.-+%T  u Iyzyxxwwvvuttsrrqpponnmllkjjihhgffeddcbba`__^^]\\ZZYYXWWVUUTSSRQPONMLJIHGFEDBA@?>=<:98654210/.-+'2h  ƨzxfwvvuttsrrqpponnmllkjjihhgffeddcbba`__^]]\[[ZYYXWWVVTTSRRQPPNMLKJIHGEDCB@?>=<:987653210/.-+(* s6ɥ|vwvvuttsrrqpponnmlkkjjihhgffeddcbba`__^]]\[[ZYXXWVVUTTSRRQPPOMLKJIHGEDCA@?>=<:987653210/.,+%2F   RŪvtasrrqpoonmmlkjjihhgffeddcbbaa`_^^]\\[[ZYXXWVUUTSSRQQPONMLKIHGFECBA@?><;:98764321/.-*')Mgq hþytsrqqponnmlkjjiiggfeedcbba``_^^]\\[[ZZYXXWWVUTSSRQPOONMKJIHFFDCBA@?>=<;987653210.-,,9U|S  Xü{|~xzzwvwvvwvvwwd o  <ûƢ@  ) M@ùŽW  k  1Xsy|ztptx~º{~b3         **          * *      k ,Liw~{vohb\UOIC>CJPV]cipv}÷wj^PJR^hr}ƽwldYSUVVXVRM>& m 7cyzrkd]UMHNV^fov~̽~n^Vbp}˿vicdefghhif`V5 ` (Un|yqjb\TMHOW^gowʻ}l]Wcp}ȼthbcdeghi jlgU, o 2[mszyo_RMIEA=940,*.27;@DINRW[_cgknrvy}|tjbYPG>529AHPW_gnv}zsle^WPJC<99::HQ *`  *.AJE     1BL= BJIJ t   4DL6 HK@?EP" g  6DM0 H@.O" ] 6EN0 H@/O" \ 6EN0 H@03#(10/0./O" ] 7EO1 H@C?D/9C>@C /O" ] 7FO1 H@@:@.5P)@ /O" ] 7FP2 H@@:@.4[A /O" _ 7GQ2 H@@:@.4Z A /O" _ 9HQ2 H@@:@.4Z A /O" _ :IR3 H@@:@.4Z A /O" ` :IR3 H@ (4:;6*@:99:99:@.4[ A /O" ` ;IS3 H@ .GG?<=BMO4@::97=<7:@?:@.6H{e A /O" a ;KS3 H@?I/Fre>2RH @:9B{<656::771x5647::@.5OI A /O" a ;KT4 H@2BB+ոe'LN@:8TZvC[t_9=U[]8ctV8:@.4[g A /O" a fR =R}j9>pD7xL<.7BYZ[U62 4 A /O" h̯ BS\8 H@ 4W^SKLVd^:@:}nQ58xqY75cu`:>.4W } A /O" iͰ BT\9 H@ +>GH@-@8EtyiP788=m{mV:8:9c|p[?6@.4Z A /O" iα DT]9 H@@:88=:59::87<;68::96<<77:@.4Z A /O" jϱ DU]: H@@:99:99:99:@.4Z A /O" jϲ EV^: H@@:@.4Z A /O" jѴ EV_: H@@:@.4X !A /O" kѴ EW_: H@B<B/8CPQ RD49A /O" kҵ FW_: H@;>=?(2?:<>>;/O" lԵ FX`; H@/O" lԶ GXa; H@/O" mն GYa< H@0O" mַ GYa<IJ?DO% n׸ HZb<KNPOO) o׸ H[b=HH7@O# oٺ J[c= H@.O" pٺ J\d= H@/O" pڼ J]e> H@589&-8575/O" pۼ K]e> H@C>C/9CEFD;=C /O" qܼ K^f> H@@:@.5S΄Х  &@ /O" qݽ K^g> H@@:@.4[A /O" r޽ K_g? H@@:@.4Z A /O" s߾ K`h? H@@:@.4Z A /O" s L`h? H@@:@.4Z A /O" t L`i@ H@  0>CD@3"@:89:99:@.4Z A /O" t Nai@ H@ 7KB799:HS>@::88FE8:9DB9:@.6Ekonq[ A /O" t NbjA H@!EC-^N.KP%@:8G=6569:761}4656::@.5RąS A /O" u NbkA8 H@G:8{-DU"@99FLiBem<=_gi9pb9:@.4[g A /O" u ObkA H@>?=ǎ,KK@8JL686?{y|AʜfC|e6@.4Ze A /O" v OckA8 H@'L'Ƴe$].@8QG8:9;pDM-;|č3@.4Ze A /O" v PdkA8 H@<:c̱ʠ5EK@9@d15`?8UPN{g8<~mB6uI<.7C`bc`OM O) A /O" | UjrD H@ +M_ZWX^dT.@8{kL57l~oS66Zr[9?.4Z A /O" | UjrE H@ #2:;3$@9>fpaJ69^qeO88:7WqhT;7@.4Z A /O" } VksE H@@:858769::968859: 67958:@.4Z A /O" } WltF H@@:9:9:9:@.4Z A /O" ~ WltF H@@:@.4[A /O" ~ XmtF H@@:@.5Tҍ w %A /O"  XmuG H@B<B.8AC D?9;B /O"  YnuG H@7;<&/<:9:;<8/O"  ZnvG H@/O"  ZovH H@/O"  [pwH HA1O"  ZpwH IMFIQ#  \qxH ;AB  \qyJ  ZryS   Uqz^   *Oqzm  >qy' ?| 'k{S < ^| /  8wh f  bV n  -zS iD  Ab %{c QyL#  )\sR  G|r\L>4/+,16:?DHMRV[_cgkosw{~{ri`WNE;36>FMU]emt|zsle]VOHA;<=>>?@@AHVl\  o  2o|rlf^WOHKS\cks{sdU\kw¶ymccdefhhijklmnov;  m =gqqkd^WOILT]dlt}scW^ly¶ymddefghiijklmnovJ k 'BPONJD>BHNU]aiov|÷xl_SIPZfq{ǽwoeZTTUUWXYXYZ[]][\]L,     **          * *     X   #)17;AGMUY`eki`VMD:1'  %,4=ELS\dkibYQIA91(!   Y   !(/7?FMT\djrz~rfZOC7,   )2=FPZdmw}si_UKB7-#  Z    !)07?FNU\dkrz|pdYNB6+   *3=FPZdnx|rh^SJ@6,"  Z     %(-15:>BFJG@:3,%  $)/5:@EJGA<50*$              #%   #,"  $//  %05   %09* *  !1<3  BJIJ 2=8   HK@?EP" 3><   H@.O" 3?=  H@/O" 4@?  H@03#(10./O" 5A>  H@C?D/9D@C /O" 6A@  H@@:@.87)@ /O" 6B@  H@@:@.84A /O" 7B@  H@@:@.84 A /O" 8CA  H@@:@.84 A /O" 8DA  H@@:@.84 A /O" 9EB  H@ (4:;6*@:99:99:@.84 A /O" :FC  H@ .GG?<=BMO4@::97=<7:@?:@.85 A /O" ;GC  H@?I/Fre>2RH@:9B{<656::771x5647::@.85 A /O" JF 8 H@9=Vϴʗ1JF@9C]147]jGI2~r_2@.84 A /O" ?JF 8 H@H,⿥zzO2Y@:6w}ilGJ2~xhē2@.84 A /O" ?KG 8 H@L-ضvllua*]$@::9g];tpd?k@6\V?pZ7@.88"!/@ /O" @KG  H@"K3Գrccra%_&@:6557:67:7::8895668:@.7AMNJ637@ /O" !AMH  H@N,ԷvllvR)_$@:@.5Qé#A /O" !BMI  H@L/zzĭ35]@::8458:8558: 9547::@.5SՀ׺ A /O" !BNI 9 H@fR =R}j9>pD7xL<.7?JKG-* + A /O" $FRL  H@ 4W^SKLVd^: @:}nQ58xqY75cu`:>.5P g A /O" $GSM  H@ +>GH@- @8EtyiP788=m{mV:8:9c|p[?6@.5SՌ o A /O" %HTN  H@ @:88=:59::87<;68::96<<77:@.5Sӌ n A /O" %IUN  H@@:99:99:99:@.5Sӌ n A /O" %IUO  H@@:@.5SՌ o A /O" &JVO  H@@:@.5Qnj j!A /O" &KVO  H@B<B/8BKL MA49A /O" &KWP  H@;>=?(2?;<>>;/O" (LXP  H@/O" (MYR  H@/O" (NZR  H@0O" )O[S IJ?DO% )P[T KNPOO) *P[T HH7@O# *Q]U   H@.O" +Q^U   H@/O" +R^W   H@589&-875/O" +S_X   H@C>C/9A:9:;=C /O" ,T`X   H@@:@.85   &@ /O" ,UaY   H@@:@.84A /O" -UaY   H@@:@.84 A /O" -VbZ   H@@:@.84 A /O" .WcZ   H@@:@.84 A /O" .WdZ   H@  0>CD@3"@:89:99:@.84 A /O" .Ye[    H@ 7KB799:HS>@::88FE8:9DB9:@.85 A /O" /Yf[    H@!EC-^N.KP%@:8G=6569:761}4656::@.84 A /O" /Zf]   8 H@G:8{-DU"@99FLiBem<=_gi9pb9:@.84 A /O" 0[f]    H@>?=ǎ,KK@8JL686?{y|AʜfC|e6@.84 A /O" 0[h^   8 H@'L'Ƴe$].@8QG8:9;pDM-;|č3@.84 A /O" 0\h_   8 H@<:c̱ʠ5EK@9@d15`?8UPN{g8<~mB6uI<.7APRQROA@ A" A /O" 5dqe   H@ +M_ZWX^dT. @8{kL57l~oS66Zr[9?.5SЂχ n A /O" 5erf   H@ #2:;3$@9>fpaJ69^qeO88:7WqhT;7@.5SԌ n A /O" 6frf   H@@:858769::968859: 67958:@.5Sӌ n A /O" 7gsf   H@@:9:9:9:@.5Sӌ n A /O" 7hti   H@@:@.5S׌ oA /O" 8iug   H@@:@.5O d %A /O" 8iui   H@B<B.8A=9DJKF@:4/)#  %.9DF. S   &-4IT{|TI?3(  )6CMlmMC6)  (5CP߀PC6(  %3BPPB3%  !.>M~M?.!  )9IlmI9) "1BTTC1# )9J{|J9)   /ASSA/  $4FhiF4$ '9JJ9'  +=OP=+  .ATTA.   0DXXD0   "2F\\F2"  #3H^^H3#  $4I``I4$ $4JaaJ4$%5JaaJ5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5KbbK5%%5JaaJ5%$4JaaJ4$ $4I``I4$  #3H^^H3#  "2F\\F2"   0DXXD0   .@TTA.  +=PO=+  '9KJ9' $4FhiF4$  /ASSA/   )9Jy|J9) "1BTTB1" )9IklI9) !.?M|~M>.!  %2BPPC3%  (5CP|PC5(  )5BMjkMB5)  (3>ITy{TI>3(  %/9BJSgɻhSJB9/%  !)19@FKPTX\^`aabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaa`^\XTPKFA91)!  "(.49=ADFHHIJJJKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKJJJIHHFDA=94/("   $'+.0234555555555555555555555555555555555555555555555555555555555555555555555555554320.+'$    ""#$$$$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$$$$#""      ic08t jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 KPA=[v.vGjXd,r@|ʣ85ARaTa-1P ^2M:Kde qdHo‹oYX+Jf\${GԴ)/* ʗ:r蔃N_"wz2HsI`/YҚ^y?4x:Ա F9=DD0:,ۍba'_M:6^X{M7H$N~gg=w7Q!pelSm M~-gtsVTFRsGB w-,򘈳{QFl^iZ?24^<>0p,؅ [Ͳ;_Q"AtBKo] -{S\ H%CLfr>^RnvveS%92hf}X[b7Pa?P(Qd׎t^ӎGGi_lA[ ÏQq!/ F+-~Y# gaa%a>f=m6-0^mL O'XhRh["r<= Kwn?x #ln}|3'P顚ͺ >%®9 HJqܸR?cz J?o0V)@3=ĴL !0_ ,\NADMWks̶ ó3",U8vz@2~R]C%\7x'x"X??ɰ Tx6iU;rG$?4+%&YhhXܡa4$m|ˈCp= sѻC!suTbσ`op)0a}sQ&^T_m dGd-ȞJ&X'%M"qו'R~s"(J9J*<q$XWxoHglB jԝ 30?-$t5z6ŕ1x0\g*a Zf FyƁK u逨YȸΜ }w_f.ɨnf|-gs*a F#R֋SxlTt77k7*<̋<}XJpYx&?&%r}k$=|.~PW, Z0G +*WeMଛ두;I¨T#)ˋ8[:m\AgUC@GuH9oG,|wٖDԢey c<<(V IJ`V*KQ _|/հUbph|yؑ˓cARp!-I[Io>gN!EtYt&&`#M Jj?l>aLJoY~?-RYqM|Sre?pYw]ސ{5< 7P.6q›xp ;isP`#m&ГS 8$,WRz=٫|N'(Yy]W=m01\o+:p~Oڄr7S@;,,9'Ib]RnP]H (IpSr@xSHzqstsSZ7yJ~ڍuMr++|JP*\vMړ ,KS,lqU}UqO²xێ7U5S_/Z!rbe wXt؆X5UVns~oL|·M͓ #GkD-5 .| U͋*$G'׷;KFC i{=%c &ֱՄoMmnӤ~1> [tÐ5/87B/IAaЍd9{R{][5Q;ε}]߬A3-&FaLʓzy9Ȧ Z!,m5Ƶ} -/Qd3 NBm)0 ր;iQAjo`ᔦԢ=W 62$yK. tl B~I'㬶KxǺ4HΣâ,#^j.ciC 'Ax+Et#qW*ijs XxհFNUi4~La(ۓ84?,yBcjW,Y ;=S`=©}?nkyDz5Ӆ>IY^pS6)zeP8˱,A=(:v}|ܹc`y@dԘ@+E&7 4nv#֩JY{U!mғ Brp$?"3D [_\cVPVm-.?s$k#3j _ X>5o -|^܊9ժuS_f1wx.D:Gx <^c='}k;RZW[!D-ȤpT^L sO# ֕-x!jڼz6_ <g򆷣v4$cdѪjyXeX|I"^D|bޭgx84.]k&S9Pv.J-+Y;y~eM[]Yk-"ÓTUs~b N`Gʹt$.RƾJ/GtżI3y[!d2/#bm1V6X6%Fß!`Qbv5]SwU(]7 ʥp;JynS/kb,Kg4f7S8¯;k [Ua485s[f@t맞Sk*+ҴoGQZ|ng;o9uN5$-n}(^{= `jْXz0ʋ_hyV[;vPmg*I0x)w/;֭'&Vs14NzFd)[HV+^H()r"ZS3j/@eOs¹\fm|i(O@en*^_xa '"d y[I7m]T#It%9A,)al3&n͈ (=Yu@7O 57|́Є)z߂$3ե9u biN xT~g;z(g *FY*8RQ6>Ҋ P+$aշH/ͷX@ӾKrxD.JqYjrThs + i#1IE`27dtۭ6isIcSviY'LaԔ|ؐj '69ǡTISN׆+-c1D՚xR_\};` @S׻s jst xoҫ &O6Zut>q{Z=Y}fԉv'>GΤM5a*e_Eʹը`"ۧ86 =?{Kt"a/'}ܘ~4 -ONY2[DŽ7~$I?FYgINH65؃ &_&/}%6qgf-E8U+K 7PI ![ns|tY_}{]xe;=W1Rsr> 2\C0 y[=x / K9uT$rfYc*O 4F1-~a:(湙Cb))o`|Nn)K6x3dh~J55{zzAjYS4#fsVmiSb(٦}5w}xBr3B+ |+W@'AU3pDH3{1YK"pJ  :"r(jh6!@ՙԜ!{ɕgZ_fEU$L "SpߙۿπlO;x{YRJҧ {]:#\.ĕ&8 +.,gjm`L(+7oN; ci-P+ T;۸⯠L@,e+<ΰ|:`K~.*P>lqk)Ƣ3UzhpmQ`;΂XqzQ(Ot< aC[KR[S {%CH4@WXt?.C# k=9rJm4/M +Sl/Aɑyj}JJ +Rǔ7&a qB!6S6N w.A|e4[C~=)\Zi)v*?NcVZIJ7: 'nE1(O OwPۡzesKGO!^%ۘ7'=vS6 g!{F a55w|5pp*.4ʥ ^LC$I$ /m;8$"?cP4ߧЋ\( ֵ}qP3! }+#`~{C?BJ9t`΍<-J{,&Y[l~`g@TTnկ8e?\>Ib9#˥Mme1_:Ru1/`k\ M"K0|1Ѣcdڎ{n(~vu!G\CIΙ鼧v_o$E=^ݓL% .FuFU{7D&܁5̘4a2c pd@1#,\7Et^зid$j]߯C&do5qc,GP8 1btc%1 9:iugnupgNK;5nyEhKܑ IHznHpȳzO~| I9?*NgoUx80em?vû`bN3?ITAiiO(\Esq?]8[[z|؈)Āp[7ywԐ[ABBn3񯂌xt&7! yTeW}u孈_L[%4ܢ'Άk>*pJdo;7m*8l59 K|"mODŽ_{M$𴲿f* X:n%c%m\С='U7Q:pN]ғ|NY3U԰Oҗѿۡ?_WL=h;]=CIErm%'Y o+sPp8٢p2ͦ`㒻I+o$:r.HvϙqQTd-o~O?sVIz';B>%I(nHl1[ҁ;rk.;^cal}}!yeΆd%ܺLf|Ҙ!D>q/&FX7g #A-fH9=gu3c4+>5ca1?DoإRWzvz/i?Cױ7H?*Q|(PXw )2%4dž _?45Ak2G~BDhݼ!8>?׍t*RPЧ cAiAoT!.q379.-0 4|@6iٴF6C3|ZҾvX,@mY n7z/tzeY<Qt`5?Ac\A]n;A%iQ9kQx! A[!fa>7c.ޏZ+>хJǾ3!Ri,~=2XZ] ?) BiZ/q21+d8A=KlE)Nrtw[mTh-rHaXzjqdikhЄh &Njy "g@] 0 Pl!/'7ޡg#E7B H_(=hprc1pR n@ ~,a78K0\&;I5Ѓ9>%Mނ|[A vp ypŰbSX]`]C`GHcݕ5,dͷžÈ/f ȉYHUhK\P5ՂrU ڽcukTך- 6Phh7?AćJhvkeنqJn}?~45\j1R]>ЍTaUؘ9ay-}p3QZUQMO׹&v)tYA(Xx[tjVA?Q`}yIX'ػP"ul=,Rş/UAc78,45{ >( vk3t D˸$AQnxo[-UJYH"L$la"AnokfZJh'#8Gh?I3qitSTjB"}󤪠#IjlhaZ^-3!2q݄VcBt.jjYO7DYlQe !g'~ŮμxKU|BrҺI?\1ظpN5ͳIIxpFe`Zi>*۔Lt~Aѡ'Y8D D˚ 88a-I-Yoe96hrP?7wW3qY@Yx4N8}x$0`C}j|& weƒX3M/xG+5[Nn#Cy>=ҁyR>TOx_6?Bxъ">t˰<x@~duΊ )[oIڥ])(3(*UNC 5!l Rq^o)sB!2Pap[ճZia}[UhV ŢyG8%idKFrT[5)B`<莩p*YzXPf4%*J1DH 4'8*j\gӈUdlKQU=p]ct؅kW\t"꒽ҧBޜNp!뛔!;!pnID+MBUX꤬9 .kXHzX `Ɉ!]7-zl3蜒 um.*\@;9z+'=H.wȡԎO^J#JOF2 jd'31BHU4!i~ 0QI(?lNUBKd&s͘x3QDepW/*ȖOkх'\fh$d8)1uz.=#AjQȔg@#`^FWf3 ᕝT?3';"f]NZB*QG>lnD6d <`PKab8̾Ww|@X0퓃QPf{A>|,+'Se }b xW=Ll4)]ңxָ9O9QKR"5ϐ6c&-ȤO U#lسDTVIsa')S!M>O2%h/HH&T֚:O0,%[CB+aMI3zͮ1'^+hRiWվRR.W(@"Z~¼faE%B3>7Ÿ"h0 cZVԋm@T瞌186_Hrv!fޞa,-ug؆/>2%$h:X49ICB}nKT? IEa8JYX_A'^BH. ՜"C]{j.UXyov+˷+ Ԑ5cZ_ .<޵>^ɱH'KV?/1cuo6=W&‘kk.EGX;`}_P(p`;6]uA`F*F J J,Unsl2K*<.m:PgXK(OJdt[R#{֪ NvL&:R jGcp:/S|=.0;v*) ޖaC0ɸcv3x+` Fr& I%U@s.p8Cg:OʂJ朜|#z%6D!|j4'D3" [涷㊸bҐfpL)E E,>FJ,&?字XOlh'VM``*9YTȄGSQ{Ҙ!z5,YAy9MIMVOB JǣӫوяGgH3e6'FjK5澩JXka $4-0@Rniy5=u]$TLSs"֎}ɏy?Qۙ'i yr"!Ag}nlNʘp]a/E8)MU<ٺ-$PVyA Am*V8v9l5S2\P|n)>B%*^~,YSc`ntExNC}mMaY[c HVnj eӁe|}En"o>e;܆um4Hl~$G`=# |nE}~e!f3_vo-ESXsXkՈv=]ϭ*12eK+)=<a ӬfEIk;kV&_sKs`}؆27yY7}>,騈]~>@5 ; cD&cPA~I0M뛟^Tn6m,Bх}c?hJX3K dU05V}t'df;j ߔP&^r]flo1,e(M͖sH@h+ҩ;<>v7C3Y_#[T5f}~JT[N[*3ڛE_P'B tn\ǵ)z4V\#7S1H` pKWuzGCrrT d0?j@YLCwxΪhʗ;ZF G/V".~U~}md^5R $"S$p^)YlFIÐ[<0;}-uJJK=8跹$"xk#\"Փz\ YCiMIY;q 4P\G^ԁ~ i]oaPe!GC# +:AGU^k"wKu/z/?Dڢ-|I6&m(rQf"XKm-]ϱUy8V{yٝ*>`ECשM Jku<|f>vw-e/A2W,!n2 ܧ(%0GCF|I[xX=m%r 4'%lIJP"&B! dBLv\$GM(AMZ|j N@ ~CXRx3/BXW並.`C!e+%3r \V{_]x Y^V\1CHnwowsLgnCϐSo00&Tqs2me&AN'E%x9gh+㽩yo6;ppo:(IlՏp֛!Hb[T[v7GHu6 =Ȓ؄)  H$p+$_.LWDD}@Q[L w_FNgM철52\ov}RG@k.hfi&OM"u 'ShG.pbk9Ddͤv*OqJfJEkL\f˯+f=u0M(k|y9>|QjvC[Ꚕ Of$_lMv)Damx2Y(7N=yuA6@ X>(, Z $W*L5Lsݻ"jŎXb]qH~l  9M#,x"pԿ6 ظf]i!>lߞqJG kJPmFlg &z$Eu Iy72; }T,.Ð(QR4[,=(VC8J!L6Gޙ[6K뽘{9f)+[^Hm$Wۣ iA2CKc|p_$5~QM u IfL$m.$ s*6G-RpC11ĘKUfe'W3>kF &8w45-r9bL_{W`W:2I:n_*I k٢$zѹ0U:o(7`DŽH6!/xvQ<kFIdyWJ!O hcb jx-Qulp4;XɮM('%xODj.+#A^D3k!}5.cB'["J?m #~ H}8ђG}/@E\?0F9x <)JR]UC\7ݫkiJ$goTDTU('XFCE0z_D³[ 5vZa5 8JVΈ!I>qp1gY}*<IԿJpU(Z+rL ]uۣ`la0ff,Hѿ+z~e,l-J `,Hq_Mte L8聑K$FT`Hi5vsILYAZZ8npA G|pkK(\)OK܄Da'$|ϭ%yBPR>kFܣ#FNfML OSzcSpg|c[U,˷Oe|^t]X}/χ%}t 6n2&"b3/=xV8qa6ȩaIj6b8vabBS#2©'Ll}&|a Q`r <䰜Lw)p ?*s`F)ngLD|&P+:?Fw43O>,JӍ-ƯB\}L3UQ}"?5g}I,8MOFdcHl-e+ow."E.]DGǫvk^*ϳeiu,7Ğ6i{і fL&"}Fѡx J,F#F#Mf 8篼 > `P*?-V ty%)h|RШ8:fQͶ`%mI*}㿑J"67ԪIKy!\Ni?5ܙ{RN fX++4@ګrSkAJޡliz4i)xg;VoYnX̺L+3E%*dx} {YjQ!}5-;#z0ԅh$YF>檭}PyZ} 1#~@^F[n]7Jlzh)֕$"a3ѵ+:sB;Q n `9yؔ_璩Y=8ϲ޿OJ{yv +aRxpS >=3`2sGH= !fxzxawJBKQ)[7dϩ?oDPm/_ qtZrH)h2\v('[k6B(LcĞ`P̌ġ~Y@iX^%2f)Mssm?dn}<~J_=;7YH9fͲZ]22W(%Is7?[Fslh]!ÌA<NZ|j)ʝ=gCnXKϲ.+j٘{\9I(2 }HX&ן3"ePj2O( o 2G AKwEB 6贎DL1J|p?ÇF3Yn#8/D ߔw5E*uI5kvQAcG*4H5?$ɬY8 h&Q[LʛP)s(\':ЙJc[ɋ`A(g,vBi=|yVs TZO\b#A\TRe'H̯t3a-%7f3n|Q'3* {Q88#v(dp>'~7ѓ c&@?g{zWA{FLx`Ml>Z `9?AO?PԆ]%Xs& }CJTs ,g"nkanR)6 E\ӿDB⪬+¯&{〟]W5Rՠ~xdWm^eoǖb`.0wޝ -qW.sO+gڲ +n$A6|FS4} t>#RQC2U3Bf뿬*3?2UMԫ! Q} N29?wҒOc?2g^ tr-uB eEz^HӾw70TZY[%D{=5wkSGgܗ^blJ@./^ 7lJa~{9MC9p6cΓ~i罼j=;|N$ 6O=1%`&n->#iH{ktv(*pT=c-gt4u"74nj-qsC'.4DjZSުӁ`P.!@=$mqdb:̵bB U1~ﰨkSѹQ2Q* ? 㩂}.7x?ZP~ْ51=[]51zE?%P-q0Vte8R|9Ѷ&$!gSj#`sjl@ljnw2Ҙ| qZ6:V48PsΑb`*YӻeuxE9XK04e_8"vf{NӬBB_ b]¢GH*JJadVL||8lpW%:!@oJ$P+"<Gg c0?MXvAK!?NE*%)Ԃ,$Zpm"Џsc^ J\ yE/ƪ:I4á5a5&;"tc2"3":6%截-OBqZaاV}) y ^ w8aDZY 1BO,qW3ԌZ6ͷJ +t~li5@3zyL !29z̭Wi]ͫl&L']F{uF>R½?<^!w4DoEvW?G ,Fz^Tm$*-|P:>{ Aj]G)c(mvc4/bhTfڴEH9  `R8Pr0ĥғ>KLΧed)t[還Hn>''mK[US@`yI/2|SdIWٵȴ#/ϭ絃OcHt*sK&"}qتD>@PĢ\S|zXzc9o)& %Y4qþ5.Sr/?8 <7SV~"KH逸;͋kX y1W\-Ou9yHUlo/6Ie-k:ݘ(y9woσ|3Te_DТ}}1a/ 3ٲvWXķ߫2ND5<0(Uq`x P>d0*4!PX9LOye"twe49 5B:WL26~&B)pN0> 3Q9̺wC(e<˄e[tS@}ʥx6= &jhDrKt$2K8_ZhW8p֥`1IVVt^QgY~䳎v/&->х|/tx*iv!4 2ow̅<6¡,s6z⛎(&1zc&lҴ7+ڱj0QEN)aCfOCn=%E Vs]1_ מ*7l̩&p1H #"4ܫ"naS='cAK蘍oE$pTr?0_vafdk3&sMNYhn]KL5"uKz1BGy]3Yx&J[Kw/򨇵V;pEhqBgH؜ŏ&T/'fDX6 X~M Z83dASLGS;UX{(гV|'7P:jhC 5|*LApvz@W:N3!zg4^9b(Y(#zP!v&xWTC.n<oJL II .^̿*О5mE9JX wzDSD0856U9ͥ`;~፾,Rij-Q{pg{P xSanW@~H!Ƅ~t{7T[*:gzY+ % fOJmhw2xjEn/B0j;N(ZUL7i% "OR偡CvNLu}ۮq,$7.mT ;x@0G1{jmvϷ>{PJcX=Je}?r=6.P0)!]#mzM\<1nsGn`5Yȝ̻cZfBO9Y6ѧ +*~!9<5;`|-$d 50Va~k!pfŒ,"1BliWmd@ɝt`=J݂vV෪%"^{suhŇ֮E7O Njl?(YLjnlvx.k ̏69}v4-Uͥ*ԱV[2jcyd[;p>_{ \Ar錇\+e.B Y8{71B @w邟UِY^Ίҧeb ԫFBgk)mMâ N A24@RS Ь)CFk9 pk&z]e1C(d`{0|Op}|>u.mh| H̡+ d(&0 _gl+4*Luojhj2F<00H'҉S61QOsDx>yRp-Lb<*#w!X[XBry&m\yÍ7Ym;?YFx>"]SvΓ$!WCI o}S"rA@,)oKgMr&0f%߯U~knB2,l봥UUCL qݡ/CQ`n EB^S$G"e8dn(ĿER:7 jH'?yh6I$I$I$9cD9do_|K=L\0e 1o! MrTHn_|GQMi]|sj~GIouA3w(MC_$.V9q,Ė/Һ$iT/H9,l8 R7k,tX.{nI$I$I$I!4T! xmt#U+eBNnw{}EjΥSI<ɸ'=Z;p_I CTv@HG/\ԟ#N51>w\G#3!JNmp iA۹ D7`y`vt*S⢧tx0 =c<ϸl g`rW{c]\Y,7t~N9&e{85?dTחL2PY Pe`&w,\ϐ&Ul0#bFH ^lXEo;)3B[g4^NٹL  F97=aQH';G= ² RWIx }-\` ٵCɳt,P2U es~'ƛЈeqAߛwO0&D\e9D5FrJFpvEޥ7Zcq#Ke;ڛ%1X՗}R?SY6{mJR (>Nf&gGz5?i4s>rOPu˝k#JT(ec#SNSҾ-FNő(fR ks_Xg8s<~-W:(Ÿ+Qf p/š*Sds ǁtp^,A4B䋡ٔ~c[2> }63cJ[6 `{,A#U|:ZQ>7,0Ix!ҧ%wA_<968dޕo \Ʌ.S%1(Bn(iQ mmmmk3c LL {L|gAUjadSɶZ#d =ߘ11EAulvEލoj]m NOG+69,T2AksMq;,*Fq8M.=gsW1)TQ8"II}2H$9I$I)@c^(,({,:7htd@ Caj !]DTY5tImmm#"f ƫ:#u+-OHW?;kf=wAGχ_:=jOdb% #v͖jj@_3!DBeu\եN&Xka>cԕs!U3KɻN*U=/G*ިslb >x{*}=0/)F@JuJXqGHv0j DjUJp22-! XS(Io ,oYԌ\#;G6:K!MNX]$z FH=b48DJH`HwlǶ:#9O;8š *x"xcЀӋ3M9wזN׉L !]G4^+"~%a]F hM=$PuW#~?@RKch{p_*$]pI~·ly$Xٹń<독 򬁈člOOHFoO:C78Z2EUO_a1)1)iqtu /jp$褿ctdU"6#2.L.]~.+%VijPMWMie݉n:l$"9L8v[]2VYjV.ZZKxtbVĦL =Y_ \5µ5+wWJnbt;W7 }z߻9O_: bF8zɞ8WTVO}6ONI6mmm -[DgzA5qPjf:z&.R5ko,T<&pBz4Z+gc(lꢇݘ^xs dBz5vٍ&jg$oߖC '/O2>!ybF؎ȡ4V$;{qzIt UMu1g5\&_.,=G_|MS.̨yXm "N`4)-nB43ULu-m6kk$!|JZ[6hMPÚOﴶMvh9%V;)+ػ|LnmYhXCC &t-$g,SU`\VxBx?1Qص|๐sFL}/ja̭= G 4MsƐ0L1Е=͛dK ]UP>>V;q!NAiI s-GrBx4HC;r }$bI5%ad 0iUut&^. UM8oOC!Ol)LL%nҝL/jޚEO /rB5hNکl)v \lwϳQFtspU xL5"r*iW8MI&{WNhb)Jg7za rw 9ݙ5޼,,) f}vfHM0[Ju.9$8G,1 *y'  <iKծf{uoC?[_%S%hiyګw.xtpS-.,ɑJo}d,UbQ=h$–` _D].6A9`:u `Vku)Cj(` x%DX**p 0y*XygIVfbK=93,Sud]:0Ugc"9ʭF;E!>.l5&- \歰Am72ޠ tcxG+ eԃ&99Qs՚4{Q)f"ͺ+Jl$=r-gӦX۟WݦLt5EO<=gʍyYL1AnQ4 X-,MgDƦAV bi]xBrFhr4;hEg|NߒAT,?uHe}(}7lZ M}eC&I\ [br>RPKMS)ր;M@ qegdj< iR,),hgaMIb]j* MRk'f H6Ŷ/Wg!יCma΢ BD4 7نp.okZs]&J|LnyɌs_c\+إ!wv"Q^k @k9B 4y]υ?Us[fu{RcR6 mѬ89i4g? h pY܅BIijz(m()Q'&T_dTTBb?=OMwJ LWJ=ʱVεL<72[@-k0#uM]i|WǦ:Cpk7b k|i zy=ob` 5v(Yp);z:73WP_1*u01@gyd_.nUv.lS'S' qs?EO+ohU(Wb|!MX=K#9wܙTuQ?ĚE7%T4IT;yz>3+ !uC/;ŅhpFbIJ{QI+DZ]UCۄD,d!%UCr_NBT]R7(}㕹Q luF7h2 7iƕxNAY̗P]ؾzbL~Ǣ }a8Ɛ+d2BکmsOu5sjs}PcD* u/ V CnI*VwcE*r2}y+#O3aD }תe 8cjŶHNމ k tlc"w}] =e4lx{޻N&%h]3ڝrb5: ))e5qgiƄf8&M-tWd KMrݐ:<4ǭ$nK`[}zn|! mKNy/󈪾4^{EREaM">yҴ {K"g;! Goʹ"̓ izg2b5.|*4,~Hš| }ZQv'uO+k߫A96Tu.fcj)p+t!p.ELzevSAAߠ-tdyRbInbds@SUԣL+%Wx84{]_ OzgnW9W61^l w^xhq<7L"A9PC vl~/R"{3#*#l%n?{]Yl]$l1sC gC_$`~VTQUF(b :r284f!WD.n(^Hbב4쐫.AlJžHƝOPW'g) Ժyhv4YRyPBsR،C`FHe Ō 6ц){j H~vf^,l4ne$_]e!J8ޝ*h! |3SM}xpkyMMEQwP~˫ZI<Z",d,aSDpV"S78H{@9X*TbuAxzݭQqhkPe?f^K=7P3#%#A(޼BŁ(583n_Fb`ĝypK9)%$Aq$)# 0imngYDl󞂇X$I6O:K]]Uilz}tl쌺8,9 SP;꺤MZP-V鷦261:ZeqOS^RG@4 ɰ"ÚJw3 p4ŰR2ih =&?co ,W {ʼ jIެuho)(K"KPyoG|yRÒ=RTm~ȣ`=\q.׵:{ ?$!!VsB|6}o4T0$ m1xL 7/9 fr6oL@iY8G)NY|0wǒaWq#G">be|LzЄa?2)wj \KecLMg}n,Bc"r?K?Pe92RwWPɝ8A%PzArDġUZ':Y^4%WkS/JQ-2s$X Zf׫e%`u'6][o{گADmAXܕI!,ށ94PɚN 1IIɫUg ݿu$H_TsrL?V>K+Ę.7)AgIz׫akt~F7rp^WuicLʹ ,}t09N-YQF=qYC3%dQvBunx;u]pMBCw7&RNA?gVh{0[ԙգ,Sˊ翨PvqJm5[ùdy`&TQ{G'd7| .]շ|vT͜/#00Y)(V^>cLIf;a%BU_dU QD<`T[b/+`a{&ϐ0o|ZD]!4@ȅT혱LkDh( vA:oOj5}E  IM}S.}CZ_ l]gXyo@RԋBC˔x ݼv C3'j0Ԧ[;I ؅`'Rܡiȃ" 'LQP5*4E^c60ME!Ge&+:~SfxAZ̆k SBC%ZK u)1GIZ\؆ (kR[K0ru鈱Si!$P{VCvzkpfߢyhN0<6Ljžb7:zeتÑop%4p YOC$d@W|K Vz9LAh q)!UÈ#EVx$_*ӋaijvJ3j5zaԵ)+oh) qԸ~B05E"J!m,L Bc"o-N/󤜻okK 7^kEMWg69cP-􈓾xa ܬ:3{/;~5ɋMW`IUv$0#!>Ŏ]#mEs'2Pe 骼X0\6k:9S|)D6+` +`yn8a?B *" zRm^ oc;R}TkBW5.טѹwyԑKVY*n3oƒ ˒!Aj|CawA~"4=?q;rkb$-^jKs=H8;Vh^BNWsٚgCZJoq4$~ REFyZc bmN==H@_p9X!M920!n"XJHpກ=톐ʗ<$D/ΙS@cCAAk4ZwN!hY6O=cbnMVSG-QvrA t68-gX Y$iiVf˥Oz N+ѽ}٩,8:"hK9MGa$*h-6.cZ~LS^rYRu1n"+{過qAc=֎k aPCt1[ nᆪZCk'4ݨùɂJ8}hKE'`n&Wr)og]T,$}|&Dj4ԙ}+>'ZLmVW^W]چ{Akѣ_gtf3ȣmuv X=ε _q _\ Ɯ*W+9.(/"uvwkœcȽsf>s}W g^`orm$1@W70nʮ{/ۓەNS*PAG!3)$3b0">Ms#/oЅP̜CzFI_W | w2C1: eoP] WEPKe ;{-'ʼn}ΟO>?W4^01 ș-Y)pN!WxJ9]\hf5?$`Qt#ͻD#L|o}Bw;9ܧT:bR_i>QM.1)ѝ6)ȜzөoA`g-”dtNS;wkN=X&\"> @hQdfLz{tn$he_7; :J˪ y2B7܄nu*֥ъou Pf(^P5E])_RyO@dk+O %iSY\z(K^~z#!OLcؗΔ`Agښ0'@+#ZnWE*EUEgB>Kߵ&:tJJ-N^L3`mhK=|rb8REsF:ؾq4G_(jbDA $9zXMѦ \L1}-3NRŒΣD&i`\^ïO8R.ZOہtQ ]~ mYi) Hq*vmOLmhR\ҺvD*!X9[1ZY\Yj|+RFXU * Ӡ)"'s NM !բ'>ֲJ_=2^3a0BMfVe5z,ڢR3KC/(kc¢{aB|b뻝JS7x3H|@fgES]L/ I{)u P8-JJSہP@4W'oشj{TPjAQ 5a֍nhyVJ-LpV0Y-XÐlw "FoQT /% i8-c{{p}4[uj"rǒG>2yk/+2Jɫ!c-e*t•g4:o#upn"t9 v|Oo=ᅤ߭@j}LbX!hv ϟ^uT6UǤ>N @u_zLqiݗQ]}.;%E~2.ʑW_.5 2) 7:,! ?sM!Xui4xEʂy.:[wn탆Y}("t+!KXQZ0D:T\2z^t0`VXE)V4.ԟۣlqN),sZ"@pauaszq6{q.^nT=omUn J:. ]a_E<6bk¨ `rR3Rz¯{*#Td^so9g<Vhktk'H맂J{Fd5V8./?&T>ԍw &uI՚b9,V%s)ʆ^+eWs}vaAPs zN⎧&\`TMaBDQphjhOP KKhz@h}M-h.15hU,!˳i@C\FC6`yt"Vim6PToX+~"3#z^V#MfDvHЕDY;?&K w#&DEDTɈWcrJSkޤjRGQq#78 Q3mLOQ6İvvoM2z |#+ L @m]QrAſk<Wͨ4S5ŷG.+bh/E[3LH83.r 3 Hvu$wY_ŭ~.y[FLU4Ox}"߰(&F'`JGZWYkiߛF몔1"m~7#c?MfY_(Q&3`a7NMz{ %Ы3 e"-R }DMN!=iiB 6Y6$oC +qDr]}+pFpZzG_7iO>r:v$gٻl |Yh0e %=琫\_)يgam R 8N<(~P/]U鸳6YI%ncrֶ/f rgi.rl|e #|dV|h, 1TEAA 8,PMyr/E\_bᆵ/9}rQ=`B9?視3 VUL"y#1I&<)n幼I*L>NFO1a4 ~ZhS;A"S+ _3}8 N _ Xg/c _Y.(IhgErNxY C,%GQ&q/3Ή#3Z?vo^~_ǩ rPXXNcw0hc <LR"4r!M2fRG?5\r)>,g;{mUη3߉'c57 != )ܼyW>΄v21]pnzˎ<]So=y+}x"]m$Vz.έ4~8O )2& JEuǠˬH! `vֳ&7h~2F(tEA:wۭP/Gh}c+@X7+or< 3J0Er!Ł_Wv7z 0LA~_ vp+qϵc7"ckpBиŚYL,Ɲ$ήL&ևc1F >2Ϡ IQC'G|7js81VTŠ4lݰD/22[>%n=Ys =8gj\h,a1KZQvhҖDҔX~L.VEׇG2Çdłp@.g=&A~q}!}&1T0 ㈩rZ8bje$E94?:|r"R褷lݺ__~CX~3X?V.џo8AG,SN ͢;a H2u{Q›mLE!E v>&1-Ȫk▚#[]2 K?~(P@IQ e'Br"Z2є 0Pv\oO W0,Т֠D;%`a *$a2I N{k]g!R¹+run4$9ᄠ <4/luQ( z'~A.tQiA?A‘+N}h(vTȺeZnؐfZ/#6J/ B>u6x2w'e 1ESWs\,1! (3cRE!g8*K.Rg;]1iFXZ,a\bjs1aOs<">*1ȍ1-u'mywVx/箟hoc9g>BVs[[#Uh{ٻSIff ]Zs8boZ,$یJpi;Ϛg@ U0_/ĂBip@d`r~&qܱKIUiF:1tshu %n ]]|0W{1ϖ`/\3 X6i~el+gX,+-" bQc ,X1/#=_nڹY߷ md TZ,Ql3ף4cf$lـ.{PhdG תz#{3#[3oԠ'H?uzc2{M5@2Tq ")c 8t0rlC^ڸ:5iuBWږ9nx 6*`;X9<7&=rT_<|wSP~}ԯBf=M*ZH\fHuY ̫z]}D1H߶Ad\XxՊH%@t~'N݃Rܬ}2e E]-%=5Fsuٌ]z[#5FA eզ&gc~ѳK87"|8Q*p/Z /%2 X/X1S5^@MR/pJs%m8m%P\ ZJL4~M Ⓝ s m1 T%“*Cٖ31lА|`Cbv'',Ӓ(|  ` =.d+QvM"J%*@Tc=ee yÜ60Lx3LEl9^8_ѬYah&S:m7&~ rSz*gu=GWXM&5OVdGU#%mIKv/m93SU]:umo[> AH9û %/爌#*K0*1`C4߲;zrPs,zvȅ?p}v`ëW4񖻴 bYql[t O"B l:q~ pbP!XkB{whUop؈'gңͺ RoDƃ0D0@b/Nd($5`R\AՆd_&_F+Ng l 왱OY:_/K{r.=./Bdg_@<> Gb|$+\Sҙf? ddJ@m<Vs"텙sMa384c3P[ZeBO74>@1k(pYE筀M ]tt Q6%.x+sҙJ Wӛ\5_5>2*C#cć8um`,Tj0PۏG,W=.$GƒAǯi!?*GiLb1 Qdjxpn¦ H`@|( o;/^{޺A:рSbM@ w5#+[,# &gPUmc ޞ/Da_7|"Ȱa`b(rRFԈ͝D%Eg5n{`6 _^8@C.OccC@XJ,9.7 MbD w@%/KnG剿qQ_aly@DžGFe"-J'eڢ~C^wg]1Mk3Ɯa:'^/" QM31͟ѤF}b]=zNJ\t %9xBКUxhs~wC_=7^2wXkNyZڅi_':ypQǤtPw0(ʑFk v&,FR}<&!Sw619kXpwu-֚#Nu#QZb)mC>N[X,&b¼Vٳǘ+Fܹg\>\ AxD 973ןU 4w Y[Zm4H$7%v<4Msu8$x%FBɑ5h&(ץu*f%yxdH̠C/ʼAqxgT| P҈EoUA@ɵdF)C72$?$\Ow3̉bҥ0!k"sGm6|U8t&UDM`QvAa,=uB{ҰPPXugL>· }oY}/y{N`8R "8gm\apCrFl.(V$mP1_5MVGFCwV=ױݹ_@!qQt't u @1¡pH:}lDaѹ._>>0kmTS9Y ¨/V`Nx3q޽G1,J NOWd ҖbL.NM^ M7$w$t7鮨.EZsW; IJB,>\p'1Ey=\ $EJU|IڑJ sk`A+Y bp1{kP&kE( H< ӉW^ g:S /8dPd 蒯LxLSzϊԌ@! @ RNkF@qR> QFj֌,~~/2~6V \׺NŚ-*ҳ K#͔Ɏ"2H`m؛k/dMGZ{~URt%u|dh;:Z^p%2HҴqB1Ur6  }0$52|G[haYLA;IlbnbIaqw{5YZB)egD"c&o &|IƎ$ؿGiuؑR4'[׍Rn;TzzoAKY`QudrG9=?3 vv?r61Wr2l gvX?{jn2) F d_H5?#S8=rN!?}'͏ZWNE,EtFa7_HYI#\^k3JYIXkNOb6PB|>Ź QI)pã1nWė>βFS"[Ϗ(>!~2mHe[$fTV~BI[I(],#a&LpW1v{Έ0S0gYai< ɌYb'?ue:p Je[+Coch5PIgR (4BDLKZ Ȣv8>!SN)8gϑ|NLdX٤wd9vլg?6p`K J_]02ʵX+1=bZ+ˢ6َ-$Q<6l_ $S? ^<; kb֟ 4wص8_^1?ne&@G)DL~SQk?^T<t4R[ތ{H7i `Ak.|4֞L1}LG$ʻg08K I8kHw8L!mViIC%JeܽެPX_ D{_c4Wgiַ`Au֡%[ "')-l[^Ѽ_\uK EN.A3hNc$ ubϟꭖ*,֦Z6j]|j/*~{?|ʾu=):B8[neqhdH?pa.IIԣ^pOkܚu UA֤$4 '/s+\KT 3 X`o4Y# sn-N cُ𭆧Rk1 !Mۓf^c9em=eM!ͶH-=~p5}n.!_IOb@U4`us`AV0bΒvY >2{FUI+e:~0E^]<<[Xɵ uIs}y$2oR;iW{&k;NZP*WS{, j[J-z÷bX͠?GܕeIK1Z}ao;f;VeYWjU}_RP2 cTjknjHpFk&=rkߕKC̔-Ks>BgYY|aL:.1u3DP/@s.OIKp˓P(IBN ն\_;=\:&HX1D = ;zW$МFo`ndrkQJJ H*54];l<'ysj~{+@h=prNioe@Q!pHҘ_}Hs,uFA8r8m^A;8b z`t#T@UJNI?*Ip>f3=Grz͏5y˜pޒFoTB)ܤi`6crU6'bĮg^Sܸ~4 ~-9GMWci&E>2˛ܐOͣd}5Y i J*- <{;򹸵AV+X;iɝqvES;=f< CVe9htD{lhr( ҋ;Z2\j7"qȉrB əR%g[cO+?$=`Bl? ) 0d}{79 ?|&t߮_,R+p{v!Wg$UָTЗ čCHMdMI^jf&1}T =M\lN| t1D5kJ]d3Pbi 'HbqS (B C ]u؞f|Ǎ-cjؙ}NKi>qi4b =3qQ,kK9mj9G1[Q(Y N}|EB1Lܱ:=.< /W$iL%zt4VWK=DH P~ MB0OdtRU{"v| [̭c6扤-VVd/ә#H$TIQ !אE#xssaXTQ:0=UO.';7͝؜[E MLj%rRJWgbaTFA'2BIe#G`k}PUXPK!uJtuc7}aZ}k^ӽ>U_3f#B˔dAy;qmM'G]At@CBQѰy!/쭲B-罘Sޟ@) XqW'F;KSEwH NN8R:Hփ൰}unr &ؕ9& |%*A:x@9^`({LujQ0Kof׵*`5~j(@1OeOۮ1H%%,e$B欧V 5nvD`AzC"laՍL>agTtX{~ӈm펬\lhHav-{4%XQ:G0^bmDU)N&e? ]A27ݹ2 @hJ<])q0`[tیNie7B xP9^.#'z߆25(4qz9]ud@Dt^h~'x.+"`搜-MZQ7;{AӜU-b#1*-29D;sD V_ -zVuC3튠0Dq,_i ~6ĠT*P.>wׯf9ʚJ|s&#SZrZwsrq6\Jdj4{Bak XN跥F, yGM 3]zBoLzJcK^R9kDfJ{\P@o6@"-)^Xgǁ,M$ Cws睶p\m?8\ ݿ7(|2"7"߂Vl dCcPOQPo/Ղ4Թhgmq%&N_>.`Շi^2xZpn3Gsq CG7px;F@uO%<.Ledƺҋ5oEsNF0Pzܡbc#uJrd\r[BN\/v8N .m,g/0G4̠7@{T lB.dǠ"Ys|6ޮej;[ވgڬƽB@K]JnyU __NqȾ k'W!nbSrF}@" U}:yTrb@$})ye[@)c=Jse'س!u1SWlҗgL`?X&nc\~'xNXib_6C131#l\j)h/*XJ1wd<溙J!PeJ&|:6Wn[c*_01j;av S_cn VX a;+rh%[r})?'7F5D UsT4߫"'.ByGwQ# RN*խ<doÀQ[|Bt]uIk}\"}B.,(3;be.As")d[=3V9/im&yډS)icJ AjU} ]ug f~̏u/ @g@aIR){]/nk5 ?-$ugϹ\lK\6 Y'4*݁A߀q:[qlO#k2*v]#wI]5 4W!T%_0t`86ݳnNXeYpXܿ¶5ʹqBJXcVh$f'4Őxgdוu8æGz\?&Iم JVwa`!.3 ~$_cb/H[dAJR7RvI1tKT-W}򓸝wuU?^ U sJkqY9%֦aXҡМ*NȒI1erg!-w%~eP9XT7f |nLY ~>tɔ Nacb=ķN[+IuO=^ݝ-#)k2N( |Reb@T]t|{x6|-} ȁ1zkgۯJOZ8zNRlLoR<3_$ObU@ o,ŧXyWxQq8oѐ+dW@Km" Ґ_,/`d! +!m+}q@'1Y坏u>J`y1N̶ {liG(tL94hMmSLa̹-Z8̕LrtQy&ןs4MxmwwPᒡ+W*LHj'*h6pH꺠'dW bDI^T*ˈrLj?fSHCdkPh;ŰJNBm~;~䈯?i9pՔNOQ^TҸki@,Q.vKh+]䒋{qУvQ+L/C!>gKi Iں934r'[݅\tGX)5]4Nv {%'LcyfL^c('|iy#~4M)C #ӓ WDO?,hh5Budzm l*zK8kY3B^BQu."':C|~O'8uc (=re]?xpx RmIx.Qw34$09oyZMjKtqre[wViru**fS'<}z?O9oF$Я<+Afmf\zNBSi7oLiY!zhed+ucȖ[ؽz rd%Z8^Vcr`S!'#rL DP6_g6:*hdفl_x6 q5= KsZJ~x?GJ~6E1_yݞqΏYrp.ᅥ]WJ-ڝweBr>Q }nzÙno?A8,WJA&7@n-Y#[uINU`?P vz YhiҼk34'zޒ]zQ^pyB2i<@[Xκ/CnA+ [>-k߸`Flvz[)cV~SamK1k3\<0-Y))2YRby(REppgeс\!Mu8/agaDƒM gL4z V 5ryhKvaad̕GA=~aq'8XHplLI@-N/~k!YL^K#ouNBsb@[)gSbKB3T^06\eI7੾=NqBږyՋƋvS@'y(gY7_+X#_+hn%ܛ9QZO067Urs^1Jɩ7FoD-gӡӧfT<1d/5̫BU{8{㭛rY1.<`5Sa,q*X{Z" -$a#],P0o+d>gQ_fTW7r9%Q0/ǹnZ7nBQq`"I]C~ƻJv]SQ> Ly*(lfl@~JIt]\?C0&s/uz5a2=xii&<;0?糄DQKr;c\x:ny,!DKbޗXQ s.)-)O>]\AUuWr#_ ShD]Iћ8 i?gnr'eJmnAVdD "_)OЪ<8P>>c āk3u (-WSTOpA 2g@1ڢ߇c,; E洅P?#~!745)=NlϺrYw(i0ĺkk(KS9k ]b a(vrҶm.EM2/##߸<uKuN9004`&LP@lJ{z_ @KXClB^t*tPjeX}8Y6-19ʙT`҉Dya"lݳ;kl$}/'wh5|W(<Z`5r9\PS#nѕV/2 c/vmq~kFq`=8q9:9}AS.y3lh~WfRnXXLs5|IA{**Dvjgr*lY@}Qi:XdKo؛0µ˦Tz+e5/ _eV'zA_txT? }G{҂d+rpa̡)ϗj۽Ur:Yxfp.(#2V'*:zL@N!|96i.#E>wɉ)#yBXyU`ӛm76+?~7׍CbI N3NpJA$C̣ {0x];{򲉊:,I%S:hU3"MPx[v}Nif0)|eA9 N'Ѝn_,F!SXdn[ꦠVŻ[xB9;Y`lYPΩNʹ $p#$eL<WY"Vd`id`(?0+7cFCX%I@u—g0_+'ͯgQqpXEn(1 CSǐ9M' ;ӷ(EU pV(HG/RmTƐZSwoDu`D)E 93Xķ7N : УL~B+{zI R.y=5Vxߩ}T%?Wx[DNY4@>B}ڹʎP7h uV"n]eإa6vZA*ͤG 4ˬ G-[S4I!MSSƎ:׭78D/ȰjqcXY9 p\Om48dL24hjZOzfR_d@?Y~ՉwX\S&Iaq(/uJKey#J_:AO^Tcz$p%^ihG#).CEa)lU+=bZSO5ڃqr) V^Ul;Љq-Ynvl x:ڕ[0]WpX0/IAS:~[IL׶xD7m\+^.,epeA1S?YxqT8zxe63_),RVIc)w~܅vxz[@v̋^+\nɜ|GS|LiF?o+X6Emڛ~sO9n~5T֡0 !:%47HFkWvrW' ?d+4xnҙdۂxsdKU{czȦ?\6)pShhL?3W!z܄5hy]"w[ͦL'!Q MrLG E~]0U$hSIo`3X69H0yWi7qQFyP6'H ۙNϜzi%YGcT;l?n {ɱwtõ-l1&6`\*Lv[8 -)qlsb,-'8<5Ȼ5o5aE k'/A/w<:~"<-_,gK8 ub6f538ӣI9`X2ŀ;8x1 dDAxB@+QuFEs$(r~(|}Qy #1L$J|閦S$8Ys (IEF Za&s?ZC1>SI[(L!rL!}svjʺBWXJx3>;ð7ŵtC_.R.7k6@;U=zmVqhGԫˎ0sӗ$E:9Rak]4l?t爣?8of`  6Mq&\y{KR*91tÔTLy>Jg! JsT(7\ I}$Q̹24W~/opSҞ:2쫒%5ٛÇ pKE4vnG' ]hI{K)aNgui_'=zu?}7ГFD Ioq="Cѫ7z4sgk)?An 6{ Egvꤗ*>nRo5_Or;gw UJ+)8@2oyiJ$$,mLqF׸m}*bǶB*/ZO/\D IMr҅ɂ`;o1;60w7Fn&n9I[%8q.DTnA 1غ6LxmXG,N?! Z&S6Cw^Fރ'en'] K^}7sZ aRԿR\Ņ\'M*jy)9O s~CG 4U°H:C~s ]i;5z?3ʱ HA{OmM:~`p7( X ^_ ]&fz}J>in,$ B=6Zt8ȭkÙ{G}gz>9RdAkڿOOdB|&Eb s%y{*WwNЧ3pWƷer4٪擉0#O9eAp/  `JM`Tяm4Voj$62AsH0jg pa>Bp:x~?{-|WY>}nw'9bͷzLœDα)JM4X8YqcR_Y鈫 ѣ%t=I~)eJyl VVd%0>lu ;p ]&6Ufж.y!TM6⯹'$g%Ehxx'~jZ x!Z_NhӴ5<{ |9!D#% g6px߂?o1qơ F<0d/:B3Ujk.^A1b&ʙV-*ľ[V7@y),'` 9^g w!XcI>|.dnV5$Ǡ~;#+RZʰ;f?J gC(g.ܓRɤ_gΜ@ju}C]H'BƠ@B09w:zŐTxm̶ܔTcYsW;(AdP<18 ~ O9CK>Q7m|8I;xī`Qܤ,B#fUJA8eM;@ z}"a FYte }je,'m*Y85=G1P ЩRC盻iGG9ӨNN0;|~mpՈ[ʥQE#߫wܖ0Dd^91̎3hua ρ2lۍvҹT.f~kOd;T˚Y" M O8ah1N;3K0l4p;MM]j xwMaGus"#&H5$NIQ/qJ]SjQȹNL-QZvCs^&I%p!+{#1臿&8CޫjTdt*!ScFvz 3=a~ߊxlᇬی~K_gx {[/ne|_:` ~Y3lh$lHq$0wI/#c~9e+Gdf~ԭhSG Ws]UUεFiR PenɅS|/n]ت@l<XP+{W5|7 Hb ['KkmsO*8>{8"b+QжeC@ۺ! Tz-S%i1jy_nSt5Q7n.`{Qu&>M<EB h481^@|8Le߃A%0˰B@MzDq'-(BFv讷B4~S#0Q,L%ܼ;UavHMm;Z`?IBK6v'MحhيbdtS_Tl΋o')߸ PVW}=,w}WjOSxs]Z+SiOKZaFK-rw@LXoa /?vg$4Y>fabQXu*oݻX];L︻݂de+bƷJ>Zi CkŶUav!ꀍ^ zT!>"`|/= c*h>go-lqFlS-z/|:zL*g>Lpwr]QFk"xVڐe)5y[2| 2ɯJc-d #d56ˆۖ IY_h$61{21+ܰկ)ʛLV8N6+ [&ᖁ<:Z9}h2z<6^`^*&?yp0&PDZQb|" K+cGnSa__.^Pa q\41QPoiVyh6_wO{d[>6-ӿ-(m\(ء+LI`gZj]&1]FCs0" SOYlFgۉ 2t@_twؚoJvRa/Dؐw3 ;PCcV88tw(f޾]2LAň<sowNƀw= Z+RRey\,_h+b(/bօFOɮIQ,&"aAyHxxڅkh{NdjvqjqBjCmZ1 %lSݽk!t̃pSJ1W'(7b`DSrމtxJlp;2DmE",f;^˼kSpp .ƻ Wf6\ݵii ':2}1Ρ},i\ 'Svۥ 2-M'=ebGھ)]c̋)˒|pX! 78<t{ 6bPe༪q?"aR۽pśڶ|ڮɵtSC-IJ+863sp HTASW̓ocϓxg5R ("fʼn" D3,}!|(Zjg'TtH0LUDDC#CoXbs(]F2@#, zCt2Jhǝ֑""7Lʈ/y"qõnG47m!#14μ4Ƅ"9~%%0PޑfΧ< byĄE/X+12 v\ݑYL9h! kOFE, ȵI?BP!Q4]7sGcvP)\GǁuR @\l 'vF}Vu?BVި ΚR4E02$ĬS@:OM"CM *yPPX]f۽ΙnPEK2hxf'KކK@zu'qx/^J-d}_L^=PGlj7T zui"B-]S>$$mv  ܅ ^v gh?xA79[bSjkA Ώ!Lu*Q$]qTL^fNu(Uvvʮ~?0<=j~3?d)IVg(,hhVzu>jL.= ] +{C5 m*|Aw1x!875Nx-oת=J %FOSwJSǗ;OyCU-jşq*[Lwpodh6I$I$I$I,]Bx?쐎70 )`G"&`'Ǣm$3Kd9E^7QtCWq4IÜyk,.6hkOZȈi*j=% K9F;mPP?|ޜ~g`ҁ:b3SmntL0 s-$o} ;"js)q' OE[!׭L ;aX@R&iJD#LZea:u)Iu".LVVI$I$I $_ٕ'Xke95?.E93ۍ&T'?Ձ[?` |9O$фʃxNѩ*x;)ב *!ghc`{^$ RvJw6j}%ɐiQ[ I"zrܫ5\fCk%T^hVcdm~n>=#u7TukNm$ʉ&YJ^J<"!vJx4cr E4󃮋6^A/Qdef0oQٙO n>,F [fk ۰5Fvri;ݻvX͹~v!5zir}a+‚'%}<+ӽ$&y~Bl7=o-z0cdKeφ*m.OdQşzk!i3~Ese{=nI1E F?;1PbA 2}mc};m~d9|ƒ,Cts~E01CTl\r|k ,ܒI$I$I!g!{^px hwnJŅʪ`uD^$pq%ro 9p[MPA[nOoІe-өq}̂~U{m`z҂8[ ['#5}EZ DF|_W j%^Rbilx[X0l'ԓ [3$@8(6I$I$I$x*gÉC}!ԇ\&jH׊ßYwz#o?S׼h *kB ea9j4N :@!ǹg F 0U9UQĚz1Gg G }W䇵"Ou$ w6pvI$I$H "Vk㇣M'N'`R2fԿ/ #e͖c˥ ݳHа?I17!zUU #X79Lr7cvef{\.}:?F^y6mmb U-׳u*iz=H_U,=Z\ Gߺ~ ꕝ j#Xes&9 Ҵ*ڜ@.~B YeOd-87-4 d -sKhk/uonDd,?couE9[ םBD5d[fU@Ż#p>0HG/񪗹ggS9s qhWqTfҚƐwEG5X.%>vMQ6~o(.MR{ 1Vcs`ZQL}vkft.8w#3 lh[xw&}ƢǧC[9o$ߖ<\"1Md0ةrI$A$KxA= &=Ź3f봥UUUV3b ۾\ۛ<*<NcMAQ2JL0v6χe=𢡊t|iV2Lه%әZj$f[`C"B:hS{I C9D~bDS.ʟ%M{REQeB/d:X\!eÅ6ck+$v.oH}:gu7.8&ۆS޷!I$I$I$@ncjN<$lӬn)) Ji.IxGUB;Ҷb#\e~('(lx-?_eYFط(̊WS}Ujpn j KH 0z,rB3VD2< o{ hZ3hT[ Dl[]C A^ܹ`Ba]x'X;L}-/r,W%}.bq KI9ݮf?h#um2`j8vҐd:a mipԙm4|V4!>}kpIZ.Ks u)嗇Δbuq>Zѩå8ҥ`ҡ\ QRA/,U`Pn"Ӭ6яjaaCn[BOY%[`=i#GΚP|[d]mmmI$up<86+X$4]U X7xCBC!ZrUw|OKuoa 'v}% UGT0{11|.QQ(o>\߱ dyfdAkᨱ;4\͵-CȹVA96e6֋Uڎ@ܒI$I$I$TU(FFbZ5)\~Bߧ@O="&@٣Fx!0ʉgs]:|&)!T]&H|(#61mV'^!x(43b/xoEljb,j(B%.J~NW,J~Op#%V% m]##6|ےI#T?ꪪ>7\ix|t0k;J=e^PKmGb/R>klh)Hd (܍Y [aMvDmmmmO*iYq;ÊNV"߀Kc9{y HUh}0Mg7֦D!B E1rT_T!C>k$y[ez-gەK? Wwj9bڴUٷM/6ֶB,dCG"_;0Dxh4$G 6 ]LGB7zmi1nls*= NEDq2 # 4FUe"̝P]-^@u3PLm%@K*y4!<)8z>]bG: U{ {y,lJ2 nn˟k&Zef)&:RN[jO53<7G#֜a{d@c>:YFvűlG.$0`V>UnQ_$&6-:3,9;᧖\*CmaVr?[eHT+{(?,m!; 0B#V= Xߍ;? /kq_ʖ/U#eiO7~g2^}?V&GڙoPj٧fQVe:Γa+UfjHDB>|inv+vQ|A5҇@2N?8鄆f8µ;.9Me w$C>YMkKMm#X7]#OJ'6 m6m3?Pxcm ӻOci. `Dt O}I .hO~% 沵*-#G@1ޖ#m*hӾdϻ{^n2.ZdF3WGJwE(]}Kc ԥUH auOPJ3kXD+ H7͸ `kuֻ̗Rnʊo!^)bTц'rbY (+/ŧ^!xc`f.yī!y4N%<x\,Ni,:T.a~oʠnDn+wz_s~ؑ?p<8 7~.?S);:W_p Dn%'Ih7 ΅v>=b$տ%19ODGJuJ1&Ji I]*H'dB ı!m#2wArg+y~헚^t]{2\uδ,Q^4{"E||8+@g0b +l!.>}EL]vdWf,DF{\gpkm/$.Fᒭ8h*w>!8H*v}@/wgspeiI>^i"N-C;`7j~S6J ?&5n<2pH[2Ieiy(iQuyfsΐC8cGI1"e'ⓨÍb] _muHqƓvP9y|iR<]N OA癲cQ]>͵ ].]Al>m gA;?΀X-Y0R.bg@xz:j#a KJz7s}mL[а#B@Q0@3NL'C6G:'B'$ ;m`@8J^j>!rQQzbަzDㅥw,Dj ͓O c)A`Ɍsj94| ;%ЊB|A[Xp̳HZBnjm(,M%h s1 cKMIN*_D҉v1WdT _oHNiޠOoan>|I~^.\G`#z3D9rlkc օꓠGѥ摒2lcs5(ALK7* UPryAy{rGǽeܫ >O@ 4z3︴Du4#v/g{8lswSB[7WĔm3sm>Ł|. .7y-^p_ (ԶT+V Gk]e5$ົv{c28f=/>9X_F@ (zEħicB󯵋IHYꭤSVK$09B#Kqf(0m3\9*`Ä1rbb̓4d+P7Q(jJm;ݣqt{??ޡ$dOh wr Y+Y̠E`׻֓X &ܺuqeQ_E^[nT&^Q"LhV9+̎ gQvu%!wN{qoei昍Lй%/R8"PJܳw8?s.޿ɤkvk<e-uN=|CD3G䚢 Z$Y#1*h+j }„~ 9JJ믑:aHLgziѕM b0eh4ަ^"QcY6l%^t]Rq>ݲ1R`Ur]1vrc{ kR˒e1La'*|@OzhrKО2.9֐/ u%/ԉfefUE ʖ*@$lIdҿ tJ@ :i87. \a5; y-IÑM4s:>!`maw?$NW66֦*zՋSKPnX]QY p&$ISߠ@ ߉6h-υȰϧ&=4:š=%>E=uպJҤݰ?{t9!fIGP+UVwK" 쉸W=[S7Ify.Q;.*!i=M~J0|)|XjFvYt쐐ԆWl)3aƴ8aިm7<x_2 ccC|#ܚk-.8 tFbش}G]URWa6#LLr䶄 {y̞]_4M: T5[w֝[ZLccX&^VFKL8|]!O$iN͓a"H U?bM 6`P`ǹ ea|4q]`WصУۂAv(>6*7 塮ڡ6މf!q7eU?&dw8Y}5uJ5%_:B 0we`@BۥR\]ul;sd9B+Xt鯯PW}]nZ*gb3ӆB?L ;v-#R5?RDYfx?lQbVL\gBAe΁E2y;3q]'4'tQ ~{It$"ʣG[X'PAG&b 7@ i0 a*@KyM I})\GXdbb:Єa?P b@}˅gDo4hhfRU#q;V F31h=?$}c˂WsK8:W*0'T8[XOBx8jpΗ>+q\ 7dR\ Ł=ӾMա9'/Uě8pBIzsk!'k"Q)<&5V6ӹ %)Op2u"kL,n-G]wj ,A6dD7j9rw }_CwG'k7sJ6 xS"{HM,[q/Wm4GaZxF (p1K Jzi5 >c}Ƌ,0J`x5asǏ[?6j$#z2J#eZ+>Z'i, Tc=tIjrcQyj,o@4N4*&Z2[D=k+׍~1PC=>w[~tV؅hTbi=!Vcu@Ë1:~(pUL)iIZ=JYlO5][/*5yځmt(R֭/xSH#JG⶘%M+řؼ]RrDfk" V$IK,һ|?$ NUuTVu|_N#XNn%CM2i㟔ۑOXbfZtjkP3^R XyƘhg+wٓqipAe,72l+3kAq9W D,^q*kYc{.=1?ye`og SF"`س%r  jưУ]`ݣ:GZՁo}y&Q8gAAҠpp6UPG)JЎ>|;W ˥Ie4d**+BYBl`$D 17vwjӭjm'au@gf)ot'р?X,J\e54™+, urmLFyR$ΖXΗ-<$7]uP֗ Qij<-YH}HG:zִw ٰm?Q5, V~cyz&n:a24~p ( X18DWi%C09m}(y6tu &j}R"+ fKٖ(?vЖ}(tLƹam {H"Mz;- JrzM Y9unEм+{'9l,;q/tj-䠗#0=tyzҠq{n! NRrnΧ&P 腻['1}(#R|LS 5F<R{@c^}@Y_T]"f^tKc w,ar癅# }qkA&o`gf.VP4fG6EG8ӝfk( ~@2 2"[54v%hX`{4S8hg6A'go{-?o/` 7q2P-,i3L Q쳋"@b"j&2cS8U;сGâ6v"OEҾ=SժuǯRlE!~t*gko߫UzXƳqBg6#`{)h7zYVK 1z;¥Ӥ"t)^G8a|A$WlŶe~܅\PG~)ٺ_p!y`cwo]'̫<-]^F5MlmE$ϑQh-7>vbH5ʘʪ.f:BcFb߻%^K+9۞%1$\8OP3)m5/zx͟~N-S0=Yrtld%IK7`VCI @{IR9`GҦD܃gHN^pCFvoBl{,Y.8BvWfX196b^SG@Op m1'hzl^Ǘ˝-llrRUI{д˷nyTv%RgdtÞ>h!]sa`-Vt龍b89\_ 4jaDJa=5ўZuV = "8 `,:ϸq ,R̼ Ck=@z+42<됔z%]G:QMJ.A1SO5 7œ}Sp]_|]<ډ^rPPFMnq:1bGQ,z=q\Ln;UaŦ<> I_Q]Vs%N3|OTV XB *q)!L@i=xO2eIP594t]d8 bYbGɝ?;ڮ]27Oķ tBhq!%h ~&Sa<݈O3+Is{W7r bv)F?b@LX{ .%o|a<)|Lц/:?MuTfQ`/zI z(W6FaLfcGIZ[%I^jjpU7OFw#WOй) Ikgvذu1}-17"~ߔc8E$AꉟoKla|@sD+b0 ޺40gTgϘ:Jݳ)^w{-&!4upy2 {0=?@V~)ғ tG\6k9!蟵Q;_z+P{5d9vўt&Wyv+͔f=[ >7x ̀0o;@}IaT\ s=hqTtJ"7R۶RJ*]B[0짬wRttTRWGF7@y՜Ra{rtJO- hWd|{zR} }/Ё`>fO$$Y[~JM4n Ņ#P8%9IR!tő8 ;"[ qsbSdm BHᚅw:"#M$nm,C ˎ$Oc;!!@w :U}F6Q@\<6Zc ^)[.Cf ڬIm鄪M5?#!e7sA1A<Єa?P b9PMsXh.zFKMs1L5.(]dO_S%%4Av J;;Q7U d]0DmdYJ DƖ[ǽI 'A$1n[a{tϩJ C;^^Q^!TR0/[lC!0p Xz7 h+EJg$Pd9M44 !L,@$P^JڇYqj_Ys!ˁwIpĘjƧfL@5Y>\q @yp f]68p`B Z22{ѦaRy"?AJ.gDBw7OJ-;DlĚӂ]UN"|*Ule{~ns0nBɲ6ۼ ›6ɶY);یꬥ˔OWXysN0˟T1A`kx赈fmu$,ڞ%2GDfv(078c(@o!.nl!,x%=9oԒ_g:4I=73Y Re1_:m D"W[k#UE],e5/W٧`+arF5 #Pl6J%pEnBWC]Z-A*].6 [w\uqV.KnUu*m:-U ʼfO|Dz?.6Y?'t%cadXfE9 $nXZ6+X]}ꊬm/Unu?7'lwm!L4ޟ\hI'`G.qWj?r9{V(yf^f@X%޹SR@'?|>7R'\ 53A7 0޴>I8kE?:dsGU@].\FyOvmyQkis}<ߙQy`k脾SpC?8NKT=w5XjU;7ЉKz(J_23DWzbܜgX[z顊0K}B ̹dd7fofdWbRF=BOJ'b ;e%tVR M%k7o)tZc"Thy>yM.(Yh|ĈCHZ1i`!$w֛`߇9Šb_5Oc?nCԈ#VY6X89M%x 2X9ђĘYd#TTIoMLYs}5~0~HѰw>#K d2~V̅,(֦Lt!93~C%b{74V.@_SȄD7ճg⯖9G=(Ԛ$nzB=#NQ -?WNVO룈*o >%nNo2֢TK1%tiwGmtuLTYb%]gZX'1p\{SP_d4΋RM 0 3(nA Fމ ,E-$EPYhĽm"͸1C-zE  OAm{.U"p4\%9챂4 >!0r R0pu6ߤh'U.x UqZCʢx{ȹ>@ -[^9jٝGL{4é;' K s붢-e$Ҵ g*:Qj|]V~)TJ2gveIRʝX4VE֧%^/'{Z@??s^M=yi]/`cU#K i]CԾ0#R8bʐ[E|a/UN1J/,Z(xyԔ2 x8vm-Ւ彞 /,׍laEsk-FCl(;@ձ: -;qpHsDMYB{G⽯:E;Pb+0 dHD{:جxhr3@ƽ*p2$6)k>2j<(_S7;$zݫU~P}U":xtX{ˋx!@aH#|3u[wTXy>X)} n=/mpdKEUؽ`;%9;UMOg٣ʾ8aowĝ¢yt#yGnNLXa&hq2[DtA=ɏ3^/47_yu垧:@ ׈8UlcRVC9vԔM&>W{r4g'oJ?|2KpXpt/ƴ%QGd\cJ}~yfH ~@DwS9qo+v TAJ;X Uoe߸>0D/ Y` Sȏ @B`uJT\ U{?A]. x!Ew_I)za906ɥ$-rE6eT 1ȓ]P0غRX#ܳٚUBrSJki[we] l=~B F0ШcL?Tv(CB\9-y$|K)X@Xz^àTm5-y&*Ta:q;NƳN\K{F#:gd"k 昤Ub*2$hiоvfrh!⬰pR@V8[M-eytPeW1uhO0bJwل4sdfs(~e$kP8$l#"1W]F~O^EĆ#154QjB[ #*Dv1呟P`Sq_Y13$խ>D0I ⥌Sџ;p"u #EHl(!O:m_T|~:^hzEҳ)@WKw_R}??imr6nS{֕.д&{g9[La8GN#ihR)>|@CwZƔf:2W9$iT3W(QcaEuRiL*tr,T~Ja{}(fG\(w|ĉ<.Sf}15"t @TT_gVh%9T'NTOJ@pjo3ChYy?p#r}Xz !и+:#\^|]*DY1x"0<_7+{GP(jcXH2׀L;K'Zڈ O7mjiZ=dQNɣ{8?͢R6:Ll LjJcք3PVm`-c~owoզ]~;o6?B_#Vwѽv}[ } oOܽjG1ϟiWmռЍwQ|=R_'[??ylOѩ> D/Q!c,IR|םUK>zQYN`+i(@̎Ckub-]i2p܎@*e=W"6+_`CP`P ^iJQLO t`$c0Ҁcn@|p.pUJ)l QhW}j }5t/ܬʂzwӌ][}9*L"nMeNZN1~Z*,̾2\jr+qU]^xzS='U&'>o\Y6=~M~*ut,}Ц3_(G;*Y)ӝ̲iZ"#ZB PJR:GĔv 1c=cKYs(c3Y$ %+&tk%Aq<#+9Cz1Yi<+"a.Kz|O—yƖuH{n ąr] ~!qmUc91Ԅ@ϦYfN+]=Vb~ v^* sVb7r#\P~^{H2ȃ^0'>𮇋CCL͡J~i-壉0[,nCZ}ΧQuo/h#>RBہz=l롧~`8cI.}NЈ,8# ;~? k:Y>7WZetzЄ`ucoN&!?VR5W3+$RWS0|08,r_`ND vz"D~dUPm })iz$?ΠZ<gvd<L>0q$zxYI ?op5:-QT9wYg9U|'$)7GNTL 1XwNbLP;h L:lHlrXr3/1r s_GD!wQ(CMZ!MB`|0#}n|3J9~MVY阝A?( ~1 2π "=.%i 1ݞ2@Td,T?$o2-@wca:F"Β!9 rz﹨?h˩Pi4hFjQj~4ȣd蘅: }Dv?Rn,$s(_DUif!nZ%s5+TNK>N//)39Mյ}`֛_DmPَ[EYu݆SE ?: DÍ:;gYF$[F_qWfN$5{yX`=o k'` enwEYvm虧$gnhp y|(٢E<nO H`( thEz4Hς˅e}aŖI'U\iOkfi9hCH.JR 6Ɍ59D0(G+u">bZ#M=)3Oz˒ʄyG_ {67~q-"{ӛ AJ(~m y`[ch$c}2OK],];9`Q":$+֬2_A'P('+ljkQVJecX:T*UV/ΨtMN 9k5#bDc5g>LYbѹYJd"LȈ5ϜM !$~-EH[KU#c-Tg |]:N4ieņBz {0e/e1䚂1'gQp6:XW7@(LFepoLrIޜd],=@zj %mUNԪ? z^ /ˊI-_C5m>y {W(W̾lS$s-O5OÝ^okd 1~/f w$7+~ٔ#)\a~Bv{}J)7"Gq5.5_?Ȼ<3Lv/ e\mc{q7Y9: F/uhtmv"XLyG[(7lqhQ8~Z"D|f|[`NZ2\@=l__1 jT;.*0I~ cP>턏ȑ9Ϸ *#Ʌl)˹?u[͋ 9ʔ@ۡhS#,W@AsO:`_ԅPh*}{ {,it ] )ٻ7q5R"S2"?}*C⣄HN~S^β|{~6_LD^o+߻wъ鴈tGzD: FW(p1WpT5d7cT@pe|nQva!yyMr7mKP-*hy0jd  ,7XH.paA- >awK64َ\1ٽ8dNR),5JCii&W;B/$U6>wR-*r(yrT!Y^$X#{+_qq<㩅f~g8v#H$ɍ%MNBtg-3=]/l$|R.*}mJ#σh Ӕ;˘aNf 1e:7ٍ6%rDӥ T)ihgv'ґ&D܀, j#G|H+\#>N<(V&5k^e1We|h CeQKFyժq"_y1$Y:@"]f3Gi`ŴRI-^R *i cJZ%F1d7 ӇXiS54P $cY|^O)\OW-3"6Kz2H1$=Kw}E Ms~vDTEDTEC¸ Ϸ?AJDE~,AU|2mx/.!7<3.K+P[^/9Ð}y UAW2w B_(PE M  )Wp"Q|kt+)aܶ`d!PhZi;SxAI5 Y7~F@T6jߊp¿ :xk„}.1xѳ^C. s2m (TJ6a)bшk[jvS.{fS }ǰfheBi2E%tWiC!<\~Ti߂*KUtٶ֭CZZH]q݇4V[h=|g0Hw_Е`J(4oh1Z6o|1b^Ou~Z:~DlRAm,!$k& ERA~g;2ĤY[1[T꿃r%8h!o?O<#oOM =3 .#@*uOZ25Iu|`Hgz\- xf^V KA9lEH"}9ŕi&Y#h0Bz92̽YB&'okK5I8FN{ʗm' AnVTdߕY:6ŎeHIot!6k>{YRO/5I*6KB 1˚|KC`5 I6v{~ xT/J.Üby JIM.i4Z*:[&iƌ!F8et򀨻_?u092>Dv-oÄ[Ш ^c]˿U \;A{gV?(`eLXU$Eqݎj\נ9T3|ag<nMx9T+ }agSie\+Y0"]z Z].B[(ӆ}cZ;g +{5WG ~ e ,^p?637 "_i4cBnO$ٳ-q\J<;DLɩP;B,k] MGK\`m]xL7m7\7t=/Yg u'>KB7ed0ǔ zxR掋]U0$p}d@A哉3GB>Gn:Rzc eQVcfOV}Wgfڞ ^ڸ0qQ$y|5a?~5r>0fbx#:+/pjIߵ&.R=轱5E%ӱſ)C GkfO/ lQbɈc]9Х:Pdswأɥ(N%@fʻ*t0O0\_5>do8߇՛mm=A.~P E8L\/ .}y 9Mըv;ybeTP_DzxPT-8OY֫ܒx-)4 N& ,܍X=adbD KA;Z"qzY~nF^?6g:'mIFPͪN5}[ݒ}X?MHg##(;}[XW6J4Cl6Bԯ"8!1#m(OBkF*W7E~ q"x Raypd~ɄH137b:8G闂9N, tmj͚:^ ^1[?X|8E3/1Łɰsw0qD|UᏄT|f||a68pϏ+Vױ+$2vf4=n=ègmm?\a3>}zP6{uc%.u"JN IS' `8'`}GGcMٙUX$uҕfl]`ei$&~V!D vQsZ'šorl@ t|cɊ-eGrإXq0LL)"_7L`z%8G bcej%/~M퀹H⣈VLjn;D?VīR7O Au0@4 .%F^ݭxҩN*%/񙥱L+xHѤ:бIyNV@r$pWaL;OSR ^M-&yMYT:߂VJ%35p_eDak?_VHD 6ܢy%z? _eǤFbhi%qSp1/8G8fY3C*N,*H.ŵt|8Hk!bpSRbWf;d!4jCpfVjŮqbjhT.KSQ>{b \&'h=nblXpo [MR?HKOmϣOn8$>˓Db&Zsvʍ}9IAJm!vM9Uڇx 1;_B ʥB_a(43\ir+r'rdv)^?Ȫ®٠酚JWZ(0d4z+Y<R,A$S(ΌvL@Tu%gDntk@GM1gV@"yr52xY NO4L9VejuxY^g vg_Z!U.Q*,!0yi~x^o+䧈}<殰 pny(%Bs& H{QUBDaa͓F 7o}*|!%/b R*lY<GP&4!= U#|:ZZx$ãcSS>x4aA|.3 bh5c揔UE) ˫\ qW^ xseF2>s :Y"`'#.t,ߛdkЯc.Nd-g?z>pf/*$ ʫǀ~Yu4Sz`9槉**2&Ԍ' ٩k{_miaŸ [֎BX;e$!]a. ,LtKqEaYKbNS˞`9G~&= D L,;@OO+}pwa+_-!ж([}?w* B0nʰf$\qYD~G't ?v. @O)|=e:={7T7|0M ֚"o K)@g\;;mWE{ ['~QJi:%ȍEx5KҦfyէd_d!X bGIY΄l+jALjlLz)̿HߚΚk͛ÉпbK{}O*tjuo|O+hr Xvzՠ6صCI},q1{9P{([^d:E}u2qF>jJ,k߁l K洳K4EIH + >5k 3{.]T|m_8*bfͿ _Ꭰ0y'0KRLwi- ;&K;, ѝOqH,k&GKUhda[bRHj l $FMF®JjX45aIb+$7&#̇p~5oU햩Gyl3pӧy^qHKHl2TY=-6mmmmmmk 2%ސ}Z5c d|BS97PǞnêL#CKm{gTJG4A|sK<3F*Z9i).z'N80!$'P. sV617/iw[] ̶<vԕ_6 _f)BHo mSR!e0nų'׳Zpɸs}No$Mu"!|@a!#B=abh'nk)j2p$I$6m2q<^}ϥ0?w6KIgD> -,ibU\bYWM"dq87$}8I!}pQ\''!sd!cw ꚇ\MSL=?[Fjh[g%ܻؗa k|,M4#/uB g6鄾+|On=;`埴m69*9;H-E@ r Lf*5jWSLsm V>B0!r{ب9R- <k Dž]N]&(6@!dzҸ6/x1LO!Etmz۶kJp(O4عW7U`#4'5[iq~]9g X/c<[BNjͲlʑܝDo/QwVXlTȑ,SlNbXX*4jĹILUD!aZ)JFտqKȆ=.4t LzPgzэ1[r2˸X;[i?Rl^?rJ\+љby;Qhdxt#2lZ0p{ӛ#Brpo|;J {Г<`SXIt"?S mj>,z4G?, U1:rSNt[cu'hlRx51[LsnRP}rBeC^|%׻RjN[E RUkrsI'j, OFҌ+ {S!0VfyG Ĉ5M絰Glh-1i?n=՚gl1 i TNu$YsNu(ʟ&LD Cj~d[чZckzX% <<(z5A&jwld}J u)yI40 gm|%lpU唇]J(0CLDQGz߄%Ud32 ;9sSؚ.Tx0pUpD$E;潮'2X;S Mqh7θ'o>n mJ4I$bKO:ErP1 Ur\{-@Dz#&(8kO-ފ1E!^ ?>2K^!9WL.Pg,[#tiBl^-5fd(CC5iRNϱ|Uhԓ+ 0Jdd6C彺K]Vuür?{`0/Vp~rgFu %]]H͐ ب/B'erʱl81׊6L9ʜ]8LtshWē4g,^̦3sKvw[*X_Gow;jv1",lɤahtZk< J55^׸sз7s c{M\ֺ&15(h/gͦ=qY"=1OK/  PI TW->N8c+f?nIM,ʑ2~F%uyiӛY-8@t*έ-=5\Y H,ՔH+o?2F7VX(d  |kUX nU`K/՟T) Ѓ,ܲu [&TX m2D/?6|"2jn(d +"*ŘY)&'@y;t.'A19ݷʪZI kp\_K!vZLgSqoÜ-!U4΄4뻗K6D 1ֿF.f>{B ! 5PCH-!|A=s3zBnj9$2wM8SIc~V1ھBOv`Gu396ciM쓴,OE[uuڳ^Xh:m ^MEնB*\\sj 1VKuVF|S<& d/lc)kZs4u ,^ ^QJE+9ͷ$I$I$J >u%=P&Y _QIw. Ծy![ %bcBTDGqK{d=0gju`"*6_mv\a#+I^n>薌kh8L[Qڨx0%2&5 *xJҠ g - 5`G~jbRPnDHbSZ[ԛè+-"Ϗ4(o-,S!,bH`@_~h @`XDR'{y$HPlN|7-4 $%m$ `o*i? e$&GtU,?Jb؍ 3E:׍ k˒Sb'"EŸĒHF_Nfq2n= x;1dP.ɜK $I$I$I$m۞Y  r=f@?-t^g [~uU͊LϲLB30|I#SyBR!ź><6m|̐et^/ے]Ԉl5jվ=ΜRLM,]\/[dyLr Nx5 {}b d{zW)4҅d;Fh} :~I@58,9Q$Tp g65`Tg L V8dʼnb*|gh؊lP>i<<c#G34=Wl}K0!}֒i7?7@qdso-o|}Bd^Η԰lvNU̜E4F=Id%%7qrS-h[j2Cx*C |0~̏,|GhLf1x#xtnb+oi*lzhlf#h ,Vv -:[ >\rvaJBcGtzB Kl"!^>`N (_bjQd7J?9Z%i0myTEz[/1SVyVtsh{7$& G`67_>k Ѝmjz^PϜay4~AR0{S`鹅@}L7$S_r#u,B`JAKZ;&-G?%: %o &W(O@:hN)~Wfqcek ?"7%K;VԼ!HB~׳R b}zjl93=&Az@9.|b=_h2K!{L{&Zl>eWyv;*+Kl1g|)kլ+3(*6gޭhzs9raN1ǫ9vT p)6rF;Vq2慎.DOc7#hIcvE (-[vx C9gBC÷t\ 8'нLT yH"meCg?= J'l¼ډ-g(2lhK7'@kT@.iચ"`Y- dIBMfxbWb'ez]9b)t[o;ńV]{z?XJIy}%ӾQU\dnN )J RɎ_~ i;5\(ǂR; ^H7gackͲPTzuF.ABAձ}eoI{FE"wQdW#_Q̑0RG5I/ea4_FӝjN>߯v1Lr1Y_>6zKZQl@be^Ƴ\P2 p V ~mn MLuH S1cRbğp UDIǧ0yAnz2@9s9s}fUeCB"Z-Z@i8U)TZI+{RyC KyP8fԂ*S1[e@M/.xNL02xoՉ2UߒNIfTߔ[ìqI$I$Uj_|n 4xQuP0N9SzI$ӌ 60Nʸ2unLwM'mvVKSH.[΀qkf` ORW"\I$I+#mLU4;ĕϝܙI4hάJ*eO4{J-A˷r8KE)p5Na8`"1hD^'_Nגk)Sow=3=3KiilFjb7.$a%&BUG /@0 (^< [Cr7jC馍6m,ڗDJ{) PW)-4Or r_L_҂闛+!EA"y vK^DŽntu}ޣ8^%e:kx60ؿqbѣXn v' [Bf!Bumv䋄ǽ}Ղ_[bGnXþZ/ 4I4E3sK* kq M/#;C@ةš/p6HЃ?\\]7'͌vam9;:ö#U>~'#R`I.V@[Lr"T5?[Ɏ@ks{Upaʇ0!!9WNK-}bU}tSrI=gѡ,DњwD9JLsk[[JUJWۅD8IZ9T|xhS} .ae`O US4ACKsfR9%hȚZ!"1rP {f c'|WUg"W#J0n<+hEKKTD>I~awU|2!IF@a ,9./aC| Rա9ԝ\=,ipy̳e''bt$x`kzGD\0~VkI0DwJۤ+V =KPj\DLW/c< $U8_[aP;F$+lG f0>Ѭ ~;/ԹP*o_-MhF8 G$%v߫jnM|''hI#eKka3*$&釹ú-uw3fSttM iDZ@0q~ # +WTؿCD4QVq()ocaf@Ne7Uw3Ǚk9$m(Aa> @:ZW5Iܑ Q~x!?OxUY[j T<*ˍ2ʡ?]h8Bh3s^a!fʔmBasK߰;`RXp ī*g6qY 5JB3um)UUUUSy1t7eZI$I$I$I$I$I$  K,`^|#k|* :RaZoLGSjTNbsMHAgכC!6oYUsh Eyԇыcjy;u0{y\D>Yw>R_94Rxuދ$@ DR{שYn~W$(*Lsl!P?s P|Xf/}4j^HӘ'ٲ##!oqW E A&1h`&O I(@69[(Ae8JM.b*P5<"ī3hͳ}ܿ^(fTϿگN!FXP?^c:; _hJқ|} P4`2Eë,7tvx8_Z Tõ+.1H*.zh1B4./StRX9.B:ͦ%g}tB6N\t{molΗgzBIAގE&f0{Gw:7S}Tz 3D揼n{ 8MH>:,]>YSjjmSVU=Jlih[ƀhƎzGBe*B}Ln#W5+Ĕvear@nWHOa><-&y,Z0QqBoI˃7:˦!NUUctlPqwc'9,ÐD_%HuqGدhMyh}mBF۱y㷔Z `;N9n O6 KEvƒ৵v5l{J&iT 3P6^ V[34ƻ$5/gږ Ջ&!"&|ځ2jU\5׫ot v A]X@bjDRT0/ؾLPCauQG+WDW}f\D*'nzN?$%UN_(jBGI|<GJK fw_]2b^vS|K,S*_ZN )/hoHjݲ;;2)>](kYV\mLgT#F;Im18:G@T-2=iXBS堶YՇ0 SOowct_#-?x^n,ゥsfJ;8𣱆4k#֧Gu+/ټԛ7YWgczvcM`_TL?L2T6-2YL!Ka,ǥ[SnnNB+vZz;"`kʋ ۬(L2ƪ(7CU}&#( `;S@1 Rϟ'&r,MY <0Fo-*5&>麎ң% K[ڳG~h ;v=؛iGNdC~xT_[qƲ-$ hSu/Ro 'Ӽ>\c7<( %ĥQgRt*:3ANcicKZtRгfM09}ïI CQr5Tp;]@G:@:oIa,L-bhtL*xcIS z1bP< y5{ ;ڨ_iR(߼ ז-(Y^_^I~eyXK@SI@4q6g@]9$׌6ʘL9}nW8̮Gr-D}rFuxXDC?nFgv؊N@yȌؖ6BF}5GR,ɦЄ+/n5:J#R%wwWM:/. UǶ8|JFǖOl,:Ƽ6ZaK/ܹKo[a( OLIN2p?1>J_JsyoO[fuDּѣ[ǟv}[ߑ կMLjr*UU񵎷-\brU%7a@T7iTE='MH|Acϓc/+a³¨ԇ̘j: B<0P.8X #4 &O`NQkz Ỷ%FAG,Nx7gjJAL4@ YuVʉ6iaK/KqPu/CZn@=ʠO`./)B=a[nrqW72ޞЙv ; mv\E:蘫Lezt1Al떜-1%vx"vYSzjp s%J Fsὐ⭅Ky5$?%1myQ r6{ڛ@{F%B"`V77DzIK{rN,Ha 4)RqD$WC2Q!m ڍfwS͝BC'}']rU^oBC-b PW(1G]$+7Zv:TRXV{hKdQ +<$!Ѹ.Ka6 * BSEޙ>NHxԇMnW|ߒx*y QBDj=ȐW "c' #n+i%C54V&!-\V\'jKl6R~]ǥ:oٹuns\̴|e_g߂YQ\ZXҝ93MZ}-Z,!=ټY.7xow 9:3iO)m@\ᯀŜ.9|~<8⅓omA2됃-GqZE'8ZhI8{E_ +o2f ^k LI18B)|*@Cmqt)z9:^y~º.X,Zǁpbԯ7trŬw!tsa0wA݇/qxӵD^vX\^T$JB= CNV4X=im1_3<䟺@'AW6SYZLa.FnPJ[# Uҫ 1RPM*vheuҽ߁'bD= }͹&lYRը=^ K/ b7J'=kk.5XVSRAZ1}"LEl`o*}#][.M#Q1:8ZF@l؄sAq-D-X&HTqe蟗|Nz-m,=gs!g@vQt_ ߏxM=Z\=7rIyc%KɣG^Z#sD]}3Z#bA-9 ѯoh0=ޛJ=DG*BGM81nc1rj+oeFͤCreab^2D &^h2U y^s! D[2^~X>^Y*dctWɸҁ!"I#eY)hMIdR,upȹ~d|' NyfQx)WmBbʉ#EXvlPȔ_WR4_#T.Ç7Bo Jz͘izߖ|˝IO >3yO)_JS#NJQuQ$f|(;NPؒ7eNS!yˬ%b*!g&7#;_8lEDlwBtwbHy} E=$O_Md veTe  \"CC|2 R]]Jj> y+]NɭY'-~_\0"^q,'=H:IXCDJؔ Q/,/FxO ~$5D~ <}>bHalQB:^ֽ_2 }v-P !?Zo*!?uI7"pR3:6=Mt8?JxJP銲',4286ӯRo1hs +U@zv\`OwZL,YojŠ!ځ*GZ޻].kw,Aioϓ ,^o26q,p=4v_JN8$y]lh;4DiFUxS/~g|:TCPjՋFb_ju֩ TRC^`/Д0Љd{%?b9mJ 6Zu[-иf;aA3C~:!$0҅qV)LG%ϼЃVгFxfWgW;,3/rM(R96WĽ6@ʧvj*<.;&}&^B\3Y1)wum͟-5uI{#u}H%{Scg#\{;B*nz6&)K&lЯn}!pB}D+Up,t6yz$:$ THNQީ.$e$xd ׸LNP'Rm*t9@Ou-Gr`^Ie>xt@帹EGR)o7Z%a.!2K 0gˏKgwyO&$6D୯2]I;f@v`F?A,EAA *ўt3 OTy6'،}1`_zÂanrԷ"z5Nicݝ[_U@O@]#paA#RDE\VYz29IWHU"C\Ŏ ><ގ5F=p!y%x*Bߨ^ewT_kS/.NsχUXМSkH]B봳U#rRҟBX6k^<)Z7wٮF/ǚgg1PcAxy(AWBn)B>@E )0 ??O#!fWϪ_oZ$>HZ5|[>~Co^KCvUoG8۷_7ɶt{t w#|l髄tZ6¢W#]z<\72^5 \kOJ`χb856 WX?ø|!6awXw%^#e}",ʉAZYƔ;;+qp-$fdrd{2Ѐr>$e<س@-C3J}0ARNxRsԍ1ײN*lHe2kd2THڳnE2n>JWy9n ^rU Z\'%SldE߼!mLCA܊ՃnbŠ[~㺤9FQ*9*Eq]|[]x|\ׇ;$Kp;-*,)0[<ɤHjjNAwmZ L}>rNDR f:fU#L[<xmN^oFsbj+fM"Hr+ymiӮ&-@,5vffLG|\p;gv¡JzQZ3_r:b?, *[@(X Y0m\TBI?Ts JȫcCE?D1];?pb&l\:u/X4y]ՃCf/QH:+꯰_PD_A'^QG7?<=2ajq\Qk"Y3uJŨdn"V F Vzyp -W\A&UHZbŢ5mpu0!EMg5l_`ٔo[p{?k&|` K>1it[HÐ'%3$+͚1<ļF*q'dûxT>)We Ǽ0$ӆl ta_&N-{BI*#?nvN%e\y{ZJƭ׬M~dQĬNR.1(J*#XӘQXۍfbV@V8`t]77#ڋ3>ȔH&cw `]:"#YjbWldfOPĭ-ꂎSmJ>Z p61O 443VE%XڴC 2Ǽd,~闀4kMY'fovtWo:#>9QF" "(Zm[a@đ, iד|UXYy{-O_Ώ,JH3:mi@s',rDvq[S/QtL g}[]'.,1.(^Z#F] )UY8LN_[p@1cmSh\c\6H¾)n9T' ?ǒsǼNf4=gT\T\Tj=]7ь}ߕc3;0nu| NZC|9ĉPE:#hiۦdWK{/l ?V#M9ht0|PryShcU)*ebNQZKZ-ov`1+M/( +#M9%LMO?(ϩ0J@tɓ+) .X>&f .@w$/3oDg][&qu ѫ\[1A2&h&26G3f5>$sS5Xam'3]GUjZ N0@+Q13ANa8"ZR"L ޹;1U$+0,c)X"$KX{֚lؘIˏd.QPr(}Xj ʉ=u"ğ|(IP$(T9C,c"ع0 %9\4LppɈg'vb-݀ڸD|2kj]6P.B>ņGOʼnK**`Q hQCqi0WY 8mMR?kDwKUտPǠrR_QOj ِx ̟jAz>:mȑ_3 E*utC;I]8|{c3+Pird,m~ [#Jc%_`,Qp:!RaTF4@6GR93xYA] f컦bQN)l\J!uz~ѡ`4Uk!HH+Ջ FfcL,K7=;*`W,APE&R˜7m`.m-Aj{ۄCܚ,LCDύƈC=PLg;ܬԾAFHLT!"EP>>T@}P`7;@i!3!k;@׋Jç dЦĬTB-i3ϒCQ=q(dM<npUڊCDDl){A=M_*Dx RRZW F[ /=zMl0'l#;j$ aҊ5uYNFMNNP$? ڿAoy1PUj|}x(POT\Z{,X7MG3q33l$fFCBiQY2,|a7[9NKК%{4ض @Z1P[;at m&(zTm8Fud*km$I$=2x$m׵=uwfFǝmRc 7&mm)7݁Nw>ys6gFc0~:lꨚ:4͍ /}~V6(F3W6 )ԯHJ$d__݋=inme!yV R4C3ۉ%L1b(KM]^+6nu$-nH8K$# n8# iK߃-ט>E0JM̨cjw& Q#q>'3.Jm}gB_p ]ɛEaLko(6I$j"UuR! 8@l-k tkCs8m$I$l샏ד4a p'| ^9qȡ# ifOv(VȼO=ƃq7 ~[\اҬKI% ѯd*34cMp!̝֤t`R i10r 6~V| O!)\Ѓspv\A`uu xL놏r`&8 Z3o*uy~M˚ 9 j8/. GgrnSwؠ5V҆>zKhmQ̻Sq> ~{h+¡[y?ZW$f9/bθr"{X@H ՙp-$`Y1H]'by\=O4&!I2iqs*gYFt:>&YrRj6G%~/&E'ɻ-@77zE} 7|W4 a])&!}`δd\C[UȨS> V/p@)F'wD哀rbAV0 Rā2+ i7eZD=߲p$ L(iJ?Z2E~n2.C3Mo/MDl=[9(@jtZ;Pg2s(/[~DezUT:űpx JoO*.ťm(ە[_U#Ato*.(TkfxAƱvZ0 -Bu$ZiSubj-"ُiYF^ex`_H_pWm'ShtsVY$۳o↠ 2z㣏^'p8Wj&T-U_\.iB\<~|220X!pW_I'6<whU2Fr+c.?09S_/,fWAB'^&WX2m@mr FJGj"42n5Q֝kb!ޥe\Zcq+Eƒ1{ۙρkpG4bL$k_R;~ߞ%vih#$VE<IAb ,;b0zM&{N0nPFl{Wbhv ]|㶓k% w b\gQ,c|:^{Ry-=,a [Jw<zHpZpL_m]Eem(^@JXzȡmiGVj}04𙝙os/2@'Fs'e4|tmVI]'|kXA^|%]"iDfT@No#s@;}g/j>~KWmeN &~5yKϐT)-G}XlRX)qQWRwwۛ_Ր qi ce=OO;Gv v.֯4xB*²b\B*.,8?]E̯QX]`Uٝ5G<4f3PⱝzˆB ޹d^S9=*IB HTיT4OdYkVt@Jyq(R&;z%l,(CpyC"A{ȋ")mG!*KaP70AbGx{Vh<"J,66EQ%t0b0Z7 %:i'Z(xz hQ3P)S˥w swl*k,-rV֭f˓ wCvoB6 ZNATHl7QbyG x>+E 0loI`@oي\zm е9I׻G/~c>WOo]2~WoWw9V|[}[Y7\;iۢ0}[?o8uuj_Nu'Z&}|>χqdTO!`Zg@ ZD]V+:X}c1 ^ /9_C{Q&jit4O2CI8+t 9:aNK[煮3>R\KWP5:S _G?C)Ơ\?lq Zx9a+U2o>{BW@Tю-TôV'5#Z[r-ui Hfٻ(6r阵YPRWhjcWΤֱ(lx0?%AzFɿހfs&6w+`Gl"n}=s>I?%?keIU@{r!ZBAҩ]8pE6iXtG\XEUGI++ֶ:OZKR-s\E܁RḷRE;{bRl)bB0E9TəHz %uw%h ڞS+o\SCOM2AP4-2Dׁ}G8(q4֋,n*Nzߦ/_EYr8jo5tK6pt+r9wyS%7E`21>3b"]KB2U9'"(_gejA;;0ͼ(bK{s ;ÕEVq5s.FH8Z Gl4_ Jmb۵3dT[ uOzWTēOѹAOۥ#0Y me%g _l[ "Hr+ymiӮ&-@,FRf(D&[Y~xn>os&/J?}Y TZgKtrXԗ~W< xr gFA/LǗZ(mX]aB i]j=Կ,XpUX!_.'tp%'V;2 SzZ96Y43܃jDODA;Z.׻+:CȁZbf]Q=qWA5*zbە'2&rLw~7gCxZE˓^.t“ xp&+]$GJrվGMM~)S̞S9LglշL+yF I2~VZcXKm.k;x#>l247X[Pafd:iwJ?SvY $KTjhl@}bOe2t.3y~kg,fp9ኴۺA@:G{}Q4Ia¶d%囵w +2o:*RzW{"9БjW\|n!P4^#:Cꌲ>!SW m)hz+9y>T eSLޗ Frc ExZ)]|^u6xNM6 VQ_A؞5ib0?P7hn8ug] !]$흤 dnp= C7z\2/mҘ;8B4m)7E8kUUvrʧk uyh9J~fT[^g^"Gbϕ\8㘅6BnKyԾZ/#%M6) 4[b ^z|oHWl'Ÿ)U񸦰4 nlv ~A'o(6@JM[em\NP{TH8\Тvkf#|=H7iDa&Nw#!6O(0ئ_GT>>c=cH _ZJ{q"|+fKܰdb9u=<7ސ)aԜ|a@ZeˣCHߍFJ__dvscrh`) ȡL#XfWqK?:j+BnU!7pqdGK{{. ڷ Da5P#Uڍ) /Դ!VE HcO2RV;Gc:S&90 .\):H5MA*fLr~@l4. wz5L}'߼.۷B)O۫ջbvg3!©`\cb-h;b/G'tCH. ܵ,Jku`*{ vɤ /7=4ݞ=MeG|AyCreɾPmöw,{PIg>o+x}W R?!9w!e, ,Zl@{1 {{V-f ƕ/ysfDvY O6'* OV[jDW3;g3X$uB4P8 Ѯi֙.S.De oĭ8{M9ж><b8Ծ' S?)қ$'ЇG`Rb'CK|f,ևE=8@u?kij{TpGi A!kBzgcm]F53XKN0x(Ei d!@,YPղŅ .ANVڄt4ւaBN<% =GMns=u! K7oo{W'_ݮs~ Q>/.{pk>&j6FeUV 2uE_[JO.E(ea(ZP|滑&-X;d޸mkb=Ƨbi@S`IW|'<6ȗ+1jx: tl9jɉ{lԥZ1l^=>gBPj6l`+c_I|]O$s%&[ﵺ2]R)AMŒ,>W~v\FI]':EL1X^lr 6/_ EmjfiFZ_S}QmAj齻UT49;O# o*VH g&bx]R3QdXyE Ѽ=PmLS#*(;5nk ܟWa2cDYq9Xj׆҅Jf彸:ͱ~ۖLHCSj~- 4S]Y {t)r+n\hYmEM#oHkq~u?ĭ%˓w>DYAJo "<;׍!Lj2o$Yl[cXP&\^x5"s cT(-a'#`5rK8@c}Eq!`T6,XݦiyFFo/0H+PiҜ)|==`xFМCxx}pD$}!/]oD@0 | ozHH'} ?Yٳ92g)aM'O줁%MbyGq.[rG, ΅p)e[r0*X]7 o,|-5EUL܋` B)26^_8Zz  [կ/kmKm#Sx!pHYO]V{'[ߏn|4|DKEˀ)0kMa,r3}ԱZ{`>RNs֪43;ʹ66)V5`R"11ք:~L n-rVLN|H)= LNkUڱٹCaT4"3:/h"R 3G(W` ̊=(I(<OUS i~Cd^Nb^#%yѡ6c#'%ȁ{^6@]J"^ j#Tx>6zvc&/ɝϐ;}A">`|H.FٺC/gWn8v7Ri$T-p&`{I $*#DßG9n^g UW?i.2T^1|gH7FJAf;_$d،$lVb1r90'NꍱZwoABB%! F|` RuH)N5'wAU},X}b(Gn ܋'e޿- s}8VӶAHf'h9|($F%en0k>-y $HGi^6G ==i ~c*Ѱ ۷P$3Wț×`@~WKjr#T[@|JUgw^|.# Su$dGZVw;,0]E{Cҍ-cC(Vw-k[c}p ނn1v1{52qE2Ի}̨m`mV95Mp8؅']ᗦ/%ekHKZG5ׯh^pz|P+^0x>|]~Zc|t%}gWmpww/ AB5NzZ1x'}$ӆY+(hYz?*T8NdsO}f\F$='9nQsu $#" X5Y0 {uSƘL}z`lHM)q/fcq=5^w.DmD#GdMe4,ѴZ z@YĔ%Sn+[zI_QYyᴜbxANe>dZ|a7.kB s67<9 _Oj"}-fgXi cDJɊ70xH'P'rэ n +$1U aba!  uoYYF3@Hm$I$V$(ۛ1 - !o$@ժ [#6qNaDtmmj`*#Aƪ=F{ߋ@C9`xܔ%/ ꪯCKWA,QU*U$-bcSixzl0F^3$?z,kTǡXdx_$}|DRfXw dXJM4ҰwrkF:nQbA(`YKUV= 2<#s+{z=93ཬЏ聁n8өB.`gY9EsS"6BplkQX.ii ;~=:i9icF,'^o", dEj,\QʶP*'@(AR0ڶSi bw묩N`S@Aڦ1/Pn4p|\]]Z]a8O[ i$Y»QFwm¢Ҝn<{\|cq SiF؜n jqG4ڙaH'/iH-[=yv(u9z987yG%9t|AA%7{]إ^1%A-g羚5աAŎșXXҕTNۜ{3_Wj e<}Ufڻ`ܐ5":HPZF쟬Y[(`| ˠg WEOR;C>tL,m,W70ᓪ6oKfN.7+m2WŐfգ Z[(uk+TFy[3EQ-T&們uwa&2֭P}jBx5ZhWdlWb+dS+1 ɥt d?qyL,n5 b ;z6sW"OcJ[FP8KoPzr>ȧyHƱ (ߤe.f萾GsY }SmIr!pYYచz&&}nȹɒ>!fth? =/(`bV?.mM" jiS%"c90't,brA@a;(Vv 6xg?BYըv]HDO **/(IkV \Ysd^»~ϻP0 >n-hS!_CMy/9NI@%Mp bn[rmf6E>٤ήYunhB}RYxKDEQv[̽da'<3^(N+w_TW!GL<ED&gq"LawroSۥ=-v5n#N;6&1UBb-vGwvu^.Za|*J<&  UsitXq%uM|ɔ:bQڰxY~?h#rXuQc0܁lrg;;d2&,iԯP@536A;EW6 Q7ٛuITM tAlBr XV] %X)LATl-n;]:JHLOH;Rw6ܝ)o"TԹ+!v9w!i- CtL޶uX}MĎR A͕xHU5|/_m. c= <5%X /|cŷhijounz/|Xլs6.iOpT4,kC)X(` ki"7hsyrWJ3zhv֭VjS@ Ă)Ϊ=9B%>H 7pς3kɉ%es# H辰Tw*KO<^ ;Kjq-Q(xp${RpmKng2D$sua%ϯ꣑}dj"="@VC'<:O!=xΤ2_PVwc@f㪔U_GI&D(#:Decv yZ *m;/qPYj!bF30%΄4I%O&gޫWf߭" wfvItj_>YPM`-@jN-+P{,&l:KQ =3Wu7:`L)GpH(#T׿z#,=ޏ7-Ɗ±^^EMR.tζ = 67n 13߶]`V? Ei10Szy#4 ] 25ZP+I:@F+Ek$O' OT"t Pf*%-SB8刖+)Kq24L_܂d'*w&}k^8˼Xk pvL0j ߎmS2tn/M9w#v~>m?X"+5p, __4-H'sGy [jS]$B\xnMR^I u8(rSp8cMN %KG ~$մ,nFSn-L-KFO#ȭy GA%qrKI~GS;D(KxEEK(DF}];=Vf7 MXr[_hWAx5 G3?F> Ɠ"MPٚ.8Ayl(L w[Sg,-gᐞPY%Hg. ~r:ܿ٣o=81IFE!M'ٴS!09om6@< ͹NKm%آnR3]Rͨ}rR">%OETsᓋ-oa@8.X؎aT+D构zS X!M#ү ݢzEo ,rMYtFBEf4,1DyT<Ӱ]4h k +88V_%Y48&?YȈ )F&xShMN0wj#\n zSє|F jAaϋP؇up&k@>A·il&?'oF@0<b_H H?~@sII(l` @"9oL xd4+l:{1X̉JFa|׊*0Q8q~uX Q%{5D~ ?EUgn7gPpf2KQmH84R4s̷r!cWt^2} >8-E."U9HV|к:bbO\9A m~EkŒ`-âbSlQ bbeU 1!?F_U\#/b;h 3uIMirZ9 L 9LRV$JiSxi.,a4zRly>׼8T{9fgtaVq)[3$n}`62CN`e"o %.`9If5 EweTalACY޾w!:R%Pnڱr}hy(" rHB_sM08?ۆHGitzN@' L;ffZMua 'G8׏2.WD!2 ęU>2i^0Y6jM|Jx~k 2;u:6sq چ jϤQ^'S<)yoIR߷h" e8J^(Doբɑa<ܦBͲ=xl\ǨϾ9;WʰT@Zl7~Fr1d3O^%3!2xʇBOF V&K4|hy =P0v̗erTc-PYnQbn&w/ -`*xle3D!eA^7?40DB:_ջ?U aU [>l [?nOST*SuNǎ]nRB%T%4i>y(` ?CU\HĚpcG^ݕB\ үХԐOtt,/ p |Ro'LnX='j8BnB&G >.^hzz2p"ү"ΓW\`ЋkR(@S1]>_E!H:Og5pA_?TC^Cn2q5TvtGH:~$Rs=h@GQ=wYEeZ!!HxU{qٓ"]fdVR[WͲ@ـ~r/ Ur$1eVS%45W5~,_4F;AG\{kB~AϙXHL&AI+k X xOe݂5ClQ*\cz>cz>cz>cz>a>H1*" B66Y|$pe߹] Jޠ(Q俜_T$72ylԠ߁lwR4!j/%>%uhѵ)=\MhAul}de/ h0rwM4[}ϙ0ȫ ]1dQO-5tY T6pn\VĢ(7{ٜҸנ8 'U4B/aٷ!גT5wUR턍N]^<dR4})G6p39QU\6K$=s9Dt?q_K/CvDK?H1ʙH[?Sy1[tix4մmD&V hB{w.氪uDП 3tCEnNv1tǗHfA02b1CY{riC n kLnDֆӻ]7 ӽqI#DZV`ۼ7`t?|QNjw^+t_ Am֕[wYtIx׶<|3#oCxUGE=B:AM%`#=^+R cȒO\lQq2B6K0uNbj@J.!yEqRY}~7 #Z8 t~%+Oe16'D55:Ǟ$QXswWȾ*qMmmmmmݬU@ /㖘FeMgZArY㰨@;N$(6I$I$I$I$I$IcD~(9_}8&mmmmmn* "㖘C<uF(qh'λ``i[sEݳ˱ 'ZIK g%+&GO5 HFlfLL/:ߊu۱V^y &6$-rJӼb&S;Z#+d.;=j&ެSwa+v"S=gh{f ob==RFy?Na7pEǜ5⃳~` 3^81)0mMp&^DZ]9ϣ\I,V4lֲiE8,ax;9<44ro8!wp_N=S $#z%W̤ J0/z~NdŁGɿ[Wu3,rr"L_!ϗu>Wh]sdà  ;lՆ愑 xXq& |I[upZc5UA <~6 K5 5],%S(wX6#\ <3uj.4QKuq+=Huge+ym&)W/Ϧ>B{5 gQWjZu7pVj9gx^{h2] E> '|7;.O=E>'!*@I@ 0*pL B$.Hb׆j} 2Z8[iaqrՒ.]ԲKr [_g 2: h,_c `~0tndK]uqAF m8*nbzGce!8+%9]`u6!^[>PFn}*1v%kPKìXR4iI CئTZ,ٻL#s & mÙ}FGh׫^70U$#FRIy]ofRit jf8;&mmmmm%mmmmmmmےIdzt׫^70U$#FRIy]ofRit jf8;&mmmmm%mmmmmmmےIdztdyl}a\8gWku8uثdnFd͹( -Vr !Ka7$~{4iC=r`a19=EnFvS+H{6:U *@?&0hP3 MOžkۯz>U-BYT<͡w¼W#ㅟwd~;&m+ژ|yܺX8Ge9tMKvk8q*j-Oxc1NDy?&`^VH.ĈoLSj6.~l+}%$Z< d-U}E~OR&fG]ZQx;k"qG8h_<|-a$WԶn2ߐˌn<,($ 08H˺x̱=7V;wV/wCa"Z(7ԌN ;#$mX9}mN>>222222222222222222222222222222222222>>>000888>>>>>>???===[H;fK7fK7RA4<<<000LLnn//VJJJQQQeeefff@@@`K;aH6C1$3(;;;88C݊ooocc666OOOPPPKKKFFF_L=`J;7-';;;000ss??x@@@PPPaaa]]]LLLdM8+ ;;;888%%%$$($$(003336336336336<9:@<;655333<<<;;;+++**.**/226559559559448448559558666>>>000""$666;;;;;;===:::dMeM>>22211211266799:99:99:88988899:99::::>>>(0` 333++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++333+++ """!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!""" +++ "/8>@AAAAAAAAAAAAAAAAAAAAAAAAAA@>8/"  41:ZMl MvAoDq Scs(7FSc\C-xX Kw f2FXeP=({cQRSVYX[v 9?Z4  <`z mG12=K Xdo'y3?KG3w!_E7{M#a3wCN?.t`My?yAyCyP4;}< 4VqDwtsqomkjhfdba_][YXVTRPNKHDA>;852.-TzPH4 ",7Z| Jzywuusqomljhfdca_][ZXVTSPMJGC@=:73/+(dd-FI\" """/Hgw}|}}||zxvtsqpnmkigedba_]\YVSQNIF?83/0aO/"""3338T{ \~|{yxwuspnkg_QC83/K]8333333$$$> XM00b88Z88\88]88]88\88\88\88\88[88[88[88[88[88Z88Z88Z88Z88Z88Y88Y88Y88Y88Y88X88X88X88W88V88S00SR@82?b>$$$333+++###@ VL99R99MaG;6=e@!!!++++++!!!A T}K99T(((555555555555555555555555555***110891891891891891891892444###99OjL>9B+}}avBPBPBP;H&&&99QuVHC8`A!!!++++++!!!A Q{H99U;;d99n""",,,iiiSSSiiiYYYaaa[[[000CI)p&&&99QxZKF7^A!!!++++++!!!A OzG99U)),mm|||wwwOO88B,,,:::999::::::999::::::999:::000CH+h~&&&99Qy\OJ7]A!!!++++++!!!A NxF99U**.wwwsssbb88E,,,<<99V'''333333333333333333333333333***///333333333333333333333333###99Rnc_)rNA!!!++++++!!!A An>99W,,,:::::::::::::::::::::::::::000CI)&&&99Spea(qMA!!!++++++!!!A Am<99W))+,,/,,,FFFLLL:::DDDNNN;;;BBBOOO<<<000CI)&&&99Srgc'pKA!!!++++++!!!A @k<99W&&+;;eOOLL==k..7,,,SSS~~~YYYwwwZZZ///=A+xx_sBPBPBP;H&&&99Stie&nIA!!!++++++!!!A >j;99W;;b~~99m!!!,,,kkkTTTkkkZZZbbbYYY000CI)p&&&99Sukg$mIA!!!++++++!!!A =j999W))+jj}}}xxxNN77A,,,:::999::::::999::::::999:::000CH*k&&&99Svmi$lGA!!!++++++!!!A >{%%',,,aaaPPP<<A!!!++++++###@6d499Y,,,:::::::::::::::::::::::::::0000?0 ***&&&99Txtd=@!!!+++333$$$>5d399X&&&&&&&&&&&&&&&&&&&&&&&&&&& ########################99Ryvc<>$$$33333383^;::c99Y99Y99Y99Y99Y99X99X99X99X99W99W99W99W99W99W99W99V99V99V99V99V99V99V99V99U99U99U99T99S::Y{xq98333"""/ -NJ}{&2w/""" " .ZJ1~;%";D\" 4 6V`:6t _w4 =A_ o}m QG:.4AN Zfq)|5AMC1tZ A;Q&f7{FK;+p] I=>JafLn=  40;]Zxwo_ O{@mEr Ses(8FUcYC,wX Mx!h3GYcP<({aQRQ| Ik,:]4  "/8>@AAAAAAAAAAAAAAAAAAAAAAAAAA@>8/" +++ """!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!""" +++333++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++333( 333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333+++$$$$$$                                                                              $$$$$$+++333+++            +++333333$$$     $$$333+++ """"#%'()))**********************************************************************)))('%#"""" +++333$$$   $).1479:;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;:9741.)$   $$$333333  !'/5;@EILNOPQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRQPONLIE@;5/'! 333+++ &/7?HOV[`e#k!m!n#o#o $o $o!%p!%p"&p"&p#'p$'p$(p%(p%(p%)p&)p&)p')p')p(*p(*p)*p )*p )*p!*+p!*+p"++p"++p!)*p ()p')p&(p%'p$'p#&p"%p!%p $p#p $p!$p"%p"&p#&p$'p%'p&(p'(p ()p!)*p!**p"++p"++p!**p!)*p ()p')p&(p&(p%'p$'p#&p"&p"%p!%p $p $p $p $p %p %p %o %o %o!%o#n#m %ke`[VOH?7/& +++333 "+5?JT!%aIb^ `^[SLELT[d k r { '-5@BCE H"I$L&M'N$I D@<6~2z-v (s#okhi k$m (o,q0t4v8x=<;:98654320/.-,*$N#5>ISU\J9+ $$$ &4EXd Kyvvuttsrrqpponmmlkkjjihhgffeddcbaa`__^]]\[[ZYYXWWVUUTSSRQQPONMLJIHGFDCBA@>=<;:98654321/.-,+.\>HS\NXF5& $$$!/?R9I|"xxwvvuttsrrqpponnmlkkjjihhgffeddcbba`__^]]\[[ZYYXXWVVUTSSRQQPONMLJIHGFDCBA@?=<;:98654321/.-,+)*P@Q\e7_bR?/!+++ '8J_s!zyxxwvvuttsrrqpponnmllkjjihhgffeddcbba``_^^]\[[ZYYXXWVVUTTSRQQPONMLJIHGFECBA@?=<;:98654321/.-,+*)NPZff""aJ8( +++   /@TX{ N{zzyxyxwwvuutssrqqpoonmmlkkjiihggfeedccbaa`__^]]\[ZZYYXWWVUUTSSRQPONMKJIHGFECBAA@>=<;9765421/.-,+*,lZdo\T@/  333 %5H $a t~t~|{z{zyyxxxwvwvuutssrqqpoonmmlkkjiihggfeedccbaa`__^]]\[[ZYYXWWVUUTSRQPPNMLKJIHFEDCBA>=<:976431/.-,+0Mdmv ()bH5% 333+++ *;OC^ v|$}|||{{{z{zzzzyyxxxwvvuttsrrqpponnmllkjjihhgffeddcbba```__^]]\[[ZYYXWVUTSRPONMLKIHGGFDB@>=:865320.-,+7[dmxHO;* +++$$$ .@V[ u{ s~}~}|}}}}~~~~~~}}|{{zyxxwvvuuutssrqqpoonmmlkkjiihhhgffeddcbba``_^^]\[ZZYXVUTSRQONMLKHGCA><965310.-,,XmvaV@. $$$$$$ "1E[ d u y M~~~~~}||{zzyyyxwwvuutssrrrqpponnmllkkkjiihggfeedcba`^]\\ZXWVTRNKGC@<:75310/-,:kvn[E1" $$$ """#4I` h s y:~~}|||{zzyxxxwwvuutttsrrqpponmlkkihgfeb_]YUPJEA<974210/.+akus`I4#"""  %7Le l r y.}||{zzywvtrokf`YSKE@<974210/"MqkuyeL7% 333'8M#l k r x(  ~ { x u o h aYSJD>;863210Diiuz )*lM8'333333(:O $n k q x'}MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM55TZQIB=975321Cjisz!*+nO:(333333 );P $n j q v'MMMFFF???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????AAAMMM55WbVME@;86542Cjgs|!*+nP;) 333333 );Q $o j q v'MMM555$$$MMM55Zh[PGB=;7654Clgq|!*+oQ;) 333333 *<Q $o j o v'MMM555$$$MMM55\n`SJD?<9765Clgqz!*+oQ<* 333333 *<R $p h o u'MMM555$$$MMM55^scVLE@=:986Cmfqz!**pR<* 333333 *<R $p h n u'MMM555GGGCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCEEE+++777AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFF $$$MMM55_vfYOFB>;:98Bmfoz!*+pR<* 333333 *<R $p g n s'MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;:::@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3@C3=?4666888DDD!!!$$$MMM55`yhZPID?<;:9Bndox!*+pR<* 333333 *<R $p g n s&MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMM55a{j[RJDA=<;:Bodmx"*+pR<* 333333 *<R $p g m s&MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMM55a|l^SKEA?><;Aodmv"*+pR<* 333333 *<R $p e m r&MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMM55b}m_TMFB@?>=Apbmv"*+pR<* 333333 *<R $p e l r&MMM555DDD::::::999;;;999666::::::::::::999;;;999555999:::::::::999;;;;;;555888:::>>>000;;;=>6DDD!!!$$$MMM55b~m`UNHCA@?>Aqbkv"*+pR<* 333333 *<R $p e l q&MMM555 111CCC???,,,DDD:::BBBzzz{{{kkkNNN555::::::???mmmoooXXX666999:::;;;\\\sss```;;;888>>>000;;;=>6DDD!!!$$$MMM55bo`VOIEBA@?Ar`ku"*+pR<* 333333 *<R $p d l q&MMM555000^^cmmmffmSStYYsmmqqqrYY]$$$DDDBBB{{{kkkMMM555:::yyyooo[[[555999[[[sssccc666>>>000;;;=>6DDD!!!$$$MMM55cpbWPJFDBA@Ar`iu"++pR<* 333333 *<R #p d j q&MMM555IILeeh66}##(({<>>DDDVVV|||lll888FFFppp>>>:::tttIII;;;000;;;998+5+5+5+5+5+5+5"          DDD!!!$$$MMM55cqcYRKGEDCA@s`iu"++pR<* 333333 *<R #pb j p&MMM555WW[PPl ^^ww}oovGGM%%j++jjsJJKDDD]]]sss}}}<<6DDD!!!$$$MMM55cqdZSMIFEDC@t^is"++pR<* 333333 *<R #pb i p%MMM555??@TTg&&ffl;;W qqs---DDDLLL~~~999>>>ddd>>>999|||fffBBB>>>000;;;=>6DDD!!!$$$MMM55cre[SNJHFED?t^gs"++pR<* 333333 *<R#pb i n%MMM555'''^^a uuy,,e??eeiDDD999bbbEEE::::::QQQmmmTTT888:::HHHqqq;;;>>>000;;;=>6DDD!!!$$$MMM55ctf\TOKIHFE?u\gq"++pR<* 333333 *<R#pa i n%MMM555FFH==raaKKQ}eeq888DDD:::999PPPfff___EEE999:::::::::IIIbbbaaaKKK999:::::::::BBB^^^fffSSS<<<:::>>>000;;;=>6DDD!!!$$$MMM55ctg]UPLJIHF?v\gq"++pR<* 333333 *<R#pa g n%MMM555RRW''~yyy{{{++iKKyIIJDDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMM55cth^WRMKJIH>v\fq"++pR<* 333333 *<R#p_ g m%MMM555\\\tttlllnnnxxxGGf77[[`DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMM55cuh_XSOMKJI>wZfo"++pR<* 333333 *<R#p_ f m$MMM555&&&WW[..ooo^^^ffftttWWc''hhlDDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;:::DH0DH0DH0DH0DH0DH0DH0775555555555555555555555555555555555555777DDD!!!$$$MMM55dvi_YTPNMKJ>xZdo"++pR<* 333333 *<R#p_ f l$MMM555YYYsssjjjlllwwwYYt44ZZ_DDD:::::::::sss\\\:::zzzpppttt:::::::::dddZZZ;;;qqqfff:::>>>000;;;:<:qqqqqqqqqqqqqP&&&&&&&&&&&&&&&&&&---DDD!!!$$$MMM55dvj`YUQONML>xXdm"++pR<* 333333 *<R#p^ f l$MMM555NNS$$}wwwyyyDD}FFwIIIDDD::::::fff]]]RRRMMM:::::::::zzzkkkQQQ:::>>>000;;;6>6DDD!!!$$$MMM55dwjaZURPONM>zXdm"*+pR<* 333333 *<R#p^ d l$MMM555BBE44p&&[[l666DDD:::;;;GGG:::::::::AAAvvv:::::::::zzzPPPrrr:::>>>000;;;6>6DDD!!!$$$MMM55dxkb[VSQPON=zXbm"*+pR<* 333333 *<R#p\ d k$MMM555***SSVaa22}``cDDD:::JJJ:::::::::::::::GGGuuu:::DDD:::zzz:::MMMyyy{{{:::>>>000;;;6>6DDD!!!$$$MMM55dxlb\WSRQPO={Wbk"*+pR<* 333333 *<R#p\ c k#MMM555==?DD`DD bbf///DDD:::<<>>000;;;6>6DDD!!!$$$MMM55dxmc\XTRRQP={W`k!*+pR<* 333333 *<R#p\ c k#MMM555MMQ<>>000;;;6>6DDD!!!$$$MMM55dymd]XUSRRQ=|W`i!*+pR<* 333333 *<R#p[ c i#MMM555 DDHNNX%%|MM{{__1166u^^a??ADDD:::::::::hhh:::::::::::::::::::::::::::ppp::::::::::::::::::>>>000;;;7=7yDDD!!!$$$MMM55ezmd^YUTSRR=|U`i!*+pR<* 333333 *<R#p[a i#MMM555111RRUUUWII_99n>>kPP`]]]RRV(((DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;7:7``````````]DDD!!!$$$MMM55ezne^ZVTTSR<}U^i!*+pR<* 333333 *<R#pYa h#MMM555&&&222??A<<=000"""DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMM55e{nf_ZWUTTS<}S^g!*+pR<* 333333 *<R#pYa h#MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMM55e|of`[WVUTT<}S\g!*+pR<* 333333 *<R#pY` h#MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMM55e|pga\XWVUT;}S\f!*+pR<* 333333 *<R#pX` f#MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMM55f|qha]YWWVU;~Q\f!*+pR<* 333333 *<R#pX_ f"MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMM55f}qib]ZXWWV;~QZf!**pR<* 333333 *<R#pV_ e"MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;8>8 DDD!!!$$$MMM55f~ric^ZYXWW;~OZd!**pR<* 333333 *<R#pV_ e"MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::DDD!!!$$$MMM55f~sic_[YYXW;OXd!**pR<* 333333 *<R#pV^ e"MMM555===========================================================================>>>&&&///==================================================================@@@$$$MMM55fsjd_\ZYYX:OXb!**pR<* 333333 *<R#pU^ c"MMM555$$$MMM55fsje`\[ZYY:MXb!**pR<* 333333 *<R#pU\ c!MMM555$$$MMM55ftkea][[ZY9MWb!)*pR<* 333333 *<R#pU\ b!MMMCCC777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777;;;MMM66eulfb^\\[Z9KW`!)*pR<* 333333 *<R#pT\ b!--~MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMEEUumgb_]\\[9KU`!)*pR<* 333333 *<R#pT[ b!MMMJJJEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGGGMMM::bvmgc_^]\\8KU`!)*pR<* 333333 *<R#pS[`!MMM555$$$MMM55gwngd`^^]\8IU^!)*pR<* 333333 *<R#pSY`!MMM555$$$MMM55gwohda_^^]8IS^ )*pR<* 333333 *<R"pSY`!MMM555$$$MMM55gxoieb`_^^8HS\ )*pR<* 333333 *<R"pQY`!MMM555BBB????????????????????????????????????????????????????????????????????????@@@)))333??????????????????????????????????????????????????????????????????CCC$$$MMM55gypifba`__8HS\ )*pR<* 333333 *<R"pQX` MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::DDD!!!$$$MMM55gzqjfcaa`_7HQ\ )*pR<* 333333 *<R"pPX^ MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMM55gzrkgdbaa`7FQZ )*pR<* 333333 *<R"pPV^ MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMM55gzrlhdcbaa7FOZ )*pR<* 333333 *<R"pPV] MMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMM55h{slieccba7DOX )*pR<* 333333 *<R"pNV] MMM555DDD::::::999:::666777::::::::::::999999888666999:::::::::888999:::555999:::>>>000;;;=>6DDD!!!$$$MMM55h{tmifdccb7DOX )*pR<* 333333 *<R"pNU]MMM555+++;;;888%%%DDD:::AAAssszzziiiIII555::::::???ccc~~~mmmTTT555999:::;;;TTTqqq]]]888888>>>000;;;=>6DDD!!!$$$MMM55h|tnjfedcc6DMX )*pR<* 333333 *<R"pMU[MMM555+++XX]kkllln]]qbbqqqrmmpSSV!!!DDD@@@zzzjjjJJJ666:::sss~~~nnnXXX555:::VVVrrrbbb666>>>000;;;=>6DDD!!!$$$MMM55h}tokgfedc6BMW )*pR<* 333333 *<R"pMS[MMM555BBDffh==z$$$$00q&&p{$$TTwllo666DDDTTT{{{kkk777EEEooo<<<888sssGGG<<<000;;;9983>3>3>3>3>3>3>.8.8.8.8.8.8.8.8.8.8.8!(DDD!!!$$$MMM55h~uolhffed5BKW )*pR<* 333333 *<R"pMS[MMM555TTXWWi""SSrrxbbkDDKn33nnsEEFDDD]]]{{{;;;LLLCCC<<6DDD!!!$$$MMM55h~vpligffe5BKU )*pR<* 333333 *<R"pKSZMMM555<<=XXf##\\c66Z$$qqs+++DDDOOO999@@@ccc>>>888YYYCCC>>>000;;;=>6DDD!!!$$$MMM55hvqmihgff5@KU (*pR<* 333333 *<R"pKRZMMM555&&&__a""llr((gCC}bbfDDD999jjjHHH999:::TTTmmmZZZ999:::III{{{;;;>>>000;;;=>6DDD!!!$$$MMM55iwqnjhhgf5@IU (*pR<* 333333 *<R"pIRXMMM555DDG@@oUUHHNffq666DDD:::999RRRkkkcccGGG999::::::999KKKfffbbbNNN::::::::::::DDDccckkkVVV===:::>>>000;;;=>6DDD!!!$$$MMM55ixrnkihhg5>IS (*pR<* 333333 *<R"pIRXMMM555QQW**|{{{|||))iLLxHHHDDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMM55ixsnkjihh5>HS (*pR<* 333333 *<R"pIPXMMM555[[\uuummmoooxxxFFg88YY^DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;=>6DDD!!!$$$MMM55iysoljjih4>HQ (*pR<* 333333 *<R"pHPWMMM555&&&XX[,,ppp___ffftttWWd''ggkDDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;;;:NV&NV&NV&NV&NV&NV&NV&12.////////////////////////////////////333DDD!!!$$$MMM55iztpmkkji4>>000;;;:<:fffffffffffff#K#******************///DDD!!!$$$MMM55i{upnlkkj3>>000;;;6>6DDD!!!$$$MMM55i{vqnmlkk3:FO ()pR<* 333333 *<R"pFOUMMM555CCG33r))YYl777DDD::::::RRR:::::::::MMMEEErrr:::::::::zzzbbbBBB:::>>>000;;;6>6DDD!!!$$$MMM55j|vrommlk3:DO()pR<* 333333 *<R"pFMUMMM555,,,RRW""gg//ccf DDD:::HHH:::::::::::::::ooo:::===:::zzz:::{{{:::>>>000;;;6>6DDD!!!$$$MMM55j}wrpnmml3:DM()pR<* 333333 *<R"pEMTMMM555@@CAAbPP``f444DDD:::???===::::::::::::ooohhh:::hhhzzz???qqqOOO:::>>>000;;;6>6DDD!!!$$$MMM55j}xsponmm39DM()pR<* 333333 *<R"pELTMMM555OOS77k;;!!QQiKKNDDD::::::<<<:::aaa:::dddPPP::::::hhhZZZuuuzzz;;;mmmJJJ::::::>>>000;;;6>6DDD!!!$$$MMM55j~xtqoonm29BM()pR<* 333333 *<R"pELSMMM555###HHLKKZ$$[[mm:://z]]aDDGDDD::::::HHH:::::::::::::::::::::::::::zzz::::::::::::::::::>>>000;;;6=6DDD!!!$$$MMM55jytrpoon27BK()pR<* 333333 *<R"pC~LSMMM555777TTUQQYBBc44r88pJJdYY]WWZ---DDD::::::::::::::::::::::::::::::::::::::::::::::::BBB???::::::::::::::::::>>>000;;;8:8PPPPPPPPPPMDDD!!!$$$MMM55jzusqppo27@K()pR<* 333333 *<R"pC~JSMMM555***777CCGAAC555(((DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMM55j{vsrqpp 17@K()pR<* 333333 *<R"pB}JRMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMM55k{wtrrqp 15@I()pR<* 333333 *<R"pB}HRMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMM55k{wusrrq 15>I')pR<* 333333 *<R!pB}HPMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMM55k|xutsrr 13>H')pR<* 333333 *<R!p@{HPMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6>6DDD!!!$$$MMM55k|yvttss 13>H')pR<* 333333 *<Q"o@{HPMMM555DDD::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::>>>000;;;6=6DDD!!!$$$MMM55k}ywutts 03>>000;;;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::DDD!!!$$$MMM55j~zwvutt 01[E1" $$$$$$ .@V4bC~LJ}}{zzy-78V@. $$$+++ *;O *HC~JS~||{z!"+7-gvO;* +++333 %5H!aAzKRK}|||p +4$&bH5% 333   /@T 5\IRX3~}|A *-}T@/  +++ '8J_CvQX_~~ x( aJ8( +++!/?R(:}PX`Y_ wDRR?/!$$$ &4FX >dXa f l?7jl whXF5& $$$ +9I\ P_ g m s gVjklut\J9+ +++ ".;K\Hl f o u |x UC1&$" !#%(*,. / 13568:<>@B C"E$G"D@;73/+ & " " &*-148;?!C#F"E B>;741- * '$ !-=ZhijkkW|\K<." +++$$$ #/<JX3D e v} z t lf_XQIFOV^e n u |!)06>ELS[aipv~ymbVL?5+yk[S alz(2;DNWajt}ypg]TI@6-"tg`abcdefgghijc5IXJ</#   #.9FR`Y}| } u of`XRJFMV]e l u |!(06=EKSYahpv~yobXLA5+yk ]S ^lx(1;DLW_jr}{pg]TK@7-$tg`abcdeffghgR|aRF9.# +++ "+5?JT #bNgr  x pi`YRJEMT]d l s | (.6=EKRY`hnv}yodXNA7+!|k ]S ^jx&19DLW_hr{{rg^TKB7/$tj`abcdea^V A_#bTJ?5+" ++++++ &/7@HOV[`e"&k!$m $n"%o!%o!$o $o#p#p#p"p#p#p $p $p!%p!%p"&p"&p#'p$'p$(p%(p%(p%)p&)p&)p')p')p(*p(*p)*p )*p )*p!*+p!*+p"++p"++p!)*p ()p')p&(p%'p$'p#&p"%p!%p $p#p $p!$p"%p"&p#&p$'p%'p&(p'(p ()p!)*p!**p"++p"++p!**p!)*p ()p')p&(p&(p%'p$'p#&p"&p"%o!%o $o $o#n#m $ke`[VOH@8/& ++++++  !(/5;@EILNOPQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRQPONLIE@;5/(! +++333$$$   %*.1479:;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;:9741.*%   333+++ """"#%'()))**********************************************************************)))('%#"""" +++333$$$     $$$333333+++            +++333+++$$$$$$                                                                              $$$$$$+++333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333??PNG  IHDR\rf IDATxyy/;Tuttff$4hZh70v|6wCc;Mr'rm9~pXE$#HH2KUu|tni$yzԩsN{=B`&BްЂ?M1Gt}BR@ &0]L~yZoa&D^3J 6@|w|+WB%Z8b6y6o,nBz^>.AUU)`RTu {?gkoiGG1 sjB "i-y / )!D0LI|EQ̱13 AC@] lbH M|95MR)jZ}FLӔB:ID찬o 7-ߢ M€"IoyA)7 !BQsbbŽ  i$~Å^}5MsNeO94QKP!5MFQS?-ABx;!D$l,RjBLJ3()i 1&"ja/}isΩl `i6jBP9D"eB@UUjzEQwC[8Qj?!&!ut_41yXRPUOLL4>D"4!P m;[}]ש(3LUUf&5M)b[Dw  0ƨ'ZA D#NH97M~0 sN)RSu.c\ EQ4 ,`:on!PK~iNۙ$T"I9W,31f[dlM1fk:X/!B aPA~s.~I19&0M4VBa1fHa3EBdRLNNrUUMoB V_4&os,+i*iRƘb"`R&`1f&E~qjVw\+-eJ 1+lzA^`hBZ^ h z^V5ZJ뺖(ʠFU(Ԩ P(Q5>094צ/h/l^LzP?c[!D҂(ZrRJ(1F&뺮i"5,R8o@-&;ɯ:j$e+҈aBQvm)ϘeK @P \TKJ_DL|kj  U Aw!P@ SZKPK_pЂOk!}ɇ.Y65^(sess~oߟݕ|C(i"pΡ*t] `NMSVLO;=p4iG !*!$fFRE1Jid8𶋋0)L:ŦܬT(PD H (),BODgc7UXN~е %Hw*κL•/Hݯk}\>W,|jgO@ 3 q.sP&TJd2a!bUMj@+}r_2dVW!1B޻"KiBI%i%@rA#( &\[É8]~m'(3H-nhB)H@0n-,GNK?._x;/J<$#,"u]BX2D6iΏ9P kW\Iǩ5u]QUvYj$11BH4p'_XX{B#%vkNx+TSI 3/`,Dw,s"6=D%SZH%+e%DZ)/!(KAa#( kY`0geV 5P0tn 0t\7`ryέs>6Lsp]f)a)e 30U:tdkSyXaΫ0܄9aFspn4uC tg7`tnœ 8:%,9#dɤ+!(J4Ms+njdY( F<t:m}42AP(aNviD"S Ð|^tcI1AhȧT1A&\ȤKQC邎 ױL/{#(iv@p΅iBQ2M]d2뺰KU8(Z!Z,I.D"hD"iJ߲c6X_]\Oc"70BU R'/*C6RVk3AqhC 9@2 t(HPƿB+/&(!!&((sεH$k#f 9y)hbmW˩y]aP8rhJQMӌp#(!$J$7-a"- 0jY~%0+s>TE[?|l#hJis1M3B)UcZ/{$'9rlYr_W)X^0ʼi<~UVP:`9"L$o]2qOL`B)'9@䤉yϣy(fŋ{$ z~Z5L&gyg뎫^iQ; ~8کxD IX<ӈl`9=EΰMRrQb\bHP+0Z9W곜wm}=rZ-?u:{9 A^WK'5 Τt%zZ2z }/L,ǁ~׽\B|}]Lh'Z{c˴Wu2ʕ+Q,;eǬ}iQ{{ۍ5΂p %(h7Rzt^{ZA35ߨ2 865//{*˦s?{oqJL&QιFa,NkkZf4_+W34ܞg Egn/u  j'Py K 55~tSPAzˬ2[&,AհsܣbʭW_:EQz[ p(Q^{zJ<ߪ`@trhgWR9 tj;,qN^A]zTnw=)8tGp SxƤApbp|TL<ﶽS~ա0EQnf[[5MJ-@:=^y/ QNhJB4MPG_|k^ ucFe|";]}xul}#4>0 v9 0~J32_5Y7ozϬ$.㗚 !"g\0 =9\ն T_]eM;LQB"t~TyJ&Aꪬ3Op>tHDw\20D.~FZHUk^c>iaxA{w*~#{2\}F[#WR"2K ҷLT_>W ݹv?nc5_BBeuO抄7 7|ARaG<$$k{}8aIu0 + x=K$#C2%MZ:a>j/ eww vu(?z,-@⹔sd@{{-E]?]?jϬbBE;t4>bD~g^$s_w%_K6_ )W+I /"MaZk8코3 vkS׭T!iN ( H /xq>Σg( /SJems7ȿi-XKjHga^>K؞C4I:&BRJi%\7!%SL >P?m~תyj2+nRV-sLo&!(,'INa3cB{uƇ ٣ncU;k(qWB09 ;!V\qi%EҫPJJOT{8;5/G:g º#zP &׽k!_/m=5I"9JB[pWKmaU)) D/%E 29*RJu]-]1RIڋgYy@Rf+ ^"W\|Z٘up ]/ [r 9y ey -`bX`ѩx)tFGhyJ)%00W!l \R*w. !ؒTRbSL`]KKuJjsTw;G G^}ߠw 9,,ԮE$>xY`Ϛ5 #ǯk5 F4M#*uP3UYH%/Dל䫵왖4(3^o`O0% rZ'( Lz03M:MX,fyÂm I:Xa"oKXu2,BEbU\J@9j~t8P%(vv Y."=65l1F8e\m˓eJ%H!BDZ7qT-irX}hAJjqnB 3 Bxa…q1DBI}8Dl: (BUUsLRa[85XEuLG%Pc8ΡhJV Q=C]H$v B( qIJUe 6dt/Rtى .>w7vw:.4)F"]jĘ%Qy65D"ao"Tr[>C8n_nQfpLA]T~pk3^)N/eyŤ y1SZ=g\ஏO3pr$?*תU坂6B-0C&;꿼S H9tUT17/oW;L-j eF[y &RZ&@WW?fURTƥ3L|T&up[{ti^%EM$TKX-lٲ œPb۶m+_jPD"W_}'O LeAP>"@U[JHwZ~@89ؙFCDF+ NXCe& ak^t[/]&{lqRؠZA$ZhlA-$C8m}Ԫ}^6ۑ S1mj|@]! "JUOh!{. {b p5L U&ĩ{IjN@g:@8l&LUj5clXq^#՗pwq;"L@;gӤI&B@~@@pi úɃhߦ>6OIuW'-[hL'A=UBhk$ 0=Lf2!y-a7)SRCc/} -4bO}M)o>7y3f8K`tri][liW\qx$ Nd<ַ|; XroxVZ C~o>Le 4Ugc-N@w⢋.?,ܾD\xXσDC!RWbK.Aҥ838y5OpW`Æ fuøpW_}5G A=$lh (;Һt`tuuwco сkE r t]GP@PiPR(E>1"B}!#296d2+VLSXv-^~eڵ+T{T [l֭[xb?3wTw_WӃ[bbb³n|cC.122kl?J SkJ~/4Z 4Z*_PB&WڰEɓؾj"E |r( (4 (տh4X,>$Ix5ٻmva8vEOOFGGk{Y(-L&1<<:G?2W<ø{O__駟,sttz׻KRO>`hɃ?G:2~N??AC,p5<9(8urr< 4M&@$sΑH$lrlܸ; ۇ#p!򽽸sPt c3gq饗ǏW%?04V,Coo/:::@k /Ƨ:wQ:a'18 #}я(([F4ܵkiv˟ffmvB@)c$F.p"O>^;߉t:~O>~١=܃n1D"Z@~~J)>OnC4id2eZA hK[ic&~N@A@|aY'55 YG/@> 6c`AUUpm@ e˖a߾},Ylߎ0##c5 wXhQK,g?Y[wo>Ep x衇*a{w}{o`ݺui?ng:H{ـ>R)0ZXAH< X#Ml_ iy;N =2B`uVimOcٲeXe//]vX,k+W}HŋUf 3:l VOvu= un5MCX&S8.μbsE<G!Rξobll <@E} 1qx{S}rF2ַbu{tj^N@ӁNr"bPֆnN9|+_0ۇ,^HOx> ^|Eh5k`ݺukO<nkqcGQ{O4GrpB`&80 &3, $ //e>oܹuv 4Bf֊_Gq 7 /:??m8.ł pa|ӟ=ǧ?~򓟔9 7mڄ曑Jꫯp`֭5?5)JԜohoo֮M24&jG؋A ߪB m;LӴt9I-R UUA)p5`J4O5UsJm;XLZ1ȂA N/ `ҥ)Oǟ<Ϯ.Kߨ4M+WpUE۱N=؊99HVUZr>[~ȜaVsXi^qaU~7dKA L&^R)̪+ 1fPJUq_{z@A&Sp6k%61(邠뺽_D_ uL&{ X,X,6!cXYzgX4l߾$GG&f"B:p.Tùz&ۃμZB-(!;pr:"[dt]Nu?#H )?Q(w`wMrΑdf0dB@4|>O =3zM=I%<. v1\tE0b1-X1Hؿ?.cܥꯪt`;v`Æ rXv ]#C>,Zv܉-[`ӦMLCCC馛0{lݻ_Bl9t:?A b8y$vڅ-[`ͶB &; t'{'uw^KyB.ѣGۋы/Fzd'A-C te{ E)[Lv1lߩ!GyLf<y}$8袋~mmmX,Kb``˗/ChV]%+): ر_~fӟ۶mC[[[ug>S`ա-Tw4AӁaF gZZg!'8yGiعc4MC"@2D2D{{;R8wH$*}Q8y8Lr’.0 tM0t]GGG/?lw4wb;3\2>]s!add^z)==Eg/n:۷D&y*B:\^Bѣx衇i&uCC( N@$b۷sqx+瞎F񖷼J%\+,X}2֬Yc$~C4NNb؍7°!xjh,Xx<]]]{pBVP(`pp7o'PJǓRpcѢEػw/E ,ܹs+pߏ_زe C4DiwI3Ӱ&lsl޼W_}5h,nG^ŷr9?A)-GŶm1p$c&HlRsןiXlm[?ԧ> wy'5MC,a`!a޼y>y9_^rՇ~;wĚ5k''`! (q=\M6xO|7oƕW^ H`oŜܿ!Vc֭شit]3 ?|>oO4Nm={`ǎ5QQ-M7݄իWcݞlۑ5՝RFl59]/a!qmxMs3V4pw9h^@=&ɓ'a\q8z5Dז-Hm6dx_x2HduzƐ!T+2 e˖i(.#xΚq("dY{a?MLLWe\r%铦Aqf#Az3Vn=Pk5`bb?tb0{nu{cx7p)%7::jOWJ-͛q5;~h#(? ZI^-h Ӂ+y߾p=wСC8|QU+E8GFFsΆپ1por9 ycxgh"$uO~[nj~:sEA@@u ̢ {޽{*]6̗snabbln;wK.msg/W&!{1zFVĉ8vDEvڅn,Y$C #y5 ̛>#t`V݋^y]1<<\~|!h7nΝ;jժ2y?~sH$\.Xr%̙Sq&0&&&VPuxsN\:UNݐ3ݞZ[fi3 rqq{+.mbn4ix饗A:R0UUV+ ؘgcF߁F<͜ 4X+b$ n.$Zrx.cҌct|C3:F)US ٢:h6HДnƠXk\ -d~-` 3y 4B $!Ӂ'@o|[8є5&. /D~w![hLV~3hAW --3rRfCы(A>(LWkԕ?ȴn`4L-X\5[ߝ&(f*|^n7ceM  ƹ&&jn(rV>cÜô~髥i Ӂ+F"i7|M5Qj޽u D:S [-U;3~QP=zaYDltj$Ò 3o$`ۃqAZ"8$e 4TE6k~fhX~3%[Kpl@n ޖEf*Mxw؍=W_O5j -4f7s{0"h@Ҹ1o޼:kB m W5Z0~a7&%fϞ]G-[h>qt:nT18'L@q/&s iG=6oL@ۃK4B 3;w>PZh ҮyZkeN jsii uxgz ŵkfoB F:s5zW '`fr:lv-6]NhjU&[g&D-LCZxߖl XL0L@#3~$`YIA-0S(`Ət*@={OA@*c9뎮u,Rzn'f hַrZza0'V^bx0Ɛdm۶nl jhkk֭[qPZa-8h0 ǎ;h"8\.wV|Y=UN@?uށ[hLgNJ«;aҴpvd&޷c:={0{mm8x1N"bhhضm[S/X`&''122u!5> _BC˕~ڔc~4Z4s& ˃2^000`o$+`:zj"{Eކҥ08rrǎ8Cݶ o\ ۋD"-[ o̴Xf 2 ۇt:yᓟ$/giȽrױXa!մ+ѼG@3ZJy0ӄn7\pΝ 8qnu]q>r8J)j8 &${ '?0q riY6liu7F*ƒ>zʾH$pwc -L 7ZMzٳ1w\B0{xX{au h0l! }xdlB۠ 7_G4F<ǪUqƺ6+?>_~_]fW6;.N+… pAC&h p 4/aMzAPJі`A[-.bf( (R0DP,000x<7xmA?p(ΚSCCXp!16V*H 6m <^}U[?˿G>򑲴\r {1Z.޽ێwy'`(Ix ę@a0mjt,]bSNarrL+~$&''0{l,Ya@z+_yѱ1B044TCm 7/]]]`z{{ kqw`…HӶpfs.V!5 x; "uuttNv0Qlr@iئl9 !`/ȁȮX]h;|G… k( e[Pa׾cǎG?|M9rVŸٟ=a\{7obll w}7ꪚ|t5 ;fP݁PpF0] C,w ˗CudYEr(v/(x( "HYOR| U+O$}ކq<(Vmoo5f!ft`'~wKj=0+eNB` r9y ;L+@$Af$ Eٳky _`&>`֬YׇpsH$n:D`FYߢEz={c3g 6u I6DQB>z,^O;I10P,Fma<:Lo/RÈ8===5җ??w][ dY?7nĽދ~~b=uǷa]=~_ wq݋޺>PKcD~'lr]a5H$25/Erp"ɹݢa;$p:%%xUUcظq#H C>{6xȚ'֭[]tݻ<y}w}7>cxꩧ+{)w|&5=HӸ[b ܹ1|\y5?ʳMu^D,Q UUtz 3 ~e΋;0T]1M0 !l sy HNG'D`yvثWM~z_"De2z衲s4#G)WS\^Qsick2c:A@Yk:jar ղ#]]ec ay$aiА?g~g\[[[`yݕ\@ g 571)#+V JR]Ra~u#H@0f-!9y]w7>>be( wkl&@5HװZcuݪ&#y]^?g>g8ɔeƭ &]h3 F^xygc+䃥KrA~gfl &x'4kP,K-T,9G2(t9H Bu0ƓIBZ}+f6݁=N4X blLFׯ6y(ѨMX,X,\)'K/2i蜜1kx: I=-f!*֜]#1hX0:: B&UNAu R(`_t̻Z!I{WcҥXp!DZk.lڴ F$Tˮt:ł :2 v܉^x^ L-[ `ll wƦMpȑ^J/5\^ v7O;oX `bbcccıK/EgqG1{"N+@^ h4Z%0裏B4A0[V髁sT* Ú5k~zNV~7>0 ر'}˖-ڵkG\st:FYΝ[¨Z"!bgP'׊={ faf6St]C"@2D2D*B*ϓɤ}x<8x z1l "ʕ gBuoۘ7o=[QNB!EX08?#y睶ϣP(@aD"xߏٳgWr7M̟?Zu81~:Nl^ZJ-Ezall ǎ!GWJoڄL&_[f: JN~R0R);iWz *x!8u885 (Go߾ I"J2Κ5c޼yJ;M뮻6uK2R.袖Oj="Knմ~ۃ}ٱcf͚X,kg_NJ+}A+E"l޼?119d>U 똸*h Լ?7tNUIȡ!رÞÝwiuN @( De.b^dz>gyz=+|G5SVN'`//<`aâP(` =믇~n9oc-)~_Uuss< f c3ذQxe嬈iE,YrP(%ECQM(c$+VCf r, \f<03s9]]}{wuU}G믿ۿ^caaַo8p<~sa; ~X?tDcǎG7ߌ >(8x#jZkjܫ}V/a|{?cǎu]ϡ0Sҽ[3윀I#.^_z Fsnu~ډwKᩧ2:ְӧO1uƩSbm V,}sh";#_=Q6Ww}8zh$t>hjj QՉg jy~vC=[0m.'GGPF\4Eaϲv>s 8|0hro?f_={яbq~cgΜiFy=|dqW[X,Xb,..nff.Q[x߆0UևЗp}iITn I^?ui$d4; Ξ=;155o 7`W1_c/c/2$!L)I6Ѹz}P{m?=dūo}}SSS¤SNavve}X>Ug<;w]7p x@M붳00 ;VVVSOnAn K݆xyg@#؀c4>9 w/ke@:^ŋob!GmڸpB~}}L!9{ GTjKJp5uήcǎɓ8x ۇ ;sgdhٳg1??Gc >{:J <->*ɓ'#j0 à$IpQ=zv5\ݻw386yWWW}F9fxgg\}ՕԩSZ0L>>SN>S-c$8瘞F1LOO'N믿)رf>|Ww,I~Gb% EF&"ʗkZk)v04t ܖS1edG}߇_rьr  M!FgXeCyY~U1i($P ~1ԝ6L N&QIeq!81QʺI1aP 1(hAMIƴ]hTϻ^?cS`L۝od{M^ {QH}/6' n[ݍ6o=?5ơ}vzm{wzwc"F0˔ŎW4z2iWG2 Iw l&dODesc3A$)CE;*OCcV N7vHΝ@ͬ;w\[ޅ .-]lN۠3#ݔ }PЪ0j\ #W^ye0R4Zƫ Cl|w^iLہBЇj? vлpàA`(/uh?|՜qLcj /r vX1ܸ-vY1!CjLc.MeyU6/tzY+Q谬 l0NNp"ۿ([Q+}vE[duXEkE*ET4D   *% n[: bO( )ZM;g%|W7%p 7~~G!6~ՎrBX) <[Ns${9EZU-ꛍiL#$4dE&,п P5q^r&<@ ȩjw` ^*G+#1m'r2"9܍R@іߵ01@k?Oմn~}Wcv!|'/р^_m/Ť;shzݮ5pA@;w/ϝ_w8>}T; aO~(HWQ*M;kvjgX}/_r徐 4ڝ~vi , ~ Wn-`wZ <|M@j3oqKDS:<B3w :{ PzP^u鵿EוWۋ@;YP" ݩ lj֊=6 b4)08E `WEVc>d3]֟t7A96]vE=eI|v__t:1K ֥ApDj> I\pX[[sKDn` JjZS@@Lo¯G "$_% Ha3K Բgj72O*ߜMQߊ}UHim4/.\0/Z]9 xnK)sgZ"2 )\:ahu46AW!#PD0q/ֵHa0Qߖ+cL?!TII@@;c(+[8S`m].2&`#6"7BƘ]ZZe{D2g38?$Ir?֚,p3U"F:]y"D{@?"9 QmH*`"E? @AS]ޞ+' WʋDd2lIL2 ر6 h4ȳ ei!E"p]$Aێpo̗ >٠sXEk+3u|̠mxU2(N#L`eE.#<ֹ@vδRmUNrfƆtq^O"Yu/Q[/F(T*@ͭV7W/ݰ^Qpcnr. })XgƳذqjW~iӁĄS%L֘n@ίөeϙ(ߕP}Xe5_AytX~t!Cpk2_릏w-_  @0h<- 7ۉ.--(O? |`P8(XlH) #06ƘId cL/ U;A F aKoT% ^o⼊Am^*9 @淚"}Q 1*Mܡ=ع}%Sz{u3cZk&c72s ܾp8p 93uC*;x骝 T>cMwA/F^8=;0z>uWu |M_KZ@g XkM$&"`)C*Z d1f/^h9h`Hk("Rz<~%&`66 -ռA/"|1e\>4tU>,imey{'t9cw;p}/0c9>3ozsPl 206(c&"u8q( ڭ"nD)m}n\U~ǰ[ ~o^e+oF|gO}'S1F9+ƆqLo#-&e1w+y, Bn \q0-mt2k~A 6 7hwz>sW?O'Ww^pSsBc5P[o?@~jVacvyy0Ɔai)QJheM4??f-4c:9)`3Po9ض*+Pm^:ȵw;{ _җ¸MkmZ+=鯕RJJ;c&ê[bznݤ9wGc|@Zk#oϾ= e@1nI|K=2]Ajro 7z#e/cя>2Ӹo.Ǩ 9U#GPl"llcM/?Z8Þ񳖓"opiD/eWPufѵmk{}Um+= Ѝ l*orJO/}!g?hzʥZe?l6B;=cj5M)e ̀<8CyZ1X$  {w6HAC442DJ(R*"EvaaȻ3xAP 0!fIQ)9SJI9)!B7(ve-[IZc2MX`&qew_X~K#} ?g 8pCw=;c7Z/[]W~'V˴覵)H2ZK!ͦΆr_׋@iZk699)$Z'Is#TQT kFPwO~G>ݸ’ ,ikeր1Y7jlRrm~ӣvxQ ne 35Z .R.jq*3q8{{׏648hhcBN8NͦX(Ą_#YxZ@^G&1VWW$5 H)sNJ)bQHs58u}?);dZg'&8Ej\H t2 c,Nk,'8#0N`<]4gb~:-euH481٦1~,-O\;g׀1` Zj*Kg牂ZJ(VQoVlD!RRH!4" @-tޑ#G077gUO2DZR$R$6Pa~;zREU8)#0Yopz&4(( -PZ@ !"J#=)cpi8OqyZ8#010!4e|Ll%.R@e. μ6t4F(F3=HIYP7M'MhmI#V@3ZqD!ʤ;s%us]GPV *P$e`M $PMLxi$RץOY|?Bj;߁i󄈤RJ !T$*"#G8M};mksss@6=yyPqC)y.Ee'd;U_f>dMY4f5YU;n_FHheສvzm ˮ+֧.*ڱ;-RֲֿC]eep;?_Qӷ9>Ƙ$e~E^]]q8Th- rshzzZ BXuLNr!i[;'~@zbA)3l"1l 8Xm- @=Xpv[A@_.,륝B |UCW {K~*R'&s?_///()@z@KtQN2H)E9]gܰD_y%;M򾙺cV@ Z6g#+p9`e =p>۩aY%ʊ@a;UZKò^@߃ruYHE}²9^^gԗHU)HRhe~)<_E @ fnn=s 08R Dd16pa12[J,s=_;r^u7O][5 4jp<-Xe a?2Th`*Q^TJe} 3**bB] ϪƯ^;HP^Z2$RK c~^3>@"b6&5ZYr֚c^OQiLض!#R&ڶc]\#0.[KQmL(0 |F|cii>CصkC6J() |л#c...L>0Cdy1Glj  p_;&QDcm`LP(9pBx}t1d i@ F-HCY0iz@m?r;oЙ- @Mgeǘ @rpP0]tf#gyNc@+Ә.99ȁΠrt@~rFW2*LcTJ]*; LaL^ӱ|H[B!T61iL4`!ៀ3I]IENDB`Carla-2.1/resources/ico/carla.rc000066400000000000000000000000241364475620200165770ustar00rootroot00000000000000id ICON "carla.ico" Carla-2.1/resources/resources-theme.qrc000066400000000000000000000003661364475620200202470ustar00rootroot00000000000000 bitmaps/style/arrow.png bitmaps/style/groupbox.png scalable/carla.svg scalable/distrho.svg Carla-2.1/resources/resources.qrc000066400000000000000000000164411364475620200171500ustar00rootroot00000000000000 16x16/carla.png 16x16/carla-control.png 16x16/application-exit.svgz 16x16/arrow-right.svgz 16x16/bookmarks.svgz 16x16/configure.svgz 16x16/dialog-cancel.svgz 16x16/dialog-error.svgz 16x16/dialog-information.svgz 16x16/dialog-ok-apply.svgz 16x16/dialog-warning.svgz 16x16/document-new.svgz 16x16/document-open.svgz 16x16/document-save.svgz 16x16/document-save-as.svgz 16x16/edit-clear.svgz 16x16/edit-delete.svgz 16x16/edit-rename.svgz 16x16/list-add.svgz 16x16/list-remove.svgz 16x16/media-playback-pause.svgz 16x16/media-playback-start.svgz 16x16/media-playback-stop.svgz 16x16/media-seek-backward.svgz 16x16/media-seek-forward.svgz 16x16/network-connect.svgz 16x16/view-refresh.svgz 16x16/view-sort-ascending.svgz 16x16/window-close.svgz 16x16/zoom-fit-best.svgz 16x16/zoom-in.svgz 16x16/zoom-original.svgz 16x16/zoom-out.svgz 48x48/carla.png 48x48/carla-control.png 48x48/canvas.png 48x48/jack.png 48x48/juce.png scalable/carla.svg scalable/carla-control.svg scalable/folder.svgz scalable/osc.svgz scalable/warning.svgz scalable/wine.svgz bitmaps/carla_about_black.png bitmaps/carla_about_white.png bitmaps/background_3bandeq.png bitmaps/background_calf_black.png bitmaps/background_calf_blue.png bitmaps/background_nekobi.png bitmaps/background_nekobi_left.png bitmaps/background_nekobi_right.png bitmaps/background_noise1.png bitmaps/background_noise2.png bitmaps/background_zynfx.png bitmaps/button_calf1.png bitmaps/button_calf2.png bitmaps/button_calf3.png bitmaps/button_calf1_down.png bitmaps/button_calf2_down.png bitmaps/button_calf3_down.png bitmaps/button_calf1_hover.png bitmaps/button_calf2_hover.png bitmaps/button_distrho-black.png bitmaps/button_distrho-white.png bitmaps/button_distrho_down-black.png bitmaps/button_distrho_down-white.png bitmaps/button_distrho_hover-black.png bitmaps/button_distrho_hover-white.png bitmaps/button_edit-black.png bitmaps/button_edit-white.png bitmaps/button_edit_down-black.png bitmaps/button_edit_down-white.png bitmaps/button_edit_hover-black.png bitmaps/button_edit_hover-white.png bitmaps/button_file-black.png bitmaps/button_file-white.png bitmaps/button_file_down-black.png bitmaps/button_file_down-white.png bitmaps/button_file_hover-black.png bitmaps/button_file_hover-white.png bitmaps/button_gui-black.png bitmaps/button_gui-white.png bitmaps/button_gui_down-black.png bitmaps/button_gui_down-white.png bitmaps/button_gui_hover-black.png bitmaps/button_gui_hover-white.png bitmaps/button_off.png bitmaps/button_on.png bitmaps/dial_03.png bitmaps/dial_03d.png bitmaps/dial_04.png bitmaps/dial_04d.png bitmaps/dial_06.png bitmaps/dial_06d.png bitmaps/dial_07.png bitmaps/dial_07d.png bitmaps/dial_08.png bitmaps/dial_08d.png bitmaps/dial_09.png bitmaps/dial_09d.png bitmaps/dial_09s.png bitmaps/dial_10.png bitmaps/dial_10d.png bitmaps/dial_11.png bitmaps/dial_11d.png bitmaps/dial_11e.png bitmaps/dial_12.png bitmaps/dial_12d.png bitmaps/dial_13.png bitmaps/dial_13d.png bitmaps/kbd_normal.png bitmaps/kbd_down-blue.png bitmaps/kbd_down-green.png bitmaps/kbd_down-orange.png bitmaps/kbd_down-red.png bitmaps/led_off.png bitmaps/led_blue.png bitmaps/led_green.png bitmaps/led_red.png bitmaps/led_yellow.png bitmaps/led_calf_off.png bitmaps/led_calf_on.png bitmaps/logo_calf.png bitmaps/meter_calf_off.png bitmaps/meter_calf_on.png bitmaps/rack_interior_left.png bitmaps/rack_interior_right.png bitmaps/rack_padding_left.png bitmaps/rack_padding_right.png bitmaps/canvas/frame_node_header.png bitmaps/canvas/frame_port_bg.png bitmaps/style/arrow.png bitmaps/style/groupbox.png scalable/pb_generic.svg scalable/pb_hardware.svg scalable/pb_plugin.svg scalable/pb_file.svg scalable/pb_configure.svg scalable/pb_audacious.svg scalable/pb_clementine.svg scalable/pb_distrho.svg scalable/pb_jamin.svg scalable/pb_mplayer.svg scalable/pb_vlc.svg cursors/zoom-generic-white.png cursors/zoom-generic-black.png cursors/zoom-in-white.png cursors/zoom-in-black.png cursors/zoom-out-white.png cursors/zoom-out-black.png cursors/zoom-area-white.png cursors/zoom-area-black.png cursors/cut-white.png cursors/cut-black.png fonts/uranium.ttf Carla-2.1/resources/scalable/000077500000000000000000000000001364475620200161675ustar00rootroot00000000000000Carla-2.1/resources/scalable/carla-control.svg000066400000000000000000000755111364475620200214610ustar00rootroot00000000000000 image/svg+xml OSC OSC Carla-2.1/resources/scalable/carla.svg000066400000000000000000000760501364475620200200020ustar00rootroot00000000000000 image/svg+xml Carla Carla Carla-2.1/resources/scalable/distrho.svg000066400000000000000000000057501364475620200203730ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/folder.svgz000066400000000000000000002544451364475620200203730ustar00rootroot00000000000000Jr-xssN@% xCXL0O?wRwEDVʵ@~] |y  t>}o?<7O}CO_<^ ?k}Zwo?0~O˷'n,`Y m@o?OO<=aӡ~ye_LOxc?OB`B3~˥m) 0t_̿mWixi~ ۜŽ2m ٚb?F/őq/c ll@?V?d}~;a [- E?O˿ˆS1Y>Mc7ŧ?.O{5t,7N^I{i?l=_; ի_\]ֳ]>˽y>_nnsI)akˏُOK?Ƴ{m Y5[d_sCp4ɍѡ{쿈_A8_o5/g}:BtD`3o[JǿfoNG H #y?.0bZ0bJ[È~E$ #M05k"4cH?_d?[M$_AHsY Qߝk3گ5ϐ?(6$Lm0+nׄGA0s7gjoa?væďƼ9[vJ'[0&guv:CPAC'qc/r?ÿp/I uĿ1G tԿ-J_GQHroe0_RPic#.__+?>A? rV_g]mg$-dzB76_`͏us`'3 9i?N~}m:t??0&'%g'rѧ%:dP=$?CL ,M=KcUwfYBwN`Yu"(gβOEqUY A*˲{xqe*}slñ_HdEC{L%vU_2ǦToQ 5!KĞe:<$ <"YuZ o'64p$6dۓ U("bm4i 0`C$퓆""jyu[*mC1mOV=yc$x}i.4=$Yy6|PF|l&K`;pj;uJvzǝG΄(Pwf?cl8DT_ssBQia2Z6}Q,Zda%$2P0L)$ *YJ<+4 oVXeY.hPtd D1xR|it^Y_jgVKtYup =@"4S/i55Q{߰螺L)hCex,p.]>dL WϡPd* G.^7hf!Vps5d~(`4pr  tأR?Z!|5i;cWIL|C*m6920=4f $]2Q -j>Vg-XdܞϲS,e0+537D@eT[6%[!)> b&quOȫi0.SUNq"kէO:.k΁+A@u65QV|N:-5~YG\zpAV;Sgly~ڡ6k^s#%S~Ob:jb70Lq ) Ձp!יD1k2{-c QM䪾/A3q=+\Af5W MA(U~ReT'Zk\rGLfBw"^=5웧-K_F@\߂ T('o\ aJgpya>.KvFwpoYe |Ʈ4G<0[)GEfJ= hL{rgR&{)|æ޴e=ĊK[a~2S^(j5 V‚ge xܼCanEYcu84Nj䶻N 04j_DcށGEU+ IyA=boxI{4)Pޗ5׋. ,k 1vNjdiZg^V+2@`C7yN.Yd(:kgrso4[tiN>Q92gs,Ho3Xa:#ibTMiS.=~{#o!aSxS@UDS)V[] Tm1%=m $g]5"#AFGMV[wm| tۮQ]ل1 qJߪʀz w,/`,e:.@vРRu(_ 2&]x8 QFQ_V"'vW19aȖ >Mk Gu?`'&&G+jLÜ͠>=6DkKeNtFU\'U:>{|G4Vt)e!n4QNQp X#>j84~q1+#T!3 }]h|&0,?|O!dhv%aZ% H9x1ie@{V7;yLC9@G;:&Rr "u8LS2;# '̥; Pgn;ӝյ)ɱ? òE[T!d=B#_UohLxSZh%tW K:q90U??dcA0 UE6Grg.F5&@ t钊9}=e%b);Ґ٧68b?%q6x㵾 /dσF9?ErqwG\QDy[ػTT wD%&t4t,*?z)H!ԦNu}`?[0C.s1 c4/'!ۑ6,;w?*/jHjg qZ'$U7 KۗhiY 'u 3Ć5Ixb6]0+bN/`oA zVkkArKbe#A:}uCfRw`[e<:挽ؠ7==C\ ul.A L?C68Nb.xP˹AɨA{JyxP{,_O`FIx+|0ȥI#mj=~bInPb2M6wEtI{1 ޔ.Q&WKJ`P,Hʗo`G;)gHL9!ߥxTO!jB8Jd6 (@M^LΛrۀW8 "=u-۵FP&rT07| dzc|=c+IC}R֭sW> G;%Qe.Uٕ ^?7GA Tm|6& Τ?< w8;FI0{I^p:%ˬ`: jY\fZs|q7.(dRIph(t H.,%!n -||}J]BfJ%eXᑥMhD5 ]ٶ64uiˑC)-FAW/|]d;*&a]GS @Mʠ Mo(k%A/Xj`_QġC0*68˜,mR1A5 )?gQ>$4t><_@B^T#4 gfP_gnE_@}0ɽvSBǼly J(8*{N)ُYvөLI0E(sWV8XyY+JنVVL:zi9mAqZ>ta2DWp@X>9w  ~3Drs|ljgv ^fBडB3Xeu `VZ! h 3vTe&jba̕]Y o٬Trlڥ+ի'#;'B\9{B\$zXA B[lB 2K0lڲ/ tٷ0KMFܨIA]s/ C49CTN,2|3vCT|~.exL\9pX5zN]k( }L,4`g͹I.xX >/ wDZY,w4aI ;sX?J>!sG$NwkeW[X픗y%xM[dS b%}* iW&! TlRKi*fenf L>h_bXȟ:Wm3pƿonvuwޟ .%IC#grlY_ KiR-|K`=슦i͔Gˉž猽Q3i] 6{ϯZ~2o#XAnȬђ\ҙ-*E(̡lxm0VEtY&r{6U>]jGB jF[v>[;sZ>3y~m05zlܾ!~A)XM9σ[s7}?F'MaML o]7]Cz#,bZ~įqY[nbXѣ(Y[ PNTH)U1@5#̹71_tу~*mR j_綠f^ЎP]֠Y+Ov7 |EQ͝,T2ht;O(td.2 ~BMb,2tpˠ=^]e]m]bYd{.P}Ju]%dnI68I,aƐC|zfܸx-' 8=4{,^MpSuUx~ 6X1SSp#S5zUW-y }S{Fp^=?>CXо\wU/dW[6qQh[Pw ݂Y4fFvȴhqMEdSuKh m!dxZ;z[`#|fvy\\7ʉH,h'maL`Vdqb9(ZZz|AavA 婗qpj| 2>Khnxdw{xFȗFj/gթwHN6= mJy( / 3c~/DƘ!}.=n)<Ȕ㼂 ?[!*.m]&W=[ʸQԍ'ݼ#ǭ > ~|kޚ8;Rn_?&M? c4=z'ecL6=Ve^s,nh"ZQryobٳó6,CyWe9!WaVYTL[E<`#|OE^쒏 e ^t1:٤Ƿp*JVk{ 𕦹Gg'0|cЂ!Kkn ,[H]? Y4v6W}g欚uRoS]>-R3Be6}T1Eğ5HEɒ_}[á63՜렬mz9m!;a ҽ蠜r]CsL)@H4W?%Js a߉ %E0_YD@caT 0nоPf#*[.~7o/7džws|s|GMcHɨ jo/[DEk*Rfu#Wj(w WE&]g. ͜s?#Dmo,>GDRޠ}e'THQC^ e.C1ےU)OwX z*>SGݛWs!1h8R6xy{Gx -S<)*W5C>B7qs:WF(UkDtGȓCs^a|5 _ E8%] 0FF=-#Ԡ*Qs$;V^IN8mJ 99Ē@}"\~6Y$[YT[Kꞟ<> TrT D{Ȫ LgúQ}# mrwfso]hjSXPf 9ѳXX@oFwm@!m~|+\V٤j1_g|fT]ݵ ۈ eYk%H>apHo]2}qpM-$5W>5վ;kӄ۲'=[˂a'Fɕ)5.HX=K.Vzx3#־ '7ݥyӆ0UTueAHܜO2!ۍv"& /ܲbw ~0?A39ʼ#(.Vh)>ܥBZnsݛ,P!r,r+[zxw_OnrP@rbur"\.N; n. |pȰyb8u;(Z璥;-BN p~F(ի(~_FڝR;9#xVA+B1(! 6 K3r 7}- |߄$9dMhee[OGVխ¦X|G u+s{M3T%_ѐ4OxkDan6 G̽:P#M_  ެ N]t5IzʟWF8vB3@Cbx^žF)T9zrW54[[R8A4[AMTe,~ E 0Z<`dT@Gwd!*f(F9{{;խrTȳn~ԮSP WDS)MF=69(hDu$ƁBvs&N=ѧ??uYopql䗖)Nl 'vrQiZ)|kzkB@{[װ6f 50a=gE#wCB)H?kT h |=j΂l ڳqdV72Ϟ,(ech:oT*#^GAV%_?O\rAA^{d:~XLm"'w{| JR[@tfti舿,K+2*nWinqJ;RBVVA~|1#ͭ뭎$J;Tl;`Y5nYҾ g<χZ!zDb$r$rOe8 rWh#=1mJUpݰ>`vG|w& b'Čv?L1DtOp%fѳޭჟ,feO*WmjJyS ،iŅ[c'A# Bs=`"IG>G{ ak`}-* ,.4WBu:zRϽ-8%Y< &^+IxWHY->~P<'ᾎuϷP:A^} }s[8kW7toi)"a-A=ݭkW(G,݂8^@ g\Uxm* O_bFۛU#> h]ޜ֛Wtj7 B-k2W5 S7z|r|mm07_q$l4x( ѱ1U'#ҴQѯ #%#k@Jj9kF0oK]RV~M|8݆tθȖ;ƷKPG~`dkdYg57MrLiD&s}M+|gy${kwiN0cxi5\IYжKI mUY浳e7$[V#yɧǤY0 +tWx>q br?%k[OAإA[dBj¸珈#Ab0^~UվqKuYt-1#CL_iŨ*uѦd̕OQ5(Ѡ7+!ѣ&%4wi=VUƆ:簢)@w.D#nKi BAֿTdVydTЏtDt:h'H7-hF|aIH+ "< J 7&g6_` ''P=kWmVK0 E&aJǗ3M8c!j(9!{eA!@`*GJ2M0 ^WXAz$Z]~@[l$-ΘW1Wq S^E/fcYQ! v1n{Y#(iE~,eut S^Ύ3\b-¶}}@̈| I2af]@+Cm\AF29)~={ObuFc}ݳ!NFlSKd*⼏UR[_/I(hipqZOfj?D2('vBiЍ3&V{""Ռc Y{nt+TӴ.:v鈆Dݹ6 /hph3A}m%Kw/U7` nG|P.;{ ;\Е?+nlR:_xW2Cy!q뀸?%;4 C}X"<1vNzy#7S=u Ep̦HnlO 9|pH~Mbgi1u%7XZ5ǡY=}/ /x~-1ӣɊd[k}YK |T~G"k9M>}czIFGndf(oʥ̽tNo羣Ωh㵢c[o@8'LUECK1r{/ןoHI-+ҳmkXaL٢ 0RTEi+pN͇h<ψm-Y?cG)J88 ݗU zۇk-bړ$6SCXkWc(QӁ;hzկ a;np eL#KXvI{1=>ffKJsՀN!&VUoȷ CDS@&GBLD4يPU2-R_|#0F|L9F3iry.W$#L%rfhn9үI0BҴ]WiQ^R$p]5)n >Ld/]c9w:_bHgv8~% H=>0홍|}pvaU:j30]<_=\D9}"vL7zycs ߡ~Nѭ( !>Dk$r o/5,rZMl-I`HPh>F?pM]Hҋ:kS2f_] Х6wxb~%?Չ/*;`d*_Uyj9 +{t: [ťs!vr|RZԘA46=䖯 x gwfrtMoP-X!$*?H۸4+̒NwJ^tPDV8d|4 ص"pPS ѯޜ/q<0CcfVm5 εH:b~e ذX3oiv]}m5&Ee{k+w)FgzzS-Ax3VH=7wW~+`GY4F-bpϔLK v \lfO2<n[jP:nnR:AU9G RK*-oF^ %YziIP1:s*zɉ oJ-?^ڥcB}ZуqtN$Iq[45|o]+ṗˌ.iRq3O  :WԼ ܄ yr9L# p_{Ʋ- }~w$7 PIaMˏ~U0Z~K7շˤ7,wp,^^]|o0x۳X .GEʼn΁~-5E~Ȁ{oҸqzGf|ڠL4<,1JH9r. Bt94ܻrK֗@_`hSu6nh 7U}1z1td \qq`rD$ENQOFRG|ḞYqً t!&pZIпcj>R!S7qsqQБR=/OH:$PM(^"9{TM %8·)g$QFrG0yՄ[_9QG2 @NIuQHK_(pЈ~% Cw6Zvq>>dH@/g¾8,/C"G5)lj~)R#*M|(sb{\%u[P;B_sYg{@A^&*mfq"tpoaߌtdo]۞Mv"k}*h1Tb."er沿ϭA-n!gxzIj29?#r8J5TDNedQ1GfjV`6iA;rnWO2ʃIHfӞ3.7azⶓ&QtiD4LU9Rz;HRM~_50rpcȞ<D|LƲR7? }.:Vnajx}XIz`^͐4U: jdSqsI /^$1(oe(޹q½B/M۫]|Q % j$vLWƗT;cXǡWUt9ɦ>}":S,m4HجhfgIoR/&],z/ъ4 HIk=.폦wS͇X[VxjS3?IA}2`D iCE 1 8eV(Hhy ?8dYvA?)-^5d QEʛd! O/He~*)#b^Q ހi@ew6GPϤ# m 8io?OP܊_ENHG4q7dLy9J6#*4TJhkmۏVXvV45T8t9;InBIC8*d^[IGQѸ+0{F0B_اѡy%8>Y Jo[&lHM^gsFYw;z/V>(z .guή ~y篅 3Bq1^wmY,zLdv=Mٛ` QR7-,K5AO5SgY/!o?ras}*a, j,)^1k.gCoBl+MOZOnp+Ny2T3!VTFUC7zhtT%b~C u"Z_jCHڊ4ICF`-'Vnx v*B%Rh\S!).d"y&=P#gP tC'GeJ⡴Ev?^ XH3?:cI2?HXk1LX/D*'\JG f"7:VX}.Ǝ[in} pьz=pX#ȋ}X'mm*ZZl#<%i*h#6`dlKI*,MO|5f)X:Kz[+oμ h %eroD7+3q#@xڷJ7ܦ 3 k tpJFW[}4/_Igɭolhz5J>"[Az~P*޽($ߚd"B&~%hϏy1&gݪCZ3ҡqt8 Q:l^,~Am`,~OH}pY–اRsH(Ph?tGa>1hk|7?ѧp .m YTroOZ\Gؗ҇Ək*5X9xSԍl}ezn WIr㒮t,=1&fPN/Hc9UL8:Kn0SV9`p!>͒F/&YO\o &TZ)ΪR1o}fYeE?̗#̓ 󷗋D9I_8fdOQP!g6 ޏ0$]p5~<{AGAgZu/ĢeX{ۿcH"I3^$-Wh`(&ɵ/n<P;A'SH6qgFk}/X-|F5yyWm4cE^oiJQ"}JQK֓glg;o8ñ33k|DldGEk(^SL_vI,;b[ yI64i=,y4O WVUӦ}oA>y%b9/`R&T2(lnH.ET&⻳;M=%{u~}U1!{?}VLxie̯n3kGwdA>h;s^Y'$ͿۜQZޠ[L9/ a^FrYM7ꙃi V%>Kz,FPC~)U#6&=0Ax鰳I7XO(󈁸pA@V]S(!TR j;`\>!^ՏwR_M+3$_%85M~\Ԯ.QƎix0_6-* aYڹ~Gʞo|X!ߝXLcy#Vn% =7!a^s@ιmo6@A[H7tH̤mcƾ! UwXrHoM q!xO_CH +>}Zjie\KdawڶP82.Dk<|oOیo,6s>,!~[|}ӫ)֧9כA0SNA1dͦIR 7n& ?H@p =O m llsg1ΊYʟlHnL{ccX0_V/}ٯҰ \*Qm'rK3oUz:l Z~vpHJMxX{bκm ފ3܎ffM[e⮞*_LVdd͗Ne;뵺xxҤ~z HA\ pe!wTO֐xh1~=oK#7YXz)fj0ЪҜ~"_ V7A|JO.P,J)ksG P{-% ns |ֺqa6>ِNJCBN=ҏs 9g()?֖(DT)bCM@Be;e\NH}ET=qq!1]#Š,;-Yo""?uWf.Pd.jZմfC3jJpG 1!XʄF/r&p\H8x^|"|ʲ5I ֔'jD3Z\CY1nY<ǯ".x_+o?,yhn[eHy<=Xã8W[cG_6I\5Xtp׉5{o/[Β9a nO'|꾰OHSY5έ6R$aIMS= :MGOJݑZ/YGaM=Cf1E!UB'm!4Z$F n/Uc6QCc \hkBs߮URdL3-##؄XA p&<#BS_V6^lOH9S>dvFeZR)Ȅ0L꾣z5 TQ𢏧RJT";#kuXj/0bf/fV0IfP↜+b`U*uIl)aA$G@z"6a hm5H|D˱@.DM3>ubqm8A&| %ZP};LҶ$׭m4Ya6>idJ4#:Go'2TKcz(I0S" \=gaKG#d(1ic:-*ٱYHoDZ8">{T(Z ~6.6[Bg`ym TOJZ9Hu'Aen|VD#鐭~2P=={{Y"wS* wR LFjK~\59Kjn>{Xp! DvD^(ۭ bU &Ŝ+'5~pGgvQ]%`A&[TP'}Sfq>$N`gO __ì9 mְFw# q Wj&/zy.ucK#xVZg9ob|-$N -R-Z̪fQfRiJ~q:A$=E1@sȬ-,wj$ɚgglIIˋZmF@QzBn/ E (XAB=q;,#^i`Z܆L8]Nt-pQjHL5ϑu2Q^z?9^k;y(+k9`i\}Lz NQaM%R#L9܇8d$T$E1;3%T ;6o\ipȟ};YH}׼=2.rZ2!H\0"mY f>i"~ X?s!Up{x6mGKۆ=&~]~C 4%*_Vs!㈅92 zz}-̘q [5wlU=G82XMqB鏤8'U9JĞ){^4fNsnc|%[;UTuFJŴkfB21oZR.ZǀT6bABn N/،Ӻ5ןW Ii);|(=J[zy=YKtp⇉ĕ|=;̾ҁg{"G _l I}G/kK>'_>zjJ{; X]}^WL?DgݓPҹh35ʺY-[?R) |*]dvtO1zJ45ý[w" tҳ,lclAPC8LcTNi5W4W%)Iصݥ8z[&&ƥheW+*jeUU-0ش^)+rS-qGJ Y:z߬ .檵%q:;||=-"}ha9 o/3I,Ӗ(#Иh(h d?$i+0s1YNGv -COց,r[ht86eYQh1,#jr8*$(uT8D<6 /+4\ v mq☝D[G)`aһ/(`f|A2RioDn.v+Բ LL9A_gUQ/N5;RW¬QְOn~>fZd-u{߁EV'p5c:)I(OG-L øޡgIpq_&Ld7p[;H@StAMc0pD^>ꪡ;J񇜇m*Ҹxʬq)Cst^G>cFDBEu+W%,‘P0>Ի e?At:]|~Rv$|`Lrb-xȸ KນOvA<XTg3Ƣ~x»`:!P=f^~na;(Th |;ak<0w^ͼ[ nz~kNt=Z?g=7'쭈/// ͝EBd'7{cF jIZ4~]9{0gL9'`aLX]Y]i*yJ0? @ѣO1 , 9jGѷeV\ALތqzwquo^bNB0/ 1>+zvB>X7᮵uf'@eDZ1Ra ag`]NdK.ې DZZ%?{m8&˘o_& #= !do:?З)]r_Gw}}Y9P`jA3/|w$! ˵߳|~1qݣީIAz pUyH6\̋i@oT% +y"꼆 _/ږ?,bMq?e?Slb\c)2:qk+8(Q%U?BCeF&JJ(h6ڬeep&ujW$AcH`5l[޴k7remL <)t#>Gϱj1įem$-tZ+gW'h8t Ni2}(V3q%,R$$+<} V/m Z@ߴ|*9mt?.^-ç&i58!,UTlE}5 !e3;Qc֏:7VHf r#AW2p=R;;b-Ȱ2NAKY[Wc:;YobWW:F+yR7gBs~u?7Po7m'W됌O&n9w~P~HVg>l}EkYkWh[r{{ N%d"6砾qE)HwdoI z̴-AԣcIv9NOW/hK@t#2zqiBQGb}%z#ec'R!>eeoy@|;-P0Uhn 㭣b]}GARU:D~y^So=A9'^Ţ/B% ݿ~WEćQ:=u IAHHUN+2-=²BhMZТ(vb)R*|D$j&S$fׯm@5Z+d ~30u`n믯); m2z+p8?ƤVgϠXW"3ɘkEK0W<@؛gmM[F"~ ^1Y!f׍bQu"tyQQ7ot)9-Aۿ,*ׂvNrA L2}.Fr4gQ) lzs/K=}b?ne*-,D6LW~YO:hDSyVvS#R~5".KԛCxVlK|U7Õ|d@9=WH[jw_V{c?$ݏ }zT_ ' w܇\N~A5ye r{3v׿#n-E.~xJ+KyqS{yQ*&>wPW`3k1kA!7[NJgNe(=Xb %Z(GB֟S(_K6"1 ѕ_21J06[x Cɔ {)Vj2]u*9 M9JTD2y6\Lyi^XB&C=!rQ*.m}_俑Tw+0NPkh wŏGZۮ' =P-O*Ui7v}6 C Ħ1JV`տ+PJGhWDĔCAF hP % ,_Y;JQ-uv[0sD_ 5l'iN?PP.N4wƌ*u0bZzoWuh:ul\mlv2j޽-۫LD"a8{g[a\ sIvq_\WPAu ?*Z8eKf= -pUFgt9$Knoq=+w (t1Ѻ)h^9叏+W^$uQ|@KolȍT*hZA{%̓G*ƛ:aE36bgtyk>9THE/c˴2gqmLjN|~xS%[M)6n t ,^М'\Z:,}AS].׏[om}]+5rC *Ba&kkߥ+=1Ʃ[˗<Es*}e8A7iz O;~Bmd4Е;CXk[YLW-1ܓO𕪒IoyIHOg$Uwq T-=rHy|1eZ>#LmHO>g.@m\V.@I:nUPoݺ} z oo@y8Oeޞ4e˴/w@>}|vCȋ/ZLx%o+(kūY @t0 sXqۅRoKNx,`jGN. #>KYnjWjIhzd?` Iʕ4R3mx7C|{=&՗4eb L'c]2aU/2y:hrOuX;l5wbj5oz)_HӕIl&I\^ʸ8-"rxs.N<3KUF[*"qz]MA,g'ͺ,'tb}j t ܆]òiH"1f72[Ty7"]/mrF&>6HfG}"sT bIdV` ZIPz0UnI8] e|^|dvpQ('yHԚtv[7b@%"T3gha~X7IsJ/H6lf&\x$15 f*:m/k`0.3K$L=U9}6}a$ T3!#Z"Em:nNefn5BeAjrSޘǐ bI=r1_;ⷥ5_l{Jt5m s$wlqV_L,j$|$鰶CVY?#o:V8)Upu2M; hJ ̑k&q cP^ГmxD*$6't?<*WtWLy.:, G6hV5С:2kCcҥef^\KIS+jo(#W;mwkM^ ?: 1OVKk#ykZWNBbx9PmHgOjۙp8v{R¬߄Ìrj}kRY G Dm|<7x7}ʬ0fڃꛡ|"AވzV_yAy.:`JCY)|PXgT>/GH Pl.=1+]a#!A>-ᬸeէˌXF(Hb%q6QT=*z7ВomKM|45UG1AyWp eg1i"\)VdޞdbX#LxԼ,)@v>[lO"ކ~^5l6FY׼g"+zueW4$'Kt!,~9L$b zA)7)D8rQ&:2ż+敽mBo yu M:ոrKu(&Ѧw>h:y/OY7GuDC?;kqf :0_~lk2əWTr *{natoDz|R"/t+o\̹@"_ڵ`sf[ʎ"` xp0~Dd{%7 MjG ƸnυjT>k=d̅ scq@&I#1Cµ!v𬢝*ӄ\yrq"O_H9FXʿpa A֖A3h\wkln3ghD+ŊD#,1nͯNj nIE<)kI$Jǚ]5'aE!_9`Kk֗=jH0K$93/Q8򷎧\d1O'VCW N /~m^է~HV)~Z$aeNS}a$XV&Ůi̬c`8f 8`'j[߯(+D7vcY1JsXb "B[k]5@eDSv}Ss7b-[Ϲڌm2CLrrm~MȜ}BdvAh[VKv;=AO2ı][וklND khz$r>Yz!ud32d'.9"i8ؿr&ͫj9 9dG3l4}7v('/RnI3 3K>D"ؿR"*>Ϧ#V'R/Fp#(1`Htg,~n"dƐJA4/m^L&"UŊiA o/aJl$I7 Q/~i[vHHa m#1Qd>.2> y]9{w'0Tݔ#҆x0=H5_.˵z;yQ~SՅ|ɢbLpMBۗsZdD'j[\Oݢd4yt9=Z_0z4s^ Z|7zz1p}jQ7[K6Ay (Qмɐn$} )/:Ϧ^}.# < 0=I.M$$C1wv] p^P﹍39ʛr%HR/)& K`^̗ޮG6XJ1'bM}h)sn#u7)z ^4K5!ؙI7YA\,̓w$}RTQet67~JLI]RƟ(Cp-\]mTƠ[Aje(ƩNlI+ %V򓙻!B:B 8'%*$~TG~4id1bb<ٺ8E[҉͜Q;3U {y "EH\39 yij!7]$^f49#`Pp0 _W(\Q \[+k:Ti+ A@ 062\|\@ (}$zy!d 4۸+sr"WQ}vy+DLyfSdI߫ѿ#G٣o4l(\ͪ~"ܗƌErb\[Urz&uYc0 + tCt`=LX|p{1H*߿Z쪉|l='9pg(pR^ FLTtSlE/;~<*}l#Ƿ}Td):$a>ٶz* Uɼd>y9q٩y'%(y39Wz{Gz_6ҏt(o.1=266)͋ -*##pjdܾ_C>Dvоmq>J&@DzuzT98q6*ydM2`ɾFi9}4s;`D;m_q1U[ڠk]6>Of[L+*T䵩ϳϑźc:wjV';Ӛjr);{@S2>3$.Vy^4њ؂]]f$iia_L@lJc3}ԿLNk=x9~-i0FJvaƆc}-]ī[!DK \Z!¡:h987!K&%]Pw}},ȿ'̉B}>7\(᯴Td= x1eq yj%  ȃiCV9\mjay_ʯ @g TDṳT{ѷx O,yiIJhFBՀ^H3l9HەH@HVC)iSrO"";$lhBƠFJuKgQeT蓑Rf=ᘢC/ һ@}}@3]/r,5MMi#SN_,'|o*drIʇ9ΑG(]Vg{qB;6 ObՠPFx}qKl[8`"/357?'V$5|تRlq-H\l[R@?'z .` B#@X1zQ?qo=t =v>ޘ"/IPљ y\ꢝ!I)dMہr)aO/4!g 9A Yu}.]~4:a$"aq篺W߷YiD\|<ɠgRLXB.∓|<[]*!_X.WIfm=0ct!Îe? {BD)1H@ۖҏ+ۇ7GqnWl֪H|"sۓJ+^R?Rn^72F8H[0lY|MfZ6-hfEi؉d|G3@_o|[Ķb49 /caj]όo ߌ/"c!İ*<6ǩF}m`YwWA痻b)=S/QEo#vupa |}<0ZrjƱe{Ó}J.&I<Լ:?_\']Cf/%S= :]eϭF'E2t" 8(Es~nG)_ v7Hm4,*4o"rcwmZX^3OJ 3Ry1,`Ux3 >'BIcSl' pNFdH62mnfKisK~׫Yx71##(Tb݆9VgE3hznM&=Ue@D?ɳ-zuk sr+)\&āRI3"#=Wi6 8Zw}BfsI4!!%\DʸmsuҒ fGBh JФ_ :rs~d#I]&r^#[.$=A wS?#H~l_;C&\=1YIes?! ! ْ(.ph,/rhsszO~Ͼ9[f&9!uH`e+II^¸_-Luԃs*]bza8n~r/k#cF3q'\TOb€0NxW p\ݼlEz G"0R0>,H x_ăe=rIr].fH ׎OX~l m#y6^Qq"L.Q+.2S'9ª1M!6!\&rX`G:E<Ҩ.NR_.~lAQǵR% mơf` 3|"^ }d5!4Tc1b]#^[#7f&\C"Һ_¹e9}Kx*O'MII_{ukoFh %=FNGnATb5VqKܹ[(f JV3ű뇼i j._x08[T7EXi?^(z慠Cz̎]9)dk3m߄$t<>)8%> 0*h-BT&"z\@04 f=ɝ(xu?Tۋ~#9YAD *ۡ4@Ӽ@{9[y*?f)MT Gr5Rxwm*4IsegF_=\L6lԷ"i0ygTXV[XaF@ܩqϼس ]Tn7 ԝepxoL0WT0jZWŊ$=\L Y,2e[ZnY$Xu5e7^m}hDS~9DZF H-0;xf!x1cm`:%ggpf![*[̂]xqnR?- A^R5Y zz^,kUF0RqCf!$ T5e k& gЄ+0\zûۋ6ݾ)+BGCPeyܽ'gW`?:uw*b˹W8Hpcrz}Rxdi<tVUzT>},,M_~xv(H |/k7+{1h g5׉f+6]`HoF3 oC{Ca1i=?V_|4+rfʩC',SNaUfQiFbliM2< ;.үR:T6i ؿ.xc߸;nlus.:Q]L\L#p#rѴwM:vA(e\9.:TKW>  kڿ]HR |Bxszc .ʢN\"syԲF i 8{~ߡF.DCz Kt1Z{Zjm?iX=y|,ff=q͝At [o= YsÈp;9€8Uv3W4Ɵk@ͭQ}^ >@y]0KZ'$-ͳ ݡl*;"@*k# s}{sE;'ߎWRD˦۬3:RA|4 ؏~GS]'QW`UE 9_Oi$09k3%aoU!'iJ]ƉJ5q>z :c*~|qbȬ]W~+iڅ+W=8IA6]汾}uZ פ0V4Vk%fLy2B;S"7;-MEuڊ&WNOT8s'#g{{h~3E*+$G*D_!'#V= }Ul$4L{PO7hd$v rPC{^s*CҊxRFbs6q^=1`em1Z-.]W74sP"a{Iާ47@↯kZ*,˥"<k u1}͞;@]w?%}c98G!,˔,gtq~[%# 2(c^4ի`Ϩ{10irFǬcj=f7VyJ^G^yqZ:sòםn67Ƶ$~*T֛[(:%~8V0~LDwZ4p{9CFX27衟c_N{ K4҃ҽ7uyʮ Z_ )Qg@h>K>iڕ}qH?x~乮1&b4Q!Ѭ]N{ | h]̔~F5 >6˾CɝL:Y/vS6^%gΎz K[ekCOSm!TTU?kAw4 % 9̯hK?A@_˹Xᇌ,>tCLGFWÌGbo 3ww Al|(y-zZNXp%mHh0tEK@twR7t![; -R, ڸ4Sʪ~C mJmy'$Re%(G4@,x`v K.J>C)θ#V_ SHKJCm|8OMǯ2|c=zPAs?\:W⪫L+ɳes _fs8J"o^}ۗh,{tfXXѝ㭖Z> wq{x<"x9,K DgV OcVbNڵ0=}/C𜯍7KXRUi'C" ܦ^&΂klnS@iGJjN;tѻ4j>!߼9jcIm'MW)ilrΦPUMw\at^sn=(u׃W7! +c8Уkl@|6V(.9ƿ~iئl]I93+zFHWUQΕ\&(؂`{ О? gign 'Wz~FE ?Db D9-KbUqR};/@#M].~Wz>zA"۱Ad졮痴- 1)pDR^nHѻYn.ISb%鋯! ƫ7fBiB2)M$BJ1 u{;r:A C@W#Ý~uY?oUc9=5FT jwTLw_Iyg<_U +G *++sMgs.͌N<(qM;jݧzA[hZc}+TDqccш -GiRd!H>Vw=O88NR@>!kaRHTJj]#9" KGG3cl>Q[vV Km/x-ں'龖>XUm?!M?FVRtH~Bazz-@H%%{c RAR֯;W}YkIRنiz,4J lC G?aMQdK;+- q ~"P 򊚫* uL]X2Ùǒ~uum{iJ`Y[sGc)TRy(e#FȰ0o4tqȤ/BaEWOAV]}h4>h%laQ/%!y[A7T4߆+6Ywn8(b{2e+2{ء*vH6ٞU#?8PG |By%#  /I Cle&wA)VyS$#TJs_*o(O׾G4TήxӒ7{MLWh>j jJQn[&I T5gjn`-.P?"R[|V?,oצS _x';Q^tN27n+ƛtTd߁zQ7W4Fe\B;%N7]rOV`^]huE28c:1Yd@Eq FbqD@g|R"QEtIj[mmUͫ(XG}c2!60c '=+}QR&5ZPjڜ Ùӷֿ%/È3;+:6~5>s2 ͝i7_K8s1]x;P2Քnj;QE0DYnqcMό#so2O42Tsj%] vc)G_Bfnp-ֆWu Nhyk"t?@}l,1YzXuɣֿo¼>#XmCG8h{ 2R#m StVw0Q?Qz|\, ]᮵[ ?oAf9L!FTїNٞ7\!/gbzLcã$ŏȧ/xIG}pIhik{nns+x! ,jѶm 3;6Tn<@@txD2(2 s@_J]F:䗺,^3K:A:Y h/TpFy5i_{^!"x$ZH 8Wx8J4R¡#Rԅ[v86 |%92o]CA%,G]&EFF Xb>ojZm @ V&&.\y ߴG9莞~x sKbo!(%|.̌3bedލ^c?t`e l̂joʒn`yGERV+LO<ȷbdllpR֭Ji], - k#:qoEgG *a%d-<cF oh^h4M[ XR[$T 9 B(R½=3ц] 49|Y t6yo^*80)R V4"4R{Ly^\($Åx=,pnykJْ{zb1BhNɀSRSf?B` =2C؇ʒJ`:#K aϓc罸 TH{] V.aWTD k 6]guDLn>鋀XeYF)̙^güYŇùyGlEjZ -Ș/zQ Vwd$ռ+6^0@pn7C*`ݿ5ݥvHg/5KoM]ÑsUAGDլ-))'mـi'gsr{MY{h#unS/ % 1b­~U@=HUFO#y%݀+DM ;8r~k*K-"ÿp v e sI"J}<՛)cCLY$j$ lt \&}#/Hv *huGܱ}\GwYCp\8.[}` 峬 ,[ -,zI6~~g.|Ϣ5N״AzK@UwWM%!rCbʊB%[h&&E[7VK|(E*U͵"4 |kTJG)Yc3`%>h"IiF%ĴÔF Vrm]2`_P"*T''9GWIQK"{J>oGƿtXZFVw򏢫g6)p8_ 9:>Okڟ9bx'Ӣ7-WX0BhJHë" J]O?*)[Fվ+DVj 3[wxˌE>!N5"gbu;vc& Tǯo lWK{̖e>*|Jw?z d !Iي 7>,FνoQl a+XݟG g(AzfbJJf6Y {uwJ28 ^bO䃝3Sր/r.}ͣ JtK z]a dͮ˕coB#9`s#95҈Q@"@/d-!pc-lJT%BHm; eXK9hݩg4irOPn|?CG&ВEFnHcv\ۇvĀhJdXKԡPc 3kT+s/d&/LWq ʿN+KWұ1oa:큾'ɴ"L ^cUOh-nR~eMPieEto|eD/@%S-[Œ7V_1 Weg:mJ}urŔ/5 >PJ|7ߺ}A 3cSr)邒!iB}W 񔠖ٔ+GJ5 p'n;B֣J6c✧V쭺qMRlO~ |6̌PCgGFTH*|M3PM0VAq~ڛnx}|xM-ɭg^/+PҔ K69鋙%{Z_:o{x0]p(K2J~7AA?jA.b¡&o|2?a>0TE JtE([`(V&8R1SScM!gw7DQxN191Xuy~6Ge#:륐L0q$_o/WrflfFTrclC.R~[8T=:8m~ǠDZ4PRؑ#=[N!Lx!J)^!BF׀Ǒ 5ZwA5 ҁ;(Ľ2qi* 6]oxSu+?Q' -=3 jK=mRJ"\ձDDdQ JeYr@+]#ѫ2;U}#ϯHL}-; eYMF](4I2:T-qe'&"X@A;b%+[u#L`q%'Wܫ',ES3ĔW#P;Xb)(4 iY2pĚ!a ن,/ GT݅u .Cb{!{/ s^k\]G*K/K87sYuM=h!ݴ'o6uv28;46\uf] D6Wy]xye@Z R w.9#NXA~~ z L fɽ:Tr?:欯,?{/>\U_)jvf 3Xh:ݵױS,/h;5aԬo:ue^wasx+߀b??"C^\;DQbf=s[*Lޥ@_ob3sXfywKWփSb{Ͼ>~qEKm✤X3'-l^&Կ|>ZpG+Vk`քnOǔm'U2KA< MC|PA*MRJ$5)\4V.w91#R-@3\uͺׄDv]ޜgjuxMWf">^i0B,!_t`KdCR/Vf[ZP3!nofJ%}Fִ6quRdC=ݢCB І]J>=+Nd7HN+ ,5 lnm )k~sQ=0Ͳ Yo)l@9HPʖ:rK]ԲrMU^fX?6xi!h8}KH~rsHQv}qýR}YAIDfEa:Fb 2b"-P?#BLB ⬤WAֱU='.(J@cHAZj˹BnG)gU Ň[ދ6A;J n",-p6ixeO:ZQy5ț&%#~5{Trھ0) \;fŅp 1b=p`>k-iSvU ˬDΔ }KRZ G}Eȳ!"uW" $_nHrќ$f#=%@h+NӤGJ-_jA!`;GGJ!ZkYP Ĩyu+$͛{'/wG2u_ NZi5q74Q|ŸJm@# 正EN*Xzb&5LԔm0W7!;j^Nnms2e,)R|2#9?qQa_,iآuj 3kxIі@jh^{)Y A1 I~͎~P;_ȫӭ)#=G9.`5zhWva}lw=IklN"+N if~hԸq]Pz"JXYA5)}u+=KvT_Z@ec \'w/8W[Ǎ,<i2mbYń{ wsWU!}SYJvߦ֗|؏Vij( U94䇇Td&6>xF zfz4 @3&^N^z0rtFz/u0zIKL_>P ࣪bO:fwJ_;5I0t_'\f/xf+I-Y ui!DlmFFsKz(X.LJy\]̠U$ 7#*Z ނ"r!|F]+7)VokH! rk,[}7؏޺`|Yw׫&X mq!)8X8J__U;ms]w{S"^KNK#"ۨfy\x~&!- N3<A.@Bu~;wtѧf(>|@kΐ;3z8Ǖ/4Y$"KO&}\3=/ěwAQEЈǍHa5[+օXYfGk1HC"%!eQ|s] 7mZѠFu\఩Puv^I=2A@k\ؐVOݩ-WGC!Q5YB (銇\bEY Gdd {/ /K67tϐxnwnԫ;1 wcz-Ӵpb|K<+ A_F 󟳎^K٧u`';ʊq3qGJvam(+ȝ VcܠAWg{KVdqX !y%RS~zZN^!6Nє( TpGhWao=H ʹ#&3{FY2UD/ + 3Rv-~P$QC]E?&:d-uWV?iYΞ/f sp1ͯyٕn*ҝkJf^]..+M sBQ؎ET3eTyZe#6UbG)֖,9R-vQY`3 d+uq`FV8JĈ] Nݔև`L-6K1jZw!mIێYI63j=53#^Q̬NHXOHڀkE=uE*x;Br(FyAmʅ#ǡo $]9=1 /T[$q/iLS❈8Mɐ33svt -5Y 0."lH%"}#Y3DHd˷KgJ0˾>DžίCEpzV)( |-dl݁G.zgyZPF K r8e0\i=CgB=O鬡]NLlP/v2Gj-- \ؒ9i,(C|=4S0'.oIc-Ԥsp_7\bއ:qcBև{]4n)ι8y7w{wt@[X~IqMmj0C׈VJlh<†XZ+KDؤ`N)EW+o$ΦMw3]Ts$E{:L[_>޻3č s@]?Yɛ7W(AARPgSBHܴb'l\)36KA|IBQW>%3%o$T܏Ʀ&:zNW~l+bI'cnHZp^h,F=}zJË Y0J5?% T,޿Ÿ? k Z'7IBXԁ^X7>LBIuhsPH>Ƞ,~/6[UQc&X}[T>.)JmR9R7e>6ӔPm@T0kt>%)W[ sz@w65en~[JR_DQ L1Kxٳ_h~u-80HƉ rPCO^l3yvʵ0gct"}O0LC5 *G857>[{ YI fcd3SrӐD@V6aZ in0 dMb艸ܩ,is&sдVbwQU?gH&Pщ5xBL%}( ftwE=p>ent9|mYLfѝ>$9}00,otG}/R,\Amț-J4d,"|ݜDZWX:(3*+KW!G#_:@ft#9dQ>Rִo`9JVZ[ܔlT6llF~aG yY2Ơ'ߘ (iV!@w+Vo2-`̰t1߻`Kɯl"Rkv X G}%Vk`ݷdԎNY#%OL()s7vf"N8ڵ_H Kk{D,^tݥ 3V0G\{\|~oc+/b ]^HQm#Ge3-;<З33FG,f{w[~M>joWV9utcg9D+Ú=*ysxn5C74ǓJ;~ڱ HƶkXۗ~:v/,-g K5{[z]3:.-BJÒmqqe_G@fZ2 iU_إ·6V]d rl.(7$1,A5Hky1hD̯ _Lyqi oSNrM_Y$]1JƻQ>& 2i0hO&p>\t@ەwϷEayo)r O*zM ]dY˨5OVe%2 n9i{X;]kSDlmXb1+%]at7 i|Wqy~y-8$xmCF`URmvYD/!6a 3|>ԍ)_UɐA&ů,J &a#n+gL k c| %QNuGRԥK:h֒h1 j,B["]t^yo\2kzgѰ&|n|]Ry$sz%eܻ A6eP2,zRL`w$ u Z-p+ PEoǀO4vV_а/^ncޠD 6%qnajMRK OՅhP-jGq1rˇTfB lcܵN\'7)">#Jz#jE8*!V+V*C K{-'imDD't\d_+Xz]QsUw2C Xt"n,h5V9!SS1gg2B;'o֨(%Cboۑ s( Џ~0 *AExj.V5a=VrP0o> X8krK0u0ܽvR}UvFEzzV,C,7[hk&qAcMفFdؿ#.Y3ou-˞mo,q3#Mʺ6TmVϒNv; 66O460gMƍ}K)&8@]>\3&qb49q\! [+#W禚cCkNF=7z`g%7V p<xMغ~0tBB:C.DNk+ŗdCEkʩPf0$A [`(oGx(K6zjgSTJ opK>qH=sZx<οm/]_?-( 4Q#3?`@dtkfޓUh[A :{{'E~ Y4LGd#"轍3DB&ǧ@=DJ- "Wmk9AY!KOzDwML$&ڪGj(p\#&&` #0 D5N1/#eW5}Եe> IJ.h= ' MT97UVQҟOw0W6giJ_&jpXnbظӞR۳;ob4SJ`p[E!{V`8t7",S2n,?NqS7n4ݷN)V!-IơZˌGzV?vLMzٗȺcƈ#iKjl-?+d&yyH^֙> O'}T#zOiϚ9UvJ;9$2lgt?P*ZEU+*X,ms;- 33L媦;Ϫe>~[NUU?Vd \Qug͔O)zՒ"x.Ȼ/x0< :4&"6 Sj" &sb9 r_bC^a2IH|е9_IMv,vcVdmj0M Vh%DXy/6+qOGnOqX}$*`oDz'리"4,x KYǒ U1,sP#D5lt>iJGOI6)˭ؽs&ᖎpdrw੮ H{Y=zs([g2y>P|N#葊GP HLE6RIG" k|.-c 'Nm/D;!:ˏH RsfzyExEAPlPPY1-0 h5L^Bt< FD@ػqxR 5}^mEd _f!e%8X6mJA޽"VM|)IUo+dʚf:Za#~5C̣\Geu܉7 w|ΫAϕ .e7z7PxL*@,XՂ:Vg7eUUdx/G3Gl(j=aVm=_3 ?çCԓr^ѬvG,^%[?]^@wzzvn$(6h<{ <-C?9geh3™ E>_ϟZxdGl1TU v-G̹(>^LX2Im1o__}9L0>lRN{x 0y2Ad JJN1eY[t=48AH Gyׯ13xt*J빛iF!J]@5V۸M^6󫬴$COVDF?~T/g8呖'Qs5TpvaV_l2C(kJfy+DYG"RYpd,Z؜՚6˅3gT Q%f5n, o2[1Ð9sglvyW c{M,_k3LdOI~vRYVӸ <>T\c[;!4]:$GqF_"1LHԦXhDMd_n]Qt8N$rK|]Dׯ%1&RJzH?S >$;<Ve1:S&^2fTt<5EȍgOA}ެKUH8$}lroNm ĨBZ3!V||lW8:΂̍SFHߖ`?,hI=*ziɣ?@9E0 '߷7ʥTl^ZtM=bXA}f;,M۷"w%]&ĝaΌQzs @,'Ӆ Eҫb䁵JƄԿ`"-yr%H*v$1})Z 3e42,K*f;ga_($BL^❅Ɩ(O ZDQ,-._c3wh6&cBgx'W> lcy/vz^@UmʼP3Z_[u0~yі42tx9G0c(u/[ :$СIcJ Y *fj;OacdlU^C'rLo`[T ̘ Lr㉿.#y{Kor];04ԃG8)ʊCLAP+0;}ᣐ"h@Ʋ ˃L:h}GsI KwN} $ZgpLt쳂+cKg<fmwojwCϏDd,iǿKB %.|h[=Rq~wsj]UU 6Wg.Iac˒|q:d_/^Pb-t6 96Sv ѢwXTzz?OQM^d34,׫Tc nX6<ʱ-"XRؓɠΐXa|b@2#^&7I]ۃ ∫91o =ݙO_^(#vQ|OF_?}P>#ou|4̚7l CF r:h;f'*pde%z[?G/qVxt u[Sa~gRMT%u$ 6eԤh lh$ocHF߮m1!mKY yTD-N,&UI_.xrৗOhsD~s{ 4`gAEN<>{5gHpB=ɩӏʨq돓_\eјpj(N߼?bNDLvf\Vv|5cwl!&g~&(0ї=t:ԉ/&: MޅJayrō1ZfԂxlz}>ԍҌ|DGD6K [ A9,5<&X}uRܿOť]@+ lLz,V(fvG6Lf!Ѡ͛h%+`ų5TuAM;'iҹJβ/MfҔEC,4z\su~o+/ F4S1sݜ&gjq2'(5iE)Wt[#mS < tTԋup1ݲh2(U1_s7<ֿ9_\ MrFXCtWhKщ-Z%x53SޤZOp4yi!n?PM/F.I.^!R;QXbl-YJL3ݫJ=5meBs8w3yLaik[Z8KźD<aG;5{i=r#mL[׸H.JwIC d^>" 7_F-u ],R<Ɇ~rFuvPԂD #cW7$f^VdIWZֆ5widbȽ6(2( nZ09 h(r#ڿ4-f@|^;.j݊Szt-! u4wm2*ϻXi:CocR4_cITHՅV3C$}X [d&6ߵ) F/] 7 GkcIG {$omLlovt,kiF$gsv!f[c?x |GU֢ۡYƘ+"/!lAPyőkFhgЄĪ` < NFn,5y% Y' nvҗ If@;ӞDtcR:Ǔɴ*tuiJd$iY_1/;7fc65;RimL*:u {.& oDaIaUKKO3(ڿ|IJQqD("xs=C+(o64RsŹEd]l|7wCisM7?*%rfb+AVuMKJe@ lAї;uڕ}ivq0g5 hfU^'@Pu1#y) ^Wti p[lU\ǹ1C'3K1N6ԻĐ[Kڹ7İBHVYfoM[pջ}U:OOA֩D'ԯt 3r%$xO2υ~4aP/':+mr$W]Ei(-VGՂ8`p},z_p^)TS*]۶z↑k] AJ*#NPYB/ M'6żT7 :o3lG0xRz+'^1S3uk&ijq%(J~hr&KНXÐK] s>?C{)+[ِeS>+Lw+{~',ן3poP&ݯxD7&)0aԬZO&@7qm~|[8I8 ?&b[O3q(\G [*[W3Suq#BI2o¸4pN5_%7o裚~& خTUxbwB!⬓`MgFun;3D,X0}pj2߼"oe)r})oŠV88|oq|}Ǚ64{LPo*ͷH}ց9 l׶9Gu{@敗TaO1[j c ~?>»՗oxfnOԁ3;MtZ2K}r=exH`>*SR)rd>2;Y `ڵ|^yb &c蔭5a)΃xEpsP>!3UxJ'@:XE9j׽6.w%G>:ҧlm֐X>|Pԇh+HEvblXd,Fh*bSHs`iU͸9&&ϽWFiв g gݫ'X$K!g_%ힻKLxB]݂~g):${ʨPN QEm_^dT]NIH}Ww9xorA]|ZGBnEM%7P( ~maz m/m;>`ʐ"Rqu ]É[.%i$tYIe 0VQ }iM' X}ڳ-_j82Fv5RTnlSQKvmpÏ3A6J[zlrMsTh[|zzD\5D!1I\)dЛ\c:I=i(f0j|j+}[VJ<hwZ}WA)wTXh`(~[a{a\]cWT/=:SylxARǧ-Q_Vo;*Aʚz~=ŝz[^[}CJ=x5qD?Ց* h`IgLs6}sH%O74}D%tAS(~K:7w6L_h|:BLaжnSBAV,ς r*K$D[~].uzDI}EZ@h?}:_$5'Hnz8v>!pl4?.vSPzb b}YC$Z_Ի7t|}XiШ A 4v+nX4g km-aIf;թ@G#7D[x zaAt!a7I DjtW߆C4TwnaQhntc|іvhy91 ǭek@ߚ7c40\cB]#Q=4RnҞ{A`H^j"Dž;JzW/VkIĬ\/ 0M<Tv< :^350a+zn]"{ d SF?@' =@Lص*M A>tǶLM% u,{C%lRv8 })I2JXn9"Alt'WvG,_ GȚћ>]qYt0شm/ V$Q'ecqfxco[ GqjSIPXgEL㖯(wz-\InvJk]dj Md'OX "Oz6}!{L#_>4iX3J6jN.-1fo3!pc,ʻf;M"mS̑lta,(6)"[WOM2c)&w7>Jx5!K Z3H6re@T,&ןVD {lD'p;mvKiYXh^Rrc,4CfXuG*% wjA4mZ|@ĸ.˷$_㾾_JhV: +Z95^|~n:.ƒ\\ѳ7,'H R>>HzXhc₡$:^V\q^_}&Cv,M@+ gѶ^ _ZgМn\=W'Jz$f UA:[v7foP1UJnn:]to.N>S"?~kwbZZc Nwo Ma֧ڍh,?PyÏif8btfqI G|zcO\4Z(6|uh .YnHs+[p%waH]KX $pwS&7 D IaQfBfYq;H'叫HYnRM2y_Pcdz\~~loJD˰@#@gە/ʜ6΃ׇx{y D#"E&ISXIA6+&[Ev'GV3 {m#.`G zEuƟHaI6=Dحi(qSn$IQsҋ@ "YDtNKNMß?)X{? fW8$dݥO cE ` sߟeħh*߿ȸ*+(=M(0#gh8~3Q\/SvwFr0D=mFc|Y;ߣ%Dg*]UNROAdC}%/ Ed78|'KX}YgCn↝<q6p{XrƋ$df1J{O}D gb4vY*8ϳ3?2 xY$SaP;LF6v)^Z0%"Mftl1oqz{0`_?ίݽai~[}8f\I>ћ(49<)2)fo\)pUަ#ODkt-J3t]G`D⫈]BG+ !@:x#EJ1>fσm_'c_4s -^V'L%;,I8=&6C;ʧ"nDAHkA㲍GS32wF hv T>s"dﱇ?Hhfb6߇_gcVhb?AޥrVkI)_Ƶ4/_ȸeKW<@v6c- h-0}xhmXJdc#,:򷚩/:R`],[M[܏C ڣbUِqݥimR}`bBZWr1"=4 (jȯĮ?mSW+EfPܗlk" -RGDq;#c$j+a)軔_ZJsM][Χ _8'~0P'o|6*/ҧM^,36 h|o9)[/ h~7/4_a:8<샏ei\`䆦 E rP`/BlÉ5f'r~!PebF_nВH@ߨ\ŝpB781&ky]n'8]τm} hgA4qz~jNֳ<_Eҋǐ,|7wV{0doBL9 ֨Għ7!=fھO_ݐ&b|{ TTùﹳʂp$xՁ)_+E$EYVCPYԮ7{Yr?uPG(}>4n,˙$!.C?C8 z)m96އ ]r.?eUvIY:,* a9c7dialHCg+Ry&p#πoO><{}Q͜sNX6>D0E)u;7ɿa<ׇ)wuUͨa-bv <(ift +o`OXڏ>mR2SS<Kb<Qv%=L"h- QIU/3q\qG֠,'_owUouFc f˦^T/j"5.Eԕt3hHD&Z-5|>6XQW{~'CMRo5 ]uv1s"`ZwsY|ຂ[B ϋ淘SƁՒQg4IStmMGпTò}aA\ukA[1RXd S%ggGE~v>3Ilj Xjt]G Yb:‚DL=Н3e,M.]6BS|b$ dsj| ][Bh2]rimQޮXWuT:{+?`"DCT Y81 4]r1|>Hm-1kKҁRf/L pG:[VG0Tj-gl298UQZg!-ܮodG]*T|'Wwa?"+F~K:kí=t䍥cSjeNFƆHj}g[FOw@z4. BPC^EbpdFm|.rVɫA3OIk{%7gX@rGK}^^ z_2|olVYWܰ8 7> ΋L33_~ ͷ0Ksoψ>/眓y?ŷXahҿCٯF`t|"wh@TOC,+teC$?y\f͍/׷wca^iuΥC 컵~vqtyĒk_ٛ[_ʦ7d2 JdRJZN7 ʜAe(i4PP'M>7[XOx['9## 0%xm&Ո =@*S_M%$OCԓ4وD1?;RpE&(٤/=zc&\nηFre }I6Y&؍l/MM@M`,?ƔslizB7h. y˰9ȖIij\sq&. ۞3TLэn2$pȬCyby%X0\"P~y*u=HQ|ve~9UQj"9㊼wr+5Ҥ wg`.:QtMKY .(i%bQ n/j(,= QA5 㠵D 'd_l&9QH |zwkPMꃃ~@@8 d]l6j{-fx@Esaz dP?yǡܯD4o7}rR t[62$[Rݤ NWe~",Kč@? w7/$VP$'F{3cLH]f뇑}=ڋמpB8YH Bx)xlR>vȆ]Ch#bWWNF1kOYrPʩ=!xqq w/[[]G1}NE;[++/;=U y/^D, Y3}{|'2 FǣKRq=6=^{,v/Vߤh_*gH/4z7h!hj_4K=!v:kNZ"*ΞE1Fr|XRLNV̻Ҿc멡`*QbH |[~k"ןNW\-OI<+yܳ7LqN/s Bp"7ӶrM}پ㾺";v/Z#=xH@<|˾_.! 7sɰ4 Niv4޴><Ț$f0;#ΉCQ5BIuQu%KY6e(˹ovP !`^:xJ;%cGr0I'k{z f[ыb P!`vEOT%:WY7whxcdg]bx*^͜[_944)R* P)5ad >T&s2תqaQ;{?e7ZMޢh@o?!_U=}_L)ݟ1W k.-9oKV&G~l1xK9 $ld}0p׆y_j>s[}K8(9 MP0C2m {lzwO?$ٷfDOX+l#e'j[B<;7S$5O=ZDEF k%˶N dN-3Ќ7/P'ÿ}VY 0dc!8"0i@)yV|OB#~;N2[c.o#s382x=\eL yƋ[B֫!{(`(-%";ˀ̋ +P})xทj#Uj v 65Q8EY-Ky_k>YЭQXS`2K:IX~̕io=2GV1-nqx]oA=]9>)vO絟./UNWt|equڰ,9T#B=D}φgg0vA|! n{=`S>Bp459j|xHVvsqXQC+ɯ_ %IYH!v"zͷ9CH0׈kK"$Ieo1LYkP0Fv>6iqHJ|?j$5r>#nޤyWnG/czhD+m++~EAyN0V{Va<2Q} 3Y;B?.:¸bsML=<~PZZf @&f>l틝_OEL>˫5! _}1{:@b@bނ oﳺ;~ٿC:/A_*ӣB @dsEk?6mz5/Q~˗`͏?5u}{fAts%]NjCîGYg󋁅Lup5`lPִgRl 4fD^ƊUml@NN; fTh7^@KJ84r=w%r|$/S8[i &o6`us)e3y3ӎI8b߀*~!l)I[vc٘zT<K!IA8 /Y@ŷE`&Wamʑ.JZ8 d1[ -?%T}L;L6~z5+D-oRY&;\ՌEwF^fWSZ;gDoE{-ʗ{u$A?[h)` ?KXȬoa>6:1OC6צ{ DG93:ƫF\ņT6૫\| rmGpue#|g چ||Ε%ӳQ@}o 4u's:A{=w Z5DH@o.$&TnafֱC,.{TV<[Kpq|#Fn%4̷#:=uxXBedK ;B~\%$fA1ر;ULl}޵<ն+5STI>X$)A| v{6:bM$ D :X \P$x'RagJIΏ 'Dcsf&6=8 Sy7sd U5q#$R! [^v7CG{\⋾C`~%q:O2*CץGvFbH#Q?i%tpT?glq8 SO4/0:Yos~;?VVR[8^V V qEh¡=:[ drOZN 3#u;6ҷ`w1@nlhݘ;~7-zĿu?38[RxH[-;t2%]9 1+կ6g>KKpӕ_Cp6AV\Vx?t t>o3Uee~l+'@MK5~ղ휁|f .ixs$6dQ2?"z|٘D[!(842=_!=+s}v [}'_ۡe!^ͱb3X6+cѶ=(q'q OA5=u77K.q~PeՌ,pYC\+wPjs(tRW [*nT Bc13W$55:$1 E+V}aM{ήI"M> X88 # 5[Jb5ſ2 uъ#J6fr__g}{ιC߼=%sS DD]Ǒ[}vQѮ%)5:ݒmIzL+/A5sT#ڶnwY,$ޒy.5*.cq}g˄P0J/$u7AeRMFJ|t f0I]FCE1ZЌy up+h>$ڔO,N$9^e,_}#4ewOf4&\%DIO`SMCZGeVeϴ-'^$_NcL]chjqOnk/MtfQ c5>uBG2smV0=E϶堈'7HV02e.~ B 0\P78Z9i~kj!vw-tҙS-Ҭ\0G:P5a1–s13Qmq)_l_/b_`vWnF0S Ma^8 zkcLEIƙl;Љ#E[!`o U |uFnnaAj,2s6oDTZ+ރ]uÀ&SQ (E1kq]%e,\ikhe{o#Q+u}(c[^)j\.矷{FYzjdof$[l{c-"ӨrIgC}$) WU|(,툛_w=LYˉV5Uv]wY[*PRQT' XY \Y̌&@LYe[q(]ڢػt-џ5;`;~ d9E%W[574غ`ߟՂ2Ϡ5 ?eHu5\ӢؘhhX#1UΗ"TCjHK2G&cf}uc=vs^ _Z:xʳ(@YS=J_/.tN\USٵf*VѲi޵s  ?gOENXRiLͦo2Z'KZyu-p^6x CRzU+ق>=6W -o>?fiYwp G0 k{VÉ s22k#qUk&-^;ĭg$-h#@_-R@\bw3WtF⌆3&vScE">f5ټ#BݡŭI6wnsZ.qClrVלþ$w  Y!f{]-˲x L5e+A@d?\ԘoFXWpnFv]ڠuFcce'Fe.N8tzh=YۯVIDrVVޙ:ӵf[ŭؽUPMvּ튽1dI3>-~%ef fW6-03oYn֋5dE\;w3ltߑG_Uem\!G(fC+%E 4w-au|;׈Wq} 'xREuREYֻݫ7vțƫy$h$%޼_ӌe֪T[%U4 CR^J.:3g2jE+͛n-l^*dXKՂQPA-J2l&m=ؗn2HΌ ~91Xvur퓌]uKizUI㪩&Xc斻lzqm瀖 ų_,T&Vk3+Uh讛v1 )fnva'3KW9vbնrv[UXGʢJlO| K3֠*HQxv{n4Djɥ4{qݬx>dlk]Wz!k'a9Lcu-JLh(no'C!<7 sgШ&B0cKhZ7 xgب:#ReY]nUm,Ub9=*b]ipt@?(y*]c<۟gՙ5=7Y֭j?Ә[;sgYv"iAve9]={`s*φs%{=Yl KzxĚbZj "NW4YIFƪ7yohUˬYN)p5cl.ƞ U׌{~\ J1eR1-MtzXѶKԲNJ Vrhw-g幞ߣCss|Z4H5Éym53ӋbGknҾ 347@`h>F 5OLg7[=9_6Π4۱ռthOРoJv乻lͥ&hW rӜEq{ͺuΓ-GiKb|I%r +L*GFΘzO7t7[ZvX{? B&?klsIe97 - $s@ZFc] 2^W lwh ReR K%ŴЗN/}b.]N s2}Ӡ0(+}peچf]}dg^Q$}_,o{K]?=ÿ-#:CP"_?`ѕ[t'Pȅj׍{~~џ0@Ok Lp 15EAEqNJXe]. (eT(T,1mxұttHlM\frld発D|op|G)cc9@cC(wy+x#]F} T'Ǟ {t~b;B!*C_ȴ,p>q=syuy 0O}s۷/ g '_U %D}N C!+7$1<u%>2l~pp)|;Zʢ"݌V5"~Q,Pg$PTen4J;m}+T˘7 +^nOnmI2 7&Nt(ҭ_;\vKn:UAHƷO+W9LH{>߯<T?<Qų#v\ZzVjQ`Xu EUTP 0"c+½99.8JVt]րZ]Y#FG32hc{<'Xqxa#=]ss阴Yuuo-XŃ,.ITY?p59GpEց薻׮+XހኯSBt,[ӆaD.(Nh{5284\\c~֗.o_|w{qvF/| 椠~ OyٍY쬤)t_(İrGz*sF : YxFWt_bCL»rpShЬkx"9rZQǝ@#7iYA>6jq{; ]M*r= =X :-I&^E7_8t96<}y%~箫N52LSHP rUT8B`p# G F VE5%W%p4 %PX%bQ_D0-(֨F4Q a(G%T,(͏.~,>}nI&\߲m]zqb`\-y3\>a8 7=*j Ȳ" \ H`2V3p!#_C9d$d$`E,8T4>NeEE ,:hav%3{5_XTtnFU$B@(׈*0Yh)0K z)$xhD<PS]>w+p{ܔD5- &/%)DdUC "5BD}7'a;"yoL][žടZ=UOt:c)5d;Jv]-~~D)үFL=nބ*?fO<8߷߃GbeP*A%/'e:1̩L"Q.Rp-JGxQ}f DT>rIMC*(p8V't3~OJXAte9@UHh zFX'CU$qĢc 40E*a2$&iDS7JHl||-@X I r à\9 A[|b`8"*cĈ@!yBE* < aЏQ\́S V CJ:9 x z~>T`Á22UIU/@J9&&jKrX1ۋG NMpu>%-t ^λLPE\k pY 6(|jfiFMo dWEt +?"@4Jp=E< zCk+`5Ւ)ڭZ#G-5+ S} JQऌg8(hzJ~I"q ޕIK0P07<2ks 5e, <XJӀ_!N@!_QtHS3? rp(K/"U]L6%b0 *]?? Ov;( tHtHUU,H廇+V`(pQ [dP DP! CHvO( e7h !L(3#*;B>PTxy#* ?H;c< cd_~5xu#(让MVfn``?|cGL{y32'eW@YS3LJoON[ݗϲx~XpY5<[_S=D缩9_O_iWV_1{6*;dp8Ȓ"-twTN\ژ90-ފ8@_M;pǖ=_7l"6p^7mFNx fvi ͱ9 f׸&+=€_J*pA ,F$~SXA7REMOGOAs+$~NLAj@Ap*A,VCD0 (na D8s9P )XiT2%BVHt0`)1e ;mDR0r$\ e?M2I#"P_6g_u#7)wA"AWޛ]٥)W a]?XՅK>.u$?2.?}'>^r)% &0 SO4`?0:((̒$U.#//fPc5t ):BckJB<<3Iȹ0S`(Ex'@6M% p Nfz5"!)p2'|m\@?B*Y4r,OدSC 7 g*3wIMp؈/6z'69YJVhi~r*}y p#@`B`IP?4H 8=ubW{CȩƋX ek8kReA'gK2=C3jTȍ@8ᱪ;- P9Bh Op Hx. ,wIw~&VX i7m*a dDi <fž̙ !@e9t{.x^I)܏Vրw5 Q1K'5YR01@csY`S(K"WT\;bGW称Hj(wϖ-~&5hJdߝnO]OF` \1GQ y$ȢFT5rjE5GtTpC(hJ9W~*_7[=bh~ v6r }'My;FoI[wgK[ݙo1Mg̷|y2T[247WNY&M|s7{}=kGD6{'yR`訂ɐʝz)* ?Fh`~`!<=н/gӽ-A?]~Ith >X 鳰t!aI3*QJHIJJkT>wqno7vzx򖗿'wn7Ol~jꟗw f׿x <%qiuxE@. i`dP7Y[ ߔ="AƗB!t|[$ۅxDgmLO4"|)L$"$J(.120I$!JK|DRb2 | DmYUB@! P.'~_~zʟ_ > _S/Carla-2.1/resources/scalable/osc.svgz000066400000000000000000000162551364475620200176770ustar00rootroot00000000000000~uFconnection-established.svgz}[sɕ~qǂsݞpw&ѳ%v JH-$*,HH;_=a}^50Al?m:Dfs|1;^zx=?[s^~tvzj~\j]x|yP@ 6niNN|5eiO نЪti%u+BB<={7pٖΪTʹryfoBjGgϿoUϧ/''Z,MM ) M>{uD n! /â Aaup꧰J6io nB' KuDh#h9g3mNe.pԆ(m 0ƌ;FڰcgF^(Ac $ F5J3l#AvF5J,LH3L; qNh ILCtϥqz(mJ34(6߱(6~rDjyѺ9 ~(KL?3AG-åe/#PBOg9nc F%1x]fix3bLz@o\d~)%(S֍rw#|֩k:o?&}wpi0d8dm("2;ޯ"7ѤR}DS:1&Fu3ɆXS)&Sd#l(P"t$)4=/gQږ  H=p~j1qi?F[Su%r#PۃZ7ғWdlq}پ˺pͷ`z՟I%;˺gr[\+''*v /JN`*(jB5W:je)nU1"Z{ƭj/9靘 "p 9׼W&YHJT!{dA1'ͻ1a%El%&ZQ[CAD6 % cr*7Io 9'1l'þx UថJ+bU~7q7.5pj蝖{<.S.2,d6ʻZ5V4";4,(,ij E&7$E>GҡbqT3-.MfxvD^/ -A|(FpuэLN|]S'ˇwZ h^ Wh5q~NBq.2(ED1cM>'2೪<6C /g E" \v FIנ|H*#Q^!":|h󙛲@@qFqg(\q R`j@ P<[aU;^yjQP`Y4Q7=NE\L@s"jJ()-PB#&+j^"o2+w-6˽qO:q; `wM>GQUEGu9Ҝ[> BG3J|Gdew( og2?y^ F %4!zQ=R/J#G4`;Bar7xZ1-7q?nUcɻVPdFmB0T,o8iz1j,Cp l/hҋq CZu,$DADxĶwnV \DzKX6kН`N]"{9[_ 损 k^n)$ꭥsi%#lO*;6ecvW"`x?a-Ha&6G) teʠ"!rױFӟ'spup9d mJުc59u=]̏gZԶnԶyؼ{-ؼ}N|o^u~R][n# :^Ѹ% '|KԐD?(B3\%0I3ڷI8Єց&4xS'ByyΚxfBo4:=I*gQ(N,3ĵ9gIlL۷;yA<ΰowl&^6<YHm-7WA557_ϗrZ^}|? XD]Mk\;h:tו]_F^~x3Nl~}YX^6rղMMNgp|<ׯ_?RÚ{ʳj_{ꫀM|y}Qy--&*jO6~7Erw9fY\-[ *ތ^0.}춲/-.w[߿.<;y|ۧ?]7n!Zkk>XNΦGj]xuUuz3]Z7i=¶"Yͥ"ͫ9SYRmNjjU~ҿkC7X=.ޞ__̻}_^/`5 /jΏ?yWZI5_ֿ^Zv%Hu^{`w&E_ׅ/{I9dgF43?]0G^nP,9CPR6g,@Q1(ss@=]oJ谹CږW`P\-̢_2(H  #) p*6.>o\j@qh\lVuA~(AOA @7DP0\&YB@ZXI[.^P Jč Jͼ-޷ k[_2CB`Ct;>- *:]鴉v{G{;^sĵ:-[H.؋P$dj#<]p@ i&rTHt2b.]! S7v ?t\uYGEP~]X _XvlРgL7R\%%:u g+f O (vS4~\Т.-3 #5ca[uBx^y}i! R c_;vvŔ^NqQgWb~^@YHOW4Huߦ+"H_ 7k@V3DXZkY<-lV@)(e r6^CAOԖ| tlgbJBjpy J <-Om9~q7tXk m1diA2&HQ<տ^5Яqox~Qlmgk`k`6>׵cm7y {8T;8ݐawk`kp6.>+ڷ"jẂ:mvcp7~McD$NYfL$\mD"b"Lt6D xh^HV;< 8A-L{A2p"^H16)fԤ!$'0 iA NX;" Ro*I+WJHL$ BEiaЉbATvlS3.(&)[d IL fyӺ@]и= m҄fv4 ("kVm:uZD[kQӧ@=)1ǪO)}*γ mZM "+dt)'[4]u)5 n!H kWCMUBxݣ1QDʜMf׉i\El~՟ЌP1_'̜Us{F$Z=ns?,$PAth HBQu( lF!Z!2An)W*"J Ȋ[HVبam}LQ|FEGձlR"2k=̖rXwr6#;VYX"m$g+v68 \`ft;TjI( z$;$=]r7?0U?Mb^[*1Q/b`Iy !n>Q1v@$%ljKQdF;!xYܘE7=(>,)T"B.rnhZ4(0Vֺ`o*Fjm=M%W,&n֚IFB~ shܕ-GQr7(_-}{{B*]˸݋!ubh= D[7XGI2GY) x]'+ lFkK_U]o_+}@b+~uX bDfQlJJh`DH P*{ I|3?F 30R3貜،|f|1lۖQ;ȩfdӀYa;MUBm%QQ?jt5iNwST`&yI0Cf?k ݚxqR rőXQ&A*NὗpNJ{J}o5 b gn#A(Carla-2.1/resources/scalable/pb_audacious.svg000066400000000000000000011376521364475620200213650ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_clementine.svg000066400000000000000000000456641364475620200215330ustar00rootroot00000000000000 Clementine Music Player Logo image/svg+xml Clementine Music Player Logo may 28 2010 Carlos Jenkins Perez CC-BY-SA clementine music player logo Carla-2.1/resources/scalable/pb_configure.svg000066400000000000000000000056051364475620200213600ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_configure_ref.svg000066400000000000000000000032261364475620200222110ustar00rootroot00000000000000 Carla-2.1/resources/scalable/pb_distrho.svg000066400000000000000000000045701364475620200210530ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_distrho_12.svg000066400000000000000000000046141364475620200213540ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_distrho_16.svg000066400000000000000000000045701364475620200213610ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_distrho_ref.svg000066400000000000000000000057231364475620200217100ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_file.svg000066400000000000000000000041101364475620200203040ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_file_16.svg000066400000000000000000000041101364475620200206120ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_file_ref.svg000066400000000000000000000014271364475620200211500ustar00rootroot00000000000000 Carla-2.1/resources/scalable/pb_generic.svg000066400000000000000000000206561364475620200210160ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_generic_12.svg000066400000000000000000000212661364475620200213160ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_generic_16.svg000066400000000000000000000206561364475620200213240ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_generic_ref.svg000066400000000000000000000216421364475620200216460ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_hardware.svg000066400000000000000000000135651364475620200212000ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_hardware_12.svg000066400000000000000000000133311364475620200214710ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_hardware_16.svg000066400000000000000000000135651364475620200215060ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_hardware_ref.svg000066400000000000000000000132631364475620200220270ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_jamin.svg000066400000000000000000000223021364475620200204660ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_jamin_16.svg000066400000000000000000000223021364475620200207740ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_jamin_ref.svg000066400000000000000000000223401364475620200213240ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_mplayer.svg000066400000000000000000000203211364475620200210400ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_mplayer_16.svg000066400000000000000000000203211364475620200213460ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_mplayer_ref.svg000066400000000000000000000202241364475620200216760ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_plugin.svg000066400000000000000000000045361364475620200206770ustar00rootroot00000000000000 Carla-2.1/resources/scalable/pb_vlc.svg000066400000000000000000000063041364475620200201600ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_vlc_16.svg000066400000000000000000000063041364475620200204660ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/pb_vlc_ref.svg000066400000000000000000000060721364475620200210160ustar00rootroot00000000000000 image/svg+xml Carla-2.1/resources/scalable/warning.svgz000066400000000000000000000115661364475620200205600ustar00rootroot00000000000000]moGI*%..]-lmdR ίRá& ز8&f~gOL~j |2i旋˓g~2Yf1o^'wfnfw7\]Noެ׷޽KaZ,_^n2n立˓՛]77f^C^W׼Jf[^v_^j.gWEJϊ|=}6_~j1p*KYy/Ӗ^-W R7֫RIf}߿/fu;lV[y_fs~S޾i_Y׳'e|l'PNm-bIP |64[\oo˻^7nyif9/\߭4TFX]>{7] S硁fYUzar}vu}.u;=ZL9@B-SǢZUnF0.ή hlMsYtznmΰ*q]zq@?ܔVYiqUM+Zf]?\7'}ժ)wsZkg'ÈƬb5h(>|4Dt|K&rE?Et} C 1@g:;{>*2=ʟ/9ңxtoO acVE[9>#e&O]]8?ň.Wz$_=9aޥ c=#ϖw3a0 V6o' T'#:AOLur~|4<~7LD~>F}NF>]َu\u\ax\3{Fڅc:~uqwӛGv_Y6p7e9}'JIԼ~xy⒂^^._7}9ۗ'o?p<=ˉĘNsSH~zI¸ta/t[8#p$b|YSt#@D-HH  H @fDȰ),zJΊ(S%Q#8u5ԪJLG  \PrA8 +3K VHD"P@Y?bu6%g~gC!EpCѡWdv Mh#`"&@;S JAǒɹGOdwUU!z0# COې++m2?cnG]C.íK'}1*D0@,B* 0K >eẗaIt8cuLAb.GPs%w)%qȴ$M<'u BOi 1@S538pSj{Q(b"(~?xoeD* RO?гԌ M]ȺFSN ŵX8u^(ŗ2(~ 2 e*:{5[ET@HkR"`j&PɁT"Jz*XL)bW#yWaIx$nY! ٝTp8$!7&hV$>.9E6MRq Xa/攋8NJJ5x&Ay4xԻY{2 nn^Py2}_/wofämlˬ-p _Y_'*&o?joΆeg˻/f^rcsQbScVV)_]?@,o˟ f|1o6ҡRg]ՂN )H.&ڞSLē#()XbUR%Lm4Y"&`MZNÓbb'3R?C mzaE O 'yI벘0Ue,ܹqJiFwH$s@is)2),B=!EU-K,L:c,C8=x5 ( ^8 !cf8ůo10qY+u7\H-eUIļ"q&p 6.62Y !KapP@:b(YPR 1 {h"0VYBzPȭ8( Z]P=tAMQ-BmH{ˇ vd28Lɺ9$Rt18s+u#ŬTe ]Q=EL IqPn똃> R'nɢٺږZ;jm ;a$D\dXbQ; *kk)B]m%G!nե&&0"K?Mmf_W.+Bgځ[ +AYk 26K? w82}<׈Rt9"b42VY]șH 1L=PHBsJRRFj[W^Pl7uf|W9T33V({IȰGE9]]\8%r5ts17]{8ՠ90 >;Sxn~N2Uoo>\pYO&+g씍عdar>uc9 'Ņ*ed6arT[Zm*|@3"!9u26"T7Z"@ rdPB r&פtzu¢W"R&8cކalՑG4(G2C8idM c.Ynąz/xY3=)U>YsHJ}ɩUCxf_cB.0<2`N4+6]Qe%4N;T'"NZN)! ;-P)7֨}ArLcBmPz,#zrh WK47JfƤCEHOՓY=iJ(b+3N!\Nv`nפ9$zdlFP_5a͊$nnEۢH亹 jwx[ r]M%[ީgyI}oZǨg<`R~K'#)O'{)dO|2L'#)a >I7 ?!d'Ov?#'_ڷ8Ju~Mh~ bwlHXZ#DtŎ. 2U;TYeih@tR&.lMDYjbo)0&&FrJ t/+:ʴ#tL!jfPpH;'$BƽyىQ3yY32ȃ/9 aa%fBloEs* !ƪ?".&E{Qm tLHf.Q @=1spպ S/dL9bBY nMs\MkH"kt]͊lKpgl-El0 &ʆ-F-vd-WU @ `d.ƨJ.בUFkռdCarla-2.1/resources/scalable/wine.svgz000066400000000000000000000260531364475620200200520ustar00rootroot00000000000000uFwine.svgz}[oY K~qu`эY 0vϔDڲ%C{2E)ti.K8/ND˫_/;/Oqp0rq<}8~=_?~ÇpᏳVe6fϯ^b%^pfvy~}uH@/A.W/o?>/yyrD|^I\}<^zp~ýSE۹AaR/}gT{WK8_^;ypr}r[wL_ջ8;~ݘ|<{z}v6>Am^qA?u[Sݩ՜\-Z__];;o=8\\^~jy~x1SݻOhkU|8;_Bw1dyz݌%џkg4\55Nr|&/ӗxw+;kvMk/\\~z18=Z6b mv%^GmMJTơb>@ MPX+xvYfNYo>,>^5[ח6 0q_qwEAQfǟ_`: L()|_/W?/pC?)61Z^wgueS[s D#n^]/w46ڑghF )(P8f5&eODz# =d`j AiƱҋ/L*SyܖMjc[?):=ss1Aj8L #q[sJjzs V!q 8x~ĜLxNPvZCPlGZ>)sӌ\(r(n:r @2Y5lr /v]V~' "E6NsǀB9,UڂYsjEc=EqOq{4f!a SŖҘ Xa<9Z<=Ǒ! @2q# *4!ٸ( Q emfby<ޕq2N#Kbi+C88ZjOlS&CРG2!J&>]5 C.`*d>lݧ{8J.tg-~<ٙ[}3ȟ"&:Gf!Mn& :dNY |u5 a=8KawYYI y򇓣˲0Kv߇ ғqۙV}@4ܿiqnl#$Cy 9(gie"\Ie4Pc(sP39 5!a-k~5? ۚ=AATb RU`E(r-tQG Q!qOClC('̼$N%$43݄0oX,KOnLn}dWRF (M(H@wm?ׯ/Z/X`#KD&/!#KElj`ʔO% =l3-Kv2:9#:zbZhs]Vѷq+VwdW? |v8 2#2$>e@G! mS[rgme.d؆6$&gjhIONNtLRZMN%_5-!9SKjW"W"ìA&k Cڄ@6^R@o-RxK,UwY{|D|S7[ulo/mnHEMś.N2'fr}ٙ ؍eH^\O0fO}wEOADG 6#'08{i c*j[!&c.jK6"oz/n0%vDjm$"69KPJv.BW= b~u:O2{ܘ) <`0/+(6Eh1`i3^H9R8Hצ@>sf/wjq88G8WK {T=lBHVn'I-} ݕj{2>2OXa؏zH6en0 "{"X;>ruyjmm])&ml(6--&P*c9x!.d3(N5Lk7۰RX.{ >Eb1ta~ą7M@[oĻ% X\'{q-JP.ml-EֲM O${']n->rN|(rnkeyԣݟޠx YZ d73@5'3@IIB'de4=]W(I|S:淾)AͺKymN@{-2jgE zO~ӼLx#0#`uaFId[_1PGq|?D=Ɏ\& p)e\"()[.,4?@ *vZԫXe>wPK@PJhJ[*t-@c^{fT7alھ?f=c6OhC ̡DjLcF)&MoTw'zl_ұwWR[{,ʙG]5CmkыmΝJvrw^ 'yN&G%FX0;Gd`NYrE;WED@ A%^>XXtH)g &G-e3&m_IHw6pm[-7*dDo)!H;@%-\Tt0IӑmCIMSO5}2ڑzz)Qka|2Fz=LRB&)7ɽ:BPx .hJPŠ= ie.1J'aD-yPMhkϴ`'oǭ]ftNnOxun:߻Y珮:g[Cg?ه_>t:g?ه_>t:{9=ه_>t:ݻه_>t:}/J)v 1{2f>G{ߩHc:#MNm[𧘁73sxlgތeOGxGKO8`:〧uǻx78<Eo%JF(ҵb!&eODzL)eIlw';SNj+-e)G;SN)('rl&7jS@qAVcV9[0A-1AEŘH5 !-Nʞe^:#Ӻv:v:mK۽20w^ʵ۶R?|^Dhd㘊Ph@O'$Oǒ8Rm=0YuI ֏FUtuqr|vy准q#ӻūeoZMgudyy{ =b]wqŇ]\4B@Jy|rbJ쟜|yTwfqنW/>r}~^ۮu]+{ptt먂g'ׯ]˳WlTˇ󦍃U m%NI(]^ZuKz1P4Q3ϓӗ/v7I k'8x՗Yɝl,ovM#퉱w\^]X^m:_^9k{ɢ㪱 9w4=wJx+2st#thz":J3f w !-gw쮪]Ψ}gYg2X~ kx>D+I1\dټA닷wgm:8jja3ˋG7/9Y^/}]^>Y|<|%i_}_Oޝus xVXn ^+aA;;ҫ}ɵf4MHHW&4YP ,b tǛqJBk(SHf YuIPdwqDe=l"ݡj/d:R*D@N $}zk?i'y (>uv85? ‰l9~?֨7o߃ծKߗժ0 0N:ST^2$gJ sN>P,$֊] *TM'8(|VЃ})]wun ;+`la EX L0Pʴ=)V|-M-lq%)v$?z}Fl΀<*nPm%mm6M݆uV "6 ЅZ3N1,$JWVZ02fNާ;U'1\$t,*7:k2pV*/ͻ5i!bsLgq3|VFBp6*D.R0}a}(Lk *HS~ǚW=lZS>Pp ?'@a9uT QuD ϒ$|B Wrv 9+kE#j:4V%h&`<Y$`ΝUIenasGwjK0sL hYDcjп6J=?Ӓf7]n?i'v27 SCfOÞ&!KF:7LTch(WW؁Q3d- -'sݒI-Ps,>d\7d]3Esf(AwdTyniMsW" >wMl aE6a ]6$^˗pLr^ŽRU-5 "d$wo`~ݑ]%n*69B~}2kjCsN3탢jX"bR>EM0T30$HAF^ )RrC=0[+bNYԠt0uɨRcC-J'lj S"$ҚuFt QnSC/cL,Y=hvB\c*唃&Du_Xu|4U%|:pbpAL${hxT/A5K !Jxg}UI:hxڽd@hԙਆvO?Y@Q2L5*Foh)GkSl5ЁC1ma4ua~[H5g1IP4p(OrpuڴmGn$ǾWf@``>ׯJ2kT.Wy1mgFէ 2"B!zlKj+3KׯTX-XqYlmH76%3woggޏ;k>6;1{}xg_Oז6&Ml͍ao-Ř;+Xj!@`bݮٛt7;¸5LtvlY![!]eVDԻ7ds7{i&]5'wdMZ^3J|8NDo.$lb1]XQ#vXxMTw2apEwSҮvٚɒ>Ҋdb#&"+VEM@lJQ3+كJ 4Y4p^m $g(\,T'$9gp]",k6&nQg3տ|~+S)Bl*9<')33f(YVbU)杲tuPXic-Ytr#S:1,-c}־bJhԽۦq ZAY+0n=j4<'. /?a{~c[XD8l]qFrJŽFUt-~'_˚]#B)>Q &|;0.ZbPF?6g='| Dj$Cs2ay}ϸ=g'~*-縟}ĹKtVY-&)hxv=椆eKu2z:z:nR87)|8$Xw?Rrqo 6ڢoPwjfQlk%qH`N) 4)ªVٰ)RjT* }̖y}Jp+= &ʁK fWfUbJ&鎎'Rg<Ǣpl\b8}eba];H,ۍ d69|J#nR.ξiS3UX(wݾ1bꈾd` ͱJn :6d}ź̈́v]Jd?$%r5}t'['HJn*V"WZ|?򲗲+c>IFM,TZXI,18ARX* Nʑ^HZ8AY62e2T9P\%W'I+˶V*sa~Z{ fLsrR6a:Pj.K0I\c|YxUV&NhbE\rg,߽3rW(}6@K[D+[$EOr-k'Z-1Q ٢ yb~IrxNl"Zl`ǐgKm-s6EOyB lY 6"pYP#pZ۔A.nfG\J.5tDM!F}I3F\-RS{X̴wp4E" Tց*k&3l 4ZwRzVvkT,Xx0'We#G%2[EunBp3 j[>^%G'G9z` kwYcPR0j2,m]ح2S4p75?}ۂScd@\Q#Nz؂n-9Ԙ0#**oMWExA%DPc6CbJ!R1~̸[Q2֌"^郌ޘb-F.T6VBe b"6ڂUH m9\6u4ۺ8.4Ü;F"cwŊAo;mvӽr3 atua]ߣCR4p%o\W|ճ<5Icp=P83+o3 ʨpf 5!acg&ӵ%8y-jJ&ΚOࠂNHvh" _iJȖ-m I$wykFE?^lnꖑKY/$)BDL2q49W-oHdHR4$o&kȫ_Qn^CRDy7 KiFg y0` !'G8k'p\-=]OZK6)3ɑ;H?GO|޻ I5yH*aC_* k=\W>5!O$9$Ol=Ԃ$'5m}$"7I.Isʡ@#oGeG#ӜgdIHR'I>NHdޖ.OJ֧u@(s +IR ITHקU:"I\3в~t㹍~*Xq ֓Q_HSI KN١;g9C}d}U99 d෶F>CHM1~La47)?cnS0yԗ6ѦhF}4!6aJ;Q,ZկhSF?ӵײؕHRjx6!LHAX^BbpT)~ª޿7'.E l>1ˆuVmLdVbQSl$V 0.%dl6[لB,A6 NY@R7TX=9Kw)tŚE-z# 1X{ϽI*ncs-r`O̸tЏTk+Xm](n?~?~~z>Carla-2.1/resources/ui/000077500000000000000000000000001364475620200150365ustar00rootroot00000000000000Carla-2.1/resources/ui/carla_about.ui000066400000000000000000001430331364475620200176550ustar00rootroot00000000000000 CarlaAboutW 0 0 512 519 About Carla 0 About About text here Qt::Vertical 20 40 Qt::Horizontal 0 0 Qt::Horizontal 0 0 :/bitmaps/carla_about_white.png Qt::AlignCenter Qt::Vertical 20 40 Extended licensing here true Artwork 16 12 0 1 Qt::Horizontal 0 0 Using KDE Oxygen icon set, designed by Oxygen Team. true 71 30 71 30 :/bitmaps/logo_calf.png 40 40 40 40 :/bitmaps/dial_09s.png 32 32 32 32 :/bitmaps/dial_11e.png 0 0 Contains some knobs, backgrounds and other small artwork from Calf Studio Gear, OpenAV and OpenOctave projects. true 34 34 34 34 :/bitmaps/dial_03.png 22 22 22 22 :/bitmaps/button_on.png 22 22 22 22 :/bitmaps/button_gui_down-white.png 22 22 22 22 :/bitmaps/button_edit_down-white.png 22 22 22 22 :/bitmaps/button_file_down-white.png 48 48 48 48 Qt::PlainText :/scalable/folder.svgz true 48 48 48 48 Qt::PlainText :/scalable/warning.svgz true 48 48 48 48 Qt::PlainText :/scalable/wine.svgz true :/bitmaps/kbd_normal.png 0 1 Qt::Horizontal VST is a trademark of Steinberg Media Technologies GmbH. true Qt::Vertical 20 40 48 48 48 48 Qt::PlainText :/scalable/carla.svg true 48 48 48 48 Qt::PlainText :/scalable/carla-control.svg true 48 48 48 48 Qt::PlainText :/48x48/canvas.png 0 0 Special thanks to António Saraiva for a few extra icons and artwork! true The LV2 logo has been designed by Thorsten Wilms, based on a concept from Peter Shorthose. true 0 0 MIDI Keyboard designed by Thorsten Wilms. true 0 1 Qt::Horizontal 0 1 Qt::Horizontal 0 0 Carla, Carla-Control and Patchbay icons designed by DoosC. true 0 1 Qt::Horizontal Features AU/AudioUnit: Qt::PlainText Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing Qt::Horizontal LADSPA: Qt::PlainText Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing 0 0 TextLabel Qt::PlainText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::Vertical 20 40 VST2: Qt::PlainText Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing DSSI: Qt::PlainText Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing 0 0 TextLabel Qt::PlainText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop LV2: Qt::PlainText Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing 0 0 TextLabel Qt::RichText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop 0 0 TextLabel Qt::PlainText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::Horizontal QSizePolicy::Expanding 1 1 Qt::Horizontal QSizePolicy::Expanding 1 1 0 1 Qt::Horizontal 0 1 Qt::Horizontal 0 1 Qt::Horizontal Qt::Horizontal VST3: Qt::PlainText Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing TextLabel Qt::PlainText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop TextLabel Qt::PlainText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop OSC Host URLs: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false true Valid commands: Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing valid osc commands here Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::TextSelectableByMouse Example: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TextLabel TextLabel Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Qt::Vertical 456 35 false true Qt::Vertical QSizePolicy::Fixed 20 5 License false GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse Qt::Horizontal QDialogButtonBox::Ok buttonBox accepted() CarlaAboutW accept() 248 254 157 274 buttonBox rejected() CarlaAboutW reject() 316 260 286 274 Carla-2.1/resources/ui/carla_about_juce.ui000066400000000000000000000115301364475620200206570ustar00rootroot00000000000000 JuceAboutW 0 0 463 244 About JUCE 48 48 48 48 :/48x48/juce.png Qt::Vertical 20 40 <b>About JUCE</b> Qt::Vertical QSizePolicy::Fixed 10 10 This program uses JUCE version 3.x.x. Qt::Vertical QSizePolicy::Fixed 10 10 JUCE (Jules' Utility Class Extensions) is an all-encompassing C++ class library for developing cross-platform software. It contains pretty much everything you're likely to need to create most applications, and is particularly well-suited for building highly-customised GUIs, and for handling graphics and sound. JUCE is licensed under the GNU Public Licence version 2.0. One module (juce_core) is permissively licensed under the ISC. Copyright (C) 2017 ROLI Ltd. true Qt::Vertical QSizePolicy::Expanding 0 0 Qt::Horizontal QDialogButtonBox::Ok buttonBox accepted() JuceAboutW accept() 248 254 157 274 buttonBox rejected() JuceAboutW reject() 316 260 286 274 Carla-2.1/resources/ui/carla_add_jack.ui000066400000000000000000000452561364475620200202730ustar00rootroot00000000000000 Dialog 0 0 458 546 Add JACK Application Note: Features not implemented yet are greyed out Application Qt::Horizontal QSizePolicy::Fixed 20 60 Name: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Qt::Horizontal QSizePolicy::Fixed 20 60 Application: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 0 0 From template 0 0 Custom true 1 0 Template: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 false 0 Command: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Setup Qt::Horizontal QSizePolicy::Fixed 20 1 Qt::Horizontal 40 20 Session Manager: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 None LADISH (SIGUSR1) NSM Qt::Horizontal 40 20 0 0 Audio inputs: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 64 Qt::Horizontal QSizePolicy::Fixed 20 1 0 1 Qt::Vertical Qt::Horizontal QSizePolicy::Fixed 20 1 MIDI inputs: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 1 Qt::Horizontal 1 1 Qt::Horizontal QSizePolicy::Fixed 20 1 0 0 Audio outputs: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 64 Qt::Horizontal QSizePolicy::Fixed 20 1 Qt::Horizontal QSizePolicy::Fixed 20 1 MIDI outputs: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 1 Qt::Horizontal 1 1 Take control of main application window Workarounds Wait for external application start (Advanced, for Debug only) false Capture only the first X11 Window Qt::Horizontal QSizePolicy::Fixed 20 1 Qt::Horizontal 135 1 Use previous client output buffer as input for the next client Simulate 16 JACK MIDI outputs, with MIDI channel as port index QFrame::StyledPanel QFrame::Raised 16 16 16 16 :/16x16/dialog-cancel.svgz true Error here Qt::Vertical 20 40 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() Dialog accept() 248 254 157 274 buttonBox rejected() Dialog reject() 316 260 286 274 Carla-2.1/resources/ui/carla_database.ui000066400000000000000000000621161364475620200203110ustar00rootroot00000000000000 PluginDatabaseW 0 0 1100 683 Carla - Add New 0 0 0 164 254 Format Internal LADSPA DSSI LV2 VST2 VST3 AU Sound Kits Qt::Vertical 20 40 0 0 164 164 Type Effects Instruments MIDI Plugins Other/Misc Qt::Vertical 20 40 0 0 164 136 Architecture Native Bridged Bridged (Wine) Qt::Vertical 20 40 Qt::Vertical 20 40 0 0 true 75 true Requirements With Custom GUI With CV Ports Real-time safe only Stereo only With Inline Display Favorites only (Number of Plugins go here) Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse Qt::Horizontal 40 20 &Add Plugin :/16x16/list-add.svgz:/16x16/list-add.svgz Cancel :/16x16/dialog-cancel.svgz:/16x16/dialog-cancel.svgz true Refresh :/16x16/view-refresh.svgz:/16x16/view-refresh.svgz Reset filters :/16x16/edit-clear.svgz:/16x16/edit-clear.svgz true Qt::Vertical 20 40 TextLabel Format: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Architecture: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TextLabel Type: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TextLabel Qt::Vertical 20 40 MIDI Ins: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Audio Ins: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter CV Outs: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter MIDI Outs: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Parameter Ins: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Parameter Outs: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Audio Outs: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter CV Ins: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter UniqueID: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Has Inline Display: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Has Custom GUI: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Is Synth: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Is Bridged: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TextLabel TextLabel TextLabel TextLabel TextLabel TextLabel TextLabel TextLabel TextLabel TextLabel TextLabel TextLabel TextLabel 75 true Information 0 1 Qt::Horizontal 0 1 Qt::Horizontal 1 0 QAbstractItemView::NoEditTriggers false false true QAbstractItemView::SingleSelection QAbstractItemView::SelectRows false Qt::NoPen true false 24 true false 12 22 :/16x16/bookmarks.svgz:/16x16/bookmarks.svgz Name Label/URI Maker Binary/Filename Focus Text Search Ctrl+F lineEdit tableWidget b_add b_cancel b_refresh b_clear_filters ch_internal ch_ladspa ch_dssi ch_lv2 ch_vst ch_vst3 ch_au ch_kits ch_effects ch_instruments ch_midi ch_other ch_native ch_bridged ch_bridged_wine ch_inline_display ch_stereo ch_rtsafe ch_gui ch_cv tab_reqs tab_info act_focus_search triggered() lineEdit setFocus() -1 -1 448 23 Carla-2.1/resources/ui/carla_edit.ui000066400000000000000000000723361364475620200174770ustar00rootroot00000000000000 PluginEdit 0 0 537 535 Plugin Editor QTabWidget::South 0 Edit Control Qt::Horizontal 40 20 MIDI Control Channel: Qt::CustomContextMenu Qt::AlignCenter N 0 16 0 Qt::Horizontal 40 20 Qt::Horizontal 10 10 34 34 34 34 Qt::CustomContextMenu Output dry/wet (100%) 34 34 34 34 Qt::CustomContextMenu Output volume (100%) 16777215 42 0 0 0 0 0 0 0 26 26 26 26 Qt::CustomContextMenu Balance Left (0%) 26 26 26 26 Qt::CustomContextMenu Balance Right (0%) 0 0 0 0 0 26 26 26 26 Qt::CustomContextMenu Balance Right (0%) 0 Use Balance true Use Panning Qt::Horizontal 10 10 0 0 Settings Use Chunks 0 1 Qt::Horizontal 75 true Audio: Fixed-Size Buffer Force Stereo (needs reload) 0 1 Qt::Horizontal 75 true MIDI: Map Program Changes Send Bank/Program Changes Send Control Changes Send Channel Pressure Send Note Aftertouch Send Pitchbend Send All Sound/Notes Off Qt::Horizontal QSizePolicy::Expanding 1 1 Plugin Name Qt::AlignCenter true Qt::Horizontal QSizePolicy::Expanding 1 1 0 0 0 1 2 2 2 2 Qt::Horizontal 1 1 0 0 Program: 150 0 2 2 2 2 Qt::Horizontal QSizePolicy::Expanding 1 1 0 0 MIDI Program: 150 0 Qt::NoFocus Save State :/16x16/document-save.png:/16x16/document-save.png Qt::NoFocus Load State :/16x16/document-open.png:/16x16/document-open.png Qt::Horizontal QSizePolicy::Expanding 1 1 0 0 Information false true Label/URI: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Name: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false true false true false true false true Type: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Maker: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Copyright: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Unique ID: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false true Qt::Vertical QSizePolicy::MinimumExpanding 1 1 PixmapDial QDial

widgets/pixmapdial.h
Carla-2.1/resources/ui/carla_host.ui000066400000000000000000001364711364475620200175300ustar00rootroot00000000000000 CarlaHostW 0 0 1045 716 MainWindow 0 4 0 1 QTabWidget::North 0 Rack 0 0 0 0 1 QFrame::StyledPanel QFrame::Sunken 0 0 25 0 25 16777215 Qt::CustomContextMenu QFrame::NoFrame QFrame::Plain Qt::ScrollBarAlwaysOff Qt::ScrollBarAlwaysOff 25 0 25 16777215 Qt::Vertical Patchbay 0 0 0 1 1 QGraphicsView::AnchorUnderMouse Logs 0 0 0 0 1 DejaVu Sans Mono Qt::ScrollBarAlwaysOn Qt::ScrollBarAlwaysOn QPlainTextEdit::NoWrap Loading... Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse 0 0 6 0 6 4 Buffer Size: 0 1 Qt::Vertical Sample Rate: 0 1 Qt::Vertical ? Xruns true 0 1 Qt::Vertical 0 Qt::AlignCenter DSP Load: %p% 0 0 1045 25 &File &Engine &Plugin Macros (all plugins) &Canvas Zoom &Settings &Help toolBar false Qt::NoToolBarArea Qt::ToolButtonTextBesideIcon TopToolBarArea false 0 10 QDockWidget::NoDockWidgetFeatures Qt::NoDockWidgetArea 1 0 1 5 0 1 Qt::Vertical 0 10 210 0 false QTabWidget::West 0 false Disk 1 0 0 0 1 Home :/16x16/list-add.svgz:/16x16/list-add.svgz false :/16x16/list-remove.svgz:/16x16/list-remove.svgz QAbstractItemView::NoEditTriggers true QAbstractItemView::DragOnly Transport Playback Controls :/16x16/media-playback-start.svgz:/16x16/media-playback-start.svgz true :/16x16/media-playback-stop.svgz:/16x16/media-playback-stop.svgz :/16x16/media-seek-backward.svgz:/16x16/media-seek-backward.svgz true :/16x16/media-seek-forward.svgz:/16x16/media-seek-forward.svgz true Time Information Frame: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter DejaVu Sans Mono 000'000'000 Qt::Horizontal QSizePolicy::Fixed 20 1 Time: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter DejaVu Sans Mono 00:00:00 Qt::Horizontal QSizePolicy::Fixed 20 1 BBT: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter DejaVu Sans Mono 000|00|0000 Qt::Horizontal QSizePolicy::Fixed 20 1 Settings BPM 1 20.000000000000000 999.000000000000000 Use JACK Transport Use Ableton Link Qt::Vertical 20 188 0 0 QTabWidget::West 0 false 0 0 0 QLayout::SetDefaultConstraint 0 0 0 1 0 0 210 162 false QFrame::StyledPanel QFrame::Sunken 1 :/16x16/document-new.svgz:/16x16/document-new.svgz &New Ctrl+N QAction::NoRole :/16x16/document-open.svgz:/16x16/document-open.svgz &Open... Open... Open... Ctrl+O QAction::NoRole :/16x16/document-save.svgz:/16x16/document-save.svgz &Save Ctrl+S QAction::NoRole :/16x16/document-save-as.svgz:/16x16/document-save-as.svgz Save &As... Save As... Save As... Ctrl+Shift+S QAction::NoRole :/16x16/application-exit.svgz:/16x16/application-exit.svgz &Quit Ctrl+Q QAction::NoRole :/16x16/media-playback-start.svgz:/16x16/media-playback-start.svgz &Start F5 QAction::NoRole :/16x16/media-playback-stop.svgz:/16x16/media-playback-stop.svgz St&op F6 QAction::NoRole :/16x16/list-add.svgz:/16x16/list-add.svgz &Add Plugin... Ctrl+A QAction::NoRole :/16x16/edit-delete.svgz:/16x16/edit-delete.svgz &Remove All QAction::NoRole Enable QAction::NoRole Disable QAction::NoRole 0% Wet (Bypass) QAction::NoRole 100% Wet QAction::NoRole 0% Volume (Mute) QAction::NoRole 100% Volume QAction::NoRole Center Balance QAction::NoRole true :/16x16/media-playback-start.svgz:/16x16/media-playback-start.svgz &Play Ctrl+Shift+P :/16x16/media-playback-stop.svgz:/16x16/media-playback-stop.svgz &Stop Ctrl+Shift+X :/16x16/media-seek-backward.svgz:/16x16/media-seek-backward.svgz &Backwards Ctrl+Shift+B :/16x16/media-seek-forward.svgz:/16x16/media-seek-forward.svgz &Forwards Ctrl+Shift+F :/16x16/view-sort-ascending.svgz:/16x16/view-sort-ascending.svgz &Arrange Ctrl+G QAction::NoRole :/16x16/view-refresh.svgz:/16x16/view-refresh.svgz &Refresh Ctrl+R QAction::NoRole Save &Image... QAction::NoRole :/16x16/zoom-fit-best.svgz:/16x16/zoom-fit-best.svgz Auto-Fit Home QAction::NoRole :/16x16/zoom-in.svgz:/16x16/zoom-in.svgz Zoom In Ctrl++ QAction::NoRole :/16x16/zoom-out.svgz:/16x16/zoom-out.svgz Zoom Out Ctrl+- QAction::NoRole :/16x16/zoom-original.svgz:/16x16/zoom-original.svgz Zoom 100% Ctrl+1 QAction::NoRole true Show &Toolbar QAction::NoRole :/16x16/configure.svgz:/16x16/configure.svgz &Configure Carla QAction::NoRole &About QAction::NoRole About &JUCE QAction::NoRole About &Qt QAction::NoRole true Show Canvas &Meters QAction::NoRole true Show Canvas &Keyboard QAction::NoRole true Show Internal QAction::NoRole true Show External QAction::NoRole true Show Time Panel true Show &Side Panel QAction::NoRole :/16x16/network-connect.svgz:/16x16/network-connect.svgz &Connect... QAction::NoRole :/16x16/view-refresh.svgz:/16x16/view-refresh.svgz &Refresh QAction::NoRole Compact Slots QAction::NoRole Expand Slots QAction::NoRole Perform secret 1 Perform secret 2 Perform secret 3 Perform secret 4 Perform secret 5 :/16x16/list-add.svgz:/16x16/list-add.svgz Add &JACK Application... QAction::NoRole :/16x16/configure.svgz:/16x16/configure.svgz &Configure driver... QAction::NoRole :/16x16/dialog-warning.svgz:/16x16/dialog-warning.svgz Panic QAction::NoRole Open custom driver panel... DigitalPeakMeter QWidget
widgets/digitalpeakmeter.h
1
CanvasPreviewFrame QFrame
widgets/canvaspreviewframe.h
1
RackListWidget QListWidget
widgets/racklistwidget.h
DraggableGraphicsView QGraphicsView
widgets/draggablegraphicsview.h
act_file_quit triggered() CarlaHostW close() -1 -1 189 34
Carla-2.1/resources/ui/carla_osc_connect.ui000066400000000000000000000210701364475620200210340ustar00rootroot00000000000000 Dialog 0 0 443 281 Carla Control - Connect Remote setup UDP Port: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Remote host: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 1024 32767 1024 32767 TCP Port: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal QSizePolicy::Fixed 20 60 Qt::Horizontal QSizePolicy::Fixed 20 60 Reported host Qt::Horizontal QSizePolicy::Fixed 92 38 0 0 Automatic Qt::Horizontal QSizePolicy::Fixed 92 38 0 0 Custom: Qt::Horizontal QSizePolicy::Fixed 10 1 QFrame::NoFrame QFrame::Plain 0 1 Qt::ScrollBarAlwaysOff Qt::ScrollBarAlwaysOff false In some networks (like USB connections), the remote system cannot reach the local network. You can specify here which hostname or IP to make the remote Carla connect to. If you are unsure, leave it as 'Automatic'. Qt::NoTextInteraction Qt::Horizontal QSizePolicy::Fixed 10 1 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() Dialog accept() 248 254 157 274 buttonBox rejected() Dialog reject() 316 260 286 274 Carla-2.1/resources/ui/carla_parameter.ui000066400000000000000000000030311364475620200205140ustar00rootroot00000000000000 PluginParameter 0 0 369 33 Form 0 Parameter Name Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Qt::CustomContextMenu ... ParamSpinBox QWidget
widgets/paramspinbox.h
1
Carla-2.1/resources/ui/carla_plugin_calf.ui000066400000000000000000000255261364475620200210340ustar00rootroot00000000000000 PluginWidget 0 0 622 90 Qt::CustomContextMenu Frame 0 4 3 6 3 1 72 0 72 16777215 2 0 Enable true On/Off Qt::Horizontal QSizePolicy::Fixed 6 1 0 20 16777215 20 0 1 Qt::Vertical Qt::Horizontal QSizePolicy::Fixed 8 1 75 true PluginName Qt::AlignCenter Qt::Horizontal 20 1 0 4 MIDI Qt::AlignBottom|Qt::AlignHCenter 25 25 25 25 25 25 true 0 AUDIO IN Qt::AlignBottom|Qt::AlignHCenter 150 0 0 AUDIO OUT Qt::AlignBottom|Qt::AlignHCenter 150 0 0 1 Qt::Horizontal 1 6 4 4 3 GUI true Edit true Remove Qt::Horizontal 40 20 0 0 2 4 0 4 0 71 30 71 30 :/bitmaps/logo_calf.png Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter DigitalPeakMeter QWidget
widgets/digitalpeakmeter.h
1
LEDButton QPushButton
widgets/ledbutton.h
PixmapButton QPushButton
widgets/pixmapbutton.h
Carla-2.1/resources/ui/carla_plugin_classic.ui000066400000000000000000000220771364475620200215460ustar00rootroot00000000000000 PluginWidget 0 0 497 37 Qt::CustomContextMenu Frame 0 2 4 2 4 2 1 0 1 0 4 24 24 24 24 :/bitmaps/button_off.png:/bitmaps/button_off.png 24 24 true true 24 24 24 24 :/bitmaps/button_gui.png:/bitmaps/button_gui.png 24 24 true true 24 24 24 24 :/bitmaps/button_edit.png:/bitmaps/button_edit.png 24 24 true true Plugin Name Qt::Horizontal 40 20 1 4 4 0 1 14 14 14 14 true 14 14 14 14 true 14 14 14 14 true 14 14 14 14 true 6 150 0 150 16777215 150 0 150 16777215 DigitalPeakMeter QWidget
widgets/digitalpeakmeter.h
1
LEDButton QPushButton
widgets/ledbutton.h
PixmapButton QPushButton
widgets/pixmapbutton.h
Carla-2.1/resources/ui/carla_plugin_compact.ui000066400000000000000000000242721364475620200215520ustar00rootroot00000000000000 PluginWidget 0 0 446 30 Qt::CustomContextMenu Frame 0 1 4 3 6 3 72 24 72 24 0 0 24 24 24 24 :/bitmaps/button_off.png:/bitmaps/button_off.png 24 24 true true 24 24 24 24 :/bitmaps/button_gui.png:/bitmaps/button_gui.png 24 24 true true 24 24 24 24 :/bitmaps/button_edit.png:/bitmaps/button_edit.png 24 24 true true Qt::Horizontal QSizePolicy::Fixed 6 1 0 20 16777215 20 0 1 Qt::Vertical Qt::Horizontal QSizePolicy::Fixed 8 1 PluginName Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Qt::Horizontal 19 1 4 4 2 4 2 100 0 100 16777215 100 0 100 16777215 1 14 14 14 14 true 14 14 14 14 true 14 14 14 14 true 14 14 14 14 true DigitalPeakMeter QWidget
widgets/digitalpeakmeter.h
1
LEDButton QPushButton
widgets/ledbutton.h
PixmapButton QPushButton
widgets/pixmapbutton.h
Carla-2.1/resources/ui/carla_plugin_default.ui000066400000000000000000000320401364475620200215400ustar00rootroot00000000000000 PluginWidget 0 0 552 60 Qt::CustomContextMenu Frame 0 0 4 3 6 3 1 72 24 72 24 0 0 24 24 24 24 :/bitmaps/button_off.png:/bitmaps/button_off.png 24 24 true true 24 24 24 24 :/bitmaps/button_gui.png:/bitmaps/button_gui.png 24 24 true true 24 24 24 24 :/bitmaps/button_edit.png:/bitmaps/button_edit.png 24 24 true true Qt::Horizontal QSizePolicy::Fixed 6 1 0 20 16777215 20 0 1 Qt::Vertical Qt::Horizontal QSizePolicy::Fixed 8 1 PluginName Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Qt::Horizontal 20 1 4 4 2 4 2 100 0 100 16777215 100 0 100 16777215 1 14 14 14 14 true 14 14 14 14 true 14 14 14 14 true 14 14 14 14 true 0 1 Qt::Horizontal 1 12 4 12 0 0 0 Qt::Horizontal 40 20 0 12 0 0 0 DigitalPeakMeter QWidget
widgets/digitalpeakmeter.h
1
LEDButton QPushButton
widgets/ledbutton.h
PixmapButton QPushButton
widgets/pixmapbutton.h
Carla-2.1/resources/ui/carla_plugin_presets.ui000066400000000000000000000333701364475620200216100ustar00rootroot00000000000000 PluginWidget 0 0 484 65 Qt::CustomContextMenu Frame 0 4 3 6 3 1 72 24 72 24 0 0 24 24 24 24 :/bitmaps/button_off.png:/bitmaps/button_off.png 24 24 true true 24 24 24 24 :/bitmaps/button_gui.png:/bitmaps/button_gui.png 24 24 true true 24 24 24 24 :/bitmaps/button_edit.png:/bitmaps/button_edit.png 24 24 true true Qt::Horizontal QSizePolicy::Fixed 6 1 0 20 16777215 20 0 1 Qt::Vertical Qt::Horizontal QSizePolicy::Fixed 8 1 PluginName Qt::PlainText Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal 20 1 4 4 4 Preset: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 125 0 1 14 14 14 14 true 14 14 14 14 true 14 14 14 14 true 14 14 14 14 true 0 1 Qt::Horizontal 1 12 4 12 0 Qt::Horizontal 40 20 0 12 0 0 0 4 4 0 4 2 150 0 150 16777215 150 0 150 16777215 DigitalPeakMeter QWidget
widgets/digitalpeakmeter.h
1
LEDButton QPushButton
widgets/ledbutton.h
PixmapButton QPushButton
widgets/pixmapbutton.h
Carla-2.1/resources/ui/carla_refresh.ui000066400000000000000000000406001364475620200201750ustar00rootroot00000000000000 PluginRefreshW 0 0 686 330 Carla - Refresh Qt::Horizontal QSizePolicy::Preferred 30 20 Search for new... Qt::AlignCenter LADSPA DSSI LV2 VST2 VST3 AU 0 1 Qt::Horizontal SF2/3 SFZ Qt::Horizontal 40 5 Qt::Vertical 20 40 0 1 Qt::Vertical Native POSIX 32bit POSIX 64bit Windows 32bit Windows 64bit Qt::Vertical 20 40 Qt::Horizontal QSizePolicy::Fixed 20 20 Available tools: Qt::AlignCenter true 16 16 :/16x16/dialog-ok-apply.svgz true 16 16 :/16x16/dialog-ok-apply.svgz true python3-rdflib (LADSPA-RDF support) carla-discovery-win64 carla-discovery-native 16 16 :/16x16/dialog-ok-apply.svgz true 16 16 :/16x16/dialog-ok-apply.svgz true carla-discovery-posix32 16 16 :/16x16/dialog-ok-apply.svgz true 16 16 :/16x16/dialog-ok-apply.svgz true carla-discovery-posix64 carla-discovery-win32 Qt::Vertical 20 40 Options: Qt::AlignCenter true Carla will run small processing checks when scanning the plugins (to make sure they won't crash). You can disable these checks to get a faster scanning time (at your own risk). Run processing checks while scanning Qt::Vertical 20 40 Qt::Horizontal QSizePolicy::Preferred 30 20 Qt::Vertical 20 6 0 0 100 0 Press 'Scan' to begin the search Scan :/16x16/arrow-right.svgz:/16x16/arrow-right.svgz >> Skip Close :/16x16/window-close.svgz:/16x16/window-close.svgz b_close clicked() PluginRefreshW close() 426 231 236 125 Carla-2.1/resources/ui/carla_settings.ui000066400000000000000000003115021364475620200204010ustar00rootroot00000000000000 CarlaSettingsW 0 0 612 572 600 0 Settings QAbstractItemView::NoEditTriggers false false QAbstractItemView::SingleSelection QAbstractItemView::SelectRows 48 48 Qt::ElideMiddle false false false true false 52 main canvas engine osc file-paths plugin-paths wine experimental Widget Main 75 true :/scalable/carla.svg:/scalable/carla.svg ItemIsSelectable|ItemIsEnabled Canvas 75 true :/48x48/canvas.png:/48x48/canvas.png ItemIsSelectable|ItemIsEnabled Engine 75 true :/48x48/jack.png:/48x48/jack.png ItemIsSelectable|ItemIsEnabled OSC 75 true :/scalable/osc.svgz:/scalable/osc.svgz ItemIsSelectable|ItemIsEnabled File Paths 75 true :/scalable/folder.svgz:/scalable/folder.svgz ItemIsSelectable|ItemIsEnabled Plugin Paths 75 true :/scalable/folder.svgz:/scalable/folder.svgz ItemIsSelectable|ItemIsEnabled Wine 75 true :/scalable/wine.svgz:/scalable/wine.svgz ItemIsSelectable|ItemIsEnabled Experimental 75 true :/scalable/warning.svgz:/scalable/warning.svgz ItemIsSelectable|ItemIsEnabled 0 0 2 <b>Main</b> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::Horizontal 40 20 48 48 :/scalable/carla.svg true Qt::AlignHCenter|Qt::AlignTop Paths Default project folder: 22 22 :/16x16/document-open.svgz:/16x16/document-open.svgz 16 16 Interface Interface refresh interval: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter ms 10 1000 250 Qt::Horizontal QSizePolicy::Preferred 130 10 Show console output in Logs tab (needs engine restart) Show a confirmation dialog before quitting Theme Use Carla "PRO" theme (needs restart) false Color scheme: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false Black System Qt::Horizontal QSizePolicy::Preferred 130 10 Experimental Enable experimental features Qt::Vertical 20 40 2 <b>Canvas</b> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::Horizontal 40 20 :/48x48/canvas.png Qt::AlignHCenter|Qt::AlignTop Theme Qt::Horizontal 40 20 Qt::Horizontal 80 20 Bezier Lines Theme: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal 40 20 Qt::Horizontal 40 20 Size: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 775x600 1550x1200 3100x2400 4650x3600 6200x4800 Qt::Horizontal 40 20 Options Auto-hide groups with no ports Auto-select items on hover Basic eye-candy (group shadows) Render Hints Anti-Aliasing true Full canvas repaints (slower, but prevents drawing issues) Qt::Vertical 20 40 2 <b>Engine</b> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::Horizontal 40 20 :/48x48/jack.png Qt::AlignHCenter|Qt::AlignTop Core 0 0 1 QLayout::SetMinimumSize 0 0 Single Client Multiple Clients Continuous Rack Patchbay QLayout::SetMinimumSize 0 Continuous Rack Patchbay Audio driver: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Process mode: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Maximum number of parameters to allow in the built-in 'Edit' dialog Max Parameters: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Maximum number of parameters to allow in the built-in 'Edit' dialog 1000 ... Qt::Horizontal 40 20 Qt::Horizontal QSizePolicy::Fixed 100 20 Reset Xrun counter after project load Plugin UIs How much time to wait for OSC GUIs to ping back the host UI Bridge Timeout: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter How much time to wait for OSC GUIs to ping back the host ms 10000 Qt::Horizontal QSizePolicy::Fixed 100 10 Use OSC-GUI bridges when possible, this way separating the UI from DSP code Use UI bridges instead of direct handling when possible Make plugin UIs always-on-top Make plugin UIs appear on top of Carla (needs restart) NOTE: Plugin-bridge UIs cannot be managed by Carla on macOS 16777215 5 Qt::Horizontal 40 20 22 22 :/16x16/dialog-information.svgz true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Restart the engine to load the new settings Qt::Horizontal 40 20 Qt::Vertical 20 300 2 <b>OSC</b> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::Horizontal 40 20 48 48 :/scalable/osc.svgz true Qt::AlignHCenter|Qt::AlignTop Core Enable OSC Qt::Horizontal 40 20 Qt::Horizontal 40 20 Enable TCP port true Use specific port: Qt::Horizontal 40 20 22 22 :/16x16/dialog-information.svgz true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Overridden by CARLA_OSC_TCP_PORT env var Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse Qt::Horizontal 40 20 Qt::Horizontal 40 20 Qt::Horizontal 40 20 false Maximum number of parameters to allow in the built-in 'Edit' dialog 1024 32767 Use randomly assigned port true Enable UDP port true Use specific port: Qt::Horizontal 40 20 Qt::Horizontal 40 20 false Maximum number of parameters to allow in the built-in 'Edit' dialog 1024 32767 Use randomly assigned port true Qt::Horizontal 40 20 22 22 :/16x16/dialog-information.svgz true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Overridden by CARLA_OSC_UDP_PORT env var Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse Qt::Horizontal 40 20 16777215 5 Qt::Horizontal 40 20 22 22 :/16x16/dialog-information.svgz true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Restart the engine to load the new settings Qt::Horizontal 40 20 Qt::Horizontal 40 20 22 22 :/16x16/dialog-warning.svgz true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter DSSI UIs require OSC UDP port enabled Qt::Horizontal 40 20 Qt::Vertical 20 126 verticalSpacer_10 label_36 group_osc_tcp_port group_osc_udp_port group_osc_core 2 <b>File Paths</b> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::Horizontal 40 20 48 48 :/scalable/folder.svgz true Qt::AlignHCenter|Qt::AlignTop true 120 0 Audio MIDI 0 0 0 0 0 Used for the "audiofile" plugin 0 0 Used for the "midifile" plugin Qt::Horizontal 20 20 0 0 0 0 0 Add... :/16x16/list-add.svgz:/16x16/list-add.svgz Remove :/16x16/list-remove.svgz:/16x16/list-remove.svgz Qt::Vertical QSizePolicy::Fixed 20 20 Change... :/16x16/edit-rename.svgz:/16x16/edit-rename.svgz Qt::Vertical 20 40 2 <b>Plugin Paths</b> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::Horizontal 40 20 48 48 :/scalable/folder.svgz true Qt::AlignHCenter|Qt::AlignTop true 120 0 LADSPA DSSI LV2 VST2 VST3 SF2/3 SFZ Qt::Horizontal 20 20 0 0 0 0 0 0 0 0 6 22 22 :/16x16/dialog-information.svgz true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Restart Carla to find new plugins 0 0 0 0 0 0 0 0 Add... :/16x16/list-add.svgz:/16x16/list-add.svgz Remove :/16x16/list-remove.svgz:/16x16/list-remove.svgz Qt::Vertical QSizePolicy::Fixed 20 20 Change... :/16x16/edit-rename.svgz:/16x16/edit-rename.svgz Qt::Vertical 20 40 2 <b>Wine</b> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::Horizontal 40 20 48 48 :/scalable/wine.svgz true Qt::AlignHCenter|Qt::AlignTop Executable Path to 'wine' binary: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Prefix Auto-detect Wine prefix based on plugin filename Fallback: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Note: WINEPREFIX env var is preferred over this fallback Qt::AlignCenter Realtime Priority true Qt::Horizontal 40 20 Qt::Horizontal 40 20 1 89 Base priority: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter WineServer priority: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 1 99 Qt::Horizontal 40 20 Qt::Horizontal 40 20 Qt::Horizontal 40 20 22 22 :/16x16/dialog-information.svgz true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter These options are not available for Carla as plugin Qt::Horizontal 40 20 Qt::Vertical 20 96 16777215 5 2 <b>Experimental</b> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::Horizontal 40 20 48 48 :/scalable/warning.svgz true Qt::AlignHCenter|Qt::AlignTop Qt::Horizontal 40 20 22 22 :/16x16/dialog-warning.svgz true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter true Experimental options! Likely to be unstable! Qt::Horizontal 40 20 Main Enable plugin bridges false Enable Wine bridges Enable jack applications Export single plugins to LV2 Load Carla backend in global namespace (NOT RECOMMENDED) Canvas Fancy eye-candy (fade-in/out groups, glow connections) Use OpenGL for rendering (needs restart) false High Quality Anti-Aliasing (OpenGL only) Render Ardour-style "Inline Displays" Engine Force mono plugins as stereo by running 2 instances at the same time. This mode is not available for VST plugins. Force mono plugins as stereo When enabled, Carla will try to prevent plugins from doing things that might mess up the audio or cause xruns, such as fork(), gtk_init() and similar. Prevent unsafe calls from plugins (needs restart) false Run plugins in a separate process, so if they crash it does not affect Carla. Plugins get automatically deactivated in such cases. Reactvate them to start the process again, with the last saved state applied to it. Run plugins in bridge mode when possible Qt::Vertical 20 70 16777215 5 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset buttonBox accepted() CarlaSettingsW accept() 254 458 157 274 buttonBox rejected() CarlaSettingsW reject() 254 458 286 274 lw_page currentCellChanged(int,int,int,int) stackedWidget setCurrentIndex(int) 113 17 170 27 ch_main_theme_pro toggled(bool) label_main_theme_color setEnabled(bool) 228 152 249 165 ch_main_theme_pro toggled(bool) cb_main_theme_color setEnabled(bool) 215 149 314 167 cb_paths currentIndexChanged(int) tw_paths setCurrentIndex(int) 323 82 323 244 cb_canvas_use_opengl toggled(bool) cb_canvas_render_hq_aa setEnabled(bool) 402 220 402 243 cb_exp_plugin_bridges toggled(bool) ch_exp_wine_bridges setEnabled(bool) 402 122 402 145 cb_exp_plugin_bridges toggled(bool) ch_engine_prefer_plugin_bridges setEnabled(bool) 402 145 402 433 rb_osc_tcp_port_specific toggled(bool) sb_osc_tcp_port_number setEnabled(bool) 368 174 467 174 rb_osc_udp_port_specific toggled(bool) sb_osc_udp_port_number setEnabled(bool) 368 282 467 282 cb_filepaths currentIndexChanged(int) tw_filepaths setCurrentIndex(int) 258 79 350 312 cb_filepaths currentIndexChanged(int) tw_filepaths_info setCurrentIndex(int) 258 79 409 79 Carla-2.1/resources/ui/carla_settings_driver.ui000066400000000000000000000203251364475620200217540ustar00rootroot00000000000000 DriverSettingsW 0 0 350 264 350 0 Driver Settings Qt::Horizontal 40 20 Qt::Horizontal 40 20 Qt::Horizontal 40 20 0 0 Device: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Buffer size: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Sample rate: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal 40 20 Triple buffer Qt::Horizontal 40 20 Qt::Horizontal QSizePolicy::Preferred 40 20 32 0 Show Driver Control Panel Qt::Horizontal QSizePolicy::Preferred 40 20 Qt::Horizontal 40 20 22 22 :/16x16/dialog-information.svgz true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Restart the engine to load the new settings Qt::Horizontal 40 20 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() DriverSettingsW accept() 248 254 157 274 buttonBox rejected() DriverSettingsW reject() 316 260 286 274 Carla-2.1/resources/ui/inputdialog_value.ui000066400000000000000000000036471364475620200211220ustar00rootroot00000000000000 Dialog 0 0 269 183 Set value TextLabel Scale Points Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() Dialog accept() 248 254 157 274 buttonBox rejected() Dialog reject() 316 260 286 274 Carla-2.1/resources/ui/midipattern.ui000066400000000000000000000276631364475620200177330ustar00rootroot00000000000000 MidiPatternW 0 0 755 436 MIDI Pattern 30 20 30 20 Time Signature: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter true 0 1/4 2/4 3/4 4/4 5/4 6/4 Qt::Horizontal QSizePolicy::Fixed 5 5 Measures: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Qt::Horizontal QSizePolicy::Fixed 5 5 Default Length: 4 1/16 1/15 1/12 1/9 1/8 1/6 1/4 1/3 1/2 1 Qt::Horizontal QSizePolicy::Fixed 5 5 Quantize: 4 1/16 1/15 1/12 1/9 1/8 1/6 1/4 1/3 1/2 1 Qt::Horizontal QSizePolicy::Fixed 5 5 Qt::Horizontal Qt::Vertical 0 0 755 20 &File &Edit &Quit true &Insert Mode F true &Velocity Mode D Select All A PianoRollView QGraphicsView
widgets/pianoroll.h
ModeIndicator QWidget
widgets/pianoroll.h
1
act_file_quit triggered() MidiPatternW close() -1 -1 377 217
Carla-2.1/source/000077500000000000000000000000001364475620200137075ustar00rootroot00000000000000Carla-2.1/source/Makefile.mk000066400000000000000000000435111364475620200157610ustar00rootroot00000000000000#!/usr/bin/make -f # Makefile for Carla C++ code # # --------------------------- # # Created by falkTX # # --------------------------------------------------------------------------------------------------------------------- # Base environment vars AR ?= ar CC ?= gcc CXX ?= g++ WINECC ?= winegcc # --------------------------------------------------------------------------------------------------------------------- # Auto-detect OS if not defined ifneq ($(BSD),true) ifneq ($(HAIKU),true) ifneq ($(HURD),true) ifneq ($(LINUX),true) ifneq ($(MACOS),true) ifneq ($(WIN32),true) TARGET_MACHINE := $(shell $(CC) -dumpmachine) ifneq (,$(findstring bsd,$(TARGET_MACHINE))) BSD=true endif ifneq (,$(findstring haiku,$(TARGET_MACHINE))) HAIKU=true endif ifneq (,$(findstring gnu,$(TARGET_MACHINE))) HURD=true endif ifneq (,$(findstring linux,$(TARGET_MACHINE))) LINUX=true endif ifneq (,$(findstring apple,$(TARGET_MACHINE))) MACOS=true endif ifneq (,$(findstring mingw,$(TARGET_MACHINE))) WIN32=true endif endif endif endif endif endif endif # --------------------------------------------------------------------------------------------------------------------- # Set LINUX_OR_MACOS ifeq ($(LINUX),true) LINUX_OR_MACOS=true endif ifeq ($(MACOS),true) LINUX_OR_MACOS=true endif # --------------------------------------------------------------------------------------------------------------------- # Set MACOS_OR_WIN32 ifeq ($(MACOS),true) MACOS_OR_WIN32=true endif ifeq ($(WIN32),true) MACOS_OR_WIN32=true endif # --------------------------------------------------------------------------------------------------------------------- # Set UNIX ifeq ($(BSD),true) UNIX=true endif ifeq ($(HURD),true) UNIX=true endif ifeq ($(LINUX),true) UNIX=true endif ifeq ($(MACOS),true) UNIX=true endif # --------------------------------------------------------------------------------------------------------------------- # Set USING_JUCE ifeq ($(MACOS_OR_WIN32),true) USING_JUCE=true endif # --------------------------------------------------------------------------------------------------------------------- # Set build and link flags BASE_FLAGS = -Wall -Wextra -pipe -DBUILDING_CARLA -DREAL_BUILD -MD -MP BASE_OPTS = -O3 -ffast-math -mtune=generic -msse -msse2 -mfpmath=sse -fdata-sections -ffunction-sections ifeq ($(MACOS),true) # MacOS linker flags BASE_FLAGS += -Wno-deprecated-declarations LINK_OPTS = -fdata-sections -ffunction-sections -Wl,-dead_strip -Wl,-dead_strip_dylibs else # Common linker flags LINK_OPTS = -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed ifneq ($(SKIP_STRIPPING),true) LINK_OPTS += -Wl,--strip-all endif endif ifeq ($(NOOPT),true) # No CPU-specific optimization flags BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections -DBUILDING_CARLA_NOOPT endif ifeq ($(WIN32),true) # mingw has issues with this specific optimization # See https://github.com/falkTX/Carla/issues/696 BASE_OPTS += -fno-rerun-cse-after-loop # See https://github.com/falkTX/Carla/issues/855 BASE_OPTS += -mstackrealign ifeq ($(BUILDING_FOR_WINDOWS),true) BASE_FLAGS += -DBUILDING_CARLA_FOR_WINDOWS endif else # Not needed for Windows BASE_FLAGS += -fPIC -DPIC endif ifeq ($(CLANG),true) BASE_FLAGS += -Wabsolute-value endif ifeq ($(DEBUG),true) BASE_FLAGS += -DDEBUG -O0 -g LINK_OPTS = else BASE_FLAGS += -DNDEBUG $(BASE_OPTS) -fvisibility=hidden CXXFLAGS += -fvisibility-inlines-hidden endif 32BIT_FLAGS = -m32 64BIT_FLAGS = -m64 ARM32_FLAGS = -mcpu=cortex-a7 -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard -mvectorize-with-neon-quad BUILD_C_FLAGS = $(BASE_FLAGS) -std=gnu99 $(CFLAGS) BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=gnu++0x $(CXXFLAGS) LINK_FLAGS = $(LINK_OPTS) $(LDFLAGS) ifneq ($(MACOS),true) # Not available on MacOS LINK_FLAGS += -Wl,--no-undefined endif ifeq ($(MACOS_OLD),true) BUILD_CXX_FLAGS = $(BASE_FLAGS) $(CXXFLAGS) -DHAVE_CPP11_SUPPORT=0 endif ifeq ($(WIN32),true) # Always build statically on windows LINK_FLAGS += -static endif # --------------------------------------------------------------------------------------------------------------------- # Strict test build ifeq ($(TESTBUILD),true) BASE_FLAGS += -Werror -Wabi=98 -Wcast-qual -Wclobbered -Wconversion -Wdisabled-optimization BASE_FLAGS += -Wdouble-promotion -Wfloat-equal -Wlogical-op -Wpointer-arith -Wsign-conversion BASE_FLAGS += -Wformat=2 -Woverlength-strings BASE_FLAGS += -Wformat-truncation=2 -Wformat-overflow=2 BASE_FLAGS += -Wstringop-overflow=4 -Wstringop-truncation BASE_FLAGS += -Wmissing-declarations -Wredundant-decls BASE_FLAGS += -Wshadow -Wundef -Wuninitialized -Wunused BASE_FLAGS += -Wstrict-aliasing -fstrict-aliasing BASE_FLAGS += -Wstrict-overflow -fstrict-overflow BASE_FLAGS += -Wduplicated-branches -Wduplicated-cond -Wnull-dereference CFLAGS += -Winit-self -Wjump-misses-init -Wmissing-prototypes -Wnested-externs -Wstrict-prototypes -Wwrite-strings CXXFLAGS += -Wc++0x-compat -Wc++11-compat CXXFLAGS += -Wnon-virtual-dtor -Woverloaded-virtual # CXXFLAGS += -Wold-style-cast -Wuseless-cast CXXFLAGS += -Wzero-as-null-pointer-constant ifneq ($(DEBUG),true) CXXFLAGS += -Weffc++ endif ifeq ($(LINUX),true) BASE_FLAGS += -isystem /opt/kxstudio/include endif ifeq ($(MACOS),true) CXXFLAGS += -isystem /System/Library/Frameworks endif ifeq ($(WIN32),true) BASE_FLAGS += -isystem /opt/mingw32/include endif ifeq ($(WIN64),true) BASE_FLAGS += -isystem /opt/mingw64/include endif endif # --------------------------------------------------------------------------------------------------------------------- # Check for optional libs (required by backend or bridges) ifeq ($(LINUX),true) HAVE_ALSA = $(shell pkg-config --exists alsa && echo true) HAVE_HYLIA = true endif ifeq ($(MACOS),true) ifneq ($(MACOS_OLD),true) HAVE_HYLIA = true endif endif ifeq ($(WIN32),true) HAVE_HYLIA = true endif ifeq ($(MACOS_OR_WIN32),true) HAVE_DGL = true else HAVE_DGL = $(shell pkg-config --exists gl x11 && echo true) HAVE_GTK2 = $(shell pkg-config --exists gtk+-2.0 && echo true) HAVE_GTK3 = $(shell pkg-config --exists gtk+-3.0 && echo true) HAVE_X11 = $(shell pkg-config --exists x11 && echo true) endif ifeq ($(UNIX),true) ifneq ($(MACOS),true) HAVE_PULSEAUDIO = $(shell pkg-config --exists libpulse-simple && echo true) endif endif # ffmpeg values taken from https://ffmpeg.org/download.html (v2.8.15 maximum) HAVE_FFMPEG = $(shell pkg-config --max-version=56.60.100 libavcodec && \ pkg-config --max-version=56.40.101 libavformat && \ pkg-config --max-version=54.31.100 libavutil && echo true) HAVE_FLUIDSYNTH = $(shell pkg-config --atleast-version=1.1.7 fluidsynth && echo true) HAVE_JACK = $(shell pkg-config --exists jack && echo true) HAVE_LIBLO = $(shell pkg-config --exists liblo && echo true) HAVE_QT4 = $(shell pkg-config --exists QtCore QtGui && echo true) HAVE_QT5 = $(shell pkg-config --exists Qt5Core Qt5Gui Qt5Widgets && \ pkg-config --variable=qt_config Qt5Core | grep -q -v "static" && echo true) HAVE_SNDFILE = $(shell pkg-config --exists sndfile && echo true) ifeq ($(JACKBRIDGE_DIRECT),true) ifeq ($(HAVE_JACK),true) BASE_FLAGS += -DJACKBRIDGE_DIRECT else $(error jackbridge direct mode requested, but jack not available) endif endif # --------------------------------------------------------------------------------------------------------------------- # Check for optional libs (special non-pkgconfig tests) ifneq ($(WIN32),true) # libmagic doesn't have a pkg-config file, so we need to call the compiler to test it HAVE_LIBMAGIC = $(shell echo '\#include ' | $(CC) $(CFLAGS) -x c -w -c - -o .libmagic-tmp 2>/dev/null && echo true) endif # --------------------------------------------------------------------------------------------------------------------- # Set Qt tools ifeq ($(HAVE_QT4),true) MOC_QT4 ?= $(shell pkg-config --variable=moc_location QtCore) RCC_QT4 ?= $(shell pkg-config --variable=rcc_location QtCore) UIC_QT4 ?= $(shell pkg-config --variable=uic_location QtCore) ifeq (,$(wildcard $(MOC_QT4))) HAVE_QT4=false endif ifeq (,$(wildcard $(RCC_QT4))) HAVE_QT4=false endif endif ifeq ($(HAVE_QT5),true) QT5_HOSTBINS = $(shell pkg-config --variable=host_bins Qt5Core) MOC_QT5 ?= $(QT5_HOSTBINS)/moc RCC_QT5 ?= $(QT5_HOSTBINS)/rcc UIC_QT5 ?= $(QT5_HOSTBINS)/uic ifeq (,$(wildcard $(MOC_QT5))) HAVE_QT5=false endif ifeq (,$(wildcard $(RCC_QT5))) HAVE_QT5=false endif endif ifeq ($(HAVE_QT4),true) HAVE_QT=true endif ifeq ($(HAVE_QT5),true) HAVE_QT=true endif ifeq ($(WIN32),true) HAVE_QT=true endif # --------------------------------------------------------------------------------------------------------------------- # Set PyQt tools PYRCC5 ?= $(shell which pyrcc5 2>/dev/null) PYUIC5 ?= $(shell which pyuic5 2>/dev/null) ifneq ($(PYUIC5),) ifneq ($(PYRCC5),) HAVE_PYQT=true endif endif # --------------------------------------------------------------------------------------------------------------------- # Set PyQt tools, part2 PYRCC ?= $(PYRCC5) PYUIC ?= $(PYUIC5) ifeq ($(HAVE_QT5),true) HAVE_THEME = true else ifeq ($(MACOS),true) ifeq ($(HAVE_PYQT),true) HAVE_THEME = true endif endif endif # --------------------------------------------------------------------------------------------------------------------- # Set base defines ifeq ($(HAVE_DGL),true) BASE_FLAGS += -DHAVE_DGL BASE_FLAGS += -DDGL_NAMESPACE=CarlaDGL -DDGL_FILE_BROWSER_DISABLED -DDGL_NO_SHARED_RESOURCES endif ifeq ($(HAVE_FLUIDSYNTH),true) BASE_FLAGS += -DHAVE_FLUIDSYNTH endif ifeq ($(HAVE_FFMPEG),true) BASE_FLAGS += -DHAVE_FFMPEG endif ifeq ($(HAVE_HYLIA),true) BASE_FLAGS += -DHAVE_HYLIA endif ifeq ($(HAVE_LIBLO),true) BASE_FLAGS += -DHAVE_LIBLO endif ifeq ($(HAVE_LIBMAGIC),true) BASE_FLAGS += -DHAVE_LIBMAGIC endif ifeq ($(HAVE_PYQT),true) BASE_FLAGS += -DHAVE_PYQT endif ifeq ($(HAVE_SNDFILE),true) BASE_FLAGS += -DHAVE_SNDFILE endif ifeq ($(HAVE_X11),true) BASE_FLAGS += -DHAVE_X11 endif ifeq ($(USING_JUCE),true) BASE_FLAGS += -DUSING_JUCE endif # --------------------------------------------------------------------------------------------------------------------- # Set libs stuff (part 1) ifeq ($(LINUX_OR_MACOS),true) LIBDL_LIBS = -ldl endif ifeq ($(WIN32),true) PKG_CONFIG_FLAGS = --static endif ifeq ($(HAVE_DGL),true) ifeq ($(MACOS),true) DGL_LIBS = -framework OpenGL -framework Cocoa endif ifeq ($(WIN32),true) DGL_LIBS = -lopengl32 -lgdi32 endif ifneq ($(MACOS_OR_WIN32),true) DGL_FLAGS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --cflags gl x11) DGL_LIBS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs gl x11) endif endif ifeq ($(HAVE_LIBLO),true) LIBLO_FLAGS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --cflags liblo) LIBLO_LIBS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs liblo) endif ifeq ($(HAVE_LIBMAGIC),true) MAGIC_LIBS += -lmagic ifeq ($(LINUX_OR_MACOS),true) MAGIC_LIBS += -lz endif endif ifeq ($(HAVE_FFMPEG),true) FFMPEG_FLAGS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --cflags libavcodec libavformat libavutil) FFMPEG_LIBS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs libavcodec libavformat libavutil) endif ifeq ($(HAVE_FLUIDSYNTH),true) FLUIDSYNTH_FLAGS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --cflags fluidsynth) FLUIDSYNTH_LIBS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs fluidsynth) endif ifeq ($(HAVE_JACK),true) JACK_FLAGS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --cflags jack) JACK_LIBS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs jack) JACK_LIBDIR = $(shell pkg-config --variable=libdir jack)/jack endif ifeq ($(HAVE_QT5),true) QT5_FLAGS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --cflags Qt5Core Qt5Gui Qt5Widgets) QT5_LIBS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs Qt5Core Qt5Gui Qt5Widgets) endif ifeq ($(HAVE_SNDFILE),true) SNDFILE_FLAGS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --cflags sndfile) SNDFILE_LIBS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs sndfile) endif ifeq ($(HAVE_X11),true) X11_FLAGS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --cflags x11) X11_LIBS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs x11) endif # --------------------------------------------------------------------------------------------------------------------- # Set libs stuff (part 2) ifneq ($(USING_JUCE),true) RTAUDIO_FLAGS = -DHAVE_GETTIMEOFDAY RTMIDI_FLAGS = ifeq ($(DEBUG),true) RTAUDIO_FLAGS += -D__RTAUDIO_DEBUG__ RTMIDI_FLAGS += -D__RTMIDI_DEBUG__ endif ifeq ($(UNIX),true) RTAUDIO_FLAGS += -D__UNIX_JACK__ ifeq ($(HAVE_PULSEAUDIO),true) RTAUDIO_FLAGS += $(shell pkg-config $(PKG_CONFIG_FLAGS) --cflags libpulse-simple) -D__UNIX_PULSE__ RTAUDIO_LIBS += $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs libpulse-simple) endif endif endif # USING_JUCE ifeq ($(BSD),true) JACKBRIDGE_LIBS = -lpthread -lrt LILV_LIBS = -lm -lrt RTMEMPOOL_LIBS = -lpthread WATER_LIBS = -lpthread -lrt endif ifeq ($(HAIKU),true) JACKBRIDGE_LIBS = -lpthread LILV_LIBS = -lm RTMEMPOOL_LIBS = -lpthread WATER_LIBS = -lpthread endif ifeq ($(HURD),true) JACKBRIDGE_LIBS = -ldl -lpthread -lrt LILV_LIBS = -ldl -lm -lrt RTMEMPOOL_LIBS = -lpthread -lrt WATER_LIBS = -ldl -lpthread -lrt endif ifeq ($(LINUX),true) HYLIA_FLAGS = -DLINK_PLATFORM_LINUX=1 JACKBRIDGE_LIBS = -ldl -lpthread -lrt LILV_LIBS = -ldl -lm -lrt RTMEMPOOL_LIBS = -lpthread -lrt WATER_LIBS = -ldl -lpthread -lrt ifeq ($(USING_JUCE),true) JUCE_AUDIO_DEVICES_LIBS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs alsa) JUCE_CORE_LIBS = -ldl -lpthread -lrt JUCE_EVENTS_LIBS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs x11) JUCE_GRAPHICS_LIBS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs freetype2) JUCE_GUI_BASICS_LIBS = $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs x11 xext) else ifeq ($(HAVE_ALSA),true) RTAUDIO_FLAGS += $(shell pkg-config $(PKG_CONFIG_FLAGS) --cflags alsa) -D__LINUX_ALSA__ RTAUDIO_LIBS += $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs alsa) -lpthread RTMIDI_FLAGS += $(shell pkg-config $(PKG_CONFIG_FLAGS) --cflags alsa) -D__LINUX_ALSA__ RTMIDI_LIBS += $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs alsa) endif endif endif ifeq ($(MACOS),true) HYLIA_FLAGS = -DLINK_PLATFORM_MACOSX=1 JACKBRIDGE_LIBS = -ldl -lpthread LILV_LIBS = -ldl -lm RTMEMPOOL_LIBS = -lpthread WATER_LIBS = -framework AppKit ifeq ($(USING_JUCE),true) JUCE_AUDIO_BASICS_LIBS = -framework Accelerate JUCE_AUDIO_DEVICES_LIBS = -framework AppKit -framework AudioToolbox -framework CoreAudio -framework CoreMIDI JUCE_AUDIO_FORMATS_LIBS = -framework AudioToolbox -framework CoreFoundation JUCE_AUDIO_PROCESSORS_LIBS = -framework AudioToolbox -framework AudioUnit -framework CoreAudio -framework CoreAudioKit -framework Cocoa -framework Carbon JUCE_CORE_LIBS = -framework AppKit JUCE_EVENTS_LIBS = -framework AppKit JUCE_GRAPHICS_LIBS = -framework Cocoa -framework QuartzCore JUCE_GUI_BASICS_LIBS = -framework Cocoa JUCE_GUI_EXTRA_LIBS = -framework IOKit else RTAUDIO_FLAGS += -D__MACOSX_CORE__ RTAUDIO_LIBS += -framework CoreAudio RTMIDI_FLAGS += -D__MACOSX_CORE__ RTMIDI_LIBS += -framework CoreMIDI endif endif ifeq ($(WIN32),true) HYLIA_FLAGS = -DLINK_PLATFORM_WINDOWS=1 HYLIA_LIBS = -liphlpapi JACKBRIDGE_LIBS = -lpthread LILV_LIBS = -lm RTMEMPOOL_LIBS = -lpthread WATER_LIBS = -luuid -lwsock32 -lwininet -lversion -lole32 -lws2_32 -loleaut32 -limm32 -lcomdlg32 -lshlwapi -lrpcrt4 -lwinmm ifeq ($(USING_JUCE),true) JUCE_AUDIO_DEVICES_LIBS = -lwinmm -lole32 JUCE_CORE_LIBS = -luuid -lwsock32 -lwininet -lversion -lole32 -lws2_32 -loleaut32 -limm32 -lcomdlg32 -lshlwapi -lrpcrt4 -lwinmm JUCE_GRAPHICS_LIBS = -lgdi32 JUCE_GUI_BASICS_LIBS = -lgdi32 -limm32 -lcomdlg32 -lole32 else RTAUDIO_FLAGS += -D__WINDOWS_ASIO__ -D__WINDOWS_DS__ -D__WINDOWS_WASAPI__ RTAUDIO_LIBS += -ldsound -luuid -lksuser -lwinmm RTMIDI_FLAGS += -D__WINDOWS_MM__ endif endif # --------------------------------------------------------------------------------------------------------------------- AUDIO_DECODER_LIBS = $(FFMPEG_LIBS) AUDIO_DECODER_LIBS += $(SNDFILE_LIBS) NATIVE_PLUGINS_LIBS += $(DGL_LIBS) NATIVE_PLUGINS_LIBS += $(FFMPEG_LIBS) NATIVE_PLUGINS_LIBS += $(SNDFILE_LIBS) # --------------------------------------------------------------------------------------------------------------------- # Set app extension ifeq ($(WIN32),true) APP_EXT = .exe endif # --------------------------------------------------------------------------------------------------------------------- # Set shared lib extension LIB_EXT = .so ifeq ($(MACOS),true) LIB_EXT = .dylib endif ifeq ($(WIN32),true) LIB_EXT = .dll endif BASE_FLAGS += -DCARLA_LIB_EXT=\"$(LIB_EXT)\" # --------------------------------------------------------------------------------------------------------------------- # Set static libs start & end ifneq ($(MACOS),true) LIBS_START = -Wl,--start-group LIBS_END = -Wl,--end-group endif # --------------------------------------------------------------------------------------------------------------------- # Set shared library CLI arg ifeq ($(MACOS),true) SHARED = -dynamiclib else SHARED = -shared endif # --------------------------------------------------------------------------------------------------------------------- # Set arguments used for inline 'sed' ifeq ($(BSD),true) SED_ARGS=-i '' -e else SED_ARGS=-i -e endif # --------------------------------------------------------------------------------------------------------------------- # Set command used for file symlinking LINK := ln -sf # --------------------------------------------------------------------------------------------------------------------- ifneq ($(DEBUG),true) ifneq ($(TESTBUILD),true) ifneq (,$(wildcard $(CWD)/native-plugins/external/Makefile.mk)) EXTERNAL_PLUGINS = true BASE_FLAGS += -DHAVE_EXTERNAL_PLUGINS include $(CWD)/native-plugins/external/Makefile.mk endif endif endif # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/000077500000000000000000000000001364475620200152765ustar00rootroot00000000000000Carla-2.1/source/backend/CarlaBackend.doxygen000066400000000000000000000240601364475620200211710ustar00rootroot00000000000000# Doxyfile 1.7.6.1 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "Carla Backend" PROJECT_NUMBER = PROJECT_BRIEF = PROJECT_LOGO = OUTPUT_DIRECTORY = ../../doc/CarlaBackend CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 4 ALIASES = TCL_SUBST = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO EXTENSION_MAPPING = BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES INLINE_GROUPED_CLASSES = NO INLINE_SIMPLE_STRUCTS = NO TYPEDEF_HIDES_STRUCT = YES SYMBOL_CACHE_SIZE = 0 LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = YES EXTRACT_PRIVATE = NO EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = YES EXTRACT_ANON_NSPACES = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES SORT_MEMBER_DOCS = NO SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO STRICT_PROTO_MATCHING = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_DIRECTORIES = NO SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = LAYOUT_FILE = CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = INPUT_ENCODING = UTF-8 FILE_PATTERNS = RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO REFERENCES_LINK_SOURCE = YES USE_HTAGS = NO VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = YES COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = . HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 HTML_TIMESTAMP = YES HTML_ALIGN_MEMBERS = YES HTML_DYNAMIC_SECTIONS = NO GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project DOCSET_PUBLISHER_ID = org.doxygen.Publisher DOCSET_PUBLISHER_NAME = Publisher GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO CHM_INDEX_ENCODING = BINARY_TOC = NO TOC_EXPAND = NO GENERATE_QHP = NO QCH_FILE = QHP_NAMESPACE = org.doxygen.Project QHP_VIRTUAL_FOLDER = doc QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = QHG_LOCATION = GENERATE_ECLIPSEHELP = NO ECLIPSE_DOC_ID = org.doxygen.Project DISABLE_INDEX = NO GENERATE_TREEVIEW = NO ENUM_VALUES_PER_LINE = 4 USE_INLINE_TREES = NO TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES USE_MATHJAX = NO MATHJAX_RELPATH = http://www.mathjax.org/mathjax MATHJAX_EXTENSIONS = SEARCHENGINE = YES SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4 EXTRA_PACKAGES = LATEX_HEADER = LATEX_FOOTER = PDF_HYPERLINKS = YES USE_PDFLATEX = YES LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO LATEX_SOURCE_CODE = NO LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = DOXYGEN \ BUILDING_CARLA REAL_BUILD \ HAVE_DGL HAVE_LIBLO HAVE_LIBMAGIC HAVE_FLUIDSYNTH HAVE_PROJECTM HAVE_X11 \ HAVE_ZYN_DEPS HAVE_ZYN_UI_DEPS EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES MSCGEN_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO DOT_NUM_THREADS = 0 DOT_FONTNAME = Helvetica DOT_FONTSIZE = 10 DOT_FONTPATH = CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png INTERACTIVE_SVG = NO DOT_PATH = DOTFILE_DIRS = MSCFILE_DIRS = DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = YES GENERATE_LEGEND = YES DOT_CLEANUP = YES Carla-2.1/source/backend/CarlaBackend.h000066400000000000000000001224661364475620200177540ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_BACKEND_H_INCLUDED #define CARLA_BACKEND_H_INCLUDED #include "CarlaDefines.h" #ifdef CARLA_PROPER_CPP11_SUPPORT # include #else # include #endif #define STR_MAX 0xFF #ifdef __cplusplus # define CARLA_BACKEND_START_NAMESPACE namespace CarlaBackend { # define CARLA_BACKEND_END_NAMESPACE } # define CARLA_BACKEND_USE_NAMESPACE using namespace CarlaBackend; # include # include # include /* Start namespace */ CARLA_BACKEND_START_NAMESPACE #endif /*! * @defgroup CarlaBackendAPI Carla Backend API * * The Carla Backend API. * * These are the base definitions for everything in the Carla backend code. * @{ */ /* ------------------------------------------------------------------------------------------------------------ * Carla Backend API (base definitions) */ /*! * Maximum default number of loadable plugins. */ static const uint MAX_DEFAULT_PLUGINS = 99; /*! * Maximum number of loadable plugins in rack mode. */ static const uint MAX_RACK_PLUGINS = 16; /*! * Maximum number of loadable plugins in patchbay mode. */ static const uint MAX_PATCHBAY_PLUGINS = 255; /*! * Maximum default number of parameters allowed. * @see ENGINE_OPTION_MAX_PARAMETERS */ static const uint MAX_DEFAULT_PARAMETERS = 200; /*! * The "plugin Id" for the global Carla instance. * Currently only used for audio peaks. */ static const uint MAIN_CARLA_PLUGIN_ID = 0xFFFF; /* ------------------------------------------------------------------------------------------------------------ * Engine Driver Device Hints */ /*! * @defgroup EngineDriverHints Engine Driver Device Hints * * Various engine driver device hints. * @see CarlaEngine::getHints(), CarlaEngine::getDriverDeviceInfo() and carla_get_engine_driver_device_info() * @{ */ /*! * Engine driver device has custom control-panel. */ static const uint ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL = 0x1; /*! * Engine driver device can use a triple-buffer (3 number of periods instead of the usual 2). * @see ENGINE_OPTION_AUDIO_NUM_PERIODS */ static const uint ENGINE_DRIVER_DEVICE_CAN_TRIPLE_BUFFER = 0x2; /*! * Engine driver device can change buffer-size on the fly. * @see ENGINE_OPTION_AUDIO_BUFFER_SIZE */ static const uint ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE = 0x4; /*! * Engine driver device can change sample-rate on the fly. * @see ENGINE_OPTION_AUDIO_SAMPLE_RATE */ static const uint ENGINE_DRIVER_DEVICE_VARIABLE_SAMPLE_RATE = 0x8; /** @} */ /* ------------------------------------------------------------------------------------------------------------ * Plugin Hints */ /*! * @defgroup PluginHints Plugin Hints * * Various plugin hints. * @see CarlaPlugin::getHints() and carla_get_plugin_info() * @{ */ /*! * Plugin is a bridge. * This hint is required because "bridge" itself is not a plugin type. */ static const uint PLUGIN_IS_BRIDGE = 0x001; /*! * Plugin is hard real-time safe. */ static const uint PLUGIN_IS_RTSAFE = 0x002; /*! * Plugin is a synth (produces sound). */ static const uint PLUGIN_IS_SYNTH = 0x004; /*! * Plugin has its own custom UI. * @see CarlaPlugin::showCustomUI() and carla_show_custom_ui() */ static const uint PLUGIN_HAS_CUSTOM_UI = 0x008; /*! * Plugin can use internal Dry/Wet control. */ static const uint PLUGIN_CAN_DRYWET = 0x010; /*! * Plugin can use internal Volume control. */ static const uint PLUGIN_CAN_VOLUME = 0x020; /*! * Plugin can use internal (Stereo) Balance controls. */ static const uint PLUGIN_CAN_BALANCE = 0x040; /*! * Plugin can use internal (Mono) Panning control. */ static const uint PLUGIN_CAN_PANNING = 0x080; /*! * Plugin needs a constant, fixed-size audio buffer. */ static const uint PLUGIN_NEEDS_FIXED_BUFFERS = 0x100; /*! * Plugin needs to receive all UI events in the main thread. */ static const uint PLUGIN_NEEDS_UI_MAIN_THREAD = 0x200; /*! * Plugin uses 1 program per MIDI channel. * @note: Only used in some internal plugins and sf2 files. */ static const uint PLUGIN_USES_MULTI_PROGS = 0x400; /*! * Plugin can make use of inline display API. */ static const uint PLUGIN_HAS_INLINE_DISPLAY = 0x800; /** @} */ /* ------------------------------------------------------------------------------------------------------------ * Plugin Options */ /*! * @defgroup PluginOptions Plugin Options * * Various plugin options. * @note Do not modify these values, as they are saved as-is in project files. * @see CarlaPlugin::getOptionsAvailable(), CarlaPlugin::getOptionsEnabled(), carla_get_plugin_info() and carla_set_option() * @{ */ /*! * Use constant/fixed-size audio buffers. */ static const uint PLUGIN_OPTION_FIXED_BUFFERS = 0x001; /*! * Force mono plugin as stereo. */ static const uint PLUGIN_OPTION_FORCE_STEREO = 0x002; /*! * Map MIDI programs to plugin programs. */ static const uint PLUGIN_OPTION_MAP_PROGRAM_CHANGES = 0x004; /*! * Use chunks to save and restore data instead of parameter values. */ static const uint PLUGIN_OPTION_USE_CHUNKS = 0x008; /*! * Send MIDI control change events. */ static const uint PLUGIN_OPTION_SEND_CONTROL_CHANGES = 0x010; /*! * Send MIDI channel pressure events. */ static const uint PLUGIN_OPTION_SEND_CHANNEL_PRESSURE = 0x020; /*! * Send MIDI note after-touch events. */ static const uint PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH = 0x040; /*! * Send MIDI pitch-bend events. */ static const uint PLUGIN_OPTION_SEND_PITCHBEND = 0x080; /*! * Send MIDI all-sounds/notes-off events, single note-offs otherwise. */ static const uint PLUGIN_OPTION_SEND_ALL_SOUND_OFF = 0x100; /*! * Send MIDI bank/program changes. * @note: This option conflicts with PLUGIN_OPTION_MAP_PROGRAM_CHANGES and cannot be used at the same time. */ static const uint PLUGIN_OPTION_SEND_PROGRAM_CHANGES = 0x200; /*! * Special flag to indicate that plugin options are not yet set. * This flag exists because 0x0 as an option value is a valid one, so we need something else to indicate "null-ness". */ static const uint PLUGIN_OPTIONS_NULL = 0x10000; /** @} */ /* ------------------------------------------------------------------------------------------------------------ * Parameter Hints */ /*! * @defgroup ParameterHints Parameter Hints * * Various parameter hints. * @see CarlaPlugin::getParameterData() and carla_get_parameter_data() * @{ */ /*! * Parameter value is boolean. * It's always at either minimum or maximum value. */ static const uint PARAMETER_IS_BOOLEAN = 0x001; /*! * Parameter value is integer. */ static const uint PARAMETER_IS_INTEGER = 0x002; /*! * Parameter value is logarithmic. */ static const uint PARAMETER_IS_LOGARITHMIC = 0x004; /*! * Parameter is enabled. * It can be viewed, changed and stored. */ static const uint PARAMETER_IS_ENABLED = 0x010; /*! * Parameter is automable (real-time safe). */ static const uint PARAMETER_IS_AUTOMABLE = 0x020; /*! * Parameter is read-only. * It cannot be changed. */ static const uint PARAMETER_IS_READ_ONLY = 0x040; /*! * Parameter needs sample rate to work. * Value and ranges are multiplied by sample rate on usage and divided by sample rate on save. */ static const uint PARAMETER_USES_SAMPLERATE = 0x100; /*! * Parameter uses scale points to define internal values in a meaningful way. */ static const uint PARAMETER_USES_SCALEPOINTS = 0x200; /*! * Parameter uses custom text for displaying its value. * @see CarlaPlugin::getParameterText() and carla_get_parameter_text() */ static const uint PARAMETER_USES_CUSTOM_TEXT = 0x400; /*! * Parameter can be turned into a CV control. */ static const uint PARAMETER_CAN_BE_CV_CONTROLLED = 0x800; /** @} */ /* ------------------------------------------------------------------------------------------------------------ * Patchbay Port Hints */ /*! * @defgroup PatchbayPortHints Patchbay Port Hints * * Various patchbay port hints. * @{ */ /*! * Patchbay port is input. * When this hint is not set, port is assumed to be output. */ static const uint PATCHBAY_PORT_IS_INPUT = 0x01; /*! * Patchbay port is of Audio type. */ static const uint PATCHBAY_PORT_TYPE_AUDIO = 0x02; /*! * Patchbay port is of CV type (Control Voltage). */ static const uint PATCHBAY_PORT_TYPE_CV = 0x04; /*! * Patchbay port is of MIDI type. */ static const uint PATCHBAY_PORT_TYPE_MIDI = 0x08; /*! * Patchbay port is of OSC type. */ static const uint PATCHBAY_PORT_TYPE_OSC = 0x10; /** @} */ /* ------------------------------------------------------------------------------------------------------------ * Patchbay Port Group Hints */ /*! * @defgroup PatchbayPortGroupHints Patchbay Port Group Hints * * Various patchbay port group hints. * @{ */ /*! * Indicates that this group should be considered the "main" input. */ static const uint PATCHBAY_PORT_GROUP_MAIN_INPUT = 0x01; /*! * Indicates that this group should be considered the "main" output. */ static const uint PATCHBAY_PORT_GROUP_MAIN_OUTPUT = 0x02; /*! * A stereo port group, where the 1st port is left and the 2nd is right. */ static const uint PATCHBAY_PORT_GROUP_STEREO = 0x04; /*! * A mid-side stereo group, where the 1st port is center and the 2nd is side. */ static const uint PATCHBAY_PORT_GROUP_MID_SIDE = 0x08; /** @} */ /* ------------------------------------------------------------------------------------------------------------ * Custom Data Types */ /*! * @defgroup CustomDataTypes Custom Data Types * * These types define how the value in the CustomData struct is stored. * @see CustomData::type * @{ */ /*! * Boolean string type URI. * Only "true" and "false" are valid values. */ static const char* const CUSTOM_DATA_TYPE_BOOLEAN = "http://kxstudio.sf.net/ns/carla/boolean"; /*! * Chunk type URI. */ static const char* const CUSTOM_DATA_TYPE_CHUNK = "http://kxstudio.sf.net/ns/carla/chunk"; /*! * Property type URI. */ static const char* const CUSTOM_DATA_TYPE_PROPERTY = "http://kxstudio.sf.net/ns/carla/property"; /*! * String type URI. */ static const char* const CUSTOM_DATA_TYPE_STRING = "http://kxstudio.sf.net/ns/carla/string"; /** @} */ /* ------------------------------------------------------------------------------------------------------------ * Custom Data Keys */ /*! * @defgroup CustomDataKeys Custom Data Keys * * Pre-defined keys used internally in Carla. * @see CustomData::key * @{ */ /*! * UI position key. */ static const char* const CUSTOM_DATA_KEY_UI_POSITION = "CarlaUiPosition"; /*! * UI size key. */ static const char* const CUSTOM_DATA_KEY_UI_SIZE = "CarlaUiSize"; /*! * UI visible key. */ static const char* const CUSTOM_DATA_KEY_UI_VISIBLE = "CarlaUiVisible"; /** @} */ /* ------------------------------------------------------------------------------------------------------------ * Binary Type */ /*! * The binary type of a plugin. */ typedef enum { /*! * Null binary type. */ BINARY_NONE = 0, /*! * POSIX 32bit binary. */ BINARY_POSIX32 = 1, /*! * POSIX 64bit binary. */ BINARY_POSIX64 = 2, /*! * Windows 32bit binary. */ BINARY_WIN32 = 3, /*! * Windows 64bit binary. */ BINARY_WIN64 = 4, /*! * Other binary type. */ BINARY_OTHER = 5 } BinaryType; /* ------------------------------------------------------------------------------------------------------------ * File Type */ /*! * File type. */ typedef enum { /*! * Null file type. */ FILE_NONE = 0, /*! * Audio file. */ FILE_AUDIO = 1, /*! * MIDI file. */ FILE_MIDI = 2 } FileType; /* ------------------------------------------------------------------------------------------------------------ * Plugin Type */ /*! * Plugin type. * Some files are handled as if they were plugins. */ typedef enum { /*! * Null plugin type. */ PLUGIN_NONE = 0, /*! * Internal plugin. */ PLUGIN_INTERNAL = 1, /*! * LADSPA plugin. */ PLUGIN_LADSPA = 2, /*! * DSSI plugin. */ PLUGIN_DSSI = 3, /*! * LV2 plugin. */ PLUGIN_LV2 = 4, /*! * VST2 plugin. */ PLUGIN_VST2 = 5, /*! * VST3 plugin. * @note Windows and MacOS only */ PLUGIN_VST3 = 6, /*! * AU plugin. * @note MacOS only */ PLUGIN_AU = 7, /*! * DLS file. */ PLUGIN_DLS = 8, /*! * GIG file. */ PLUGIN_GIG = 9, /*! * SF2/3 file (SoundFont). */ PLUGIN_SF2 = 10, /*! * SFZ file. */ PLUGIN_SFZ = 11, /*! * JACK application. */ PLUGIN_JACK = 12 } PluginType; /* ------------------------------------------------------------------------------------------------------------ * Plugin Category */ /*! * Plugin category, which describes the functionality of a plugin. */ typedef enum { /*! * Null plugin category. */ PLUGIN_CATEGORY_NONE = 0, /*! * A synthesizer or generator. */ PLUGIN_CATEGORY_SYNTH = 1, /*! * A delay or reverb. */ PLUGIN_CATEGORY_DELAY = 2, /*! * An equalizer. */ PLUGIN_CATEGORY_EQ = 3, /*! * A filter. */ PLUGIN_CATEGORY_FILTER = 4, /*! * A distortion plugin. */ PLUGIN_CATEGORY_DISTORTION = 5, /*! * A 'dynamic' plugin (amplifier, compressor, gate, etc). */ PLUGIN_CATEGORY_DYNAMICS = 6, /*! * A 'modulator' plugin (chorus, flanger, phaser, etc). */ PLUGIN_CATEGORY_MODULATOR = 7, /*! * An 'utility' plugin (analyzer, converter, mixer, etc). */ PLUGIN_CATEGORY_UTILITY = 8, /*! * Miscellaneous plugin (used to check if the plugin has a category). */ PLUGIN_CATEGORY_OTHER = 9 } PluginCategory; /* ------------------------------------------------------------------------------------------------------------ * Parameter Type */ /*! * Plugin parameter type. */ typedef enum { /*! * Null parameter type. */ PARAMETER_UNKNOWN = 0, /*! * Input parameter. */ PARAMETER_INPUT = 1, /*! * Output parameter. */ PARAMETER_OUTPUT = 2 } ParameterType; /* ------------------------------------------------------------------------------------------------------------ * Internal Parameter Index */ /*! * Special parameters used internally in Carla. * Plugins do not know about their existence. */ typedef enum { /*! * Null parameter. */ PARAMETER_NULL = -1, #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH /*! * Active parameter, boolean type. * Default is 'false'. */ PARAMETER_ACTIVE = -2, /*! * Dry/Wet parameter. * Range 0.0...1.0; default is 1.0. */ PARAMETER_DRYWET = -3, /*! * Volume parameter. * Range 0.0...1.27; default is 1.0. */ PARAMETER_VOLUME = -4, /*! * Stereo Balance-Left parameter. * Range -1.0...1.0; default is -1.0. */ PARAMETER_BALANCE_LEFT = -5, /*! * Stereo Balance-Right parameter. * Range -1.0...1.0; default is 1.0. */ PARAMETER_BALANCE_RIGHT = -6, /*! * Mono Panning parameter. * Range -1.0...1.0; default is 0.0. */ PARAMETER_PANNING = -7, /*! * MIDI Control channel, integer type. * Range -1...15 (-1 = off). */ PARAMETER_CTRL_CHANNEL = -8, #endif /*! * Max value, defined only for convenience. */ PARAMETER_MAX = -9 } InternalParameterIndex; /* ------------------------------------------------------------------------------------------------------------ * Special Mapped Control Index */ /*! * Specially designated mapped control indexes. * Values between 0 and 119 (0x77) are reserved for MIDI CC, which uses direct values. * @see ParameterData::mappedControlIndex */ typedef enum { /*! * Unused control index, meaning no mapping is enabled. */ CONTROL_INDEX_NONE = -1, /*! * CV control index, meaning the parameter is exposed as CV port. */ CONTROL_INDEX_CV = 130, /*! * Special value to indicate MIDI pitchbend. */ CONTROL_INDEX_MIDI_PITCHBEND = 131, /*! * Highest index allowed for mappings. */ CONTROL_INDEX_MAX_ALLOWED = CONTROL_INDEX_MIDI_PITCHBEND } SpecialMappedControlIndex; /* ------------------------------------------------------------------------------------------------------------ * Engine Callback Opcode */ /*! * Engine callback opcodes. * Front-ends must never block indefinitely during a callback. * @see EngineCallbackFunc, CarlaEngine::setCallback() and carla_set_engine_callback() */ typedef enum { /*! * Debug. * This opcode is undefined and used only for testing purposes. */ ENGINE_CALLBACK_DEBUG = 0, /*! * A plugin has been added. * @a pluginId Plugin Id * @a valueStr Plugin name */ ENGINE_CALLBACK_PLUGIN_ADDED = 1, /*! * A plugin has been removed. * @a pluginId Plugin Id */ ENGINE_CALLBACK_PLUGIN_REMOVED = 2, /*! * A plugin has been renamed. * @a pluginId Plugin Id * @a valueStr New plugin name */ ENGINE_CALLBACK_PLUGIN_RENAMED = 3, /*! * A plugin has become unavailable. * @a pluginId Plugin Id * @a valueStr Related error string */ ENGINE_CALLBACK_PLUGIN_UNAVAILABLE = 4, /*! * A parameter value has changed. * @a pluginId Plugin Id * @a value1 Parameter index * @a valuef New parameter value */ ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED = 5, /*! * A parameter default has changed. * @a pluginId Plugin Id * @a value1 Parameter index * @a valuef New default value */ ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED = 6, #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH /*! * A parameter's mapped control index has changed. * @a pluginId Plugin Id * @a value1 Parameter index * @a value2 New control index */ ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED = 7, /*! * A parameter's MIDI channel has changed. * @a pluginId Plugin Id * @a value1 Parameter index * @a value2 New MIDI channel */ ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED = 8, /*! * A plugin option has changed. * @a pluginId Plugin Id * @a value1 Option * @a value2 New on/off state (1 for on, 0 for off) * @see PluginOptions */ ENGINE_CALLBACK_OPTION_CHANGED = 9, #endif /*! * The current program of a plugin has changed. * @a pluginId Plugin Id * @a value1 New program index */ ENGINE_CALLBACK_PROGRAM_CHANGED = 10, /*! * The current MIDI program of a plugin has changed. * @a pluginId Plugin Id * @a value1 New MIDI program index */ ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED = 11, /*! * A plugin's custom UI state has changed. * @a pluginId Plugin Id * @a value1 New state, as follows: * 0: UI is now hidden * 1: UI is now visible * -1: UI has crashed and should not be shown again */ ENGINE_CALLBACK_UI_STATE_CHANGED = 12, /*! * A note has been pressed. * @a pluginId Plugin Id * @a value1 Channel * @a value2 Note * @a value3 Velocity */ ENGINE_CALLBACK_NOTE_ON = 13, /*! * A note has been released. * @a pluginId Plugin Id * @a value1 Channel * @a value2 Note */ ENGINE_CALLBACK_NOTE_OFF = 14, /*! * A plugin needs update. * @a pluginId Plugin Id */ ENGINE_CALLBACK_UPDATE = 15, /*! * A plugin's data/information has changed. * @a pluginId Plugin Id */ ENGINE_CALLBACK_RELOAD_INFO = 16, /*! * A plugin's parameters have changed. * @a pluginId Plugin Id */ ENGINE_CALLBACK_RELOAD_PARAMETERS = 17, /*! * A plugin's programs have changed. * @a pluginId Plugin Id */ ENGINE_CALLBACK_RELOAD_PROGRAMS = 18, /*! * A plugin state has changed. * @a pluginId Plugin Id */ ENGINE_CALLBACK_RELOAD_ALL = 19, #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH /*! * A patchbay client has been added. * @a pluginId Client Id * @a value1 Client icon * @a value2 Plugin Id (-1 if not a plugin) * @a valueStr Client name * @see PatchbayIcon */ ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED = 20, /*! * A patchbay client has been removed. * @a pluginId Client Id */ ENGINE_CALLBACK_PATCHBAY_CLIENT_REMOVED = 21, /*! * A patchbay client has been renamed. * @a pluginId Client Id * @a valueStr New client name */ ENGINE_CALLBACK_PATCHBAY_CLIENT_RENAMED = 22, /*! * A patchbay client data has changed. * @a pluginId Client Id * @a value1 New icon * @a value2 New plugin Id (-1 if not a plugin) * @see PatchbayIcon */ ENGINE_CALLBACK_PATCHBAY_CLIENT_DATA_CHANGED = 23, /*! * A patchbay port has been added. * @a pluginId Client Id * @a value1 Port Id * @a value2 Port hints * @a value3 Port group Id (0 for none) * @a valueStr Port name * @see PatchbayPortHints */ ENGINE_CALLBACK_PATCHBAY_PORT_ADDED = 24, /*! * A patchbay port has been removed. * @a pluginId Client Id * @a value1 Port Id */ ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED = 25, /*! * A patchbay port has changed (like the name or group Id). * @a pluginId Client Id * @a value1 Port Id * @a value2 Port hints * @a value3 Port group Id (0 for none) * @a valueStr Port name */ ENGINE_CALLBACK_PATCHBAY_PORT_CHANGED = 26, /*! * A patchbay connection has been added. * @a pluginId Connection Id * @a valueStr Out group and port plus in group and port, in "og:op:ig:ip" syntax. */ ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED = 27, /*! * A patchbay connection has been removed. * @a pluginId Connection Id */ ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED = 28, #endif /*! * Engine started. * @a pluginId How many plugins are known to be running * @a value1 Process mode * @a value2 Transport mode * @a value3 Buffer size * @a valuef Sample rate * @a valuestr Engine driver * @see EngineProcessMode * @see EngineTransportMode */ ENGINE_CALLBACK_ENGINE_STARTED = 29, /*! * Engine stopped. */ ENGINE_CALLBACK_ENGINE_STOPPED = 30, /*! * Engine process mode has changed. * @a value1 New process mode * @see EngineProcessMode */ ENGINE_CALLBACK_PROCESS_MODE_CHANGED = 31, /*! * Engine transport mode has changed. * @a value1 New transport mode * @a valueStr New transport features enabled * @see EngineTransportMode */ ENGINE_CALLBACK_TRANSPORT_MODE_CHANGED = 32, /*! * Engine buffer-size changed. * @a value1 New buffer size */ ENGINE_CALLBACK_BUFFER_SIZE_CHANGED = 33, /*! * Engine sample-rate changed. * @a valuef New sample rate */ ENGINE_CALLBACK_SAMPLE_RATE_CHANGED = 34, /*! * A cancelable action has been started or stopped. * @a pluginId Plugin Id the action relates to, -1 for none * @a value1 1 for action started, 0 for stopped * @a valueStr Action name */ ENGINE_CALLBACK_CANCELABLE_ACTION = 35, /*! * Project has finished loading. */ ENGINE_CALLBACK_PROJECT_LOAD_FINISHED = 36, /*! * NSM callback, to be handled by a frontend. * Frontend must call carla_nsm_ready() with opcode as parameter as a response * @a value1 NSM opcode * @a value2 Integer value * @a valueStr String value * @see NsmCallbackOpcode */ ENGINE_CALLBACK_NSM = 37, /*! * Idle frontend. * This is used by the engine during long operations that might block the frontend, * giving it the possibility to idle while the operation is still in place. */ ENGINE_CALLBACK_IDLE = 38, /*! * Show a message as information. * @a valueStr The message */ ENGINE_CALLBACK_INFO = 39, /*! * Show a message as an error. * @a valueStr The message */ ENGINE_CALLBACK_ERROR = 40, /*! * The engine has crashed or malfunctioned and will no longer work. */ ENGINE_CALLBACK_QUIT = 41, /*! * A plugin requested for its inline display to be redrawn. * @a pluginId Plugin Id to redraw */ ENGINE_CALLBACK_INLINE_DISPLAY_REDRAW = 42, /*! * A patchbay port group has been added. * @a pluginId Client Id * @a value1 Group Id (unique value within this client) * @a value2 Group hints * @a valueStr Group name * @see PatchbayPortGroupHints */ ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_ADDED = 43, /*! * A patchbay port group has been removed. * @a pluginId Client Id * @a value1 Group Id */ ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_REMOVED = 44, /*! * A patchbay port group has changed. * @a pluginId Client Id * @a value1 Group Id * @a value2 Group hints * @a valueStr Group name * @see PatchbayPortGroupHints */ ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_CHANGED = 45, /*! * A parameter's mapped range has changed. * @a pluginId Plugin Id * @a value1 Parameter index * @a valueStr New mapped range as "%f:%f" syntax */ ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED = 46 } EngineCallbackOpcode; /* ------------------------------------------------------------------------------------------------------------ * NSM Callback Opcode */ /*! * NSM callback opcodes. * @see ENGINE_CALLBACK_NSM */ typedef enum { /*! * NSM is available and initialized. */ NSM_CALLBACK_INIT = 0, /*! * Error from NSM side. * @a valueInt Error code * @a valueStr Error string */ NSM_CALLBACK_ERROR = 1, /*! * Announce message. * @a valueInt SM Flags (WIP, to be defined) * @a valueStr SM Name */ NSM_CALLBACK_ANNOUNCE = 2, /*! * Open message. * @a valueStr Project filename */ NSM_CALLBACK_OPEN = 3, /*! * Save message. */ NSM_CALLBACK_SAVE = 4, /*! * Session-is-loaded message. */ NSM_CALLBACK_SESSION_IS_LOADED = 5, /*! * Show-optional-gui message. */ NSM_CALLBACK_SHOW_OPTIONAL_GUI = 6, /*! * Hide-optional-gui message. */ NSM_CALLBACK_HIDE_OPTIONAL_GUI = 7 } NsmCallbackOpcode; /* ------------------------------------------------------------------------------------------------------------ * Engine Option */ /*! * Engine options. * @see CarlaEngine::getOptions(), CarlaEngine::setOption() and carla_set_engine_option() */ typedef enum { /*! * Debug. * This option is undefined and used only for testing purposes. */ ENGINE_OPTION_DEBUG = 0, /*! * Set the engine processing mode. * Default is ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS on Linux and ENGINE_PROCESS_MODE_PATCHBAY for all other OSes. * @see EngineProcessMode */ ENGINE_OPTION_PROCESS_MODE = 1, /*! * Set the engine transport mode. * Default is ENGINE_TRANSPORT_MODE_JACK on Linux and ENGINE_TRANSPORT_MODE_INTERNAL for all other OSes. * @see EngineTransportMode */ ENGINE_OPTION_TRANSPORT_MODE = 2, /*! * Force mono plugins as stereo, by running 2 instances at the same time. * Default is false, but always true when process mode is ENGINE_PROCESS_MODE_CONTINUOUS_RACK. * @note Not supported by all plugins * @see PLUGIN_OPTION_FORCE_STEREO */ ENGINE_OPTION_FORCE_STEREO = 3, /*! * Use plugin bridges whenever possible. * Default is no, EXPERIMENTAL. */ ENGINE_OPTION_PREFER_PLUGIN_BRIDGES = 4, /*! * Use UI bridges whenever possible, otherwise UIs will be directly handled in the main backend thread. * Default is yes. */ ENGINE_OPTION_PREFER_UI_BRIDGES = 5, /*! * Make custom plugin UIs always-on-top. * Default is yes. */ ENGINE_OPTION_UIS_ALWAYS_ON_TOP = 6, /*! * Maximum number of parameters allowed. * Default is MAX_DEFAULT_PARAMETERS. */ ENGINE_OPTION_MAX_PARAMETERS = 7, /*! * Reset Xrun counter after project load. */ ENGINE_OPTION_RESET_XRUNS = 8, /*! * Timeout value for how much to wait for UI bridges to respond, in milliseconds. * Default is 4000 (4 seconds). */ ENGINE_OPTION_UI_BRIDGES_TIMEOUT = 9, /*! * Audio buffer size. * Default is 512. */ ENGINE_OPTION_AUDIO_BUFFER_SIZE = 10, /*! * Audio sample rate. * Default is 44100. */ ENGINE_OPTION_AUDIO_SAMPLE_RATE = 11, /*! * Wherever to use 3 audio periods instead of the default 2. * Default is false. */ ENGINE_OPTION_AUDIO_TRIPLE_BUFFER = 12, /*! * Audio driver. * Default depends on platform. */ ENGINE_OPTION_AUDIO_DRIVER = 13, /*! * Audio device (within a driver). * Default unset. */ ENGINE_OPTION_AUDIO_DEVICE = 14, /*! * Wherever to enable OSC support in the engine. */ ENGINE_OPTION_OSC_ENABLED = 15, /*! * The network TCP port to use for OSC. * A value of 0 means use a random port. * A value of < 0 means to not enable the TCP port for OSC. * @note Valid ports begin at 1024 and end at 32767 (inclusive) */ ENGINE_OPTION_OSC_PORT_TCP = 16, /*! * The network UDP port to use for OSC. * A value of 0 means use a random port. * A value of < 0 means to not enable the UDP port for OSC. * @note Disabling this option prevents DSSI UIs from working! * @note Valid ports begin at 1024 and end at 32767 (inclusive) */ ENGINE_OPTION_OSC_PORT_UDP = 17, /*! * Set path used for a specific file type. * Uses value as the file format, valueStr as actual path. */ ENGINE_OPTION_FILE_PATH = 18, /*! * Set path used for a specific plugin type. * Uses value as the plugin format, valueStr as actual path. * @see PluginType */ ENGINE_OPTION_PLUGIN_PATH = 19, /*! * Set path to the binary files. * Default unset. * @note Must be set for plugin and UI bridges to work */ ENGINE_OPTION_PATH_BINARIES = 20, /*! * Set path to the resource files. * Default unset. * @note Must be set for some internal plugins to work */ ENGINE_OPTION_PATH_RESOURCES = 21, /*! * Prevent bad plugin and UI behaviour. * @note: Linux only */ ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR = 22, /*! * Set background color used in the frontend, so backend can do the same for plugin UIs. */ ENGINE_OPTION_FRONTEND_BACKGROUND_COLOR = 23, /*! * Set foreground color used in the frontend, so backend can do the same for plugin UIs. */ ENGINE_OPTION_FRONTEND_FOREGROUND_COLOR = 24, /*! * Set UI scaling used in the frontend, so backend can do the same for plugin UIs. */ ENGINE_OPTION_FRONTEND_UI_SCALE = 25, /*! * Set frontend winId, used to define as parent window for plugin UIs. */ ENGINE_OPTION_FRONTEND_WIN_ID = 26, #if !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH) && !defined(CARLA_OS_WIN) /*! * Set path to wine executable. */ ENGINE_OPTION_WINE_EXECUTABLE = 27, /*! * Enable automatic wineprefix detection. */ ENGINE_OPTION_WINE_AUTO_PREFIX = 28, /*! * Fallback wineprefix to use if automatic detection fails or is disabled, and WINEPREFIX is not set. */ ENGINE_OPTION_WINE_FALLBACK_PREFIX = 29, /*! * Enable realtime priority for Wine application and server threads. */ ENGINE_OPTION_WINE_RT_PRIO_ENABLED = 30, /*! * Base realtime priority for Wine threads. */ ENGINE_OPTION_WINE_BASE_RT_PRIO = 31, /*! * Wine server realtime priority. */ ENGINE_OPTION_WINE_SERVER_RT_PRIO = 32, #endif /*! * Capture console output into debug callbacks. */ ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT = 33 } EngineOption; /* ------------------------------------------------------------------------------------------------------------ * Engine Process Mode */ /*! * Engine process mode. * @see ENGINE_OPTION_PROCESS_MODE */ typedef enum { /*! * Single client mode. * Inputs and outputs are added dynamically as needed by plugins. */ ENGINE_PROCESS_MODE_SINGLE_CLIENT = 0, /*! * Multiple client mode. * It has 1 master client + 1 client per plugin. */ ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS = 1, /*! * Single client, 'rack' mode. * Processes plugins in order of Id, with forced stereo always on. */ ENGINE_PROCESS_MODE_CONTINUOUS_RACK = 2, /*! * Single client, 'patchbay' mode. */ ENGINE_PROCESS_MODE_PATCHBAY = 3, /*! * Special mode, used in plugin-bridges only. */ ENGINE_PROCESS_MODE_BRIDGE = 4 } EngineProcessMode; /* ------------------------------------------------------------------------------------------------------------ * Engine Transport Mode */ /*! * Engine transport mode. * @see ENGINE_OPTION_TRANSPORT_MODE */ typedef enum { /*! * No transport. */ ENGINE_TRANSPORT_MODE_DISABLED = 0, /*! * Internal transport mode. */ ENGINE_TRANSPORT_MODE_INTERNAL = 1, /*! * Transport from JACK. * Only available if driver name is "JACK". */ ENGINE_TRANSPORT_MODE_JACK = 2, /*! * Transport from host, used when Carla is a plugin. */ ENGINE_TRANSPORT_MODE_PLUGIN = 3, /*! * Special mode, used in plugin-bridges only. */ ENGINE_TRANSPORT_MODE_BRIDGE = 4 } EngineTransportMode; /* ------------------------------------------------------------------------------------------------------------ * File Callback Opcode */ /*! * File callback opcodes. * Front-ends must always block-wait for user input. * @see FileCallbackFunc, CarlaEngine::setFileCallback() and carla_set_file_callback() */ typedef enum { /*! * Debug. * This opcode is undefined and used only for testing purposes. */ FILE_CALLBACK_DEBUG = 0, /*! * Open file or folder. */ FILE_CALLBACK_OPEN = 1, /*! * Save file or folder. */ FILE_CALLBACK_SAVE = 2 } FileCallbackOpcode; /* ------------------------------------------------------------------------------------------------------------ * Patchbay Icon */ /*! * The icon of a patchbay client/group. */ enum PatchbayIcon { /*! * Generic application icon. * Used for all non-plugin clients that don't have a specific icon. */ PATCHBAY_ICON_APPLICATION = 0, /*! * Plugin icon. * Used for all plugin clients that don't have a specific icon. */ PATCHBAY_ICON_PLUGIN = 1, /*! * Hardware icon. * Used for hardware (audio or MIDI) clients. */ PATCHBAY_ICON_HARDWARE = 2, /*! * Carla icon. * Used for the main app. */ PATCHBAY_ICON_CARLA = 3, /*! * DISTRHO icon. * Used for DISTRHO based plugins. */ PATCHBAY_ICON_DISTRHO = 4, /*! * File icon. * Used for file type plugins (like SF2 snd SFZ). */ PATCHBAY_ICON_FILE = 5 }; /* ------------------------------------------------------------------------------------------------------------ * Carla Backend API (C stuff) */ /*! * Engine callback function. * Front-ends must never block indefinitely during a callback. * @see EngineCallbackOpcode, CarlaEngine::setCallback() and carla_set_engine_callback() */ typedef void (*EngineCallbackFunc)(void* ptr, EngineCallbackOpcode action, uint pluginId, int value1, int value2, int value3, float valuef, const char* valueStr); /*! * File callback function. * @see FileCallbackOpcode */ typedef const char* (*FileCallbackFunc)(void* ptr, FileCallbackOpcode action, bool isDir, const char* title, const char* filter); /*! * Parameter data. */ typedef struct { /*! * This parameter type. */ ParameterType type; /*! * This parameter hints. * @see ParameterHints */ uint hints; /*! * Index as seen by Carla. */ int32_t index; /*! * Real index as seen by plugins. */ int32_t rindex; /*! * Currently mapped MIDI channel. * Counts from 0 to 15. */ uint8_t midiChannel; /*! * Currently mapped index. * @see SpecialMappedControlIndex */ int16_t mappedControlIndex; /*! * Minimum value that this parameter maps to. */ float mappedMinimum; /*! * Maximum value that this parameter maps to. */ float mappedMaximum; } ParameterData; /*! * Parameter ranges. */ typedef struct _ParameterRanges { /*! * Default value. */ float def; /*! * Minimum value. */ float min; /*! * Maximum value. */ float max; /*! * Regular, single step value. */ float step; /*! * Small step value. */ float stepSmall; /*! * Large step value. */ float stepLarge; #ifdef __cplusplus /*! * Fix the default value within range. */ void fixDefault() noexcept { fixValue(def); } /*! * Fix a value within range. */ void fixValue(float& value) const noexcept { if (value < min) value = min; else if (value > max) value = max; } /*! * Get a fixed value within range. */ const float& getFixedValue(const float& value) const noexcept { if (value <= min) return min; if (value >= max) return max; return value; } /*! * Get a value normalized to 0.0<->1.0. */ float getNormalizedValue(const float& value) const noexcept { const float normValue((value - min) / (max - min)); if (normValue <= 0.0f) return 0.0f; if (normValue >= 1.0f) return 1.0f; return normValue; } /*! * Get a value normalized to 0.0<->1.0, fixed within range. */ float getFixedAndNormalizedValue(const float& value) const noexcept { if (value <= min) return 0.0f; if (value >= max) return 1.0f; const float normValue((value - min) / (max - min)); if (normValue <= 0.0f) return 0.0f; if (normValue >= 1.0f) return 1.0f; return normValue; } /*! * Get a proper value previously normalized to 0.0<->1.0. */ float getUnnormalizedValue(const float& value) const noexcept { if (value <= 0.0f) return min; if (value >= 1.0f) return max; return value * (max - min) + min; } /*! * Get a logarithmic value previously normalized to 0.0<->1.0. */ float getUnnormalizedLogValue(const float& value) const noexcept { if (value <= 0.0f) return min; if (value >= 1.0f) return max; float rmin = min; if (std::abs(min) < std::numeric_limits::epsilon()) rmin = 0.00001f; return rmin * std::pow(max/rmin, value); } #endif /* __cplusplus */ } ParameterRanges; /*! * MIDI Program data. */ typedef struct { /*! * MIDI bank. */ uint32_t bank; /*! * MIDI program. */ uint32_t program; /*! * MIDI program name. */ const char* name; } MidiProgramData; /*! * Custom data, used for saving key:value 'dictionaries'. */ typedef struct { /*! * Value type, in URI form. * @see CustomDataTypes */ const char* type; /*! * Key. * @see CustomDataKeys */ const char* key; /*! * Value. */ const char* value; #ifdef __cplusplus /*! * Check if valid. */ bool isValid() const noexcept { if (type == nullptr || type[0] == '\0') return false; if (key == nullptr || key [0] == '\0') return false; if (value == nullptr) return false; return true; } #endif /* __cplusplus */ } CustomData; /*! * Engine driver device information. */ typedef struct { /*! * This driver device hints. * @see EngineDriverHints */ uint hints; /*! * Available buffer sizes. * Terminated with 0. */ const uint32_t* bufferSizes; /*! * Available sample rates. * Terminated with 0.0. */ const double* sampleRates; } EngineDriverDeviceInfo; /** @} */ #ifdef __cplusplus /* Forward declarations of commonly used Carla classes */ class CarlaEngine; class CarlaEngineClient; class CarlaEngineCVSourcePorts; class CarlaPlugin; /* End namespace */ CARLA_BACKEND_END_NAMESPACE #endif #endif /* CARLA_BACKEND_H_INCLUDED */ Carla-2.1/source/backend/CarlaEngine.hpp000066400000000000000000001075671364475620200201770ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_ENGINE_HPP_INCLUDED #define CARLA_ENGINE_HPP_INCLUDED #include "CarlaBackend.h" namespace water { class MemoryOutputStream; class XmlDocument; } CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- /*! * @defgroup CarlaEngineAPI Carla Engine API * * The Carla Engine API. * @{ */ /*! * The type of an engine. */ enum EngineType { /*! * Null engine type. */ kEngineTypeNull = 0, /*! * JACK engine type. * Provides all processing modes. */ kEngineTypeJack = 1, /*! * JUCE engine type, used to provide Native Audio and MIDI support. */ kEngineTypeJuce = 2, /*! * RtAudio engine type, used to provide Native Audio and MIDI support. */ kEngineTypeRtAudio = 3, /*! * Plugin engine type, used to export the engine as a plugin. */ kEngineTypePlugin = 4, /*! * Bridge engine type, used in BridgePlugin class. */ kEngineTypeBridge = 5, /*! * Dummy engine type, does not send audio or MIDI anywhere. */ kEngineTypeDummy = 6 }; /*! * The type of an engine port. */ enum EnginePortType { /*! * Null port type. */ kEnginePortTypeNull = 0, /*! * Audio port type. * @see CarlaEngineAudioPort */ kEnginePortTypeAudio = 1, /*! * CV port type. * @see CarlaEngineCVPort */ kEnginePortTypeCV = 2, /*! * Event port type (Control or MIDI). * @see CarlaEngineEventPort */ kEnginePortTypeEvent = 3 }; /*! * The type of an engine event. */ enum EngineEventType { /*! * Null port type. */ kEngineEventTypeNull = 0, /*! * Control event type. * @see EngineControlEvent */ kEngineEventTypeControl = 1, /*! * MIDI event type. * @see EngineMidiEvent */ kEngineEventTypeMidi = 2 }; /*! * The type of an engine control event. */ enum EngineControlEventType { /*! * Null event type. */ kEngineControlEventTypeNull = 0, /*! * Parameter event type. * @note Value uses a normalized range of 0.0f<->1.0f. */ kEngineControlEventTypeParameter = 1, /*! * MIDI Bank event type. */ kEngineControlEventTypeMidiBank = 2, /*! * MIDI Program change event type. */ kEngineControlEventTypeMidiProgram = 3, /*! * All sound off event type. */ kEngineControlEventTypeAllSoundOff = 4, /*! * All notes off event type. */ kEngineControlEventTypeAllNotesOff = 5 }; /*! * Special value for EngineEvent channel field, indicating a non-midi parameter event. */ static const uint8_t kEngineEventNonMidiChannel = 0x30; // ----------------------------------------------------------------------- /*! * Engine control event. */ struct CARLA_API EngineControlEvent { EngineControlEventType type; //!< Control-Event type. uint16_t param; //!< Parameter Id, midi bank or midi program. float value; //!< Parameter value, normalized to 0.0f<->1.0f. /*! * Convert this control event into MIDI data. * Returns size. */ uint8_t convertToMidiData(uint8_t channel, uint8_t data[3]) const noexcept; }; /*! * Engine MIDI event. */ struct CARLA_API EngineMidiEvent { static const uint8_t kDataSize = 4; //!< Size of internal data uint8_t port; //!< Port offset (usually 0) uint8_t size; //!< Number of bytes used /*! * MIDI data, without channel bit. * If size > kDataSize, dataExt is used (otherwise NULL). */ uint8_t data[kDataSize]; const uint8_t* dataExt; }; /*! * Engine event. */ struct CARLA_API EngineEvent { EngineEventType type; //!< Event Type; either Control or MIDI uint32_t time; //!< Time offset in frames uint8_t channel; //!< Channel, used for MIDI-related events /*! * Event specific data. */ union { EngineControlEvent ctrl; EngineMidiEvent midi; }; /*! * Fill this event from MIDI data. */ void fillFromMidiData(uint8_t size, const uint8_t* data, uint8_t midiPortOffset) noexcept; }; // ----------------------------------------------------------------------- /*! * Engine options. */ struct CARLA_API EngineOptions { EngineProcessMode processMode; EngineTransportMode transportMode; const char* transportExtra; bool forceStereo; bool resetXruns; bool preferPluginBridges; bool preferUiBridges; bool uisAlwaysOnTop; uint bgColor; uint fgColor; float uiScale; uint maxParameters; uint uiBridgesTimeout; uint audioBufferSize; uint audioSampleRate; bool audioTripleBuffer; const char* audioDriver; const char* audioDevice; #ifndef BUILD_BRIDGE bool oscEnabled; int oscPortTCP; int oscPortUDP; #endif const char* pathAudio; const char* pathMIDI; const char* pathLADSPA; const char* pathDSSI; const char* pathLV2; const char* pathVST2; const char* pathVST3; const char* pathSF2; const char* pathSFZ; const char* binaryDir; const char* resourceDir; bool preventBadBehaviour; uintptr_t frontendWinId; #ifndef CARLA_OS_WIN struct Wine { const char* executable; bool autoPrefix; const char* fallbackPrefix; bool rtPrio; int baseRtPrio; int serverRtPrio; Wine() noexcept; ~Wine() noexcept; CARLA_DECLARE_NON_COPY_STRUCT(Wine) } wine; #endif #ifndef DOXYGEN EngineOptions() noexcept; ~EngineOptions() noexcept; CARLA_DECLARE_NON_COPY_STRUCT(EngineOptions) #endif }; /*! * Engine BBT Time information. */ struct CARLA_API EngineTimeInfoBBT { bool valid; int32_t bar; //!< current bar int32_t beat; //!< current beat-within-bar double tick; //!< current tick-within-beat double barStartTick; float beatsPerBar; //!< time signature "numerator" float beatType; //!< time signature "denominator" double ticksPerBeat; double beatsPerMinute; /*! * Clear. */ void clear() noexcept; #ifndef DOXYGEN EngineTimeInfoBBT() noexcept; EngineTimeInfoBBT(const EngineTimeInfoBBT&) noexcept; #endif }; /*! * Engine Time information. */ struct CARLA_API EngineTimeInfo { bool playing; uint64_t frame; uint64_t usecs; EngineTimeInfoBBT bbt; /*! * Clear. */ void clear() noexcept; #ifndef DOXYGEN EngineTimeInfo() noexcept; EngineTimeInfo(const EngineTimeInfo&) noexcept; EngineTimeInfo& operator=(const EngineTimeInfo&) noexcept; // fast comparison, doesn't check all values bool compareIgnoringRollingFrames(const EngineTimeInfo& timeInfo, uint32_t maxFrames) const noexcept; // quick operator, doesn't check all values bool operator==(const EngineTimeInfo& timeInfo) const noexcept; bool operator!=(const EngineTimeInfo& timeInfo) const noexcept; #endif }; // ----------------------------------------------------------------------- /*! * Carla Engine port (Abstract). * This is the base class for all Carla Engine ports. */ class CARLA_API CarlaEnginePort { protected: /*! * The constructor, protected. * All constructor parameters are constant and will never change in the lifetime of the port. */ CarlaEnginePort(const CarlaEngineClient& client, bool isInputPort, uint32_t indexOffset) noexcept; public: /*! * The destructor. */ virtual ~CarlaEnginePort() noexcept; /*! * Get the type of the port, as provided by the respective subclasses. */ virtual EnginePortType getType() const noexcept = 0; /*! * Initialize the port's internal buffer. */ virtual void initBuffer() noexcept = 0; /*! * Check if this port is an input. */ inline bool isInput() const noexcept { return kIsInput; } /*! * Get the index offset as passed in the constructor. */ inline uint32_t getIndexOffset() const noexcept { return kIndexOffset; } /*! * Get this ports' engine client. */ inline const CarlaEngineClient& getEngineClient() const noexcept { return kClient; } /*! * Set a meta-data property on this port. */ virtual void setMetaData(const char* key, const char* value, const char* type); #ifndef DOXYGEN protected: const CarlaEngineClient& kClient; const bool kIsInput; const uint32_t kIndexOffset; CARLA_DECLARE_NON_COPY_CLASS(CarlaEnginePort) #endif }; /*! * Carla Engine Audio port. */ class CARLA_API CarlaEngineAudioPort : public CarlaEnginePort { public: /*! * The constructor. * All constructor parameters are constant and will never change in the lifetime of the port. */ CarlaEngineAudioPort(const CarlaEngineClient& client, bool isInputPort, uint32_t indexOffset) noexcept; /*! * The destructor. */ ~CarlaEngineAudioPort() noexcept override; /*! * Get the type of the port, in this case kEnginePortTypeAudio. */ inline EnginePortType getType() const noexcept final { return kEnginePortTypeAudio; } /*! * Initialize the port's internal buffer. */ void initBuffer() noexcept override; /*! * Direct access to the port's audio buffer. * May be null. */ inline float* getBuffer() const noexcept { return fBuffer; } #ifndef DOXYGEN protected: float* fBuffer; CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineAudioPort) #endif }; /*! * Carla Engine CV port. */ class CARLA_API CarlaEngineCVPort : public CarlaEnginePort { public: /*! * The constructor. * All constructor parameters are constant and will never change in the lifetime of the port. */ CarlaEngineCVPort(const CarlaEngineClient& client, bool isInputPort, uint32_t indexOffset) noexcept; /*! * The destructor. */ ~CarlaEngineCVPort() noexcept override; /*! * Get the type of the port, in this case kEnginePortTypeCV. */ inline EnginePortType getType() const noexcept final { return kEnginePortTypeCV; } /*! * Initialize the port's internal buffer. */ void initBuffer() noexcept override; /*! * Direct access to the port's CV buffer. * May be null. */ inline float* getBuffer() const noexcept { return fBuffer; } /*! * Get min/max range for this CV port. */ inline void getRange(float& min, float& max) const noexcept { min = fMinimum; max = fMaximum; } /*! * Set min/max range for this CV port. */ void setRange(float min, float max) noexcept; #ifndef DOXYGEN protected: float* fBuffer; float fMinimum, fMaximum; CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineCVPort) #endif }; /*! * Carla Engine Event port. */ class CARLA_API CarlaEngineEventPort : public CarlaEnginePort { public: /*! * The constructor. * All constructor parameters are constant and will never change in the lifetime of the port. */ CarlaEngineEventPort(const CarlaEngineClient& client, bool isInputPort, uint32_t indexOffset) noexcept; /*! * The destructor. */ ~CarlaEngineEventPort() noexcept override; /*! * Get the type of the port, in this case kEnginePortTypeEvent. */ inline EnginePortType getType() const noexcept final { return kEnginePortTypeEvent; } /*! * Initialize the port's internal buffer for @a engine. */ void initBuffer() noexcept override; /*! * Get the number of events present in the buffer. * @note You must only call this for input ports. */ virtual uint32_t getEventCount() const noexcept; /*! * Get the event at @a index. * @note You must only call this for input ports. */ virtual const EngineEvent& getEvent(uint32_t index) const noexcept; /*! * Get the event at @a index, faster unchecked version. */ virtual const EngineEvent& getEventUnchecked(uint32_t index) const noexcept; /*! * Write a control event into the buffer. * @note You must only call this for output ports. */ bool writeControlEvent(uint32_t time, uint8_t channel, const EngineControlEvent& ctrl) noexcept; /*! * Write a control event into the buffer. * Arguments are the same as in the EngineControlEvent struct. * @note You must only call this for output ports. */ virtual bool writeControlEvent(uint32_t time, uint8_t channel, EngineControlEventType type, uint16_t param, float value = 0.0f) noexcept; /*! * Write a MIDI event into the buffer. * @note You must only call this for output ports. */ bool writeMidiEvent(uint32_t time, uint8_t size, const uint8_t* data) noexcept; /*! * Write a MIDI event into the buffer. * @note You must only call this for output ports. */ bool writeMidiEvent(uint32_t time, uint8_t channel, const EngineMidiEvent& midi) noexcept; /*! * Write a MIDI event into the buffer. * Arguments are the same as in the EngineMidiEvent struct. * @note You must only call this for output ports. */ virtual bool writeMidiEvent(uint32_t time, uint8_t channel, uint8_t size, const uint8_t* data) noexcept; #ifndef DOXYGEN protected: const EngineProcessMode kProcessMode; EngineEvent* fBuffer; friend class CarlaPluginInstance; friend class CarlaEngineCVSourcePorts; CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineEventPort) #endif }; // ----------------------------------------------------------------------- /*! * Carla Engine Meta CV Port. * FIXME needs a better name... */ class CARLA_API CarlaEngineCVSourcePorts { public: /*! * The destructor. */ virtual ~CarlaEngineCVSourcePorts(); /*! * Add a CV port as a source of events. */ virtual bool addCVSource(CarlaEngineCVPort* port, uint32_t portIndexOffset); /*! * Remove a CV port as a source of events. */ virtual bool removeCVSource(uint32_t portIndexOffset); /*! * Get events and add them to an event port. * FIXME needs a better name... */ virtual void initPortBuffers(const float* const* buffers, uint32_t frames, bool sampleAccurate, CarlaEngineEventPort* eventPort); /*! * Set value range for a CV port. */ bool setCVSourceRange(uint32_t portIndexOffset, float minimum, float maximum); /*! * Destroy all ports. */ void cleanup(); #ifndef DOXYGEN protected: /** @internal */ struct ProtectedData; ProtectedData* const pData; /*! * The constructor, protected. */ CarlaEngineCVSourcePorts(); CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineCVSourcePorts) #endif }; // ----------------------------------------------------------------------- /*! * Carla Engine Client. * Each plugin requires one client from the engine (created via CarlaEngine::addClient()). * @note This is a virtual class, some engine types provide custom functionality. */ class CARLA_API CarlaEngineClient { public: /*! * The destructor. */ virtual ~CarlaEngineClient() noexcept; /*! * Activate this client. * Client must be deactivated before calling this function. */ virtual void activate() noexcept; /*! * Deactivate this client. * Client must be activated before calling this function. */ virtual void deactivate() noexcept; /*! * Check if the client is activated. */ virtual bool isActive() const noexcept; /*! * Check if the client is ok. * Plugins will refuse to instantiate if this returns false. * @note This is always true in rack and patchbay processing modes. */ virtual bool isOk() const noexcept; /*! * Get the current latency, in samples. */ virtual uint32_t getLatency() const noexcept; /*! * Change the client's latency. */ virtual void setLatency(uint32_t samples) noexcept; /*! * Add a new port of type @a portType. * @note This function does nothing in rack processing mode since ports are static there. */ virtual CarlaEnginePort* addPort(EnginePortType portType, const char* name, bool isInput, uint32_t indexOffset); /*! * Remove a previously added port via addPort(). */ virtual bool removePort(EnginePortType portType, const char* name, bool isInput); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH /*! * Create an instance of CV source ports. * Must be called only once per client. */ virtual CarlaEngineCVSourcePorts* createCVSourcePorts(); #endif /*! * Get this client's engine. */ const CarlaEngine& getEngine() const noexcept; /*! * Get the engine's process mode. */ EngineProcessMode getProcessMode() const noexcept; /*! * Get port count for a type and mode. */ uint getPortCount(EnginePortType portType, bool isInput) const noexcept; /*! * Get an audio port name. */ const char* getAudioPortName(bool isInput, uint index) const noexcept; /*! * Get a CV port name. */ const char* getCVPortName(bool isInput, uint index) const noexcept; /*! * Get an event port name. */ const char* getEventPortName(bool isInput, uint index) const noexcept; #ifndef DOXYGEN protected: /** @internal */ struct ProtectedData; ProtectedData* const pData; /*! * The constructor, protected. */ CarlaEngineClient(ProtectedData* pData); CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineClient) #endif }; // ----------------------------------------------------------------------- /*! * Carla Engine. * @note This is a virtual class for all available engine types available in Carla. */ class CARLA_API CarlaEngine { protected: /*! * The constructor, protected. * @note This only initializes engine data, it doesn't actually start the engine. */ CarlaEngine(); public: /*! * The destructor. * The engine must have been closed before this happens. */ virtual ~CarlaEngine(); // ------------------------------------------------------------------- // Static calls /*! * Get the number of available engine drivers. */ static uint getDriverCount(); /*! * Get the name of the engine driver at @a index. */ static const char* getDriverName(uint index); /*! * Get the device names of the driver at @a index. */ static const char* const* getDriverDeviceNames(uint index); /*! * Get device information about the driver at @a index and name @a driverName. */ static const EngineDriverDeviceInfo* getDriverDeviceInfo(uint index, const char* driverName); /*! * Show a device custom control panel. * @see ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL */ static bool showDriverDeviceControlPanel(uint index, const char* deviceName); /*! * Create a new engine, using driver @a driverName. * Returned value must be deleted when no longer needed. * @note This only initializes engine data, it doesn't actually start the engine. */ static CarlaEngine* newDriverByName(const char* driverName); // ------------------------------------------------------------------- // Constant values /*! * Maximum client name size. */ virtual uint getMaxClientNameSize() const noexcept; /*! * Maximum port name size. */ virtual uint getMaxPortNameSize() const noexcept; /*! * Current number of plugins loaded. */ uint getCurrentPluginCount() const noexcept; /*! * Maximum number of loadable plugins allowed. * This function returns 0 if engine is not started. */ uint getMaxPluginNumber() const noexcept; // ------------------------------------------------------------------- // Virtual, per-engine type calls /*! * Initialize/start the engine, using @a clientName. * When the engine is initialized, you need to call idle() at regular intervals. */ virtual bool init(const char* clientName) = 0; /*! * Close engine. * This function always closes the engine even if it returns false. * In other words, even when something goes wrong when closing the engine it still be closed nonetheless. */ virtual bool close(); /*! * Idle engine. */ virtual void idle() noexcept; /*! * Check if engine is running. */ virtual bool isRunning() const noexcept = 0; /*! * Check if engine is running offline (aka freewheel mode). */ virtual bool isOffline() const noexcept = 0; /*! * Check if engine runs on a constant buffer size value. * Default implementation returns true. */ virtual bool usesConstantBufferSize() const noexcept; /*! * Get engine type. */ virtual EngineType getType() const noexcept = 0; /*! * Get the currently used driver name. */ virtual const char* getCurrentDriverName() const noexcept = 0; /*! * Add new engine client. * @note This function must only be called within a plugin class. */ virtual CarlaEngineClient* addClient(CarlaPlugin* plugin); /*! * Get the current CPU load estimated by the engine. */ virtual float getDSPLoad() const noexcept; /*! * Get the total number of xruns so far. */ virtual uint32_t getTotalXruns() const noexcept; /*! * Clear the xrun count. */ virtual void clearXruns() const noexcept; /*! * Dynamically change buffer size and/or sample rate while engine is running. * @see ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE * @see ENGINE_DRIVER_DEVICE_VARIABLE_SAMPLE_RATE */ virtual bool setBufferSizeAndSampleRate(uint bufferSize, double sampleRate); /*! * Show the custom control panel for the current engine device. * @see ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL */ virtual bool showDeviceControlPanel() const noexcept; // ------------------------------------------------------------------- // Plugin management /*! * Add new plugin. * @see ENGINE_CALLBACK_PLUGIN_ADDED */ bool addPlugin(BinaryType btype, PluginType ptype, const char* filename, const char* name, const char* label, int64_t uniqueId, const void* extra, uint options = PLUGIN_OPTIONS_NULL); /*! * Add new plugin, using native binary type. * @see ENGINE_CALLBACK_PLUGIN_ADDED */ bool addPlugin(PluginType ptype, const char* filename, const char* name, const char* label, int64_t uniqueId, const void* extra); /*! * Remove plugin with id @a id. * @see ENGINE_CALLBACK_PLUGIN_REMOVED */ virtual bool removePlugin(uint id); /*! * Remove all plugins. */ bool removeAllPlugins(); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH /*! * Rename plugin with id @a id to @a newName. * Returns the new name, or null if the operation failed. * Returned variable must be deleted if non-null. * @see ENGINE_CALLBACK_PLUGIN_RENAMED */ virtual bool renamePlugin(uint id, const char* newName); /*! * Clone plugin with id @a id. */ bool clonePlugin(uint id); /*! * Prepare replace of plugin with id @a id. * The next call to addPlugin() will use this id, replacing the selected plugin. * @note This function requires addPlugin() to be called afterwards, as soon as possible. */ bool replacePlugin(uint id) noexcept; /*! * Switch plugins with id @a idA and @a idB. */ virtual bool switchPlugins(uint idA, uint idB) noexcept; #endif /*! * Set a plugin's parameter in drag/touch mode. * Usually happens from a UI when the user is moving a parameter with a mouse or similar input. * * @param parameterId The parameter to update * @param touch The new state for the parameter */ virtual void touchPluginParameter(uint id, uint32_t parameterId, bool touch) noexcept; /*! * Get plugin with id @a id. */ CarlaPlugin* getPlugin(uint id) const noexcept; /*! * Get plugin with id @a id, faster unchecked version. */ CarlaPlugin* getPluginUnchecked(uint id) const noexcept; /*! * Get a unique plugin name within the engine. * Returned variable must be deleted if non-null. */ const char* getUniquePluginName(const char* name) const; // ------------------------------------------------------------------- // Project management /*! * Load a file of any type. * This will try to load a generic file as a plugin, * either by direct handling (SF2 and SFZ) or by using an internal plugin (like Audio and MIDI). */ bool loadFile(const char* filename); /*! * Load a project file. * @note Already loaded plugins are not removed; call removeAllPlugins() first if needed. */ bool loadProject(const char* filename, bool setAsCurrentProject); /*! * Save current project to a file. */ bool saveProject(const char* filename, bool setAsCurrentProject); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH /*! * Get the currently set project filename. */ const char* getCurrentProjectFilename() const noexcept; /*! * Clear the currently set project filename. */ void clearCurrentProjectFilename() noexcept; #endif // ------------------------------------------------------------------- // Information (base) /*! * Get the current buffer size. */ uint32_t getBufferSize() const noexcept; /*! * Get the current sample rate. */ double getSampleRate() const noexcept; /*! * Get the current engine name. */ const char* getName() const noexcept; /*! * Get the current engine process mode. */ EngineProcessMode getProccessMode() const noexcept; /*! * Get the current engine options (read-only). */ const EngineOptions& getOptions() const noexcept; /*! * Get the current Time information (read-only). */ virtual EngineTimeInfo getTimeInfo() const noexcept; // ------------------------------------------------------------------- // Information (peaks) /*! * Get a plugin's peak values. * @note not thread-safe if pluginId == MAIN_CARLA_PLUGIN_ID */ const float* getPeaks(uint pluginId) const noexcept; /*! * Get a plugin's input peak value. */ float getInputPeak(uint pluginId, bool isLeft) const noexcept; /*! * Get a plugin's output peak value. */ float getOutputPeak(uint pluginId, bool isLeft) const noexcept; // ------------------------------------------------------------------- // Callback /*! * Call the main engine callback, if set. * May be called by plugins. */ virtual void callback(bool sendHost, bool sendOSC, EngineCallbackOpcode action, uint pluginId, int value1, int value2, int value3, float valuef, const char* valueStr) noexcept; /*! * Set the main engine callback to @a func. */ void setCallback(EngineCallbackFunc func, void* ptr) noexcept; // ------------------------------------------------------------------- // Callback /*! * Call the file callback, if set. * May be called by plugins. */ const char* runFileCallback(FileCallbackOpcode action, bool isDir, const char* title, const char* filter) noexcept; /*! * Set the file callback to @a func. */ void setFileCallback(FileCallbackFunc func, void* ptr) noexcept; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // ------------------------------------------------------------------- // Patchbay /*! * Connect two patchbay ports. */ virtual bool patchbayConnect(bool external, uint groupA, uint portA, uint groupB, uint portB); /*! * Remove a patchbay connection. */ virtual bool patchbayDisconnect(bool external, uint connectionId); /*! * Force the engine to resend all patchbay clients, ports and connections again. */ virtual bool patchbayRefresh(bool sendHost, bool sendOSC, bool external); #endif // ------------------------------------------------------------------- // Transport /*! * Start playback of the engine transport. */ virtual void transportPlay() noexcept; /*! * Pause the engine transport. */ virtual void transportPause() noexcept; /*! * Set the engine transport bpm to @a bpm. */ virtual void transportBPM(double bpm) noexcept; /*! * Relocate the engine transport to @a frames. */ virtual void transportRelocate(uint64_t frame) noexcept; // ------------------------------------------------------------------- // Error handling /*! * Get last error. */ const char* getLastError() const noexcept; /*! * Set last error. */ void setLastError(const char* error) const noexcept; // ------------------------------------------------------------------- // Misc /*! * Check if the engine is about to close. */ bool isAboutToClose() const noexcept; /*! * Tell the engine it's about to close. * This is used to prevent the engine thread(s) from reactivating. * Returns true if there's no pending engine events. */ bool setAboutToClose() noexcept; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH /*! * TODO. */ bool isLoadingProject() const noexcept; #endif /*! * Tell the engine to stop the current cancelable action. * @see ENGINE_CALLBACK_CANCELABLE_ACTION */ void setActionCanceled(bool canceled) noexcept; /*! * Check wherever the last cancelable action was indeed canceled or not. */ bool wasActionCanceled() const noexcept; // ------------------------------------------------------------------- // Options /*! * Set the engine option @a option to @a value or @a valueStr. */ virtual void setOption(EngineOption option, int value, const char* valueStr) noexcept; // ------------------------------------------------------------------- // OSC Stuff #ifndef BUILD_BRIDGE /*! * Check if OSC controller is registered. */ bool isOscControlRegistered() const noexcept; /*! * Get OSC TCP server path. */ const char* getOscServerPathTCP() const noexcept; /*! * Get OSC UDP server path. */ const char* getOscServerPathUDP() const noexcept; #endif // ------------------------------------------------------------------- protected: /*! * Internal data, for CarlaEngine subclasses and friends. */ struct ProtectedData; ProtectedData* const pData; /*! * Some internal classes read directly from pData or call protected functions. */ friend class CarlaEngineEventPort; friend class CarlaEngineOsc; friend class CarlaEngineThread; friend class CarlaPluginInstance; friend class EngineInternalGraph; friend class PendingRtEventsRunner; friend class ScopedActionLock; friend class ScopedEngineEnvironmentLocker; friend class ScopedThreadStopper; friend class PatchbayGraph; friend struct ExternalGraph; friend struct RackGraph; // ------------------------------------------------------------------- // Internal stuff /*! * Report to all plugins about buffer size change. */ void bufferSizeChanged(uint32_t newBufferSize); /*! * Report to all plugins about sample rate change. * This is not supported on all plugin types, in which case they will have to be re-initiated. */ void sampleRateChanged(double newSampleRate); /*! * Report to all plugins about offline mode change. */ void offlineModeChanged(bool isOffline); /*! * Set a plugin (stereo) peak values. * @note RT call */ void setPluginPeaksRT(uint pluginId, float const inPeaks[2], float const outPeaks[2]) noexcept; /*! * Common save project function for main engine and plugin. */ void saveProjectInternal(water::MemoryOutputStream& outStrm) const; /*! * Common load project function for main engine and plugin. */ bool loadProjectInternal(water::XmlDocument& xmlDoc); // ------------------------------------------------------------------- // Helper functions /*! * Return internal data, needed for EventPorts when used in Rack, Patchbay and Bridge modes. * @note RT call */ EngineEvent* getInternalEventBuffer(bool isInput) const noexcept; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // ------------------------------------------------------------------- // Patchbay stuff /*! * Virtual functions for handling patchbay state. * Do not free returned data. */ virtual const char* const* getPatchbayConnections(bool external) const; virtual void restorePatchbayConnection(bool external, const char* sourcePort, const char* targetPort); /*! * Virtual functions for handling external graph ports. */ virtual bool connectExternalGraphPort(uint, uint, const char*); virtual bool disconnectExternalGraphPort(uint, uint, const char*); #endif // ------------------------------------------------------------------- public: /*! * Native audio APIs. */ enum AudioApi { AUDIO_API_NULL, // common AUDIO_API_JACK, AUDIO_API_OSS, // linux AUDIO_API_ALSA, AUDIO_API_PULSEAUDIO, // macos AUDIO_API_COREAUDIO, // windows AUDIO_API_ASIO, AUDIO_API_DIRECTSOUND, AUDIO_API_WASAPI }; // ------------------------------------------------------------------- // Engine initializers // JACK static CarlaEngine* newJack(); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // Dummy static CarlaEngine* newDummy(); #endif #ifdef BUILD_BRIDGE // Bridge static CarlaEngine* newBridge(const char* audioPoolBaseName, const char* rtClientBaseName, const char* nonRtClientBaseName, const char* nonRtServerBaseName); #else # ifdef USING_JUCE // Juce static CarlaEngine* newJuce(AudioApi api); static uint getJuceApiCount(); static const char* getJuceApiName(uint index); static const char* const* getJuceApiDeviceNames(uint index); static const EngineDriverDeviceInfo* getJuceDeviceInfo(uint index, const char* deviceName); static bool showJuceDeviceControlPanel(uint index, const char* deviceName); # else // RtAudio static CarlaEngine* newRtAudio(AudioApi api); static uint getRtAudioApiCount(); static const char* getRtAudioApiName(uint index); static const char* const* getRtAudioApiDeviceNames(uint index); static const EngineDriverDeviceInfo* getRtAudioDeviceInfo(uint index, const char* deviceName); # endif #endif CARLA_DECLARE_NON_COPY_CLASS(CarlaEngine) }; /**@}*/ // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE #endif // CARLA_ENGINE_HPP_INCLUDED Carla-2.1/source/backend/CarlaHost.h000066400000000000000000000675571364475620200173530ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_HOST_H_INCLUDED #define CARLA_HOST_H_INCLUDED #include "CarlaBackend.h" #ifdef __cplusplus using CarlaBackend::BinaryType; using CarlaBackend::PluginType; using CarlaBackend::PluginCategory; using CarlaBackend::InternalParameterIndex; using CarlaBackend::EngineCallbackOpcode; using CarlaBackend::NsmCallbackOpcode; using CarlaBackend::EngineOption; using CarlaBackend::EngineProcessMode; using CarlaBackend::EngineTransportMode; using CarlaBackend::FileCallbackOpcode; using CarlaBackend::EngineCallbackFunc; using CarlaBackend::FileCallbackFunc; using CarlaBackend::ParameterData; using CarlaBackend::ParameterRanges; using CarlaBackend::MidiProgramData; using CarlaBackend::CustomData; using CarlaBackend::EngineDriverDeviceInfo; using CarlaBackend::CarlaEngine; using CarlaBackend::CarlaEngineClient; using CarlaBackend::CarlaPlugin; #endif /*! * @defgroup CarlaHostAPI Carla Host API * * The Carla Host API. * * This API makes it possible to use the Carla Backend in a standalone host application.. * * None of the returned values in this API calls need to be deleted or free'd. * When a function fails (returns false or NULL), use carla_get_last_error() to find out what went wrong. * @{ */ /* ------------------------------------------------------------------------------------------------------------ * Carla Host API (C stuff) */ /*! * Information about a loaded plugin. * @see carla_get_plugin_info() */ typedef struct _CarlaPluginInfo { /*! * Plugin type. */ PluginType type; /*! * Plugin category. */ PluginCategory category; /*! * Plugin hints. * @see PluginHints */ uint hints; /*! * Plugin options available for the user to change. * @see PluginOptions */ uint optionsAvailable; /*! * Plugin options currently enabled. * Some options are enabled but not available, which means they will always be on. * @see PluginOptions */ uint optionsEnabled; /*! * Plugin filename. * This can be the plugin binary or resource file. */ const char* filename; /*! * Plugin name. * This name is unique within a Carla instance. * @see carla_get_real_plugin_name() */ const char* name; /*! * Plugin label or URI. */ const char* label; /*! * Plugin author/maker. */ const char* maker; /*! * Plugin copyright/license. */ const char* copyright; /*! * Icon name for this plugin, in lowercase. * Default is "plugin". */ const char* iconName; /*! * Plugin unique Id. * This Id is dependent on the plugin type and may sometimes be 0. */ int64_t uniqueId; #ifdef __cplusplus /*! * C++ constructor and destructor. */ CARLA_API _CarlaPluginInfo() noexcept; CARLA_API ~_CarlaPluginInfo() noexcept; CARLA_DECLARE_NON_COPY_STRUCT(_CarlaPluginInfo) #endif } CarlaPluginInfo; /*! * Port count information, used for Audio and MIDI ports and parameters. * @see carla_get_audio_port_count_info() * @see carla_get_midi_port_count_info() * @see carla_get_parameter_count_info() */ typedef struct _CarlaPortCountInfo { /*! * Number of inputs. */ uint32_t ins; /*! * Number of outputs. */ uint32_t outs; } CarlaPortCountInfo; /*! * Parameter information. * @see carla_get_parameter_info() */ typedef struct _CarlaParameterInfo { /*! * Parameter name. */ const char* name; /*! * Parameter symbol. */ const char* symbol; /*! * Parameter unit. */ const char* unit; /*! * Parameter comment / documentation. */ const char* comment; /*! * Parameter group name, prefixed by a unique symbol and ":". */ const char* groupName; /*! * Number of scale points. * @see CarlaScalePointInfo */ uint32_t scalePointCount; #ifdef __cplusplus /*! * C++ constructor and destructor. */ CARLA_API _CarlaParameterInfo() noexcept; CARLA_API ~_CarlaParameterInfo() noexcept; CARLA_DECLARE_NON_COPY_STRUCT(_CarlaParameterInfo) #endif } CarlaParameterInfo; /*! * Parameter scale point information. * @see carla_get_parameter_scalepoint_info() */ typedef struct _CarlaScalePointInfo { /*! * Scale point value. */ float value; /*! * Scale point label. */ const char* label; #ifdef __cplusplus /*! * C++ constructor and destructor. */ CARLA_API _CarlaScalePointInfo() noexcept; CARLA_API ~_CarlaScalePointInfo() noexcept; CARLA_DECLARE_NON_COPY_STRUCT(_CarlaScalePointInfo) #endif } CarlaScalePointInfo; /*! * Transport information. * @see carla_get_transport_info() */ typedef struct _CarlaTransportInfo { /*! * Wherever transport is playing. */ bool playing; /*! * Current transport frame. */ uint64_t frame; /*! * Bar. */ int32_t bar; /*! * Beat. */ int32_t beat; /*! * Tick. */ int32_t tick; /*! * Beats per minute. */ double bpm; #ifdef __cplusplus /*! * C++ constructor. */ CARLA_API _CarlaTransportInfo() noexcept; /*! * Clear struct contents. */ CARLA_API void clear() noexcept; #endif } CarlaTransportInfo; /*! * Runtime engine information. */ typedef struct _CarlaRuntimeEngineInfo { /*! * DSP load. */ float load; /*! * Number of xruns. */ uint32_t xruns; } CarlaRuntimeEngineInfo; /*! * Runtime engine driver device information. */ typedef struct { /*! * Name of the driver device. */ const char* name; /*! * This driver device hints. * @see EngineDriverHints */ uint hints; /*! * Current buffer size. */ uint bufferSize; /*! * Available buffer sizes. * Terminated with 0. */ const uint32_t* bufferSizes; /*! * Current sample rate. */ double sampleRate; /*! * Available sample rates. * Terminated with 0.0. */ const double* sampleRates; } CarlaRuntimeEngineDriverDeviceInfo; /*! * Image data for LV2 inline display API. * raw image pixmap format is ARGB32, */ typedef struct { unsigned char* data; int width; int height; int stride; } CarlaInlineDisplayImageSurface; /* ------------------------------------------------------------------------------------------------------------ * Carla Host API (C functions) */ /*! * Get how many engine drivers are available. */ CARLA_EXPORT uint carla_get_engine_driver_count(void); /*! * Get an engine driver name. * @param index Driver index */ CARLA_EXPORT const char* carla_get_engine_driver_name(uint index); /*! * Get the device names of an engine driver. * @param index Driver index */ CARLA_EXPORT const char* const* carla_get_engine_driver_device_names(uint index); /*! * Get information about a device driver. * @param index Driver index * @param name Device name */ CARLA_EXPORT const EngineDriverDeviceInfo* carla_get_engine_driver_device_info(uint index, const char* name); /*! * Show a device custom control panel. * @see ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL * @param index Driver index * @param name Device name */ CARLA_EXPORT bool carla_show_engine_driver_device_control_panel(uint index, const char* name); #ifdef __cplusplus /*! * Get the currently used engine, may be NULL. * @note C++ only */ CARLA_EXPORT CarlaEngine* carla_get_engine(void); #endif /*! * Initialize the engine. * Make sure to call carla_engine_idle() at regular intervals afterwards. * @param driverName Driver to use * @param clientName Engine master client name */ CARLA_EXPORT bool carla_engine_init(const char* driverName, const char* clientName); #ifdef BUILD_BRIDGE /*! * Initialize the engine in bridged mode. */ CARLA_EXPORT bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtClientBaseName[6+1], const char nonRtClientBaseName[6+1], const char nonRtServerBaseName[6+1], const char* clientName); #endif /*! * Close the engine. * This function always closes the engine even if it returns false. * In other words, even when something goes wrong when closing the engine it still be closed nonetheless. */ CARLA_EXPORT bool carla_engine_close(void); /*! * Idle the engine. * Do not call this if the engine is not running. */ CARLA_EXPORT void carla_engine_idle(void); /*! * Check if the engine is running. */ CARLA_EXPORT bool carla_is_engine_running(void); /*! * Get information about the currently running engine. */ CARLA_EXPORT const CarlaRuntimeEngineInfo* carla_get_runtime_engine_info(void); #ifndef BUILD_BRIDGE /*! * Get information about the currently running engine driver device. */ CARLA_EXPORT const CarlaRuntimeEngineDriverDeviceInfo* carla_get_runtime_engine_driver_device_info(void); /*! * Dynamically change buffer size and/or sample rate while engine is running. * @see ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE * @see ENGINE_DRIVER_DEVICE_VARIABLE_SAMPLE_RATE */ CARLA_EXPORT bool carla_set_engine_buffer_size_and_sample_rate(uint bufferSize, double sampleRate); /*! * Show the custom control panel for the current engine device. * @see ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL */ CARLA_EXPORT bool carla_show_engine_device_control_panel(void); #endif /*! * Clear the xrun count on the engine, so that the next time carla_get_runtime_engine_info() is called, it returns 0. */ CARLA_EXPORT void carla_clear_engine_xruns(void); /*! * Tell the engine to stop the current cancelable action. * @see ENGINE_CALLBACK_CANCELABLE_ACTION */ CARLA_EXPORT void carla_cancel_engine_action(void); /*! * Tell the engine it's about to close. * This is used to prevent the engine thread(s) from reactivating. * Returns true if there's no pending engine events. */ CARLA_EXPORT bool carla_set_engine_about_to_close(void); /*! * Set the engine callback function. * @param func Callback function * @param ptr Callback pointer */ CARLA_EXPORT void carla_set_engine_callback(EngineCallbackFunc func, void* ptr); #ifndef BUILD_BRIDGE /*! * Set an engine option. * @param option Option * @param value Value as number * @param valueStr Value as string */ CARLA_EXPORT void carla_set_engine_option(EngineOption option, int value, const char* valueStr); #endif /*! * Set the file callback function. * @param func Callback function * @param ptr Callback pointer */ CARLA_EXPORT void carla_set_file_callback(FileCallbackFunc func, void* ptr); /*! * Load a file of any type. * This will try to load a generic file as a plugin, * either by direct handling (SF2 and SFZ) or by using an internal plugin (like Audio and MIDI). * @see carla_get_supported_file_extensions() */ CARLA_EXPORT bool carla_load_file(const char* filename); /*! * Load a Carla project file. * @note Currently loaded plugins are not removed; call carla_remove_all_plugins() first if needed. */ CARLA_EXPORT bool carla_load_project(const char* filename); /*! * Save current project to a file. */ CARLA_EXPORT bool carla_save_project(const char* filename); #ifndef BUILD_BRIDGE /*! * Clear the currently set project filename. */ CARLA_EXPORT void carla_clear_project_filename(void); /*! * Connect two patchbay ports. * @param groupIdA Output group * @param portIdA Output port * @param groupIdB Input group * @param portIdB Input port * @see ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED */ CARLA_EXPORT bool carla_patchbay_connect(bool external, uint groupIdA, uint portIdA, uint groupIdB, uint portIdB); /*! * Disconnect two patchbay ports. * @param connectionId Connection Id * @see ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED */ CARLA_EXPORT bool carla_patchbay_disconnect(bool external, uint connectionId); /*! * Force the engine to resend all patchbay clients, ports and connections again. * @param external Wherever to show external/hardware ports instead of internal ones. * Only valid in patchbay engine mode, other modes will ignore this. */ CARLA_EXPORT bool carla_patchbay_refresh(bool external); /*! * Start playback of the engine transport. */ CARLA_EXPORT void carla_transport_play(void); /*! * Pause the engine transport. */ CARLA_EXPORT void carla_transport_pause(void); /*! * Set the engine transport bpm. */ CARLA_EXPORT void carla_transport_bpm(double bpm); /*! * Relocate the engine transport to a specific frame. */ CARLA_EXPORT void carla_transport_relocate(uint64_t frame); /*! * Get the current transport frame. */ CARLA_EXPORT uint64_t carla_get_current_transport_frame(void); /*! * Get the engine transport information. */ CARLA_EXPORT const CarlaTransportInfo* carla_get_transport_info(void); #endif /*! * Current number of plugins loaded. */ CARLA_EXPORT uint32_t carla_get_current_plugin_count(void); /*! * Maximum number of loadable plugins allowed. * Returns 0 if engine is not started. */ CARLA_EXPORT uint32_t carla_get_max_plugin_number(void); /*! * Add a new plugin. * If you don't know the binary type use the BINARY_NATIVE macro. * @param btype Binary type * @param ptype Plugin type * @param filename Filename, if applicable * @param name Name of the plugin, can be NULL * @param label Plugin label, if applicable * @param uniqueId Plugin unique Id, if applicable * @param extraPtr Extra pointer, defined per plugin type * @param options Initial plugin options */ CARLA_EXPORT bool carla_add_plugin(BinaryType btype, PluginType ptype, const char* filename, const char* name, const char* label, int64_t uniqueId, const void* extraPtr, uint options); /*! * Remove one plugin. * @param pluginId Plugin to remove. */ CARLA_EXPORT bool carla_remove_plugin(uint pluginId); /*! * Remove all plugins. */ CARLA_EXPORT bool carla_remove_all_plugins(void); #ifndef BUILD_BRIDGE /*! * Rename a plugin. * Returns the new name, or NULL if the operation failed. * @param pluginId Plugin to rename * @param newName New plugin name */ CARLA_EXPORT bool carla_rename_plugin(uint pluginId, const char* newName); /*! * Clone a plugin. * @param pluginId Plugin to clone */ CARLA_EXPORT bool carla_clone_plugin(uint pluginId); /*! * Prepare replace of a plugin. * The next call to carla_add_plugin() will use this id, replacing the current plugin. * @param pluginId Plugin to replace * @note This function requires carla_add_plugin() to be called afterwards *as soon as possible*. */ CARLA_EXPORT bool carla_replace_plugin(uint pluginId); /*! * Switch two plugins positions. * @param pluginIdA Plugin A * @param pluginIdB Plugin B */ CARLA_EXPORT bool carla_switch_plugins(uint pluginIdA, uint pluginIdB); #endif /*! * Load a plugin state. * @param pluginId Plugin * @param filename Path to plugin state * @see carla_save_plugin_state() */ CARLA_EXPORT bool carla_load_plugin_state(uint pluginId, const char* filename); /*! * Save a plugin state. * @param pluginId Plugin * @param filename Path to plugin state * @see carla_load_plugin_state() */ CARLA_EXPORT bool carla_save_plugin_state(uint pluginId, const char* filename); /*! * Export plugin as LV2. * @param pluginId Plugin * @param lv2path Path to lv2 plugin folder */ CARLA_EXPORT bool carla_export_plugin_lv2(uint pluginId, const char* lv2path); /*! * Get information from a plugin. * @param pluginId Plugin */ CARLA_EXPORT const CarlaPluginInfo* carla_get_plugin_info(uint pluginId); /*! * Get audio port count information from a plugin. * @param pluginId Plugin */ CARLA_EXPORT const CarlaPortCountInfo* carla_get_audio_port_count_info(uint pluginId); /*! * Get MIDI port count information from a plugin. * @param pluginId Plugin */ CARLA_EXPORT const CarlaPortCountInfo* carla_get_midi_port_count_info(uint pluginId); /*! * Get parameter count information from a plugin. * @param pluginId Plugin */ CARLA_EXPORT const CarlaPortCountInfo* carla_get_parameter_count_info(uint pluginId); /*! * Get parameter information from a plugin. * @param pluginId Plugin * @param parameterId Parameter index * @see carla_get_parameter_count() */ CARLA_EXPORT const CarlaParameterInfo* carla_get_parameter_info(uint pluginId, uint32_t parameterId); /*! * Get parameter scale point information from a plugin. * @param pluginId Plugin * @param parameterId Parameter index * @param scalePointId Parameter scale-point index * @see CarlaParameterInfo::scalePointCount */ CARLA_EXPORT const CarlaScalePointInfo* carla_get_parameter_scalepoint_info(uint pluginId, uint32_t parameterId, uint32_t scalePointId); /*! * Get a plugin's parameter data. * @param pluginId Plugin * @param parameterId Parameter index * @see carla_get_parameter_count() */ CARLA_EXPORT const ParameterData* carla_get_parameter_data(uint pluginId, uint32_t parameterId); /*! * Get a plugin's parameter ranges. * @param pluginId Plugin * @param parameterId Parameter index * @see carla_get_parameter_count() */ CARLA_EXPORT const ParameterRanges* carla_get_parameter_ranges(uint pluginId, uint32_t parameterId); /*! * Get a plugin's MIDI program data. * @param pluginId Plugin * @param midiProgramId MIDI Program index * @see carla_get_midi_program_count() */ CARLA_EXPORT const MidiProgramData* carla_get_midi_program_data(uint pluginId, uint32_t midiProgramId); /*! * Get a plugin's custom data, using index. * @param pluginId Plugin * @param customDataId Custom data index * @see carla_get_custom_data_count() */ CARLA_EXPORT const CustomData* carla_get_custom_data(uint pluginId, uint32_t customDataId); /*! * Get a plugin's custom data value, using type and key. * @param pluginId Plugin * @param type Custom data type * @param key Custom data key * @see carla_get_custom_data_count() */ CARLA_EXPORT const char* carla_get_custom_data_value(uint pluginId, const char* type, const char* key); /*! * Get a plugin's chunk data. * @param pluginId Plugin * @see PLUGIN_OPTION_USE_CHUNKS and carla_set_chunk_data() */ CARLA_EXPORT const char* carla_get_chunk_data(uint pluginId); /*! * Get how many parameters a plugin has. * @param pluginId Plugin */ CARLA_EXPORT uint32_t carla_get_parameter_count(uint pluginId); /*! * Get how many programs a plugin has. * @param pluginId Plugin * @see carla_get_program_name() */ CARLA_EXPORT uint32_t carla_get_program_count(uint pluginId); /*! * Get how many MIDI programs a plugin has. * @param pluginId Plugin * @see carla_get_midi_program_name() and carla_get_midi_program_data() */ CARLA_EXPORT uint32_t carla_get_midi_program_count(uint pluginId); /*! * Get how many custom data sets a plugin has. * @param pluginId Plugin * @see carla_get_custom_data() */ CARLA_EXPORT uint32_t carla_get_custom_data_count(uint pluginId); /*! * Get a plugin's parameter text (custom display of internal values). * @param pluginId Plugin * @param parameterId Parameter index * @see PARAMETER_USES_CUSTOM_TEXT */ CARLA_EXPORT const char* carla_get_parameter_text(uint pluginId, uint32_t parameterId); /*! * Get a plugin's program name. * @param pluginId Plugin * @param programId Program index * @see carla_get_program_count() */ CARLA_EXPORT const char* carla_get_program_name(uint pluginId, uint32_t programId); /*! * Get a plugin's MIDI program name. * @param pluginId Plugin * @param midiProgramId MIDI Program index * @see carla_get_midi_program_count() */ CARLA_EXPORT const char* carla_get_midi_program_name(uint pluginId, uint32_t midiProgramId); /*! * Get a plugin's real name. * This is the name the plugin uses to identify itself; may not be unique. * @param pluginId Plugin */ CARLA_EXPORT const char* carla_get_real_plugin_name(uint pluginId); /*! * Get a plugin's program index. * @param pluginId Plugin */ CARLA_EXPORT int32_t carla_get_current_program_index(uint pluginId); /*! * Get a plugin's midi program index. * @param pluginId Plugin */ CARLA_EXPORT int32_t carla_get_current_midi_program_index(uint pluginId); /*! * Get a plugin's default parameter value. * @param pluginId Plugin * @param parameterId Parameter index */ CARLA_EXPORT float carla_get_default_parameter_value(uint pluginId, uint32_t parameterId); /*! * Get a plugin's current parameter value. * @param pluginId Plugin * @param parameterId Parameter index */ CARLA_EXPORT float carla_get_current_parameter_value(uint pluginId, uint32_t parameterId); /*! * Get a plugin's internal parameter value. * @param pluginId Plugin * @param parameterId Parameter index, maybe be negative * @see InternalParameterIndex */ CARLA_EXPORT float carla_get_internal_parameter_value(uint pluginId, int32_t parameterId); /*! * Get a plugin's peak values. * @param pluginId Plugin */ CARLA_EXPORT const float* carla_get_peak_values(uint pluginId); /*! * Get a plugin's input peak value. * @param pluginId Plugin * @param isLeft Wherever to get the left/mono value, otherwise right. */ CARLA_EXPORT float carla_get_input_peak_value(uint pluginId, bool isLeft); /*! * Get a plugin's output peak value. * @param pluginId Plugin * @param isLeft Wherever to get the left/mono value, otherwise right. */ CARLA_EXPORT float carla_get_output_peak_value(uint pluginId, bool isLeft); /*! * Render a plugin's inline display. * @param pluginId Plugin */ CARLA_EXPORT const CarlaInlineDisplayImageSurface* carla_render_inline_display(uint pluginId, uint32_t width, uint32_t height); /*! * Enable or disable a plugin. * @param pluginId Plugin * @param onOff New active state */ CARLA_EXPORT void carla_set_active(uint pluginId, bool onOff); #ifndef BUILD_BRIDGE /*! * Change a plugin's internal dry/wet. * @param pluginId Plugin * @param value New dry/wet value */ CARLA_EXPORT void carla_set_drywet(uint pluginId, float value); /*! * Change a plugin's internal volume. * @param pluginId Plugin * @param value New volume */ CARLA_EXPORT void carla_set_volume(uint pluginId, float value); /*! * Change a plugin's internal stereo balance, left channel. * @param pluginId Plugin * @param value New value */ CARLA_EXPORT void carla_set_balance_left(uint pluginId, float value); /*! * Change a plugin's internal stereo balance, right channel. * @param pluginId Plugin * @param value New value */ CARLA_EXPORT void carla_set_balance_right(uint pluginId, float value); /*! * Change a plugin's internal mono panning value. * @param pluginId Plugin * @param value New value */ CARLA_EXPORT void carla_set_panning(uint pluginId, float value); /*! * Change a plugin's internal control channel. * @param pluginId Plugin * @param channel New channel */ CARLA_EXPORT void carla_set_ctrl_channel(uint pluginId, int8_t channel); #endif /*! * Enable a plugin's option. * @param pluginId Plugin * @param option An option from PluginOptions * @param yesNo New enabled state */ CARLA_EXPORT void carla_set_option(uint pluginId, uint option, bool yesNo); /*! * Change a plugin's parameter value. * @param pluginId Plugin * @param parameterId Parameter index * @param value New value */ CARLA_EXPORT void carla_set_parameter_value(uint pluginId, uint32_t parameterId, float value); #ifndef BUILD_BRIDGE /*! * Change a plugin's parameter MIDI channel. * @param pluginId Plugin * @param parameterId Parameter index * @param channel New MIDI channel */ CARLA_EXPORT void carla_set_parameter_midi_channel(uint pluginId, uint32_t parameterId, uint8_t channel); /*! * Change a plugin's parameter mapped control index. * @param pluginId Plugin * @param parameterId Parameter index * @param cc New control index */ CARLA_EXPORT void carla_set_parameter_mapped_control_index(uint pluginId, uint32_t parameterId, int16_t index); /*! * Change a plugin's parameter mapped range. * @param pluginId Plugin * @param parameterId Parameter index * @param minimum New mapped minimum * @param maximum New mapped maximum */ CARLA_EXPORT void carla_set_parameter_mapped_range(uint pluginId, uint32_t parameterId, float minimum, float maximum); /*! * Change a plugin's parameter in drag/touch mode state. * Usually happens from a UI when the user is moving a parameter with a mouse or similar input. * @param pluginId Plugin * @param parameterId Parameter index * @param touch New state */ CARLA_EXPORT void carla_set_parameter_touch(uint pluginId, uint32_t parameterId, bool touch); #endif /*! * Change a plugin's current program. * @param pluginId Plugin * @param programId New program */ CARLA_EXPORT void carla_set_program(uint pluginId, uint32_t programId); /*! * Change a plugin's current MIDI program. * @param pluginId Plugin * @param midiProgramId New value */ CARLA_EXPORT void carla_set_midi_program(uint pluginId, uint32_t midiProgramId); /*! * Set a plugin's custom data set. * @param pluginId Plugin * @param type Type * @param key Key * @param value New value * @see CustomDataTypes and CustomDataKeys */ CARLA_EXPORT void carla_set_custom_data(uint pluginId, const char* type, const char* key, const char* value); /*! * Set a plugin's chunk data. * @param pluginId Plugin * @param chunkData New chunk data * @see PLUGIN_OPTION_USE_CHUNKS and carla_get_chunk_data() */ CARLA_EXPORT void carla_set_chunk_data(uint pluginId, const char* chunkData); /*! * Tell a plugin to prepare for save. * This should be called before saving custom data sets. * @param pluginId Plugin */ CARLA_EXPORT void carla_prepare_for_save(uint pluginId); /*! * Reset all plugin's parameters. * @param pluginId Plugin */ CARLA_EXPORT void carla_reset_parameters(uint pluginId); /*! * Randomize all plugin's parameters. * @param pluginId Plugin */ CARLA_EXPORT void carla_randomize_parameters(uint pluginId); #ifndef BUILD_BRIDGE /*! * Send a single note of a plugin. * If velocity is 0, note-off is sent; note-on otherwise. * @param pluginId Plugin * @param channel Note channel * @param note Note pitch * @param velocity Note velocity */ CARLA_EXPORT void carla_send_midi_note(uint pluginId, uint8_t channel, uint8_t note, uint8_t velocity); #endif /*! * Tell a plugin to show its own custom UI. * @param pluginId Plugin * @param yesNo New UI state, visible or not * @see PLUGIN_HAS_CUSTOM_UI */ CARLA_EXPORT void carla_show_custom_ui(uint pluginId, bool yesNo); /*! * Get the current engine buffer size. */ CARLA_EXPORT uint32_t carla_get_buffer_size(void); /*! * Get the current engine sample rate. */ CARLA_EXPORT double carla_get_sample_rate(void); /*! * Get the last error. */ CARLA_EXPORT const char* carla_get_last_error(void); /*! * Get the current engine OSC URL (TCP). */ CARLA_EXPORT const char* carla_get_host_osc_url_tcp(void); /*! * Get the current engine OSC URL (UDP). */ CARLA_EXPORT const char* carla_get_host_osc_url_udp(void); /*! * Get the absolute filename of this carla library. */ CARLA_EXPORT const char* carla_get_library_filename(void); /*! * Get the folder where this carla library resides. */ CARLA_EXPORT const char* carla_get_library_folder(void); /*! * Initialize NSM (that is, announce ourselves to it). * Must be called as early as possible in the program's lifecycle. * Returns true if NSM is available and initialized correctly. */ CARLA_EXPORT bool carla_nsm_init(uint64_t pid, const char* executableName); /*! * Respond to an NSM callback. */ CARLA_EXPORT void carla_nsm_ready(NsmCallbackOpcode opcode); /** @} */ #endif /* CARLA_HOST_H_INCLUDED */ Carla-2.1/source/backend/CarlaHostCommon.cpp000066400000000000000000000073731364475620200210450ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2014 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaHost.h" #include "CarlaString.hpp" #include "water/files/File.h" namespace CB = CarlaBackend; // ------------------------------------------------------------------------------------------------------------------- // Always return a valid string ptr static const char* const gNullCharPtr = ""; #ifdef CARLA_COMMON_NEED_CHECKSTRINGPTR static void checkStringPtr(const char*& charPtr) noexcept { if (charPtr == nullptr) charPtr = gNullCharPtr; } #endif // ------------------------------------------------------------------------------------------------------------------- // Constructors _CarlaPluginInfo::_CarlaPluginInfo() noexcept : type(CB::PLUGIN_NONE), category(CB::PLUGIN_CATEGORY_NONE), hints(0x0), optionsAvailable(0x0), optionsEnabled(0x0), filename(gNullCharPtr), name(gNullCharPtr), label(gNullCharPtr), maker(gNullCharPtr), copyright(gNullCharPtr), iconName(gNullCharPtr), uniqueId(0) {} _CarlaPluginInfo::~_CarlaPluginInfo() noexcept { if (label != gNullCharPtr) delete[] label; if (maker != gNullCharPtr) delete[] maker; if (copyright != gNullCharPtr) delete[] copyright; } _CarlaParameterInfo::_CarlaParameterInfo() noexcept : name(gNullCharPtr), symbol(gNullCharPtr), unit(gNullCharPtr), comment(gNullCharPtr), groupName(gNullCharPtr), scalePointCount(0) {} _CarlaParameterInfo::~_CarlaParameterInfo() noexcept { if (name != gNullCharPtr) delete[] name; if (symbol != gNullCharPtr) delete[] symbol; if (unit != gNullCharPtr) delete[] unit; if (comment != gNullCharPtr) delete[] comment; if (groupName != gNullCharPtr) delete[] groupName; } _CarlaScalePointInfo::_CarlaScalePointInfo() noexcept : value(0.0f), label(gNullCharPtr) {} _CarlaScalePointInfo::~_CarlaScalePointInfo() noexcept { if (label != gNullCharPtr) delete[] label; } _CarlaTransportInfo::_CarlaTransportInfo() noexcept : playing(false), frame(0), bar(0), beat(0), tick(0), bpm(0.0) {} void _CarlaTransportInfo::clear() noexcept { playing = false; frame = 0; bar = 0; beat = 0; tick = 0; bpm = 0.0; } // ------------------------------------------------------------------------------------------------------------------- const char* carla_get_library_filename() { carla_debug("carla_get_library_filename()"); static CarlaString ret; if (ret.isEmpty()) { using water::File; ret = File(File::getSpecialLocation(File::currentExecutableFile)).getFullPathName().toRawUTF8(); } return ret; } const char* carla_get_library_folder() { carla_debug("carla_get_library_folder()"); static CarlaString ret; if (ret.isEmpty()) { using water::File; ret = File(File::getSpecialLocation(File::currentExecutableFile).getParentDirectory()).getFullPathName().toRawUTF8(); } return ret; } // ------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/CarlaPlugin.hpp000066400000000000000000000742611364475620200202220ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_PLUGIN_HPP_INCLUDED #define CARLA_PLUGIN_HPP_INCLUDED #include "CarlaBackend.h" // ----------------------------------------------------------------------- // Avoid including extra libs here typedef void* lo_message; typedef struct _NativePluginDescriptor NativePluginDescriptor; struct LADSPA_RDF_Descriptor; // ----------------------------------------------------------------------- CARLA_BACKEND_START_NAMESPACE #if 0 } /* Fix editor indentation */ #endif // ----------------------------------------------------------------------- /*! * @defgroup CarlaPluginAPI Carla Plugin API * * The Carla Plugin API. * @{ */ class CarlaEngineAudioPort; class CarlaEngineCVPort; class CarlaEngineEventPort; class CarlaEngineCVSourcePorts; class CarlaEngineBridge; struct CarlaStateSave; // ----------------------------------------------------------------------- /*! * Carla Backend base plugin class * * This is the base class for all available plugin types available in Carla Backend. * All virtual calls are implemented in this class as fallback (except reload and process), * so it's safe to only override needed calls. * * @see PluginType */ class CARLA_API CarlaPlugin { protected: /*! * This is the constructor of the base plugin class. * * @param engine The engine which this plugin belongs to, must not be null * @param id The 'id' of this plugin, must be between 0 and CarlaEngine::maxPluginNumber() */ CarlaPlugin(CarlaEngine* engine, uint id); public: /*! * This is the destructor of the base plugin class. */ virtual ~CarlaPlugin(); // ------------------------------------------------------------------- // Information (base) /*! * Get the plugin's type (a subclass of CarlaPlugin). * * @note Plugin bridges will return their respective plugin type, there is no plugin type such as "bridge". * To check if a plugin is a bridge use: * @code * if (getHints() & PLUGIN_IS_BRIDGE) * ... * @endcode */ virtual PluginType getType() const noexcept = 0; /*! * Get the plugin's id (as passed in the constructor). * * @see setId() */ uint getId() const noexcept; /*! * Get the plugin's hints. * * @see PluginHints */ uint getHints() const noexcept; /*! * Get the plugin's options (currently in use). * * @see PluginOptions, getOptionsAvailable() and setOption() */ uint getOptionsEnabled() const noexcept; /*! * Check if the plugin is enabled. * When a plugin is disabled, it will never be processed or managed in any way. * * @see setEnabled() */ bool isEnabled() const noexcept; /*! * Get the plugin's internal name. * This name is unique within all plugins in an engine. * * @see getRealName() and setName() */ const char* getName() const noexcept; /*! * Get the currently loaded DLL filename for this plugin. * (Sound kits return their exact filename). */ const char* getFilename() const noexcept; /*! * Get the plugins's icon name. */ const char* getIconName() const noexcept; /*! * Get the plugin's category (delay, filter, synth, etc). */ virtual PluginCategory getCategory() const noexcept; /*! * Get the plugin's native unique Id. * May return 0 on plugin types that don't support Ids. */ virtual int64_t getUniqueId() const noexcept; /*! * Get the plugin's latency, in sample frames. */ virtual uint32_t getLatencyInFrames() const noexcept; // ------------------------------------------------------------------- // Information (count) /*! * Get the number of audio inputs. */ uint32_t getAudioInCount() const noexcept; /*! * Get the number of audio outputs. */ uint32_t getAudioOutCount() const noexcept; /*! * Get the number of CV inputs. */ uint32_t getCVInCount() const noexcept; /*! * Get the number of CV outputs. */ uint32_t getCVOutCount() const noexcept; /*! * Get the number of MIDI inputs. */ virtual uint32_t getMidiInCount() const noexcept; /*! * Get the number of MIDI outputs. */ virtual uint32_t getMidiOutCount() const noexcept; /*! * Get the number of parameters. * To know the number of parameter inputs and outputs separately use getParameterCountInfo() instead. */ uint32_t getParameterCount() const noexcept; /*! * Get the number of scalepoints for parameter @a parameterId. */ virtual uint32_t getParameterScalePointCount(uint32_t parameterId) const noexcept; /*! * Get the number of programs. */ uint32_t getProgramCount() const noexcept; /*! * Get the number of MIDI programs. */ uint32_t getMidiProgramCount() const noexcept; /*! * Get the number of custom data sets. */ uint32_t getCustomDataCount() const noexcept; // ------------------------------------------------------------------- // Information (current data) /*! * Get the current program number (-1 if unset). * * @see setProgram() */ int32_t getCurrentProgram() const noexcept; /*! * Get the current MIDI program number (-1 if unset). * * @see setMidiProgram() * @see setMidiProgramById() */ int32_t getCurrentMidiProgram() const noexcept; /*! * Get the parameter data of @a parameterId. */ const ParameterData& getParameterData(uint32_t parameterId) const noexcept; /*! * Get the parameter ranges of @a parameterId. */ const ParameterRanges& getParameterRanges(uint32_t parameterId) const noexcept; /*! * Check if parameter @a parameterId is of output type. */ bool isParameterOutput(uint32_t parameterId) const noexcept; /*! * Get the MIDI program at @a index. * * @see getMidiProgramName() */ const MidiProgramData& getMidiProgramData(uint32_t index) const noexcept; /*! * Get the custom data set at @a index. * * @see getCustomDataCount() and setCustomData() */ const CustomData& getCustomData(uint32_t index) const noexcept; /*! * Get the complete plugin chunk data into @a dataPtr. * * @note Make sure to verify the plugin supports chunks before calling this function! * @return The size of the chunk or 0 if invalid. * * @see setChunkData() */ virtual std::size_t getChunkData(void** dataPtr) noexcept; // ------------------------------------------------------------------- // Information (per-plugin data) /*! * Get the plugin available options. * * @see PluginOptions, getOptions() and setOption() */ virtual uint getOptionsAvailable() const noexcept; /*! * Get the current parameter value of @a parameterId. */ virtual float getParameterValue(uint32_t parameterId) const noexcept; /*! * Get the scalepoint @a scalePointId value of the parameter @a parameterId. */ virtual float getParameterScalePointValue(uint32_t parameterId, uint32_t scalePointId) const noexcept; /*! * Get the plugin's label (URI for LV2 plugins). */ __attribute__((warn_unused_result)) virtual bool getLabel(char* strBuf) const noexcept; /*! * Get the plugin's maker. */ __attribute__((warn_unused_result)) virtual bool getMaker(char* strBuf) const noexcept; /*! * Get the plugin's copyright/license. */ __attribute__((warn_unused_result)) virtual bool getCopyright(char* strBuf) const noexcept; /*! * Get the plugin's (real) name. * * @see getName() and setName() */ __attribute__((warn_unused_result)) virtual bool getRealName(char* strBuf) const noexcept; /*! * Get the name of the parameter @a parameterId. */ __attribute__((warn_unused_result)) virtual bool getParameterName(uint32_t parameterId, char* strBuf) const noexcept; /*! * Get the symbol of the parameter @a parameterId. */ __attribute__((warn_unused_result)) virtual bool getParameterSymbol(uint32_t parameterId, char* strBuf) const noexcept; /*! * Get the custom text of the parameter @a parameterId. * @see PARAMETER_USES_CUSTOM_TEXT */ __attribute__((warn_unused_result)) virtual bool getParameterText(uint32_t parameterId, char* strBuf) noexcept; /*! * Get the unit of the parameter @a parameterId. */ __attribute__((warn_unused_result)) virtual bool getParameterUnit(uint32_t parameterId, char* strBuf) const noexcept; /*! * Get the comment (documentation) of the parameter @a parameterId. */ __attribute__((warn_unused_result)) virtual bool getParameterComment(uint32_t parameterId, char* strBuf) const noexcept; /*! * Get the group name of the parameter @a parameterId. * @note The group name is prefixed by a unique symbol and ":". */ __attribute__((warn_unused_result)) virtual bool getParameterGroupName(uint32_t parameterId, char* strBuf) const noexcept; /*! * Get the scalepoint @a scalePointId label of the parameter @a parameterId. */ __attribute__((warn_unused_result)) virtual bool getParameterScalePointLabel(uint32_t parameterId, uint32_t scalePointId, char* strBuf) const noexcept; /*! * Get the current parameter value of @a parameterId. * @a parameterId can be negative to allow internal parameters. * @see InternalParametersIndex */ float getInternalParameterValue(int32_t parameterId) const noexcept; /*! * Get the name of the program at @a index. */ __attribute__((warn_unused_result)) bool getProgramName(uint32_t index, char* strBuf) const noexcept; /*! * Get the name of the MIDI program at @a index. * * @see getMidiProgramInfo() */ __attribute__((warn_unused_result)) bool getMidiProgramName(uint32_t index, char* strBuf) const noexcept; /*! * Get information about the plugin's parameter count. * This is used to check how many input, output and total parameters are available. * * @note Some parameters might not be input or output (ie, invalid). * * @see getParameterCount() */ void getParameterCountInfo(uint32_t& ins, uint32_t& outs) const noexcept; // ------------------------------------------------------------------- // Set data (state) /*! * Tell the plugin to prepare for save. */ virtual void prepareForSave(); /*! * Reset all possible parameters. */ virtual void resetParameters() noexcept; /*! * Randomize all possible parameters. */ virtual void randomizeParameters() noexcept; /*! * Get the plugin's save state. * The plugin will automatically call prepareForSave() if requested. * * @see loadStateSave() */ const CarlaStateSave& getStateSave(bool callPrepareForSave = true); /*! * Get the plugin's save state. * * @see getStateSave() */ void loadStateSave(const CarlaStateSave& stateSave); /*! * Save the current plugin state to @a filename. * * @see loadStateFromFile() */ bool saveStateToFile(const char* filename); /*! * Save the plugin state from @a filename. * * @see saveStateToFile() */ bool loadStateFromFile(const char* filename); /*! * Export this plugin as LV2. */ bool exportAsLV2(const char* lv2path); // ------------------------------------------------------------------- // Set data (internal stuff) /*! * Set the plugin's id to @a newId. * * @see getId() * @note RT call */ virtual void setId(uint newId) noexcept; /*! * Set the plugin's name to @a newName. * * @see getName() and getRealName() */ virtual void setName(const char* newName); /*! * Set a plugin's option. * * @see getOptions() and getOptionsAvailable() */ virtual void setOption(uint option, bool yesNo, bool sendCallback); /*! * Enable or disable the plugin according to @a yesNo. * When a plugin is disabled, it will never be processed or managed in any way. * * @see isEnabled() */ void setEnabled(bool yesNo) noexcept; /*! * Set plugin as active according to @a active. * * @param sendOsc Send message change over OSC * @param sendCallback Send message change to registered callback */ void setActive(bool active, bool sendOsc, bool sendCallback) noexcept; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH /*! * Set the plugin's dry/wet signal value to @a value. * @a value must be between 0.0 and 1.0. * * @param sendOsc Send message change over OSC * @param sendCallback Send message change to registered callback */ void setDryWet(float value, bool sendOsc, bool sendCallback) noexcept; /*! * Set the plugin's output volume to @a value. * @a value must be between 0.0 and 1.27. * * @param sendOsc Send message change over OSC * @param sendCallback Send message change to registered callback */ void setVolume(float value, bool sendOsc, bool sendCallback) noexcept; /*! * Set the plugin's output left balance value to @a value. * @a value must be between -1.0 and 1.0. * * @param sendOsc Send message change over OSC * @param sendCallback Send message change to registered callback * * @note Pure-Stereo plugins only! */ void setBalanceLeft(float value, bool sendOsc, bool sendCallback) noexcept; /*! * Set the plugin's output right balance value to @a value. * @a value must be between -1.0 and 1.0. * * @param sendOsc Send message change over OSC * @param sendCallback Send message change to registered callback * * @note Pure-Stereo plugins only! */ void setBalanceRight(float value, bool sendOsc, bool sendCallback) noexcept; /*! * Set the plugin's output panning value to @a value. * @a value must be between -1.0 and 1.0. * * @param sendOsc Send message change over OSC * @param sendCallback Send message change to registered callback * * @note Force-Stereo plugins only! */ void setPanning(float value, bool sendOsc, bool sendCallback) noexcept; /*! * Overloaded functions, to be called from within RT context only. */ void setDryWetRT(float value, bool sendCallbackLater) noexcept; void setVolumeRT(float value, bool sendCallbackLater) noexcept; void setBalanceLeftRT(float value, bool sendCallbackLater) noexcept; void setBalanceRightRT(float value, bool sendCallbackLater) noexcept; void setPanningRT(float value, bool sendCallbackLater) noexcept; #endif // ! BUILD_BRIDGE_ALTERNATIVE_ARCH /*! * Set the plugin's midi control channel. * * @param sendOsc Send message change over OSC * @param sendCallback Send message change to registered callback */ virtual void setCtrlChannel(int8_t channel, bool sendOsc, bool sendCallback) noexcept; // ------------------------------------------------------------------- // Set data (plugin-specific stuff) /*! * Set a plugin's parameter value. * * @param parameterId The parameter to change * @param value The new parameter value, must be within the parameter's range * @param sendGui Send message change to plugin's custom GUI, if any * @param sendOsc Send message change over OSC * @param sendCallback Send message change to registered callback * * @see getParameterValue() */ virtual void setParameterValue(uint32_t parameterId, float value, bool sendGui, bool sendOsc, bool sendCallback) noexcept; /*! * Overloaded function, to be called from within RT context only. */ virtual void setParameterValueRT(uint32_t parameterId, float value, bool sendCallbackLater) noexcept; /*! * Set a plugin's parameter value, including internal parameters. * @a rindex can be negative to allow internal parameters change (as defined in InternalParametersIndex). * * @see setParameterValue() * @see setActive() * @see setDryWet() * @see setVolume() * @see setBalanceLeft() * @see setBalanceRight() */ void setParameterValueByRealIndex(int32_t rindex, float value, bool sendGui, bool sendOsc, bool sendCallback) noexcept; /*! * Set parameter's @a parameterId MIDI channel to @a channel. * @a channel must be between 0 and 15. */ virtual void setParameterMidiChannel(uint32_t parameterId, uint8_t channel, bool sendOsc, bool sendCallback) noexcept; /*! * Set parameter's @a parameterId mapped control index to @a index. * @see ParameterData::mappedControlIndex */ virtual void setParameterMappedControlIndex(uint32_t parameterId, int16_t index, bool sendOsc, bool sendCallback) noexcept; /*! * Set parameter's @a parameterId mapped range to @a minimum and @a maximum. */ virtual void setParameterMappedRange(uint32_t parameterId, float minimum, float maximum, bool sendOsc, bool sendCallback) noexcept; /*! * Add a custom data set. * If @a key already exists, its current value will be swapped with @a value. * * @param type Type of data used in @a value. * @param key A key identifying this data set. * @param value The value of the data set, of type @a type. * @param sendGui Send message change to plugin's custom GUI, if any * * @see getCustomDataCount() and getCustomData() */ virtual void setCustomData(const char* type, const char* key, const char* value, bool sendGui); /*! * Set the complete chunk data as @a data. * * @see getChunkData() * * @note Make sure to verify the plugin supports chunks before calling this function */ virtual void setChunkData(const void* data, std::size_t dataSize); /*! * Change the current plugin program to @a index. * * If @a index is negative the plugin's program will be considered unset. * The plugin's default parameter values will be updated when this function is called. * * @param index New program index to use * @param sendGui Send message change to plugin's custom GUI, if any * @param sendOsc Send message change over OSC * @param sendCallback Send message change to registered callback */ virtual void setProgram(int32_t index, bool sendGui, bool sendOsc, bool sendCallback, bool doingInit = false) noexcept; /*! * Change the current MIDI plugin program to @a index. * * If @a index is negative the plugin's program will be considered unset. * The plugin's default parameter values will be updated when this function is called. * * @param index New program index to use * @param sendGui Send message change to plugin's custom GUI, if any * @param sendOsc Send message change over OSC * @param sendCallback Send message change to registered callback */ virtual void setMidiProgram(int32_t index, bool sendGui, bool sendOsc, bool sendCallback, bool doingInit = false) noexcept; /*! * This is an overloaded call to setMidiProgram(). * It changes the current MIDI program using @a bank and @a program values instead of index. */ void setMidiProgramById(uint32_t bank, uint32_t program, bool sendGui, bool sendOsc, bool sendCallback) noexcept; /*! * Overloaded functions, to be called from within RT context only. */ virtual void setProgramRT(uint32_t index, bool sendCallbackLater) noexcept; virtual void setMidiProgramRT(uint32_t index, bool sendCallbackLater) noexcept; // ------------------------------------------------------------------- // Plugin state /*! * Reload the plugin's entire state (including programs). * The plugin will be disabled during this call. */ virtual void reload() = 0; /*! * Reload the plugin's programs state. */ virtual void reloadPrograms(bool doInit); // ------------------------------------------------------------------- // Plugin processing protected: /*! * Plugin activate call. */ virtual void activate() noexcept; /*! * Plugin activate call. */ virtual void deactivate() noexcept; public: /*! * Plugin process call. */ virtual void process(const float* const* audioIn, float** audioOut, const float* const* cvIn, float** cvOut, uint32_t frames) = 0; /*! * Tell the plugin the current buffer size changed. */ virtual void bufferSizeChanged(uint32_t newBufferSize); /*! * Tell the plugin the current sample rate changed. */ virtual void sampleRateChanged(double newSampleRate); /*! * Tell the plugin the current offline mode changed. */ virtual void offlineModeChanged(bool isOffline); // ------------------------------------------------------------------- // Misc /*! * Idle function (non-UI), called at regular intervals. * @note: This function is NOT called from the main thread. */ virtual void idle(); /*! * Try to lock the plugin's master mutex. * @param forcedOffline When true, always locks and returns true */ bool tryLock(bool forcedOffline) noexcept; /*! * Unlock the plugin's master mutex. */ void unlock() noexcept; // ------------------------------------------------------------------- // Plugin buffers /*! * Initialize all RT buffers of the plugin. */ virtual void initBuffers() const noexcept; /*! * Delete and clear all RT buffers. */ virtual void clearBuffers() noexcept; // ------------------------------------------------------------------- // OSC stuff /*! * Handle an OSC message. * FIXME */ virtual void handleOscMessage(const char* method, int argc, const void* argv, const char* types, lo_message msg); // ------------------------------------------------------------------- // MIDI events /*! * Send a single midi note to be processed in the next audio callback. * A note with 0 velocity means note-off. * @note Non-RT call */ void sendMidiSingleNote(uint8_t channel, uint8_t note, uint8_t velo, bool sendGui, bool sendOsc, bool sendCallback); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH /*! * Send all midi notes off to the host callback. * This doesn't send the actual MIDI All-Notes-Off event, but 128 note-offs instead (IFF ctrlChannel is valid). * @note RT call */ void postponeRtAllNotesOff(); #endif // ------------------------------------------------------------------- // UI Stuff /*! * Show (or hide) the plugin's custom UI according to @a yesNo. * This function is always called from the main thread. */ virtual void showCustomUI(bool yesNo); /*! * UI idle function, called at regular intervals. * This function is only called from the main thread if PLUGIN_NEEDS_UI_MAIN_THREAD is set. * @note This function may sometimes be called even if the UI is not visible yet. */ virtual void uiIdle(); /*! * Tell the UI a parameter has changed. * @see uiIdle */ virtual void uiParameterChange(uint32_t index, float value) noexcept; /*! * Tell the UI the current program has changed. * @see uiIdle */ virtual void uiProgramChange(uint32_t index) noexcept; /*! * Tell the UI the current midi program has changed. * @see uiIdle */ virtual void uiMidiProgramChange(uint32_t index) noexcept; /*! * Tell the UI a note has been pressed. * @see uiIdle */ virtual void uiNoteOn(uint8_t channel, uint8_t note, uint8_t velo) noexcept; /*! * Tell the UI a note has been released. * @see uiIdle */ virtual void uiNoteOff(uint8_t channel, uint8_t note) noexcept; // ------------------------------------------------------------------- // Helper functions /*! * Get the plugin's engine, as passed in the constructor. */ CarlaEngine* getEngine() const noexcept; /*! * Get the plugin's engine client. */ CarlaEngineClient* getEngineClient() const noexcept; /*! * Get a plugin's audio input port. */ CarlaEngineAudioPort* getAudioInPort(uint32_t index) const noexcept; /*! * Get a plugin's audio output port. */ CarlaEngineAudioPort* getAudioOutPort(uint32_t index) const noexcept; /*! * Get a plugin's CV input port. */ CarlaEngineCVPort* getCVInPort(uint32_t index) const noexcept; /*! * Get a plugin's CV output port. */ CarlaEngineCVPort* getCVOutPort(uint32_t index) const noexcept; /*! * Get the plugin's default event input port. */ CarlaEngineEventPort* getDefaultEventInPort() const noexcept; /*! * Get the plugin's default event output port. */ CarlaEngineEventPort* getDefaultEventOutPort() const noexcept; /*! * Get the plugin's type native handle. * This will be LADSPA_Handle, LV2_Handle, etc. */ virtual void* getNativeHandle() const noexcept; /*! * Get the plugin's type native descriptor. * This will be LADSPA_Descriptor, DSSI_Descriptor, LV2_Descriptor, AEffect, etc. */ virtual const void* getNativeDescriptor() const noexcept; /*! * Get the plugin UI bridge process Id. */ virtual uintptr_t getUiBridgeProcessId() const noexcept; // ------------------------------------------------------------------- /*! * Get the plugin's patchbay nodeId. * @see setPatchbayNodeId() */ uint32_t getPatchbayNodeId() const noexcept; /*! * Set the plugin's patchbay nodeId. * @see getPatchbayNodeId() */ void setPatchbayNodeId(uint32_t nodeId) noexcept; // ------------------------------------------------------------------- // Plugin initializers /*! * Get a plugin's binary type. * This is always BINARY_NATIVE unless the plugin is a bridge. */ virtual BinaryType getBinaryType() const noexcept { return BINARY_NATIVE; } /*! * Handy function required by CarlaEngine::clonePlugin(). */ virtual const void* getExtraStuff() const noexcept { return nullptr; } #ifndef DOXYGEN struct Initializer { CarlaEngine* const engine; const uint id; const char* const filename; const char* const name; const char* const label; const int64_t uniqueId; const uint options; // see PluginOptions }; static CarlaPlugin* newNative(const Initializer& init); static CarlaPlugin* newBridge(const Initializer& init, BinaryType btype, PluginType ptype, const char* bridgeBinary); static CarlaPlugin* newLADSPA(const Initializer& init, const LADSPA_RDF_Descriptor* rdfDescriptor); static CarlaPlugin* newDSSI(const Initializer& init); static CarlaPlugin* newLV2(const Initializer& init); static CarlaPlugin* newVST2(const Initializer& init); static CarlaPlugin* newVST3(const Initializer& init); static CarlaPlugin* newAU(const Initializer& init); static CarlaPlugin* newJuce(const Initializer& init, const char* format); static CarlaPlugin* newFluidSynth(const Initializer& init, bool use16Outs); static CarlaPlugin* newSFZero(const Initializer& init); static CarlaPlugin* newJackApp(const Initializer& init); #endif // ------------------------------------------------------------------- protected: /*! * Internal data, for CarlaPlugin subclasses only. */ struct ProtectedData; ProtectedData* const pData; // ------------------------------------------------------------------- // Internal helper functions public: // FIXME: remove public exception on 2.1 release /*! * Call LV2 restore. */ virtual void restoreLV2State() noexcept; protected: /*! * Give plugin bridges a change to update their custom data sets. */ virtual void waitForBridgeSaveSignal() noexcept; // ------------------------------------------------------------------- // Helper classes /*! * Fully disable plugin in scope and also its engine client. * May wait-block on constructor for plugin process to end. */ class ScopedDisabler { public: ScopedDisabler(CarlaPlugin* plugin) noexcept; ~ScopedDisabler() noexcept; private: CarlaPlugin* const fPlugin; bool fWasEnabled; CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_CLASS(ScopedDisabler) }; /*! * Lock the plugin's own run/process call. * Plugin will still work as normal, but output only silence. * On destructor needsReset flag might be set if the plugin might have missed some events. */ class ScopedSingleProcessLocker { public: ScopedSingleProcessLocker(CarlaPlugin* plugin, bool block) noexcept; ~ScopedSingleProcessLocker() noexcept; private: CarlaPlugin* const fPlugin; const bool fBlock; CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_CLASS(ScopedSingleProcessLocker) }; friend class CarlaEngineBridge; CARLA_DECLARE_NON_COPY_CLASS(CarlaPlugin) }; /**@}*/ // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE #endif // CARLA_PLUGIN_HPP_INCLUDED Carla-2.1/source/backend/CarlaStandalone.cpp000066400000000000000000002431721364475620200210460ustar00rootroot00000000000000/* * Carla Standalone * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ // TODO: // Check carla_stderr2("Engine is not running"); <= prepend func name and args #include "CarlaHost.h" #include "CarlaMIDI.h" #include "CarlaEngine.hpp" #include "CarlaPlugin.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaBase64Utils.hpp" #include "ThreadSafeFFTW.hpp" #ifdef BUILD_BRIDGE # include "water/files/File.h" #else # include "CarlaLogThread.hpp" #endif #ifdef USING_JUCE # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Weffc++" # pragma GCC diagnostic ignored "-Wsign-conversion" # pragma GCC diagnostic ignored "-Wundef" # endif # include "AppConfig.h" # include "juce_events/juce_events.h" # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic pop # endif #endif #define CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(cond, msg, ret) \ if (! (cond)) { \ carla_stderr2("%s: " msg, __FUNCTION__); \ gStandalone.lastError = msg; \ return ret; \ } namespace CB = CarlaBackend; using CB::EngineOptions; // -------------------------------------------------------------------------------------------------------------------- // Single, standalone engine struct CarlaBackendStandalone { CarlaEngine* engine; EngineCallbackFunc engineCallback; void* engineCallbackPtr; #ifndef BUILD_BRIDGE EngineOptions engineOptions; CarlaLogThread logThread; bool logThreadEnabled; #endif FileCallbackFunc fileCallback; void* fileCallbackPtr; CarlaString lastError; CarlaBackendStandalone() noexcept : engine(nullptr), engineCallback(nullptr), engineCallbackPtr(nullptr), #ifndef BUILD_BRIDGE engineOptions(), logThread(), logThreadEnabled(false), #endif fileCallback(nullptr), fileCallbackPtr(nullptr), lastError() {} ~CarlaBackendStandalone() noexcept { CARLA_SAFE_ASSERT(engine == nullptr); } CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_STRUCT(CarlaBackendStandalone) }; CarlaBackendStandalone gStandalone; #ifdef CARLA_OS_UNIX static ThreadSafeFFTW sThreadSafeFFTW; #endif // -------------------------------------------------------------------------------------------------------------------- // API #define CARLA_COMMON_NEED_CHECKSTRINGPTR #include "CarlaHostCommon.cpp" #undef CARLA_COMMON_NEED_CHECKSTRINGPTR // -------------------------------------------------------------------------------------------------------------------- uint carla_get_engine_driver_count() { carla_debug("carla_get_engine_driver_count()"); return CarlaEngine::getDriverCount(); } const char* carla_get_engine_driver_name(uint index) { carla_debug("carla_get_engine_driver_name(%i)", index); return CarlaEngine::getDriverName(index); } const char* const* carla_get_engine_driver_device_names(uint index) { carla_debug("carla_get_engine_driver_device_names(%i)", index); return CarlaEngine::getDriverDeviceNames(index); } const EngineDriverDeviceInfo* carla_get_engine_driver_device_info(uint index, const char* name) { CARLA_SAFE_ASSERT_RETURN(name != nullptr, nullptr); static EngineDriverDeviceInfo retDevInfo; static const uint32_t nullBufferSizes[] = { 0 }; static const double nullSampleRates[] = { 0.0 }; carla_debug("carla_get_engine_driver_device_info(%i, \"%s\")", index, name); if (const EngineDriverDeviceInfo* const devInfo = CarlaEngine::getDriverDeviceInfo(index, name)) { retDevInfo.hints = devInfo->hints; retDevInfo.bufferSizes = (devInfo->bufferSizes != nullptr) ? devInfo->bufferSizes : nullBufferSizes; retDevInfo.sampleRates = (devInfo->sampleRates != nullptr) ? devInfo->sampleRates : nullSampleRates; } else { retDevInfo.hints = 0x0; retDevInfo.bufferSizes = nullBufferSizes; retDevInfo.sampleRates = nullSampleRates; } return &retDevInfo; } bool carla_show_engine_driver_device_control_panel(uint index, const char* name) { return CarlaEngine::showDriverDeviceControlPanel(index, name); } // -------------------------------------------------------------------------------------------------------------------- CarlaEngine* carla_get_engine() { carla_debug("carla_get_engine()"); return gStandalone.engine; } // -------------------------------------------------------------------------------------------------------------------- static void carla_engine_init_common(CarlaEngine* const engine) { engine->setCallback(gStandalone.engineCallback, gStandalone.engineCallbackPtr); engine->setFileCallback(gStandalone.fileCallback, gStandalone.fileCallbackPtr); using water::File; const File waterBinaryDir(File::getSpecialLocation(File::currentExecutableFile).getParentDirectory()); #ifdef BUILD_BRIDGE /* if (const char* const forceStereo = std::getenv("ENGINE_OPTION_FORCE_STEREO")) engine->setOption(CB::ENGINE_OPTION_FORCE_STEREO, (std::strcmp(forceStereo, "true") == 0) ? 1 : 0, nullptr); if (const char* const preferPluginBridges = std::getenv("ENGINE_OPTION_PREFER_PLUGIN_BRIDGES")) engine->setOption(CB::ENGINE_OPTION_PREFER_PLUGIN_BRIDGES, (std::strcmp(preferPluginBridges, "true") == 0) ? 1 : 0, nullptr); if (const char* const preferUiBridges = std::getenv("ENGINE_OPTION_PREFER_UI_BRIDGES")) engine->setOption(CB::ENGINE_OPTION_PREFER_UI_BRIDGES, (std::strcmp(preferUiBridges, "true") == 0) ? 1 : 0, nullptr); */ if (const char* const uisAlwaysOnTop = std::getenv("ENGINE_OPTION_UIS_ALWAYS_ON_TOP")) engine->setOption(CB::ENGINE_OPTION_UIS_ALWAYS_ON_TOP, (std::strcmp(uisAlwaysOnTop, "true") == 0) ? 1 : 0, nullptr); if (const char* const maxParameters = std::getenv("ENGINE_OPTION_MAX_PARAMETERS")) engine->setOption(CB::ENGINE_OPTION_MAX_PARAMETERS, std::atoi(maxParameters), nullptr); if (const char* const resetXruns = std::getenv("ENGINE_OPTION_RESET_XRUNS")) engine->setOption(CB::ENGINE_OPTION_RESET_XRUNS, (std::strcmp(resetXruns, "true") == 0) ? 1 : 0, nullptr); if (const char* const uiBridgesTimeout = std::getenv("ENGINE_OPTION_UI_BRIDGES_TIMEOUT")) engine->setOption(CB::ENGINE_OPTION_UI_BRIDGES_TIMEOUT, std::atoi(uiBridgesTimeout), nullptr); if (const char* const pathAudio = std::getenv("ENGINE_OPTION_FILE_PATH_AUDIO")) engine->setOption(CB::ENGINE_OPTION_FILE_PATH, CB::FILE_AUDIO, pathAudio); if (const char* const pathMIDI = std::getenv("ENGINE_OPTION_FILE_PATH_MIDI")) engine->setOption(CB::ENGINE_OPTION_FILE_PATH, CB::FILE_MIDI, pathMIDI); if (const char* const pathLADSPA = std::getenv("ENGINE_OPTION_PLUGIN_PATH_LADSPA")) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_LADSPA, pathLADSPA); if (const char* const pathDSSI = std::getenv("ENGINE_OPTION_PLUGIN_PATH_DSSI")) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_DSSI, pathDSSI); if (const char* const pathLV2 = std::getenv("ENGINE_OPTION_PLUGIN_PATH_LV2")) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_LV2, pathLV2); if (const char* const pathVST2 = std::getenv("ENGINE_OPTION_PLUGIN_PATH_VST2")) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_VST2, pathVST2); if (const char* const pathVST3 = std::getenv("ENGINE_OPTION_PLUGIN_PATH_VST3")) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_VST3, pathVST3); if (const char* const pathSF2 = std::getenv("ENGINE_OPTION_PLUGIN_PATH_SF2")) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_SF2, pathSF2); if (const char* const pathSFZ = std::getenv("ENGINE_OPTION_PLUGIN_PATH_SFZ")) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_SFZ, pathSFZ); if (const char* const binaryDir = std::getenv("ENGINE_OPTION_PATH_BINARIES")) engine->setOption(CB::ENGINE_OPTION_PATH_BINARIES, 0, binaryDir); else engine->setOption(CB::ENGINE_OPTION_PATH_BINARIES, 0, waterBinaryDir.getFullPathName().toRawUTF8()); if (const char* const resourceDir = std::getenv("ENGINE_OPTION_PATH_RESOURCES")) engine->setOption(CB::ENGINE_OPTION_PATH_RESOURCES, 0, resourceDir); else engine->setOption(CB::ENGINE_OPTION_PATH_RESOURCES, 0, waterBinaryDir.getChildFile("resources").getFullPathName().toRawUTF8()); if (const char* const preventBadBehaviour = std::getenv("ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR")) engine->setOption(CB::ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR, (std::strcmp(preventBadBehaviour, "true") == 0) ? 1 : 0, nullptr); if (const char* const frontendWinId = std::getenv("ENGINE_OPTION_FRONTEND_WIN_ID")) engine->setOption(CB::ENGINE_OPTION_FRONTEND_WIN_ID, 0, frontendWinId); #else engine->setOption(CB::ENGINE_OPTION_FORCE_STEREO, gStandalone.engineOptions.forceStereo ? 1 : 0, nullptr); engine->setOption(CB::ENGINE_OPTION_PREFER_PLUGIN_BRIDGES, gStandalone.engineOptions.preferPluginBridges ? 1 : 0, nullptr); engine->setOption(CB::ENGINE_OPTION_PREFER_UI_BRIDGES, gStandalone.engineOptions.preferUiBridges ? 1 : 0, nullptr); engine->setOption(CB::ENGINE_OPTION_UIS_ALWAYS_ON_TOP, gStandalone.engineOptions.uisAlwaysOnTop ? 1 : 0, nullptr); engine->setOption(CB::ENGINE_OPTION_MAX_PARAMETERS, static_cast(gStandalone.engineOptions.maxParameters), nullptr); engine->setOption(CB::ENGINE_OPTION_RESET_XRUNS, gStandalone.engineOptions.resetXruns ? 1 : 0, nullptr); engine->setOption(CB::ENGINE_OPTION_UI_BRIDGES_TIMEOUT, static_cast(gStandalone.engineOptions.uiBridgesTimeout), nullptr); engine->setOption(CB::ENGINE_OPTION_AUDIO_BUFFER_SIZE, static_cast(gStandalone.engineOptions.audioBufferSize), nullptr); engine->setOption(CB::ENGINE_OPTION_AUDIO_SAMPLE_RATE, static_cast(gStandalone.engineOptions.audioSampleRate), nullptr); engine->setOption(CB::ENGINE_OPTION_AUDIO_TRIPLE_BUFFER, gStandalone.engineOptions.audioTripleBuffer ? 1 : 0, nullptr); if (gStandalone.engineOptions.audioDriver != nullptr) engine->setOption(CB::ENGINE_OPTION_AUDIO_DRIVER, 0, gStandalone.engineOptions.audioDriver); if (gStandalone.engineOptions.audioDevice != nullptr) engine->setOption(CB::ENGINE_OPTION_AUDIO_DEVICE, 0, gStandalone.engineOptions.audioDevice); engine->setOption(CB::ENGINE_OPTION_OSC_ENABLED, gStandalone.engineOptions.oscEnabled, nullptr); engine->setOption(CB::ENGINE_OPTION_OSC_PORT_TCP, gStandalone.engineOptions.oscPortTCP, nullptr); engine->setOption(CB::ENGINE_OPTION_OSC_PORT_UDP, gStandalone.engineOptions.oscPortUDP, nullptr); if (gStandalone.engineOptions.pathAudio != nullptr) engine->setOption(CB::ENGINE_OPTION_FILE_PATH, CB::FILE_AUDIO, gStandalone.engineOptions.pathAudio); if (gStandalone.engineOptions.pathMIDI != nullptr) engine->setOption(CB::ENGINE_OPTION_FILE_PATH, CB::FILE_MIDI, gStandalone.engineOptions.pathMIDI); if (gStandalone.engineOptions.pathLADSPA != nullptr) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_LADSPA, gStandalone.engineOptions.pathLADSPA); if (gStandalone.engineOptions.pathDSSI != nullptr) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_DSSI, gStandalone.engineOptions.pathDSSI); if (gStandalone.engineOptions.pathLV2 != nullptr) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_LV2, gStandalone.engineOptions.pathLV2); if (gStandalone.engineOptions.pathVST2 != nullptr) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_VST2, gStandalone.engineOptions.pathVST2); if (gStandalone.engineOptions.pathVST3 != nullptr) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_VST3, gStandalone.engineOptions.pathVST3); if (gStandalone.engineOptions.pathSF2 != nullptr) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_SF2, gStandalone.engineOptions.pathSF2); if (gStandalone.engineOptions.pathSFZ != nullptr) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_SFZ, gStandalone.engineOptions.pathSFZ); if (gStandalone.engineOptions.binaryDir != nullptr && gStandalone.engineOptions.binaryDir[0] != '\0') engine->setOption(CB::ENGINE_OPTION_PATH_BINARIES, 0, gStandalone.engineOptions.binaryDir); else engine->setOption(CB::ENGINE_OPTION_PATH_BINARIES, 0, waterBinaryDir.getFullPathName().toRawUTF8()); if (gStandalone.engineOptions.resourceDir != nullptr && gStandalone.engineOptions.resourceDir[0] != '\0') engine->setOption(CB::ENGINE_OPTION_PATH_RESOURCES, 0, gStandalone.engineOptions.resourceDir); engine->setOption(CB::ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR, gStandalone.engineOptions.preventBadBehaviour ? 1 : 0, nullptr); engine->setOption(CB::ENGINE_OPTION_FRONTEND_BACKGROUND_COLOR, static_cast(gStandalone.engineOptions.bgColor), nullptr); engine->setOption(CB::ENGINE_OPTION_FRONTEND_FOREGROUND_COLOR, static_cast(gStandalone.engineOptions.fgColor), nullptr); engine->setOption(CB::ENGINE_OPTION_FRONTEND_UI_SCALE, static_cast(gStandalone.engineOptions.uiScale * 1000.0f), nullptr); if (gStandalone.engineOptions.frontendWinId != 0) { char strBuf[STR_MAX+1]; strBuf[STR_MAX] = '\0'; std::snprintf(strBuf, STR_MAX, P_UINTPTR, gStandalone.engineOptions.frontendWinId); engine->setOption(CB::ENGINE_OPTION_FRONTEND_WIN_ID, 0, strBuf); } else { engine->setOption(CB::ENGINE_OPTION_FRONTEND_WIN_ID, 0, "0"); } # ifndef CARLA_OS_WIN if (gStandalone.engineOptions.wine.executable != nullptr && gStandalone.engineOptions.wine.executable[0] != '\0') engine->setOption(CB::ENGINE_OPTION_WINE_EXECUTABLE, 0, gStandalone.engineOptions.wine.executable); engine->setOption(CB::ENGINE_OPTION_WINE_AUTO_PREFIX, gStandalone.engineOptions.wine.autoPrefix ? 1 : 0, nullptr); if (gStandalone.engineOptions.wine.fallbackPrefix != nullptr && gStandalone.engineOptions.wine.fallbackPrefix[0] != '\0') engine->setOption(CB::ENGINE_OPTION_WINE_FALLBACK_PREFIX, 0, gStandalone.engineOptions.wine.fallbackPrefix); engine->setOption(CB::ENGINE_OPTION_WINE_RT_PRIO_ENABLED, gStandalone.engineOptions.wine.rtPrio ? 1 : 0, nullptr); engine->setOption(CB::ENGINE_OPTION_WINE_BASE_RT_PRIO, gStandalone.engineOptions.wine.baseRtPrio, nullptr); engine->setOption(CB::ENGINE_OPTION_WINE_SERVER_RT_PRIO, gStandalone.engineOptions.wine.serverRtPrio, nullptr); # endif #endif } bool carla_engine_init(const char* driverName, const char* clientName) { CARLA_SAFE_ASSERT_RETURN(driverName != nullptr && driverName[0] != '\0', false); CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false); carla_debug("carla_engine_init(\"%s\", \"%s\")", driverName, clientName); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine == nullptr, "Engine is already initialized", false); #ifdef CARLA_OS_WIN carla_setenv("WINEASIO_CLIENT_NAME", clientName); #endif #ifdef USING_JUCE juce::initialiseJuce_GUI(); #endif CarlaEngine* const engine = CarlaEngine::newDriverByName(driverName); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(engine != nullptr, "The selected audio driver is not available", false); gStandalone.engine = engine; #ifdef BUILD_BRIDGE if (std::getenv("CARLA_BRIDGE_DUMMY") != nullptr) { // engine->setOption(CB::ENGINE_OPTION_PROCESS_MODE, CB::ENGINE_PROCESS_MODE_PATCHBAY, nullptr); engine->setOption(CB::ENGINE_OPTION_PROCESS_MODE, CB::ENGINE_PROCESS_MODE_CONTINUOUS_RACK, nullptr); engine->setOption(CB::ENGINE_OPTION_TRANSPORT_MODE, CB::ENGINE_TRANSPORT_MODE_INTERNAL, nullptr); engine->setOption(CB::ENGINE_OPTION_AUDIO_BUFFER_SIZE, 4096, nullptr); engine->setOption(CB::ENGINE_OPTION_AUDIO_SAMPLE_RATE, 48000, nullptr); } else { engine->setOption(CB::ENGINE_OPTION_PROCESS_MODE, CB::ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, nullptr); engine->setOption(CB::ENGINE_OPTION_TRANSPORT_MODE, CB::ENGINE_TRANSPORT_MODE_JACK, nullptr); } engine->setOption(CB::ENGINE_OPTION_FORCE_STEREO, false, nullptr); engine->setOption(CB::ENGINE_OPTION_PREFER_PLUGIN_BRIDGES, false, nullptr); engine->setOption(CB::ENGINE_OPTION_PREFER_UI_BRIDGES, false, nullptr); #else engine->setOption(CB::ENGINE_OPTION_PROCESS_MODE, static_cast(gStandalone.engineOptions.processMode), nullptr); engine->setOption(CB::ENGINE_OPTION_TRANSPORT_MODE, static_cast(gStandalone.engineOptions.transportMode), gStandalone.engineOptions.transportExtra); #endif carla_engine_init_common(engine); if (engine->init(clientName)) { #ifndef BUILD_BRIDGE if (gStandalone.logThreadEnabled && std::getenv("CARLA_LOGS_DISABLED") == nullptr) gStandalone.logThread.init(); #endif #ifdef CARLA_OS_UNIX sThreadSafeFFTW.init(); #endif gStandalone.lastError = "No error"; return true; } else { gStandalone.lastError = engine->getLastError(); gStandalone.engine = nullptr; delete engine; #ifdef USING_JUCE juce::shutdownJuce_GUI(); #endif return false; } } #ifdef BUILD_BRIDGE bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtClientBaseName[6+1], const char nonRtClientBaseName[6+1], const char nonRtServerBaseName[6+1], const char* const clientName) { CARLA_SAFE_ASSERT_RETURN(audioBaseName != nullptr && audioBaseName[0] != '\0', false); CARLA_SAFE_ASSERT_RETURN(rtClientBaseName != nullptr && rtClientBaseName[0] != '\0', false); CARLA_SAFE_ASSERT_RETURN(nonRtClientBaseName != nullptr && nonRtClientBaseName[0] != '\0', false); CARLA_SAFE_ASSERT_RETURN(nonRtServerBaseName != nullptr && nonRtServerBaseName[0] != '\0', false); CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false); carla_debug("carla_engine_init_bridge(\"%s\", \"%s\", \"%s\", \"%s\", \"%s\")", audioBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName, clientName); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine == nullptr, "Engine is already initialized", false); CarlaScopedPointer engine(CarlaEngine::newBridge(audioBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName)); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(engine != nullptr, "The selected audio driver is not available", false); engine->setOption(CB::ENGINE_OPTION_PROCESS_MODE, CB::ENGINE_PROCESS_MODE_BRIDGE, nullptr); engine->setOption(CB::ENGINE_OPTION_TRANSPORT_MODE, CB::ENGINE_TRANSPORT_MODE_BRIDGE, nullptr); carla_engine_init_common(engine); if (engine->init(clientName)) { gStandalone.lastError = "No error"; gStandalone.engine = engine.release(); return true; } else { gStandalone.lastError = engine->getLastError(); return false; } } #endif bool carla_engine_close() { carla_debug("carla_engine_close()"); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); #ifdef CARLA_OS_UNIX const ThreadSafeFFTW::Deinitializer tsfftwde(sThreadSafeFFTW); #endif CarlaEngine* const engine = gStandalone.engine; engine->setAboutToClose(); engine->removeAllPlugins(); const bool closed = engine->close(); if (! closed) gStandalone.lastError = engine->getLastError(); #ifndef BUILD_BRIDGE gStandalone.logThread.stop(); #endif gStandalone.engine = nullptr; delete engine; #ifdef USING_JUCE juce::shutdownJuce_GUI(); #endif return closed; } void carla_engine_idle() { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); gStandalone.engine->idle(); #if defined(USING_JUCE) && !(defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) const juce::MessageManager* const msgMgr(juce::MessageManager::getInstanceWithoutCreating()); CARLA_SAFE_ASSERT_RETURN(msgMgr != nullptr,); for (; msgMgr->dispatchNextMessageOnSystemQueue(true);) {} #endif } bool carla_is_engine_running() { return (gStandalone.engine != nullptr && gStandalone.engine->isRunning()); } const CarlaRuntimeEngineInfo* carla_get_runtime_engine_info() { static CarlaRuntimeEngineInfo retInfo; // reset retInfo.load = 0.0f; retInfo.xruns = 0; CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, &retInfo); retInfo.load = gStandalone.engine->getDSPLoad(); retInfo.xruns = gStandalone.engine->getTotalXruns(); return &retInfo; } #ifndef BUILD_BRIDGE const CarlaRuntimeEngineDriverDeviceInfo* carla_get_runtime_engine_driver_device_info() { static CarlaRuntimeEngineDriverDeviceInfo retInfo; // reset retInfo.name = gNullCharPtr; retInfo.hints = 0x0; retInfo.bufferSize = 0; retInfo.bufferSizes = nullptr; retInfo.sampleRate = 0.0; retInfo.sampleRates = nullptr; const char* audioDriver; const char* audioDevice; if (CarlaEngine* const engine = gStandalone.engine) { audioDriver = engine->getCurrentDriverName(); audioDevice = engine->getOptions().audioDevice; retInfo.bufferSize = engine->getBufferSize(); retInfo.sampleRate = engine->getSampleRate(); } else { audioDriver = gStandalone.engineOptions.audioDriver; audioDevice = gStandalone.engineOptions.audioDevice; retInfo.bufferSize = gStandalone.engineOptions.audioBufferSize; retInfo.sampleRate = gStandalone.engineOptions.audioSampleRate; } CARLA_SAFE_ASSERT_RETURN(audioDriver != nullptr, &retInfo); CARLA_SAFE_ASSERT_RETURN(audioDevice != nullptr, &retInfo); uint index = 0; uint count = CarlaEngine::getDriverCount(); for (; indexhints; retInfo.bufferSizes = devInfo->bufferSizes; retInfo.sampleRates = devInfo->sampleRates; return &retInfo; } bool carla_set_engine_buffer_size_and_sample_rate(uint bufferSize, double sampleRate) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, false); carla_debug("carla_set_engine_buffer_size_and_sample_rate(%u, %f)", bufferSize, sampleRate); return gStandalone.engine->setBufferSizeAndSampleRate(bufferSize, sampleRate); } bool carla_show_engine_device_control_panel() { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, false); carla_debug("carla_show_engine_device_control_panel()"); return gStandalone.engine->showDeviceControlPanel(); } #endif void carla_clear_engine_xruns() { if (gStandalone.engine != nullptr) gStandalone.engine->clearXruns(); } void carla_cancel_engine_action() { if (gStandalone.engine != nullptr) gStandalone.engine->setActionCanceled(true); } bool carla_set_engine_about_to_close() { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, true); carla_debug("carla_set_engine_about_to_close()"); return gStandalone.engine->setAboutToClose(); } void carla_set_engine_callback(EngineCallbackFunc func, void* ptr) { carla_debug("carla_set_engine_callback(%p, %p)", func, ptr); gStandalone.engineCallback = func; gStandalone.engineCallbackPtr = ptr; #ifndef BUILD_BRIDGE gStandalone.logThread.setCallback(func, ptr); #endif if (gStandalone.engine != nullptr) gStandalone.engine->setCallback(func, ptr); } #ifndef BUILD_BRIDGE void carla_set_engine_option(EngineOption option, int value, const char* valueStr) { carla_debug("carla_set_engine_option(%i:%s, %i, \"%s\")", option, CB::EngineOption2Str(option), value, valueStr); switch (option) { case CB::ENGINE_OPTION_DEBUG: break; case CB::ENGINE_OPTION_PROCESS_MODE: CARLA_SAFE_ASSERT_RETURN(value >= CB::ENGINE_PROCESS_MODE_SINGLE_CLIENT && value < CB::ENGINE_PROCESS_MODE_BRIDGE,); gStandalone.engineOptions.processMode = static_cast(value); break; case CB::ENGINE_OPTION_TRANSPORT_MODE: CARLA_SAFE_ASSERT_RETURN(value >= CB::ENGINE_TRANSPORT_MODE_DISABLED && value <= CB::ENGINE_TRANSPORT_MODE_BRIDGE,); // jack transport cannot be disabled in multi-client if (gStandalone.engineOptions.processMode == CB::ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS && value != CB::ENGINE_TRANSPORT_MODE_JACK) { gStandalone.engineOptions.transportMode = CB::ENGINE_TRANSPORT_MODE_JACK; if (gStandalone.engineCallback != nullptr) gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_TRANSPORT_MODE_CHANGED, 0, CB::ENGINE_TRANSPORT_MODE_JACK, 0, 0, 0.0f, gStandalone.engineOptions.transportExtra); } else { gStandalone.engineOptions.transportMode = static_cast(value); } delete[] gStandalone.engineOptions.transportExtra; if (value != CB::ENGINE_TRANSPORT_MODE_DISABLED && valueStr != nullptr) gStandalone.engineOptions.transportExtra = carla_strdup_safe(valueStr); else gStandalone.engineOptions.transportExtra = nullptr; break; case CB::ENGINE_OPTION_FORCE_STEREO: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); gStandalone.engineOptions.forceStereo = (value != 0); break; case CB::ENGINE_OPTION_PREFER_PLUGIN_BRIDGES: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); gStandalone.engineOptions.preferPluginBridges = (value != 0); break; case CB::ENGINE_OPTION_PREFER_UI_BRIDGES: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); gStandalone.engineOptions.preferUiBridges = (value != 0); break; case CB::ENGINE_OPTION_UIS_ALWAYS_ON_TOP: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); gStandalone.engineOptions.uisAlwaysOnTop = (value != 0); break; case CB::ENGINE_OPTION_MAX_PARAMETERS: CARLA_SAFE_ASSERT_RETURN(value >= 0,); gStandalone.engineOptions.maxParameters = static_cast(value); break; case CB::ENGINE_OPTION_RESET_XRUNS: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); gStandalone.engineOptions.resetXruns = (value != 0); break; case CB::ENGINE_OPTION_UI_BRIDGES_TIMEOUT: CARLA_SAFE_ASSERT_RETURN(value >= 0,); gStandalone.engineOptions.uiBridgesTimeout = static_cast(value); break; case CB::ENGINE_OPTION_AUDIO_BUFFER_SIZE: CARLA_SAFE_ASSERT_RETURN(value >= 8,); gStandalone.engineOptions.audioBufferSize = static_cast(value); break; case CB::ENGINE_OPTION_AUDIO_SAMPLE_RATE: CARLA_SAFE_ASSERT_RETURN(value >= 22050,); gStandalone.engineOptions.audioSampleRate = static_cast(value); break; case CB::ENGINE_OPTION_AUDIO_TRIPLE_BUFFER: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); gStandalone.engineOptions.audioTripleBuffer = (value != 0); break; case CB::ENGINE_OPTION_AUDIO_DRIVER: CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,); if (gStandalone.engineOptions.audioDriver != nullptr) delete[] gStandalone.engineOptions.audioDriver; gStandalone.engineOptions.audioDriver = carla_strdup_safe(valueStr); break; case CB::ENGINE_OPTION_AUDIO_DEVICE: CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,); if (gStandalone.engineOptions.audioDevice != nullptr) delete[] gStandalone.engineOptions.audioDevice; gStandalone.engineOptions.audioDevice = carla_strdup_safe(valueStr); break; case CB::ENGINE_OPTION_OSC_ENABLED: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); gStandalone.engineOptions.oscEnabled = (value != 0); break; case CB::ENGINE_OPTION_OSC_PORT_TCP: CARLA_SAFE_ASSERT_RETURN(value <= 0 || value >= 1024,); gStandalone.engineOptions.oscPortTCP = value; break; case CB::ENGINE_OPTION_OSC_PORT_UDP: CARLA_SAFE_ASSERT_RETURN(value <= 0 || value >= 1024,); gStandalone.engineOptions.oscPortUDP = value; break; case CB::ENGINE_OPTION_FILE_PATH: CARLA_SAFE_ASSERT_RETURN(value > CB::FILE_NONE,); CARLA_SAFE_ASSERT_RETURN(value <= CB::FILE_MIDI,); CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,); switch (value) { case CB::FILE_AUDIO: if (gStandalone.engineOptions.pathAudio != nullptr) delete[] gStandalone.engineOptions.pathAudio; gStandalone.engineOptions.pathAudio = carla_strdup_safe(valueStr); break; case CB::FILE_MIDI: if (gStandalone.engineOptions.pathMIDI != nullptr) delete[] gStandalone.engineOptions.pathMIDI; gStandalone.engineOptions.pathMIDI = carla_strdup_safe(valueStr); break; } break; case CB::ENGINE_OPTION_PLUGIN_PATH: CARLA_SAFE_ASSERT_RETURN(value > CB::PLUGIN_NONE,); CARLA_SAFE_ASSERT_RETURN(value <= CB::PLUGIN_SFZ,); CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,); switch (value) { case CB::PLUGIN_LADSPA: if (gStandalone.engineOptions.pathLADSPA != nullptr) delete[] gStandalone.engineOptions.pathLADSPA; gStandalone.engineOptions.pathLADSPA = carla_strdup_safe(valueStr); break; case CB::PLUGIN_DSSI: if (gStandalone.engineOptions.pathDSSI != nullptr) delete[] gStandalone.engineOptions.pathDSSI; gStandalone.engineOptions.pathDSSI = carla_strdup_safe(valueStr); break; case CB::PLUGIN_LV2: if (gStandalone.engineOptions.pathLV2 != nullptr) delete[] gStandalone.engineOptions.pathLV2; gStandalone.engineOptions.pathLV2 = carla_strdup_safe(valueStr); break; case CB::PLUGIN_VST2: if (gStandalone.engineOptions.pathVST2 != nullptr) delete[] gStandalone.engineOptions.pathVST2; gStandalone.engineOptions.pathVST2 = carla_strdup_safe(valueStr); break; case CB::PLUGIN_VST3: if (gStandalone.engineOptions.pathVST3 != nullptr) delete[] gStandalone.engineOptions.pathVST3; gStandalone.engineOptions.pathVST3 = carla_strdup_safe(valueStr); break; case CB::PLUGIN_SF2: if (gStandalone.engineOptions.pathSF2 != nullptr) delete[] gStandalone.engineOptions.pathSF2; gStandalone.engineOptions.pathSF2 = carla_strdup_safe(valueStr); break; case CB::PLUGIN_SFZ: if (gStandalone.engineOptions.pathSFZ != nullptr) delete[] gStandalone.engineOptions.pathSFZ; gStandalone.engineOptions.pathSFZ = carla_strdup_safe(valueStr); break; } break; case CB::ENGINE_OPTION_PATH_BINARIES: CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); if (gStandalone.engineOptions.binaryDir != nullptr) delete[] gStandalone.engineOptions.binaryDir; gStandalone.engineOptions.binaryDir = carla_strdup_safe(valueStr); break; case CB::ENGINE_OPTION_PATH_RESOURCES: CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); if (gStandalone.engineOptions.resourceDir != nullptr) delete[] gStandalone.engineOptions.resourceDir; gStandalone.engineOptions.resourceDir = carla_strdup_safe(valueStr); break; case CB::ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); gStandalone.engineOptions.preventBadBehaviour = (value != 0); break; case CB::ENGINE_OPTION_FRONTEND_BACKGROUND_COLOR: gStandalone.engineOptions.bgColor = static_cast(value); break; case CB::ENGINE_OPTION_FRONTEND_FOREGROUND_COLOR: gStandalone.engineOptions.fgColor = static_cast(value); break; case CB::ENGINE_OPTION_FRONTEND_UI_SCALE: CARLA_SAFE_ASSERT_RETURN(value > 0,); gStandalone.engineOptions.uiScale = static_cast(value) / 1000; break; case CB::ENGINE_OPTION_FRONTEND_WIN_ID: { CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); const long long winId(std::strtoll(valueStr, nullptr, 16)); CARLA_SAFE_ASSERT_RETURN(winId >= 0,); gStandalone.engineOptions.frontendWinId = static_cast(winId); } break; #ifndef CARLA_OS_WIN case CB::ENGINE_OPTION_WINE_EXECUTABLE: CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); if (gStandalone.engineOptions.wine.executable != nullptr) delete[] gStandalone.engineOptions.wine.executable; gStandalone.engineOptions.wine.executable = carla_strdup_safe(valueStr); break; case CB::ENGINE_OPTION_WINE_AUTO_PREFIX: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); gStandalone.engineOptions.wine.autoPrefix = (value != 0); break; case CB::ENGINE_OPTION_WINE_FALLBACK_PREFIX: CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); if (gStandalone.engineOptions.wine.fallbackPrefix != nullptr) delete[] gStandalone.engineOptions.wine.fallbackPrefix; gStandalone.engineOptions.wine.fallbackPrefix = carla_strdup_safe(valueStr); break; case CB::ENGINE_OPTION_WINE_RT_PRIO_ENABLED: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); gStandalone.engineOptions.wine.rtPrio = (value != 0); break; case CB::ENGINE_OPTION_WINE_BASE_RT_PRIO: CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 89,); gStandalone.engineOptions.wine.baseRtPrio = value; break; case CB::ENGINE_OPTION_WINE_SERVER_RT_PRIO: CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 99,); gStandalone.engineOptions.wine.serverRtPrio = value; break; #endif case CB::ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT: gStandalone.logThreadEnabled = (value != 0); break; } if (gStandalone.engine != nullptr) gStandalone.engine->setOption(option, value, valueStr); } #endif void carla_set_file_callback(FileCallbackFunc func, void* ptr) { carla_debug("carla_set_file_callback(%p, %p)", func, ptr); gStandalone.fileCallback = func; gStandalone.fileCallbackPtr = ptr; if (gStandalone.engine != nullptr) gStandalone.engine->setFileCallback(func, ptr); } // -------------------------------------------------------------------------------------------------------------------- bool carla_load_file(const char* filename) { CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_load_file(\"%s\")", filename); return gStandalone.engine->loadFile(filename); } bool carla_load_project(const char* filename) { CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_load_project(\"%s\")", filename); return gStandalone.engine->loadProject(filename, true); } bool carla_save_project(const char* filename) { CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_save_project(\"%s\")", filename); return gStandalone.engine->saveProject(filename, true); } #ifndef BUILD_BRIDGE void carla_clear_project_filename() { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); carla_debug("carla_clear_project_filename()"); gStandalone.engine->clearCurrentProjectFilename(); } // -------------------------------------------------------------------------------------------------------------------- bool carla_patchbay_connect(bool external, uint groupIdA, uint portIdA, uint groupIdB, uint portIdB) { CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_patchbay_connect(%s, %u, %u, %u, %u)", bool2str(external), groupIdA, portIdA, groupIdB, portIdB); return gStandalone.engine->patchbayConnect(external, groupIdA, portIdA, groupIdB, portIdB); } bool carla_patchbay_disconnect(bool external, uint connectionId) { CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_patchbay_disconnect(%s, %i)", bool2str(external), connectionId); return gStandalone.engine->patchbayDisconnect(external, connectionId); } bool carla_patchbay_refresh(bool external) { CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_patchbay_refresh(%s)", bool2str(external)); return gStandalone.engine->patchbayRefresh(true, false, external); } // -------------------------------------------------------------------------------------------------------------------- void carla_transport_play() { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr && gStandalone.engine->isRunning(),); carla_debug("carla_transport_play()"); gStandalone.engine->transportPlay(); } void carla_transport_pause() { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr && gStandalone.engine->isRunning(),); carla_debug("carla_transport_pause()"); gStandalone.engine->transportPause(); } void carla_transport_bpm(double bpm) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr && gStandalone.engine->isRunning(),); carla_debug("carla_transport_bpm(%f)", bpm); gStandalone.engine->transportBPM(bpm); } void carla_transport_relocate(uint64_t frame) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr && gStandalone.engine->isRunning(),); carla_debug("carla_transport_relocate(%i)", frame); gStandalone.engine->transportRelocate(frame); } uint64_t carla_get_current_transport_frame() { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr && gStandalone.engine->isRunning(), 0); return gStandalone.engine->getTimeInfo().frame; } const CarlaTransportInfo* carla_get_transport_info() { static CarlaTransportInfo retTransInfo; retTransInfo.clear(); CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr && gStandalone.engine->isRunning(), &retTransInfo); const CB::EngineTimeInfo& timeInfo(gStandalone.engine->getTimeInfo()); retTransInfo.playing = timeInfo.playing; retTransInfo.frame = timeInfo.frame; if (timeInfo.bbt.valid) { retTransInfo.bar = timeInfo.bbt.bar; retTransInfo.beat = timeInfo.bbt.beat; retTransInfo.tick = static_cast(timeInfo.bbt.tick + 0.5); retTransInfo.bpm = timeInfo.bbt.beatsPerMinute; } return &retTransInfo; } #endif // -------------------------------------------------------------------------------------------------------------------- uint32_t carla_get_current_plugin_count() { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0); carla_debug("carla_get_current_plugin_count()"); return gStandalone.engine->getCurrentPluginCount(); } uint32_t carla_get_max_plugin_number() { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0); carla_debug("carla_get_max_plugin_number()"); return gStandalone.engine->getMaxPluginNumber(); } // -------------------------------------------------------------------------------------------------------------------- bool carla_add_plugin(BinaryType btype, PluginType ptype, const char* filename, const char* name, const char* label, int64_t uniqueId, const void* extraPtr, uint options) { CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_add_plugin(%i:%s, %i:%s, \"%s\", \"%s\", \"%s\", " P_INT64 ", %p, %u)", btype, CB::BinaryType2Str(btype), ptype, CB::PluginType2Str(ptype), filename, name, label, uniqueId, extraPtr, options); return gStandalone.engine->addPlugin(btype, ptype, filename, name, label, uniqueId, extraPtr, options); } bool carla_remove_plugin(uint pluginId) { CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_remove_plugin(%i)", pluginId); return gStandalone.engine->removePlugin(pluginId); } bool carla_remove_all_plugins() { CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_remove_all_plugins()"); return gStandalone.engine->removeAllPlugins(); } #ifndef BUILD_BRIDGE bool carla_rename_plugin(uint pluginId, const char* newName) { CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0', false); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_rename_plugin(%i, \"%s\")", pluginId, newName); return gStandalone.engine->renamePlugin(pluginId, newName); } bool carla_clone_plugin(uint pluginId) { CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_clone_plugin(%i)", pluginId); return gStandalone.engine->clonePlugin(pluginId); } bool carla_replace_plugin(uint pluginId) { CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_replace_plugin(%i)", pluginId); return gStandalone.engine->replacePlugin(pluginId); } bool carla_switch_plugins(uint pluginIdA, uint pluginIdB) { CARLA_SAFE_ASSERT_RETURN(pluginIdA != pluginIdB, false); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); carla_debug("carla_switch_plugins(%i, %i)", pluginIdA, pluginIdB); return gStandalone.engine->switchPlugins(pluginIdA, pluginIdB); } #endif // -------------------------------------------------------------------------------------------------------------------- bool carla_load_plugin_state(uint pluginId, const char* filename) { CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr && gStandalone.engine->isRunning(), "Engine is not running", false); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(plugin != nullptr, "could not find requested plugin", false); carla_debug("carla_load_plugin_state(%i, \"%s\")", pluginId, filename); return plugin->loadStateFromFile(filename); } bool carla_save_plugin_state(uint pluginId, const char* filename) { CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(plugin != nullptr, "could not find requested plugin", false); carla_debug("carla_save_plugin_state(%i, \"%s\")", pluginId, filename); return plugin->saveStateToFile(filename); } bool carla_export_plugin_lv2(uint pluginId, const char* lv2path) { CARLA_SAFE_ASSERT_RETURN(lv2path != nullptr && lv2path[0] != '\0', false); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(plugin != nullptr, "could not find requested plugin", false); carla_debug("carla_export_plugin_lv2(%i, \"%s\")", pluginId, lv2path); return plugin->exportAsLV2(lv2path); } // -------------------------------------------------------------------------------------------------------------------- const CarlaPluginInfo* carla_get_plugin_info(uint pluginId) { static CarlaPluginInfo retInfo; // reset retInfo.type = CB::PLUGIN_NONE; retInfo.category = CB::PLUGIN_CATEGORY_NONE; retInfo.hints = 0x0; retInfo.optionsAvailable = 0x0; retInfo.optionsEnabled = 0x0; retInfo.filename = gNullCharPtr; retInfo.name = gNullCharPtr; retInfo.iconName = gNullCharPtr; retInfo.uniqueId = 0; // cleanup if (retInfo.label != gNullCharPtr) { delete[] retInfo.label; retInfo.label = gNullCharPtr; } if (retInfo.maker != gNullCharPtr) { delete[] retInfo.maker; retInfo.maker = gNullCharPtr; } if (retInfo.copyright != gNullCharPtr) { delete[] retInfo.copyright; retInfo.copyright = gNullCharPtr; } CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, &retInfo); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, &retInfo); carla_debug("carla_get_plugin_info(%i)", pluginId); char strBuf[STR_MAX+1]; carla_zeroChars(strBuf, STR_MAX+1); retInfo.type = plugin->getType(); retInfo.category = plugin->getCategory(); retInfo.hints = plugin->getHints(); retInfo.filename = plugin->getFilename(); retInfo.name = plugin->getName(); retInfo.iconName = plugin->getIconName(); retInfo.uniqueId = plugin->getUniqueId(); retInfo.optionsAvailable = plugin->getOptionsAvailable(); retInfo.optionsEnabled = plugin->getOptionsEnabled(); if (plugin->getLabel(strBuf)) retInfo.label = carla_strdup_safe(strBuf); if (plugin->getMaker(strBuf)) retInfo.maker = carla_strdup_safe(strBuf); if (plugin->getCopyright(strBuf)) retInfo.copyright = carla_strdup_safe(strBuf); checkStringPtr(retInfo.filename); checkStringPtr(retInfo.name); checkStringPtr(retInfo.iconName); checkStringPtr(retInfo.label); checkStringPtr(retInfo.maker); checkStringPtr(retInfo.copyright); return &retInfo; } const CarlaPortCountInfo* carla_get_audio_port_count_info(uint pluginId) { static CarlaPortCountInfo retInfo; carla_zeroStruct(retInfo); CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, &retInfo); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, &retInfo); carla_debug("carla_get_audio_port_count_info(%i)", pluginId); retInfo.ins = plugin->getAudioInCount(); retInfo.outs = plugin->getAudioOutCount(); return &retInfo; } const CarlaPortCountInfo* carla_get_midi_port_count_info(uint pluginId) { static CarlaPortCountInfo retInfo; carla_zeroStruct(retInfo); CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, &retInfo); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, &retInfo); carla_debug("carla_get_midi_port_count_info(%i)", pluginId); retInfo.ins = plugin->getMidiInCount(); retInfo.outs = plugin->getMidiOutCount(); return &retInfo; } const CarlaPortCountInfo* carla_get_parameter_count_info(uint pluginId) { static CarlaPortCountInfo retInfo; carla_zeroStruct(retInfo); CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, &retInfo); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, &retInfo); carla_debug("carla_get_parameter_count_info(%i)", pluginId); plugin->getParameterCountInfo(retInfo.ins, retInfo.outs); return &retInfo; } const CarlaParameterInfo* carla_get_parameter_info(uint pluginId, uint32_t parameterId) { static CarlaParameterInfo retInfo; // reset retInfo.scalePointCount = 0; // cleanup if (retInfo.name != gNullCharPtr) { delete[] retInfo.name; retInfo.name = gNullCharPtr; } if (retInfo.symbol != gNullCharPtr) { delete[] retInfo.symbol; retInfo.symbol = gNullCharPtr; } if (retInfo.unit != gNullCharPtr) { delete[] retInfo.unit; retInfo.unit = gNullCharPtr; } if (retInfo.comment != gNullCharPtr) { delete[] retInfo.comment; retInfo.comment = gNullCharPtr; } if (retInfo.groupName != gNullCharPtr) { delete[] retInfo.groupName; retInfo.groupName = gNullCharPtr; } CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, &retInfo); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, &retInfo); carla_debug("carla_get_parameter_info(%i, %i)", pluginId, parameterId); char strBuf[STR_MAX+1]; carla_zeroChars(strBuf, STR_MAX+1); retInfo.scalePointCount = plugin->getParameterScalePointCount(parameterId); if (plugin->getParameterName(parameterId, strBuf)) { retInfo.name = carla_strdup_safe(strBuf); carla_zeroChars(strBuf, STR_MAX+1); } if (plugin->getParameterSymbol(parameterId, strBuf)) { retInfo.symbol = carla_strdup_safe(strBuf); carla_zeroChars(strBuf, STR_MAX+1); } if (plugin->getParameterUnit(parameterId, strBuf)) { retInfo.unit = carla_strdup_safe(strBuf); carla_zeroChars(strBuf, STR_MAX+1); } if (plugin->getParameterComment(parameterId, strBuf)) { retInfo.comment = carla_strdup_safe(strBuf); carla_zeroChars(strBuf, STR_MAX+1); } if (plugin->getParameterGroupName(parameterId, strBuf)) { retInfo.groupName = carla_strdup_safe(strBuf); carla_zeroChars(strBuf, STR_MAX+1); } checkStringPtr(retInfo.name); checkStringPtr(retInfo.symbol); checkStringPtr(retInfo.unit); checkStringPtr(retInfo.comment); checkStringPtr(retInfo.groupName); return &retInfo; } const CarlaScalePointInfo* carla_get_parameter_scalepoint_info(uint pluginId, uint32_t parameterId, uint32_t scalePointId) { CARLA_ASSERT(gStandalone.engine != nullptr); static CarlaScalePointInfo retInfo; // reset retInfo.value = 0.0f; // cleanup if (retInfo.label != gNullCharPtr) { delete[] retInfo.label; retInfo.label = gNullCharPtr; } CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, &retInfo); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, &retInfo); carla_debug("carla_get_parameter_scalepoint_info(%i, %i, %i)", pluginId, parameterId, scalePointId); char strBuf[STR_MAX+1]; retInfo.value = plugin->getParameterScalePointValue(parameterId, scalePointId); carla_zeroChars(strBuf, STR_MAX+1); if (plugin->getParameterScalePointLabel(parameterId, scalePointId, strBuf)) retInfo.label = carla_strdup_safe(strBuf); checkStringPtr(retInfo.label); return &retInfo; } // -------------------------------------------------------------------------------------------------------------------- const ParameterData* carla_get_parameter_data(uint pluginId, uint32_t parameterId) { static ParameterData retParamData; // reset retParamData.type = CB::PARAMETER_UNKNOWN; retParamData.hints = 0x0; retParamData.index = CB::PARAMETER_NULL; retParamData.rindex = -1; retParamData.midiChannel = 0; retParamData.mappedControlIndex = CB::CONTROL_INDEX_NONE; retParamData.mappedMinimum = 0.0f; retParamData.mappedMaximum = 0.0f; CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, &retParamData); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, &retParamData); carla_debug("carla_get_parameter_data(%i, %i)", pluginId, parameterId); CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(), &retParamData); const ParameterData& pluginParamData(plugin->getParameterData(parameterId)); retParamData.type = pluginParamData.type; retParamData.hints = pluginParamData.hints; retParamData.index = pluginParamData.index; retParamData.rindex = pluginParamData.rindex; retParamData.midiChannel = pluginParamData.midiChannel; retParamData.mappedControlIndex = pluginParamData.mappedControlIndex; retParamData.mappedMinimum = pluginParamData.mappedMinimum; retParamData.mappedMaximum = pluginParamData.mappedMaximum; return &plugin->getParameterData(parameterId); } const ParameterRanges* carla_get_parameter_ranges(uint pluginId, uint32_t parameterId) { static ParameterRanges retParamRanges; // reset retParamRanges.def = 0.0f; retParamRanges.min = 0.0f; retParamRanges.max = 1.0f; retParamRanges.step = 0.01f; retParamRanges.stepSmall = 0.0001f; retParamRanges.stepLarge = 0.1f; CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, &retParamRanges); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, &retParamRanges); carla_debug("carla_get_parameter_ranges(%i, %i)", pluginId, parameterId); CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(), &retParamRanges); const ParameterRanges& pluginParamRanges(plugin->getParameterRanges(parameterId)); retParamRanges.def = pluginParamRanges.def; retParamRanges.min = pluginParamRanges.min; retParamRanges.max = pluginParamRanges.max; retParamRanges.step = pluginParamRanges.step; retParamRanges.stepSmall = pluginParamRanges.stepSmall; retParamRanges.stepLarge = pluginParamRanges.stepLarge; return &pluginParamRanges; } const MidiProgramData* carla_get_midi_program_data(uint pluginId, uint32_t midiProgramId) { static MidiProgramData retMidiProgData = { 0, 0, gNullCharPtr }; // reset retMidiProgData.bank = 0; retMidiProgData.program = 0; if (retMidiProgData.name != gNullCharPtr) { delete[] retMidiProgData.name; retMidiProgData.name = gNullCharPtr; } CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, &retMidiProgData); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, &retMidiProgData); carla_debug("carla_get_midi_program_data(%i, %i)", pluginId, midiProgramId); CARLA_SAFE_ASSERT_RETURN(midiProgramId < plugin->getMidiProgramCount(), &retMidiProgData); const MidiProgramData& pluginMidiProgData(plugin->getMidiProgramData(midiProgramId)); retMidiProgData.bank = pluginMidiProgData.bank; retMidiProgData.program = pluginMidiProgData.program; if (pluginMidiProgData.name != nullptr) { retMidiProgData.name = carla_strdup_safe(pluginMidiProgData.name); checkStringPtr(retMidiProgData.name); } else { retMidiProgData.name = gNullCharPtr; } return &retMidiProgData; } const CustomData* carla_get_custom_data(uint pluginId, uint32_t customDataId) { static CustomData retCustomData = { gNullCharPtr, gNullCharPtr, gNullCharPtr }; // reset if (retCustomData.type != gNullCharPtr) { delete[] retCustomData.type; retCustomData.type = gNullCharPtr; } if (retCustomData.key != gNullCharPtr) { delete[] retCustomData.key; retCustomData.key = gNullCharPtr; } if (retCustomData.value != gNullCharPtr) { delete[] retCustomData.value; retCustomData.value = gNullCharPtr; } CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, &retCustomData); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, &retCustomData); carla_debug("carla_get_custom_data(%i, %i)", pluginId, customDataId); CARLA_SAFE_ASSERT_RETURN(customDataId < plugin->getCustomDataCount(), &retCustomData) const CustomData& pluginCustomData(plugin->getCustomData(customDataId)); retCustomData.type = carla_strdup_safe(pluginCustomData.type); retCustomData.key = carla_strdup_safe(pluginCustomData.key); retCustomData.value = carla_strdup_safe(pluginCustomData.value); checkStringPtr(retCustomData.type); checkStringPtr(retCustomData.key); checkStringPtr(retCustomData.value); return &retCustomData; } const char* carla_get_custom_data_value(uint pluginId, const char* type, const char* key) { CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0', gNullCharPtr); CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', gNullCharPtr); CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, gNullCharPtr); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, gNullCharPtr); carla_debug("carla_get_custom_data_value(%i, %s, %s)", pluginId, type, key); const uint32_t count = plugin->getCustomDataCount(); if (count == 0) return gNullCharPtr; static CarlaString customDataValue; for (uint32_t i=0; igetCustomData(i)); if (std::strcmp(pluginCustomData.type, type) != 0) continue; if (std::strcmp(pluginCustomData.key, key) != 0) continue; customDataValue = pluginCustomData.value; return customDataValue.buffer(); } return gNullCharPtr; } const char* carla_get_chunk_data(uint pluginId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, gNullCharPtr); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, gNullCharPtr); carla_debug("carla_get_chunk_data(%i)", pluginId); CARLA_SAFE_ASSERT_RETURN(plugin->getOptionsEnabled() & CB::PLUGIN_OPTION_USE_CHUNKS, gNullCharPtr); void* data = nullptr; const std::size_t dataSize(plugin->getChunkData(&data)); CARLA_SAFE_ASSERT_RETURN(data != nullptr && dataSize > 0, gNullCharPtr); static CarlaString chunkData; chunkData = CarlaString::asBase64(data, static_cast(dataSize)); return chunkData.buffer(); } // -------------------------------------------------------------------------------------------------------------------- uint32_t carla_get_parameter_count(uint pluginId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, 0); carla_debug("carla_get_parameter_count(%i)", pluginId); return plugin->getParameterCount(); } uint32_t carla_get_program_count(uint pluginId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, 0); carla_debug("carla_get_program_count(%i)", pluginId); return plugin->getProgramCount(); } uint32_t carla_get_midi_program_count(uint pluginId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, 0); carla_debug("carla_get_midi_program_count(%i)", pluginId); return plugin->getMidiProgramCount(); } uint32_t carla_get_custom_data_count(uint pluginId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, 0); carla_debug("carla_get_custom_data_count(%i)", pluginId); return plugin->getCustomDataCount(); } // -------------------------------------------------------------------------------------------------------------------- const char* carla_get_parameter_text(uint pluginId, uint32_t parameterId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, gNullCharPtr); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, gNullCharPtr); carla_debug("carla_get_parameter_text(%i, %i)", pluginId, parameterId); CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(), gNullCharPtr); static char textBuf[STR_MAX+1]; carla_zeroChars(textBuf, STR_MAX+1); if (! plugin->getParameterText(parameterId, textBuf)) textBuf[0] = '\0'; return textBuf; } const char* carla_get_program_name(uint pluginId, uint32_t programId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, nullptr); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, gNullCharPtr); carla_debug("carla_get_program_name(%i, %i)", pluginId, programId); CARLA_SAFE_ASSERT_RETURN(programId < plugin->getProgramCount(), gNullCharPtr); static char programName[STR_MAX+1]; carla_zeroChars(programName, STR_MAX+1); if (! plugin->getProgramName(programId, programName)) programName[0] = '\0'; return programName; } const char* carla_get_midi_program_name(uint pluginId, uint32_t midiProgramId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, gNullCharPtr); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, gNullCharPtr); carla_debug("carla_get_midi_program_name(%i, %i)", pluginId, midiProgramId); CARLA_SAFE_ASSERT_RETURN(midiProgramId < plugin->getMidiProgramCount(), gNullCharPtr); static char midiProgramName[STR_MAX+1]; carla_zeroChars(midiProgramName, STR_MAX+1); if (! plugin->getMidiProgramName(midiProgramId, midiProgramName)) midiProgramName[0] = '\0'; return midiProgramName; } const char* carla_get_real_plugin_name(uint pluginId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, gNullCharPtr); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, gNullCharPtr); carla_debug("carla_get_real_plugin_name(%i)", pluginId); static char realPluginName[STR_MAX+1]; carla_zeroChars(realPluginName, STR_MAX+1); if (! plugin->getRealName(realPluginName)) realPluginName[0] = '\0'; return realPluginName; } // -------------------------------------------------------------------------------------------------------------------- int32_t carla_get_current_program_index(uint pluginId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, -1); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, -1); carla_debug("carla_get_current_program_index(%i)", pluginId); return plugin->getCurrentProgram(); } int32_t carla_get_current_midi_program_index(uint pluginId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, -1); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, -1); carla_debug("carla_get_current_midi_program_index(%i)", pluginId); return plugin->getCurrentMidiProgram(); } // -------------------------------------------------------------------------------------------------------------------- float carla_get_default_parameter_value(uint pluginId, uint32_t parameterId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0.0f); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, 0.0f); carla_debug("carla_get_default_parameter_value(%i, %i)", pluginId, parameterId); CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(), 0.0f); return plugin->getParameterRanges(parameterId).def; } float carla_get_current_parameter_value(uint pluginId, uint32_t parameterId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0.0f); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, 0.0f); CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(), 0.0f); return plugin->getParameterValue(parameterId); } float carla_get_internal_parameter_value(uint pluginId, int32_t parameterId) { #ifdef BUILD_BRIDGE CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0.0f); #else CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, (parameterId == CB::PARAMETER_CTRL_CHANNEL) ? -1.0f : 0.0f); #endif CARLA_SAFE_ASSERT_RETURN(parameterId != CB::PARAMETER_NULL && parameterId > CB::PARAMETER_MAX, 0.0f); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, 0.0f); carla_debug("carla_get_internal_parameter_value(%i, %i)", pluginId, parameterId); return plugin->getInternalParameterValue(parameterId); } // -------------------------------------------------------------------------------------------------------------------- const float* carla_get_peak_values(uint pluginId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, nullptr); return gStandalone.engine->getPeaks(pluginId); } float carla_get_input_peak_value(uint pluginId, bool isLeft) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0.0f); return gStandalone.engine->getInputPeak(pluginId, isLeft); } float carla_get_output_peak_value(uint pluginId, bool isLeft) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0.0f); return gStandalone.engine->getOutputPeak(pluginId, isLeft); } // -------------------------------------------------------------------------------------------------------------------- CARLA_BACKEND_START_NAMESPACE #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // defined in CarlaPluginInternal.cpp const void* carla_render_inline_display_internal(CarlaPlugin* plugin, uint32_t width, uint32_t height); #endif // defined in CarlaPluginLV2.cpp const void* carla_render_inline_display_lv2(CarlaPlugin* plugin, uint32_t width, uint32_t height); CARLA_BACKEND_END_NAMESPACE const CarlaInlineDisplayImageSurface* carla_render_inline_display(uint pluginId, uint32_t width, uint32_t height) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, nullptr); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, nullptr); carla_debug("carla_render_inline_display(%i, %i, %i)", pluginId, width, height); switch (plugin->getType()) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH case CB::PLUGIN_INTERNAL: return (const CarlaInlineDisplayImageSurface*)CB::carla_render_inline_display_internal(plugin, width, height); #endif case CB::PLUGIN_LV2: return (const CarlaInlineDisplayImageSurface*)CB::carla_render_inline_display_lv2(plugin, width, height); default: return nullptr; } } // -------------------------------------------------------------------------------------------------------------------- void carla_set_active(uint pluginId, bool onOff) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_active(%i, %s)", pluginId, bool2str(onOff)); return plugin->setActive(onOff, true, false); } #ifndef BUILD_BRIDGE void carla_set_drywet(uint pluginId, float value) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_drywet(%i, %f)", pluginId, static_cast(value)); return plugin->setDryWet(value, true, false); } void carla_set_volume(uint pluginId, float value) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_volume(%i, %f)", pluginId, static_cast(value)); return plugin->setVolume(value, true, false); } void carla_set_balance_left(uint pluginId, float value) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_balance_left(%i, %f)", pluginId, static_cast(value)); return plugin->setBalanceLeft(value, true, false); } void carla_set_balance_right(uint pluginId, float value) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_balance_right(%i, %f)", pluginId, static_cast(value)); return plugin->setBalanceRight(value, true, false); } void carla_set_panning(uint pluginId, float value) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_panning(%i, %f)", pluginId, static_cast(value)); return plugin->setPanning(value, true, false); } void carla_set_ctrl_channel(uint pluginId, int8_t channel) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(channel >= -1 && channel < MAX_MIDI_CHANNELS,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_ctrl_channel(%i, %i)", pluginId, channel); return plugin->setCtrlChannel(channel, true, false); } #endif void carla_set_option(uint pluginId, uint option, bool yesNo) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_option(%i, %i, %s)", pluginId, option, bool2str(yesNo)); return plugin->setOption(option, yesNo, false); } // -------------------------------------------------------------------------------------------------------------------- void carla_set_parameter_value(uint pluginId, uint32_t parameterId, float value) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_parameter_value(%i, %i, %f)", pluginId, parameterId, static_cast(value)); CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(),); return plugin->setParameterValue(parameterId, value, true, true, false); } #ifndef BUILD_BRIDGE void carla_set_parameter_midi_channel(uint pluginId, uint32_t parameterId, uint8_t channel) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_parameter_midi_channel(%i, %i, %i)", pluginId, parameterId, channel); CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(),); return plugin->setParameterMidiChannel(parameterId, channel, true, false); } void carla_set_parameter_mapped_control_index(uint pluginId, uint32_t parameterId, int16_t index) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(index >= CB::CONTROL_INDEX_NONE && index <= CB::CONTROL_INDEX_MAX_ALLOWED,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_parameter_mapped_control_index(%i, %i, %i)", pluginId, parameterId, index); CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(),); return plugin->setParameterMappedControlIndex(parameterId, index, true, false); } void carla_set_parameter_mapped_range(uint pluginId, uint32_t parameterId, float minimum, float maximum) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_parameter_mapped_range(%i, %i, %f, %f)", pluginId, parameterId, static_cast(minimum), static_cast(maximum)); CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(),); return plugin->setParameterMappedRange(parameterId, minimum, maximum, true, false); } void carla_set_parameter_touch(uint pluginId, uint32_t parameterId, bool touch) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); carla_debug("carla_set_parameter_touch(%i, %i, %s)", pluginId, parameterId, bool2str(touch)); return gStandalone.engine->touchPluginParameter(pluginId, parameterId, touch); } #endif // -------------------------------------------------------------------------------------------------------------------- void carla_set_program(uint pluginId, uint32_t programId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_program(%i, %i)", pluginId, programId); CARLA_SAFE_ASSERT_RETURN(programId < plugin->getProgramCount(),); return plugin->setProgram(static_cast(programId), true, true, false); } void carla_set_midi_program(uint pluginId, uint32_t midiProgramId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_midi_program(%i, %i)", pluginId, midiProgramId); CARLA_SAFE_ASSERT_RETURN(midiProgramId < plugin->getMidiProgramCount(),); return plugin->setMidiProgram(static_cast(midiProgramId), true, true, false); } // -------------------------------------------------------------------------------------------------------------------- void carla_set_custom_data(uint pluginId, const char* type, const char* key, const char* value) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_custom_data(%i, \"%s\", \"%s\", \"%s\")", pluginId, type, key, value); return plugin->setCustomData(type, key, value, true); } void carla_set_chunk_data(uint pluginId, const char* chunkData) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(chunkData != nullptr && chunkData[0] != '\0',); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_set_chunk_data(%i, \"%s\")", pluginId, chunkData); CARLA_SAFE_ASSERT_RETURN(plugin->getOptionsEnabled() & CB::PLUGIN_OPTION_USE_CHUNKS,); std::vector chunk(carla_getChunkFromBase64String(chunkData)); #ifdef CARLA_PROPER_CPP11_SUPPORT return plugin->setChunkData(chunk.data(), chunk.size()); #else return plugin->setChunkData(&chunk.front(), chunk.size()); #endif } // -------------------------------------------------------------------------------------------------------------------- void carla_prepare_for_save(uint pluginId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_prepare_for_save(%i)", pluginId); return plugin->prepareForSave(); } void carla_reset_parameters(uint pluginId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_reset_parameters(%i)", pluginId); return plugin->resetParameters(); } void carla_randomize_parameters(uint pluginId) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_randomize_parameters(%i)", pluginId); return plugin->randomizeParameters(); } #ifndef BUILD_BRIDGE void carla_send_midi_note(uint pluginId, uint8_t channel, uint8_t note, uint8_t velocity) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr && gStandalone.engine->isRunning(),); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_send_midi_note(%i, %i, %i, %i)", pluginId, channel, note, velocity); return plugin->sendMidiSingleNote(channel, note, velocity, true, true, false); } #endif void carla_show_custom_ui(uint pluginId, bool yesNo) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("carla_show_custom_ui(%i, %s)", pluginId, bool2str(yesNo)); return plugin->showCustomUI(yesNo); } // -------------------------------------------------------------------------------------------------------------------- uint32_t carla_get_buffer_size() { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0); carla_debug("carla_get_buffer_size()"); return gStandalone.engine->getBufferSize(); } double carla_get_sample_rate() { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, 0.0); carla_debug("carla_get_sample_rate()"); return gStandalone.engine->getSampleRate(); } // -------------------------------------------------------------------------------------------------------------------- const char* carla_get_last_error() { carla_debug("carla_get_last_error()"); if (gStandalone.engine != nullptr) return gStandalone.engine->getLastError(); return gStandalone.lastError; } const char* carla_get_host_osc_url_tcp() { carla_debug("carla_get_host_osc_url_tcp()"); #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (gStandalone.engine == nullptr) { carla_stderr2("carla_get_host_osc_url_tcp() failed, engine is not running"); gStandalone.lastError = "Engine is not running"; return gNullCharPtr; } const char* const path = gStandalone.engine->getOscServerPathTCP(); if (path != nullptr && path[0] != '\0') return path; static const char* const notAvailable = "(OSC TCP port not available)"; return notAvailable; #else return gNullCharPtr; #endif } const char* carla_get_host_osc_url_udp() { carla_debug("carla_get_host_osc_url_udp()"); #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (gStandalone.engine == nullptr) { carla_stderr2("carla_get_host_osc_url_udp() failed, engine is not running"); gStandalone.lastError = "Engine is not running"; return gNullCharPtr; } const char* const path = gStandalone.engine->getOscServerPathUDP(); if (path != nullptr && path[0] != '\0') return path; static const char* const notAvailable = "(OSC UDP port not available)"; return notAvailable; #else return gNullCharPtr; #endif } // -------------------------------------------------------------------------------------------------------------------- #define CARLA_PLUGIN_UI_CLASS_PREFIX Standalone #include "CarlaPluginUI.cpp" #undef CARLA_PLUGIN_UI_CLASS_PREFIX #include "CarlaDssiUtils.cpp" #include "CarlaMacUtils.cpp" #include "CarlaPatchbayUtils.cpp" #include "CarlaPipeUtils.cpp" #include "CarlaStateUtils.cpp" // -------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/CarlaStandaloneNSM.cpp000066400000000000000000000551701364475620200214230ustar00rootroot00000000000000/* * Carla Standalone * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaHost.h" #ifdef HAVE_LIBLO #define NSM_API_VERSION_MAJOR 1 #define NSM_API_VERSION_MINOR 2 #define NSM_CLIENT_FEATURES ":switch:" //#define NSM_CLIENT_FEATURES ":switch:optional-gui:" #include "CarlaOscUtils.hpp" #include "CarlaString.hpp" #include "water/files/File.h" namespace CB = CarlaBackend; // ------------------------------------------------------------------------------------------------------------------- struct CarlaBackendStandalone { CarlaEngine* engine; EngineCallbackFunc engineCallback; void* engineCallbackPtr; // ... }; extern CarlaBackendStandalone gStandalone; // ------------------------------------------------------------------------------------------------------------------- class CarlaNSM { public: CarlaNSM() noexcept : fReplyAddress(nullptr), fServer(nullptr), fServerThread(nullptr), fServerURL(nullptr), fClientNameId(), fProjectPath(), fHasBroadcast(false), fHasOptionalGui(false), fHasServerControl(false), fStarted(), fReadyActionOpen(true), fReadyActionSave(true) {} ~CarlaNSM() { CARLA_SAFE_ASSERT(fReadyActionOpen); CARLA_SAFE_ASSERT(fReadyActionSave); if (fServerThread != nullptr) { lo_server_thread_stop(fServerThread); lo_server_thread_free(fServerThread); fServerThread = nullptr; fServer = nullptr; } if (fServerURL != nullptr) { std::free(fServerURL); fServerURL = nullptr; } if (fReplyAddress != nullptr) { lo_address_free(fReplyAddress); fReplyAddress = nullptr; } } bool announce(const uint64_t pid, const char* const executableName) { CARLA_SAFE_ASSERT_RETURN(pid != 0, false); CARLA_SAFE_ASSERT_RETURN(executableName != nullptr && executableName[0] != '\0', false); const char* const NSM_URL(std::getenv("NSM_URL")); if (NSM_URL == nullptr) return false; const lo_address nsmAddress(lo_address_new_from_url(NSM_URL)); CARLA_SAFE_ASSERT_RETURN(nsmAddress != nullptr, false); const int proto = lo_address_get_protocol(nsmAddress); if (fServerThread == nullptr) { // create new OSC server fServerThread = lo_server_thread_new_with_proto(nullptr, proto, _osc_error_handler); CARLA_SAFE_ASSERT_RETURN(fServerThread != nullptr, false); // register message handlers lo_server_thread_add_method(fServerThread, "/error", "sis", _error_handler, this); lo_server_thread_add_method(fServerThread, "/reply", "ssss", _reply_handler, this); lo_server_thread_add_method(fServerThread, "/nsm/client/open", "sss", _open_handler, this); lo_server_thread_add_method(fServerThread, "/nsm/client/save", "", _save_handler, this); lo_server_thread_add_method(fServerThread, "/nsm/client/session_is_loaded", "", _loaded_handler, this); lo_server_thread_add_method(fServerThread, "/nsm/client/show_optional_gui", "", _show_gui_handler, this); lo_server_thread_add_method(fServerThread, "/nsm/client/hide_optional_gui", "", _hide_gui_handler, this); lo_server_thread_add_method(fServerThread, nullptr, nullptr, _broadcast_handler, this); fServer = lo_server_thread_get_server(fServerThread); fServerURL = lo_server_thread_get_url(fServerThread); } const char* appName = std::getenv("CARLA_NSM_NAME"); if (appName == nullptr) appName = "Carla"; lo_send_from(nsmAddress, fServer, LO_TT_IMMEDIATE, "/nsm/server/announce", "sssiii", appName, NSM_CLIENT_FEATURES, executableName, NSM_API_VERSION_MAJOR, NSM_API_VERSION_MINOR, pid); lo_address_free(nsmAddress); if (gStandalone.engineCallback != nullptr) { gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, CB::NSM_CALLBACK_INIT, 0, 0, 0.0f, nullptr); } return true; } void ready(const NsmCallbackOpcode action) { CARLA_SAFE_ASSERT_RETURN(fServerThread != nullptr,); switch (action) { case CB::NSM_CALLBACK_INIT: CARLA_SAFE_ASSERT_BREAK(! fStarted); fStarted = true; lo_server_thread_start(fServerThread); break; case CB::NSM_CALLBACK_ERROR: break; case CB::NSM_CALLBACK_ANNOUNCE: break; case CB::NSM_CALLBACK_OPEN: fReadyActionOpen = true; break; case CB::NSM_CALLBACK_SAVE: fReadyActionSave = true; break; case CB::NSM_CALLBACK_SESSION_IS_LOADED: break; case CB::NSM_CALLBACK_SHOW_OPTIONAL_GUI: CARLA_SAFE_ASSERT_BREAK(fReplyAddress != nullptr); CARLA_SAFE_ASSERT_BREAK(fServer != nullptr); { // NOTE: lo_send_from is a macro that creates local variables lo_send_from(fReplyAddress, fServer, LO_TT_IMMEDIATE, "/nsm/client/gui_is_shown", ""); } break; case CB::NSM_CALLBACK_HIDE_OPTIONAL_GUI: CARLA_SAFE_ASSERT_BREAK(fReplyAddress != nullptr); CARLA_SAFE_ASSERT_BREAK(fServer != nullptr); { // NOTE: lo_send_from is a macro that creates local variables lo_send_from(fReplyAddress, fServer, LO_TT_IMMEDIATE, "/nsm/client/gui_is_hidden", ""); } break; } } static CarlaNSM& getInstance() { static CarlaNSM sInstance; return sInstance; } protected: int handleError(const char* const method, const int code, const char* const message) { carla_stdout("CarlaNSM::handleError(\"%s\", %i, \"%s\")", method, code, message); if (gStandalone.engineCallback != nullptr) gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, CB::NSM_CALLBACK_ERROR, code, 0, 0.0f, message); return 0; // may be unused (void)method; } int handleReply(const char* const method, const char* const message, const char* const smName, const char* const features, const lo_message msg) { CARLA_SAFE_ASSERT_RETURN(fServerThread != nullptr, 1); carla_stdout("CarlaNSM::handleReply(\"%s\", \"%s\", \"%s\", \"%s\")", method, message, smName, features); if (std::strcmp(method, "/nsm/server/announce") == 0) { const lo_address msgAddress(lo_message_get_source(msg)); CARLA_SAFE_ASSERT_RETURN(msgAddress != nullptr, 0); char* const msgURL(lo_address_get_url(msgAddress)); CARLA_SAFE_ASSERT_RETURN(msgURL != nullptr, 0); if (fReplyAddress != nullptr) lo_address_free(fReplyAddress); fReplyAddress = lo_address_new_from_url(msgURL); CARLA_SAFE_ASSERT_RETURN(fReplyAddress != nullptr, 0); fHasBroadcast = std::strstr(features, ":broadcast:") != nullptr; fHasOptionalGui = std::strstr(features, ":optional-gui:") != nullptr; fHasServerControl = std::strstr(features, ":server_control:") != nullptr; #if 0 // UI starts visible if (fHasOptionalGui) lo_send_from(fReplyAddress, fServer, LO_TT_IMMEDIATE, "/nsm/client/gui_is_shown", ""); #endif carla_stdout("Carla started via '%s', message: %s", smName, message); if (gStandalone.engineCallback != nullptr) { int flags = 0; if (fHasBroadcast) flags |= 1 << 0; if (fHasOptionalGui) flags |= 1 << 1; if (fHasServerControl) flags |= 1 << 2; gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, CB::NSM_CALLBACK_ANNOUNCE, flags, 0, 0.0f, smName); } std::free(msgURL); } else { carla_stdout("Got unknown NSM reply method '%s'", method); } return 0; } int handleOpen(const char* const projectPath, const char* const displayName, const char* const clientNameId) { CARLA_SAFE_ASSERT_RETURN(fReplyAddress != nullptr, 1); CARLA_SAFE_ASSERT_RETURN(fServer != nullptr, 1); carla_stdout("CarlaNSM::handleOpen(\"%s\", \"%s\", \"%s\")", projectPath, displayName, clientNameId); if (gStandalone.engineCallback != nullptr) { fReadyActionOpen = false; gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, CB::NSM_CALLBACK_OPEN, 0, 0, 0.0f, projectPath); for (; ! fReadyActionOpen;) carla_msleep(10); } else { using namespace water; if (carla_is_engine_running()) carla_engine_close(); carla_engine_init("JACK", clientNameId); fProjectPath = projectPath; fProjectPath += ".carxp"; const String jfilename = String(CharPointer_UTF8(fProjectPath)); if (File(jfilename).existsAsFile()) carla_load_project(fProjectPath); } fClientNameId = clientNameId; lo_send_from(fReplyAddress, fServer, LO_TT_IMMEDIATE, "/reply", "ss", "/nsm/client/open", "OK"); // Broadcast ourselves if (fHasBroadcast) { const char* appName = std::getenv("CARLA_NSM_NAME"); if (appName == nullptr) appName = "Carla"; lo_send_from(fReplyAddress, fServer, LO_TT_IMMEDIATE, "/nsm/server/broadcast", "sssss", "/non/hello", fServerURL, appName, CARLA_VERSION_STRING, fClientNameId.buffer()); } return 0; } int handleSave() { CARLA_SAFE_ASSERT_RETURN(fReplyAddress != nullptr, 1); CARLA_SAFE_ASSERT_RETURN(fServer != nullptr, 1); carla_stdout("CarlaNSM::handleSave()"); if (gStandalone.engineCallback != nullptr) { fReadyActionSave = false; gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, CB::NSM_CALLBACK_SAVE, 0, 0, 0.0f, nullptr); for (; ! fReadyActionSave;) carla_msleep(10); } else { CARLA_SAFE_ASSERT_RETURN(fProjectPath.isNotEmpty(), 0); carla_save_project(fProjectPath); } lo_send_from(fReplyAddress, fServer, LO_TT_IMMEDIATE, "/reply", "ss", "/nsm/client/save", "OK"); return 0; } int handleSessionIsLoaded() { CARLA_SAFE_ASSERT_RETURN(fReplyAddress != nullptr, 1); CARLA_SAFE_ASSERT_RETURN(fServer != nullptr, 1); carla_stdout("CarlaNSM::handleSessionIsLoaded()"); if (gStandalone.engineCallback != nullptr) gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, CB::NSM_CALLBACK_SESSION_IS_LOADED, 0, 0, 0.0f, nullptr); return 0; } int handleShowOptionalGui() { CARLA_SAFE_ASSERT_RETURN(fReplyAddress != nullptr, 1); CARLA_SAFE_ASSERT_RETURN(fServer != nullptr, 1); carla_stdout("CarlaNSM::handleShowOptionalGui()"); if (gStandalone.engineCallback != nullptr) gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, CB::NSM_CALLBACK_SHOW_OPTIONAL_GUI, 0, 0, 0.0f, nullptr); return 0; } int handleHideOptionalGui() { CARLA_SAFE_ASSERT_RETURN(fReplyAddress != nullptr, 1); CARLA_SAFE_ASSERT_RETURN(fServer != nullptr, 1); carla_stdout("CarlaNSM::handleHideOptionalGui()"); if (gStandalone.engineCallback != nullptr) gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, CB::NSM_CALLBACK_HIDE_OPTIONAL_GUI, 0, 0, 0.0f, nullptr); return 0; } int handleBroadcast(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg) { CARLA_SAFE_ASSERT_RETURN(fReplyAddress != nullptr, 1); CARLA_SAFE_ASSERT_RETURN(fServer != nullptr, 1); CARLA_SAFE_ASSERT_RETURN(argc >= 0, 0); carla_stdout("CarlaNSM::handleBroadcast(%s, %s, %p, %i)", path, types, argv, argc); #if 0 if (std::strcmp(path, "/non/hello") == 0) { CARLA_SAFE_ASSERT_RETURN(argc == 4, 0); CARLA_SAFE_ASSERT_RETURN(std::strcmp(types, "ssss") == 0, 0); const char* const url = &argv[0]->s; //const char* const name = &argv[1]->s; //const char* const version = &argv[2]->s; //const char* const clientId = &argv[3]->s; const lo_address targetAddress(lo_address_new_from_url(url)); CARLA_SAFE_ASSERT_RETURN(targetAddress != nullptr, 0); lo_send_from(targetAddress, fServer, LO_TT_IMMEDIATE, "/signal/hello", "ss", fClientNameId.buffer(), fServerURL); lo_address_free(targetAddress); return 0; } if (std::strcmp(path, "/signal/hello") == 0) { //const char* const name = &argv[0]->s; const char* const url = &argv[1]->s; const lo_address targetAddress(lo_address_new_from_url(url)); CARLA_SAFE_ASSERT_RETURN(targetAddress != nullptr, 0); lo_send_from(targetAddress, fServer, LO_TT_IMMEDIATE, "/signal/hello", "ss", fClientNameId.buffer(), fServerURL); lo_address_free(targetAddress); return 0; } if (std::strcmp(path, "/signal/list") == 0) { carla_stdout("CarlaNSM::handleBroadcast - got list"); CARLA_SAFE_ASSERT_RETURN(carla_is_engine_running(), 0); const char* prefix = nullptr; if (argc > 0) prefix = &argv[0]->s; const lo_address msgAddress(lo_message_get_source(msg)); CARLA_SAFE_ASSERT_RETURN(msgAddress != nullptr, 0); for (uint32_t i = 0, pluginCount = carla_get_current_plugin_count(); i < pluginCount; ++i) { const CarlaPluginInfo* const pluginInfo(carla_get_plugin_info(i)); CARLA_SAFE_ASSERT_CONTINUE(pluginInfo != nullptr); /*const*/ CarlaString pluginNameId(fClientNameId + "/" + CarlaString(pluginInfo->name).replace('/','_') + "/"); for (uint32_t j=0, paramCount = carla_get_parameter_count(i); j < paramCount; ++j) { const CarlaParameterInfo* const paramInfo(carla_get_parameter_info(i, j)); CARLA_SAFE_ASSERT_CONTINUE(paramInfo != nullptr); const ParameterData* const paramData(carla_get_parameter_data(i, j)); CARLA_SAFE_ASSERT_CONTINUE(paramData != nullptr); const ParameterRanges* const paramRanges(carla_get_parameter_ranges(i, j)); CARLA_SAFE_ASSERT_CONTINUE(paramRanges != nullptr); if (paramData->type != CB::PARAMETER_INPUT /*&& paramData->type != CB::PARAMETER_OUTPUT*/) continue; if ((paramData->hints & CB::PARAMETER_IS_ENABLED) == 0) continue; if ((paramData->hints & CB::PARAMETER_IS_AUTOMABLE) == 0) continue; if (paramData->hints & CB::PARAMETER_IS_READ_ONLY) continue; const char* const dir = paramData->type == CB::PARAMETER_INPUT ? "in" : "out"; const CarlaString paramNameId = pluginNameId + CarlaString(paramInfo->name).replace('/','_'); const float defNorm = paramRanges->getNormalizedValue(paramRanges->def); if (prefix == nullptr || std::strncmp(paramNameId, prefix, std::strlen(prefix)) == 0) { lo_send_from(msgAddress, fServer, LO_TT_IMMEDIATE, "/reply", "sssfff", path, paramNameId.buffer(), dir, 0.0f, 1.0f, defNorm); } } } lo_send_from(msgAddress, fServer, LO_TT_IMMEDIATE, "/reply", "s", path); //return 0; } for (int i=0; is); #endif return 0; // unused (void)msg; } private: lo_address fReplyAddress; lo_server fServer; lo_server_thread fServerThread; char* fServerURL; CarlaString fClientNameId; CarlaString fProjectPath; bool fHasBroadcast; bool fHasOptionalGui; bool fHasServerControl; bool fStarted; volatile bool fReadyActionOpen; volatile bool fReadyActionSave; #define handlePtr ((CarlaNSM*)data) static void _osc_error_handler(int num, const char* msg, const char* path) { carla_stderr2("CarlaNSM::_osc_error_handler(%i, \"%s\", \"%s\")", num, msg, path); } static int _error_handler(const char*, const char* types, lo_arg** argv, int argc, lo_message, void* data) { CARLA_SAFE_ASSERT_RETURN(argc == 3, 1); CARLA_SAFE_ASSERT_RETURN(std::strcmp(types, "sis") == 0, 1); const char* const method = &argv[0]->s; const int code = argv[1]->i; const char* const message = &argv[2]->s; return handlePtr->handleError(method, code, message); } static int _reply_handler(const char*, const char* types, lo_arg** argv, int argc, lo_message msg, void* data) { CARLA_SAFE_ASSERT_RETURN(argc == 4, 1); CARLA_SAFE_ASSERT_RETURN(std::strcmp(types, "ssss") == 0, 1); const char* const method = &argv[0]->s; const char* const message = &argv[1]->s; const char* const smName = &argv[2]->s; const char* const features = &argv[3]->s; return handlePtr->handleReply(method, message, smName, features, msg); } static int _open_handler(const char*, const char* types, lo_arg** argv, int argc, lo_message, void* data) { CARLA_SAFE_ASSERT_RETURN(argc == 3, 1); CARLA_SAFE_ASSERT_RETURN(std::strcmp(types, "sss") == 0, 1); const char* const projectPath = &argv[0]->s; const char* const displayName = &argv[1]->s; const char* const clientNameId = &argv[2]->s; return handlePtr->handleOpen(projectPath, displayName, clientNameId); } static int _save_handler(const char*, const char*, lo_arg**, int argc, lo_message, void* data) { CARLA_SAFE_ASSERT_RETURN(argc == 0, 1); return handlePtr->handleSave(); } static int _loaded_handler(const char*, const char*, lo_arg**, int argc, lo_message, void* data) { CARLA_SAFE_ASSERT_RETURN(argc == 0, 1); return handlePtr->handleSessionIsLoaded(); } static int _show_gui_handler(const char*, const char*, lo_arg**, int argc, lo_message, void* data) { CARLA_SAFE_ASSERT_RETURN(argc == 0, 1); return handlePtr->handleShowOptionalGui(); } static int _hide_gui_handler(const char*, const char*, lo_arg**, int argc, lo_message, void* data) { CARLA_SAFE_ASSERT_RETURN(argc == 0, 1); return handlePtr->handleHideOptionalGui(); } static int _broadcast_handler(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* data) { return handlePtr->handleBroadcast(path, types, argv, argc, msg); } #undef handlePtr CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_CLASS(CarlaNSM) }; #endif // HAVE_LIBLO // ------------------------------------------------------------------------------------------------------------------- bool carla_nsm_init(uint64_t pid, const char* executableName) { #ifdef HAVE_LIBLO return CarlaNSM::getInstance().announce(pid, executableName); #else return false; // unused (void)pid; (void)executableName; #endif } void carla_nsm_ready(NsmCallbackOpcode action) { #ifdef HAVE_LIBLO CarlaNSM::getInstance().ready(action); #else // unused return; (void)action; #endif } // ------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/CarlaUtils.h000066400000000000000000000155621364475620200175230ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_UTILS_H_INCLUDED #define CARLA_UTILS_H_INCLUDED #include "CarlaBackend.h" #ifdef __cplusplus using CarlaBackend::PluginCategory; using CarlaBackend::PluginType; #endif /*! * @defgroup CarlaUtilsAPI Carla Utils API * * The Carla Utils API. * * This API allows to call advanced features from Python. * @{ */ /*! * TODO. */ typedef void* CarlaPipeClientHandle; /*! * TODO. */ typedef void (*CarlaPipeCallbackFunc)(void* ptr, const char* msg); /*! * Information about a cached plugin. * @see carla_get_cached_plugin_info() */ typedef struct _CarlaCachedPluginInfo { /*! * Wherever the data in this struct is valid. * For performance reasons, plugins are only checked on request, * and as such, the count vs number of really valid plugins might not match. * Use this field to skip on plugins which cannot be loaded in Carla. */ bool valid; /*! * Plugin category. */ PluginCategory category; /*! * Plugin hints. * @see PluginHints */ uint hints; /*! * Number of audio inputs. */ uint32_t audioIns; /*! * Number of audio outputs. */ uint32_t audioOuts; /*! * Number of CV inputs. */ uint32_t cvIns; /*! * Number of CV outputs. */ uint32_t cvOuts; /*! * Number of MIDI inputs. */ uint32_t midiIns; /*! * Number of MIDI outputs. */ uint32_t midiOuts; /*! * Number of input parameters. */ uint32_t parameterIns; /*! * Number of output parameters. */ uint32_t parameterOuts; /*! * Plugin name. */ const char* name; /*! * Plugin label. */ const char* label; /*! * Plugin author/maker. */ const char* maker; /*! * Plugin copyright/license. */ const char* copyright; #ifdef __cplusplus /*! * C++ constructor. */ CARLA_API _CarlaCachedPluginInfo() noexcept; CARLA_DECLARE_NON_COPY_STRUCT(_CarlaCachedPluginInfo) #endif } CarlaCachedPluginInfo; /* -------------------------------------------------------------------------------------------------------------------- * get stuff */ /*! * Get the complete license text of used third-party code and features. * Returned string is in basic html format. */ CARLA_EXPORT const char* carla_get_complete_license_text(void); /*! * Get the juce version used in the current Carla build. */ CARLA_EXPORT const char* carla_get_juce_version(void); /*! * Get the list of supported file extensions in carla_load_file(). */ CARLA_EXPORT const char* const* carla_get_supported_file_extensions(void); /*! * Get the list of supported features in the current Carla build. */ CARLA_EXPORT const char* const* carla_get_supported_features(void); /*! * Get how many cached plugins are available. * Internal and LV2 plugin formats are cached and need to be discovered via this function. * Do not call this for any other plugin formats. */ CARLA_EXPORT uint carla_get_cached_plugin_count(PluginType ptype, const char* pluginPath); /*! * Get information about a cached plugin. */ CARLA_EXPORT const CarlaCachedPluginInfo* carla_get_cached_plugin_info(PluginType ptype, uint index); /* -------------------------------------------------------------------------------------------------------------------- * set stuff */ /*! * Flush stdout or stderr. */ CARLA_EXPORT void carla_fflush(bool err); /*! * Print the string @a string to stdout or stderr. */ CARLA_EXPORT void carla_fputs(bool err, const char* string); /*! * Set the current process name to @a name. */ CARLA_EXPORT void carla_set_process_name(const char* name); /* -------------------------------------------------------------------------------------------------------------------- * pipes */ /*! * TODO. */ CARLA_EXPORT CarlaPipeClientHandle carla_pipe_client_new(const char* argv[], CarlaPipeCallbackFunc callbackFunc, void* callbackPtr); /*! * TODO. */ CARLA_EXPORT const char* carla_pipe_client_idle(CarlaPipeClientHandle handle); /*! * TODO. */ CARLA_EXPORT bool carla_pipe_client_is_running(CarlaPipeClientHandle handle); /*! * TODO. */ CARLA_EXPORT void carla_pipe_client_lock(CarlaPipeClientHandle handle); /*! * TODO. */ CARLA_EXPORT void carla_pipe_client_unlock(CarlaPipeClientHandle handle); /*! * TODO. */ CARLA_EXPORT const char* carla_pipe_client_readlineblock(CarlaPipeClientHandle handle, uint timeout); /*! * Extras. * TODO. */ CARLA_EXPORT bool carla_pipe_client_readlineblock_bool(CarlaPipeClientHandle handle, uint timeout); CARLA_EXPORT int carla_pipe_client_readlineblock_int(CarlaPipeClientHandle handle, uint timeout); CARLA_EXPORT double carla_pipe_client_readlineblock_float(CarlaPipeClientHandle handle, uint timeout); /*! * TODO. */ CARLA_EXPORT bool carla_pipe_client_write_msg(CarlaPipeClientHandle handle, const char* msg); /*! * TODO. */ CARLA_EXPORT bool carla_pipe_client_write_and_fix_msg(CarlaPipeClientHandle handle, const char* msg); /*! * TODO. */ CARLA_EXPORT bool carla_pipe_client_flush(CarlaPipeClientHandle handle); /*! * TODO. */ CARLA_EXPORT bool carla_pipe_client_flush_and_unlock(CarlaPipeClientHandle handle); /*! * TODO. */ CARLA_EXPORT void carla_pipe_client_destroy(CarlaPipeClientHandle handle); #ifndef CARLA_HOST_H_INCLUDED /* -------------------------------------------------------------------------------------------------------------------- * info about current library */ /*! * Get the absolute filename of this carla library. */ CARLA_EXPORT const char* carla_get_library_filename(void); /*! * Get the folder where this carla library resides. */ CARLA_EXPORT const char* carla_get_library_folder(void); #endif /* -------------------------------------------------------------------------------------------------------------------- * window control */ CARLA_EXPORT int carla_cocoa_get_window(void* nsViewPtr); CARLA_EXPORT void carla_x11_reparent_window(uintptr_t winId1, uintptr_t winId2); CARLA_EXPORT void carla_x11_move_window(uintptr_t winId, int x, int y); CARLA_EXPORT int* carla_x11_get_window_pos(uintptr_t winId); /* ----------------------------------------------------------------------------------------------------------------- */ /** @} */ #endif /* CARLA_UTILS_H_INCLUDED */ Carla-2.1/source/backend/Makefile000066400000000000000000000103071364475620200167370ustar00rootroot00000000000000#!/usr/bin/make -f # Makefile for carla-backend # # -------------------------- # # Created by falkTX # CWD=.. include Makefile.mk # --------------------------------------------------------------------------------------------------------------------- OBJS_standalone = \ $(OBJDIR)/CarlaStandalone.cpp.o \ $(OBJDIR)/CarlaStandaloneNSM.cpp.o TARGETS = \ $(BINDIR)/libcarla_standalone2$(LIB_EXT) # --------------------------------------------------------------------------------------------------------------------- STANDALONE_LIBS = $(MODULEDIR)/carla_engine.a STANDALONE_LIBS += $(MODULEDIR)/carla_plugin.a STANDALONE_LIBS += $(MODULEDIR)/jackbridge.a STANDALONE_LIBS += $(MODULEDIR)/audio_decoder.a STANDALONE_LIBS += $(MODULEDIR)/lilv.a STANDALONE_LIBS += $(MODULEDIR)/native-plugins.a STANDALONE_LIBS += $(MODULEDIR)/rtmempool.a STANDALONE_LIBS += $(MODULEDIR)/sfzero.a STANDALONE_LIBS += $(MODULEDIR)/water.a ifeq ($(HAVE_DGL),true) STANDALONE_LIBS += $(MODULEDIR)/dgl.a endif ifeq ($(HAVE_HYLIA),true) STANDALONE_LIBS += $(MODULEDIR)/hylia.a endif ifeq ($(USING_JUCE),true) STANDALONE_LIBS += $(MODULEDIR)/juce_audio_basics.a STANDALONE_LIBS += $(MODULEDIR)/juce_audio_devices.a STANDALONE_LIBS += $(MODULEDIR)/juce_audio_processors.a STANDALONE_LIBS += $(MODULEDIR)/juce_core.a STANDALONE_LIBS += $(MODULEDIR)/juce_data_structures.a STANDALONE_LIBS += $(MODULEDIR)/juce_events.a STANDALONE_LIBS += $(MODULEDIR)/juce_graphics.a STANDALONE_LIBS += $(MODULEDIR)/juce_gui_basics.a ifeq ($(MACOS),true) STANDALONE_LIBS += $(MODULEDIR)/juce_gui_extra.a endif else STANDALONE_LIBS += $(MODULEDIR)/rtaudio.a STANDALONE_LIBS += $(MODULEDIR)/rtmidi.a endif # --------------------------------------------------------------------------------------------------------------------- STANDALONE_LINK_FLAGS = $(HYLIA_LIBS) STANDALONE_LINK_FLAGS += $(JACKBRIDGE_LIBS) STANDALONE_LINK_FLAGS += $(LILV_LIBS) STANDALONE_LINK_FLAGS += $(NATIVE_PLUGINS_LIBS) STANDALONE_LINK_FLAGS += $(RTMEMPOOL_LIBS) STANDALONE_LINK_FLAGS += $(WATER_LIBS) STANDALONE_LINK_FLAGS += $(LIBLO_LIBS) STANDALONE_LINK_FLAGS += $(MAGIC_LIBS) STANDALONE_LINK_FLAGS += $(FLUIDSYNTH_LIBS) STANDALONE_LINK_FLAGS += $(X11_LIBS) ifeq ($(USING_JUCE),true) STANDALONE_LINK_FLAGS += $(JUCE_AUDIO_BASICS_LIBS) STANDALONE_LINK_FLAGS += $(JUCE_AUDIO_DEVICES_LIBS) STANDALONE_LINK_FLAGS += $(JUCE_AUDIO_PROCESSORS_LIBS) STANDALONE_LINK_FLAGS += $(JUCE_CORE_LIBS) STANDALONE_LINK_FLAGS += $(JUCE_DATA_STRUCTURES_LIBS) STANDALONE_LINK_FLAGS += $(JUCE_EVENTS_LIBS) STANDALONE_LINK_FLAGS += $(JUCE_GRAPHICS_LIBS) STANDALONE_LINK_FLAGS += $(JUCE_GUI_BASICS_LIBS) ifeq ($(MACOS),true) STANDALONE_LINK_FLAGS += $(JUCE_GUI_EXTRA_LIBS) endif else STANDALONE_LINK_FLAGS += $(RTAUDIO_LIBS) STANDALONE_LINK_FLAGS += $(RTMIDI_LIBS) endif ifeq ($(JACKBRIDGE_DIRECT),true) STANDALONE_LINK_FLAGS += $(JACK_LIBS) endif # --------------------------------------------------------------------------------------------------------------------- all: $(TARGETS) $(MAKE) -C utils # --------------------------------------------------------------------------------------------------------------------- clean: rm -f $(OBJS_standalone) $(TARGETS) $(MAKE) clean -C engine $(MAKE) clean -C plugin $(MAKE) clean -C utils debug: $(MAKE) DEBUG=true doxygen: CarlaBackend.doxygen doxygen $^ # --------------------------------------------------------------------------------------------------------------------- $(BINDIR)/libcarla_standalone2$(LIB_EXT): $(OBJS_standalone) $(STANDALONE_LIBS) -@mkdir -p $(BINDIR) @echo "Linking libcarla_standalone2$(LIB_EXT)" @$(CXX) $(OBJS_standalone) $(LIBS_START) $(STANDALONE_LIBS) $(LIBS_END) $(LINK_FLAGS) $(STANDALONE_LINK_FLAGS) $(SHARED) -o $@ # --------------------------------------------------------------------------------------------------------------------- ifeq ($(MACOS),true) $(OBJDIR)/CarlaStandalone.cpp.o: CarlaStandalone.cpp -@mkdir -p $(OBJDIR) @echo "Compiling $<" @$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@ endif $(OBJDIR)/%.cpp.o: %.cpp -@mkdir -p $(OBJDIR) @echo "Compiling $<" @$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ -include $(OBJS_standalone:%.o=%.d) # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/Makefile.mk000066400000000000000000000022341364475620200173450ustar00rootroot00000000000000#!/usr/bin/make -f # Makefile for carla-backend # # -------------------------- # # Created by falkTX # ifeq ($(CWD),) $(error CWD not defined) endif include $(CWD)/Makefile.mk # Workaround GCC bug ifeq ($(TESTBUILD),true) ifeq ($(USING_JUCE),true) BUILD_CXX_FLAGS += -Wno-undef endif endif # --------------------------------------------------------------------------------------------------------------------- BINDIR := $(CWD)/../bin ifeq ($(DEBUG),true) OBJDIR := $(CWD)/../build/backend/Debug MODULEDIR := $(CWD)/../build/modules/Debug else OBJDIR := $(CWD)/../build/backend/Release MODULEDIR := $(CWD)/../build/modules/Release endif # --------------------------------------------------------------------------------------------------------------------- BUILD_CXX_FLAGS += -I. -I.. -I$(CWD) -I$(CWD)/includes -I$(CWD)/modules -I$(CWD)/utils BUILD_CXX_FLAGS += $(LIBLO_FLAGS) # --------------------------------------------------------------------------------------------------------------------- BUILD_CXX_FLAGS += $(NATIVE_PLUGINS_FLAGS) # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/engine/000077500000000000000000000000001364475620200165435ustar00rootroot00000000000000Carla-2.1/source/backend/engine/CarlaEngine.cpp000066400000000000000000002764131364475620200214340ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ /* TODO: * - complete processRack(): carefully add to input, sorted events * - implement processPatchbay() * - implement oscSend_control_switch_plugins() * - something about the peaks? */ #include "CarlaEngineClient.hpp" #include "CarlaEngineInternal.hpp" #include "CarlaPlugin.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaBinaryUtils.hpp" #include "CarlaEngineUtils.hpp" #include "CarlaMathUtils.hpp" #include "CarlaPipeUtils.hpp" #include "CarlaProcessUtils.hpp" #include "CarlaScopeUtils.hpp" #include "CarlaStateUtils.hpp" #include "CarlaMIDI.h" #include "jackbridge/JackBridge.hpp" #include "water/files/File.h" #include "water/streams/MemoryOutputStream.h" #include "water/xml/XmlDocument.h" #include "water/xml/XmlElement.h" // FIXME Remove on 2.1 release #include "lv2/atom.h" using water::Array; using water::CharPointer_UTF8; using water::File; using water::MemoryOutputStream; using water::String; using water::StringArray; using water::XmlDocument; using water::XmlElement; CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // Carla Engine CarlaEngine::CarlaEngine() : pData(new ProtectedData(this)) { carla_debug("CarlaEngine::CarlaEngine()"); } CarlaEngine::~CarlaEngine() { carla_debug("CarlaEngine::~CarlaEngine()"); delete pData; } // ----------------------------------------------------------------------- // Static calls uint CarlaEngine::getDriverCount() { carla_debug("CarlaEngine::getDriverCount()"); uint count = 0; if (jackbridge_is_ok()) count += 1; #ifndef BUILD_BRIDGE # ifdef USING_JUCE count += getJuceApiCount(); # else count += getRtAudioApiCount(); # endif #endif return count; } const char* CarlaEngine::getDriverName(const uint index2) { carla_debug("CarlaEngine::getDriverName(%i)", index2); uint index = index2; if (jackbridge_is_ok() && index-- == 0) return "JACK"; #ifndef BUILD_BRIDGE # ifdef USING_JUCE if (const uint count = getJuceApiCount()) { if (index < count) return getJuceApiName(index); index -= count; } # else if (const uint count = getRtAudioApiCount()) { if (index < count) return getRtAudioApiName(index); } # endif #endif carla_stderr("CarlaEngine::getDriverName(%i) - invalid index", index2); return nullptr; } const char* const* CarlaEngine::getDriverDeviceNames(const uint index2) { carla_debug("CarlaEngine::getDriverDeviceNames(%i)", index2); uint index = index2; if (jackbridge_is_ok() && index-- == 0) { static const char* ret[3] = { "Auto-Connect ON", "Auto-Connect OFF", nullptr }; return ret; } #ifndef BUILD_BRIDGE # ifdef USING_JUCE if (const uint count = getJuceApiCount()) { if (index < count) return getJuceApiDeviceNames(index); index -= count; } # else if (const uint count = getRtAudioApiCount()) { if (index < count) return getRtAudioApiDeviceNames(index); } # endif #endif carla_stderr("CarlaEngine::getDriverDeviceNames(%i) - invalid index", index2); return nullptr; } const EngineDriverDeviceInfo* CarlaEngine::getDriverDeviceInfo(const uint index2, const char* const deviceName) { carla_debug("CarlaEngine::getDriverDeviceInfo(%i, \"%s\")", index2, deviceName); uint index = index2; if (jackbridge_is_ok() && index-- == 0) { static EngineDriverDeviceInfo devInfo; devInfo.hints = ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE; devInfo.bufferSizes = nullptr; devInfo.sampleRates = nullptr; return &devInfo; } #ifndef BUILD_BRIDGE # ifdef USING_JUCE if (const uint count = getJuceApiCount()) { if (index < count) return getJuceDeviceInfo(index, deviceName); index -= count; } # else if (const uint count = getRtAudioApiCount()) { if (index < count) return getRtAudioDeviceInfo(index, deviceName); } # endif #endif carla_stderr("CarlaEngine::getDriverDeviceNames(%i, \"%s\") - invalid index", index2, deviceName); return nullptr; } bool CarlaEngine::showDriverDeviceControlPanel(const uint index2, const char* const deviceName) { carla_debug("CarlaEngine::showDriverDeviceControlPanel(%i, \"%s\")", index2, deviceName); uint index = index2; if (jackbridge_is_ok() && index-- == 0) { return false; } #ifndef BUILD_BRIDGE # ifdef USING_JUCE if (const uint count = getJuceApiCount()) { if (index < count) return showJuceDeviceControlPanel(index, deviceName); index -= count; } # else if (const uint count = getRtAudioApiCount()) { if (index < count) return false; } # endif #endif carla_stderr("CarlaEngine::showDriverDeviceControlPanel(%i, \"%s\") - invalid index", index2, deviceName); return false; } CarlaEngine* CarlaEngine::newDriverByName(const char* const driverName) { CARLA_SAFE_ASSERT_RETURN(driverName != nullptr && driverName[0] != '\0', nullptr); carla_debug("CarlaEngine::newDriverByName(\"%s\")", driverName); if (std::strcmp(driverName, "JACK") == 0) return newJack(); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (std::strcmp(driverName, "Dummy") == 0) return newDummy(); #endif #ifndef BUILD_BRIDGE # ifdef USING_JUCE // ------------------------------------------------------------------- // linux if (std::strcmp(driverName, "ALSA") == 0) return newJuce(AUDIO_API_ALSA); // ------------------------------------------------------------------- // macos if (std::strcmp(driverName, "CoreAudio") == 0) return newJuce(AUDIO_API_COREAUDIO); // ------------------------------------------------------------------- // windows if (std::strcmp(driverName, "ASIO") == 0) return newJuce(AUDIO_API_ASIO); if (std::strcmp(driverName, "DirectSound") == 0) return newJuce(AUDIO_API_DIRECTSOUND); if (std::strcmp(driverName, "WASAPI") == 0 || std::strcmp(driverName, "Windows Audio") == 0) return newJuce(AUDIO_API_WASAPI); # else // ------------------------------------------------------------------- // common if (std::strncmp(driverName, "JACK ", 5) == 0) return newRtAudio(AUDIO_API_JACK); if (std::strcmp(driverName, "OSS") == 0) return newRtAudio(AUDIO_API_OSS); // ------------------------------------------------------------------- // linux if (std::strcmp(driverName, "ALSA") == 0) return newRtAudio(AUDIO_API_ALSA); if (std::strcmp(driverName, "PulseAudio") == 0) return newRtAudio(AUDIO_API_PULSEAUDIO); // ------------------------------------------------------------------- // macos if (std::strcmp(driverName, "CoreAudio") == 0) return newRtAudio(AUDIO_API_COREAUDIO); // ------------------------------------------------------------------- // windows if (std::strcmp(driverName, "ASIO") == 0) return newRtAudio(AUDIO_API_ASIO); if (std::strcmp(driverName, "DirectSound") == 0) return newRtAudio(AUDIO_API_DIRECTSOUND); if (std::strcmp(driverName, "WASAPI") == 0) return newRtAudio(AUDIO_API_WASAPI); # endif #endif carla_stderr("CarlaEngine::newDriverByName(\"%s\") - invalid driver name", driverName); return nullptr; } // ----------------------------------------------------------------------- // Constant values uint CarlaEngine::getMaxClientNameSize() const noexcept { return STR_MAX/2; } uint CarlaEngine::getMaxPortNameSize() const noexcept { return STR_MAX; } uint CarlaEngine::getCurrentPluginCount() const noexcept { return pData->curPluginCount; } uint CarlaEngine::getMaxPluginNumber() const noexcept { return pData->maxPluginNumber; } // ----------------------------------------------------------------------- // Virtual, per-engine type calls bool CarlaEngine::close() { carla_debug("CarlaEngine::close()"); if (pData->curPluginCount != 0) { pData->aboutToClose = true; removeAllPlugins(); } pData->close(); callback(true, true, ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0, 0.0f, nullptr); return true; } bool CarlaEngine::usesConstantBufferSize() const noexcept { return true; } void CarlaEngine::idle() noexcept { CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,); CARLA_SAFE_ASSERT_RETURN(pData->nextPluginId == pData->maxPluginNumber,); CARLA_SAFE_ASSERT_RETURN(getType() != kEngineTypePlugin,); for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin != nullptr && plugin->isEnabled()) { const uint hints(plugin->getHints()); if ((hints & PLUGIN_HAS_CUSTOM_UI) != 0 && (hints & PLUGIN_NEEDS_UI_MAIN_THREAD) != 0) { try { plugin->uiIdle(); } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin uiIdle"); } } } #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) pData->osc.idle(); #endif } CarlaEngineClient* CarlaEngine::addClient(CarlaPlugin* const plugin) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH return new CarlaEngineClientForStandalone(*this, pData->graph, plugin); #else return new CarlaEngineClientForBridge(*this); // unused (void)plugin; #endif } float CarlaEngine::getDSPLoad() const noexcept { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH return pData->dspLoad; #else return 0.0f; #endif } uint32_t CarlaEngine::getTotalXruns() const noexcept { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH return pData->xruns; #else return 0; #endif } void CarlaEngine::clearXruns() const noexcept { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->xruns = 0; #endif } bool CarlaEngine::showDeviceControlPanel() const noexcept { return false; } bool CarlaEngine::setBufferSizeAndSampleRate(const uint, const double) { return false; } // ----------------------------------------------------------------------- // Plugin management bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, const char* const filename, const char* const name, const char* const label, const int64_t uniqueId, const void* const extra, const uint options) { CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish"); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextPluginId <= pData->maxPluginNumber, "Invalid engine internal data"); #endif CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(btype != BINARY_NONE, "Invalid plugin binary mode"); CARLA_SAFE_ASSERT_RETURN_ERR(ptype != PLUGIN_NONE, "Invalid plugin type"); CARLA_SAFE_ASSERT_RETURN_ERR((filename != nullptr && filename[0] != '\0') || (label != nullptr && label[0] != '\0'), "Invalid plugin filename and label"); carla_debug("CarlaEngine::addPlugin(%i:%s, %i:%s, \"%s\", \"%s\", \"%s\", " P_INT64 ", %p, %u)", btype, BinaryType2Str(btype), ptype, PluginType2Str(ptype), filename, name, label, uniqueId, extra, options); #ifndef CARLA_OS_WIN if (ptype != PLUGIN_JACK && ptype != PLUGIN_LV2 && filename != nullptr && filename[0] != '\0') { CARLA_SAFE_ASSERT_RETURN_ERR(filename[0] == CARLA_OS_SEP || filename[0] == '.' || filename[0] == '~', "Invalid plugin filename"); } #endif uint id; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaPlugin* oldPlugin = nullptr; if (pData->nextPluginId < pData->curPluginCount) { id = pData->nextPluginId; pData->nextPluginId = pData->maxPluginNumber; oldPlugin = pData->plugins[id].plugin; CARLA_SAFE_ASSERT_RETURN_ERR(oldPlugin != nullptr, "Invalid replace plugin Id"); } else #endif { id = pData->curPluginCount; if (id == pData->maxPluginNumber) { setLastError("Maximum number of plugins reached"); return false; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins[id].plugin == nullptr, "Invalid engine internal data"); #endif } CarlaPlugin::Initializer initializer = { this, id, filename, name, label, uniqueId, options }; CarlaPlugin* plugin = nullptr; CarlaString bridgeBinary(pData->options.binaryDir); if (bridgeBinary.isNotEmpty()) { #ifndef CARLA_OS_WIN if (btype == BINARY_NATIVE) { bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-native"; } else #endif { switch (btype) { case BINARY_POSIX32: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-posix32"; break; case BINARY_POSIX64: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-posix64"; break; case BINARY_WIN32: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-win32.exe"; break; case BINARY_WIN64: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-win64.exe"; break; default: bridgeBinary.clear(); break; } } if (! File(bridgeBinary.buffer()).existsAsFile()) bridgeBinary.clear(); } // Prefer bridges for some specific plugins const bool preferBridges = pData->options.preferPluginBridges; #if 0 // ndef BUILD_BRIDGE if (! preferBridges) { if (ptype == PLUGIN_LV2 && label != nullptr) { if (std::strncmp(label, "http://calf.sourceforge.net/plugins/", 36) == 0 || std::strcmp(label, "http://factorial.hu/plugins/lv2/ir") == 0 || std::strstr(label, "v1.sourceforge.net/lv2") != nullptr) { preferBridges = true; } } } #endif // ! BUILD_BRIDGE const bool canBeBridged = ptype != PLUGIN_INTERNAL && ptype != PLUGIN_SF2 && ptype != PLUGIN_SFZ && ptype != PLUGIN_JACK; if (canBeBridged && (btype != BINARY_NATIVE || (preferBridges && bridgeBinary.isNotEmpty()))) { if (bridgeBinary.isNotEmpty()) { plugin = CarlaPlugin::newBridge(initializer, btype, ptype, bridgeBinary); } else { setLastError("This Carla build cannot handle this binary"); return false; } } else { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH bool use16Outs; #endif setLastError("Invalid or unsupported plugin type"); // Some stupid plugins mess up with global signals, err!! const CarlaSignalRestorer csr; switch (ptype) { case PLUGIN_NONE: break; case PLUGIN_LADSPA: plugin = CarlaPlugin::newLADSPA(initializer, (const LADSPA_RDF_Descriptor*)extra); break; case PLUGIN_DSSI: plugin = CarlaPlugin::newDSSI(initializer); break; case PLUGIN_LV2: plugin = CarlaPlugin::newLV2(initializer); break; case PLUGIN_VST2: plugin = CarlaPlugin::newVST2(initializer); break; case PLUGIN_VST3: plugin = CarlaPlugin::newVST3(initializer); break; case PLUGIN_AU: plugin = CarlaPlugin::newAU(initializer); break; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH case PLUGIN_INTERNAL: plugin = CarlaPlugin::newNative(initializer); break; case PLUGIN_DLS: case PLUGIN_GIG: case PLUGIN_SF2: use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0); plugin = CarlaPlugin::newFluidSynth(initializer, use16Outs); break; case PLUGIN_SFZ: plugin = CarlaPlugin::newSFZero(initializer); break; case PLUGIN_JACK: plugin = CarlaPlugin::newJackApp(initializer); break; #else case PLUGIN_INTERNAL: case PLUGIN_DLS: case PLUGIN_GIG: case PLUGIN_SF2: case PLUGIN_SFZ: case PLUGIN_JACK: setLastError("Plugin bridges cannot handle this binary"); break; #endif } } if (plugin == nullptr) return false; plugin->reload(); bool canRun = true; /**/ if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { if (plugin->getCVInCount() > 0 || plugin->getCVInCount() > 0) { setLastError("Carla's rack mode cannot work with plugins that have CV ports, sorry!"); canRun = false; } } else if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { /**/ if (plugin->getMidiInCount() > 1 || plugin->getMidiOutCount() > 1) { setLastError("Carla's patchbay mode cannot work with plugins that have multiple MIDI ports, sorry!"); canRun = false; } } if (! canRun) { delete plugin; return false; } EnginePluginData& pluginData(pData->plugins[id]); pluginData.plugin = plugin; carla_zeroFloats(pluginData.peaks, 4); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (oldPlugin != nullptr) { CARLA_SAFE_ASSERT(! pData->loadingProject); const ScopedThreadStopper sts(this); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) pData->graph.replacePlugin(oldPlugin, plugin); const bool wasActive = oldPlugin->getInternalParameterValue(PARAMETER_ACTIVE) >= 0.5f; const float oldDryWet = oldPlugin->getInternalParameterValue(PARAMETER_DRYWET); const float oldVolume = oldPlugin->getInternalParameterValue(PARAMETER_VOLUME); delete oldPlugin; if (plugin->getHints() & PLUGIN_CAN_DRYWET) plugin->setDryWet(oldDryWet, true, true); if (plugin->getHints() & PLUGIN_CAN_VOLUME) plugin->setVolume(oldVolume, true, true); plugin->setActive(wasActive, true, true); plugin->setEnabled(true); callback(true, true, ENGINE_CALLBACK_RELOAD_ALL, id, 0, 0, 0, 0.0f, nullptr); } else if (! pData->loadingProject) #endif { plugin->setEnabled(true); ++pData->curPluginCount; callback(true, true, ENGINE_CALLBACK_PLUGIN_ADDED, id, 0, 0, 0, 0.0f, plugin->getName()); if (getType() != kEngineTypeBridge) plugin->setActive(true, true, true); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) pData->graph.addPlugin(plugin); #endif } return true; } bool CarlaEngine::addPlugin(const PluginType ptype, const char* const filename, const char* const name, const char* const label, const int64_t uniqueId, const void* const extra) { return addPlugin(BINARY_NATIVE, ptype, filename, name, label, uniqueId, extra, PLUGIN_OPTIONS_NULL); } bool CarlaEngine::removePlugin(const uint id) { CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish"); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data"); #endif CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id"); carla_debug("CarlaEngine::removePlugin(%i)", id); CarlaPlugin* const plugin(pData->plugins[id].plugin); CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to remove"); CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data"); const ScopedThreadStopper sts(this); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) pData->graph.removePlugin(plugin); const ScopedActionLock sal(this, kEnginePostActionRemovePlugin, id, 0); /* for (uint i=id; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin2(pData->plugins[i].plugin); CARLA_SAFE_ASSERT_BREAK(plugin2 != nullptr); plugin2->updateOscURL(); } */ #else pData->curPluginCount = 0; carla_zeroStructs(pData->plugins, 1); #endif delete plugin; callback(true, true, ENGINE_CALLBACK_PLUGIN_REMOVED, id, 0, 0, 0, 0.0f, nullptr); return true; } bool CarlaEngine::removeAllPlugins() { CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish"); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextPluginId == pData->maxPluginNumber, "Invalid engine internal data"); #endif CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data"); carla_debug("CarlaEngine::removeAllPlugins()"); if (pData->curPluginCount == 0) return true; const ScopedThreadStopper sts(this); const uint curPluginCount(pData->curPluginCount); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) pData->graph.removeAllPlugins(); #endif const ScopedActionLock sal(this, kEnginePostActionZeroCount, 0, 0); callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); for (uint i=0; i < curPluginCount; ++i) { const uint id = curPluginCount - i - 1; EnginePluginData& pluginData(pData->plugins[id]); if (pluginData.plugin != nullptr) { delete pluginData.plugin; pluginData.plugin = nullptr; } carla_zeroFloats(pluginData.peaks, 4); callback(true, true, ENGINE_CALLBACK_PLUGIN_REMOVED, id, 0, 0, 0, 0.0f, nullptr); callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); } return true; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH bool CarlaEngine::renamePlugin(const uint id, const char* const newName) { CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id"); CARLA_SAFE_ASSERT_RETURN_ERR(newName != nullptr && newName[0] != '\0', "Invalid plugin name"); carla_debug("CarlaEngine::renamePlugin(%i, \"%s\")", id, newName); CarlaPlugin* const plugin(pData->plugins[id].plugin); CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to rename"); CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data"); const char* const uniqueName(getUniquePluginName(newName)); CARLA_SAFE_ASSERT_RETURN_ERR(uniqueName != nullptr, "Unable to get new unique plugin name"); plugin->setName(uniqueName); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) pData->graph.renamePlugin(plugin, uniqueName); callback(true, true, ENGINE_CALLBACK_PLUGIN_RENAMED, id, 0, 0, 0, 0.0f, uniqueName); delete[] uniqueName; return true; } bool CarlaEngine::clonePlugin(const uint id) { CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id"); carla_debug("CarlaEngine::clonePlugin(%i)", id); CarlaPlugin* const plugin(pData->plugins[id].plugin); CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to clone"); CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data"); char label[STR_MAX+1]; carla_zeroChars(label, STR_MAX+1); if (! plugin->getLabel(label)) label[0] = '\0'; const uint pluginCountBefore(pData->curPluginCount); if (! addPlugin(plugin->getBinaryType(), plugin->getType(), plugin->getFilename(), plugin->getName(), label, plugin->getUniqueId(), plugin->getExtraStuff(), plugin->getOptionsEnabled())) return false; CARLA_SAFE_ASSERT_RETURN_ERR(pluginCountBefore+1 == pData->curPluginCount, "No new plugin found"); if (CarlaPlugin* const newPlugin = pData->plugins[pluginCountBefore].plugin) newPlugin->loadStateSave(plugin->getStateSave()); return true; } bool CarlaEngine::replacePlugin(const uint id) noexcept { CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data"); carla_debug("CarlaEngine::replacePlugin(%i)", id); // might use this to reset if (id == pData->maxPluginNumber) { pData->nextPluginId = pData->maxPluginNumber; return true; } CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id"); CarlaPlugin* const plugin(pData->plugins[id].plugin); CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to replace"); CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data"); pData->nextPluginId = id; return true; } bool CarlaEngine::switchPlugins(const uint idA, const uint idB) noexcept { CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount >= 2, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(idA != idB, "Invalid operation, cannot switch plugin with itself"); CARLA_SAFE_ASSERT_RETURN_ERR(idA < pData->curPluginCount, "Invalid plugin Id"); CARLA_SAFE_ASSERT_RETURN_ERR(idB < pData->curPluginCount, "Invalid plugin Id"); carla_debug("CarlaEngine::switchPlugins(%i)", idA, idB); CarlaPlugin* const pluginA(pData->plugins[idA].plugin); CarlaPlugin* const pluginB(pData->plugins[idB].plugin); CARLA_SAFE_ASSERT_RETURN_ERR(pluginA != nullptr, "Could not find plugin to switch"); CARLA_SAFE_ASSERT_RETURN_ERR(pluginA != nullptr, "Could not find plugin to switch"); CARLA_SAFE_ASSERT_RETURN_ERR(pluginA->getId() == idA, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERR(pluginB->getId() == idB, "Invalid engine internal data"); const ScopedThreadStopper sts(this); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) pData->graph.replacePlugin(pluginA, pluginB); const ScopedActionLock sal(this, kEnginePostActionSwitchPlugins, idA, idB); // TODO /* pluginA->updateOscURL(); pluginB->updateOscURL(); if (isOscControlRegistered()) oscSend_control_switch_plugins(idA, idB); */ return true; } #endif void CarlaEngine::touchPluginParameter(const uint, const uint32_t, const bool) noexcept { } CarlaPlugin* CarlaEngine::getPlugin(const uint id) const noexcept { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT_RETURN_ERRN(pData->plugins != nullptr, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERRN(pData->curPluginCount != 0, "Invalid engine internal data"); #endif CARLA_SAFE_ASSERT_RETURN_ERRN(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data"); CARLA_SAFE_ASSERT_RETURN_ERRN(id < pData->curPluginCount, "Invalid plugin Id"); return pData->plugins[id].plugin; } CarlaPlugin* CarlaEngine::getPluginUnchecked(const uint id) const noexcept { return pData->plugins[id].plugin; } const char* CarlaEngine::getUniquePluginName(const char* const name) const { CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull, nullptr); CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr); carla_debug("CarlaEngine::getUniquePluginName(\"%s\")", name); CarlaString sname; sname = name; if (sname.isEmpty()) { sname = "(No name)"; return sname.dup(); } const std::size_t maxNameSize(carla_minConstrained(getMaxClientNameSize(), 0xff, 6U) - 6); // 6 = strlen(" (10)") + 1 if (maxNameSize == 0 || ! isRunning()) return sname.dup(); sname.truncate(maxNameSize); sname.replace(':', '.'); // ':' is used in JACK1 to split client/port names for (uint i=0; i < pData->curPluginCount; ++i) { CARLA_SAFE_ASSERT_BREAK(pData->plugins[i].plugin != nullptr); // Check if unique name doesn't exist if (const char* const pluginName = pData->plugins[i].plugin->getName()) { if (sname != pluginName) continue; } // Check if string has already been modified { const std::size_t len(sname.length()); // 1 digit, ex: " (2)" if (sname[len-4] == ' ' && sname[len-3] == '(' && sname.isDigit(len-2) && sname[len-1] == ')') { const int number = sname[len-2] - '0'; if (number == 9) { // next number is 10, 2 digits sname.truncate(len-4); sname += " (10)"; //sname.replace(" (9)", " (10)"); } else sname[len-2] = char('0' + number + 1); continue; } // 2 digits, ex: " (11)" if (sname[len-5] == ' ' && sname[len-4] == '(' && sname.isDigit(len-3) && sname.isDigit(len-2) && sname[len-1] == ')') { char n2 = sname[len-2]; char n3 = sname[len-3]; if (n2 == '9') { n2 = '0'; n3 = static_cast(n3 + 1); } else n2 = static_cast(n2 + 1); sname[len-2] = n2; sname[len-3] = n3; continue; } } // Modify string if not sname += " (2)"; } return sname.dup(); } // ----------------------------------------------------------------------- // Project management bool CarlaEngine::loadFile(const char* const filename) { CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish"); CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename"); carla_debug("CarlaEngine::loadFile(\"%s\")", filename); const String jfilename = String(CharPointer_UTF8(filename)); File file(jfilename); CARLA_SAFE_ASSERT_RETURN_ERR(file.exists(), "Requested file does not exist or is not a readable"); CarlaString baseName(file.getFileNameWithoutExtension().toRawUTF8()); CarlaString extension(file.getFileExtension().replace(".","").toLowerCase().toRawUTF8()); const uint curPluginId(pData->nextPluginId < pData->curPluginCount ? pData->nextPluginId : pData->curPluginCount); // ------------------------------------------------------------------- // NOTE: please keep in sync with carla_get_supported_file_extensions!! if (extension == "carxp" || extension == "carxs") return loadProject(filename, false); // ------------------------------------------------------------------- if (extension == "sf2" || extension == "sf3") return addPlugin(PLUGIN_SF2, filename, baseName, baseName, 0, nullptr); if (extension == "sfz") return addPlugin(PLUGIN_SFZ, filename, baseName, baseName, 0, nullptr); // ------------------------------------------------------------------- if ( #ifdef HAVE_SNDFILE extension == "aif" || extension == "aifc" || extension == "aiff" || extension == "au" || extension == "bwf" || extension == "flac" || extension == "htk" || extension == "iff" || extension == "mat4" || extension == "mat5" || extension == "oga" || extension == "ogg" || extension == "paf" || extension == "pvf" || extension == "pvf5" || extension == "sd2" || extension == "sf" || extension == "snd" || extension == "svx" || extension == "vcc" || extension == "w64" || extension == "wav" || extension == "xi" || #endif #ifdef HAVE_FFMPEG extension == "3g2" || extension == "3gp" || extension == "aac" || extension == "ac3" || extension == "amr" || extension == "ape" || extension == "mp2" || extension == "mp3" || extension == "mpc" || extension == "wma" || # ifndef HAVE_SNDFILE // FFmpeg without sndfile extension == "flac" || extension == "oga" || extension == "ogg" || extension == "w64" || extension == "wav" || # endif #endif false ) { if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "audiofile", 0, nullptr)) { if (CarlaPlugin* const plugin = getPlugin(curPluginId)) plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "file", filename, true); return true; } return false; } // ------------------------------------------------------------------- if (extension == "mid" || extension == "midi") { if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "midifile", 0, nullptr)) { if (CarlaPlugin* const plugin = getPlugin(curPluginId)) plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "file", filename, true); return true; } return false; } // ------------------------------------------------------------------- // ZynAddSubFX if (extension == "xmz" || extension == "xiz") { #ifdef HAVE_ZYN_DEPS CarlaString nicerName("Zyn - "); const std::size_t sep(baseName.find('-')+1); if (sep < baseName.length()) nicerName += baseName.buffer()+sep; else nicerName += baseName; //nicerName if (addPlugin(PLUGIN_INTERNAL, nullptr, nicerName, "zynaddsubfx", 0, nullptr)) { callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, curPluginId, 0, 0, 0, 0.0f, nullptr); if (CarlaPlugin* const plugin = getPlugin(curPluginId)) plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, (extension == "xmz") ? "CarlaAlternateFile1" : "CarlaAlternateFile2", filename, true); return true; } return false; #else setLastError("This Carla build does not have ZynAddSubFX support"); return false; #endif } // ------------------------------------------------------------------- // Direct plugin binaries #ifdef CARLA_OS_MAC if (extension == "vst") return addPlugin(PLUGIN_VST2, filename, nullptr, nullptr, 0, nullptr); #else if (extension == "dll" || extension == "so") return addPlugin(getBinaryTypeFromFile(filename), PLUGIN_VST2, filename, nullptr, nullptr, 0, nullptr); #endif #if defined(USING_JUCE) && (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) if (extension == "vst3") return addPlugin(getBinaryTypeFromFile(filename), PLUGIN_VST3, filename, nullptr, nullptr, 0, nullptr); #endif // ------------------------------------------------------------------- setLastError("Unknown file extension"); return false; } bool CarlaEngine::loadProject(const char* const filename, const bool setAsCurrentProject) { CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish"); CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename"); carla_debug("CarlaEngine::loadProject(\"%s\")", filename); const String jfilename = String(CharPointer_UTF8(filename)); File file(jfilename); CARLA_SAFE_ASSERT_RETURN_ERR(file.existsAsFile(), "Requested file does not exist or is not a readable file"); if (setAsCurrentProject) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->currentProjectFilename = filename; #endif } XmlDocument xml(file); return loadProjectInternal(xml); } bool CarlaEngine::saveProject(const char* const filename, const bool setAsCurrentProject) { CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename"); carla_debug("CarlaEngine::saveProject(\"%s\")", filename); MemoryOutputStream out; saveProjectInternal(out); const String jfilename = String(CharPointer_UTF8(filename)); File file(jfilename); if (setAsCurrentProject) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->currentProjectFilename = filename; #endif } if (file.replaceWithData(out.getData(), out.getDataSize())) return true; setLastError("Failed to write file"); return false; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH const char* CarlaEngine::getCurrentProjectFilename() const noexcept { return pData->currentProjectFilename; } void CarlaEngine::clearCurrentProjectFilename() noexcept { pData->currentProjectFilename.clear(); } #endif // ----------------------------------------------------------------------- // Information (base) uint32_t CarlaEngine::getBufferSize() const noexcept { return pData->bufferSize; } double CarlaEngine::getSampleRate() const noexcept { return pData->sampleRate; } const char* CarlaEngine::getName() const noexcept { return pData->name; } EngineProcessMode CarlaEngine::getProccessMode() const noexcept { return pData->options.processMode; } const EngineOptions& CarlaEngine::getOptions() const noexcept { return pData->options; } EngineTimeInfo CarlaEngine::getTimeInfo() const noexcept { return pData->timeInfo; } // ----------------------------------------------------------------------- // Information (peaks) const float* CarlaEngine::getPeaks(const uint pluginId) const noexcept { static const float kFallback[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; if (pluginId == MAIN_CARLA_PLUGIN_ID) { // get peak from first plugin, if available if (const uint count = pData->curPluginCount) { pData->peaks[0] = pData->plugins[0].peaks[0]; pData->peaks[1] = pData->plugins[0].peaks[1]; pData->peaks[2] = pData->plugins[count-1].peaks[2]; pData->peaks[3] = pData->plugins[count-1].peaks[3]; } else { carla_zeroFloats(pData->peaks, 4); } return pData->peaks; } CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, kFallback); return pData->plugins[pluginId].peaks; } float CarlaEngine::getInputPeak(const uint pluginId, const bool isLeft) const noexcept { if (pluginId == MAIN_CARLA_PLUGIN_ID) { // get peak from first plugin, if available if (pData->curPluginCount > 0) return pData->plugins[0].peaks[isLeft ? 0 : 1]; return 0.0f; } CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, 0.0f); return pData->plugins[pluginId].peaks[isLeft ? 0 : 1]; } float CarlaEngine::getOutputPeak(const uint pluginId, const bool isLeft) const noexcept { if (pluginId == MAIN_CARLA_PLUGIN_ID) { // get peak from last plugin, if available if (pData->curPluginCount > 0) return pData->plugins[pData->curPluginCount-1].peaks[isLeft ? 2 : 3]; return 0.0f; } CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, 0.0f); return pData->plugins[pluginId].peaks[isLeft ? 2 : 3]; } // ----------------------------------------------------------------------- // Callback void CarlaEngine::callback(const bool sendHost, const bool sendOSC, const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const int value3, const float valuef, const char* const valueStr) noexcept { #ifdef DEBUG if (pData->isIdling) carla_stdout("CarlaEngine::callback [while idling] (%i:%s, %i, %i, %i, %i, %f, \"%s\")", action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3, static_cast(valuef), valueStr); else if (action != ENGINE_CALLBACK_IDLE && action != ENGINE_CALLBACK_NOTE_ON && action != ENGINE_CALLBACK_NOTE_OFF) carla_debug("CarlaEngine::callback(%i:%s, %i, %i, %i, %i, %f, \"%s\")", action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3, static_cast(valuef), valueStr); #endif if (sendHost && pData->callback != nullptr) { if (action == ENGINE_CALLBACK_IDLE) ++pData->isIdling; try { pData->callback(pData->callbackPtr, action, pluginId, value1, value2, value3, valuef, valueStr); #if defined(CARLA_OS_LINUX) && defined(__arm__) } catch (__cxxabiv1::__forced_unwind&) { carla_stderr2("Caught forced unwind exception in callback"); throw; #endif } catch (...) { carla_safe_exception("callback", __FILE__, __LINE__); } if (action == ENGINE_CALLBACK_IDLE) --pData->isIdling; } if (sendOSC) { #if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) if (pData->osc.isControlRegisteredForTCP()) { switch (action) { case ENGINE_CALLBACK_RELOAD_INFO: { CarlaPlugin* const plugin = pData->plugins[pluginId].plugin; CARLA_SAFE_ASSERT_BREAK(plugin != nullptr); pData->osc.sendPluginInfo(plugin); break; } case ENGINE_CALLBACK_RELOAD_PARAMETERS: { CarlaPlugin* const plugin = pData->plugins[pluginId].plugin; CARLA_SAFE_ASSERT_BREAK(plugin != nullptr); pData->osc.sendPluginPortCount(plugin); if (const uint32_t count = plugin->getParameterCount()) { for (uint32_t i=0; iosc.sendPluginParameterInfo(plugin, i); } break; } case ENGINE_CALLBACK_RELOAD_PROGRAMS: { CarlaPlugin* const plugin = pData->plugins[pluginId].plugin; CARLA_SAFE_ASSERT_BREAK(plugin != nullptr); pData->osc.sendPluginProgramCount(plugin); if (const uint32_t count = plugin->getProgramCount()) { for (uint32_t i=0; iosc.sendPluginProgram(plugin, i); } if (const uint32_t count = plugin->getMidiProgramCount()) { for (uint32_t i=0; iosc.sendPluginMidiProgram(plugin, i); } break; } case ENGINE_CALLBACK_PLUGIN_ADDED: case ENGINE_CALLBACK_RELOAD_ALL: { CarlaPlugin* const plugin = pData->plugins[pluginId].plugin; CARLA_SAFE_ASSERT_BREAK(plugin != nullptr); pData->osc.sendPluginInfo(plugin); pData->osc.sendPluginPortCount(plugin); pData->osc.sendPluginDataCount(plugin); if (const uint32_t count = plugin->getParameterCount()) { for (uint32_t i=0; iosc.sendPluginParameterInfo(plugin, i); } if (const uint32_t count = plugin->getProgramCount()) { for (uint32_t i=0; iosc.sendPluginProgram(plugin, i); } if (const uint32_t count = plugin->getMidiProgramCount()) { for (uint32_t i=0; iosc.sendPluginMidiProgram(plugin, i); } if (const uint32_t count = plugin->getCustomDataCount()) { for (uint32_t i=0; iosc.sendPluginCustomData(plugin, i); } pData->osc.sendPluginInternalParameterValues(plugin); break; } case ENGINE_CALLBACK_IDLE: return; default: break; } pData->osc.sendCallback(action, pluginId, value1, value2, value3, valuef, valueStr); } #endif } } void CarlaEngine::setCallback(const EngineCallbackFunc func, void* const ptr) noexcept { carla_debug("CarlaEngine::setCallback(%p, %p)", func, ptr); pData->callback = func; pData->callbackPtr = ptr; } // ----------------------------------------------------------------------- // File Callback const char* CarlaEngine::runFileCallback(const FileCallbackOpcode action, const bool isDir, const char* const title, const char* const filter) noexcept { CARLA_SAFE_ASSERT_RETURN(title != nullptr && title[0] != '\0', nullptr); CARLA_SAFE_ASSERT_RETURN(filter != nullptr, nullptr); carla_debug("CarlaEngine::runFileCallback(%i:%s, %s, \"%s\", \"%s\")", action, FileCallbackOpcode2Str(action), bool2str(isDir), title, filter); const char* ret = nullptr; if (pData->fileCallback != nullptr) { try { ret = pData->fileCallback(pData->fileCallbackPtr, action, isDir, title, filter); } CARLA_SAFE_EXCEPTION("runFileCallback"); } return ret; } void CarlaEngine::setFileCallback(const FileCallbackFunc func, void* const ptr) noexcept { carla_debug("CarlaEngine::setFileCallback(%p, %p)", func, ptr); pData->fileCallback = func; pData->fileCallbackPtr = ptr; } // ----------------------------------------------------------------------- // Transport void CarlaEngine::transportPlay() noexcept { pData->timeInfo.playing = true; pData->time.setNeedsReset(); } void CarlaEngine::transportPause() noexcept { if (pData->timeInfo.playing) pData->time.pause(); else pData->time.setNeedsReset(); } void CarlaEngine::transportBPM(const double bpm) noexcept { CARLA_SAFE_ASSERT_RETURN(bpm >= 20.0,) try { pData->time.setBPM(bpm); } CARLA_SAFE_EXCEPTION("CarlaEngine::transportBPM"); } void CarlaEngine::transportRelocate(const uint64_t frame) noexcept { pData->time.relocate(frame); } // ----------------------------------------------------------------------- // Error handling const char* CarlaEngine::getLastError() const noexcept { return pData->lastError; } void CarlaEngine::setLastError(const char* const error) const noexcept { pData->lastError = error; } // ----------------------------------------------------------------------- // Misc bool CarlaEngine::isAboutToClose() const noexcept { return pData->aboutToClose; } bool CarlaEngine::setAboutToClose() noexcept { carla_debug("CarlaEngine::setAboutToClose()"); pData->aboutToClose = true; return (pData->isIdling == 0); } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH bool CarlaEngine::isLoadingProject() const noexcept { return pData->loadingProject; } #endif void CarlaEngine::setActionCanceled(const bool canceled) noexcept { pData->actionCanceled = canceled; } bool CarlaEngine::wasActionCanceled() const noexcept { return pData->actionCanceled; } // ----------------------------------------------------------------------- // Global options void CarlaEngine::setOption(const EngineOption option, const int value, const char* const valueStr) noexcept { carla_debug("CarlaEngine::setOption(%i:%s, %i, \"%s\")", option, EngineOption2Str(option), value, valueStr); if (isRunning()) { switch (option) { case ENGINE_OPTION_PROCESS_MODE: case ENGINE_OPTION_AUDIO_TRIPLE_BUFFER: case ENGINE_OPTION_AUDIO_DRIVER: case ENGINE_OPTION_AUDIO_DEVICE: return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Cannot set this option while engine is running!", option, EngineOption2Str(option), value, valueStr); default: break; } } // do not un-force stereo for rack mode if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK && option == ENGINE_OPTION_FORCE_STEREO && value != 0) return; switch (option) { case ENGINE_OPTION_DEBUG: break; case ENGINE_OPTION_PROCESS_MODE: CARLA_SAFE_ASSERT_RETURN(value >= ENGINE_PROCESS_MODE_SINGLE_CLIENT && value <= ENGINE_PROCESS_MODE_BRIDGE,); pData->options.processMode = static_cast(value); break; case ENGINE_OPTION_TRANSPORT_MODE: CARLA_SAFE_ASSERT_RETURN(value >= ENGINE_TRANSPORT_MODE_DISABLED && value <= ENGINE_TRANSPORT_MODE_BRIDGE,); CARLA_SAFE_ASSERT_RETURN(getType() == kEngineTypeJack || value != ENGINE_TRANSPORT_MODE_JACK,); pData->options.transportMode = static_cast(value); delete[] pData->options.transportExtra; if (value >= ENGINE_TRANSPORT_MODE_DISABLED && valueStr != nullptr) pData->options.transportExtra = carla_strdup_safe(valueStr); else pData->options.transportExtra = nullptr; pData->time.setNeedsReset(); #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE) // enable link now if needed { const bool linkEnabled = pData->options.transportExtra != nullptr && std::strstr(pData->options.transportExtra, ":link:") != nullptr; pData->time.enableLink(linkEnabled); } #endif break; case ENGINE_OPTION_FORCE_STEREO: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); pData->options.forceStereo = (value != 0); break; case ENGINE_OPTION_PREFER_PLUGIN_BRIDGES: #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT_RETURN(value == 0,); #else CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); #endif pData->options.preferPluginBridges = (value != 0); break; case ENGINE_OPTION_PREFER_UI_BRIDGES: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); pData->options.preferUiBridges = (value != 0); break; case ENGINE_OPTION_UIS_ALWAYS_ON_TOP: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); pData->options.uisAlwaysOnTop = (value != 0); break; case ENGINE_OPTION_MAX_PARAMETERS: CARLA_SAFE_ASSERT_RETURN(value >= 0,); pData->options.maxParameters = static_cast(value); break; case ENGINE_OPTION_RESET_XRUNS: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); pData->options.resetXruns = (value != 0); break; case ENGINE_OPTION_UI_BRIDGES_TIMEOUT: CARLA_SAFE_ASSERT_RETURN(value >= 0,); pData->options.uiBridgesTimeout = static_cast(value); break; case ENGINE_OPTION_AUDIO_BUFFER_SIZE: CARLA_SAFE_ASSERT_RETURN(value >= 8,); pData->options.audioBufferSize = static_cast(value); break; case ENGINE_OPTION_AUDIO_SAMPLE_RATE: CARLA_SAFE_ASSERT_RETURN(value >= 22050,); pData->options.audioSampleRate = static_cast(value); break; case ENGINE_OPTION_AUDIO_TRIPLE_BUFFER: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); pData->options.audioTripleBuffer = (value != 0); break; case ENGINE_OPTION_AUDIO_DRIVER: CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,); if (pData->options.audioDriver != nullptr) delete[] pData->options.audioDriver; pData->options.audioDriver = carla_strdup_safe(valueStr); break; case ENGINE_OPTION_AUDIO_DEVICE: CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,); if (pData->options.audioDevice != nullptr) delete[] pData->options.audioDevice; pData->options.audioDevice = carla_strdup_safe(valueStr); break; case ENGINE_OPTION_OSC_ENABLED: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); #ifndef BUILD_BRIDGE pData->options.oscEnabled = (value != 0); #endif break; case ENGINE_OPTION_OSC_PORT_TCP: CARLA_SAFE_ASSERT_RETURN(value <= 0 || value >= 1024,); #ifndef BUILD_BRIDGE pData->options.oscPortTCP = value; #endif break; case ENGINE_OPTION_OSC_PORT_UDP: CARLA_SAFE_ASSERT_RETURN(value <= 0 || value >= 1024,); #ifndef BUILD_BRIDGE pData->options.oscPortUDP = value; #endif break; case ENGINE_OPTION_FILE_PATH: CARLA_SAFE_ASSERT_RETURN(value > FILE_NONE,); CARLA_SAFE_ASSERT_RETURN(value <= FILE_MIDI,); switch (value) { case FILE_AUDIO: if (pData->options.pathAudio != nullptr) delete[] pData->options.pathAudio; if (valueStr != nullptr) pData->options.pathAudio = carla_strdup_safe(valueStr); else pData->options.pathAudio = nullptr; break; case FILE_MIDI: if (pData->options.pathMIDI != nullptr) delete[] pData->options.pathMIDI; if (valueStr != nullptr) pData->options.pathMIDI = carla_strdup_safe(valueStr); else pData->options.pathMIDI = nullptr; break; default: return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Invalid file type", option, EngineOption2Str(option), value, valueStr); break; } break; case ENGINE_OPTION_PLUGIN_PATH: CARLA_SAFE_ASSERT_RETURN(value > PLUGIN_NONE,); CARLA_SAFE_ASSERT_RETURN(value <= PLUGIN_SFZ,); switch (value) { case PLUGIN_LADSPA: if (pData->options.pathLADSPA != nullptr) delete[] pData->options.pathLADSPA; if (valueStr != nullptr) pData->options.pathLADSPA = carla_strdup_safe(valueStr); else pData->options.pathLADSPA = nullptr; break; case PLUGIN_DSSI: if (pData->options.pathDSSI != nullptr) delete[] pData->options.pathDSSI; if (valueStr != nullptr) pData->options.pathDSSI = carla_strdup_safe(valueStr); else pData->options.pathDSSI = nullptr; break; case PLUGIN_LV2: if (pData->options.pathLV2 != nullptr) delete[] pData->options.pathLV2; if (valueStr != nullptr) pData->options.pathLV2 = carla_strdup_safe(valueStr); else pData->options.pathLV2 = nullptr; break; case PLUGIN_VST2: if (pData->options.pathVST2 != nullptr) delete[] pData->options.pathVST2; if (valueStr != nullptr) pData->options.pathVST2 = carla_strdup_safe(valueStr); else pData->options.pathVST2 = nullptr; break; case PLUGIN_VST3: if (pData->options.pathVST3 != nullptr) delete[] pData->options.pathVST3; if (valueStr != nullptr) pData->options.pathVST3 = carla_strdup_safe(valueStr); else pData->options.pathVST3 = nullptr; break; case PLUGIN_SF2: if (pData->options.pathSF2 != nullptr) delete[] pData->options.pathSF2; if (valueStr != nullptr) pData->options.pathSF2 = carla_strdup_safe(valueStr); else pData->options.pathSF2 = nullptr; break; case PLUGIN_SFZ: if (pData->options.pathSFZ != nullptr) delete[] pData->options.pathSFZ; if (valueStr != nullptr) pData->options.pathSFZ = carla_strdup_safe(valueStr); else pData->options.pathSFZ = nullptr; break; default: return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Invalid plugin type", option, EngineOption2Str(option), value, valueStr); break; } break; case ENGINE_OPTION_PATH_BINARIES: CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); if (pData->options.binaryDir != nullptr) delete[] pData->options.binaryDir; pData->options.binaryDir = carla_strdup_safe(valueStr); break; case ENGINE_OPTION_PATH_RESOURCES: CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); if (pData->options.resourceDir != nullptr) delete[] pData->options.resourceDir; pData->options.resourceDir = carla_strdup_safe(valueStr); break; case ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR: { CARLA_SAFE_ASSERT_RETURN(pData->options.binaryDir != nullptr && pData->options.binaryDir[0] != '\0',); #ifdef CARLA_OS_LINUX const ScopedEngineEnvironmentLocker _seel(this); if (value != 0) { CarlaString interposerPath(CarlaString(pData->options.binaryDir) + "/libcarla_interposer-safe.so"); ::setenv("LD_PRELOAD", interposerPath.buffer(), 1); } else { ::unsetenv("LD_PRELOAD"); } #endif } break; case ENGINE_OPTION_FRONTEND_BACKGROUND_COLOR: pData->options.bgColor = static_cast(value); break; case ENGINE_OPTION_FRONTEND_FOREGROUND_COLOR: pData->options.fgColor = static_cast(value); break; case ENGINE_OPTION_FRONTEND_UI_SCALE: CARLA_SAFE_ASSERT_RETURN(value > 0,); pData->options.uiScale = static_cast(value) / 1000; break; case ENGINE_OPTION_FRONTEND_WIN_ID: { CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); const long long winId(std::strtoll(valueStr, nullptr, 16)); CARLA_SAFE_ASSERT_RETURN(winId >= 0,); pData->options.frontendWinId = static_cast(winId); } break; #if !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH) && !defined(CARLA_OS_WIN) case ENGINE_OPTION_WINE_EXECUTABLE: CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); if (pData->options.wine.executable != nullptr) delete[] pData->options.wine.executable; pData->options.wine.executable = carla_strdup_safe(valueStr); break; case ENGINE_OPTION_WINE_AUTO_PREFIX: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); pData->options.wine.autoPrefix = (value != 0); break; case ENGINE_OPTION_WINE_FALLBACK_PREFIX: CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); if (pData->options.wine.fallbackPrefix != nullptr) delete[] pData->options.wine.fallbackPrefix; pData->options.wine.fallbackPrefix = carla_strdup_safe(valueStr); break; case ENGINE_OPTION_WINE_RT_PRIO_ENABLED: CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); pData->options.wine.rtPrio = (value != 0); break; case ENGINE_OPTION_WINE_BASE_RT_PRIO: CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 89,); pData->options.wine.baseRtPrio = value; break; case ENGINE_OPTION_WINE_SERVER_RT_PRIO: CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 99,); pData->options.wine.serverRtPrio = value; break; #endif case ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT: break; } } #ifndef BUILD_BRIDGE // ----------------------------------------------------------------------- // OSC Stuff bool CarlaEngine::isOscControlRegistered() const noexcept { # ifdef HAVE_LIBLO return pData->osc.isControlRegisteredForTCP(); # else return false; # endif } const char* CarlaEngine::getOscServerPathTCP() const noexcept { # ifdef HAVE_LIBLO return pData->osc.getServerPathTCP(); # else return nullptr; # endif } const char* CarlaEngine::getOscServerPathUDP() const noexcept { # ifdef HAVE_LIBLO return pData->osc.getServerPathUDP(); # else return nullptr; # endif } #endif // ----------------------------------------------------------------------- // Internal stuff void CarlaEngine::bufferSizeChanged(const uint32_t newBufferSize) { carla_debug("CarlaEngine::bufferSizeChanged(%i)", newBufferSize); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { pData->graph.setBufferSize(newBufferSize); } #endif pData->time.updateAudioValues(newBufferSize, pData->sampleRate); for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin != nullptr && plugin->isEnabled()) { plugin->tryLock(true); plugin->bufferSizeChanged(newBufferSize); plugin->unlock(); } } callback(true, true, ENGINE_CALLBACK_BUFFER_SIZE_CHANGED, 0, static_cast(newBufferSize), 0, 0, 0.0f, nullptr); } void CarlaEngine::sampleRateChanged(const double newSampleRate) { carla_debug("CarlaEngine::sampleRateChanged(%g)", newSampleRate); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { pData->graph.setSampleRate(newSampleRate); } #endif pData->time.updateAudioValues(pData->bufferSize, newSampleRate); for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin != nullptr && plugin->isEnabled()) { plugin->tryLock(true); plugin->sampleRateChanged(newSampleRate); plugin->unlock(); } } callback(true, true, ENGINE_CALLBACK_SAMPLE_RATE_CHANGED, 0, 0, 0, 0, static_cast(newSampleRate), nullptr); } void CarlaEngine::offlineModeChanged(const bool isOfflineNow) { carla_debug("CarlaEngine::offlineModeChanged(%s)", bool2str(isOfflineNow)); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { pData->graph.setOffline(isOfflineNow); } #endif for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin != nullptr && plugin->isEnabled()) plugin->offlineModeChanged(isOfflineNow); } } void CarlaEngine::setPluginPeaksRT(const uint pluginId, float const inPeaks[2], float const outPeaks[2]) noexcept { EnginePluginData& pluginData(pData->plugins[pluginId]); pluginData.peaks[0] = inPeaks[0]; pluginData.peaks[1] = inPeaks[1]; pluginData.peaks[2] = outPeaks[0]; pluginData.peaks[3] = outPeaks[1]; } void CarlaEngine::saveProjectInternal(water::MemoryOutputStream& outStream) const { // send initial prepareForSave first, giving time for bridges to act for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin != nullptr && plugin->isEnabled()) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // deactivate bridge client-side ping check, since some plugins block during save if (plugin->getHints() & PLUGIN_IS_BRIDGE) plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "false", false); #endif plugin->prepareForSave(); } } outStream << "\n"; outStream << "\n"; outStream << "\n"; const bool isPlugin(getType() == kEngineTypePlugin); const EngineOptions& options(pData->options); { MemoryOutputStream outSettings(1024); outSettings << " \n"; outSettings << " " << bool2str(options.forceStereo) << "\n"; outSettings << " " << bool2str(options.preferPluginBridges) << "\n"; outSettings << " " << bool2str(options.preferUiBridges) << "\n"; outSettings << " " << bool2str(options.uisAlwaysOnTop) << "\n"; outSettings << " " << String(options.maxParameters) << "\n"; outSettings << " " << String(options.uiBridgesTimeout) << "\n"; if (isPlugin) { outSettings << " " << xmlSafeString(options.pathLADSPA, true) << "\n"; outSettings << " " << xmlSafeString(options.pathDSSI, true) << "\n"; outSettings << " " << xmlSafeString(options.pathLV2, true) << "\n"; outSettings << " " << xmlSafeString(options.pathVST2, true) << "\n"; outSettings << " " << xmlSafeString(options.pathVST3, true) << "\n"; outSettings << " " << xmlSafeString(options.pathSF2, true) << "\n"; outSettings << " " << xmlSafeString(options.pathSFZ, true) << "\n"; } outSettings << " \n"; outStream << outSettings; } if (pData->timeInfo.bbt.valid && ! isPlugin) { MemoryOutputStream outTransport(128); outTransport << "\n \n"; // outTransport << " " << pData->timeInfo.bbt.beatsPerBar << "\n"; outTransport << " " << pData->timeInfo.bbt.beatsPerMinute << "\n"; outTransport << " \n"; outStream << outTransport; } char strBuf[STR_MAX+1]; carla_zeroChars(strBuf, STR_MAX+1); for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin != nullptr && plugin->isEnabled()) { MemoryOutputStream outPlugin(4096), streamPlugin; plugin->getStateSave(false).dumpToMemoryStream(streamPlugin); outPlugin << "\n"; if (plugin->getRealName(strBuf)) outPlugin << " \n"; outPlugin << " \n"; outPlugin << streamPlugin; outPlugin << " \n"; outStream << outPlugin; } } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // tell bridges we're done saving for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin != nullptr && plugin->isEnabled() && (plugin->getHints() & PLUGIN_IS_BRIDGE) != 0) plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "true", false); } // save internal connections if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { if (const char* const* const patchbayConns = getPatchbayConnections(false)) { MemoryOutputStream outPatchbay(2048); outPatchbay << "\n \n"; for (int i=0; patchbayConns[i] != nullptr && patchbayConns[i+1] != nullptr; ++i, ++i ) { const char* const connSource(patchbayConns[i]); const char* const connTarget(patchbayConns[i+1]); CARLA_SAFE_ASSERT_CONTINUE(connSource != nullptr && connSource[0] != '\0'); CARLA_SAFE_ASSERT_CONTINUE(connTarget != nullptr && connTarget[0] != '\0'); outPatchbay << " \n"; outPatchbay << " " << xmlSafeString(connSource, true) << "\n"; outPatchbay << " " << xmlSafeString(connTarget, true) << "\n"; outPatchbay << " \n"; } outPatchbay << " \n"; outStream << outPatchbay; } } // if we're running inside some session-manager (and using JACK), let them handle the connections bool saveExternalConnections; /**/ if (isPlugin) saveExternalConnections = false; else if (std::strcmp(getCurrentDriverName(), "JACK") != 0) saveExternalConnections = true; else if (std::getenv("CARLA_DONT_MANAGE_CONNECTIONS") != nullptr) saveExternalConnections = false; else if (std::getenv("LADISH_APP_NAME") != nullptr) saveExternalConnections = false; else if (std::getenv("NSM_URL") != nullptr) saveExternalConnections = false; else saveExternalConnections = true; if (saveExternalConnections) { if (const char* const* const patchbayConns = getPatchbayConnections(true)) { MemoryOutputStream outPatchbay(2048); outPatchbay << "\n \n"; for (int i=0; patchbayConns[i] != nullptr && patchbayConns[i+1] != nullptr; ++i, ++i ) { const char* const connSource(patchbayConns[i]); const char* const connTarget(patchbayConns[i+1]); CARLA_SAFE_ASSERT_CONTINUE(connSource != nullptr && connSource[0] != '\0'); CARLA_SAFE_ASSERT_CONTINUE(connTarget != nullptr && connTarget[0] != '\0'); outPatchbay << " \n"; outPatchbay << " " << xmlSafeString(connSource, true) << "\n"; outPatchbay << " " << xmlSafeString(connTarget, true) << "\n"; outPatchbay << " \n"; } outPatchbay << " \n"; outStream << outPatchbay; } } #endif outStream << "\n"; } static String findBinaryInCustomPath(const char* const searchPath, const char* const binary) { const StringArray searchPaths(StringArray::fromTokens(searchPath, CARLA_OS_SPLIT_STR, "")); // try direct filename first String jbinary(binary); // adjust for current platform #ifdef CARLA_OS_WIN if (jbinary[0] == '/') jbinary = "C:" + jbinary.replaceCharacter('/', '\\'); #else if (jbinary[1] == ':' && (jbinary[2] == '\\' || jbinary[2] == '/')) jbinary = jbinary.substring(2).replaceCharacter('\\', '/'); #endif String filename = File(jbinary).getFileName(); int searchFlags = File::findFiles|File::ignoreHiddenFiles; #ifdef CARLA_OS_MAC if (filename.endsWithIgnoreCase(".vst") || filename.endsWithIgnoreCase(".vst3")) searchFlags |= File::findDirectories; #endif Array results; for (const String *it=searchPaths.begin(), *end=searchPaths.end(); it != end; ++it) { const File path(*it); results.clear(); path.findChildFiles(results, searchFlags, true, filename); if (results.size() > 0) return results.getFirst().getFullPathName(); } // try changing extension #if defined(CARLA_OS_MAC) if (filename.endsWithIgnoreCase(".dll") || filename.endsWithIgnoreCase(".so")) filename = File(jbinary).getFileNameWithoutExtension() + ".dylib"; #elif defined(CARLA_OS_WIN) if (filename.endsWithIgnoreCase(".dylib") || filename.endsWithIgnoreCase(".so")) filename = File(jbinary).getFileNameWithoutExtension() + ".dll"; #else if (filename.endsWithIgnoreCase(".dll") || filename.endsWithIgnoreCase(".dylib")) filename = File(jbinary).getFileNameWithoutExtension() + ".so"; #endif else return String(); for (const String *it=searchPaths.begin(), *end=searchPaths.end(); it != end; ++it) { const File path(*it); results.clear(); path.findChildFiles(results, searchFlags, true, filename); if (results.size() > 0) return results.getFirst().getFullPathName(); } return String(); } bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc) { CarlaScopedPointer xmlElement(xmlDoc.getDocumentElement(true)); CARLA_SAFE_ASSERT_RETURN_ERR(xmlElement != nullptr, "Failed to parse project file"); const String& xmlType(xmlElement->getTagName()); const bool isPreset(xmlType.equalsIgnoreCase("carla-preset")); if (! (xmlType.equalsIgnoreCase("carla-project") || isPreset)) { callback(true, true, ENGINE_CALLBACK_PROJECT_LOAD_FINISHED, 0, 0, 0, 0, 0.0f, nullptr); setLastError("Not a valid Carla project or preset file"); return false; } pData->actionCanceled = false; callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, 0, 1, 0, 0, 0.0f, "Loading project"); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH const CarlaScopedValueSetter csvs(pData->loadingProject, true, false); #endif // completely load file xmlElement = xmlDoc.getDocumentElement(false); CARLA_SAFE_ASSERT_RETURN_ERR(xmlElement != nullptr, "Failed to completely parse project file"); callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (pData->aboutToClose) return true; if (pData->actionCanceled) { setLastError("Project load canceled"); return false; } const bool isPlugin(getType() == kEngineTypePlugin); // load engine settings first of all if (XmlElement* const elem = isPreset ? nullptr : xmlElement->getChildByName("EngineSettings")) { for (XmlElement* settElem = elem->getFirstChildElement(); settElem != nullptr; settElem = settElem->getNextElement()) { const String& tag(settElem->getTagName()); const String text(settElem->getAllSubText().trim()); /** some settings might be incorrect or require extra work, so we call setOption rather than modifying them direly */ int option = -1; int value = 0; const char* valueStr = nullptr; /**/ if (tag == "ForceStereo") { option = ENGINE_OPTION_FORCE_STEREO; value = text == "true" ? 1 : 0; } else if (tag == "PreferPluginBridges") { option = ENGINE_OPTION_PREFER_PLUGIN_BRIDGES; value = text == "true" ? 1 : 0; } else if (tag == "PreferUiBridges") { option = ENGINE_OPTION_PREFER_UI_BRIDGES; value = text == "true" ? 1 : 0; } else if (tag == "UIsAlwaysOnTop") { option = ENGINE_OPTION_UIS_ALWAYS_ON_TOP; value = text == "true" ? 1 : 0; } else if (tag == "MaxParameters") { option = ENGINE_OPTION_MAX_PARAMETERS; value = text.getIntValue(); } else if (tag == "UIBridgesTimeout") { option = ENGINE_OPTION_UI_BRIDGES_TIMEOUT; value = text.getIntValue(); } else if (isPlugin) { /**/ if (tag == "LADSPA_PATH") { option = ENGINE_OPTION_PLUGIN_PATH; value = PLUGIN_LADSPA; valueStr = text.toRawUTF8(); } else if (tag == "DSSI_PATH") { option = ENGINE_OPTION_PLUGIN_PATH; value = PLUGIN_DSSI; valueStr = text.toRawUTF8(); } else if (tag == "LV2_PATH") { option = ENGINE_OPTION_PLUGIN_PATH; value = PLUGIN_LV2; valueStr = text.toRawUTF8(); } else if (tag == "VST2_PATH") { option = ENGINE_OPTION_PLUGIN_PATH; value = PLUGIN_VST2; valueStr = text.toRawUTF8(); } else if (tag.equalsIgnoreCase("VST3_PATH")) { option = ENGINE_OPTION_PLUGIN_PATH; value = PLUGIN_VST3; valueStr = text.toRawUTF8(); } else if (tag == "SF2_PATH") { option = ENGINE_OPTION_PLUGIN_PATH; value = PLUGIN_SF2; valueStr = text.toRawUTF8(); } else if (tag == "SFZ_PATH") { option = ENGINE_OPTION_PLUGIN_PATH; value = PLUGIN_SFZ; valueStr = text.toRawUTF8(); } } if (option == -1) { // check old stuff, unhandled now if (tag == "GIG_PATH") continue; // ignored tags if (tag == "LADSPA_PATH" || tag == "DSSI_PATH" || tag == "LV2_PATH" || tag == "VST2_PATH") continue; if (tag == "VST3_PATH" || tag == "AU_PATH") continue; if (tag == "SF2_PATH" || tag == "SFZ_PATH") continue; // hmm something is wrong.. carla_stderr2("CarlaEngine::loadProjectInternal() - Unhandled option '%s'", tag.toRawUTF8()); continue; } setOption(static_cast(option), value, valueStr); } callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (pData->aboutToClose) return true; if (pData->actionCanceled) { setLastError("Project load canceled"); return false; } } // now setup transport if (XmlElement* const elem = (isPreset || isPlugin) ? nullptr : xmlElement->getChildByName("Transport")) { if (XmlElement* const bpmElem = elem->getChildByName("BeatsPerMinute")) { const String bpmText(bpmElem->getAllSubText().trim()); const double bpm = bpmText.getDoubleValue(); // some sane limits if (bpm >= 20.0 && bpm < 400.0) pData->time.setBPM(bpm); callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (pData->aboutToClose) return true; if (pData->actionCanceled) { setLastError("Project load canceled"); return false; } } } // and we handle plugins for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement()) { const String& tagName(elem->getTagName()); if (isPreset || tagName == "Plugin") { CarlaStateSave stateSave; stateSave.fillFromXmlElement(isPreset ? xmlElement.get() : elem); callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (pData->aboutToClose) return true; if (pData->actionCanceled) { setLastError("Project load canceled"); return false; } CARLA_SAFE_ASSERT_CONTINUE(stateSave.type != nullptr); #ifndef BUILD_BRIDGE // compatibility code to load projects with GIG files // FIXME Remove on 2.1 release if (std::strcmp(stateSave.type, "GIG") == 0) { if (addPlugin(PLUGIN_LV2, "", stateSave.name, "http://linuxsampler.org/plugins/linuxsampler", 0, nullptr)) { const uint pluginId = pData->curPluginCount; if (CarlaPlugin* const plugin = pData->plugins[pluginId].plugin) { callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (pData->aboutToClose) return true; if (pData->actionCanceled) { setLastError("Project load canceled"); return false; } String lsState; lsState << "0.35\n"; lsState << "18 0 Chromatic\n"; lsState << "18 1 Drum Kits\n"; lsState << "20 0\n"; lsState << "0 1 " << stateSave.binary << "\n"; lsState << "0 0 0 0 1 0 GIG\n"; plugin->setCustomData(LV2_ATOM__String, "http://linuxsampler.org/schema#state-string", lsState.toRawUTF8(), true); plugin->restoreLV2State(); plugin->setDryWet(stateSave.dryWet, true, true); plugin->setVolume(stateSave.volume, true, true); plugin->setBalanceLeft(stateSave.balanceLeft, true, true); plugin->setBalanceRight(stateSave.balanceRight, true, true); plugin->setPanning(stateSave.panning, true, true); plugin->setCtrlChannel(stateSave.ctrlChannel, true, true); plugin->setActive(stateSave.active, true, true); plugin->setEnabled(true); ++pData->curPluginCount; callback(true, true, ENGINE_CALLBACK_PLUGIN_ADDED, pluginId, 0, 0, 0, 0.0f, plugin->getName()); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) pData->graph.addPlugin(plugin); } else { carla_stderr2("Failed to get new plugin, state will not be restored correctly\n"); } } else { carla_stderr2("Failed to load a linuxsampler LV2 plugin, GIG file won't be loaded"); } continue; } #endif const void* extraStuff = nullptr; static const char kTrue[] = "true"; const PluginType ptype(getPluginTypeFromString(stateSave.type)); switch (ptype) { case PLUGIN_SF2: if (CarlaString(stateSave.label).endsWith(" (16 outs)")) extraStuff = kTrue; // fall through case PLUGIN_LADSPA: case PLUGIN_DSSI: case PLUGIN_VST2: case PLUGIN_VST3: case PLUGIN_SFZ: if (stateSave.binary != nullptr && stateSave.binary[0] != '\0' && ! (File::isAbsolutePath(stateSave.binary) && File(stateSave.binary).exists())) { const char* searchPath; switch (ptype) { case PLUGIN_LADSPA: searchPath = pData->options.pathLADSPA; break; case PLUGIN_DSSI: searchPath = pData->options.pathDSSI; break; case PLUGIN_VST2: searchPath = pData->options.pathVST2; break; case PLUGIN_VST3: searchPath = pData->options.pathVST3; break; case PLUGIN_SF2: searchPath = pData->options.pathSF2; break; case PLUGIN_SFZ: searchPath = pData->options.pathSFZ; break; default: searchPath = nullptr; break; } if (searchPath != nullptr && searchPath[0] != '\0') { carla_stderr("Plugin binary '%s' doesn't exist on this filesystem, let's look for it...", stateSave.binary); String result = findBinaryInCustomPath(searchPath, stateSave.binary); if (result.isEmpty()) { switch (ptype) { case PLUGIN_LADSPA: searchPath = std::getenv("LADSPA_PATH"); break; case PLUGIN_DSSI: searchPath = std::getenv("DSSI_PATH"); break; case PLUGIN_VST2: searchPath = std::getenv("VST_PATH"); break; case PLUGIN_VST3: searchPath = std::getenv("VST3_PATH"); break; case PLUGIN_SF2: searchPath = std::getenv("SF2_PATH"); break; case PLUGIN_SFZ: searchPath = std::getenv("SFZ_PATH"); break; default: searchPath = nullptr; break; } if (searchPath != nullptr && searchPath[0] != '\0') result = findBinaryInCustomPath(searchPath, stateSave.binary); } if (result.isNotEmpty()) { delete[] stateSave.binary; stateSave.binary = carla_strdup(result.toRawUTF8()); carla_stderr("Found it! :)"); } else { carla_stderr("Damn, we failed... :("); } } } break; default: break; } BinaryType btype; switch (ptype) { case PLUGIN_LADSPA: case PLUGIN_DSSI: case PLUGIN_LV2: case PLUGIN_VST2: btype = getBinaryTypeFromFile(stateSave.binary); break; default: btype = BINARY_NATIVE; break; } if (addPlugin(btype, ptype, stateSave.binary, stateSave.name, stateSave.label, stateSave.uniqueId, extraStuff, stateSave.options)) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH const uint pluginId = pData->curPluginCount; #else const uint pluginId = 0; #endif if (CarlaPlugin* const plugin = pData->plugins[pluginId].plugin) { callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (pData->aboutToClose) return true; if (pData->actionCanceled) { setLastError("Project load canceled"); return false; } // deactivate bridge client-side ping check, since some plugins block during load if ((plugin->getHints() & PLUGIN_IS_BRIDGE) != 0 && ! isPreset) plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "false", false); plugin->loadStateSave(stateSave); /* NOTE: The following code is the same as the end of addPlugin(). * When project is loading we do not enable the plugin right away, * as we want to load state first. */ plugin->setEnabled(true); ++pData->curPluginCount; callback(true, true, ENGINE_CALLBACK_PLUGIN_ADDED, pluginId, 0, 0, 0, 0.0f, plugin->getName()); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) pData->graph.addPlugin(plugin); #endif } else { carla_stderr2("Failed to get new plugin, state will not be restored correctly\n"); } } else { carla_stderr2("Failed to load a plugin '%s', error was:\n%s", stateSave.name, getLastError()); } } if (isPreset) { callback(true, true, ENGINE_CALLBACK_PROJECT_LOAD_FINISHED, 0, 0, 0, 0, 0.0f, nullptr); callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, 0, 0, 0, 0, 0.0f, "Loading project"); return true; } } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // tell bridges we're done loading for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin != nullptr && plugin->isEnabled() && (plugin->getHints() & PLUGIN_IS_BRIDGE) != 0) plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "true", false); } callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (pData->aboutToClose) return true; if (pData->actionCanceled) { setLastError("Project load canceled"); return false; } bool hasInternalConnections = false; // and now we handle connections (internal) if (XmlElement* const elem = xmlElement->getChildByName("Patchbay")) { hasInternalConnections = true; if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { CarlaString sourcePort, targetPort; for (XmlElement* patchElem = elem->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement()) { const String& patchTag(patchElem->getTagName()); if (patchTag != "Connection") continue; sourcePort.clear(); targetPort.clear(); for (XmlElement* connElem = patchElem->getFirstChildElement(); connElem != nullptr; connElem = connElem->getNextElement()) { const String& tag(connElem->getTagName()); const String text(connElem->getAllSubText().trim()); /**/ if (tag == "Source") sourcePort = xmlSafeString(text, false).toRawUTF8(); else if (tag == "Target") targetPort = xmlSafeString(text, false).toRawUTF8(); } if (sourcePort.isNotEmpty() && targetPort.isNotEmpty()) restorePatchbayConnection(false, sourcePort, targetPort); } callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (pData->aboutToClose) return true; if (pData->actionCanceled) { setLastError("Project load canceled"); return false; } } } // if we're running inside some session-manager (and using JACK), let them handle the external connections bool loadExternalConnections; /**/ if (std::strcmp(getCurrentDriverName(), "JACK") != 0) loadExternalConnections = true; else if (std::getenv("CARLA_DONT_MANAGE_CONNECTIONS") != nullptr) loadExternalConnections = false; else if (std::getenv("LADISH_APP_NAME") != nullptr) loadExternalConnections = false; else if (std::getenv("NSM_URL") != nullptr) loadExternalConnections = false; else loadExternalConnections = true; // plus external connections too if (loadExternalConnections) { const bool loadingAsExternal = pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY && hasInternalConnections; for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement()) { const String& tagName(elem->getTagName()); // check if we want to load patchbay-mode connections into an external (multi-client) graph if (tagName == "Patchbay") { if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) continue; } // or load external patchbay connections else if (tagName != "ExternalPatchbay") { continue; } CarlaString sourcePort, targetPort; for (XmlElement* patchElem = elem->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement()) { const String& patchTag(patchElem->getTagName()); if (patchTag != "Connection") continue; sourcePort.clear(); targetPort.clear(); for (XmlElement* connElem = patchElem->getFirstChildElement(); connElem != nullptr; connElem = connElem->getNextElement()) { const String& tag(connElem->getTagName()); const String text(connElem->getAllSubText().trim()); /**/ if (tag == "Source") sourcePort = xmlSafeString(text, false).toRawUTF8(); else if (tag == "Target") targetPort = xmlSafeString(text, false).toRawUTF8(); } if (sourcePort.isNotEmpty() && targetPort.isNotEmpty()) restorePatchbayConnection(loadingAsExternal, sourcePort, targetPort); } break; } } #endif if (pData->options.resetXruns) clearXruns(); callback(true, true, ENGINE_CALLBACK_PROJECT_LOAD_FINISHED, 0, 0, 0, 0, 0.0f, nullptr); callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, 0, 0, 0, 0, 0.0f, "Loading project"); return true; } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/engine/CarlaEngineBridge.cpp000066400000000000000000001724511364475620200225460ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef BUILD_BRIDGE # error This file should not be compiled if not building bridge #endif #include "CarlaEngineClient.hpp" #include "CarlaPlugin.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaBase64Utils.hpp" #include "CarlaBridgeUtils.hpp" #include "CarlaMIDI.h" #ifdef __SSE2_MATH__ # include #endif #include "water/files/File.h" #include "water/misc/Time.h" // must be last #include "jackbridge/JackBridge.hpp" using water::File; using water::MemoryBlock; using water::String; using water::Time; CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // just want to access private options... struct CarlaPlugin::ProtectedData { CarlaEngine* const engine; CarlaEngineClient* client; uint id, hints, options; // ...etc }; // ----------------------------------------------------------------------- // Bridge Engine client struct LatencyChangedCallback { virtual ~LatencyChangedCallback() noexcept {} virtual void latencyChanged(const uint32_t samples) noexcept = 0; }; class CarlaEngineBridgeClient : public CarlaEngineClientForSubclassing { public: #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaEngineBridgeClient(const CarlaEngine& engine, EngineInternalGraph& egraph, CarlaPlugin* const plugin, LatencyChangedCallback* const cb) : CarlaEngineClientForSubclassing(engine, egraph, plugin), fLatencyCallback(cb) {} #else CarlaEngineBridgeClient(const CarlaEngine& engine, LatencyChangedCallback* const cb) : CarlaEngineClientForSubclassing(engine), fLatencyCallback(cb) {} #endif protected: void setLatency(const uint32_t samples) noexcept override { if (getLatency() == samples) return; fLatencyCallback->latencyChanged(samples); CarlaEngineClient::setLatency(samples); } private: LatencyChangedCallback* const fLatencyCallback; CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineBridgeClient) }; // ------------------------------------------------------------------- class CarlaEngineBridge : public CarlaEngine, private CarlaThread, private LatencyChangedCallback { public: CarlaEngineBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName) : CarlaEngine(), CarlaThread("CarlaEngineBridge"), fShmAudioPool(), fShmRtClientControl(), fShmNonRtClientControl(), fShmNonRtServerControl(), fBaseNameAudioPool(audioPoolBaseName), fBaseNameRtClientControl(rtClientBaseName), fBaseNameNonRtClientControl(nonRtClientBaseName), fBaseNameNonRtServerControl(nonRtServerBaseName), fClosingDown(false), fIsOffline(false), fFirstIdle(true), fLastPingTime(-1) { carla_debug("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); } ~CarlaEngineBridge() noexcept override { carla_debug("CarlaEngineBridge::~CarlaEngineBridge()"); clear(); } // ------------------------------------- // CarlaEngine virtual calls bool init(const char* const clientName) override { carla_debug("CarlaEngineBridge::init(\"%s\")", clientName); if (! pData->init(clientName)) { setLastError("Failed to init internal data"); return false; } if (! fShmAudioPool.attachClient(fBaseNameAudioPool)) { carla_stderr("Failed to attach to audio pool shared memory"); return false; } if (! fShmRtClientControl.attachClient(fBaseNameRtClientControl)) { clear(); carla_stderr("Failed to attach to rt client control shared memory"); return false; } if (! fShmRtClientControl.mapData()) { clear(); carla_stderr("Failed to map rt client control shared memory"); return false; } if (! fShmNonRtClientControl.attachClient(fBaseNameNonRtClientControl)) { clear(); carla_stderr("Failed to attach to non-rt client control shared memory"); return false; } if (! fShmNonRtClientControl.mapData()) { clear(); carla_stderr("Failed to map non-rt control client shared memory"); return false; } if (! fShmNonRtServerControl.attachClient(fBaseNameNonRtServerControl)) { clear(); carla_stderr("Failed to attach to non-rt server control shared memory"); return false; } if (! fShmNonRtServerControl.mapData()) { clear(); carla_stderr("Failed to map non-rt control server shared memory"); return false; } PluginBridgeNonRtClientOpcode opcode; opcode = fShmNonRtClientControl.readOpcode(); CARLA_SAFE_ASSERT_RETURN(opcode == kPluginBridgeNonRtClientVersion, false); const uint32_t apiVersion = fShmNonRtClientControl.readUInt(); CARLA_SAFE_ASSERT_RETURN(apiVersion >= CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM, false); const uint32_t shmRtClientDataSize = fShmNonRtClientControl.readUInt(); CARLA_SAFE_ASSERT_INT2(shmRtClientDataSize == sizeof(BridgeRtClientData), shmRtClientDataSize, sizeof(BridgeRtClientData)); const uint32_t shmNonRtClientDataSize = fShmNonRtClientControl.readUInt(); CARLA_SAFE_ASSERT_INT2(shmNonRtClientDataSize == sizeof(BridgeNonRtClientData), shmNonRtClientDataSize, sizeof(BridgeNonRtClientData)); const uint32_t shmNonRtServerDataSize = fShmNonRtClientControl.readUInt(); CARLA_SAFE_ASSERT_INT2(shmNonRtServerDataSize == sizeof(BridgeNonRtServerData), shmNonRtServerDataSize, sizeof(BridgeNonRtServerData)); if (shmRtClientDataSize != sizeof(BridgeRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtServerDataSize != sizeof(BridgeNonRtServerData)) { carla_stderr2("CarlaEngineBridge: data size mismatch"); return false; } opcode = fShmNonRtClientControl.readOpcode(); CARLA_SAFE_ASSERT_RETURN(opcode == kPluginBridgeNonRtClientInitialSetup, false); pData->bufferSize = fShmNonRtClientControl.readUInt(); pData->sampleRate = fShmNonRtClientControl.readDouble(); if (pData->bufferSize == 0 || carla_isZero(pData->sampleRate)) { carla_stderr2("CarlaEngineBridge: invalid empty state"); return false; } pData->initTime(nullptr); // tell backend we're live { const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); // kPluginBridgeNonRtServerVersion was added in API 7 if (apiVersion >= 7) { fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerVersion); fShmNonRtServerControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT); } else { fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong); } fShmNonRtServerControl.commitWrite(); } startThread(true); return true; } bool close() override { carla_debug("CarlaEngineBridge::close()"); fLastPingTime = -1; CarlaEngine::close(); stopThread(5000); clear(); return true; } bool isRunning() const noexcept override { if (fClosingDown) return false; return isThreadRunning() || ! fFirstIdle; } bool isOffline() const noexcept override { return fIsOffline; } EngineType getType() const noexcept override { return kEngineTypeBridge; } const char* getCurrentDriverName() const noexcept override { return "Bridge"; } void touchPluginParameter(const uint id, const uint32_t parameterId, const bool touch) noexcept override { CARLA_SAFE_ASSERT_RETURN(id == 0,); const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterTouch); fShmNonRtServerControl.writeUInt(parameterId); fShmNonRtServerControl.writeBool(touch); fShmNonRtServerControl.commitWrite(); } CarlaEngineClient* addClient(CarlaPlugin* const plugin) override { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH return new CarlaEngineBridgeClient(*this, pData->graph, plugin, this); #else return new CarlaEngineBridgeClient(*this, this); // unused (void)plugin; #endif } void idle() noexcept override { CarlaPlugin* const plugin(pData->plugins[0].plugin); if (plugin == nullptr) { if (const uint32_t length = static_cast(pData->lastError.length())) { const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerError); fShmNonRtServerControl.writeUInt(length); fShmNonRtServerControl.writeCustomData(pData->lastError.buffer(), length); fShmNonRtServerControl.commitWrite(); } signalThreadShouldExit(); callback(true, true, ENGINE_CALLBACK_QUIT, 0, 0, 0, 0, 0.0f, nullptr); return; } const bool wasFirstIdle(fFirstIdle); if (wasFirstIdle) { fFirstIdle = false; fLastPingTime = Time::currentTimeMillis(); CARLA_SAFE_ASSERT(fLastPingTime > 0); char bufStr[STR_MAX+1]; carla_zeroChars(bufStr, STR_MAX+1); uint32_t bufStrSize; const CarlaEngineClient* const client(plugin->getEngineClient()); const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); // kPluginBridgeNonRtServerPluginInfo1 { // uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPluginInfo1); fShmNonRtServerControl.writeUInt(plugin->getCategory()); fShmNonRtServerControl.writeUInt(plugin->getHints()); fShmNonRtServerControl.writeUInt(plugin->getOptionsAvailable()); fShmNonRtServerControl.writeUInt(plugin->getOptionsEnabled()); fShmNonRtServerControl.writeLong(plugin->getUniqueId()); fShmNonRtServerControl.commitWrite(); } // kPluginBridgeNonRtServerPluginInfo2 { // uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright) fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPluginInfo2); if (! plugin->getRealName(bufStr)) bufStr[0] = '\0'; bufStrSize = carla_fixedValue(1U, 64U, static_cast(std::strlen(bufStr))); fShmNonRtServerControl.writeUInt(bufStrSize); fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize); if (! plugin->getLabel(bufStr)) bufStr[0] = '\0'; bufStrSize = carla_fixedValue(1U, 256U, static_cast(std::strlen(bufStr))); fShmNonRtServerControl.writeUInt(bufStrSize); fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize); if (! plugin->getMaker(bufStr)) bufStr[0] = '\0'; bufStrSize = carla_fixedValue(1U, 64U, static_cast(std::strlen(bufStr))); fShmNonRtServerControl.writeUInt(bufStrSize); fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize); if (! plugin->getCopyright(bufStr)) bufStr[0] = '\0'; bufStrSize = carla_fixedValue(1U, 64U, static_cast(std::strlen(bufStr))); fShmNonRtServerControl.writeUInt(bufStrSize); fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize); fShmNonRtServerControl.commitWrite(); } // kPluginBridgeNonRtServerAudioCount { const uint32_t aIns = plugin->getAudioInCount(); const uint32_t aOuts = plugin->getAudioOutCount(); // uint/ins, uint/outs fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerAudioCount); fShmNonRtServerControl.writeUInt(aIns); fShmNonRtServerControl.writeUInt(aOuts); fShmNonRtServerControl.commitWrite(); // kPluginBridgeNonRtServerPortName for (uint32_t i=0; igetAudioPortName(true, i)); CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0'); // byte/type, uint/index, uint/size, str[] (name) fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPortName); fShmNonRtServerControl.writeByte(kPluginBridgePortAudioInput); fShmNonRtServerControl.writeUInt(i); bufStrSize = static_cast(std::strlen(portName)); fShmNonRtServerControl.writeUInt(bufStrSize); fShmNonRtServerControl.writeCustomData(portName, bufStrSize); } // kPluginBridgeNonRtServerPortName for (uint32_t i=0; igetAudioPortName(false, i)); CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0'); // byte/type, uint/index, uint/size, str[] (name) fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPortName); fShmNonRtServerControl.writeByte(kPluginBridgePortAudioOutput); fShmNonRtServerControl.writeUInt(i); bufStrSize = static_cast(std::strlen(portName)); fShmNonRtServerControl.writeUInt(bufStrSize); fShmNonRtServerControl.writeCustomData(portName, bufStrSize); } } fShmNonRtServerControl.waitIfDataIsReachingLimit(); // kPluginBridgeNonRtServerMidiCount { // uint/ins, uint/outs fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerMidiCount); fShmNonRtServerControl.writeUInt(plugin->getMidiInCount()); fShmNonRtServerControl.writeUInt(plugin->getMidiOutCount()); fShmNonRtServerControl.commitWrite(); } fShmNonRtServerControl.waitIfDataIsReachingLimit(); // kPluginBridgeNonRtServerCvCount { // uint/ins, uint/outs fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerCvCount); fShmNonRtServerControl.writeUInt(plugin->getCVInCount()); fShmNonRtServerControl.writeUInt(plugin->getCVOutCount()); fShmNonRtServerControl.commitWrite(); } fShmNonRtServerControl.waitIfDataIsReachingLimit(); // kPluginBridgeNonRtServerParameter* if (const uint32_t count = std::min(pData->options.maxParameters, plugin->getParameterCount())) { // uint/count fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterCount); fShmNonRtServerControl.writeUInt(count); fShmNonRtServerControl.commitWrite(); for (uint32_t i=0; igetParameterData(i)); if (paramData.type != PARAMETER_INPUT && paramData.type != PARAMETER_OUTPUT) continue; if ((paramData.hints & PARAMETER_IS_ENABLED) == 0) continue; // kPluginBridgeNonRtServerParameterData1 { // uint/index, int/rindex, uint/type, uint/hints, short/cc fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterData1); fShmNonRtServerControl.writeUInt(i); fShmNonRtServerControl.writeInt(paramData.rindex); fShmNonRtServerControl.writeUInt(paramData.type); fShmNonRtServerControl.writeUInt(paramData.hints); fShmNonRtServerControl.writeShort(paramData.mappedControlIndex); fShmNonRtServerControl.commitWrite(); } // kPluginBridgeNonRtServerParameterData2 { // uint/index, uint/size, str[] (name), uint/size, str[] (symbol), uint/size, str[] (unit) fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterData2); fShmNonRtServerControl.writeUInt(i); if (! plugin->getParameterName(i, bufStr)) std::snprintf(bufStr, STR_MAX, "Param %u", i+1); bufStrSize = carla_fixedValue(1U, 32U, static_cast(std::strlen(bufStr))); fShmNonRtServerControl.writeUInt(bufStrSize); fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize); if (! plugin->getParameterSymbol(i, bufStr)) bufStr[0] = '\0'; bufStrSize = carla_fixedValue(1U, 64U, static_cast(std::strlen(bufStr))); fShmNonRtServerControl.writeUInt(bufStrSize); fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize); if (! plugin->getParameterUnit(i, bufStr)) bufStr[0] = '\0'; bufStrSize = carla_fixedValue(1U, 32U, static_cast(std::strlen(bufStr))); fShmNonRtServerControl.writeUInt(bufStrSize); fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize); fShmNonRtServerControl.commitWrite(); } // kPluginBridgeNonRtServerParameterRanges { const ParameterRanges& paramRanges(plugin->getParameterRanges(i)); // uint/index, float/def, float/min, float/max, float/step, float/stepSmall, float/stepLarge fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterRanges); fShmNonRtServerControl.writeUInt(i); fShmNonRtServerControl.writeFloat(paramRanges.def); fShmNonRtServerControl.writeFloat(paramRanges.min); fShmNonRtServerControl.writeFloat(paramRanges.max); fShmNonRtServerControl.writeFloat(paramRanges.step); fShmNonRtServerControl.writeFloat(paramRanges.stepSmall); fShmNonRtServerControl.writeFloat(paramRanges.stepLarge); fShmNonRtServerControl.commitWrite(); } // kPluginBridgeNonRtServerParameterValue2 { // uint/index float/value (used for init/output parameters only, don't resend values) fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterValue2); fShmNonRtServerControl.writeUInt(i); fShmNonRtServerControl.writeFloat(plugin->getParameterValue(i)); fShmNonRtServerControl.commitWrite(); } fShmNonRtServerControl.waitIfDataIsReachingLimit(); } } // kPluginBridgeNonRtServerProgram* if (const uint32_t count = plugin->getProgramCount()) { // uint/count fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerProgramCount); fShmNonRtServerControl.writeUInt(count); fShmNonRtServerControl.commitWrite(); for (uint32_t i=0; i < count; ++i) { // uint/index, uint/size, str[] (name) fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerProgramName); fShmNonRtServerControl.writeUInt(i); if (! plugin->getProgramName(i, bufStr)) bufStr[0] = '\0'; bufStrSize = carla_fixedValue(1U, 32U, static_cast(std::strlen(bufStr))); fShmNonRtServerControl.writeUInt(bufStrSize); fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize); fShmNonRtServerControl.commitWrite(); fShmNonRtServerControl.waitIfDataIsReachingLimit(); } } // kPluginBridgeNonRtServerMidiProgram* if (const uint32_t count = plugin->getMidiProgramCount()) { // uint/count fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerMidiProgramCount); fShmNonRtServerControl.writeUInt(count); fShmNonRtServerControl.commitWrite(); for (uint32_t i=0; i < count; ++i) { const MidiProgramData& mpData(plugin->getMidiProgramData(i)); CARLA_SAFE_ASSERT_CONTINUE(mpData.name != nullptr); // uint/index, uint/bank, uint/program, uint/size, str[] (name) fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerMidiProgramData); fShmNonRtServerControl.writeUInt(i); fShmNonRtServerControl.writeUInt(mpData.bank); fShmNonRtServerControl.writeUInt(mpData.program); bufStrSize = carla_fixedValue(1U, 32U, static_cast(std::strlen(mpData.name))); fShmNonRtServerControl.writeUInt(bufStrSize); fShmNonRtServerControl.writeCustomData(mpData.name, bufStrSize); fShmNonRtServerControl.commitWrite(); fShmNonRtServerControl.waitIfDataIsReachingLimit(); } } if (const uint32_t latency = plugin->getLatencyInFrames()) { fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetLatency); fShmNonRtServerControl.writeUInt(latency); fShmNonRtServerControl.commitWrite(); } // ready! fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerReady); fShmNonRtServerControl.commitWrite(); fShmNonRtServerControl.waitIfDataIsReachingLimit(); carla_stdout("Carla Bridge Ready!"); fLastPingTime = Time::currentTimeMillis(); } // send parameter outputs if (const uint32_t count = plugin->getParameterCount()) { const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); for (uint32_t i=0; i < count; ++i) { if (! plugin->isParameterOutput(i)) continue; fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterValue2); fShmNonRtServerControl.writeUInt(i); fShmNonRtServerControl.writeFloat(plugin->getParameterValue(i)); // parameter outputs are not that important, we can skip some if (! fShmNonRtServerControl.commitWrite()) break; } } CarlaEngine::idle(); try { handleNonRtData(); } CARLA_SAFE_EXCEPTION("handleNonRtData"); if (fLastPingTime > 0 && Time::currentTimeMillis() > fLastPingTime + 30000 && ! wasFirstIdle) { carla_stderr("Did not receive ping message from server for 30 secs, closing..."); signalThreadShouldExit(); callback(true, true, ENGINE_CALLBACK_QUIT, 0, 0, 0, 0, 0.0f, nullptr); } } void callback(const bool sendHost, const bool sendOsc, const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const int value3, const float valuef, const char* const valueStr) noexcept override { CarlaEngine::callback(sendHost, sendOsc, action, pluginId, value1, value2, value3, valuef, valueStr); if (fClosingDown || ! sendHost) return; switch (action) { // uint/index float/value case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED: { CARLA_SAFE_ASSERT_BREAK(value1 >= 0); const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterValue); fShmNonRtServerControl.writeUInt(static_cast(value1)); fShmNonRtServerControl.writeFloat(valuef); fShmNonRtServerControl.commitWrite(); } break; // uint/index float/value case ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: { CARLA_SAFE_ASSERT_BREAK(value1 >= 0); const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerDefaultValue); fShmNonRtServerControl.writeUInt(static_cast(value1)); fShmNonRtServerControl.writeFloat(valuef); fShmNonRtServerControl.commitWrite(); } break; // int/index case ENGINE_CALLBACK_PROGRAM_CHANGED: { CARLA_SAFE_ASSERT_BREAK(value1 >= -1); const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerCurrentProgram); fShmNonRtServerControl.writeInt(value1); fShmNonRtServerControl.commitWrite(); } break; // int/index case ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED: { CARLA_SAFE_ASSERT_BREAK(value1 >= -1); const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerCurrentMidiProgram); fShmNonRtServerControl.writeInt(value1); fShmNonRtServerControl.commitWrite(); } break; case ENGINE_CALLBACK_UI_STATE_CHANGED: if (value1 != 1) { const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerUiClosed); fShmNonRtServerControl.commitWrite(); } break; case ENGINE_CALLBACK_RELOAD_PARAMETERS: if (CarlaPlugin* const plugin = pData->plugins[0].plugin) { if (const uint32_t count = std::min(pData->options.maxParameters, plugin->getParameterCount())) { const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); for (uint32_t i=0; igetParameterData(i)); if (paramData.type != PARAMETER_INPUT && paramData.type != PARAMETER_OUTPUT) continue; if ((paramData.hints & PARAMETER_IS_ENABLED) == 0) continue; fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterValue); fShmNonRtServerControl.writeUInt(i); fShmNonRtServerControl.writeFloat(plugin->getParameterValue(i)); fShmNonRtServerControl.commitWrite(); fShmNonRtServerControl.waitIfDataIsReachingLimit(); } } } break; default: break; } } // ------------------------------------------------------------------- void clear() noexcept { fShmAudioPool.clear(); fShmRtClientControl.clear(); fShmNonRtClientControl.clear(); fShmNonRtServerControl.clear(); } void handleNonRtData() { CarlaPlugin* const plugin(pData->plugins[0].plugin); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); for (; fShmNonRtClientControl.isDataAvailableForReading();) { const PluginBridgeNonRtClientOpcode opcode(fShmNonRtClientControl.readOpcode()); #ifdef DEBUG if (opcode != kPluginBridgeNonRtClientPing) { carla_debug("CarlaEngineBridge::handleNonRtData() - got opcode: %s", PluginBridgeNonRtClientOpcode2str(opcode)); } #endif if (opcode != kPluginBridgeNonRtClientNull && opcode != kPluginBridgeNonRtClientPingOnOff && fLastPingTime > 0) fLastPingTime = Time::currentTimeMillis(); switch (opcode) { case kPluginBridgeNonRtClientNull: break; case kPluginBridgeNonRtClientVersion: { const uint apiVersion = fShmNonRtServerControl.readUInt(); CARLA_SAFE_ASSERT_UINT2(apiVersion >= CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM, apiVersion, CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM); } break; case kPluginBridgeNonRtClientPing: { const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong); fShmNonRtServerControl.commitWrite(); } break; case kPluginBridgeNonRtClientPingOnOff: { const uint32_t onOff(fShmNonRtClientControl.readBool()); fLastPingTime = onOff ? Time::currentTimeMillis() : -1; } break; case kPluginBridgeNonRtClientActivate: if (plugin != nullptr && plugin->isEnabled()) plugin->setActive(true, false, false); break; case kPluginBridgeNonRtClientDeactivate: if (plugin != nullptr && plugin->isEnabled()) plugin->setActive(false, false, false); break; case kPluginBridgeNonRtClientInitialSetup: // should never happen!! fShmNonRtServerControl.readUInt(); fShmNonRtServerControl.readDouble(); break; case kPluginBridgeNonRtClientSetParameterValue: { const uint32_t index(fShmNonRtClientControl.readUInt()); const float value(fShmNonRtClientControl.readFloat()); if (plugin != nullptr && plugin->isEnabled()) plugin->setParameterValue(index, value, false, false, false); break; } case kPluginBridgeNonRtClientSetParameterMidiChannel: { const uint32_t index(fShmNonRtClientControl.readUInt()); const uint8_t channel(fShmNonRtClientControl.readByte()); if (plugin != nullptr && plugin->isEnabled()) plugin->setParameterMidiChannel(index, channel, false, false); break; } case kPluginBridgeNonRtClientSetParameterMappedControlIndex: { const uint32_t index(fShmNonRtClientControl.readUInt()); const int16_t ctrl(fShmNonRtClientControl.readShort()); if (plugin != nullptr && plugin->isEnabled()) plugin->setParameterMappedControlIndex(index, ctrl, false, false); break; } case kPluginBridgeNonRtClientSetParameterMappedRange: { const uint32_t index = fShmNonRtClientControl.readUInt(); const float minimum = fShmNonRtClientControl.readFloat(); const float maximum = fShmNonRtClientControl.readFloat(); if (plugin != nullptr && plugin->isEnabled()) plugin->setParameterMappedRange(index, minimum, maximum, false, false); break; } case kPluginBridgeNonRtClientSetProgram: { const int32_t index(fShmNonRtClientControl.readInt()); if (plugin != nullptr && plugin->isEnabled()) plugin->setProgram(index, true, false, false); break; } case kPluginBridgeNonRtClientSetMidiProgram: { const int32_t index(fShmNonRtClientControl.readInt()); if (plugin != nullptr && plugin->isEnabled()) plugin->setMidiProgram(index, true, false, false); break; } case kPluginBridgeNonRtClientSetCustomData: { // type const uint32_t typeSize(fShmNonRtClientControl.readUInt()); char typeStr[typeSize+1]; carla_zeroChars(typeStr, typeSize+1); fShmNonRtClientControl.readCustomData(typeStr, typeSize); // key const uint32_t keySize(fShmNonRtClientControl.readUInt()); char keyStr[keySize+1]; carla_zeroChars(keyStr, keySize+1); fShmNonRtClientControl.readCustomData(keyStr, keySize); // value const uint32_t valueSize(fShmNonRtClientControl.readUInt()); char valueStr[valueSize+1]; carla_zeroChars(valueStr, valueSize+1); if (valueSize > 0) fShmNonRtClientControl.readCustomData(valueStr, valueSize); if (plugin != nullptr && plugin->isEnabled()) plugin->setCustomData(typeStr, keyStr, valueStr, true); break; } case kPluginBridgeNonRtClientSetChunkDataFile: { const uint32_t size(fShmNonRtClientControl.readUInt()); CARLA_SAFE_ASSERT_BREAK(size > 0); char chunkFilePathTry[size+1]; carla_zeroChars(chunkFilePathTry, size+1); fShmNonRtClientControl.readCustomData(chunkFilePathTry, size); CARLA_SAFE_ASSERT_BREAK(chunkFilePathTry[0] != '\0'); if (plugin == nullptr || ! plugin->isEnabled()) break; String chunkFilePath(chunkFilePathTry); #ifdef CARLA_OS_WIN // check if running under Wine if (chunkFilePath.startsWith("/")) chunkFilePath = chunkFilePath.replaceSection(0, 1, "Z:\\").replace("/", "\\"); #endif File chunkFile(chunkFilePath); CARLA_SAFE_ASSERT_BREAK(chunkFile.existsAsFile()); String chunkDataBase64(chunkFile.loadFileAsString()); chunkFile.deleteFile(); CARLA_SAFE_ASSERT_BREAK(chunkDataBase64.isNotEmpty()); std::vector chunk(carla_getChunkFromBase64String(chunkDataBase64.toRawUTF8())); #ifdef CARLA_PROPER_CPP11_SUPPORT plugin->setChunkData(chunk.data(), chunk.size()); #else plugin->setChunkData(&chunk.front(), chunk.size()); #endif break; } case kPluginBridgeNonRtClientSetCtrlChannel: { const int16_t channel(fShmNonRtClientControl.readShort()); CARLA_SAFE_ASSERT_BREAK(channel >= -1 && channel < MAX_MIDI_CHANNELS); if (plugin != nullptr && plugin->isEnabled()) plugin->setCtrlChannel(static_cast(channel), false, false); break; } case kPluginBridgeNonRtClientSetOption: { const uint32_t option(fShmNonRtClientControl.readUInt()); const bool yesNo(fShmNonRtClientControl.readBool()); if (plugin != nullptr && plugin->isEnabled()) plugin->setOption(option, yesNo, false); break; } case kPluginBridgeNonRtClientSetOptions: { const uint32_t options(fShmNonRtClientControl.readUInt()); if (plugin != nullptr) plugin->pData->options = options; break; } case kPluginBridgeNonRtClientGetParameterText: { const int32_t index(fShmNonRtClientControl.readInt()); if (index >= 0 && plugin != nullptr && plugin->isEnabled()) { char bufStr[STR_MAX+1]; carla_zeroChars(bufStr, STR_MAX+1); if (! plugin->getParameterText(static_cast(index), bufStr)) bufStr[0] = '\0'; const uint32_t bufStrLen = static_cast(std::strlen(bufStr)); const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetParameterText); fShmNonRtServerControl.writeInt(index); fShmNonRtServerControl.writeUInt(bufStrLen); fShmNonRtServerControl.writeCustomData(bufStr, bufStrLen); fShmNonRtServerControl.commitWrite(); fShmNonRtServerControl.waitIfDataIsReachingLimit(); } break; } case kPluginBridgeNonRtClientPrepareForSave: { if (plugin == nullptr || ! plugin->isEnabled()) break; plugin->prepareForSave(); for (uint32_t i=0, count=plugin->getCustomDataCount(); igetCustomData(i)); if (std::strcmp(cdata.type, CUSTOM_DATA_TYPE_PROPERTY) == 0) continue; const uint32_t typeLen(static_cast(std::strlen(cdata.type))); const uint32_t keyLen(static_cast(std::strlen(cdata.key))); const uint32_t valueLen(static_cast(std::strlen(cdata.value))); { const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetCustomData); fShmNonRtServerControl.writeUInt(typeLen); fShmNonRtServerControl.writeCustomData(cdata.type, typeLen); fShmNonRtServerControl.writeUInt(keyLen); fShmNonRtServerControl.writeCustomData(cdata.key, keyLen); fShmNonRtServerControl.writeUInt(valueLen); if (valueLen > 0) fShmNonRtServerControl.writeCustomData(cdata.value, valueLen); fShmNonRtServerControl.commitWrite(); fShmNonRtServerControl.waitIfDataIsReachingLimit(); } } if (plugin->getOptionsEnabled() & PLUGIN_OPTION_USE_CHUNKS) { void* data = nullptr; if (const std::size_t dataSize = plugin->getChunkData(&data)) { CARLA_SAFE_ASSERT_BREAK(data != nullptr); CarlaString dataBase64 = CarlaString::asBase64(data, dataSize); CARLA_SAFE_ASSERT_BREAK(dataBase64.length() > 0); String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName()); filePath += CARLA_OS_SEP_STR ".CarlaChunk_"; filePath += fShmAudioPool.getFilenameSuffix(); if (File(filePath).replaceWithText(dataBase64.buffer())) { const uint32_t ulength(static_cast(filePath.length())); const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetChunkDataFile); fShmNonRtServerControl.writeUInt(ulength); fShmNonRtServerControl.writeCustomData(filePath.toRawUTF8(), ulength); fShmNonRtServerControl.commitWrite(); } } } { const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSaved); fShmNonRtServerControl.commitWrite(); } break; } case kPluginBridgeNonRtClientRestoreLV2State: if (plugin != nullptr && plugin->isEnabled()) plugin->restoreLV2State(); break; case kPluginBridgeNonRtClientShowUI: if (plugin != nullptr && plugin->isEnabled()) plugin->showCustomUI(true); break; case kPluginBridgeNonRtClientHideUI: if (plugin != nullptr && plugin->isEnabled()) plugin->showCustomUI(false); break; case kPluginBridgeNonRtClientUiParameterChange: { const uint32_t index(fShmNonRtClientControl.readUInt()); const float value(fShmNonRtClientControl.readFloat()); if (plugin != nullptr && plugin->isEnabled()) plugin->uiParameterChange(index, value); break; } case kPluginBridgeNonRtClientUiProgramChange: { const uint32_t index(fShmNonRtClientControl.readUInt()); if (plugin != nullptr && plugin->isEnabled()) plugin->uiProgramChange(index); break; } case kPluginBridgeNonRtClientUiMidiProgramChange: { const uint32_t index(fShmNonRtClientControl.readUInt()); if (plugin != nullptr && plugin->isEnabled()) plugin->uiMidiProgramChange(index); break; } case kPluginBridgeNonRtClientUiNoteOn: { const uint8_t chnl(fShmNonRtClientControl.readByte()); const uint8_t note(fShmNonRtClientControl.readByte()); const uint8_t velo(fShmNonRtClientControl.readByte()); if (plugin != nullptr && plugin->isEnabled()) plugin->uiNoteOn(chnl, note, velo); break; } case kPluginBridgeNonRtClientUiNoteOff: { const uint8_t chnl(fShmNonRtClientControl.readByte()); const uint8_t note(fShmNonRtClientControl.readByte()); if (plugin != nullptr && plugin->isEnabled()) plugin->uiNoteOff(chnl, note); break; } case kPluginBridgeNonRtClientQuit: fClosingDown = true; signalThreadShouldExit(); callback(true, true, ENGINE_CALLBACK_QUIT, 0, 0, 0, 0, 0.0f, nullptr); break; } } } // ------------------------------------------------------------------- protected: void run() override { #ifdef __SSE2_MATH__ // Set FTZ and DAZ flags _mm_setcsr(_mm_getcsr() | 0x8040); #endif bool quitReceived = false; for (; ! shouldThreadExit();) { const BridgeRtClientControl::WaitHelper helper(fShmRtClientControl); if (! helper.ok) continue; for (; fShmRtClientControl.isDataAvailableForReading();) { const PluginBridgeRtClientOpcode opcode(fShmRtClientControl.readOpcode()); CarlaPlugin* const plugin(pData->plugins[0].plugin); #ifdef DEBUG if (opcode != kPluginBridgeRtClientProcess && opcode != kPluginBridgeRtClientMidiEvent) { carla_debug("CarlaEngineBridgeRtThread::run() - got opcode: %s", PluginBridgeRtClientOpcode2str(opcode)); } #endif switch (opcode) { case kPluginBridgeRtClientNull: break; case kPluginBridgeRtClientSetAudioPool: { if (fShmAudioPool.data != nullptr) { jackbridge_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data); fShmAudioPool.data = nullptr; } const uint64_t poolSize(fShmRtClientControl.readULong()); CARLA_SAFE_ASSERT_BREAK(poolSize > 0); fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast(poolSize)); break; } case kPluginBridgeRtClientSetBufferSize: { const uint32_t bufferSize(fShmRtClientControl.readUInt()); pData->bufferSize = bufferSize; bufferSizeChanged(bufferSize); break; } case kPluginBridgeRtClientSetSampleRate: { const double sampleRate(fShmRtClientControl.readDouble()); pData->sampleRate = sampleRate; sampleRateChanged(sampleRate); break; } case kPluginBridgeRtClientSetOnline: fIsOffline = fShmRtClientControl.readBool(); offlineModeChanged(fIsOffline); break; case kPluginBridgeRtClientControlEventParameter: { const uint32_t time(fShmRtClientControl.readUInt()); const uint8_t channel(fShmRtClientControl.readByte()); const uint16_t param(fShmRtClientControl.readUShort()); const float value(fShmRtClientControl.readFloat()); if (EngineEvent* const event = getNextFreeInputEvent()) { event->type = kEngineEventTypeControl; event->time = time; event->channel = channel; event->ctrl.type = kEngineControlEventTypeParameter; event->ctrl.param = param; event->ctrl.value = value; } break; } case kPluginBridgeRtClientControlEventMidiBank: { const uint32_t time(fShmRtClientControl.readUInt()); const uint8_t channel(fShmRtClientControl.readByte()); const uint16_t index(fShmRtClientControl.readUShort()); if (EngineEvent* const event = getNextFreeInputEvent()) { event->type = kEngineEventTypeControl; event->time = time; event->channel = channel; event->ctrl.type = kEngineControlEventTypeMidiBank; event->ctrl.param = index; event->ctrl.value = 0.0f; } break; } case kPluginBridgeRtClientControlEventMidiProgram: { const uint32_t time(fShmRtClientControl.readUInt()); const uint8_t channel(fShmRtClientControl.readByte()); const uint16_t index(fShmRtClientControl.readUShort()); if (EngineEvent* const event = getNextFreeInputEvent()) { event->type = kEngineEventTypeControl; event->time = time; event->channel = channel; event->ctrl.type = kEngineControlEventTypeMidiProgram; event->ctrl.param = index; event->ctrl.value = 0.0f; } break; } case kPluginBridgeRtClientControlEventAllSoundOff: { const uint32_t time(fShmRtClientControl.readUInt()); const uint8_t channel(fShmRtClientControl.readByte()); if (EngineEvent* const event = getNextFreeInputEvent()) { event->type = kEngineEventTypeControl; event->time = time; event->channel = channel; event->ctrl.type = kEngineControlEventTypeAllSoundOff; event->ctrl.param = 0; event->ctrl.value = 0.0f; } } break; case kPluginBridgeRtClientControlEventAllNotesOff: { const uint32_t time(fShmRtClientControl.readUInt()); const uint8_t channel(fShmRtClientControl.readByte()); if (EngineEvent* const event = getNextFreeInputEvent()) { event->type = kEngineEventTypeControl; event->time = time; event->channel = channel; event->ctrl.type = kEngineControlEventTypeAllNotesOff; event->ctrl.param = 0; event->ctrl.value = 0.0f; } } break; case kPluginBridgeRtClientMidiEvent: { const uint32_t time(fShmRtClientControl.readUInt()); const uint8_t port(fShmRtClientControl.readByte()); const uint8_t size(fShmRtClientControl.readByte()); CARLA_SAFE_ASSERT_BREAK(size > 0); // FIXME variable-size stack uint8_t data[size]; for (uint8_t i=0; itype = kEngineEventTypeMidi; event->time = time; event->channel = MIDI_GET_CHANNEL_FROM_DATA(data); event->midi.port = port; event->midi.size = size; if (size > EngineMidiEvent::kDataSize) { event->midi.dataExt = data; std::memset(event->midi.data, 0, sizeof(uint8_t)*EngineMidiEvent::kDataSize); } else { event->midi.data[0] = MIDI_GET_STATUS_FROM_DATA(data); uint8_t i=1; for (; i < size; ++i) event->midi.data[i] = data[i]; for (; i < EngineMidiEvent::kDataSize; ++i) event->midi.data[i] = 0; event->midi.dataExt = nullptr; } } break; } case kPluginBridgeRtClientProcess: { const uint32_t frames(fShmRtClientControl.readUInt()); CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr); if (plugin != nullptr && plugin->isEnabled() && plugin->tryLock(fIsOffline)) { const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo); const uint32_t audioInCount(plugin->getAudioInCount()); const uint32_t audioOutCount(plugin->getAudioOutCount()); const uint32_t cvInCount(plugin->getCVInCount()); const uint32_t cvOutCount(plugin->getCVOutCount()); const float* audioIn[audioInCount]; /* */ float* audioOut[audioOutCount]; const float* cvIn[cvInCount]; /* */ float* cvOut[cvOutCount]; float* fdata = fShmAudioPool.data; for (uint32_t i=0; i < audioInCount; ++i, fdata += pData->bufferSize) audioIn[i] = fdata; for (uint32_t i=0; i < audioOutCount; ++i, fdata += pData->bufferSize) audioOut[i] = fdata; for (uint32_t i=0; i < cvInCount; ++i, fdata += pData->bufferSize) cvIn[i] = fdata; for (uint32_t i=0; i < cvOutCount; ++i, fdata += pData->bufferSize) cvOut[i] = fdata; EngineTimeInfo& timeInfo(pData->timeInfo); timeInfo.playing = bridgeTimeInfo.playing; timeInfo.frame = bridgeTimeInfo.frame; timeInfo.usecs = bridgeTimeInfo.usecs; timeInfo.bbt.valid = (bridgeTimeInfo.validFlags & kPluginBridgeTimeInfoValidBBT) != 0; if (timeInfo.bbt.valid) { timeInfo.bbt.bar = bridgeTimeInfo.bar; timeInfo.bbt.beat = bridgeTimeInfo.beat; timeInfo.bbt.tick = bridgeTimeInfo.tick; timeInfo.bbt.beatsPerBar = bridgeTimeInfo.beatsPerBar; timeInfo.bbt.beatType = bridgeTimeInfo.beatType; timeInfo.bbt.ticksPerBeat = bridgeTimeInfo.ticksPerBeat; timeInfo.bbt.beatsPerMinute = bridgeTimeInfo.beatsPerMinute; timeInfo.bbt.barStartTick = bridgeTimeInfo.barStartTick; } plugin->initBuffers(); plugin->process(audioIn, audioOut, cvIn, cvOut, frames); plugin->unlock(); } uint8_t* midiData(fShmRtClientControl.data->midiOut); carla_zeroBytes(midiData, kBridgeBaseMidiOutHeaderSize); std::size_t curMidiDataPos = 0; if (pData->events.in[0].type != kEngineEventTypeNull) carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount); if (pData->events.out[0].type != kEngineEventTypeNull) { for (ushort i=0; i < kMaxEngineEventInternalCount; ++i) { const EngineEvent& event(pData->events.out[i]); if (event.type == kEngineEventTypeNull) break; if (event.type == kEngineEventTypeControl) { uint8_t data[3]; const uint8_t size = event.ctrl.convertToMidiData(event.channel, data); CARLA_SAFE_ASSERT_CONTINUE(size > 0 && size <= 3); if (curMidiDataPos + kBridgeBaseMidiOutHeaderSize + size >= kBridgeRtClientDataMidiOutSize) break; // set time *(uint32_t*)midiData = event.time; midiData = midiData + 4; curMidiDataPos += 4; // set port *midiData++ = 0; ++curMidiDataPos; // set size *midiData++ = size; ++curMidiDataPos; // set data for (uint8_t j=0; j= kBridgeRtClientDataMidiOutSize) break; const uint8_t* const _midiData(_midiEvent.dataExt != nullptr ? _midiEvent.dataExt : _midiEvent.data); // set time *(uint32_t*)midiData = event.time; midiData += 4; curMidiDataPos += 4; // set port *midiData++ = _midiEvent.port; ++curMidiDataPos; // set size *midiData++ = _midiEvent.size; ++curMidiDataPos; // set data *midiData++ = uint8_t(_midiData[0] | (event.channel & MIDI_CHANNEL_BIT)); for (uint8_t j=1; j<_midiEvent.size; ++j) *midiData++ = _midiData[j]; curMidiDataPos += _midiEvent.size; } } if (curMidiDataPos != 0 && curMidiDataPos + kBridgeBaseMidiOutHeaderSize < kBridgeRtClientDataMidiOutSize) carla_zeroBytes(midiData, kBridgeBaseMidiOutHeaderSize); carla_zeroStructs(pData->events.out, kMaxEngineEventInternalCount); } } break; case kPluginBridgeRtClientQuit: { quitReceived = true; fClosingDown = true; signalThreadShouldExit(); } break; } } } callback(true, true, ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0, 0.0f, nullptr); if (! quitReceived) { const char* const message("Plugin bridge error, process thread has stopped"); const std::size_t messageSize(std::strlen(message)); const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerError); fShmNonRtServerControl.writeUInt(messageSize); fShmNonRtServerControl.writeCustomData(message, messageSize); fShmNonRtServerControl.commitWrite(); } } // called from process thread above EngineEvent* getNextFreeInputEvent() const noexcept { for (ushort i=0; i < kMaxEngineEventInternalCount; ++i) { EngineEvent* const event(&pData->events.in[i]); if (event->type == kEngineEventTypeNull) return event; } return nullptr; } void latencyChanged(const uint32_t samples) noexcept override { const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetLatency); fShmNonRtServerControl.writeUInt(samples); fShmNonRtServerControl.commitWrite(); } // ------------------------------------------------------------------- private: BridgeAudioPool fShmAudioPool; BridgeRtClientControl fShmRtClientControl; BridgeNonRtClientControl fShmNonRtClientControl; BridgeNonRtServerControl fShmNonRtServerControl; CarlaString fBaseNameAudioPool; CarlaString fBaseNameRtClientControl; CarlaString fBaseNameNonRtClientControl; CarlaString fBaseNameNonRtServerControl; bool fClosingDown; bool fIsOffline; bool fFirstIdle; int64_t fLastPingTime; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineBridge) }; // ----------------------------------------------------------------------- CarlaEngine* CarlaEngine::newBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName) { return new CarlaEngineBridge(audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE // ----------------------------------------------------------------------- #include "CarlaBridgeUtils.cpp" // ----------------------------------------------------------------------- Carla-2.1/source/backend/engine/CarlaEngineClient.cpp000066400000000000000000000231431364475620200225610ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaEngineClient.hpp" #include "CarlaEngineUtils.hpp" #include "CarlaString.hpp" CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- static void _getUniquePortName(CarlaString& sname, const CarlaStringList& list) { for (CarlaStringList::Itenerator it = list.begin2(); it.valid(); it.next()) { const char* const portName(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0'); // Check if unique name doesn't exist if (sname != portName) continue; // Check if string has already been modified { const std::size_t len(sname.length()); // 1 digit, ex: " (2)" if (sname[len-4] == ' ' && sname[len-3] == '(' && sname.isDigit(len-2) && sname[len-1] == ')') { const int number = sname[len-2] - '0'; if (number == 9) { // next number is 10, 2 digits sname.truncate(len-4); sname += " (10)"; //sname.replace(" (9)", " (10)"); } else sname[len-2] = char('0' + number + 1); continue; } // 2 digits, ex: " (11)" if (sname[len-5] == ' ' && sname[len-4] == '(' && sname.isDigit(len-3) && sname.isDigit(len-2) && sname[len-1] == ')') { char n2 = sname[len-2]; char n3 = sname[len-3]; if (n2 == '9') { n2 = '0'; n3 = static_cast(n3 + 1); } else n2 = static_cast(n2 + 1); sname[len-2] = n2; sname[len-3] = n3; continue; } } // Modify string if not sname += " (2)"; } } // ----------------------------------------------------------------------- // Carla Engine Client #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaEngineClient::ProtectedData::ProtectedData(const CarlaEngine& eng, EngineInternalGraph& eg, CarlaPlugin* const p) noexcept #else CarlaEngineClient::ProtectedData::ProtectedData(const CarlaEngine& eng) noexcept #endif : engine(eng), active(false), latency(0), #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH cvSourcePorts(), egraph(eg), plugin(p), #endif audioInList(), audioOutList(), cvInList(), cvOutList(), eventInList(), eventOutList() {} void CarlaEngineClient::ProtectedData::addAudioPortName(const bool isInput, const char* const name) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); CarlaStringList& portList(isInput ? audioInList : audioOutList); portList.append(name); } void CarlaEngineClient::ProtectedData::addCVPortName(const bool isInput, const char* const name) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); CarlaStringList& portList(isInput ? cvInList : cvOutList); portList.append(name); } void CarlaEngineClient::ProtectedData::addEventPortName(const bool isInput, const char* const name) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); CarlaStringList& portList(isInput ? eventInList : eventOutList); portList.append(name); } const char* CarlaEngineClient::ProtectedData::getUniquePortName(const char* const name) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr); CarlaString sname; sname = name; _getUniquePortName(sname, audioInList); _getUniquePortName(sname, audioOutList); _getUniquePortName(sname, cvInList); _getUniquePortName(sname, cvOutList); _getUniquePortName(sname, eventInList); _getUniquePortName(sname, eventOutList); return sname.dup(); } void CarlaEngineClient::ProtectedData::clearPorts() { audioInList.clear(); audioOutList.clear(); cvInList.clear(); cvOutList.clear(); eventInList.clear(); eventOutList.clear(); } // ----------------------------------------------------------------------- CarlaEngineClient::CarlaEngineClient(ProtectedData* const p) : pData(p) { carla_debug("CarlaEngineClient::CarlaEngineClient()"); } CarlaEngineClient::~CarlaEngineClient() noexcept { carla_debug("CarlaEngineClient::~CarlaEngineClient()"); } void CarlaEngineClient::activate() noexcept { CARLA_SAFE_ASSERT(! pData->active); carla_debug("CarlaEngineClient::activate()"); pData->active = true; } void CarlaEngineClient::deactivate() noexcept { CARLA_SAFE_ASSERT(pData->active); carla_debug("CarlaEngineClient::deactivate()"); pData->active = false; } bool CarlaEngineClient::isActive() const noexcept { return pData->active; } bool CarlaEngineClient::isOk() const noexcept { return true; } uint32_t CarlaEngineClient::getLatency() const noexcept { return pData->latency; } void CarlaEngineClient::setLatency(const uint32_t samples) noexcept { pData->latency = samples; } CarlaEnginePort* CarlaEngineClient::addPort(const EnginePortType portType, const char* const name, const bool isInput, const uint32_t indexOffset) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr); carla_debug("CarlaEngineClient::addPort(%i:%s, \"%s\", %s, %u)", portType, EnginePortType2Str(portType), name, bool2str(isInput), indexOffset); switch (portType) { case kEnginePortTypeNull: break; case kEnginePortTypeAudio: pData->addAudioPortName(isInput, name); return new CarlaEngineAudioPort(*this, isInput, indexOffset); case kEnginePortTypeCV: pData->addCVPortName(isInput, name); return new CarlaEngineCVPort(*this, isInput, indexOffset); case kEnginePortTypeEvent: pData->addEventPortName(isInput, name); return new CarlaEngineEventPort(*this, isInput, indexOffset); } carla_stderr("CarlaEngineClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput)); return nullptr; } bool CarlaEngineClient::removePort(const EnginePortType portType, const char* const name, const bool isInput) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', false); carla_debug("CarlaEngineClient::removePort(%i:%s, \"%s\", %s)", portType, EnginePortType2Str(portType), name, bool2str(isInput)); switch (portType) { case kEnginePortTypeNull: break; case kEnginePortTypeAudio: { CarlaStringList& portList(isInput ? pData->audioInList : pData->audioOutList); portList.append(name); return portList.removeOne(name); } case kEnginePortTypeCV: { CarlaStringList& portList(isInput ? pData->cvInList : pData->cvOutList); return portList.removeOne(name); } case kEnginePortTypeEvent: { CarlaStringList& portList(isInput ? pData->eventInList : pData->eventOutList); return portList.removeOne(name); } } return false; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaEngineCVSourcePorts* CarlaEngineClient::createCVSourcePorts() { pData->cvSourcePorts.setGraphAndPlugin(pData->egraph.getPatchbayGraphOrNull(), pData->plugin); return &pData->cvSourcePorts; } #endif const CarlaEngine& CarlaEngineClient::getEngine() const noexcept { return pData->engine; } EngineProcessMode CarlaEngineClient::getProcessMode() const noexcept { return pData->engine.getProccessMode(); } uint CarlaEngineClient::getPortCount(const EnginePortType portType, const bool isInput) const noexcept { size_t ret = 0; switch (portType) { case kEnginePortTypeNull: break; case kEnginePortTypeAudio: ret = isInput ? pData->audioInList.count() : pData->audioOutList.count(); break; case kEnginePortTypeCV: ret = isInput ? pData->cvInList.count() : pData->cvOutList.count(); break; case kEnginePortTypeEvent: ret = isInput ? pData->eventInList.count() : pData->eventOutList.count(); break; } return static_cast(ret); } const char* CarlaEngineClient::getAudioPortName(const bool isInput, const uint index) const noexcept { CarlaStringList& portList(isInput ? pData->audioInList : pData->audioOutList); CARLA_SAFE_ASSERT_RETURN(index < portList.count(), nullptr); return portList.getAt(index); } const char* CarlaEngineClient::getCVPortName(const bool isInput, const uint index) const noexcept { CarlaStringList& portList(isInput ? pData->cvInList : pData->cvOutList); CARLA_SAFE_ASSERT_RETURN(index < portList.count(), nullptr); return portList.getAt(index); } const char* CarlaEngineClient::getEventPortName(const bool isInput, const uint index) const noexcept { CarlaStringList& portList(isInput ? pData->eventInList : pData->eventOutList); CARLA_SAFE_ASSERT_RETURN(index < portList.count(), nullptr); return portList.getAt(index); } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/engine/CarlaEngineClient.hpp000066400000000000000000000066101364475620200225660ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_ENGINE_CLIENT_HPP_INCLUDED #define CARLA_ENGINE_CLIENT_HPP_INCLUDED #include "CarlaEngine.hpp" #include "CarlaEnginePorts.hpp" #include "CarlaStringList.hpp" CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // Carla Engine Client Protected Data struct CarlaEngineClient::ProtectedData { const CarlaEngine& engine; bool active; uint32_t latency; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaEngineCVSourcePortsForStandalone cvSourcePorts; EngineInternalGraph& egraph; CarlaPlugin* const plugin; #endif CarlaStringList audioInList; CarlaStringList audioOutList; CarlaStringList cvInList; CarlaStringList cvOutList; CarlaStringList eventInList; CarlaStringList eventOutList; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH ProtectedData(const CarlaEngine& eng, EngineInternalGraph& eg, CarlaPlugin* p) noexcept; #else ProtectedData(const CarlaEngine& eng) noexcept; #endif void addAudioPortName(bool isInput, const char* name); void addCVPortName(bool isInput, const char* name); void addEventPortName(bool isInput, const char* name); void clearPorts(); const char* getUniquePortName(const char* name); #ifdef CARLA_PROPER_CPP11_SUPPORT ProtectedData() = delete; CARLA_DECLARE_NON_COPY_STRUCT(ProtectedData) #endif }; // ----------------------------------------------------------------------- // Carla Engine Client #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH class CarlaEngineClientForStandalone : public CarlaEngineClient { public: CarlaEngineClientForStandalone(const CarlaEngine& engine, EngineInternalGraph& egraph, CarlaPlugin* const plugin) : CarlaEngineClient(new ProtectedData(engine, egraph, plugin)) {} ~CarlaEngineClientForStandalone() noexcept override { delete pData; } protected: inline PatchbayGraph* getPatchbayGraphOrNull() const noexcept { return pData->egraph.getPatchbayGraphOrNull(); } inline CarlaPlugin* getPlugin() const noexcept { return pData->plugin; } CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineClientForStandalone) }; typedef CarlaEngineClientForStandalone CarlaEngineClientForSubclassing; #else class CarlaEngineClientForBridge : public CarlaEngineClient { public: CarlaEngineClientForBridge(const CarlaEngine& engine) : CarlaEngineClient(new ProtectedData(engine)) {} ~CarlaEngineClientForBridge() override { delete pData; } CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineClientForBridge) }; typedef CarlaEngineClientForBridge CarlaEngineClientForSubclassing; #endif // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE #endif // CARLA_ENGINE_CLIENT_HPP_INCLUDED Carla-2.1/source/backend/engine/CarlaEngineData.cpp000066400000000000000000000300001364475620200222020ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaEngine.hpp" #include "CarlaMathUtils.hpp" #include "CarlaMIDI.h" CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // EngineControlEvent uint8_t EngineControlEvent::convertToMidiData(const uint8_t channel, uint8_t data[3]) const noexcept { switch (type) { case kEngineControlEventTypeNull: break; case kEngineControlEventTypeParameter: CARLA_SAFE_ASSERT_RETURN(param < MAX_MIDI_VALUE, 0); data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); if (MIDI_IS_CONTROL_BANK_SELECT(param)) { data[1] = MIDI_CONTROL_BANK_SELECT; data[2] = uint8_t(carla_fixedValue(0.0f, static_cast(MAX_MIDI_VALUE-1), value)); } else { data[1] = static_cast(param); data[2] = uint8_t(carla_fixedValue(0.0f, 1.0f, value) * static_cast(MAX_MIDI_VALUE-1)); } return 3; case kEngineControlEventTypeMidiBank: data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); data[1] = MIDI_CONTROL_BANK_SELECT; data[2] = uint8_t(carla_fixedValue(0, MAX_MIDI_VALUE-1, param)); return 3; case kEngineControlEventTypeMidiProgram: data[0] = static_cast(MIDI_STATUS_PROGRAM_CHANGE | (channel & MIDI_CHANNEL_BIT)); data[1] = uint8_t(carla_fixedValue(0, MAX_MIDI_VALUE-1, param)); return 2; case kEngineControlEventTypeAllSoundOff: data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); data[1] = MIDI_CONTROL_ALL_SOUND_OFF; return 2; case kEngineControlEventTypeAllNotesOff: data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); data[1] = MIDI_CONTROL_ALL_NOTES_OFF; return 2; } return 0; } // ----------------------------------------------------------------------- // EngineEvent void EngineEvent::fillFromMidiData(const uint8_t size, const uint8_t* const data, const uint8_t midiPortOffset) noexcept { if (size == 0 || data == nullptr || data[0] < MIDI_STATUS_NOTE_OFF) { type = kEngineEventTypeNull; channel = 0; return; } // get channel channel = uint8_t(MIDI_GET_CHANNEL_FROM_DATA(data)); // get status const uint8_t midiStatus(uint8_t(MIDI_GET_STATUS_FROM_DATA(data))); if (midiStatus == MIDI_STATUS_CONTROL_CHANGE) { CARLA_SAFE_ASSERT_RETURN(size >= 2,); type = kEngineEventTypeControl; const uint8_t midiControl(data[1]); if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) { CARLA_SAFE_ASSERT_RETURN(size >= 3,); const uint8_t midiBank(data[2]); ctrl.type = kEngineControlEventTypeMidiBank; ctrl.param = midiBank; ctrl.value = 0.0f; } else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) { ctrl.type = kEngineControlEventTypeAllSoundOff; ctrl.param = 0; ctrl.value = 0.0f; } else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) { ctrl.type = kEngineControlEventTypeAllNotesOff; ctrl.param = 0; ctrl.value = 0.0f; } else { CARLA_SAFE_ASSERT_RETURN(size >= 3,); const uint8_t midiValue = carla_fixedValue(0, 127, data[2]); // ensures 0.0<->1.0 value range ctrl.type = kEngineControlEventTypeParameter; ctrl.param = midiControl; ctrl.value = float(midiValue)/127.0f; } } else if (midiStatus == MIDI_STATUS_PROGRAM_CHANGE) { CARLA_SAFE_ASSERT_RETURN(size >= 2,); type = kEngineEventTypeControl; const uint8_t midiProgram(data[1]); ctrl.type = kEngineControlEventTypeMidiProgram; ctrl.param = midiProgram; ctrl.value = 0.0f; } else { type = kEngineEventTypeMidi; midi.port = midiPortOffset; midi.size = size; if (size > EngineMidiEvent::kDataSize) { midi.dataExt = data; std::memset(midi.data, 0, sizeof(uint8_t)*EngineMidiEvent::kDataSize); } else { midi.data[0] = midiStatus; uint8_t i=1; for (; i < size; ++i) midi.data[i] = data[i]; for (; i < EngineMidiEvent::kDataSize; ++i) midi.data[i] = 0; midi.dataExt = nullptr; } } } // ----------------------------------------------------------------------- // EngineOptions EngineOptions::EngineOptions() noexcept #ifdef CARLA_OS_LINUX : processMode(ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS), transportMode(ENGINE_TRANSPORT_MODE_JACK), #else : processMode(ENGINE_PROCESS_MODE_PATCHBAY), transportMode(ENGINE_TRANSPORT_MODE_INTERNAL), #endif transportExtra(nullptr), forceStereo(false), resetXruns(false), preferPluginBridges(false), #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) preferUiBridges(false), #else preferUiBridges(true), #endif uisAlwaysOnTop(true), bgColor(0x000000ff), fgColor(0xffffffff), uiScale(1.0f), maxParameters(MAX_DEFAULT_PARAMETERS), uiBridgesTimeout(4000), audioBufferSize(512), audioSampleRate(44100), audioTripleBuffer(false), audioDriver(nullptr), audioDevice(nullptr), #ifndef BUILD_BRIDGE # ifdef CARLA_OS_WIN oscEnabled(false), # else oscEnabled(true), # endif oscPortTCP(22752), oscPortUDP(22752), #endif pathAudio(nullptr), pathMIDI(nullptr), pathLADSPA(nullptr), pathDSSI(nullptr), pathLV2(nullptr), pathVST2(nullptr), pathVST3(nullptr), pathSF2(nullptr), pathSFZ(nullptr), binaryDir(nullptr), resourceDir(nullptr), preventBadBehaviour(false), frontendWinId(0) #ifndef CARLA_OS_WIN , wine() #endif { } EngineOptions::~EngineOptions() noexcept { if (audioDriver != nullptr) { delete[] audioDriver; audioDriver = nullptr; } if (audioDevice != nullptr) { delete[] audioDevice; audioDevice = nullptr; } if (pathAudio != nullptr) { delete[] pathAudio; pathAudio = nullptr; } if (pathMIDI != nullptr) { delete[] pathMIDI; pathMIDI = nullptr; } if (pathLADSPA != nullptr) { delete[] pathLADSPA; pathLADSPA = nullptr; } if (pathDSSI != nullptr) { delete[] pathDSSI; pathDSSI = nullptr; } if (pathLV2 != nullptr) { delete[] pathLV2; pathLV2 = nullptr; } if (pathVST2 != nullptr) { delete[] pathVST2; pathVST2 = nullptr; } if (pathVST3 != nullptr) { delete[] pathVST3; pathVST3 = nullptr; } if (pathSF2 != nullptr) { delete[] pathSF2; pathSF2 = nullptr; } if (pathSFZ != nullptr) { delete[] pathSFZ; pathSFZ = nullptr; } if (binaryDir != nullptr) { delete[] binaryDir; binaryDir = nullptr; } if (resourceDir != nullptr) { delete[] resourceDir; resourceDir = nullptr; } } #ifndef CARLA_OS_WIN EngineOptions::Wine::Wine() noexcept : executable(nullptr), autoPrefix(true), fallbackPrefix(nullptr), rtPrio(true), baseRtPrio(15), serverRtPrio(10) {} EngineOptions::Wine::~Wine() noexcept { if (executable != nullptr) { delete[] executable; executable = nullptr; } if (fallbackPrefix != nullptr) { delete[] fallbackPrefix; fallbackPrefix = nullptr; } } #endif // ----------------------------------------------------------------------- // EngineTimeInfoBBT EngineTimeInfoBBT::EngineTimeInfoBBT() noexcept : valid(false), bar(0), beat(0), tick(0.0), barStartTick(0.0), beatsPerBar(0.0f), beatType(0.0f), ticksPerBeat(0.0), beatsPerMinute(0.0) {} EngineTimeInfoBBT::EngineTimeInfoBBT(const EngineTimeInfoBBT& bbt) noexcept : valid(bbt.valid), bar(bbt.bar), beat(bbt.beat), tick(bbt.tick), barStartTick(bbt.barStartTick), beatsPerBar(bbt.beatsPerBar), beatType(bbt.beatType), ticksPerBeat(bbt.ticksPerBeat), beatsPerMinute(bbt.beatsPerMinute) {} void EngineTimeInfoBBT::clear() noexcept { valid = false; bar = 0; beat = 0; tick = 0.0; barStartTick = 0.0; beatsPerBar = 0.0f; beatType = 0.0f; ticksPerBeat = 0.0; beatsPerMinute = 0.0; } // ----------------------------------------------------------------------- // EngineTimeInfo EngineTimeInfo::EngineTimeInfo() noexcept : playing(false), frame(0), usecs(0), bbt() {} void EngineTimeInfo::clear() noexcept { playing = false; frame = 0; usecs = 0; bbt.clear(); } EngineTimeInfo::EngineTimeInfo(const EngineTimeInfo& info) noexcept : playing(info.playing), frame(info.frame), usecs(info.usecs), bbt(info.bbt) {} EngineTimeInfo& EngineTimeInfo::operator=(const EngineTimeInfo& info) noexcept { playing = info.playing; frame = info.frame; usecs = info.usecs; bbt.valid = info.bbt.valid; bbt.bar = info.bbt.bar; bbt.beat = info.bbt.beat; bbt.tick = info.bbt.tick; bbt.barStartTick = info.bbt.barStartTick; bbt.beatsPerBar = info.bbt.beatsPerBar; bbt.beatType = info.bbt.beatType; bbt.ticksPerBeat = info.bbt.ticksPerBeat; bbt.beatsPerMinute = info.bbt.beatsPerMinute; return *this; } bool EngineTimeInfo::compareIgnoringRollingFrames(const EngineTimeInfo& timeInfo, const uint32_t maxFrames) const noexcept { if (timeInfo.playing != playing || timeInfo.bbt.valid != bbt.valid) return false; if (bbt.valid) { if (carla_isNotEqual(timeInfo.bbt.beatsPerBar, bbt.beatsPerBar)) return false; if (carla_isNotEqual(timeInfo.bbt.beatsPerMinute, bbt.beatsPerMinute)) return false; } // frame matches, nothing else to compare if (timeInfo.frame == frame) return true; // if we went back in time, so a case of reposition if (frame > timeInfo.frame) return false; // not playing, so don't bother checking transport // assume frame changed, likely playback has stopped if (! playing) return false; // if we are within expected bounds, assume we are rolling normally if (frame + maxFrames <= timeInfo.frame) return true; // out of bounds, another reposition return false; } bool EngineTimeInfo::operator==(const EngineTimeInfo& timeInfo) const noexcept { if (timeInfo.playing != playing || timeInfo.frame != frame || timeInfo.bbt.valid != bbt.valid) return false; if (! bbt.valid) return true; if (carla_isNotEqual(timeInfo.bbt.beatsPerBar, bbt.beatsPerBar)) return false; if (carla_isNotEqual(timeInfo.bbt.beatsPerMinute, bbt.beatsPerMinute)) return false; return true; } bool EngineTimeInfo::operator!=(const EngineTimeInfo& timeInfo) const noexcept { return !operator==(timeInfo); } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/engine/CarlaEngineDummy.cpp000066400000000000000000000204311364475620200224330ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the GPL.txt file */ #include "CarlaEngineGraph.hpp" #include "CarlaEngineInternal.hpp" #include #include CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- // Dummy Engine class CarlaEngineDummy : public CarlaEngine, public CarlaThread { public: CarlaEngineDummy() : CarlaEngine(), CarlaThread("CarlaEngineDummy"), fRunning(false) { carla_debug("CarlaEngineDummy::CarlaEngineDummy()"); // just to make sure pData->options.transportMode = ENGINE_TRANSPORT_MODE_INTERNAL; } ~CarlaEngineDummy() override { carla_debug("CarlaEngineDummy::~CarlaEngineDummy()"); } // ------------------------------------- bool init(const char* const clientName) override { CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false); carla_debug("CarlaEngineDummy::init(\"%s\")", clientName); if (pData->options.processMode != ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { setLastError("Invalid process mode"); return false; } fRunning = true; if (! pData->init(clientName)) { close(); setLastError("Failed to init internal data"); return false; } pData->bufferSize = pData->options.audioBufferSize; pData->sampleRate = pData->options.audioSampleRate; pData->initTime(pData->options.transportExtra); pData->graph.create(2, 2, 0, 0); if (! startThread(true)) { close(); setLastError("Failed to start dummy audio thread"); return false; } patchbayRefresh(true, false, false); callback(true, true, ENGINE_CALLBACK_ENGINE_STARTED, 0, pData->options.processMode, pData->options.transportMode, static_cast(pData->bufferSize), static_cast(pData->sampleRate), getCurrentDriverName()); return true; } bool close() override { carla_debug("CarlaEngineDummy::close()"); fRunning = false; stopThread(-1); CarlaEngine::close(); pData->graph.destroy(); return true; } bool isRunning() const noexcept override { return fRunning; } bool isOffline() const noexcept override { return false; } EngineType getType() const noexcept override { return kEngineTypeDummy; } const char* getCurrentDriverName() const noexcept override { return "Dummy"; } // ------------------------------------------------------------------- // Patchbay bool patchbayRefresh(const bool sendHost, const bool sendOSC, const bool) override { CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(), false); RackGraph* const graph = pData->graph.getRackGraph(); CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); ExternalGraph& extGraph(graph->extGraph); // --------------------------------------------------------------- // clear last ports extGraph.clear(); // --------------------------------------------------------------- // fill in new ones { PortNameToId portNameToId; portNameToId.setData(kExternalGraphGroupAudioIn, 1, "capture_1", ""); extGraph.audioPorts.ins.append(portNameToId); } { PortNameToId portNameToId; portNameToId.setData(kExternalGraphGroupAudioIn, 2, "capture_2", ""); extGraph.audioPorts.ins.append(portNameToId); } { PortNameToId portNameToId; portNameToId.setData(kExternalGraphGroupAudioOut, 1, "playback_1", ""); extGraph.audioPorts.outs.append(portNameToId); } { PortNameToId portNameToId; portNameToId.setData(kExternalGraphGroupAudioOut, 2, "playback_2", ""); extGraph.audioPorts.outs.append(portNameToId); } // --------------------------------------------------------------- // now refresh if (sendHost || sendOSC) graph->refresh(sendHost, sendOSC, false, "Dummy"); return true; } // ------------------------------------------------------------------- protected: static int64_t getTimeInMicroseconds() noexcept { #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) struct timeval tv; gettimeofday(&tv, nullptr); return (tv.tv_sec * 1000000) + tv.tv_usec; #else struct timespec ts; # ifdef CLOCK_MONOTONIC_RAW clock_gettime(CLOCK_MONOTONIC_RAW, &ts); # else clock_gettime(CLOCK_MONOTONIC, &ts); # endif return (ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); #endif } void run() override { const uint32_t bufferSize = pData->bufferSize; const int64_t cycleTime = static_cast( static_cast(bufferSize) / pData->sampleRate * 1000000 + 0.5); carla_stdout("CarlaEngineDummy audio thread started, cycle time: " P_INT64 "ms", cycleTime / 1000); float* audioIns[2] = { (float*)std::malloc(sizeof(float)*bufferSize), (float*)std::malloc(sizeof(float)*bufferSize), }; CARLA_SAFE_ASSERT_RETURN(audioIns[0] != nullptr,); CARLA_SAFE_ASSERT_RETURN(audioIns[1] != nullptr,); float* audioOuts[2] = { (float*)std::malloc(sizeof(float)*bufferSize), (float*)std::malloc(sizeof(float)*bufferSize), }; CARLA_SAFE_ASSERT_RETURN(audioOuts[0] != nullptr,); CARLA_SAFE_ASSERT_RETURN(audioOuts[1] != nullptr,); carla_zeroFloats(audioIns[0], bufferSize); carla_zeroFloats(audioIns[1], bufferSize); carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount); while (! shouldThreadExit()) { const int64_t oldTime = getTimeInMicroseconds(); const PendingRtEventsRunner prt(this, bufferSize, true); carla_zeroFloats(audioOuts[0], bufferSize); carla_zeroFloats(audioOuts[1], bufferSize); carla_zeroStructs(pData->events.out, kMaxEngineEventInternalCount); pData->graph.process(pData, audioIns, audioOuts, bufferSize); const int64_t newTime = getTimeInMicroseconds(); CARLA_SAFE_ASSERT_CONTINUE(newTime >= oldTime); const int64_t remainingTime = cycleTime - (newTime - oldTime); if (remainingTime <= 0) { ++pData->xruns; carla_stdout("XRUN! remaining time: " P_INT64 ", old: " P_INT64 ", new: " P_INT64 ")", remainingTime, oldTime, newTime); } else { CARLA_SAFE_ASSERT_CONTINUE(remainingTime < 1000000); // 1 sec carla_msleep(static_cast(remainingTime / 1000)); } } std::free(audioIns[0]); std::free(audioIns[1]); std::free(audioOuts[0]); std::free(audioOuts[1]); carla_stdout("CarlaEngineDummy audio thread finished"); } // ------------------------------------------------------------------- private: bool fRunning; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineDummy) }; // ----------------------------------------- CarlaEngine* CarlaEngine::newDummy() { return new CarlaEngineDummy(); } // ----------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/engine/CarlaEngineGraph.cpp000066400000000000000000003007101364475620200224020ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaEngineGraph.hpp" #include "CarlaEngineInternal.hpp" #include "CarlaPlugin.hpp" #include "CarlaMathUtils.hpp" #include "CarlaScopeUtils.hpp" #include "CarlaMIDI.h" using water::jmax; using water::jmin; using water::AudioProcessor; using water::MidiBuffer; using water::String; using water::StringArray; CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // Fallback data static const PortNameToId kPortNameToIdFallback = { 0, 0, { '\0' }, { '\0' } }; static /* */ PortNameToId kPortNameToIdFallbackNC = { 0, 0, { '\0' }, { '\0' } }; // ----------------------------------------------------------------------- // External Graph stuff static inline uint getExternalGraphPortIdFromName(const char* const shortname) noexcept { if (std::strcmp(shortname, "AudioIn1") == 0 || std::strcmp(shortname, "audio-in1") == 0) return kExternalGraphCarlaPortAudioIn1; if (std::strcmp(shortname, "AudioIn2") == 0 || std::strcmp(shortname, "audio-in2") == 0) return kExternalGraphCarlaPortAudioIn2; if (std::strcmp(shortname, "AudioOut1") == 0 || std::strcmp(shortname, "audio-out1") == 0) return kExternalGraphCarlaPortAudioOut1; if (std::strcmp(shortname, "AudioOut2") == 0 || std::strcmp(shortname, "audio-out2") == 0) return kExternalGraphCarlaPortAudioOut2; if (std::strcmp(shortname, "MidiIn") == 0 || std::strcmp(shortname, "midi-in") == 0) return kExternalGraphCarlaPortMidiIn; if (std::strcmp(shortname, "MidiOut") == 0 || std::strcmp(shortname, "midi-out") == 0) return kExternalGraphCarlaPortMidiOut; carla_stderr("CarlaBackend::getExternalGraphPortIdFromName(%s) - invalid short name", shortname); return kExternalGraphCarlaPortNull; } static inline const char* getExternalGraphFullPortNameFromId(const /*RackGraphCarlaPortIds*/ uint portId) { switch (portId) { case kExternalGraphCarlaPortAudioIn1: return "Carla:AudioIn1"; case kExternalGraphCarlaPortAudioIn2: return "Carla:AudioIn2"; case kExternalGraphCarlaPortAudioOut1: return "Carla:AudioOut1"; case kExternalGraphCarlaPortAudioOut2: return "Carla:AudioOut2"; case kExternalGraphCarlaPortMidiIn: return "Carla:MidiIn"; case kExternalGraphCarlaPortMidiOut: return "Carla:MidiOut"; //case kExternalGraphCarlaPortNull: //case kExternalGraphCarlaPortMax: // break; } carla_stderr("CarlaBackend::getExternalGraphFullPortNameFromId(%i) - invalid port id", portId); return nullptr; } // ----------------------------------------------------------------------- ExternalGraphPorts::ExternalGraphPorts() noexcept : ins(), outs() {} const char* ExternalGraphPorts::getName(const bool isInput, const uint portId) const noexcept { for (LinkedList::Itenerator it = isInput ? ins.begin2() : outs.begin2(); it.valid(); it.next()) { const PortNameToId& portNameToId(it.getValue(kPortNameToIdFallback)); CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group > 0); if (portNameToId.port == portId) return portNameToId.name; } return nullptr; } uint ExternalGraphPorts::getPortId(const bool isInput, const char portName[], bool* const ok) const noexcept { for (LinkedList::Itenerator it = isInput ? ins.begin2() : outs.begin2(); it.valid(); it.next()) { const PortNameToId& portNameToId(it.getValue(kPortNameToIdFallback)); CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group > 0); if (std::strncmp(portNameToId.name, portName, STR_MAX) == 0) { if (ok != nullptr) *ok = true; return portNameToId.port; } } if (ok != nullptr) *ok = false; return 0; } // ----------------------------------------------------------------------- ExternalGraph::ExternalGraph(CarlaEngine* const engine) noexcept : connections(), audioPorts(), midiPorts(), retCon(), kEngine(engine) {} void ExternalGraph::clear() noexcept { connections.clear(); audioPorts.ins.clear(); audioPorts.outs.clear(); midiPorts.ins.clear(); midiPorts.outs.clear(); } bool ExternalGraph::connect(const bool sendHost, const bool sendOSC, const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept { uint otherGroup, otherPort, carlaPort; if (groupA == kExternalGraphGroupCarla) { CARLA_SAFE_ASSERT_RETURN(groupB != kExternalGraphGroupCarla, false); carlaPort = portA; otherGroup = groupB; otherPort = portB; } else { CARLA_SAFE_ASSERT_RETURN(groupB == kExternalGraphGroupCarla, false); carlaPort = portB; otherGroup = groupA; otherPort = portA; } CARLA_SAFE_ASSERT_RETURN(carlaPort > kExternalGraphCarlaPortNull && carlaPort < kExternalGraphCarlaPortMax, false); CARLA_SAFE_ASSERT_RETURN(otherGroup > kExternalGraphGroupCarla && otherGroup < kExternalGraphGroupMax, false); bool makeConnection = false; switch (carlaPort) { case kExternalGraphCarlaPortAudioIn1: CARLA_SAFE_ASSERT_RETURN(otherGroup == kExternalGraphGroupAudioIn, false); makeConnection = kEngine->connectExternalGraphPort(kExternalGraphConnectionAudioIn1, otherPort, nullptr); break; case kExternalGraphCarlaPortAudioIn2: CARLA_SAFE_ASSERT_RETURN(otherGroup == kExternalGraphGroupAudioIn, false); makeConnection = kEngine->connectExternalGraphPort(kExternalGraphConnectionAudioIn2, otherPort, nullptr); break; case kExternalGraphCarlaPortAudioOut1: CARLA_SAFE_ASSERT_RETURN(otherGroup == kExternalGraphGroupAudioOut, false); makeConnection = kEngine->connectExternalGraphPort(kExternalGraphConnectionAudioOut1, otherPort, nullptr); break; case kExternalGraphCarlaPortAudioOut2: CARLA_SAFE_ASSERT_RETURN(otherGroup == kExternalGraphGroupAudioOut, false); makeConnection = kEngine->connectExternalGraphPort(kExternalGraphConnectionAudioOut2, otherPort, nullptr); break; case kExternalGraphCarlaPortMidiIn: CARLA_SAFE_ASSERT_RETURN(otherGroup == kExternalGraphGroupMidiIn, false); if (const char* const portName = midiPorts.getName(true, otherPort)) makeConnection = kEngine->connectExternalGraphPort(kExternalGraphConnectionMidiInput, 0, portName); break; case kExternalGraphCarlaPortMidiOut: CARLA_SAFE_ASSERT_RETURN(otherGroup == kExternalGraphGroupMidiOut, false); if (const char* const portName = midiPorts.getName(false, otherPort)) makeConnection = kEngine->connectExternalGraphPort(kExternalGraphConnectionMidiOutput, 0, portName); break; } if (! makeConnection) { kEngine->setLastError("Invalid rack connection"); return false; } ConnectionToId connectionToId; connectionToId.setData(++connections.lastId, groupA, portA, groupB, portB); char strBuf[STR_MAX+1]; strBuf[STR_MAX] = '\0'; std::snprintf(strBuf, STR_MAX, "%u:%u:%u:%u", groupA, portA, groupB, portB); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); connections.list.append(connectionToId); return true; } bool ExternalGraph::disconnect(const bool sendHost, const bool sendOSC, const uint connectionId) noexcept { CARLA_SAFE_ASSERT_RETURN(connections.list.count() > 0, false); for (LinkedList::Itenerator it=connections.list.begin2(); it.valid(); it.next()) { static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; const ConnectionToId& connectionToId(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id > 0); if (connectionToId.id != connectionId) continue; uint otherGroup, otherPort, carlaPort; if (connectionToId.groupA == kExternalGraphGroupCarla) { CARLA_SAFE_ASSERT_RETURN(connectionToId.groupB != kExternalGraphGroupCarla, false); carlaPort = connectionToId.portA; otherGroup = connectionToId.groupB; otherPort = connectionToId.portB; } else { CARLA_SAFE_ASSERT_RETURN(connectionToId.groupB == kExternalGraphGroupCarla, false); carlaPort = connectionToId.portB; otherGroup = connectionToId.groupA; otherPort = connectionToId.portA; } CARLA_SAFE_ASSERT_RETURN(carlaPort > kExternalGraphCarlaPortNull && carlaPort < kExternalGraphCarlaPortMax, false); CARLA_SAFE_ASSERT_RETURN(otherGroup > kExternalGraphGroupCarla && otherGroup < kExternalGraphGroupMax, false); bool makeDisconnection = false; switch (carlaPort) { case kExternalGraphCarlaPortAudioIn1: makeDisconnection = kEngine->disconnectExternalGraphPort(kExternalGraphConnectionAudioIn1, otherPort, nullptr); break; case kExternalGraphCarlaPortAudioIn2: makeDisconnection = kEngine->disconnectExternalGraphPort(kExternalGraphConnectionAudioIn2, otherPort, nullptr); break; case kExternalGraphCarlaPortAudioOut1: makeDisconnection = kEngine->disconnectExternalGraphPort(kExternalGraphConnectionAudioOut1, otherPort, nullptr); break; case kExternalGraphCarlaPortAudioOut2: makeDisconnection = kEngine->disconnectExternalGraphPort(kExternalGraphConnectionAudioOut2, otherPort, nullptr); break; case kExternalGraphCarlaPortMidiIn: if (const char* const portName = midiPorts.getName(true, otherPort)) makeDisconnection = kEngine->disconnectExternalGraphPort(kExternalGraphConnectionMidiInput, 0, portName); break; case kExternalGraphCarlaPortMidiOut: if (const char* const portName = midiPorts.getName(false, otherPort)) makeDisconnection = kEngine->disconnectExternalGraphPort(kExternalGraphConnectionMidiOutput, 0, portName); break; } if (! makeDisconnection) { kEngine->setLastError("Invalid rack connection"); return false; } kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connectionToId.id, 0, 0, 0, 0.0f, nullptr); connections.list.remove(it); return true; } kEngine->setLastError("Failed to find connection"); return false; } void ExternalGraph::refresh(const bool sendHost, const bool sendOSC, const char* const deviceName) { CARLA_SAFE_ASSERT_RETURN(deviceName != nullptr,); const bool isRack(kEngine->getOptions().processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK); // Main { kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, kExternalGraphGroupCarla, PATCHBAY_ICON_CARLA, MAIN_CARLA_PLUGIN_ID, 0, 0.0f, kEngine->getName()); if (isRack) { kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioIn1, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0, 0.0f, "audio-in1"); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioIn2, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0, 0.0f, "audio-in2"); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioOut1, PATCHBAY_PORT_TYPE_AUDIO, 0, 0.0f, "audio-out1"); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioOut2, PATCHBAY_PORT_TYPE_AUDIO, 0, 0.0f, "audio-out2"); } kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiIn, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0, 0.0f, "midi-in"); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiOut, PATCHBAY_PORT_TYPE_MIDI, 0, 0.0f, "midi-out"); } char strBuf[STR_MAX+1]; strBuf[STR_MAX] = '\0'; if (isRack) { // Audio In if (deviceName[0] != '\0') std::snprintf(strBuf, STR_MAX, "Capture (%s)", deviceName); else std::strncpy(strBuf, "Capture", STR_MAX); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, kExternalGraphGroupAudioIn, PATCHBAY_ICON_HARDWARE, -1, 0, 0.0f, strBuf); const CarlaString groupNameIn(strBuf); int h = 0; for (LinkedList::Itenerator it = audioPorts.ins.begin2(); it.valid(); it.next()) { PortNameToId& portNameToId(it.getValue(kPortNameToIdFallbackNC)); CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group > 0); portNameToId.setFullName(groupNameIn + portNameToId.name); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupAudioIn, ++h, PATCHBAY_PORT_TYPE_AUDIO, 0, 0.0f, portNameToId.name); } // Audio Out if (deviceName[0] != '\0') std::snprintf(strBuf, STR_MAX, "Playback (%s)", deviceName); else std::strncpy(strBuf, "Playback", STR_MAX); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, kExternalGraphGroupAudioOut, PATCHBAY_ICON_HARDWARE, -1, 0, 0.0f, strBuf); const CarlaString groupNameOut(strBuf); h = 0; for (LinkedList::Itenerator it = audioPorts.outs.begin2(); it.valid(); it.next()) { PortNameToId& portNameToId(it.getValue(kPortNameToIdFallbackNC)); CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group > 0); portNameToId.setFullName(groupNameOut + portNameToId.name); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupAudioOut, ++h, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0, 0.0f, portNameToId.name); } } // MIDI In { kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, kExternalGraphGroupMidiIn, PATCHBAY_ICON_HARDWARE, -1, 0, 0.0f, "Readable MIDI ports"); const CarlaString groupNamePlus("Readable MIDI ports:"); int h = 0; for (LinkedList::Itenerator it = midiPorts.ins.begin2(); it.valid(); it.next()) { PortNameToId& portNameToId(it.getValue(kPortNameToIdFallbackNC)); CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group > 0); portNameToId.setFullName(groupNamePlus + portNameToId.name); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupMidiIn, ++h, PATCHBAY_PORT_TYPE_MIDI, 0, 0.0f, portNameToId.name); } } // MIDI Out { kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, kExternalGraphGroupMidiOut, PATCHBAY_ICON_HARDWARE, -1, 0, 0.0f, "Writable MIDI ports"); const CarlaString groupNamePlus("Writable MIDI ports:"); int h = 0; for (LinkedList::Itenerator it = midiPorts.outs.begin2(); it.valid(); it.next()) { PortNameToId& portNameToId(it.getValue(kPortNameToIdFallbackNC)); CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group > 0); portNameToId.setFullName(groupNamePlus + portNameToId.name); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupMidiOut, ++h, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0, 0.0f, portNameToId.name); } } } const char* const* ExternalGraph::getConnections() const noexcept { if (connections.list.count() == 0) return nullptr; CarlaStringList connList; char strBuf[STR_MAX+1]; strBuf[STR_MAX] = '\0'; for (LinkedList::Itenerator it=connections.list.begin2(); it.valid(); it.next()) { static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; const ConnectionToId& connectionToId(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id > 0); uint otherGroup, otherPort, carlaPort; if (connectionToId.groupA == kExternalGraphGroupCarla) { CARLA_SAFE_ASSERT_CONTINUE(connectionToId.groupB != kExternalGraphGroupCarla); carlaPort = connectionToId.portA; otherGroup = connectionToId.groupB; otherPort = connectionToId.portB; } else { CARLA_SAFE_ASSERT_CONTINUE(connectionToId.groupB == kExternalGraphGroupCarla); carlaPort = connectionToId.portB; otherGroup = connectionToId.groupA; otherPort = connectionToId.portA; } CARLA_SAFE_ASSERT_CONTINUE(carlaPort > kExternalGraphCarlaPortNull && carlaPort < kExternalGraphCarlaPortMax); CARLA_SAFE_ASSERT_CONTINUE(otherGroup > kExternalGraphGroupCarla && otherGroup < kExternalGraphGroupMax); switch (carlaPort) { case kExternalGraphCarlaPortAudioIn1: case kExternalGraphCarlaPortAudioIn2: std::snprintf(strBuf, STR_MAX, "AudioIn:%s", audioPorts.getName(true, otherPort)); connList.append(strBuf); connList.append(getExternalGraphFullPortNameFromId(carlaPort)); break; case kExternalGraphCarlaPortAudioOut1: case kExternalGraphCarlaPortAudioOut2: std::snprintf(strBuf, STR_MAX, "AudioOut:%s", audioPorts.getName(false, otherPort)); connList.append(getExternalGraphFullPortNameFromId(carlaPort)); connList.append(strBuf); break; case kExternalGraphCarlaPortMidiIn: std::snprintf(strBuf, STR_MAX, "MidiIn:%s", midiPorts.getName(true, otherPort)); connList.append(strBuf); connList.append(getExternalGraphFullPortNameFromId(carlaPort)); break; case kExternalGraphCarlaPortMidiOut: std::snprintf(strBuf, STR_MAX, "MidiOut:%s", midiPorts.getName(false, otherPort)); connList.append(getExternalGraphFullPortNameFromId(carlaPort)); connList.append(strBuf); break; } } if (connList.count() == 0) return nullptr; retCon = connList.toCharStringListPtr(); return retCon; } bool ExternalGraph::getGroupAndPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) const noexcept { CARLA_SAFE_ASSERT_RETURN(fullPortName != nullptr && fullPortName[0] != '\0', false); if (std::strncmp(fullPortName, "Carla:", 6) == 0) { groupId = kExternalGraphGroupCarla; portId = getExternalGraphPortIdFromName(fullPortName+6); if (portId > kExternalGraphCarlaPortNull && portId < kExternalGraphCarlaPortMax) return true; } else if (std::strncmp(fullPortName, "AudioIn:", 8) == 0) { groupId = kExternalGraphGroupAudioIn; if (const char* const portName = fullPortName+8) { bool ok; portId = audioPorts.getPortId(true, portName, &ok); return ok; } } else if (std::strncmp(fullPortName, "AudioOut:", 9) == 0) { groupId = kExternalGraphGroupAudioOut; if (const char* const portName = fullPortName+9) { bool ok; portId = audioPorts.getPortId(false, portName, &ok); return ok; } } else if (std::strncmp(fullPortName, "MidiIn:", 7) == 0) { groupId = kExternalGraphGroupMidiIn; if (const char* const portName = fullPortName+7) { bool ok; portId = midiPorts.getPortId(true, portName, &ok); return ok; } } else if (std::strncmp(fullPortName, "MidiOut:", 8) == 0) { groupId = kExternalGraphGroupMidiOut; if (const char* const portName = fullPortName+8) { bool ok; portId = midiPorts.getPortId(false, portName, &ok); return ok; } } return false; } // ----------------------------------------------------------------------- // RackGraph Buffers RackGraph::Buffers::Buffers() noexcept : mutex(), connectedIn1(), connectedIn2(), connectedOut1(), connectedOut2(), #ifdef CARLA_PROPER_CPP11_SUPPORT inBuf{nullptr, nullptr}, inBufTmp{nullptr, nullptr}, outBuf{nullptr, nullptr}, #endif unusedBuf(nullptr) { #ifndef CARLA_PROPER_CPP11_SUPPORT inBuf[0] = inBuf[1] = nullptr; inBufTmp[0] = inBufTmp[1] = nullptr; outBuf[0] = outBuf[1] = nullptr; #endif } RackGraph::Buffers::~Buffers() noexcept { const CarlaRecursiveMutexLocker cml(mutex); if (inBuf[0] != nullptr) { delete[] inBuf[0]; inBuf[0] = nullptr; } if (inBuf[1] != nullptr) { delete[] inBuf[1]; inBuf[1] = nullptr; } if (inBufTmp[0] != nullptr) { delete[] inBufTmp[0]; inBufTmp[0] = nullptr; } if (inBufTmp[1] != nullptr) { delete[] inBufTmp[1]; inBufTmp[1] = nullptr; } if (outBuf[0] != nullptr) { delete[] outBuf[0]; outBuf[0] = nullptr; } if (outBuf[1] != nullptr) { delete[] outBuf[1]; outBuf[1] = nullptr; } if (unusedBuf != nullptr) { delete[] unusedBuf; unusedBuf = nullptr; } connectedIn1.clear(); connectedIn2.clear(); connectedOut1.clear(); connectedOut2.clear(); } void RackGraph::Buffers::setBufferSize(const uint32_t bufferSize, const bool createBuffers) noexcept { const CarlaRecursiveMutexLocker cml(mutex); if (inBuf[0] != nullptr) { delete[] inBuf[0]; inBuf[0] = nullptr; } if (inBuf[1] != nullptr) { delete[] inBuf[1]; inBuf[1] = nullptr; } if (inBufTmp[0] != nullptr) { delete[] inBufTmp[0]; inBufTmp[0] = nullptr; } if (inBufTmp[1] != nullptr) { delete[] inBufTmp[1]; inBufTmp[1] = nullptr; } if (outBuf[0] != nullptr) { delete[] outBuf[0]; outBuf[0] = nullptr; } if (outBuf[1] != nullptr) { delete[] outBuf[1]; outBuf[1] = nullptr; } if (unusedBuf != nullptr) { delete[] unusedBuf; unusedBuf = nullptr; } CARLA_SAFE_ASSERT_RETURN(bufferSize > 0,); try { inBufTmp[0] = new float[bufferSize]; inBufTmp[1] = new float[bufferSize]; unusedBuf = new float[bufferSize]; if (createBuffers) { inBuf[0] = new float[bufferSize]; inBuf[1] = new float[bufferSize]; outBuf[0] = new float[bufferSize]; outBuf[1] = new float[bufferSize]; } } catch(...) { if (inBufTmp[0] != nullptr) { delete[] inBufTmp[0]; inBufTmp[0] = nullptr; } if (inBufTmp[1] != nullptr) { delete[] inBufTmp[1]; inBufTmp[1] = nullptr; } if (unusedBuf != nullptr) { delete[] unusedBuf; unusedBuf = nullptr; } if (createBuffers) { if (inBuf[0] != nullptr) { delete[] inBuf[0]; inBuf[0] = nullptr; } if (inBuf[1] != nullptr) { delete[] inBuf[1]; inBuf[1] = nullptr; } if (outBuf[0] != nullptr) { delete[] outBuf[0]; outBuf[0] = nullptr; } if (outBuf[1] != nullptr) { delete[] outBuf[1]; outBuf[1] = nullptr; } } return; } carla_zeroFloats(inBufTmp[0], bufferSize); carla_zeroFloats(inBufTmp[1], bufferSize); if (createBuffers) { carla_zeroFloats(inBuf[0], bufferSize); carla_zeroFloats(inBuf[1], bufferSize); carla_zeroFloats(outBuf[0], bufferSize); carla_zeroFloats(outBuf[1], bufferSize); } } // ----------------------------------------------------------------------- // RackGraph RackGraph::RackGraph(CarlaEngine* const engine, const uint32_t ins, const uint32_t outs) noexcept : extGraph(engine), inputs(ins), outputs(outs), isOffline(false), audioBuffers(), kEngine(engine) { setBufferSize(engine->getBufferSize()); } RackGraph::~RackGraph() noexcept { extGraph.clear(); } void RackGraph::setBufferSize(const uint32_t bufferSize) noexcept { audioBuffers.setBufferSize(bufferSize, (inputs > 0 || outputs > 0)); } void RackGraph::setOffline(const bool offline) noexcept { isOffline = offline; } bool RackGraph::connect(const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept { return extGraph.connect(true, true, groupA, portA, groupB, portB); } bool RackGraph::disconnect(const uint connectionId) noexcept { return extGraph.disconnect(true, true, connectionId); } void RackGraph::refresh(const bool sendHost, const bool sendOSC, const bool, const char* const deviceName) { extGraph.refresh(sendHost, sendOSC, deviceName); char strBuf[STR_MAX+1]; strBuf[STR_MAX] = '\0'; // Connections const CarlaRecursiveMutexLocker cml(audioBuffers.mutex); for (LinkedList::Itenerator it = audioBuffers.connectedIn1.begin2(); it.valid(); it.next()) { const uint& portId(it.getValue(0)); CARLA_SAFE_ASSERT_CONTINUE(portId > 0); CARLA_SAFE_ASSERT_CONTINUE(portId <= extGraph.audioPorts.ins.count()); ConnectionToId connectionToId; connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupAudioIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioIn1); std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); extGraph.connections.list.append(connectionToId); } for (LinkedList::Itenerator it = audioBuffers.connectedIn2.begin2(); it.valid(); it.next()) { const uint& portId(it.getValue(0)); CARLA_SAFE_ASSERT_CONTINUE(portId > 0); CARLA_SAFE_ASSERT_CONTINUE(portId <= extGraph.audioPorts.ins.count()); ConnectionToId connectionToId; connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupAudioIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioIn2); std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); extGraph.connections.list.append(connectionToId); } for (LinkedList::Itenerator it = audioBuffers.connectedOut1.begin2(); it.valid(); it.next()) { const uint& portId(it.getValue(0)); CARLA_SAFE_ASSERT_CONTINUE(portId > 0); CARLA_SAFE_ASSERT_CONTINUE(portId <= extGraph.audioPorts.outs.count()); ConnectionToId connectionToId; connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioOut1, kExternalGraphGroupAudioOut, portId); std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); extGraph.connections.list.append(connectionToId); } for (LinkedList::Itenerator it = audioBuffers.connectedOut2.begin2(); it.valid(); it.next()) { const uint& portId(it.getValue(0)); CARLA_SAFE_ASSERT_CONTINUE(portId > 0); CARLA_SAFE_ASSERT_CONTINUE(portId <= extGraph.audioPorts.outs.count()); ConnectionToId connectionToId; connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioOut2, kExternalGraphGroupAudioOut, portId); std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); extGraph.connections.list.append(connectionToId); } } const char* const* RackGraph::getConnections() const noexcept { return extGraph.getConnections(); } bool RackGraph::getGroupAndPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) const noexcept { return extGraph.getGroupAndPortIdFromFullName(fullPortName, groupId, portId); } void RackGraph::process(CarlaEngine::ProtectedData* const data, const float* inBufReal[2], float* outBufReal[2], const uint32_t frames) { CARLA_SAFE_ASSERT_RETURN(data != nullptr,); CARLA_SAFE_ASSERT_RETURN(data->events.in != nullptr,); CARLA_SAFE_ASSERT_RETURN(data->events.out != nullptr,); // safe copy float* const dummyBuf = audioBuffers.unusedBuf; float* const inBuf0 = audioBuffers.inBufTmp[0]; float* const inBuf1 = audioBuffers.inBufTmp[1]; // initialize audio inputs carla_copyFloats(inBuf0, inBufReal[0], frames); carla_copyFloats(inBuf1, inBufReal[1], frames); // initialize audio outputs (zero) carla_zeroFloats(outBufReal[0], frames); carla_zeroFloats(outBufReal[1], frames); // initialize event outputs (zero) carla_zeroStructs(data->events.out, kMaxEngineEventInternalCount); uint32_t oldAudioInCount = 0; uint32_t oldAudioOutCount = 0; uint32_t oldMidiOutCount = 0; bool processed = false; // process plugins for (uint i=0; i < data->curPluginCount; ++i) { CarlaPlugin* const plugin = data->plugins[i].plugin; if (plugin == nullptr || ! plugin->isEnabled() || ! plugin->tryLock(isOffline)) continue; if (processed) { // initialize audio inputs (from previous outputs) carla_copyFloats(inBuf0, outBufReal[0], frames); carla_copyFloats(inBuf1, outBufReal[1], frames); // initialize audio outputs (zero) carla_zeroFloats(outBufReal[0], frames); carla_zeroFloats(outBufReal[1], frames); // if plugin has no midi out, add previous events if (oldMidiOutCount == 0 && data->events.in[0].type != kEngineEventTypeNull) { if (data->events.out[0].type != kEngineEventTypeNull) { // TODO: carefully add to input, sorted events //carla_stderr("TODO midi event mixing here %s", plugin->getName()); } // else nothing needed } else { // initialize event inputs from previous outputs carla_copyStructs(data->events.in, data->events.out, kMaxEngineEventInternalCount); // initialize event outputs (zero) carla_zeroStructs(data->events.out, kMaxEngineEventInternalCount); } } oldAudioInCount = plugin->getAudioInCount(); oldAudioOutCount = plugin->getAudioOutCount(); oldMidiOutCount = plugin->getMidiOutCount(); const uint32_t numInBufs = std::max(oldAudioInCount, 2U); const uint32_t numOutBufs = std::max(oldAudioOutCount, 2U); const float* inBuf[numInBufs]; inBuf[0] = inBuf0; inBuf[1] = inBuf1; float* outBuf[numOutBufs]; outBuf[0] = outBufReal[0]; outBuf[1] = outBufReal[1]; if (numInBufs > 2 || numOutBufs > 2) { carla_zeroFloats(dummyBuf, frames); for (uint32_t j=2; jinitBuffers(); plugin->process(inBuf, outBuf, nullptr, nullptr, frames); plugin->unlock(); // if plugin has no audio inputs, add input buffer if (oldAudioInCount == 0) { carla_addFloats(outBufReal[0], inBuf0, frames); carla_addFloats(outBufReal[1], inBuf1, frames); } // if plugin only has 1 output, copy it to the 2nd if (oldAudioOutCount == 1) { carla_copyFloats(outBufReal[1], outBufReal[0], frames); } // set peaks { EnginePluginData& pluginData(data->plugins[i]); if (oldAudioInCount > 0) { pluginData.peaks[0] = carla_findMaxNormalizedFloat(inBuf0, frames); pluginData.peaks[1] = carla_findMaxNormalizedFloat(inBuf1, frames); } else { pluginData.peaks[0] = 0.0f; pluginData.peaks[1] = 0.0f; } if (oldAudioOutCount > 0) { pluginData.peaks[2] = carla_findMaxNormalizedFloat(outBufReal[0], frames); pluginData.peaks[3] = carla_findMaxNormalizedFloat(outBufReal[1], frames); } else { pluginData.peaks[2] = 0.0f; pluginData.peaks[3] = 0.0f; } } processed = true; } } void RackGraph::processHelper(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const uint32_t frames) { CARLA_SAFE_ASSERT_RETURN(audioBuffers.outBuf[1] != nullptr,); const CarlaRecursiveMutexLocker _cml(audioBuffers.mutex); if (inBuf != nullptr && inputs > 0) { bool noConnections = true; // connect input buffers for (LinkedList::Itenerator it = audioBuffers.connectedIn1.begin2(); it.valid(); it.next()) { const uint& port(it.getValue(0)); CARLA_SAFE_ASSERT_CONTINUE(port > 0); CARLA_SAFE_ASSERT_CONTINUE(port <= inputs); if (noConnections) { carla_copyFloats(audioBuffers.inBuf[0], inBuf[port], frames); noConnections = false; } else { carla_addFloats(audioBuffers.inBuf[0], inBuf[port], frames); } } if (noConnections) carla_zeroFloats(audioBuffers.inBuf[0], frames); noConnections = true; for (LinkedList::Itenerator it = audioBuffers.connectedIn2.begin2(); it.valid(); it.next()) { const uint& port(it.getValue(0)); CARLA_SAFE_ASSERT_CONTINUE(port > 0); CARLA_SAFE_ASSERT_CONTINUE(port <= inputs); if (noConnections) { carla_copyFloats(audioBuffers.inBuf[1], inBuf[port-1], frames); noConnections = false; } else { carla_addFloats(audioBuffers.inBuf[1], inBuf[port-1], frames); } } if (noConnections) carla_zeroFloats(audioBuffers.inBuf[1], frames); } else { carla_zeroFloats(audioBuffers.inBuf[0], frames); carla_zeroFloats(audioBuffers.inBuf[1], frames); } carla_zeroFloats(audioBuffers.outBuf[0], frames); carla_zeroFloats(audioBuffers.outBuf[1], frames); // process process(data, const_cast(audioBuffers.inBuf), audioBuffers.outBuf, frames); // connect output buffers if (audioBuffers.connectedOut1.count() != 0) { for (LinkedList::Itenerator it = audioBuffers.connectedOut1.begin2(); it.valid(); it.next()) { const uint& port(it.getValue(0)); CARLA_SAFE_ASSERT_CONTINUE(port > 0); CARLA_SAFE_ASSERT_CONTINUE(port <= outputs); carla_addFloats(outBuf[port-1], audioBuffers.outBuf[0], frames); } } if (audioBuffers.connectedOut2.count() != 0) { for (LinkedList::Itenerator it = audioBuffers.connectedOut2.begin2(); it.valid(); it.next()) { const uint& port(it.getValue(0)); CARLA_SAFE_ASSERT_CONTINUE(port > 0); CARLA_SAFE_ASSERT_CONTINUE(port <= outputs); carla_addFloats(outBuf[port-1], audioBuffers.outBuf[1], frames); } } } // ----------------------------------------------------------------------- // Patchbay Graph stuff static const uint32_t kMaxPortsPerPlugin = 255; static const uint32_t kAudioInputPortOffset = kMaxPortsPerPlugin*1; static const uint32_t kAudioOutputPortOffset = kMaxPortsPerPlugin*2; static const uint32_t kCVInputPortOffset = kMaxPortsPerPlugin*3; static const uint32_t kCVOutputPortOffset = kMaxPortsPerPlugin*4; static const uint32_t kMidiInputPortOffset = kMaxPortsPerPlugin*5; static const uint32_t kMidiOutputPortOffset = kMaxPortsPerPlugin*6; static const uint32_t kMaxPortOffset = kMaxPortsPerPlugin*7; static inline bool adjustPatchbayPortIdForWater(AudioProcessor::ChannelType& channelType, uint& portId) { CARLA_SAFE_ASSERT_RETURN(portId >= kAudioInputPortOffset, false); CARLA_SAFE_ASSERT_RETURN(portId < kMaxPortOffset, false); if (portId >= kMidiOutputPortOffset) { portId -= kMidiOutputPortOffset; channelType = AudioProcessor::ChannelTypeMIDI; return true; } if (portId >= kMidiInputPortOffset) { portId -= kMidiInputPortOffset; channelType = AudioProcessor::ChannelTypeMIDI; return true; } if (portId >= kCVOutputPortOffset) { portId -= kCVOutputPortOffset; channelType = AudioProcessor::ChannelTypeCV; return true; } if (portId >= kCVInputPortOffset) { portId -= kCVInputPortOffset; channelType = AudioProcessor::ChannelTypeCV; return true; } if (portId >= kAudioOutputPortOffset) { portId -= kAudioOutputPortOffset; channelType = AudioProcessor::ChannelTypeAudio; return true; } if (portId >= kAudioInputPortOffset) { portId -= kAudioInputPortOffset; channelType = AudioProcessor::ChannelTypeAudio; return true; } return false; } static inline const String getProcessorFullPortName(AudioProcessor* const proc, const uint32_t portId) { CARLA_SAFE_ASSERT_RETURN(proc != nullptr, String()); CARLA_SAFE_ASSERT_RETURN(portId >= kAudioInputPortOffset, String()); CARLA_SAFE_ASSERT_RETURN(portId < kMaxPortOffset, String()); String fullPortName(proc->getName()); /**/ if (portId >= kMidiOutputPortOffset) { CARLA_SAFE_ASSERT_RETURN(proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeMIDI) > 0, String()); fullPortName += ":" + proc->getOutputChannelName(AudioProcessor::ChannelTypeMIDI, portId-kMidiOutputPortOffset); } else if (portId >= kMidiInputPortOffset) { CARLA_SAFE_ASSERT_RETURN(proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeMIDI) > 0, String()); fullPortName += ":" + proc->getInputChannelName(AudioProcessor::ChannelTypeMIDI, portId-kMidiInputPortOffset); } else if (portId >= kCVOutputPortOffset) { CARLA_SAFE_ASSERT_RETURN(proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeCV) > 0, String()); fullPortName += ":" + proc->getOutputChannelName(AudioProcessor::ChannelTypeCV, portId-kCVOutputPortOffset); } else if (portId >= kCVInputPortOffset) { CARLA_SAFE_ASSERT_RETURN(proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeCV) > 0, String()); fullPortName += ":" + proc->getInputChannelName(AudioProcessor::ChannelTypeCV, portId-kCVInputPortOffset); } else if (portId >= kAudioOutputPortOffset) { CARLA_SAFE_ASSERT_RETURN(proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeAudio) > 0, String()); fullPortName += ":" + proc->getOutputChannelName(AudioProcessor::ChannelTypeAudio, portId-kAudioOutputPortOffset); } else if (portId >= kAudioInputPortOffset) { CARLA_SAFE_ASSERT_RETURN(proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeAudio) > 0, String()); fullPortName += ":" + proc->getInputChannelName(AudioProcessor::ChannelTypeAudio, portId-kAudioInputPortOffset); } else { return String(); } return fullPortName; } static inline void addNodeToPatchbay(const bool sendHost, const bool sendOSC, CarlaEngine* const engine, const uint32_t groupId, const int clientId, const AudioProcessor* const proc) { CARLA_SAFE_ASSERT_RETURN(engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(proc != nullptr,); engine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupId, clientId >= 0 ? PATCHBAY_ICON_PLUGIN : PATCHBAY_ICON_HARDWARE, clientId, 0, 0.0f, proc->getName().toRawUTF8()); for (uint i=0, numInputs=proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeAudio); icallback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, groupId, static_cast(kAudioInputPortOffset+i), PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0, 0.0f, proc->getInputChannelName(AudioProcessor::ChannelTypeAudio, i).toRawUTF8()); } for (uint i=0, numOutputs=proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeAudio); icallback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, groupId, static_cast(kAudioOutputPortOffset+i), PATCHBAY_PORT_TYPE_AUDIO, 0, 0.0f, proc->getOutputChannelName(AudioProcessor::ChannelTypeAudio, i).toRawUTF8()); } for (uint i=0, numInputs=proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeCV); icallback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, groupId, static_cast(kCVInputPortOffset+i), PATCHBAY_PORT_TYPE_CV|PATCHBAY_PORT_IS_INPUT, 0, 0.0f, proc->getInputChannelName(AudioProcessor::ChannelTypeCV, i).toRawUTF8()); } for (uint i=0, numOutputs=proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeCV); icallback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, groupId, static_cast(kCVOutputPortOffset+i), PATCHBAY_PORT_TYPE_CV, 0, 0.0f, proc->getOutputChannelName(AudioProcessor::ChannelTypeCV, i).toRawUTF8()); } for (uint i=0, numInputs=proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeMIDI); icallback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, groupId, static_cast(kMidiInputPortOffset+i), PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0, 0.0f, proc->getInputChannelName(AudioProcessor::ChannelTypeMIDI, i).toRawUTF8()); } for (uint i=0, numOutputs=proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeMIDI); icallback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, groupId, static_cast(kMidiOutputPortOffset+i), PATCHBAY_PORT_TYPE_MIDI, 0, 0.0f, proc->getOutputChannelName(AudioProcessor::ChannelTypeMIDI, i).toRawUTF8()); } } static inline void removeNodeFromPatchbay(const bool sendHost, const bool sendOSC, CarlaEngine* const engine, const uint32_t groupId, const AudioProcessor* const proc) { CARLA_SAFE_ASSERT_RETURN(engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(proc != nullptr,); for (uint i=0, numInputs=proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeAudio); icallback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, groupId, static_cast(kAudioInputPortOffset+i), 0, 0, 0.0f, nullptr); } for (uint i=0, numOutputs=proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeAudio); icallback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, groupId, static_cast(kAudioOutputPortOffset+i), 0, 0, 0.0f, nullptr); } for (uint i=0, numInputs=proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeCV); icallback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, groupId, static_cast(kCVInputPortOffset+i), 0, 0, 0.0f, nullptr); } for (uint i=0, numOutputs=proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeCV); icallback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, groupId, static_cast(kCVOutputPortOffset+i), 0, 0, 0.0f, nullptr); } for (uint i=0, numInputs=proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeMIDI); icallback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, groupId, static_cast(kMidiInputPortOffset+i), 0, 0, 0.0f, nullptr); } for (uint i=0, numOutputs=proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeMIDI); icallback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, groupId, static_cast(kMidiOutputPortOffset+i), 0, 0, 0.0f, nullptr); } engine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CLIENT_REMOVED, groupId, 0, 0, 0, 0.0f, nullptr); } // ----------------------------------------------------------------------- class CarlaPluginInstance : public AudioProcessor { public: CarlaPluginInstance(CarlaEngine* const engine, CarlaPlugin* const plugin) : kEngine(engine), fPlugin(plugin) { CarlaEngineClient* const client = plugin->getEngineClient(); setPlayConfigDetails(client->getPortCount(kEnginePortTypeAudio, true), client->getPortCount(kEnginePortTypeAudio, false), client->getPortCount(kEnginePortTypeCV, true), client->getPortCount(kEnginePortTypeCV, false), client->getPortCount(kEnginePortTypeEvent, true), client->getPortCount(kEnginePortTypeEvent, false), getSampleRate(), getBlockSize()); } ~CarlaPluginInstance() override { } void reconfigure() override { CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,); CarlaEngineClient* const client = fPlugin->getEngineClient(); CARLA_SAFE_ASSERT_RETURN(client != nullptr,); carla_stdout("reconfigure called"); setPlayConfigDetails(client->getPortCount(kEnginePortTypeAudio, true), client->getPortCount(kEnginePortTypeAudio, false), client->getPortCount(kEnginePortTypeCV, true), client->getPortCount(kEnginePortTypeCV, false), client->getPortCount(kEnginePortTypeEvent, true), client->getPortCount(kEnginePortTypeEvent, false), getSampleRate(), getBlockSize()); } void invalidatePlugin() noexcept { fPlugin = nullptr; } // ------------------------------------------------------------------- const String getName() const override { return fPlugin->getName(); } void processBlockWithCV(AudioSampleBuffer& audio, const AudioSampleBuffer& cvIn, AudioSampleBuffer& cvOut, MidiBuffer& midi) override { if (fPlugin == nullptr || ! fPlugin->isEnabled() || ! fPlugin->tryLock(kEngine->isOffline())) { audio.clear(); cvOut.clear(); midi.clear(); return; } if (CarlaEngineEventPort* const port = fPlugin->getDefaultEventInPort()) { EngineEvent* const engineEvents(port->fBuffer); CARLA_SAFE_ASSERT_RETURN(engineEvents != nullptr,); carla_zeroStructs(engineEvents, kMaxEngineEventInternalCount); fillEngineEventsFromWaterMidiBuffer(engineEvents, midi); } midi.clear(); fPlugin->initBuffers(); const uint32_t numSamples = audio.getNumSamples(); const uint32_t numAudioChan = audio.getNumChannels(); const uint32_t numCVInChan = cvIn.getNumChannels(); const uint32_t numCVOutChan = cvOut.getNumChannels(); if (numAudioChan+numCVInChan+numCVOutChan == 0) { // nothing to process fPlugin->process(nullptr, nullptr, nullptr, nullptr, numSamples); } else if (numAudioChan != 0) { // processing audio, include code for peaks const uint32_t numChan2 = jmin(numAudioChan, 2U); if (fPlugin->getAudioInCount() == 0) audio.clear(); float* audioBuffers[numAudioChan]; float* cvOutBuffers[numCVOutChan]; const float* cvInBuffers[numCVInChan]; for (uint32_t i=0; igetAudioInCount(), numChan2); iprocess(const_cast(audioBuffers), audioBuffers, cvInBuffers, cvOutBuffers, numSamples); for (uint32_t i=0, count=jmin(fPlugin->getAudioOutCount(), numChan2); isetPluginPeaksRT(fPlugin->getId(), inPeaks, outPeaks); } else { // processing CV only, skip audiopeaks float* cvOutBuffers[numCVOutChan]; const float* cvInBuffers[numCVInChan]; for (uint32_t i=0; iprocess(nullptr, nullptr, cvInBuffers, cvOutBuffers, numSamples); } midi.clear(); if (CarlaEngineEventPort* const port = fPlugin->getDefaultEventOutPort()) { /*const*/ EngineEvent* const engineEvents(port->fBuffer); CARLA_SAFE_ASSERT_RETURN(engineEvents != nullptr,); fillWaterMidiBufferFromEngineEvents(midi, engineEvents); carla_zeroStructs(engineEvents, kMaxEngineEventInternalCount); } fPlugin->unlock(); } const String getInputChannelName(ChannelType t, uint i) const override { CarlaEngineClient* const client = fPlugin->getEngineClient(); switch (t) { case ChannelTypeAudio: return client->getAudioPortName(true, i); case ChannelTypeCV: return client->getCVPortName(true, i); case ChannelTypeMIDI: return client->getEventPortName(true, i); } return String(); } const String getOutputChannelName(ChannelType t, uint i) const override { CarlaEngineClient* const client(fPlugin->getEngineClient()); switch (t) { case ChannelTypeAudio: return client->getAudioPortName(false, i); case ChannelTypeCV: return client->getCVPortName(false, i); case ChannelTypeMIDI: return client->getEventPortName(false, i); } return String(); } void prepareToPlay(double, int) override {} void releaseResources() override {} bool acceptsMidi() const override { return fPlugin->getDefaultEventInPort() != nullptr; } bool producesMidi() const override { return fPlugin->getDefaultEventOutPort() != nullptr; } private: CarlaEngine* const kEngine; CarlaPlugin* fPlugin; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginInstance) }; // ----------------------------------------------------------------------- // Patchbay Graph class NamedAudioGraphIOProcessor : public AudioProcessorGraph::AudioGraphIOProcessor { public: NamedAudioGraphIOProcessor(const IODeviceType iotype) : AudioProcessorGraph::AudioGraphIOProcessor(iotype), inputNames(), outputNames() {} const String getInputChannelName (ChannelType, uint _index) const override { const int index = static_cast(_index); // FIXME if (index < inputNames.size()) return inputNames[index]; return String("Playback ") + String(index+1); } const String getOutputChannelName (ChannelType, uint _index) const override { const int index = static_cast(_index); // FIXME if (index < outputNames.size()) return outputNames[index]; return String("Capture ") + String(index+1); } void setNames(const bool setInputNames, const StringArray& names) { if (setInputNames) inputNames = names; else outputNames = names; } private: StringArray inputNames; StringArray outputNames; }; PatchbayGraph::PatchbayGraph(CarlaEngine* const engine, const uint32_t audioIns, const uint32_t audioOuts, const uint32_t cvIns, const uint32_t cvOuts) : CarlaThread("PatchbayReorderThread"), connections(), graph(), audioBuffer(), cvInBuffer(), cvOutBuffer(), midiBuffer(), numAudioIns(carla_fixedValue(0U, 64U, audioIns)), numAudioOuts(carla_fixedValue(0U, 64U, audioOuts)), numCVIns(carla_fixedValue(0U, 8U, cvIns)), numCVOuts(carla_fixedValue(0U, 8U, cvOuts)), retCon(), usingExternalHost(false), usingExternalOSC(false), extGraph(engine), kEngine(engine) { const uint32_t bufferSize(engine->getBufferSize()); const double sampleRate(engine->getSampleRate()); graph.setPlayConfigDetails(numAudioIns, numAudioOuts, numCVIns, numCVOuts, 1, 1, sampleRate, static_cast(bufferSize)); graph.prepareToPlay(sampleRate, static_cast(bufferSize)); audioBuffer.setSize(jmax(numAudioIns, numAudioOuts), bufferSize); cvInBuffer.setSize(numCVIns, bufferSize); cvOutBuffer.setSize(numCVOuts, bufferSize); midiBuffer.ensureSize(kMaxEngineEventInternalCount*2); midiBuffer.clear(); StringArray channelNames; switch (numAudioIns) { case 2: channelNames.add("Left"); channelNames.add("Right"); break; case 3: channelNames.add("Left"); channelNames.add("Right"); channelNames.add("Sidechain"); break; } if (numAudioIns != 0) { NamedAudioGraphIOProcessor* const proc( new NamedAudioGraphIOProcessor(NamedAudioGraphIOProcessor::audioInputNode)); proc->setNames(false, channelNames); AudioProcessorGraph::Node* const node(graph.addNode(proc)); node->properties.set("isPlugin", false); node->properties.set("isOutput", false); node->properties.set("isAudio", true); node->properties.set("isCV", false); node->properties.set("isMIDI", false); node->properties.set("isOSC", false); } if (numAudioOuts != 0) { NamedAudioGraphIOProcessor* const proc( new NamedAudioGraphIOProcessor(NamedAudioGraphIOProcessor::audioOutputNode)); proc->setNames(true, channelNames); AudioProcessorGraph::Node* const node(graph.addNode(proc)); node->properties.set("isPlugin", false); node->properties.set("isOutput", false); node->properties.set("isAudio", true); node->properties.set("isCV", false); node->properties.set("isMIDI", false); node->properties.set("isOSC", false); } if (numCVIns != 0) { NamedAudioGraphIOProcessor* const proc( new NamedAudioGraphIOProcessor(NamedAudioGraphIOProcessor::cvInputNode)); // proc->setNames(false, channelNames); AudioProcessorGraph::Node* const node(graph.addNode(proc)); node->properties.set("isPlugin", false); node->properties.set("isOutput", false); node->properties.set("isAudio", false); node->properties.set("isCV", true); node->properties.set("isMIDI", false); node->properties.set("isOSC", false); } if (numCVOuts != 0) { NamedAudioGraphIOProcessor* const proc( new NamedAudioGraphIOProcessor(NamedAudioGraphIOProcessor::cvOutputNode)); // proc->setNames(true, channelNames); AudioProcessorGraph::Node* const node(graph.addNode(proc)); node->properties.set("isPlugin", false); node->properties.set("isOutput", false); node->properties.set("isAudio", false); node->properties.set("isCV", true); node->properties.set("isMIDI", false); node->properties.set("isOSC", false); } { NamedAudioGraphIOProcessor* const proc( new NamedAudioGraphIOProcessor(NamedAudioGraphIOProcessor::midiInputNode)); AudioProcessorGraph::Node* const node(graph.addNode(proc)); node->properties.set("isPlugin", false); node->properties.set("isOutput", false); node->properties.set("isAudio", false); node->properties.set("isCV", false); node->properties.set("isMIDI", true); node->properties.set("isOSC", false); } { NamedAudioGraphIOProcessor* const proc( new NamedAudioGraphIOProcessor(NamedAudioGraphIOProcessor::midiOutputNode)); AudioProcessorGraph::Node* const node(graph.addNode(proc)); node->properties.set("isPlugin", false); node->properties.set("isOutput", true); node->properties.set("isAudio", false); node->properties.set("isCV", false); node->properties.set("isMIDI", true); node->properties.set("isOSC", false); } startThread(); } PatchbayGraph::~PatchbayGraph() { stopThread(-1); connections.clear(); extGraph.clear(); graph.releaseResources(); graph.clear(); audioBuffer.clear(); cvInBuffer.clear(); cvOutBuffer.clear(); } void PatchbayGraph::setBufferSize(const uint32_t bufferSize) { const CarlaRecursiveMutexLocker cml1(graph.getReorderMutex()); graph.releaseResources(); graph.prepareToPlay(kEngine->getSampleRate(), static_cast(bufferSize)); audioBuffer.setSize(audioBuffer.getNumChannels(), bufferSize); cvInBuffer.setSize(numCVIns, bufferSize); cvOutBuffer.setSize(numCVOuts, bufferSize); } void PatchbayGraph::setSampleRate(const double sampleRate) { const CarlaRecursiveMutexLocker cml1(graph.getReorderMutex()); graph.releaseResources(); graph.prepareToPlay(sampleRate, static_cast(kEngine->getBufferSize())); } void PatchbayGraph::setOffline(const bool offline) { graph.setNonRealtime(offline); } void PatchbayGraph::addPlugin(CarlaPlugin* const plugin) { CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("PatchbayGraph::addPlugin(%p)", plugin); CarlaPluginInstance* const instance(new CarlaPluginInstance(kEngine, plugin)); AudioProcessorGraph::Node* const node(graph.addNode(instance)); CARLA_SAFE_ASSERT_RETURN(node != nullptr,); const bool sendHost = !usingExternalHost; const bool sendOSC = !usingExternalOSC; plugin->setPatchbayNodeId(node->nodeId); node->properties.set("isPlugin", true); node->properties.set("pluginId", static_cast(plugin->getId())); addNodeToPatchbay(sendHost, sendOSC, kEngine, node->nodeId, static_cast(plugin->getId()), instance); } void PatchbayGraph::replacePlugin(CarlaPlugin* const oldPlugin, CarlaPlugin* const newPlugin) { CARLA_SAFE_ASSERT_RETURN(oldPlugin != nullptr,); CARLA_SAFE_ASSERT_RETURN(newPlugin != nullptr,); CARLA_SAFE_ASSERT_RETURN(oldPlugin != newPlugin,); CARLA_SAFE_ASSERT_RETURN(oldPlugin->getId() == newPlugin->getId(),); AudioProcessorGraph::Node* const oldNode(graph.getNodeForId(oldPlugin->getPatchbayNodeId())); CARLA_SAFE_ASSERT_RETURN(oldNode != nullptr,); const bool sendHost = !usingExternalHost; const bool sendOSC = !usingExternalOSC; disconnectInternalGroup(oldNode->nodeId); removeNodeFromPatchbay(sendHost, sendOSC, kEngine, oldNode->nodeId, oldNode->getProcessor()); ((CarlaPluginInstance*)oldNode->getProcessor())->invalidatePlugin(); graph.removeNode(oldNode->nodeId); CarlaPluginInstance* const instance(new CarlaPluginInstance(kEngine, newPlugin)); AudioProcessorGraph::Node* const node(graph.addNode(instance)); CARLA_SAFE_ASSERT_RETURN(node != nullptr,); newPlugin->setPatchbayNodeId(node->nodeId); node->properties.set("isPlugin", true); node->properties.set("pluginId", static_cast(newPlugin->getId())); addNodeToPatchbay(sendHost, sendOSC, kEngine, node->nodeId, static_cast(newPlugin->getId()), instance); } void PatchbayGraph::renamePlugin(CarlaPlugin* const plugin, const char* const newName) { CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("PatchbayGraph::renamePlugin(%p)", plugin, newName); AudioProcessorGraph::Node* const node(graph.getNodeForId(plugin->getPatchbayNodeId())); CARLA_SAFE_ASSERT_RETURN(node != nullptr,); const bool sendHost = !usingExternalHost; const bool sendOSC = !usingExternalOSC; kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CLIENT_RENAMED, node->nodeId, 0, 0, 0, 0.0f, newName); } void PatchbayGraph::reconfigureForCV(CarlaPlugin* const plugin, const uint portIndex, bool added) { CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("PatchbayGraph::reconfigureForCV(%p, %u, %s)", plugin, portIndex, bool2str(added)); AudioProcessorGraph::Node* const node = graph.getNodeForId(plugin->getPatchbayNodeId()); CARLA_SAFE_ASSERT_RETURN(node != nullptr,); CarlaPluginInstance* const proc = dynamic_cast(node->getProcessor()); CARLA_SAFE_ASSERT_RETURN(proc != nullptr,); const bool sendHost = !usingExternalHost; const bool sendOSC = !usingExternalOSC; const uint oldCvIn = proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeCV); // const uint oldCvOut = proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeCV); { const CarlaRecursiveMutexLocker crml(graph.getCallbackLock()); proc->reconfigure(); graph.buildRenderingSequence(); } const uint newCvIn = proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeCV); // const uint newCvOut = proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeCV); if (added) { CARLA_SAFE_ASSERT_UINT2_RETURN(newCvIn > oldCvIn, newCvIn, oldCvIn,); // CARLA_SAFE_ASSERT_UINT2_RETURN(newCvOut >= oldCvOut, newCvOut, oldCvOut,); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, node->nodeId, static_cast(kCVInputPortOffset + plugin->getCVInCount() + portIndex), PATCHBAY_PORT_TYPE_CV|PATCHBAY_PORT_IS_INPUT, 0, 0.0f, proc->getInputChannelName(AudioProcessor::ChannelTypeCV, portIndex).toRawUTF8()); } else { CARLA_SAFE_ASSERT_UINT2_RETURN(newCvIn < oldCvIn, newCvIn, oldCvIn,); // CARLA_SAFE_ASSERT_UINT2_RETURN(newCvOut <= oldCvOut, newCvOut, oldCvOut,); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, node->nodeId, static_cast(kCVInputPortOffset + plugin->getCVInCount() + portIndex), 0, 0, 0.0f, nullptr); } } void PatchbayGraph::removePlugin(CarlaPlugin* const plugin) { CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("PatchbayGraph::removePlugin(%p)", plugin); AudioProcessorGraph::Node* const node(graph.getNodeForId(plugin->getPatchbayNodeId())); CARLA_SAFE_ASSERT_RETURN(node != nullptr,); const bool sendHost = !usingExternalHost; const bool sendOSC = !usingExternalOSC; disconnectInternalGroup(node->nodeId); removeNodeFromPatchbay(sendHost, sendOSC, kEngine, node->nodeId, node->getProcessor()); ((CarlaPluginInstance*)node->getProcessor())->invalidatePlugin(); // Fix plugin Ids properties for (uint i=plugin->getId()+1, count=kEngine->getCurrentPluginCount(); igetPlugin(i)); CARLA_SAFE_ASSERT_BREAK(plugin2 != nullptr); if (AudioProcessorGraph::Node* const node2 = graph.getNodeForId(plugin2->getPatchbayNodeId())) { CARLA_SAFE_ASSERT_CONTINUE(node2->properties.getWithDefault("pluginId", -1) != water::var(-1)); node2->properties.set("pluginId", static_cast(i-1)); } } CARLA_SAFE_ASSERT_RETURN(graph.removeNode(node->nodeId),); } void PatchbayGraph::removeAllPlugins() { carla_debug("PatchbayGraph::removeAllPlugins()"); const bool sendHost = !usingExternalHost; const bool sendOSC = !usingExternalOSC; for (uint i=0, count=kEngine->getCurrentPluginCount(); igetPlugin(i)); CARLA_SAFE_ASSERT_CONTINUE(plugin != nullptr); AudioProcessorGraph::Node* const node(graph.getNodeForId(plugin->getPatchbayNodeId())); CARLA_SAFE_ASSERT_CONTINUE(node != nullptr); disconnectInternalGroup(node->nodeId); removeNodeFromPatchbay(sendHost, sendOSC, kEngine, node->nodeId, node->getProcessor()); ((CarlaPluginInstance*)node->getProcessor())->invalidatePlugin(); graph.removeNode(node->nodeId); } } bool PatchbayGraph::connect(const bool external, const uint groupA, const uint portA, const uint groupB, const uint portB) { if (external) return extGraph.connect(usingExternalHost, usingExternalOSC, groupA, portA, groupB, portB); uint adjustedPortA = portA; uint adjustedPortB = portB; AudioProcessor::ChannelType channelType; if (! adjustPatchbayPortIdForWater(channelType, adjustedPortA)) return false; if (! adjustPatchbayPortIdForWater(channelType, adjustedPortB)) return false; if (! graph.addConnection(channelType, groupA, adjustedPortA, groupB, adjustedPortB)) { kEngine->setLastError("Failed from water"); return false; } ConnectionToId connectionToId; connectionToId.setData(++connections.lastId, groupA, portA, groupB, portB); char strBuf[STR_MAX+1]; strBuf[STR_MAX] = '\0'; std::snprintf(strBuf, STR_MAX, "%u:%u:%u:%u", groupA, portA, groupB, portB); kEngine->callback(!usingExternalHost, !usingExternalOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); connections.list.append(connectionToId); return true; } bool PatchbayGraph::disconnect(const bool external, const uint connectionId) { if (external) return extGraph.disconnect(usingExternalHost, usingExternalOSC, connectionId); for (LinkedList::Itenerator it=connections.list.begin2(); it.valid(); it.next()) { static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; const ConnectionToId& connectionToId(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id > 0); if (connectionToId.id != connectionId) continue; uint adjustedPortA = connectionToId.portA; uint adjustedPortB = connectionToId.portB; AudioProcessor::ChannelType channelType; if (! adjustPatchbayPortIdForWater(channelType, adjustedPortA)) return false; if (! adjustPatchbayPortIdForWater(channelType, adjustedPortB)) return false; if (! graph.removeConnection(channelType, connectionToId.groupA, adjustedPortA, connectionToId.groupB, adjustedPortB)) return false; kEngine->callback(!usingExternalHost, !usingExternalOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connectionToId.id, 0, 0, 0, 0.0f, nullptr); connections.list.remove(it); return true; } kEngine->setLastError("Failed to find connection"); return false; } void PatchbayGraph::disconnectInternalGroup(const uint groupId) noexcept { for (LinkedList::Itenerator it=connections.list.begin2(); it.valid(); it.next()) { static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; const ConnectionToId& connectionToId(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id > 0); if (connectionToId.groupA != groupId && connectionToId.groupB != groupId) continue; /* uint adjustedPortA = connectionToId.portA; uint adjustedPortB = connectionToId.portB; AudioProcessor::ChannelType channelType; if (! adjustPatchbayPortIdForWater(adjustedPortA)) return false; if (! adjustPatchbayPortIdForWater(adjustedPortB)) return false; graph.removeConnection(connectionToId.groupA, static_cast(adjustedPortA), connectionToId.groupB, static_cast(adjustedPortB)); */ kEngine->callback(!usingExternalHost, !usingExternalOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connectionToId.id, 0, 0, 0, 0.0f, nullptr); connections.list.remove(it); } } void PatchbayGraph::refresh(const bool sendHost, const bool sendOSC, const bool external, const char* const deviceName) { if (external) return extGraph.refresh(sendHost, sendOSC, deviceName); CARLA_SAFE_ASSERT_RETURN(deviceName != nullptr,); connections.clear(); graph.removeIllegalConnections(); for (int i=0, count=graph.getNumNodes(); igetProcessor()); CARLA_SAFE_ASSERT_CONTINUE(proc != nullptr); int clientId = -1; // plugin node if (node->properties.getWithDefault("isPlugin", false) == water::var(true)) clientId = node->properties.getWithDefault("pluginId", -1); addNodeToPatchbay(sendHost, sendOSC, kEngine, node->nodeId, clientId, proc); } char strBuf[STR_MAX+1]; strBuf[STR_MAX] = '\0'; for (size_t i=0, count=graph.getNumConnections(); isourceNodeId; const uint groupB = conn->destNodeId; uint portA = conn->sourceChannelIndex; uint portB = conn->destChannelIndex; switch (conn->channelType) { case AudioProcessor::ChannelTypeAudio: portA += kAudioOutputPortOffset; portB += kAudioInputPortOffset; break; case AudioProcessor::ChannelTypeCV: portA += kCVOutputPortOffset; portB += kCVInputPortOffset; break; case AudioProcessor::ChannelTypeMIDI: portA += kMidiOutputPortOffset; portB += kMidiInputPortOffset; break; } ConnectionToId connectionToId; connectionToId.setData(++connections.lastId, groupA, portA, groupB, portB); std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", groupA, portA, groupB, portB); kEngine->callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); connections.list.append(connectionToId); } } const char* const* PatchbayGraph::getConnections(const bool external) const { if (external) return extGraph.getConnections(); if (connections.list.count() == 0) return nullptr; CarlaStringList connList; for (LinkedList::Itenerator it=connections.list.begin2(); it.valid(); it.next()) { static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; const ConnectionToId& connectionToId(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id > 0); AudioProcessorGraph::Node* const nodeA(graph.getNodeForId(connectionToId.groupA)); CARLA_SAFE_ASSERT_CONTINUE(nodeA != nullptr); AudioProcessorGraph::Node* const nodeB(graph.getNodeForId(connectionToId.groupB)); CARLA_SAFE_ASSERT_CONTINUE(nodeB != nullptr); AudioProcessor* const procA(nodeA->getProcessor()); CARLA_SAFE_ASSERT_CONTINUE(procA != nullptr); AudioProcessor* const procB(nodeB->getProcessor()); CARLA_SAFE_ASSERT_CONTINUE(procB != nullptr); String fullPortNameA(getProcessorFullPortName(procA, connectionToId.portA)); CARLA_SAFE_ASSERT_CONTINUE(fullPortNameA.isNotEmpty()); String fullPortNameB(getProcessorFullPortName(procB, connectionToId.portB)); CARLA_SAFE_ASSERT_CONTINUE(fullPortNameB.isNotEmpty()); connList.append(fullPortNameA.toRawUTF8()); connList.append(fullPortNameB.toRawUTF8()); } if (connList.count() == 0) return nullptr; retCon = connList.toCharStringListPtr(); return retCon; } bool PatchbayGraph::getGroupAndPortIdFromFullName(const bool external, const char* const fullPortName, uint& groupId, uint& portId) const { if (external) return extGraph.getGroupAndPortIdFromFullName(fullPortName, groupId, portId); String groupName(String(fullPortName).upToFirstOccurrenceOf(":", false, false)); String portName(String(fullPortName).fromFirstOccurrenceOf(":", false, false)); for (int i=0, count=graph.getNumNodes(); igetProcessor()); CARLA_SAFE_ASSERT_CONTINUE(proc != nullptr); if (proc->getName() != groupName) continue; groupId = node->nodeId; for (uint j=0, numInputs=proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeAudio); jgetInputChannelName(AudioProcessor::ChannelTypeAudio, j) != portName) continue; portId = kAudioInputPortOffset+j; return true; } for (uint j=0, numOutputs=proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeAudio); jgetOutputChannelName(AudioProcessor::ChannelTypeAudio, j) != portName) continue; portId = kAudioOutputPortOffset+j; return true; } for (uint j=0, numInputs=proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeCV); jgetInputChannelName(AudioProcessor::ChannelTypeCV, j) != portName) continue; portId = kCVInputPortOffset+j; return true; } for (uint j=0, numOutputs=proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeCV); jgetOutputChannelName(AudioProcessor::ChannelTypeCV, j) != portName) continue; portId = kCVOutputPortOffset+j; return true; } for (uint j=0, numInputs=proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeMIDI); jgetInputChannelName(AudioProcessor::ChannelTypeMIDI, j) != portName) continue; portId = kMidiInputPortOffset+j; return true; } for (uint j=0, numOutputs=proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeMIDI); jgetOutputChannelName(AudioProcessor::ChannelTypeMIDI, j) != portName) continue; portId = kMidiOutputPortOffset+j; return true; } } return false; } void PatchbayGraph::process(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const uint32_t frames) { CARLA_SAFE_ASSERT_RETURN(data != nullptr,); CARLA_SAFE_ASSERT_RETURN(data->events.in != nullptr,); CARLA_SAFE_ASSERT_RETURN(data->events.out != nullptr,); CARLA_SAFE_ASSERT_RETURN(frames > 0,); // put events in water buffer { midiBuffer.clear(); fillWaterMidiBufferFromEngineEvents(midiBuffer, data->events.in); } // set audio and cv buffer size, needed for water internals if (! audioBuffer.setSizeRT(frames)) return; if (! cvInBuffer.setSizeRT(frames)) return; if (! cvOutBuffer.setSizeRT(frames)) return; // put carla audio and cv in water buffer { uint32_t i=0; for (; i < numAudioIns; ++i) { CARLA_SAFE_ASSERT_BREAK(inBuf[i]); audioBuffer.copyFrom(i, 0, inBuf[i], frames); } for (uint32_t j=0; j < numCVIns; ++j, ++i) { CARLA_SAFE_ASSERT_BREAK(inBuf[i]); cvInBuffer.copyFrom(j, 0, inBuf[i], frames); } // clear remaining channels for (uint32_t j=numAudioIns, count=audioBuffer.getNumChannels(); j < count; ++j) audioBuffer.clear(j, 0, frames); for (uint32_t j=0; j < numCVOuts; ++j) cvOutBuffer.clear(j, 0, frames); } // ready to go! graph.processBlockWithCV(audioBuffer, cvInBuffer, cvOutBuffer, midiBuffer); // put water audio and cv in carla buffer { uint32_t i=0; for (; i < numAudioOuts; ++i) carla_copyFloats(outBuf[i], audioBuffer.getReadPointer(i), frames); for (uint32_t j=0; j < numCVOuts; ++j, ++i) carla_copyFloats(outBuf[i], cvOutBuffer.getReadPointer(j), frames); } // put water events in carla buffer { carla_zeroStructs(data->events.out, kMaxEngineEventInternalCount); fillEngineEventsFromWaterMidiBuffer(data->events.out, midiBuffer); midiBuffer.clear(); } } void PatchbayGraph::run() { while (! shouldThreadExit()) { carla_msleep(100); graph.reorderNowIfNeeded(); } } // ----------------------------------------------------------------------- // InternalGraph EngineInternalGraph::EngineInternalGraph(CarlaEngine* const engine) noexcept : fIsRack(false), fIsReady(false), fRack(nullptr), kEngine(engine) {} EngineInternalGraph::~EngineInternalGraph() noexcept { CARLA_SAFE_ASSERT(! fIsReady); CARLA_SAFE_ASSERT(fRack == nullptr); } void EngineInternalGraph::create(const uint32_t audioIns, const uint32_t audioOuts, const uint32_t cvIns, const uint32_t cvOuts) { fIsRack = (kEngine->getOptions().processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK); if (fIsRack) { CARLA_SAFE_ASSERT_RETURN(fRack == nullptr,); fRack = new RackGraph(kEngine, audioIns, audioOuts); } else { CARLA_SAFE_ASSERT_RETURN(fPatchbay == nullptr,); fPatchbay = new PatchbayGraph(kEngine, audioIns, audioOuts, cvIns, cvOuts); } fIsReady = true; } void EngineInternalGraph::destroy() noexcept { if (! fIsReady) { CARLA_SAFE_ASSERT(fRack == nullptr); return; } if (fIsRack) { CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,); delete fRack; fRack = nullptr; } else { CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); delete fPatchbay; fPatchbay = nullptr; } fIsReady = false; } void EngineInternalGraph::setBufferSize(const uint32_t bufferSize) { CarlaScopedValueSetter svs(fIsReady, false, true); if (fIsRack) { CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,); fRack->setBufferSize(bufferSize); } else { CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); fPatchbay->setBufferSize(bufferSize); } } void EngineInternalGraph::setSampleRate(const double sampleRate) { CarlaScopedValueSetter svs(fIsReady, false, true); if (fIsRack) { CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,); } else { CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); fPatchbay->setSampleRate(sampleRate); } } void EngineInternalGraph::setOffline(const bool offline) { CarlaScopedValueSetter svs(fIsReady, false, true); if (fIsRack) { CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,); fRack->setOffline(offline); } else { CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); fPatchbay->setOffline(offline); } } bool EngineInternalGraph::isReady() const noexcept { return fIsReady; } RackGraph* EngineInternalGraph::getRackGraph() const noexcept { CARLA_SAFE_ASSERT_RETURN(fIsRack, nullptr); return fRack; } PatchbayGraph* EngineInternalGraph::getPatchbayGraph() const noexcept { CARLA_SAFE_ASSERT_RETURN(! fIsRack, nullptr); return fPatchbay; } PatchbayGraph* EngineInternalGraph::getPatchbayGraphOrNull() const noexcept { return fIsRack ? nullptr : fPatchbay; } void EngineInternalGraph::process(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const uint32_t frames) { if (fIsRack) { CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,); fRack->processHelper(data, inBuf, outBuf, frames); } else { CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); fPatchbay->process(data, inBuf, outBuf, frames); } } void EngineInternalGraph::processRack(CarlaEngine::ProtectedData* const data, const float* inBuf[2], float* outBuf[2], const uint32_t frames) { CARLA_SAFE_ASSERT_RETURN(fIsRack,); CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,); fRack->process(data, inBuf, outBuf, frames); } // ----------------------------------------------------------------------- // used for internal patchbay mode void EngineInternalGraph::addPlugin(CarlaPlugin* const plugin) { CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); fPatchbay->addPlugin(plugin); } void EngineInternalGraph::replacePlugin(CarlaPlugin* const oldPlugin, CarlaPlugin* const newPlugin) { CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); fPatchbay->replacePlugin(oldPlugin, newPlugin); } void EngineInternalGraph::renamePlugin(CarlaPlugin* const plugin, const char* const newName) { CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); fPatchbay->renamePlugin(plugin, newName); } void EngineInternalGraph::removePlugin(CarlaPlugin* const plugin) { CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); fPatchbay->removePlugin(plugin); } void EngineInternalGraph::removeAllPlugins() { CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); fPatchbay->removeAllPlugins(); } bool EngineInternalGraph::isUsingExternalHost() const noexcept { if (fIsRack) return true; CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr, false); return fPatchbay->usingExternalHost; } bool EngineInternalGraph::isUsingExternalOSC() const noexcept { if (fIsRack) return true; CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr, false); return fPatchbay->usingExternalOSC; } void EngineInternalGraph::setUsingExternalHost(const bool usingExternal) noexcept { CARLA_SAFE_ASSERT_RETURN(! fIsRack,); CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); fPatchbay->usingExternalHost = usingExternal; } void EngineInternalGraph::setUsingExternalOSC(const bool usingExternal) noexcept { CARLA_SAFE_ASSERT_RETURN(! fIsRack,); CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); fPatchbay->usingExternalOSC = usingExternal; } // ----------------------------------------------------------------------- // CarlaEngine Patchbay stuff bool CarlaEngine::patchbayConnect(const bool external, const uint groupA, const uint portA, const uint groupB, const uint portB) { CARLA_SAFE_ASSERT_RETURN(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY, false); CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(), false); carla_debug("CarlaEngine::patchbayConnect(%u, %u, %u, %u)", groupA, portA, groupB, portB); if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { RackGraph* const graph = pData->graph.getRackGraph(); CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); return graph->connect(groupA, portA, groupB, portB); } else { PatchbayGraph* const graph = pData->graph.getPatchbayGraph(); CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); return graph->connect(external, groupA, portA, groupB, portB); } return false; } bool CarlaEngine::patchbayDisconnect(const bool external, const uint connectionId) { CARLA_SAFE_ASSERT_RETURN(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY, false); CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(), false); carla_debug("CarlaEngine::patchbayDisconnect(%u)", connectionId); if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { RackGraph* const graph = pData->graph.getRackGraph(); CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); return graph->disconnect(connectionId); } else { PatchbayGraph* const graph = pData->graph.getPatchbayGraph(); CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); return graph->disconnect(external, connectionId); } return false; } bool CarlaEngine::patchbayRefresh(const bool sendHost, const bool sendOSC, const bool external) { // subclasses should handle this CARLA_SAFE_ASSERT_RETURN(! external, false); if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { // This is implemented in engine subclasses setLastError("Unsupported operation"); return false; } if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { PatchbayGraph* const graph = pData->graph.getPatchbayGraph(); CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); graph->refresh(sendHost, sendOSC, external, ""); return true; } setLastError("Unsupported operation"); return false; } // ----------------------------------------------------------------------- // Patchbay stuff const char* const* CarlaEngine::getPatchbayConnections(const bool external) const { CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(), nullptr); carla_debug("CarlaEngine::getPatchbayConnections(%s)", bool2str(external)); if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { RackGraph* const graph = pData->graph.getRackGraph(); CARLA_SAFE_ASSERT_RETURN(graph != nullptr, nullptr); CARLA_SAFE_ASSERT_RETURN(external, nullptr); return graph->getConnections(); } else { PatchbayGraph* const graph = pData->graph.getPatchbayGraph(); CARLA_SAFE_ASSERT_RETURN(graph != nullptr, nullptr); return graph->getConnections(external); } return nullptr; } void CarlaEngine::restorePatchbayConnection(const bool external, const char* const sourcePort, const char* const targetPort) { CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(),); CARLA_SAFE_ASSERT_RETURN(sourcePort != nullptr && sourcePort[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(targetPort != nullptr && targetPort[0] != '\0',); carla_debug("CarlaEngine::restorePatchbayConnection(%s, \"%s\", \"%s\")", bool2str(external), sourcePort, targetPort); uint groupA, portA; uint groupB, portB; if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { RackGraph* const graph = pData->graph.getRackGraph(); CARLA_SAFE_ASSERT_RETURN(graph != nullptr,); CARLA_SAFE_ASSERT_RETURN(external,); if (! graph->getGroupAndPortIdFromFullName(sourcePort, groupA, portA)) return; if (! graph->getGroupAndPortIdFromFullName(targetPort, groupB, portB)) return; graph->connect(groupA, portA, groupB, portB); } else { PatchbayGraph* const graph = pData->graph.getPatchbayGraph(); CARLA_SAFE_ASSERT_RETURN(graph != nullptr,); if (! graph->getGroupAndPortIdFromFullName(external, sourcePort, groupA, portA)) return; if (! graph->getGroupAndPortIdFromFullName(external, targetPort, groupB, portB)) return; graph->connect(external, groupA, portA, groupB, portB); } } // ----------------------------------------------------------------------- bool CarlaEngine::connectExternalGraphPort(const uint connectionType, const uint portId, const char* const portName) { CARLA_SAFE_ASSERT_RETURN(connectionType != 0 || (portName != nullptr && portName[0] != '\0'), false); CARLA_SAFE_ASSERT_RETURN(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK, false); RackGraph* const graph(pData->graph.getRackGraph()); CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); const CarlaRecursiveMutexLocker cml(graph->audioBuffers.mutex); switch (connectionType) { case kExternalGraphConnectionAudioIn1: return graph->audioBuffers.connectedIn1.append(portId); case kExternalGraphConnectionAudioIn2: return graph->audioBuffers.connectedIn2.append(portId); case kExternalGraphConnectionAudioOut1: return graph->audioBuffers.connectedOut1.append(portId); case kExternalGraphConnectionAudioOut2: return graph->audioBuffers.connectedOut2.append(portId); } return false; } bool CarlaEngine::disconnectExternalGraphPort(const uint connectionType, const uint portId, const char* const portName) { CARLA_SAFE_ASSERT_RETURN(connectionType != 0 || (portName != nullptr && portName[0] != '\0'), false); CARLA_SAFE_ASSERT_RETURN(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK, false); RackGraph* const graph(pData->graph.getRackGraph()); CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); const CarlaRecursiveMutexLocker cml(graph->audioBuffers.mutex); switch (connectionType) { case kExternalGraphConnectionAudioIn1: return graph->audioBuffers.connectedIn1.removeOne(portId); case kExternalGraphConnectionAudioIn2: return graph->audioBuffers.connectedIn2.removeOne(portId); case kExternalGraphConnectionAudioOut1: return graph->audioBuffers.connectedOut1.removeOne(portId); case kExternalGraphConnectionAudioOut2: return graph->audioBuffers.connectedOut2.removeOne(portId); } return false; } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/engine/CarlaEngineGraph.hpp000066400000000000000000000162731364475620200224170ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2018 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_ENGINE_GRAPH_HPP_INCLUDED #define CARLA_ENGINE_GRAPH_HPP_INCLUDED #include "CarlaEngine.hpp" #include "CarlaMutex.hpp" #include "CarlaPatchbayUtils.hpp" #include "CarlaStringList.hpp" #include "CarlaThread.hpp" #include "water/processors/AudioProcessorGraph.h" #include "water/text/StringArray.h" using water::AudioProcessorGraph; using water::AudioSampleBuffer; using water::MidiBuffer; CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // External Graph stuff enum ExternalGraphGroupIds { kExternalGraphGroupNull = 0, kExternalGraphGroupCarla = 1, kExternalGraphGroupAudioIn = 2, kExternalGraphGroupAudioOut = 3, kExternalGraphGroupMidiIn = 4, kExternalGraphGroupMidiOut = 5, kExternalGraphGroupMax = 6 }; enum ExternalGraphCarlaPortIds { kExternalGraphCarlaPortNull = 0, kExternalGraphCarlaPortAudioIn1 = 1, kExternalGraphCarlaPortAudioIn2 = 2, kExternalGraphCarlaPortAudioOut1 = 3, kExternalGraphCarlaPortAudioOut2 = 4, kExternalGraphCarlaPortMidiIn = 5, kExternalGraphCarlaPortMidiOut = 6, kExternalGraphCarlaPortMax = 7 }; enum ExternalGraphConnectionType { kExternalGraphConnectionNull = 0, kExternalGraphConnectionAudioIn1 = 1, kExternalGraphConnectionAudioIn2 = 2, kExternalGraphConnectionAudioOut1 = 3, kExternalGraphConnectionAudioOut2 = 4, kExternalGraphConnectionMidiInput = 5, kExternalGraphConnectionMidiOutput = 6 }; struct ExternalGraphPorts { LinkedList ins; LinkedList outs; const char* getName(bool isInput, uint portId) const noexcept; uint getPortId(bool isInput, const char portName[], bool* ok = nullptr) const noexcept; ExternalGraphPorts() noexcept; CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_CLASS(ExternalGraphPorts) }; struct ExternalGraph { PatchbayConnectionList connections; ExternalGraphPorts audioPorts, midiPorts; mutable CharStringListPtr retCon; ExternalGraph(CarlaEngine* engine) noexcept; void clear() noexcept; bool connect(bool sendHost, bool sendOSC, uint groupA, uint portA, uint groupB, uint portB) noexcept; bool disconnect(bool sendHost, bool sendOSC, uint connectionId) noexcept; void refresh(bool sendHost, bool sendOSC, const char* deviceName); const char* const* getConnections() const noexcept; bool getGroupAndPortIdFromFullName(const char* fullPortName, uint& groupId, uint& portId) const noexcept; CarlaEngine* const kEngine; CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_CLASS(ExternalGraph) }; // ----------------------------------------------------------------------- // RackGraph struct RackGraph { ExternalGraph extGraph; const uint32_t inputs; const uint32_t outputs; bool isOffline; struct Buffers { CarlaRecursiveMutex mutex; LinkedList connectedIn1; LinkedList connectedIn2; LinkedList connectedOut1; LinkedList connectedOut2; float* inBuf[2]; float* inBufTmp[2]; float* outBuf[2]; float* unusedBuf; Buffers() noexcept; ~Buffers() noexcept; void setBufferSize(uint32_t bufferSize, bool createBuffers) noexcept; CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_CLASS(Buffers) } audioBuffers; RackGraph(CarlaEngine* engine, uint32_t inputs, uint32_t outputs) noexcept; ~RackGraph() noexcept; void setBufferSize(uint32_t bufferSize) noexcept; void setOffline(bool offline) noexcept; bool connect(uint groupA, uint portA, uint groupB, uint portB) noexcept; bool disconnect(uint connectionId) noexcept; void refresh(bool sendHost, bool sendOsc, bool ignored, const char* deviceName); const char* const* getConnections() const noexcept; bool getGroupAndPortIdFromFullName(const char* fullPortName, uint& groupId, uint& portId) const noexcept; // the base, where plugins run void process(CarlaEngine::ProtectedData* data, const float* inBuf[2], float* outBuf[2], uint32_t frames); // extended, will call process() in the middle void processHelper(CarlaEngine::ProtectedData* data, const float* const* inBuf, float* const* outBuf, uint32_t frames); CarlaEngine* const kEngine; CARLA_DECLARE_NON_COPY_CLASS(RackGraph) }; // ----------------------------------------------------------------------- // PatchbayGraph class PatchbayGraph : private CarlaThread { public: PatchbayConnectionList connections; AudioProcessorGraph graph; AudioSampleBuffer audioBuffer; AudioSampleBuffer cvInBuffer; AudioSampleBuffer cvOutBuffer; MidiBuffer midiBuffer; const uint32_t numAudioIns; const uint32_t numAudioOuts; const uint32_t numCVIns; const uint32_t numCVOuts; mutable CharStringListPtr retCon; bool usingExternalHost; bool usingExternalOSC; ExternalGraph extGraph; PatchbayGraph(CarlaEngine* engine, uint32_t audioIns, uint32_t audioOuts, uint32_t cvIns, uint32_t cvOuts); ~PatchbayGraph(); void setBufferSize(uint32_t bufferSize); void setSampleRate(double sampleRate); void setOffline(bool offline); void addPlugin(CarlaPlugin* plugin); void replacePlugin(CarlaPlugin* oldPlugin, CarlaPlugin* newPlugin); void renamePlugin(CarlaPlugin* plugin, const char* newName); void reconfigureForCV(CarlaPlugin* const plugin, const uint portIndex, bool added); void reconfigurePlugin(CarlaPlugin* plugin, bool portsAdded); void removePlugin(CarlaPlugin* plugin); void removeAllPlugins(); bool connect(bool external, uint groupA, uint portA, uint groupB, uint portB); bool disconnect(bool external, uint connectionId); void disconnectInternalGroup(uint groupId) noexcept; void refresh(bool sendHost, bool sendOsc, bool external, const char* deviceName); const char* const* getConnections(bool external) const; bool getGroupAndPortIdFromFullName(bool external, const char* fullPortName, uint& groupId, uint& portId) const; void process(CarlaEngine::ProtectedData* data, const float* const* inBuf, float* const* outBuf, uint32_t frames); private: void run() override; CarlaEngine* const kEngine; CARLA_DECLARE_NON_COPY_CLASS(PatchbayGraph) }; // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE #endif // CARLA_ENGINE_GRAPH_HPP_INCLUDED Carla-2.1/source/backend/engine/CarlaEngineInternal.cpp000066400000000000000000000537641364475620200231330ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaEngineInternal.hpp" #include "CarlaPlugin.hpp" #include "CarlaSemUtils.hpp" #include "jackbridge/JackBridge.hpp" #include #include CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // Engine Internal helper macro, sets lastError and returns false/NULL #define CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); lastError = err; return false; } #define CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERRN(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); lastError = err; return nullptr; } // ----------------------------------------------------------------------- // InternalEvents EngineInternalEvents::EngineInternalEvents() noexcept : in(nullptr), out(nullptr) {} EngineInternalEvents::~EngineInternalEvents() noexcept { CARLA_SAFE_ASSERT(in == nullptr); CARLA_SAFE_ASSERT(out == nullptr); } void EngineInternalEvents::clear() noexcept { if (in != nullptr) { delete[] in; in = nullptr; } if (out != nullptr) { delete[] out; out = nullptr; } } // ----------------------------------------------------------------------- // InternalTime static const double kTicksPerBeat = 1920.0; #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE) static uint32_t calculate_link_latency(const double bufferSize, const double sampleRate) noexcept { CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate), 0); const long long int latency = llround(1.0e6 * bufferSize / sampleRate); CARLA_SAFE_ASSERT_RETURN(latency >= 0 && latency < UINT32_MAX, 0); return static_cast(latency); } #endif EngineInternalTime::EngineInternalTime(EngineTimeInfo& ti, const EngineTransportMode& tm) noexcept : beatsPerBar(4.0), beatsPerMinute(120.0), bufferSize(0.0), sampleRate(0.0), tick(0.0), needsReset(false), nextFrame(0), #ifndef BUILD_BRIDGE hylia(), #endif timeInfo(ti), transportMode(tm) {} void EngineInternalTime::init(const uint32_t bsize, const double srate) { bufferSize = bsize; sampleRate = srate; #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE) if (hylia.instance != nullptr) { hylia_set_beats_per_bar(hylia.instance, beatsPerBar); hylia_set_beats_per_minute(hylia.instance, beatsPerMinute); hylia_set_output_latency(hylia.instance, calculate_link_latency(bsize, srate)); if (hylia.enabled) hylia_enable(hylia.instance, true); } #endif needsReset = true; } void EngineInternalTime::updateAudioValues(const uint32_t bsize, const double srate) { bufferSize = bsize; sampleRate = srate; #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE) if (hylia.instance != nullptr) hylia_set_output_latency(hylia.instance, calculate_link_latency(bsize, srate)); #endif needsReset = true; } void EngineInternalTime::enableLink(const bool enable) { #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE) if (hylia.enabled == enable) return; if (hylia.instance != nullptr) { hylia.enabled = enable; hylia_enable(hylia.instance, enable); } #else // unused (void)enable; #endif needsReset = true; } void EngineInternalTime::setBPM(const double bpm) { beatsPerMinute = bpm; #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE) if (hylia.instance != nullptr) hylia_set_beats_per_minute(hylia.instance, bpm); #endif } void EngineInternalTime::setNeedsReset() noexcept { needsReset = true; } void EngineInternalTime::pause() noexcept { timeInfo.playing = false; nextFrame = timeInfo.frame; needsReset = true; } void EngineInternalTime::relocate(const uint64_t frame) noexcept { timeInfo.frame = frame; nextFrame = frame; needsReset = true; } void EngineInternalTime::fillEngineTimeInfo(const uint32_t newFrames) noexcept { CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate),); CARLA_SAFE_ASSERT_RETURN(newFrames > 0,); double ticktmp; if (transportMode == ENGINE_TRANSPORT_MODE_INTERNAL) { timeInfo.usecs = 0; timeInfo.frame = nextFrame; } if (needsReset) { timeInfo.bbt.valid = true; timeInfo.bbt.beatType = 4.0f; timeInfo.bbt.ticksPerBeat = kTicksPerBeat; double abs_beat, abs_tick; #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE) if (hylia.enabled) { if (hylia.timeInfo.beat >= 0.0) { abs_beat = hylia.timeInfo.beat; abs_tick = abs_beat * kTicksPerBeat; } else { abs_beat = 0.0; abs_tick = 0.0; timeInfo.playing = false; } } else #endif { const double min = static_cast(timeInfo.frame) / (sampleRate * 60.0); abs_beat = min * beatsPerMinute; abs_tick = abs_beat * kTicksPerBeat; needsReset = false; } const double bar = std::floor(abs_beat / beatsPerBar); const double beat = std::floor(std::fmod(abs_beat, beatsPerBar)); timeInfo.bbt.bar = static_cast(bar) + 1; timeInfo.bbt.beat = static_cast(beat) + 1; timeInfo.bbt.barStartTick = ((bar * beatsPerBar) + beat) * kTicksPerBeat; ticktmp = abs_tick - timeInfo.bbt.barStartTick; } else if (timeInfo.playing) { ticktmp = tick + (newFrames * kTicksPerBeat * beatsPerMinute / (sampleRate * 60)); while (ticktmp >= kTicksPerBeat) { ticktmp -= kTicksPerBeat; if (++timeInfo.bbt.beat > beatsPerBar) { ++timeInfo.bbt.bar; timeInfo.bbt.beat = 1; timeInfo.bbt.barStartTick += beatsPerBar * kTicksPerBeat; } } } else { ticktmp = tick; } timeInfo.bbt.beatsPerBar = static_cast(beatsPerBar); timeInfo.bbt.beatsPerMinute = beatsPerMinute; timeInfo.bbt.tick = ticktmp; tick = ticktmp; if (transportMode == ENGINE_TRANSPORT_MODE_INTERNAL && timeInfo.playing) nextFrame += newFrames; } void EngineInternalTime::fillJackTimeInfo(jack_position_t* const pos, const uint32_t newFrames) noexcept { CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate),); CARLA_SAFE_ASSERT_RETURN(newFrames > 0,); CARLA_SAFE_ASSERT(transportMode == ENGINE_TRANSPORT_MODE_JACK); fillEngineTimeInfo(newFrames); pos->valid = JackPositionBBT; pos->bar = timeInfo.bbt.bar; pos->beat = timeInfo.bbt.beat; pos->tick = static_cast(tick + 0.5); pos->bar_start_tick = timeInfo.bbt.barStartTick; pos->beats_per_bar = timeInfo.bbt.beatsPerBar; pos->beat_type = timeInfo.bbt.beatType; pos->ticks_per_beat = kTicksPerBeat; pos->beats_per_minute = beatsPerMinute; } void EngineInternalTime::preProcess(const uint32_t numFrames) { #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE) if (hylia.enabled) { hylia_process(hylia.instance, numFrames, &hylia.timeInfo); const double new_bpb = hylia.timeInfo.beatsPerBar; const double new_bpm = hylia.timeInfo.beatsPerMinute; if (new_bpb >= 1.0 && carla_isNotEqual(beatsPerBar, new_bpb)) { beatsPerBar = new_bpb; needsReset = true; } if (new_bpm > 0.0 && carla_isNotEqual(beatsPerMinute, new_bpm)) { beatsPerMinute = new_bpm; needsReset = true; } } #endif if (transportMode == ENGINE_TRANSPORT_MODE_INTERNAL) fillEngineTimeInfo(numFrames); } // ----------------------------------------------------------------------- // EngineInternalTime::Hylia #ifndef BUILD_BRIDGE EngineInternalTime::Hylia::Hylia() : enabled(false), instance(nullptr), timeInfo() { carla_zeroStruct(timeInfo); # ifdef HAVE_HYLIA instance = hylia_create(); # endif } EngineInternalTime::Hylia::~Hylia() { # ifdef HAVE_HYLIA hylia_cleanup(instance); # endif } #endif // ----------------------------------------------------------------------- // NextAction EngineNextAction::EngineNextAction() noexcept : opcode(kEnginePostActionNull), pluginId(0), value(0), mutex(), needsPost(false), postDone(false), sem(carla_sem_create(false)) {} EngineNextAction::~EngineNextAction() noexcept { CARLA_SAFE_ASSERT(opcode == kEnginePostActionNull); if (sem != nullptr) { carla_sem_destroy(sem); sem = nullptr; } } void EngineNextAction::clearAndReset() noexcept { mutex.lock(); CARLA_SAFE_ASSERT(opcode == kEnginePostActionNull); opcode = kEnginePostActionNull; pluginId = 0; value = 0; needsPost = false; postDone = false; mutex.unlock(); } // ----------------------------------------------------------------------- // Helper functions EngineEvent* CarlaEngine::getInternalEventBuffer(const bool isInput) const noexcept { return isInput ? pData->events.in : pData->events.out; } // ----------------------------------------------------------------------- // CarlaEngine::ProtectedData CarlaEngine::ProtectedData::ProtectedData(CarlaEngine* const engine) noexcept : thread(engine), #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) osc(engine), #endif callback(nullptr), callbackPtr(nullptr), fileCallback(nullptr), fileCallbackPtr(nullptr), actionCanceled(false), #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH loadingProject(false), currentProjectFilename(), #endif bufferSize(0), sampleRate(0.0), aboutToClose(false), isIdling(0), curPluginCount(0), maxPluginNumber(0), nextPluginId(0), envMutex(), lastError(), name(), options(), timeInfo(), #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH plugins(nullptr), xruns(0), dspLoad(0.0f), #endif events(), #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH graph(engine), #endif time(timeInfo, options.transportMode), nextAction() { #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH carla_zeroStructs(plugins, 1); #endif } CarlaEngine::ProtectedData::~ProtectedData() noexcept { CARLA_SAFE_ASSERT(curPluginCount == 0); CARLA_SAFE_ASSERT(maxPluginNumber == 0); CARLA_SAFE_ASSERT(nextPluginId == 0); CARLA_SAFE_ASSERT(isIdling == 0); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT(plugins == nullptr); #endif } // ----------------------------------------------------------------------- bool CarlaEngine::ProtectedData::init(const char* const clientName) { CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(name.isEmpty(), "Invalid engine internal data (err #1)"); CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.in == nullptr, "Invalid engine internal data (err #4)"); CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.out == nullptr, "Invalid engine internal data (err #5)"); CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(clientName != nullptr && clientName[0] != '\0', "Invalid client name"); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(plugins == nullptr, "Invalid engine internal data (err #3)"); #endif aboutToClose = false; curPluginCount = 0; nextPluginId = 0; switch (options.processMode) { case ENGINE_PROCESS_MODE_CONTINUOUS_RACK: maxPluginNumber = MAX_RACK_PLUGINS; options.forceStereo = true; break; case ENGINE_PROCESS_MODE_PATCHBAY: maxPluginNumber = MAX_PATCHBAY_PLUGINS; break; case ENGINE_PROCESS_MODE_BRIDGE: maxPluginNumber = 1; break; default: maxPluginNumber = MAX_DEFAULT_PLUGINS; break; } switch (options.processMode) { case ENGINE_PROCESS_MODE_CONTINUOUS_RACK: case ENGINE_PROCESS_MODE_PATCHBAY: case ENGINE_PROCESS_MODE_BRIDGE: events.in = new EngineEvent[kMaxEngineEventInternalCount]; events.out = new EngineEvent[kMaxEngineEventInternalCount]; carla_zeroStructs(events.in, kMaxEngineEventInternalCount); carla_zeroStructs(events.out, kMaxEngineEventInternalCount); break; default: break; } nextPluginId = maxPluginNumber; name = clientName; name.toBasic(); timeInfo.clear(); #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (options.oscEnabled) osc.init(clientName, options.oscPortTCP, options.oscPortUDP); #endif #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH plugins = new EnginePluginData[maxPluginNumber]; carla_zeroStructs(plugins, maxPluginNumber); xruns = 0; dspLoad = 0.0f; #endif nextAction.clearAndReset(); thread.startThread(); return true; } void CarlaEngine::ProtectedData::close() { CARLA_SAFE_ASSERT(name.isNotEmpty()); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT(plugins != nullptr); CARLA_SAFE_ASSERT(nextPluginId == maxPluginNumber); #endif aboutToClose = true; thread.stopThread(500); nextAction.clearAndReset(); #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) osc.close(); #endif aboutToClose = false; curPluginCount = 0; maxPluginNumber = 0; nextPluginId = 0; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (plugins != nullptr) { delete[] plugins; plugins = nullptr; } #endif events.clear(); name.clear(); } void CarlaEngine::ProtectedData::initTime(const char* const features) { time.init(bufferSize, sampleRate); #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE) const bool linkEnabled = features != nullptr && std::strstr(features, ":link:") != nullptr; time.enableLink(linkEnabled); #else return; // unused (void)features; #endif } // ----------------------------------------------------------------------- #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH void CarlaEngine::ProtectedData::doPluginRemove(const uint pluginId) noexcept { CARLA_SAFE_ASSERT_RETURN(curPluginCount > 0,); CARLA_SAFE_ASSERT_RETURN(pluginId < curPluginCount,); --curPluginCount; // move all plugins 1 spot backwards for (uint i=pluginId; i < curPluginCount; ++i) { CarlaPlugin* const plugin(plugins[i+1].plugin); CARLA_SAFE_ASSERT_BREAK(plugin != nullptr); plugin->setId(i); plugins[i].plugin = plugin; carla_zeroFloats(plugins[i].peaks, 4); } const uint id(curPluginCount); // reset last plugin (now removed) plugins[id].plugin = nullptr; carla_zeroFloats(plugins[id].peaks, 4); } void CarlaEngine::ProtectedData::doPluginsSwitch(const uint idA, const uint idB) noexcept { CARLA_SAFE_ASSERT_RETURN(curPluginCount >= 2,); CARLA_SAFE_ASSERT_RETURN(idA < curPluginCount,); CARLA_SAFE_ASSERT_RETURN(idB < curPluginCount,); CarlaPlugin* const pluginA(plugins[idA].plugin); CARLA_SAFE_ASSERT_RETURN(pluginA != nullptr,); CarlaPlugin* const pluginB(plugins[idB].plugin); CARLA_SAFE_ASSERT_RETURN(pluginB != nullptr,); pluginA->setId(idB); plugins[idA].plugin = pluginB; pluginB->setId(idA); plugins[idB].plugin = pluginA; } #endif void CarlaEngine::ProtectedData::doNextPluginAction() noexcept { if (! nextAction.mutex.tryLock()) return; const EnginePostAction opcode = nextAction.opcode; const bool needsPost = nextAction.needsPost; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH const uint pluginId = nextAction.pluginId; const uint value = nextAction.value; #endif nextAction.opcode = kEnginePostActionNull; nextAction.pluginId = 0; nextAction.value = 0; nextAction.needsPost = false; nextAction.mutex.unlock(); switch (opcode) { case kEnginePostActionNull: break; case kEnginePostActionZeroCount: curPluginCount = 0; break; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH case kEnginePostActionRemovePlugin: doPluginRemove(pluginId); break; case kEnginePostActionSwitchPlugins: doPluginsSwitch(pluginId, value); break; #endif } if (needsPost) { if (nextAction.sem != nullptr) carla_sem_post(*nextAction.sem); nextAction.postDone = true; } } // ----------------------------------------------------------------------- // PendingRtEventsRunner static int64_t getTimeInMicroseconds() noexcept { #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) struct timeval tv; gettimeofday(&tv, nullptr); return (tv.tv_sec * 1000000) + tv.tv_usec; #else struct timespec ts; # ifdef CLOCK_MONOTONIC_RAW clock_gettime(CLOCK_MONOTONIC_RAW, &ts); # else clock_gettime(CLOCK_MONOTONIC, &ts); # endif return (ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); #endif } PendingRtEventsRunner::PendingRtEventsRunner(CarlaEngine* const engine, const uint32_t frames, const bool calcDSPLoad) noexcept : pData(engine->pData), prevTime(calcDSPLoad ? getTimeInMicroseconds() : 0) { pData->time.preProcess(frames); } PendingRtEventsRunner::~PendingRtEventsRunner() noexcept { pData->doNextPluginAction(); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (prevTime > 0) { const int64_t newTime = getTimeInMicroseconds(); if (newTime < prevTime) return; const double timeDiff = static_cast(newTime - prevTime) / 1000000.0; const double maxTime = pData->bufferSize / pData->sampleRate; const float dspLoad = static_cast(timeDiff / maxTime) * 100.0f; if (dspLoad > pData->dspLoad) pData->dspLoad = std::min(100.0f, dspLoad); else pData->dspLoad *= static_cast(1.0 - maxTime) + 1e-12f; } #endif } // ----------------------------------------------------------------------- // ScopedActionLock ScopedActionLock::ScopedActionLock(CarlaEngine* const engine, const EnginePostAction action, const uint pluginId, const uint value) noexcept : pData(engine->pData) { CARLA_SAFE_ASSERT_RETURN(action != kEnginePostActionNull,); { const CarlaMutexLocker cml(pData->nextAction.mutex); CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,); pData->nextAction.opcode = action; pData->nextAction.pluginId = pluginId; pData->nextAction.value = value; pData->nextAction.needsPost = engine->isRunning(); pData->nextAction.postDone = false; } #ifdef BUILD_BRIDGE #define ACTION_MSG_PREFIX "Bridge: " #else #define ACTION_MSG_PREFIX "" #endif if (pData->nextAction.needsPost) { #if defined(DEBUG) || defined(BUILD_BRIDGE) // block wait for unlock on processing side carla_stdout(ACTION_MSG_PREFIX "ScopedPluginAction(%i) - blocking START", pluginId); #endif bool engineStoppedWhileWaiting = false; if (! pData->nextAction.postDone) { for (int i = 10; --i >= 0;) { if (pData->nextAction.sem != nullptr) { if (carla_sem_timedwait(*pData->nextAction.sem, 200)) break; } else { carla_msleep(200); } if (! engine->isRunning()) { engineStoppedWhileWaiting = true; break; } } } #if defined(DEBUG) || defined(BUILD_BRIDGE) carla_stdout(ACTION_MSG_PREFIX "ScopedPluginAction(%i) - blocking DONE", pluginId); #endif // check if anything went wrong... if (! pData->nextAction.postDone) { bool needsCorrection = false; { const CarlaMutexLocker cml(pData->nextAction.mutex); if (pData->nextAction.opcode != kEnginePostActionNull) { needsCorrection = true; pData->nextAction.needsPost = false; } } if (needsCorrection) { pData->doNextPluginAction(); if (! engineStoppedWhileWaiting) carla_stderr2(ACTION_MSG_PREFIX "Failed to wait for engine, is audio not running?"); } } } else { pData->doNextPluginAction(); } } ScopedActionLock::~ScopedActionLock() noexcept { CARLA_SAFE_ASSERT(pData->nextAction.opcode == kEnginePostActionNull); } // ----------------------------------------------------------------------- // ScopedThreadStopper ScopedThreadStopper::ScopedThreadStopper(CarlaEngine* const e) noexcept : engine(e), pData(e->pData) { pData->thread.stopThread(500); } ScopedThreadStopper::~ScopedThreadStopper() noexcept { if (engine->isRunning() && ! pData->aboutToClose) pData->thread.startThread(); } // ----------------------------------------------------------------------- // ScopedEngineEnvironmentLocker ScopedEngineEnvironmentLocker::ScopedEngineEnvironmentLocker(CarlaEngine* const engine) noexcept : pData(engine->pData) { pData->envMutex.lock(); } ScopedEngineEnvironmentLocker::~ScopedEngineEnvironmentLocker() noexcept { pData->envMutex.unlock(); } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/engine/CarlaEngineInternal.hpp000066400000000000000000000234401364475620200231240ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_ENGINE_INTERNAL_HPP_INCLUDED #define CARLA_ENGINE_INTERNAL_HPP_INCLUDED #include "CarlaEngineThread.hpp" #include "CarlaEngineUtils.hpp" #include "LinkedList.hpp" #ifndef BUILD_BRIDGE # include "CarlaEngineOsc.hpp" # include "hylia/hylia.h" #endif #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH # include "water/processors/AudioProcessorGraph.h" # include "water/containers/Array.h" # include "water/memory/Atomic.h" #endif // FIXME only use CARLA_PREVENT_HEAP_ALLOCATION for structs // maybe separate macro typedef struct _jack_position jack_position_t; struct carla_sem_t; CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // Engine helper macro, sets lastError and returns false/NULL #define CARLA_SAFE_ASSERT_RETURN_ERR(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); setLastError(err); return false; } #define CARLA_SAFE_ASSERT_RETURN_ERRN(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); setLastError(err); return nullptr; } #define CARLA_SAFE_EXCEPTION_RETURN_ERR(excptMsg, errMsg) catch(...) { carla_safe_exception(excptMsg, __FILE__, __LINE__); setLastError(errMsg); return false; } #define CARLA_SAFE_EXCEPTION_RETURN_ERRN(excptMsg, errMsg) catch(...) { carla_safe_exception(excptMsg, __FILE__, __LINE__); setLastError(errMsg); return nullptr; } // ----------------------------------------------------------------------- // InternalEvents struct EngineInternalEvents { EngineEvent* in; EngineEvent* out; EngineInternalEvents() noexcept; ~EngineInternalEvents() noexcept; void clear() noexcept; CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalEvents) }; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // ----------------------------------------------------------------------- // InternalGraph struct RackGraph; class PatchbayGraph; class EngineInternalGraph { public: EngineInternalGraph(CarlaEngine* engine) noexcept; ~EngineInternalGraph() noexcept; void create(uint32_t audioIns, uint32_t audioOuts, uint32_t cvIns, uint32_t cvOuts); void destroy() noexcept; void setBufferSize(uint32_t bufferSize); void setSampleRate(double sampleRate); void setOffline(bool offline); bool isReady() const noexcept; RackGraph* getRackGraph() const noexcept; PatchbayGraph* getPatchbayGraph() const noexcept; PatchbayGraph* getPatchbayGraphOrNull() const noexcept; void process(CarlaEngine::ProtectedData* data, const float* const* inBuf, float* const* outBuf, uint32_t frames); // special direct process with connections already handled, used in JACK and Plugin void processRack(CarlaEngine::ProtectedData* data, const float* inBuf[2], float* outBuf[2], uint32_t frames); // used for internal patchbay mode void addPlugin(CarlaPlugin* plugin); void replacePlugin(CarlaPlugin* oldPlugin, CarlaPlugin* newPlugin); void renamePlugin(CarlaPlugin* plugin, const char* newName); void removePlugin(CarlaPlugin* plugin); void removeAllPlugins(); bool isUsingExternalHost() const noexcept; bool isUsingExternalOSC() const noexcept; void setUsingExternalHost(bool usingExternal) noexcept; void setUsingExternalOSC(bool usingExternal) noexcept; private: bool fIsRack; volatile bool fIsReady; union { RackGraph* fRack; PatchbayGraph* fPatchbay; }; CarlaEngine* const kEngine; CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalGraph) }; #endif // BUILD_BRIDGE_ALTERNATIVE_ARCH // ----------------------------------------------------------------------- // InternalTime class EngineInternalTime { public: EngineInternalTime(EngineTimeInfo& timeInfo, const EngineTransportMode& transportMode) noexcept; void init(uint32_t bufferSize, double sampleRate); void updateAudioValues(uint32_t bufferSize, double sampleRate); void enableLink(bool enable); void setBPM(double bpm); void setNeedsReset() noexcept; void pause() noexcept; void relocate(uint64_t frame) noexcept; private: double beatsPerBar; double beatsPerMinute; double bufferSize; double sampleRate; double tick; bool needsReset; uint64_t nextFrame; #ifndef BUILD_BRIDGE struct Hylia { bool enabled; hylia_t* instance; hylia_time_info_t timeInfo; Hylia(); ~Hylia(); CARLA_DECLARE_NON_COPY_STRUCT(Hylia) } hylia; #endif EngineTimeInfo& timeInfo; const EngineTransportMode& transportMode; friend class PendingRtEventsRunner; void preProcess(uint32_t numFrames); void fillEngineTimeInfo(uint32_t newFrames) noexcept; friend class CarlaEngineJack; void fillJackTimeInfo(jack_position_t* pos, uint32_t newFrames) noexcept; CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalTime) }; // ----------------------------------------------------------------------- // EngineNextAction enum EnginePostAction { kEnginePostActionNull = 0, kEnginePostActionZeroCount, // set curPluginCount to 0 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH kEnginePostActionRemovePlugin, // remove a plugin kEnginePostActionSwitchPlugins // switch between 2 plugins #endif }; struct EngineNextAction { EnginePostAction opcode; uint pluginId; uint value; CarlaMutex mutex; bool needsPost; volatile bool postDone; carla_sem_t* sem; EngineNextAction() noexcept; ~EngineNextAction() noexcept; void clearAndReset() noexcept; CARLA_DECLARE_NON_COPY_STRUCT(EngineNextAction) }; // ----------------------------------------------------------------------- // EnginePluginData struct EnginePluginData { CarlaPlugin* plugin; float peaks[4]; }; // ----------------------------------------------------------------------- // CarlaEngineProtectedData struct CarlaEngine::ProtectedData { CarlaEngineThread thread; #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) CarlaEngineOsc osc; #endif EngineCallbackFunc callback; void* callbackPtr; FileCallbackFunc fileCallback; void* fileCallbackPtr; bool actionCanceled; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH bool loadingProject; CarlaString currentProjectFilename; #endif uint32_t bufferSize; double sampleRate; bool aboutToClose; // don't re-activate thread if true int isIdling; // don't allow any operations while idling uint curPluginCount; // number of plugins loaded (0...max) uint maxPluginNumber; // number of plugins allowed (0, 16, 99 or 255) uint nextPluginId; // invalid if == maxPluginNumber CarlaMutex envMutex; CarlaString lastError; CarlaString name; EngineOptions options; EngineTimeInfo timeInfo; #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH EnginePluginData plugins[1]; #else EnginePluginData* plugins; uint32_t xruns; float dspLoad; #endif float peaks[4]; EngineInternalEvents events; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH EngineInternalGraph graph; #endif EngineInternalTime time; EngineNextAction nextAction; // ------------------------------------------------------------------- ProtectedData(CarlaEngine* engine) noexcept; ~ProtectedData() noexcept; // ------------------------------------------------------------------- bool init(const char* clientName); void close(); void initTime(const char* features); // ------------------------------------------------------------------- void doPluginRemove(uint pluginId) noexcept; void doPluginsSwitch(uint idA, uint idB) noexcept; void doNextPluginAction() noexcept; // ------------------------------------------------------------------- #ifdef CARLA_PROPER_CPP11_SUPPORT ProtectedData() = delete; CARLA_DECLARE_NON_COPY_STRUCT(ProtectedData) #endif }; // ----------------------------------------------------------------------- class PendingRtEventsRunner { public: PendingRtEventsRunner(CarlaEngine* engine, uint32_t numFrames, bool calcDSPLoad = false) noexcept; ~PendingRtEventsRunner() noexcept; private: CarlaEngine::ProtectedData* const pData; int64_t prevTime; CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_CLASS(PendingRtEventsRunner) }; // ----------------------------------------------------------------------- class ScopedActionLock { public: ScopedActionLock(CarlaEngine* engine, EnginePostAction action, uint pluginId, uint value) noexcept; ~ScopedActionLock() noexcept; private: CarlaEngine::ProtectedData* const pData; CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_CLASS(ScopedActionLock) }; // ----------------------------------------------------------------------- class ScopedThreadStopper { public: ScopedThreadStopper(CarlaEngine* engine) noexcept; ~ScopedThreadStopper() noexcept; private: CarlaEngine* const engine; CarlaEngine::ProtectedData* const pData; CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_CLASS(ScopedThreadStopper) }; // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE #endif // CARLA_ENGINE_INTERNAL_HPP_INCLUDED Carla-2.1/source/backend/engine/CarlaEngineJack.cpp000066400000000000000000003763131364475620200222250ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaEngineClient.hpp" #include "CarlaEngineInternal.hpp" #include "CarlaPlugin.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaEngineUtils.hpp" #include "CarlaMathUtils.hpp" #include "CarlaMIDI.h" #include "CarlaPatchbayUtils.hpp" #include "CarlaStringList.hpp" #include "jackey.h" #ifdef USING_JUCE # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Weffc++" # pragma GCC diagnostic ignored "-Wsign-conversion" # pragma GCC diagnostic ignored "-Wundef" # endif # include "AppConfig.h" # include "juce_events/juce_events.h" # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic pop # endif #endif #ifdef __SSE2_MATH__ # include #endif // must be last #include "jackbridge/JackBridge.hpp" #define URI_CANVAS_ICON "http://kxstudio.sf.net/ns/canvas/icon" #define URI_MAIN_CLIENT_NAME "https://kx.studio/ns/carla/main-client-name" #define URI_PLUGIN_ICON "https://kx.studio/ns/carla/plugin-icon" #define URI_PLUGIN_ID "https://kx.studio/ns/carla/plugin-id" #define URI_TYPE_INTEGER "http://www.w3.org/2001/XMLSchema#integer" #define URI_TYPE_STRING "text/plain" CARLA_BACKEND_START_NAMESPACE class CarlaEngineJack; class CarlaEngineJackClient; struct CarlaJackPortHints { bool isHardware : 1; bool isInput : 1; bool isAudio : 1; bool isMIDI : 1; bool isCV : 1; bool isOSC : 1; static CarlaJackPortHints fromPort(const jack_port_t* const jackPort) { CarlaJackPortHints ph = { false, false, false, false, false, false }; const int portFlags = jackbridge_port_flags(jackPort); const char* const portType = jackbridge_port_type(jackPort); ph.isHardware = portFlags & JackPortIsPhysical; ph.isInput = portFlags & JackPortIsInput; ph.isAudio = portType != nullptr && std::strcmp(portType, JACK_DEFAULT_AUDIO_TYPE) == 0; ph.isMIDI = portType != nullptr && std::strcmp(portType, JACK_DEFAULT_MIDI_TYPE) == 0; ph.isCV = false; ph.isOSC = false; if (const jack_uuid_t uuid = jackbridge_port_uuid(jackPort)) { char* value = nullptr; char* type = nullptr; if (jackbridge_get_property(uuid, JACKEY_SIGNAL_TYPE, &value, &type) && value != nullptr && type != nullptr && std::strcmp(type, URI_TYPE_STRING) == 0) { ph.isCV = (std::strcmp(value, "CV") == 0); ph.isOSC = (std::strcmp(value, "OSC") == 0); } } return ph; } }; // ----------------------------------------------------------------------- // Fallback data static const EngineEvent kFallbackJackEngineEvent = { kEngineEventTypeNull, 0, 0, {{ kEngineControlEventTypeNull, 0, 0.0f }} }; //static CarlaEngineEventCV kFallbackEngineEventCV = { nullptr, (uint32_t)-1, 0.0f }; // ----------------------------------------------------------------------- // Carla Engine Port removal helper class CarlaEngineJackAudioPort; class CarlaEngineJackCVPort; class CarlaEngineJackEventPort; struct JackPortDeletionCallback { virtual ~JackPortDeletionCallback() noexcept {} virtual void jackAudioPortDeleted(CarlaEngineJackAudioPort* const) noexcept = 0; virtual void jackCVPortDeleted(CarlaEngineJackCVPort* const) noexcept = 0; virtual void jackEventPortDeleted(CarlaEngineJackEventPort* const) noexcept = 0; }; // ----------------------------------------------------------------------- // Carla Engine JACK-Audio port class CarlaEngineJackAudioPort : public CarlaEngineAudioPort { public: CarlaEngineJackAudioPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset, jack_client_t* const jackClient, jack_port_t* const jackPort, JackPortDeletionCallback* const delCallback) noexcept : CarlaEngineAudioPort(client, isInputPort, indexOffset), fJackClient(jackClient), fJackPort(jackPort), kDeletionCallback(delCallback) { carla_debug("CarlaEngineJackAudioPort::CarlaEngineJackAudioPort(%s, %p, %p)", bool2str(isInputPort), jackClient, jackPort); switch (kClient.getEngine().getProccessMode()) { case ENGINE_PROCESS_MODE_SINGLE_CLIENT: case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS: CARLA_SAFE_ASSERT_RETURN(jackClient != nullptr && jackPort != nullptr,); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (const jack_uuid_t uuid = jackbridge_port_uuid(jackPort)) jackbridge_set_property(jackClient, uuid, JACKEY_SIGNAL_TYPE, "AUDIO", URI_TYPE_STRING); #endif break; default: CARLA_SAFE_ASSERT(jackClient == nullptr && jackPort == nullptr); break; } } ~CarlaEngineJackAudioPort() noexcept override { carla_debug("CarlaEngineJackAudioPort::~CarlaEngineJackAudioPort()"); if (fJackClient != nullptr && fJackPort != nullptr) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH try { if (const jack_uuid_t uuid = jackbridge_port_uuid(fJackPort)) jackbridge_remove_property(fJackClient, uuid, JACKEY_SIGNAL_TYPE); } CARLA_SAFE_EXCEPTION("Audio port remove meta type"); #endif try { jackbridge_port_unregister(fJackClient, fJackPort); } CARLA_SAFE_EXCEPTION("Audio port unregister"); fJackClient = nullptr; fJackPort = nullptr; } if (kDeletionCallback != nullptr) kDeletionCallback->jackAudioPortDeleted(this); } void initBuffer() noexcept override { if (fJackPort == nullptr) return CarlaEngineAudioPort::initBuffer(); const uint32_t bufferSize(kClient.getEngine().getBufferSize()); try { fBuffer = (float*)jackbridge_port_get_buffer(fJackPort, bufferSize); } catch(...) { fBuffer = nullptr; return; } if (! kIsInput) carla_zeroFloats(fBuffer, bufferSize); } void invalidate() noexcept { fJackClient = nullptr; fJackPort = nullptr; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH void setMetaData(const char* const key, const char* const value, const char* const type) override { if (fJackPort == nullptr) return CarlaEngineJackAudioPort::setMetaData(key, value, type); try { if (const jack_uuid_t uuid = jackbridge_port_uuid(fJackPort)) jackbridge_set_property(fJackClient, uuid, key, value, type); } CARLA_SAFE_EXCEPTION("Port setMetaData"); } #endif private: jack_client_t* fJackClient; jack_port_t* fJackPort; JackPortDeletionCallback* const kDeletionCallback; friend class CarlaEngineJackClient; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackAudioPort) }; // ----------------------------------------------------------------------- // Carla Engine JACK-CV port class CarlaEngineJackCVPort : public CarlaEngineCVPort { public: CarlaEngineJackCVPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset, jack_client_t* const jackClient, jack_port_t* const jackPort, JackPortDeletionCallback* const delCallback) noexcept : CarlaEngineCVPort(client, isInputPort, indexOffset), fJackClient(jackClient), fJackPort(jackPort), kDeletionCallback(delCallback) { carla_debug("CarlaEngineJackCVPort::CarlaEngineJackCVPort(%s, %p, %p)", bool2str(isInputPort), jackClient, jackPort); switch (kClient.getEngine().getProccessMode()) { case ENGINE_PROCESS_MODE_SINGLE_CLIENT: case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS: CARLA_SAFE_ASSERT_RETURN(jackClient != nullptr && jackPort != nullptr,); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (const jack_uuid_t uuid = jackbridge_port_uuid(jackPort)) jackbridge_set_property(jackClient, uuid, JACKEY_SIGNAL_TYPE, "CV", URI_TYPE_STRING); #endif break; default: CARLA_SAFE_ASSERT(jackClient == nullptr && jackPort == nullptr); break; } } ~CarlaEngineJackCVPort() noexcept override { carla_debug("CarlaEngineJackCVPort::~CarlaEngineJackCVPort()"); if (fJackClient != nullptr && fJackPort != nullptr) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH try { if (const jack_uuid_t uuid = jackbridge_port_uuid(fJackPort)) jackbridge_remove_property(fJackClient, uuid, JACKEY_SIGNAL_TYPE); } CARLA_SAFE_EXCEPTION("CV port remove meta type"); #endif try { jackbridge_port_unregister(fJackClient, fJackPort); } CARLA_SAFE_EXCEPTION("CV port unregister"); fJackClient = nullptr; fJackPort = nullptr; } if (kDeletionCallback != nullptr) kDeletionCallback->jackCVPortDeleted(this); } void initBuffer() noexcept override { if (fJackPort == nullptr) return CarlaEngineCVPort::initBuffer(); const uint32_t bufferSize(kClient.getEngine().getBufferSize()); try { fBuffer = (float*)jackbridge_port_get_buffer(fJackPort, bufferSize); } catch(...) { fBuffer = nullptr; return; } if (! kIsInput) carla_zeroFloats(fBuffer, bufferSize); } void invalidate() noexcept { fJackClient = nullptr; fJackPort = nullptr; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH void setMetaData(const char* const key, const char* const value, const char* const type) override { if (fJackPort == nullptr) return CarlaEngineCVPort::setMetaData(key, value, type); try { if (const jack_uuid_t uuid = jackbridge_port_uuid(fJackPort)) jackbridge_set_property(fJackClient, uuid, key, value, type); } CARLA_SAFE_EXCEPTION("Port setMetaData"); } #endif private: jack_client_t* fJackClient; jack_port_t* fJackPort; JackPortDeletionCallback* const kDeletionCallback; friend class CarlaEngineJackClient; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackCVPort) }; // ----------------------------------------------------------------------- // Carla Engine JACK-Event port class CarlaEngineJackEventPort : public CarlaEngineEventPort { public: CarlaEngineJackEventPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset, jack_client_t* const jackClient, jack_port_t* const jackPort, JackPortDeletionCallback* const delCallback) noexcept : CarlaEngineEventPort(client, isInputPort, indexOffset), fJackClient(jackClient), fJackPort(jackPort), fJackBuffer(nullptr), fRetEvent(kFallbackJackEngineEvent), fCvSourceEvents(nullptr), fCvSourceEventCount(0), kDeletionCallback(delCallback) { carla_debug("CarlaEngineJackEventPort::CarlaEngineJackEventPort(%s, %p, %p)", bool2str(isInputPort), jackClient, jackPort); switch (kClient.getEngine().getProccessMode()) { case ENGINE_PROCESS_MODE_SINGLE_CLIENT: case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS: CARLA_SAFE_ASSERT_RETURN(jackClient != nullptr && jackPort != nullptr,); break; default: CARLA_SAFE_ASSERT(jackClient == nullptr && jackPort == nullptr); break; } } ~CarlaEngineJackEventPort() noexcept override { carla_debug("CarlaEngineJackEventPort::~CarlaEngineJackEventPort()"); if (fJackClient != nullptr && fJackPort != nullptr) { try { jackbridge_port_unregister(fJackClient, fJackPort); } CARLA_SAFE_EXCEPTION("Event port unregister"); fJackClient = nullptr; fJackPort = nullptr; } if (kDeletionCallback != nullptr) kDeletionCallback->jackEventPortDeleted(this); } void initBuffer() noexcept override { if (fJackPort == nullptr) return CarlaEngineEventPort::initBuffer(); fCvSourceEvents = nullptr; fCvSourceEventCount = 0; try { fJackBuffer = jackbridge_port_get_buffer(fJackPort, kClient.getEngine().getBufferSize()); } catch(...) { fJackBuffer = nullptr; return; } if (! kIsInput) jackbridge_midi_clear_buffer(fJackBuffer); } void setCvSourceEvents(EngineEvent* const events, const uint32_t eventCount) noexcept { fCvSourceEvents = events; fCvSourceEventCount = eventCount; } uint32_t getEventCount() const noexcept override { if (fJackPort == nullptr) return CarlaEngineEventPort::getEventCount(); CARLA_SAFE_ASSERT_RETURN(kIsInput, 0); CARLA_SAFE_ASSERT_RETURN(fJackBuffer != nullptr, 0); try { return jackbridge_midi_get_event_count(fJackBuffer) + fCvSourceEventCount; } CARLA_SAFE_EXCEPTION_RETURN("jack_midi_get_event_count", 0); } const EngineEvent& getEvent(const uint32_t index) const noexcept override { if (fJackPort == nullptr) return CarlaEngineEventPort::getEvent(index); CARLA_SAFE_ASSERT_RETURN(kIsInput, kFallbackJackEngineEvent); CARLA_SAFE_ASSERT_RETURN(fJackBuffer != nullptr, kFallbackJackEngineEvent); return getEventUnchecked(index); } const EngineEvent& getEventUnchecked(uint32_t index) const noexcept override { if (index < fCvSourceEventCount) return fCvSourceEvents[index]; index -= fCvSourceEventCount; jack_midi_event_t jackEvent; bool test = false; try { test = jackbridge_midi_event_get(&jackEvent, fJackBuffer, index); } CARLA_SAFE_EXCEPTION_RETURN("jack_midi_event_get", kFallbackJackEngineEvent); if (! test) return kFallbackJackEngineEvent; CARLA_SAFE_ASSERT_RETURN(jackEvent.size < 0xFF /* uint8_t max */, kFallbackJackEngineEvent); uint8_t port; if (kIndexOffset < 0xFF /* uint8_t max */) { port = static_cast(kIndexOffset); } else { port = 0; carla_safe_assert_uint("kIndexOffset < 0xFF", __FILE__, __LINE__, kIndexOffset); } fRetEvent.time = jackEvent.time; fRetEvent.fillFromMidiData(static_cast(jackEvent.size), jackEvent.buffer, port); return fRetEvent; } bool writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const float value) noexcept override { if (fJackPort == nullptr) return CarlaEngineEventPort::writeControlEvent(time, channel, type, param, value); CARLA_SAFE_ASSERT_RETURN(! kIsInput, false); CARLA_SAFE_ASSERT_RETURN(fJackBuffer != nullptr, false); CARLA_SAFE_ASSERT_RETURN(type != kEngineControlEventTypeNull, false); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); CARLA_SAFE_ASSERT_RETURN(param < MAX_MIDI_VALUE, false); CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f); if (type == kEngineControlEventTypeParameter) { CARLA_SAFE_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param)); } uint8_t data[3] = { 0, 0, 0 }; EngineControlEvent ctrlEvent = { type, param, value }; const uint8_t size = ctrlEvent.convertToMidiData(channel, data); if (size == 0) return false; try { return jackbridge_midi_event_write(fJackBuffer, time, data, size); } CARLA_SAFE_EXCEPTION_RETURN("jack_midi_event_write", false); } bool writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t size, const uint8_t* const data) noexcept override { if (fJackPort == nullptr) return CarlaEngineEventPort::writeMidiEvent(time, channel, size, data); CARLA_SAFE_ASSERT_RETURN(! kIsInput, false); CARLA_SAFE_ASSERT_RETURN(fJackBuffer != nullptr, false); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); CARLA_SAFE_ASSERT_RETURN(size > 0, false); CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); jack_midi_data_t jdata[size]; jdata[0] = static_cast(MIDI_GET_STATUS_FROM_DATA(data) + channel); for (uint8_t i=1; i < size; ++i) jdata[i] = data[i]; try { return jackbridge_midi_event_write(fJackBuffer, time, jdata, size); } CARLA_SAFE_EXCEPTION_RETURN("jack_midi_event_write", false); } void invalidate() noexcept { fJackClient = nullptr; fJackPort = nullptr; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH void setMetaData(const char* const key, const char* const value, const char* const type) override { if (fJackPort == nullptr) return CarlaEngineJackEventPort::setMetaData(key, value, type); try { if (const jack_uuid_t uuid = jackbridge_port_uuid(fJackPort)) jackbridge_set_property(fJackClient, uuid, key, value, type); } CARLA_SAFE_EXCEPTION("Port setMetaData"); } #endif private: jack_client_t* fJackClient; jack_port_t* fJackPort; void* fJackBuffer; mutable EngineEvent fRetEvent; EngineEvent* fCvSourceEvents; uint32_t fCvSourceEventCount; JackPortDeletionCallback* const kDeletionCallback; friend class CarlaEngineJackClient; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackEventPort) }; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // ----------------------------------------------------------------------- // Jack Engine CV source ports class CarlaEngineJackCVSourcePorts : public CarlaEngineCVSourcePorts { public: CarlaEngineJackCVSourcePorts(const bool useClient) : CarlaEngineCVSourcePorts(), fUseClient(useClient), fBuffer(nullptr), fBufferToDeleteLater(nullptr) {} ~CarlaEngineJackCVSourcePorts() override { if (fBufferToDeleteLater != nullptr) { delete[] fBufferToDeleteLater; fBufferToDeleteLater = nullptr; } } bool addCVSource(CarlaEngineCVPort* const port, const uint32_t portIndexOffset) override { if (! fUseClient) return CarlaEngineCVSourcePorts::addCVSource(port, portIndexOffset); const CarlaRecursiveMutexLocker crml(pData->rmutex); if (! CarlaEngineCVSourcePorts::addCVSource(port, portIndexOffset)) return false; if (pData->cvs.size() == 1 && fBuffer == nullptr) { EngineEvent* const buffer = new EngineEvent[kMaxEngineEventInternalCount]; carla_zeroStructs(buffer, kMaxEngineEventInternalCount); fBuffer = buffer; } return true; } bool removeCVSource(const uint32_t portIndexOffset) override { if (! fUseClient) return CarlaEngineCVSourcePorts::removeCVSource(portIndexOffset); const CarlaRecursiveMutexLocker crml(pData->rmutex); if (! CarlaEngineCVSourcePorts::removeCVSource(portIndexOffset)) return false; if (pData->cvs.size() == 0 && fBuffer != nullptr) { if (fBufferToDeleteLater != nullptr) delete[] fBufferToDeleteLater; fBufferToDeleteLater = fBuffer; fBuffer = nullptr; } return true; } void initPortBuffers(const float* const* const buffers, const uint32_t frames, const bool sampleAccurate, CarlaEngineEventPort* const eventPort) override { if (! fUseClient) return CarlaEngineCVSourcePorts::initPortBuffers(buffers, frames, sampleAccurate, eventPort); CARLA_SAFE_ASSERT_RETURN(buffers != nullptr,); CARLA_SAFE_ASSERT_RETURN(eventPort != nullptr,); const CarlaRecursiveMutexTryLocker crmtl(pData->rmutex); if (! crmtl.wasLocked()) return; const int numCVs = pData->cvs.size(); if (numCVs == 0) return; EngineEvent* const buffer = fBuffer; CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,); uint32_t eventCount = 0; float v, min, max; for (int i = 0; i < numCVs && eventCount < kMaxEngineEventInternalCount; ++i) { CarlaEngineEventCV& ecv(pData->cvs.getReference(i)); CARLA_SAFE_ASSERT_CONTINUE(ecv.cvPort != nullptr); CARLA_SAFE_ASSERT_CONTINUE(buffers[i] != nullptr); float previousValue = ecv.previousValue; ecv.cvPort->getRange(min, max); v = buffers[i][0]; if (carla_isNotEqual(v, previousValue)) { previousValue = v; EngineEvent& event(buffer[eventCount++]); event.type = kEngineEventTypeControl; event.time = 0; event.channel = kEngineEventNonMidiChannel; event.ctrl.type = kEngineControlEventTypeParameter; event.ctrl.param = static_cast(ecv.indexOffset); event.ctrl.value = carla_fixedValue(0.0f, 1.0f, (v - min) / (max - min)); } ecv.previousValue = previousValue; } if (eventCount != 0) if (CarlaEngineJackEventPort* const jackEventPort = dynamic_cast(eventPort)) jackEventPort->setCvSourceEvents(buffer, eventCount); } CarlaRecursiveMutex& getMutex() const noexcept { return pData->rmutex; } uint32_t getPortCount() const noexcept { return static_cast(pData->cvs.size()); } CarlaEngineCVPort* getPort(const uint32_t portIndexOffset) const { const int ioffset = static_cast(portIndexOffset); return pData->cvs[ioffset].cvPort; } void setGraphAndPlugin(PatchbayGraph* const graph, CarlaPlugin* const plugin) noexcept { pData->graph = graph; pData->plugin = plugin; } private: const bool fUseClient; EngineEvent* fBuffer; EngineEvent* fBufferToDeleteLater; CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineJackCVSourcePorts) }; #endif // ----------------------------------------------------------------------- // Jack Engine client class CarlaEngineJackClient : public CarlaEngineClientForSubclassing, private JackPortDeletionCallback { public: #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaEngineJackClient(const CarlaEngine& engine, EngineInternalGraph& egraph, CarlaPlugin* const plugin, const CarlaString& mainClientName, jack_client_t* const jackClient) : CarlaEngineClientForSubclassing(engine, egraph, plugin), #else CarlaEngineJackClient(const CarlaEngine& engine, const CarlaString& mainClientName, jack_client_t* const jackClient) : CarlaEngineClientForSubclassing(engine), #endif fJackClient(jackClient), fUseClient(engine.getProccessMode() == ENGINE_PROCESS_MODE_SINGLE_CLIENT || engine.getProccessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS), fAudioPorts(), fCVPorts(), fEventPorts(), #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH fCVSourcePorts(fUseClient), #endif fMainClientName(mainClientName), fPreRenameMutex(), fPreRenameConnections(), fPreRenamePluginId(), fPreRenamePluginIcon() { carla_debug("CarlaEngineJackClient::CarlaEngineJackClient(%p)", jackClient); if (fUseClient) { CARLA_SAFE_ASSERT(jackClient != nullptr); } else { CARLA_SAFE_ASSERT(jackClient == nullptr); } } ~CarlaEngineJackClient() noexcept override { carla_debug("CarlaEngineJackClient::~CarlaEngineJackClient()"); if (getProcessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS && fJackClient != nullptr) // FIXME jackbridge_client_close(fJackClient); // ports must have been deleted by now! //fAudioPorts.clear(); //fCVPorts.clear(); //fEventPorts.clear(); } void activate() noexcept override { carla_debug("CarlaEngineJackClient::activate()"); if (getProcessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS) { CARLA_SAFE_ASSERT_RETURN(fJackClient != nullptr && ! isActive(),); try { jackbridge_activate(fJackClient); } catch(...) {} } CarlaEngineClient::activate(); const CarlaMutexLocker cml(fPreRenameMutex); if (fJackClient != nullptr) { // restore pre-rename connections const char* portNameA = nullptr; const char* portNameB = nullptr; bool doConnection = false; for (CarlaStringList::Itenerator it = fPreRenameConnections.begin2(); it.valid(); it.next()) { const bool connectNow = doConnection; doConnection = !doConnection; if (connectNow) portNameB = it.getValue(nullptr); else portNameA = it.getValue(nullptr); if (! connectNow) continue; CARLA_SAFE_ASSERT_CONTINUE(portNameA != nullptr && portNameA[0] != '\0'); CARLA_SAFE_ASSERT_CONTINUE(portNameB != nullptr && portNameB[0] != '\0'); jackbridge_connect(fJackClient, portNameA, portNameB); } if (fPreRenamePluginId.isNotEmpty()) { if (const char* const uuidchar = jackbridge_client_get_uuid(fJackClient)) { jack_uuid_t uuid; if (jackbridge_uuid_parse(uuidchar, &uuid)) { jackbridge_set_property(fJackClient, uuid, URI_MAIN_CLIENT_NAME, fMainClientName, URI_TYPE_STRING); jackbridge_set_property(fJackClient, uuid, URI_PLUGIN_ID, fPreRenamePluginId, URI_TYPE_INTEGER); if (fPreRenamePluginIcon.isNotEmpty()) jackbridge_set_property(fJackClient, uuid, URI_PLUGIN_ICON, fPreRenamePluginIcon, URI_TYPE_STRING); } } } } fPreRenameConnections.clear(); fPreRenamePluginId.clear(); fPreRenamePluginIcon.clear(); } void deactivate() noexcept override { carla_debug("CarlaEngineJackClient::deactivate()"); if (getProcessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS) { CARLA_SAFE_ASSERT_RETURN(fJackClient != nullptr && isActive(),); try { jackbridge_deactivate(fJackClient); } catch(...) {} } CarlaEngineClient::deactivate(); } bool isOk() const noexcept override { if (fUseClient) return (fJackClient != nullptr); return CarlaEngineClient::isOk(); } CarlaEnginePort* addPort(const EnginePortType portType, const char* const name, const bool isInput, const uint32_t indexOffset) override { carla_debug("CarlaEngineJackClient::addPort(%i:%s, \"%s\", %s)", portType, EnginePortType2Str(portType), name, bool2str(isInput)); jack_port_t* jackPort = nullptr; const char* realName = name; // Create JACK port first, if needed if (fUseClient) { CARLA_SAFE_ASSERT_RETURN(fJackClient != nullptr, nullptr); realName = pData->getUniquePortName(name); switch (portType) { case kEnginePortTypeNull: break; case kEnginePortTypeAudio: jackPort = jackbridge_port_register(fJackClient, realName, JACK_DEFAULT_AUDIO_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0); break; case kEnginePortTypeCV: jackPort = jackbridge_port_register(fJackClient, realName, JACK_DEFAULT_AUDIO_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0); break; case kEnginePortTypeEvent: jackPort = jackbridge_port_register(fJackClient, realName, JACK_DEFAULT_MIDI_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0); break; } CARLA_SAFE_ASSERT_RETURN(jackPort != nullptr, nullptr); } // Create Engine port switch (portType) { case kEnginePortTypeNull: break; case kEnginePortTypeAudio: { pData->addAudioPortName(isInput, realName); if (realName != name) delete[] realName; CarlaEngineJackAudioPort* const enginePort(new CarlaEngineJackAudioPort(*this, isInput, indexOffset, fJackClient, jackPort, this)); fAudioPorts.append(enginePort); return enginePort; } case kEnginePortTypeCV: { pData->addCVPortName(isInput, realName); if (realName != name) delete[] realName; CarlaEngineJackCVPort* const enginePort(new CarlaEngineJackCVPort(*this, isInput, indexOffset, fJackClient, jackPort, this)); fCVPorts.append(enginePort); return enginePort; } case kEnginePortTypeEvent: { pData->addEventPortName(isInput, realName); if (realName != name) delete[] realName; CarlaEngineJackEventPort* const enginePort(new CarlaEngineJackEventPort(*this, isInput, indexOffset, fJackClient, jackPort, this)); fEventPorts.append(enginePort); return enginePort; } } carla_stderr("CarlaEngineJackClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput)); return nullptr; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaEngineCVSourcePorts* createCVSourcePorts() override { fCVSourcePorts.setGraphAndPlugin(getPatchbayGraphOrNull(), getPlugin()); return &fCVSourcePorts; } CarlaEngineJackCVSourcePorts& getCVSourcePorts() noexcept { return fCVSourcePorts; } #endif void invalidate() noexcept { for (LinkedList::Itenerator it = fAudioPorts.begin2(); it.valid(); it.next()) { CarlaEngineJackAudioPort* const port(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(port != nullptr); port->invalidate(); } for (LinkedList::Itenerator it = fCVPorts.begin2(); it.valid(); it.next()) { CarlaEngineJackCVPort* const port(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(port != nullptr); port->invalidate(); } for (LinkedList::Itenerator it = fEventPorts.begin2(); it.valid(); it.next()) { CarlaEngineJackEventPort* const port(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(port != nullptr); port->invalidate(); } fJackClient = nullptr; CarlaEngineClient::deactivate(); } const char* getJackClientName() const noexcept { CARLA_SAFE_ASSERT_RETURN(fJackClient != nullptr, nullptr); try { return jackbridge_get_client_name(fJackClient); } CARLA_SAFE_EXCEPTION_RETURN("jack_get_client_name", nullptr); } void jackAudioPortDeleted(CarlaEngineJackAudioPort* const port) noexcept override { fAudioPorts.removeAll(port); } void jackCVPortDeleted(CarlaEngineJackCVPort* const port) noexcept override { fCVPorts.removeAll(port); } void jackEventPortDeleted(CarlaEngineJackEventPort* const port) noexcept override { fEventPorts.removeAll(port); } bool renameInSingleClient(const CarlaString& newClientName) { const CarlaString clientNamePrefix(newClientName + ":"); return _renamePorts(fAudioPorts, clientNamePrefix) && _renamePorts(fCVPorts, clientNamePrefix) && _renamePorts(fEventPorts, clientNamePrefix); } void closeForRename(jack_client_t* const newClient, const CarlaString& newClientName) noexcept { if (fJackClient != nullptr) { if (isActive()) { { const CarlaString clientNamePrefix(newClientName + ":"); // store current client connections const CarlaMutexLocker cml(fPreRenameMutex); fPreRenameConnections.clear(); fPreRenamePluginId.clear(); fPreRenamePluginIcon.clear(); _savePortsConnections(fAudioPorts, clientNamePrefix); _savePortsConnections(fCVPorts, clientNamePrefix); _savePortsConnections(fEventPorts, clientNamePrefix); _saveProperties(); } try { jackbridge_deactivate(fJackClient); } catch(...) {} } try { jackbridge_client_close(fJackClient); } catch(...) {} invalidate(); } fAudioPorts.clear(); fCVPorts.clear(); fEventPorts.clear(); pData->clearPorts(); fJackClient = newClient; } void setNewPluginId(const uint id) const { if (const char* const uuidchar = jackbridge_client_get_uuid(fJackClient)) { jack_uuid_t uuid; if (jackbridge_uuid_parse(uuidchar, &uuid)) { char buf[32]; std::snprintf(buf, 32, "%u", id); jackbridge_set_property(fJackClient, uuid, URI_PLUGIN_ID, buf, URI_TYPE_INTEGER); } } } private: jack_client_t* fJackClient; const bool fUseClient; LinkedList fAudioPorts; LinkedList fCVPorts; LinkedList fEventPorts; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaEngineJackCVSourcePorts fCVSourcePorts; #endif const CarlaString& fMainClientName; CarlaMutex fPreRenameMutex; CarlaStringList fPreRenameConnections; CarlaString fPreRenamePluginId; CarlaString fPreRenamePluginIcon; template bool _renamePorts(const LinkedList& t, const CarlaString& clientNamePrefix) { for (typename LinkedList::Itenerator it = t.begin2(); it.valid(); it.next()) { T* const port(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(port != nullptr); CARLA_SAFE_ASSERT_CONTINUE(port->fJackPort != nullptr); const char* shortPortName(jackbridge_port_short_name(port->fJackPort)); CARLA_SAFE_ASSERT_CONTINUE(shortPortName != nullptr && shortPortName[0] != '\0'); const char* const oldClientNameSep(std::strstr(shortPortName, ":")); CARLA_SAFE_ASSERT_CONTINUE(oldClientNameSep != nullptr && oldClientNameSep[0] != '\0' && oldClientNameSep[1] != '\0'); shortPortName += oldClientNameSep-shortPortName + 1; const CarlaString newPortName(clientNamePrefix + shortPortName); if (! jackbridge_port_rename(fJackClient, port->fJackPort, newPortName)) return false; } return true; } template void _savePortsConnections(const LinkedList& t, const CarlaString& clientNamePrefix) { for (typename LinkedList::Itenerator it = t.begin2(); it.valid(); it.next()) { T* const port(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(port != nullptr); CARLA_SAFE_ASSERT_CONTINUE(port->fJackPort != nullptr); const char* const shortPortName(jackbridge_port_short_name(port->fJackPort)); CARLA_SAFE_ASSERT_CONTINUE(shortPortName != nullptr && shortPortName[0] != '\0'); const CarlaString portName(clientNamePrefix + shortPortName); if (const char** const connections = jackbridge_port_get_all_connections(fJackClient, port->fJackPort)) { for (int i=0; connections[i] != nullptr; ++i) { if (port->kIsInput) { fPreRenameConnections.append(connections[i]); fPreRenameConnections.append(portName); } else { fPreRenameConnections.append(portName); fPreRenameConnections.append(connections[i]); } } jackbridge_free(connections); } } } void _saveProperties() { if (const char* const uuidchar = jackbridge_client_get_uuid(fJackClient)) { jack_uuid_t uuid; if (jackbridge_uuid_parse(uuidchar, &uuid)) { char* value; char* type; CARLA_SAFE_ASSERT_RETURN(jackbridge_get_property(uuid, URI_PLUGIN_ID, &value, &type),); CARLA_SAFE_ASSERT_RETURN(type != nullptr,); CARLA_SAFE_ASSERT_RETURN(std::strcmp(type, URI_TYPE_INTEGER) == 0,); fPreRenamePluginId = value; if (jackbridge_get_property(uuid, URI_PLUGIN_ICON, &value, &type)) { CARLA_SAFE_ASSERT_RETURN(type != nullptr,); CARLA_SAFE_ASSERT_RETURN(std::strcmp(type, URI_TYPE_STRING) == 0,); fPreRenamePluginIcon = value; } } } } CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackClient) }; // ----------------------------------------------------------------------- // Jack Engine class CarlaEngineJack : public CarlaEngine #ifndef BUILD_BRIDGE , private CarlaThread #endif { public: CarlaEngineJack() : CarlaEngine(), #ifndef BUILD_BRIDGE CarlaThread("CarlaEngineJackCallbacks"), #endif fClient(nullptr), fExternalPatchbayHost(true), fExternalPatchbayOsc(true), fFreewheel(false), fClientName(), #ifdef BUILD_BRIDGE fIsRunning(false) #else fTimebaseMaster(false), fTimebaseRolling(false), fTimebaseUsecs(0), fUsedGroups(), fUsedPorts(), fUsedConnections(), fPatchbayProcThreadProtectionMutex(), fRetConns(), fPostPonedEvents(), fPostPonedEventsMutex(), fIsInternalClient(false) #endif { carla_debug("CarlaEngineJack::CarlaEngineJack()"); #ifdef BUILD_BRIDGE pData->options.processMode = ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS; #else carla_zeroPointers(fRackPorts, kRackPortCount); #endif } ~CarlaEngineJack() noexcept override { carla_debug("CarlaEngineJack::~CarlaEngineJack()"); CARLA_SAFE_ASSERT(fClient == nullptr); #ifndef BUILD_BRIDGE fUsedGroups.clear(); fUsedPorts.clear(); fUsedConnections.clear(); CARLA_SAFE_ASSERT(fPostPonedEvents.count() == 0); #endif } // ------------------------------------------------------------------- // Maximum values uint getMaxClientNameSize() const noexcept override { #ifndef BUILD_BRIDGE if (pData->options.processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT || pData->options.processMode == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS) #endif { try { return static_cast(jackbridge_client_name_size()-1); } CARLA_SAFE_EXCEPTION_RETURN("jack_client_name_size", 32); } return CarlaEngine::getMaxClientNameSize(); } uint getMaxPortNameSize() const noexcept override { if (pData->options.processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT || pData->options.processMode == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS) { try { return static_cast(jackbridge_port_name_size()-1); } CARLA_SAFE_EXCEPTION_RETURN("jack_port_name_size", 255); } return CarlaEngine::getMaxPortNameSize(); } // ------------------------------------------------------------------- // Virtual, per-engine type calls bool init(const char* const clientName) override { CARLA_SAFE_ASSERT_RETURN(fClient != nullptr || (clientName != nullptr && clientName[0] != '\0'), false); CARLA_SAFE_ASSERT_RETURN(jackbridge_is_ok(), false); carla_debug("CarlaEngineJack::init(\"%s\")", clientName); fFreewheel = false; fExternalPatchbayHost = true; fExternalPatchbayOsc = true; CarlaString truncatedClientName; if (fClient == nullptr && clientName != nullptr) { truncatedClientName = clientName; truncatedClientName.truncate(getMaxClientNameSize()); } #ifdef BUILD_BRIDGE fIsRunning = true; if (! pData->init(truncatedClientName)) { close(); setLastError("Failed to init internal data"); return false; } if (pData->bufferSize == 0 || carla_isEqual(pData->sampleRate, 0.0)) { // open temp client to get initial buffer-size and sample-rate values if (jack_client_t* const tmpClient = jackbridge_client_open(truncatedClientName, JackNoStartServer, nullptr)) { pData->bufferSize = jackbridge_get_buffer_size(tmpClient); pData->sampleRate = jackbridge_get_sample_rate(tmpClient); jackbridge_client_close(tmpClient); } else { close(); setLastError("Failed to init temporary jack client"); return false; } } return true; #else if (fClient == nullptr && clientName != nullptr) fClient = jackbridge_client_open(truncatedClientName, JackNoStartServer, nullptr); if (fClient == nullptr) { setLastError("Failed to create new JACK client"); return false; } const char* const jackClientName = jackbridge_get_client_name(fClient); if (! pData->init(jackClientName)) { jackbridge_client_close(fClient); fClient = nullptr; setLastError("Failed to init internal data"); return false; } fClientName = jackClientName; const EngineOptions& opts(pData->options); pData->bufferSize = jackbridge_get_buffer_size(fClient); pData->sampleRate = jackbridge_get_sample_rate(fClient); pData->initTime(opts.transportExtra); jackbridge_set_thread_init_callback(fClient, carla_jack_thread_init_callback, nullptr); jackbridge_set_buffer_size_callback(fClient, carla_jack_bufsize_callback, this); jackbridge_set_sample_rate_callback(fClient, carla_jack_srate_callback, this); jackbridge_set_freewheel_callback(fClient, carla_jack_freewheel_callback, this); jackbridge_set_latency_callback(fClient, carla_jack_latency_callback, this); jackbridge_set_process_callback(fClient, carla_jack_process_callback, this); jackbridge_on_shutdown(fClient, carla_jack_shutdown_callback, this); fTimebaseRolling = false; if (opts.transportMode == ENGINE_TRANSPORT_MODE_JACK) fTimebaseMaster = jackbridge_set_timebase_callback(fClient, true, carla_jack_timebase_callback, this); else fTimebaseMaster = false; if (opts.processMode != ENGINE_PROCESS_MODE_PATCHBAY) initJackPatchbay(true, false, jackClientName); jackbridge_set_client_registration_callback(fClient, carla_jack_client_registration_callback, this); jackbridge_set_port_registration_callback(fClient, carla_jack_port_registration_callback, this); jackbridge_set_port_connect_callback(fClient, carla_jack_port_connect_callback, this); jackbridge_set_port_rename_callback(fClient, carla_jack_port_rename_callback, this); jackbridge_set_xrun_callback(fClient, carla_jack_xrun_callback, this); if (opts.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || opts.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { fRackPorts[kRackPortAudioIn1] = jackbridge_port_register(fClient, "audio-in1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); fRackPorts[kRackPortAudioIn2] = jackbridge_port_register(fClient, "audio-in2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); fRackPorts[kRackPortAudioOut1] = jackbridge_port_register(fClient, "audio-out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); fRackPorts[kRackPortAudioOut2] = jackbridge_port_register(fClient, "audio-out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); fRackPorts[kRackPortEventIn] = jackbridge_port_register(fClient, "events-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); fRackPorts[kRackPortEventOut] = jackbridge_port_register(fClient, "events-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); if (opts.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { // FIXME? pData->graph.create(0, 0, 0, 0); } else { pData->graph.create(2, 2, 0, 0); // pData->graph.setUsingExternalHost(true); // pData->graph.setUsingExternalOSC(true); patchbayRefresh(true, false, false); } } if (const char* const uuidchar = jackbridge_client_get_uuid(fClient)) { jack_uuid_t uuid; if (jackbridge_uuid_parse(uuidchar, &uuid)) { #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) const CarlaString& tcp(pData->osc.getServerPathTCP()); const CarlaString& udp(pData->osc.getServerPathUDP()); if (tcp.isNotEmpty()) jackbridge_set_property(fClient, uuid, "https://kx.studio/ns/carla/osc-tcp", tcp.buffer(), URI_TYPE_STRING); if (tcp.isNotEmpty()) jackbridge_set_property(fClient, uuid, "https://kx.studio/ns/carla/osc-udp", udp.buffer(), URI_TYPE_STRING); #endif } } if (jackbridge_activate(fClient)) { if (opts.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || opts.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { if (pData->options.audioDevice != nullptr && std::strcmp(pData->options.audioDevice, "Auto-Connect ON") == 0 && std::getenv("LADISH_APP_NAME") == nullptr && std::getenv("NSM_URL") == nullptr) { char strBuf[STR_MAX]; if (jackbridge_port_by_name(fClient, "system:capture_1") != nullptr) { std::snprintf(strBuf, STR_MAX, "%s:audio-in1", jackClientName); strBuf[STR_MAX-1] = '\0'; jackbridge_connect(fClient, "system:capture_1", strBuf); std::snprintf(strBuf, STR_MAX, "%s:audio-in2", jackClientName); strBuf[STR_MAX-1] = '\0'; if (jackbridge_port_by_name(fClient, "system:capture_2") != nullptr) jackbridge_connect(fClient, "system:capture_2", strBuf); else jackbridge_connect(fClient, "system:capture_1", strBuf); } if (jackbridge_port_by_name(fClient, "system:playback_1") != nullptr) { std::snprintf(strBuf, STR_MAX, "%s:audio-out1", jackClientName); strBuf[STR_MAX-1] = '\0'; jackbridge_connect(fClient, strBuf, "system:playback_1"); std::snprintf(strBuf, STR_MAX, "%s:audio-out2", jackClientName); strBuf[STR_MAX-1] = '\0'; if (jackbridge_port_by_name(fClient, "system:playback_2") != nullptr) jackbridge_connect(fClient, strBuf, "system:playback_2"); else jackbridge_connect(fClient, strBuf, "system:playback_1"); } } } startThread(); callback(true, true, ENGINE_CALLBACK_ENGINE_STARTED, 0, opts.processMode, opts.transportMode, static_cast(pData->bufferSize), static_cast(pData->sampleRate), getCurrentDriverName()); return true; } if (opts.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || opts.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { pData->graph.destroy(); } pData->close(); jackbridge_client_close(fClient); fClient = nullptr; setLastError("Failed to activate the JACK client"); return false; #endif } #ifndef BUILD_BRIDGE bool initInternal(jack_client_t* const client) { fClient = client; fIsInternalClient = true; return init(nullptr); } #endif bool close() override { carla_debug("CarlaEngineJack::close()"); #ifdef BUILD_BRIDGE fClient = nullptr; fIsRunning = false; CarlaEngine::close(); return true; #else stopThread(-1); fClientName.clear(); fPostPonedEvents.clear(); CARLA_SAFE_ASSERT_RETURN_ERR(fClient != nullptr, "JACK Client is null"); // deactivate and close client jackbridge_deactivate(fClient); jackbridge_client_close(fClient); // clear engine data CarlaEngine::close(); fUsedGroups.clear(); fUsedPorts.clear(); fUsedConnections.clear(); fPostPonedEvents.clear(); // clear rack/patchbay stuff if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { carla_zeroPointers(fRackPorts, kRackPortCount); pData->graph.destroy(); } fClient = nullptr; return true; #endif } bool isRunning() const noexcept override { #ifdef BUILD_BRIDGE return (fClient != nullptr || fIsRunning); #else return (fClient != nullptr); #endif } bool isOffline() const noexcept override { return fFreewheel; } EngineType getType() const noexcept override { return kEngineTypeJack; } const char* getCurrentDriverName() const noexcept override { return "JACK"; } #ifndef BUILD_BRIDGE float getDSPLoad() const noexcept override { CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, 0.0f); return jackbridge_cpu_load(fClient); } void callback(const bool sendHost, const bool sendOsc, const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const int value3, const float valuef, const char* const valueStr) noexcept override { if (action == ENGINE_CALLBACK_PROJECT_LOAD_FINISHED && fTimebaseMaster) { // project finished loading, need to set bpm here, so we force an update of timebase master transportRelocate(pData->timeInfo.frame); } CarlaEngine::callback(sendHost, sendOsc, action, pluginId, value1, value2, value3, valuef, valueStr); } #endif bool setBufferSizeAndSampleRate(const uint bufferSize, const double sampleRate) override { CARLA_SAFE_ASSERT_RETURN(carla_isEqual(pData->sampleRate, sampleRate), false); CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, false); try { return jackbridge_set_buffer_size(fClient, bufferSize); } CARLA_SAFE_EXCEPTION_RETURN("setBufferSizeAndSampleRate", false); } EngineTimeInfo getTimeInfo() const noexcept override { if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK) return CarlaEngine::getTimeInfo(); if (pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS) return CarlaEngine::getTimeInfo(); jack_position_t jpos; // invalidate jpos.unique_1 = 1; jpos.unique_2 = 2; EngineTimeInfo timeInfo; const bool playing = jackbridge_transport_query(fClient, &jpos) == JackTransportRolling; if (jpos.unique_1 != jpos.unique_2) { timeInfo.playing = false; timeInfo.frame = 0; timeInfo.usecs = 0; timeInfo.bbt.valid = false; return timeInfo; } timeInfo.playing = playing; timeInfo.frame = jpos.frame; timeInfo.usecs = jpos.usecs; if (jpos.valid & JackPositionBBT) { timeInfo.bbt.valid = true; timeInfo.bbt.bar = jpos.bar; timeInfo.bbt.beat = jpos.beat; timeInfo.bbt.tick = jpos.tick; timeInfo.bbt.barStartTick = jpos.bar_start_tick; timeInfo.bbt.beatsPerBar = jpos.beats_per_bar; timeInfo.bbt.beatType = jpos.beat_type; timeInfo.bbt.ticksPerBeat = jpos.ticks_per_beat; timeInfo.bbt.beatsPerMinute = jpos.beats_per_minute; } else { timeInfo.bbt.valid = false; } return timeInfo; } #ifndef BUILD_BRIDGE void setOption(const EngineOption option, const int value, const char* const valueStr) noexcept override { if (option == ENGINE_OPTION_TRANSPORT_MODE && fClient != nullptr) { CARLA_SAFE_ASSERT_RETURN(value >= ENGINE_TRANSPORT_MODE_DISABLED && value <= ENGINE_TRANSPORT_MODE_JACK,); if (value == ENGINE_TRANSPORT_MODE_JACK) { fTimebaseMaster = jackbridge_set_timebase_callback(fClient, true, carla_jack_timebase_callback, this); } else { // jack transport cannot be disabled in multi-client callback(true, true, ENGINE_CALLBACK_TRANSPORT_MODE_CHANGED, 0, ENGINE_TRANSPORT_MODE_JACK, 0, 0, 0.0f, pData->options.transportExtra); CARLA_SAFE_ASSERT_RETURN(pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS,); jackbridge_release_timebase(fClient); fTimebaseMaster = false; } } CarlaEngine::setOption(option, value, valueStr); } #endif CarlaEngineClient* addClient(CarlaPlugin* const plugin) override { jack_client_t* client = nullptr; #ifndef BUILD_BRIDGE if (pData->options.processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { client = fClient; } else if (pData->options.processMode == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS) #endif { client = jackbridge_client_open(plugin->getName(), JackNoStartServer, nullptr); CARLA_SAFE_ASSERT_RETURN(client != nullptr, nullptr); jackbridge_set_thread_init_callback(client, carla_jack_thread_init_callback, nullptr); #ifndef BUILD_BRIDGE /* jackbridge_set_buffer_size_callback(fClient, carla_jack_bufsize_callback_plugin, plugin); jackbridge_set_sample_rate_callback(fClient, carla_jack_srate_callback_plugin, plugin); */ jackbridge_set_latency_callback(client, carla_jack_latency_callback_plugin, plugin); jackbridge_set_process_callback(client, carla_jack_process_callback_plugin, plugin); jackbridge_on_shutdown(client, carla_jack_shutdown_callback_plugin, plugin); if (const char* const uuidchar = jackbridge_client_get_uuid(client)) { jack_uuid_t uuid; if (jackbridge_uuid_parse(uuidchar, &uuid)) { char strBufId[24]; std::snprintf(strBufId, 24, "%u", plugin->getId()); strBufId[23] = '\0'; jackbridge_set_property(client, uuid, URI_MAIN_CLIENT_NAME, fClientName, URI_TYPE_STRING); jackbridge_set_property(client, uuid, URI_PLUGIN_ID, strBufId, URI_TYPE_INTEGER); if (const char* const pluginIcon = plugin->getIconName()) jackbridge_set_property(client, uuid, URI_PLUGIN_ICON, pluginIcon, URI_TYPE_STRING); } } #else fClient = client; pData->bufferSize = jackbridge_get_buffer_size(client); pData->sampleRate = jackbridge_get_sample_rate(client); pData->initTime(nullptr); jackbridge_set_buffer_size_callback(client, carla_jack_bufsize_callback, this); jackbridge_set_sample_rate_callback(client, carla_jack_srate_callback, this); jackbridge_set_freewheel_callback(client, carla_jack_freewheel_callback, this); jackbridge_set_latency_callback(client, carla_jack_latency_callback, this); jackbridge_set_process_callback(client, carla_jack_process_callback, this); jackbridge_on_shutdown(client, carla_jack_shutdown_callback, this); fClientName = jackbridge_get_client_name(client); #endif } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH return new CarlaEngineJackClient(*this, pData->graph, plugin, fClientName, client); #else return new CarlaEngineJackClient(*this, fClientName, client); #endif } #ifndef BUILD_BRIDGE bool removePlugin(const uint id) override { if (! CarlaEngine::removePlugin(id)) return false; for (uint i=id; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin = pData->plugins[i].plugin; CARLA_SAFE_ASSERT_BREAK(plugin != nullptr); CarlaEngineJackClient* const client = dynamic_cast(plugin->getEngineClient()); CARLA_SAFE_ASSERT_BREAK(client != nullptr); client->setNewPluginId(i); } return true; } bool switchPlugins(const uint idA, const uint idB) noexcept override { if (! CarlaEngine::switchPlugins(idA, idB)) return false; CarlaPlugin* const newPluginA(pData->plugins[idA].plugin); CARLA_SAFE_ASSERT_RETURN(newPluginA != nullptr, true); CarlaPlugin* const newPluginB(pData->plugins[idB].plugin); CARLA_SAFE_ASSERT_RETURN(newPluginB != nullptr, true); CarlaEngineJackClient* const clientA = dynamic_cast(newPluginA->getEngineClient()); CARLA_SAFE_ASSERT_RETURN(clientA != nullptr, true); CarlaEngineJackClient* const clientB = dynamic_cast(newPluginB->getEngineClient()); CARLA_SAFE_ASSERT_RETURN(clientB != nullptr, true); clientA->setNewPluginId(idA); clientB->setNewPluginId(idB); return true; } bool renamePlugin(const uint id, const char* const newName) override { if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { return CarlaEngine::renamePlugin(id, newName); } CARLA_SAFE_ASSERT_RETURN(pData->plugins != nullptr, false); CARLA_SAFE_ASSERT_RETURN(pData->curPluginCount != 0, false); CARLA_SAFE_ASSERT_RETURN(id < pData->curPluginCount, false); CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0', false); CarlaPlugin* const plugin(pData->plugins[id].plugin); CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to rename"); CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data"); // before we stop the engine thread we might need to get the plugin data const bool needsReinit = (pData->options.processMode == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS); const CarlaStateSave* saveStatePtr = nullptr; if (needsReinit) { const CarlaStateSave& saveState(plugin->getStateSave()); saveStatePtr = &saveState; } CarlaString uniqueName; try { const char* const tmpName = getUniquePluginName(newName); uniqueName = tmpName; delete[] tmpName; } CARLA_SAFE_EXCEPTION("JACK renamePlugin getUniquePluginName"); if (uniqueName.isEmpty()) { setLastError("Failed to request new unique plugin name"); return false; } const ScopedThreadStopper sts(this); // rename on client client mode, just rename the ports if (pData->options.processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { CarlaEngineJackClient* const client((CarlaEngineJackClient*)plugin->getEngineClient()); if (! client->renameInSingleClient(uniqueName)) { setLastError("Failed to rename some JACK ports, does your JACK version support proper port renaming?"); return false; } } // rename in multiple client mode else if (pData->options.processMode == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS) { CarlaEngineJackClient* const client((CarlaEngineJackClient*)plugin->getEngineClient()); // we should not be able to do this, jack really needs to allow client rename if (jack_client_t* const jackClient = jackbridge_client_open(uniqueName, JackNoStartServer, nullptr)) { // get new client name uniqueName = jackbridge_get_client_name(jackClient); fClientName = uniqueName; // close client client->closeForRename(jackClient, uniqueName); // disable plugin plugin->setEnabled(false); // set new client data jackbridge_set_latency_callback(jackClient, carla_jack_latency_callback_plugin, plugin); jackbridge_set_process_callback(jackClient, carla_jack_process_callback_plugin, plugin); jackbridge_on_shutdown(jackClient, carla_jack_shutdown_callback_plugin, plugin); // NOTE: jack1 locks up here if (jackbridge_get_version_string() != nullptr) jackbridge_set_thread_init_callback(jackClient, carla_jack_thread_init_callback, nullptr); /* The following code is because of a tricky situation. We cannot lock or do jack operations during jack callbacks on jack1. jack2 events are asynchronous. When we close the client jack will trigger unregister-port callbacks, which we handle on a separate thread ASAP. But before that happens we already registered a new client with the same ports (the "renamed" one), and at this point the port we receive during that callback is actually the new one from the new client.. JACK2 seems to be reusing ports to save space, which is understandable. Anyway, this means we have to remove all our port-related data before the new client ports are created. (we also stop the separate jack-events thread to avoid any race conditions while modying our port data) */ stopThread(-1); const uint groupId(fUsedGroups.getGroupId(plugin->getName())); if (groupId > 0) { for (LinkedList::Itenerator it = fUsedPorts.list.begin2(); it.valid(); it.next()) { for (LinkedList::Itenerator it2 = fUsedConnections.list.begin2(); it2.valid(); it2.next()) { static ConnectionToId connectionFallback = { 0, 0, 0, 0, 0 }; ConnectionToId& connectionToId = it2.getValue(connectionFallback); CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0); if (connectionToId.groupA != groupId && connectionToId.groupB != groupId) continue; callback(fExternalPatchbayHost, fExternalPatchbayOsc, ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connectionToId.id, 0, 0, 0, 0.0f, nullptr); fUsedConnections.list.remove(it2); } static PortNameToId portNameFallback = { 0, 0, { '\0' }, { '\0' } }; PortNameToId& portNameToId(it.getValue(portNameFallback)); CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group != 0); if (portNameToId.group != groupId) continue; callback(fExternalPatchbayHost, fExternalPatchbayOsc, ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, portNameToId.group, static_cast(portNameToId.port), 0, 0, 0.0f, nullptr); fUsedPorts.list.remove(it); } } startThread(); } else { setLastError("Failed to create new JACK client"); return false; } } // Rename plugin->setName(uniqueName); if (needsReinit) { // reload plugin to recreate its ports plugin->reload(); plugin->loadStateSave(*saveStatePtr); plugin->setEnabled(true); } callback(true, true, ENGINE_CALLBACK_PLUGIN_RENAMED, id, 0, 0, 0, 0.0f, uniqueName); return true; } // ------------------------------------------------------------------- // Patchbay bool patchbayConnect(const bool external, const uint groupA, const uint portA, const uint groupB, const uint portB) override { CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, false); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY && ! external) return CarlaEngine::patchbayConnect(false, groupA, portA, groupB, portB); const char* const fullPortNameA = fUsedPorts.getFullPortName(groupA, portA); CARLA_SAFE_ASSERT_RETURN(fullPortNameA != nullptr && fullPortNameA[0] != '\0', false); const char* const fullPortNameB = fUsedPorts.getFullPortName(groupB, portB); CARLA_SAFE_ASSERT_RETURN(fullPortNameB != nullptr && fullPortNameB[0] != '\0', false); if (! jackbridge_connect(fClient, fullPortNameA, fullPortNameB)) { setLastError("JACK operation failed"); return false; } return true; } bool patchbayDisconnect(const bool external, const uint connectionId) override { CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, false); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY && ! external) return CarlaEngine::patchbayDisconnect(false, connectionId); ConnectionToId connectionToId = { 0, 0, 0, 0, 0 }; { const CarlaMutexLocker cml(fUsedConnections.mutex); for (LinkedList::Itenerator it = fUsedConnections.list.begin2(); it.valid(); it.next()) { connectionToId = it.getValue(connectionToId); CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0); if (connectionToId.id == connectionId) break; } } if (connectionToId.id == 0 || connectionToId.id != connectionId) { setLastError("Failed to find the requested connection"); return false; } const char* const fullPortNameA = fUsedPorts.getFullPortName(connectionToId.groupA, connectionToId.portA); CARLA_SAFE_ASSERT_RETURN(fullPortNameA != nullptr && fullPortNameA[0] != '\0', false); const char* const fullPortNameB = fUsedPorts.getFullPortName(connectionToId.groupB, connectionToId.portB); CARLA_SAFE_ASSERT_RETURN(fullPortNameB != nullptr && fullPortNameB[0] != '\0', false); if (! jackbridge_disconnect(fClient, fullPortNameA, fullPortNameB)) { setLastError("JACK operation failed"); return false; } return true; } bool patchbayRefresh(const bool sendHost, const bool sendOSC, const bool external) override { CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, false); carla_debug("patchbayRefresh(%s, %s, %s)", bool2str(sendHost), bool2str(sendOSC), bool2str(external)); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { if (sendHost) { fExternalPatchbayHost = external; pData->graph.setUsingExternalHost(external); } if (sendOSC) { fExternalPatchbayOsc = external; pData->graph.setUsingExternalOSC(external); } if (! external) return CarlaEngine::patchbayRefresh(sendHost, sendOSC, false); } fUsedGroups.clear(); fUsedPorts.clear(); fUsedConnections.clear(); initJackPatchbay(sendHost, sendOSC, jackbridge_get_client_name(fClient)); return true; } // ------------------------------------------------------------------- // Transport void transportPlay() noexcept override { if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK) return CarlaEngine::transportPlay(); if (fClient != nullptr) { if (! pData->timeInfo.bbt.valid) { // old timebase master no longer active, make ourselves master again pData->time.setNeedsReset(); fTimebaseMaster = jackbridge_set_timebase_callback(fClient, true, carla_jack_timebase_callback, this); } try { jackbridge_transport_start(fClient); } catch(...) {} } } void transportPause() noexcept override { if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK) return CarlaEngine::transportPause(); if (fClient != nullptr) { try { jackbridge_transport_stop(fClient); } catch(...) {} } } void transportBPM(const double bpm) noexcept override { if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK || fTimebaseMaster) return CarlaEngine::transportBPM(bpm); if (fClient == nullptr) return; jack_position_t jpos; // invalidate jpos.unique_1 = 1; jpos.unique_2 = 2; jackbridge_transport_query(fClient, &jpos); if (jpos.unique_1 == jpos.unique_2 && (jpos.valid & JackPositionBBT) != 0) { carla_stdout("NOTE: Changing BPM without being JACK timebase master"); jpos.beats_per_minute = bpm; try { jackbridge_transport_reposition(fClient, &jpos); } catch(...) {} } } void transportRelocate(const uint64_t frame) noexcept override { if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK) return CarlaEngine::transportRelocate(frame); if (fClient != nullptr) { try { jackbridge_transport_locate(fClient, static_cast(frame)); } catch(...) {} } } // ------------------------------------------------------------------- // Patchbay stuff const char* const* getPatchbayConnections(const bool external) const override { CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, nullptr); carla_debug("CarlaEngineJack::getPatchbayConnections(%s)", bool2str(external)); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY && ! external) return CarlaEngine::getPatchbayConnections(external); CarlaStringList connList; if (const char** const ports = jackbridge_get_ports(fClient, nullptr, nullptr, JackPortIsOutput)) { for (int i=0; ports[i] != nullptr; ++i) { const jack_port_t* const jackPort(jackbridge_port_by_name(fClient, ports[i])); const char* const fullPortName(ports[i]); CARLA_SAFE_ASSERT_CONTINUE(jackPort != nullptr); if (const char** const connections = jackbridge_port_get_all_connections(fClient, jackPort)) { for (int j=0; connections[j] != nullptr; ++j) { connList.append(fullPortName); connList.append(connections[j]); } jackbridge_free(connections); } } jackbridge_free(ports); } if (connList.count() == 0) return nullptr; fRetConns = connList.toCharStringListPtr(); return fRetConns; } void restorePatchbayConnection(const bool external, const char* const connSource, const char* const connTarget) override { CARLA_SAFE_ASSERT_RETURN(fClient != nullptr,); CARLA_SAFE_ASSERT_RETURN(connSource != nullptr && connSource[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(connTarget != nullptr && connTarget[0] != '\0',); carla_debug("CarlaEngineJack::restorePatchbayConnection(%s, \"%s\", \"%s\")", bool2str(external), connSource, connTarget); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY && ! external) return CarlaEngine::restorePatchbayConnection(external, connSource, connTarget); if (const jack_port_t* const port = jackbridge_port_by_name(fClient, connSource)) { if (jackbridge_port_by_name(fClient, connTarget) == nullptr) return; if (! jackbridge_port_connected_to(port, connTarget)) jackbridge_connect(fClient, connSource, connTarget); } } #endif // ------------------------------------------------------------------- protected: void handleJackBufferSizeCallback(const uint32_t newBufferSize) { if (pData->bufferSize == newBufferSize) return; #ifndef BUILD_BRIDGE const CarlaMutexLocker cml(fPatchbayProcThreadProtectionMutex); #endif pData->bufferSize = newBufferSize; bufferSizeChanged(newBufferSize); } void handleJackSampleRateCallback(const double newSampleRate) { if (carla_isEqual(pData->sampleRate, newSampleRate)) return; #ifndef BUILD_BRIDGE const CarlaMutexLocker cml(fPatchbayProcThreadProtectionMutex); #endif pData->sampleRate = newSampleRate; sampleRateChanged(newSampleRate); } void handleJackFreewheelCallback(const bool isFreewheel) { if (fFreewheel == isFreewheel) return; #ifndef BUILD_BRIDGE const CarlaMutexLocker cml(fPatchbayProcThreadProtectionMutex); #endif fFreewheel = isFreewheel; offlineModeChanged(isFreewheel); } void handleJackProcessCallback(const uint32_t nframes) { const PendingRtEventsRunner prt(this, nframes); CARLA_SAFE_ASSERT_INT2_RETURN(nframes == pData->bufferSize, nframes, pData->bufferSize,); #ifdef BUILD_BRIDGE CarlaPlugin* const plugin(pData->plugins[0].plugin); if (plugin != nullptr && plugin->isEnabled() && plugin->tryLock(fFreewheel)) { plugin->initBuffers(); processPlugin(plugin, nframes); plugin->unlock(); } #else if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_JACK && !fTimebaseMaster) { jack_position_t jpos; // invalidate jpos.unique_1 = 1; jpos.unique_2 = 2; EngineTimeInfo timeInfo; const bool playing = jackbridge_transport_query(fClient, &jpos) == JackTransportRolling; if (jpos.unique_1 != jpos.unique_2) { timeInfo.playing = false; timeInfo.frame = 0; timeInfo.usecs = 0; timeInfo.bbt.valid = false; } else { timeInfo.playing = playing; timeInfo.frame = jpos.frame; timeInfo.usecs = jpos.usecs; if (jpos.valid & JackPositionBBT) { timeInfo.bbt.valid = true; timeInfo.bbt.bar = jpos.bar; timeInfo.bbt.beat = jpos.beat; timeInfo.bbt.tick = jpos.tick; timeInfo.bbt.barStartTick = jpos.bar_start_tick; timeInfo.bbt.beatsPerBar = jpos.beats_per_bar; timeInfo.bbt.beatType = jpos.beat_type; timeInfo.bbt.ticksPerBeat = jpos.ticks_per_beat; timeInfo.bbt.beatsPerMinute = jpos.beats_per_minute; } else { timeInfo.bbt.valid = false; } } pData->timeInfo = timeInfo; } if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { if (pData->aboutToClose) { if (float* const audioOut1 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioOut1], nframes)) carla_zeroFloats(audioOut1, nframes); if (float* const audioOut2 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioOut2], nframes)) carla_zeroFloats(audioOut2, nframes); } else if (pData->curPluginCount == 0) { float* const audioIn1 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn1], nframes); float* const audioIn2 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn2], nframes); float* const audioOut1 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioOut1], nframes); float* const audioOut2 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioOut2], nframes); // assert buffers CARLA_SAFE_ASSERT_RETURN(audioIn1 != nullptr,); CARLA_SAFE_ASSERT_RETURN(audioIn2 != nullptr,); CARLA_SAFE_ASSERT_RETURN(audioOut1 != nullptr,); CARLA_SAFE_ASSERT_RETURN(audioOut2 != nullptr,); // pass-through carla_copyFloats(audioOut1, audioIn1, nframes); carla_copyFloats(audioOut2, audioIn2, nframes); // TODO pass-through MIDI as well if (void* const eventOut = jackbridge_port_get_buffer(fRackPorts[kRackPortEventOut], nframes)) jackbridge_midi_clear_buffer(eventOut); return; } } if (pData->options.processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin != nullptr && plugin->isEnabled() && plugin->tryLock(fFreewheel)) { plugin->initBuffers(); processPlugin(plugin, nframes); plugin->unlock(); } } } else if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { CARLA_SAFE_ASSERT_RETURN(pData->events.in != nullptr,); CARLA_SAFE_ASSERT_RETURN(pData->events.out != nullptr,); // get buffers from jack float* const audioIn1 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn1], nframes); float* const audioIn2 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn2], nframes); float* const audioOut1 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioOut1], nframes); float* const audioOut2 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioOut2], nframes); void* const eventIn = jackbridge_port_get_buffer(fRackPorts[kRackPortEventIn], nframes); void* const eventOut = jackbridge_port_get_buffer(fRackPorts[kRackPortEventOut], nframes); // assert buffers CARLA_SAFE_ASSERT_RETURN(audioIn1 != nullptr,); CARLA_SAFE_ASSERT_RETURN(audioIn2 != nullptr,); CARLA_SAFE_ASSERT_RETURN(audioOut1 != nullptr,); CARLA_SAFE_ASSERT_RETURN(audioOut2 != nullptr,); // create audio buffers const float* inBuf[2] = { audioIn1, audioIn2 }; /**/ float* outBuf[2] = { audioOut1, audioOut2 }; // initialize events carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount); carla_zeroStructs(pData->events.out, kMaxEngineEventInternalCount); if (eventIn != nullptr) { ushort engineEventIndex = 0; jack_midi_event_t jackEvent; const uint32_t jackEventCount(jackbridge_midi_get_event_count(eventIn)); for (uint32_t jackEventIndex=0; jackEventIndex < jackEventCount; ++jackEventIndex) { if (! jackbridge_midi_event_get(&jackEvent, eventIn, jackEventIndex)) continue; CARLA_SAFE_ASSERT_CONTINUE(jackEvent.size < 0xFF /* uint8_t max */); EngineEvent& engineEvent(pData->events.in[engineEventIndex++]); engineEvent.time = jackEvent.time; engineEvent.fillFromMidiData(static_cast(jackEvent.size), jackEvent.buffer, 0); if (engineEventIndex >= kMaxEngineEventInternalCount) break; } } if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { pData->graph.processRack(pData, inBuf, outBuf, nframes); } else { const CarlaMutexLocker cml(fPatchbayProcThreadProtectionMutex); pData->graph.process(pData, inBuf, outBuf, nframes); } // output control if (eventOut != nullptr) { jackbridge_midi_clear_buffer(eventOut); uint8_t size = 0; uint8_t mdata[3] = { 0, 0, 0 }; uint8_t mdataTmp[EngineMidiEvent::kDataSize]; const uint8_t* mdataPtr; for (ushort i=0; i < kMaxEngineEventInternalCount; ++i) { const EngineEvent& engineEvent(pData->events.out[i]); /**/ if (engineEvent.type == kEngineEventTypeNull) { break; } else if (engineEvent.type == kEngineEventTypeControl) { const EngineControlEvent& ctrlEvent(engineEvent.ctrl); size = ctrlEvent.convertToMidiData(engineEvent.channel, mdata); mdataPtr = mdata; } else if (engineEvent.type == kEngineEventTypeMidi) { const EngineMidiEvent& midiEvent(engineEvent.midi); size = midiEvent.size; CARLA_SAFE_ASSERT_CONTINUE(size > 0); if (size > EngineMidiEvent::kDataSize) { CARLA_SAFE_ASSERT_CONTINUE(midiEvent.dataExt != nullptr); mdataPtr = midiEvent.dataExt; } else { // set first byte mdataTmp[0] = static_cast(midiEvent.data[0] | (engineEvent.channel & MIDI_CHANNEL_BIT)); // copy rest carla_copy(mdataTmp+1, midiEvent.data+1, size-1U); // done mdataPtr = mdataTmp; } } else { continue; } if (size > 0) jackbridge_midi_event_write(eventOut, engineEvent.time, mdataPtr, size); } } } if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_JACK) { if (fTimebaseMaster) { const bool playing = jackbridge_transport_query(fClient, nullptr) == JackTransportRolling; if (fTimebaseRolling != playing) { fTimebaseRolling = playing; pData->timeInfo.playing = playing; } // Check if we are no longer timebase master if (playing && fTimebaseUsecs != 0 && fTimebaseUsecs == pData->timeInfo.usecs) { carla_debug("No longer timerbase master"); fTimebaseMaster = false; } } fTimebaseUsecs = pData->timeInfo.usecs; } #endif // ! BUILD_BRIDGE } void handleJackLatencyCallback(const jack_latency_callback_mode_t /*mode*/) { // TODO } #ifndef BUILD_BRIDGE void handleJackTimebaseCallback(jack_nframes_t nframes, jack_position_t* const pos, const int new_pos) { if (new_pos) pData->time.setNeedsReset(); pData->timeInfo.playing = fTimebaseRolling; pData->timeInfo.frame = pos->frame; pData->timeInfo.usecs = pos->usecs; pData->time.fillJackTimeInfo(pos, nframes); } void handleJackClientUnregistrationCallback(const char* const name) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); // ignore this if on internal patchbay mode #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (! (fExternalPatchbayHost || (fExternalPatchbayOsc && pData->osc.isControlRegisteredForTCP()))) return; #else if (! fExternalPatchbayHost) return; #endif const uint groupId(fUsedGroups.getGroupId(name)); // clients might have been registered without ports if (groupId == 0) return; GroupNameToId groupNameToId; groupNameToId.setData(groupId, name); callback(fExternalPatchbayHost, fExternalPatchbayOsc, ENGINE_CALLBACK_PATCHBAY_CLIENT_REMOVED, groupNameToId.group, 0, 0, 0, 0.0f, nullptr); fUsedGroups.list.removeOne(groupNameToId); } void handleJackPortRegistrationCallback(const char* const portName, const char* const shortPortName, const CarlaJackPortHints& jackPortHints) { // ignore this if on internal patchbay mode #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (! (fExternalPatchbayHost || (fExternalPatchbayOsc && pData->osc.isControlRegisteredForTCP()))) return; #else if (! fExternalPatchbayHost) return; #endif bool found; CarlaString groupName(portName); groupName.truncate(groupName.rfind(shortPortName, &found)-1); CARLA_SAFE_ASSERT_RETURN(found,); uint groupId(fUsedGroups.getGroupId(groupName)); if (groupId == 0) { groupId = ++fUsedGroups.lastId; GroupNameToId groupNameToId; groupNameToId.setData(groupId, groupName); int pluginId = -1; PatchbayIcon icon = jackPortHints.isHardware ? PATCHBAY_ICON_HARDWARE : PATCHBAY_ICON_APPLICATION; findPluginIdAndIcon(groupName, pluginId, icon); callback(fExternalPatchbayHost, fExternalPatchbayOsc, ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupNameToId.group, icon, pluginId, 0, 0.0f, groupNameToId.name); fUsedGroups.list.append(groupNameToId); } addPatchbayJackPort(fExternalPatchbayHost, fExternalPatchbayOsc, groupId, jackPortHints, shortPortName, portName); } void handleJackPortUnregistrationCallback(const char* const portName) { // ignore this if on internal patchbay mode #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (! (fExternalPatchbayHost || (fExternalPatchbayOsc && pData->osc.isControlRegisteredForTCP()))) return; #else if (! fExternalPatchbayHost) return; #endif const PortNameToId& portNameToId(fUsedPorts.getPortNameToId(portName)); /* NOTE: Due to JACK2 async behaviour the port we get here might be the same of a previous rename-plugin request. See the comment on CarlaEngineJack::renamePlugin() for more information. */ if (portNameToId.group <= 0 || portNameToId.port <= 0) return; callback(fExternalPatchbayHost, fExternalPatchbayOsc, ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, portNameToId.group, static_cast(portNameToId.port), 0, 0, 0.0f, nullptr); fUsedPorts.list.removeOne(portNameToId); } void handleJackPortConnectCallback(const char* const portNameA, const char* const portNameB) { // ignore this if on internal patchbay mode #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (! (fExternalPatchbayHost || (fExternalPatchbayOsc && pData->osc.isControlRegisteredForTCP()))) return; #else if (! fExternalPatchbayHost) return; #endif const PortNameToId& portNameToIdA(fUsedPorts.getPortNameToId(portNameA)); const PortNameToId& portNameToIdB(fUsedPorts.getPortNameToId(portNameB)); /* NOTE: Due to JACK2 async behaviour the port we get here might be the same of a previous rename-plugin request. See the comment on CarlaEngineJack::renamePlugin() for more information. */ if (portNameToIdA.group <= 0 || portNameToIdA.port <= 0) return; if (portNameToIdB.group <= 0 || portNameToIdB.port <= 0) return; char strBuf[STR_MAX+1]; std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", portNameToIdA.group, portNameToIdA.port, portNameToIdB.group, portNameToIdB.port); strBuf[STR_MAX] = '\0'; ConnectionToId connectionToId; connectionToId.setData(++fUsedConnections.lastId, portNameToIdA.group, portNameToIdA.port, portNameToIdB.group, portNameToIdB.port); callback(fExternalPatchbayHost, fExternalPatchbayOsc, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); fUsedConnections.list.append(connectionToId); } void handleJackPortDisconnectCallback(const char* const portNameA, const char* const portNameB) { // ignore this if on internal patchbay mode #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (! (fExternalPatchbayHost || (fExternalPatchbayOsc && pData->osc.isControlRegisteredForTCP()))) return; #else if (! fExternalPatchbayHost) return; #endif const PortNameToId& portNameToIdA(fUsedPorts.getPortNameToId(portNameA)); const PortNameToId& portNameToIdB(fUsedPorts.getPortNameToId(portNameB)); /* NOTE: Due to JACK2 async behaviour the port we get here might be the same of a previous rename-plugin request. See the comment on CarlaEngineJack::renamePlugin() for more information. */ if (portNameToIdA.group <= 0 || portNameToIdA.port <= 0) return; if (portNameToIdB.group <= 0 || portNameToIdB.port <= 0) return; ConnectionToId connectionToId = { 0, 0, 0, 0, 0 }; bool found = false; { const CarlaMutexLocker cml(fUsedConnections.mutex); for (LinkedList::Itenerator it = fUsedConnections.list.begin2(); it.valid(); it.next()) { connectionToId = it.getValue(connectionToId); CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0); if (connectionToId.groupA == portNameToIdA.group && connectionToId.portA == portNameToIdA.port && connectionToId.groupB == portNameToIdB.group && connectionToId.portB == portNameToIdB.port) { found = true; fUsedConnections.list.remove(it); break; } } } if (found) { callback(fExternalPatchbayHost, fExternalPatchbayOsc, ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connectionToId.id, 0, 0, 0, 0.0f, nullptr); } } void handleJackPortRenameCallback(const char* const oldFullName, const char* const newFullName, const char* const newShortName) { // ignore this if on internal patchbay mode #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (! (fExternalPatchbayHost || (fExternalPatchbayOsc && pData->osc.isControlRegisteredForTCP()))) return; #else if (! fExternalPatchbayHost) return; #endif CARLA_SAFE_ASSERT_RETURN(oldFullName != nullptr && oldFullName[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(newFullName != nullptr && newFullName[0] != '\0',); bool found; CarlaString groupName(newFullName); groupName.truncate(groupName.rfind(newShortName, &found)-1); CARLA_SAFE_ASSERT_RETURN(found,); const uint groupId(fUsedGroups.getGroupId(groupName)); CARLA_SAFE_ASSERT_RETURN(groupId > 0,); for (LinkedList::Itenerator it = fUsedPorts.list.begin2(); it.valid(); it.next()) { static PortNameToId portNameFallback = { 0, 0, { '\0' }, { '\0' } }; PortNameToId& portNameToId(it.getValue(portNameFallback)); CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group != 0); if (std::strncmp(portNameToId.fullName, oldFullName, STR_MAX) == 0) { CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group == groupId); portNameToId.rename(newShortName, newFullName); callback(fExternalPatchbayHost, fExternalPatchbayOsc, ENGINE_CALLBACK_PATCHBAY_PORT_CHANGED, portNameToId.group, static_cast(portNameToId.port), 0, 0, 0.0f, portNameToId.name); break; } } } #endif void handleJackShutdownCallback() { #ifndef BUILD_BRIDGE signalThreadShouldExit(); #endif const PendingRtEventsRunner prt(this, pData->bufferSize); for (uint i=0; i < pData->curPluginCount; ++i) { if (CarlaPlugin* const plugin = pData->plugins[i].plugin) { plugin->tryLock(true); if (CarlaEngineJackClient* const client = (CarlaEngineJackClient*)plugin->getEngineClient()) client->invalidate(); plugin->unlock(); } } fClient = nullptr; #ifndef BUILD_BRIDGE carla_zeroPointers(fRackPorts, kRackPortCount); #endif callback(true, true, ENGINE_CALLBACK_QUIT, 0, 0, 0, 0, 0.0f, nullptr); } // ------------------------------------------------------------------- void handlePluginJackShutdownCallback(CarlaPlugin* const plugin) { CarlaEngineJackClient* const engineClient((CarlaEngineJackClient*)plugin->getEngineClient()); CARLA_SAFE_ASSERT_RETURN(engineClient != nullptr,); plugin->tryLock(true); engineClient->invalidate(); plugin->unlock(); //if (pData->nextAction.pluginId == plugin->getId()) // pData->nextAction.clearAndReset(); callback(true, true, ENGINE_CALLBACK_PLUGIN_UNAVAILABLE, plugin->getId(), 0, 0, 0, 0.0f, "Killed by JACK"); } // ------------------------------------------------------------------- private: jack_client_t* fClient; bool fExternalPatchbayHost; bool fExternalPatchbayOsc; bool fFreewheel; CarlaString fClientName; // ------------------------------------------------------------------- #ifdef BUILD_BRIDGE bool fIsRunning; #else enum RackPorts { kRackPortAudioIn1 = 0, kRackPortAudioIn2 = 1, kRackPortAudioOut1 = 2, kRackPortAudioOut2 = 3, kRackPortEventIn = 4, kRackPortEventOut = 5, kRackPortCount = 6 }; jack_port_t* fRackPorts[kRackPortCount]; bool fTimebaseMaster; bool fTimebaseRolling; uint64_t fTimebaseUsecs; PatchbayGroupList fUsedGroups; PatchbayPortList fUsedPorts; PatchbayConnectionList fUsedConnections; CarlaMutex fPatchbayProcThreadProtectionMutex; mutable CharStringListPtr fRetConns; void findPluginIdAndIcon(const char* const clientName, int& pluginId, PatchbayIcon& icon) const noexcept { carla_debug("CarlaEngineJack::findPluginIdAndIcon(\"%s\", ...)", clientName); // TODO - this currently only works in multi-client mode if (pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS) return; const char* const uuidstr = jackbridge_get_uuid_for_client_name(fClient, clientName); CARLA_SAFE_ASSERT_RETURN(uuidstr != nullptr && uuidstr[0] != '\0',); jack_uuid_t uuid; CARLA_SAFE_ASSERT_RETURN(jackbridge_uuid_parse(uuidstr, &uuid),); bool clientBelongsToUs; { char* value = nullptr; char* type = nullptr; if (! jackbridge_get_property(uuid, URI_MAIN_CLIENT_NAME, &value, &type)) return; CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr && value[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(std::strcmp(type, URI_TYPE_STRING) == 0,); clientBelongsToUs = fClientName == value; } { char* value = nullptr; char* type = nullptr; if (! jackbridge_get_property(uuid, URI_PLUGIN_ID, &value, &type)) return; CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr && value[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(std::strcmp(type, URI_TYPE_INTEGER) == 0,); if (clientBelongsToUs) pluginId = std::atoi(value); icon = PATCHBAY_ICON_PLUGIN; } { char* value = nullptr; char* type = nullptr; if (! jackbridge_get_property(uuid, URI_PLUGIN_ICON, &value, &type)) return; CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr && value[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(std::strcmp(type, URI_TYPE_STRING) == 0,); /**/ if (std::strcmp(value, "app") == 0) icon = PATCHBAY_ICON_APPLICATION; else if (std::strcmp(value, "application") == 0) icon = PATCHBAY_ICON_APPLICATION; else if (std::strcmp(value, "plugin") == 0) icon = PATCHBAY_ICON_PLUGIN; else if (std::strcmp(value, "hardware") == 0) icon = PATCHBAY_ICON_HARDWARE; else if (std::strcmp(value, "carla") == 0) icon = PATCHBAY_ICON_CARLA; else if (std::strcmp(value, "distrho") == 0) icon = PATCHBAY_ICON_DISTRHO; else if (std::strcmp(value, "file") == 0) icon = PATCHBAY_ICON_FILE; } } void initJackPatchbay(const bool sendHost, const bool sendOSC, const char* const ourName) { CARLA_SAFE_ASSERT_RETURN(pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY || (fExternalPatchbayHost && sendHost) || (fExternalPatchbayOsc && sendOSC),); CARLA_SAFE_ASSERT_RETURN(ourName != nullptr && ourName[0] != '\0',); CarlaStringList parsedGroups; // add our client first { parsedGroups.append(ourName); GroupNameToId groupNameToId; groupNameToId.setData(++fUsedGroups.lastId, ourName); callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupNameToId.group, PATCHBAY_ICON_CARLA, MAIN_CARLA_PLUGIN_ID, 0, 0.0f, groupNameToId.name); fUsedGroups.list.append(groupNameToId); } // query all jack ports { const char** const ports = jackbridge_get_ports(fClient, nullptr, nullptr, 0); CARLA_SAFE_ASSERT_RETURN(ports != nullptr,); for (int i=0; ports[i] != nullptr; ++i) { const char* const fullPortName(ports[i]); CARLA_SAFE_ASSERT_CONTINUE(fullPortName != nullptr && fullPortName[0] != '\0'); const jack_port_t* const jackPort(jackbridge_port_by_name(fClient, fullPortName)); CARLA_SAFE_ASSERT_CONTINUE(jackPort != nullptr); const char* const shortPortName(jackbridge_port_short_name(jackPort)); CARLA_SAFE_ASSERT_CONTINUE(shortPortName != nullptr && shortPortName[0] != '\0'); const CarlaJackPortHints jackPortHints(CarlaJackPortHints::fromPort(jackPort)); uint groupId = 0; bool found; CarlaString groupName(fullPortName); groupName.truncate(groupName.rfind(shortPortName, &found)-1); CARLA_SAFE_ASSERT_CONTINUE(found); if (parsedGroups.contains(groupName)) { groupId = fUsedGroups.getGroupId(groupName); CARLA_SAFE_ASSERT_CONTINUE(groupId > 0); } else { groupId = ++fUsedGroups.lastId; parsedGroups.append(groupName); GroupNameToId groupNameToId; groupNameToId.setData(groupId, groupName); int pluginId = -1; PatchbayIcon icon = jackPortHints.isHardware ? PATCHBAY_ICON_HARDWARE : PATCHBAY_ICON_APPLICATION; findPluginIdAndIcon(groupName, pluginId, icon); callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupNameToId.group, icon, pluginId, 0, 0.0f, groupNameToId.name); fUsedGroups.list.append(groupNameToId); } addPatchbayJackPort(sendHost, sendOSC, groupId, jackPortHints, shortPortName, fullPortName); } jackbridge_free(ports); } // query connections, after all ports are in place if (const char** const ports = jackbridge_get_ports(fClient, nullptr, nullptr, JackPortIsOutput)) { char strBuf[STR_MAX+1]; for (int i=0; ports[i] != nullptr; ++i) { const char* const fullPortName(ports[i]); CARLA_SAFE_ASSERT_CONTINUE(fullPortName != nullptr && fullPortName[0] != '\0'); const jack_port_t* const jackPort(jackbridge_port_by_name(fClient, fullPortName)); CARLA_SAFE_ASSERT_CONTINUE(jackPort != nullptr); const PortNameToId& thisPort(fUsedPorts.getPortNameToId(fullPortName)); CARLA_SAFE_ASSERT_CONTINUE(thisPort.group > 0); CARLA_SAFE_ASSERT_CONTINUE(thisPort.port > 0); if (const char** const connections = jackbridge_port_get_all_connections(fClient, jackPort)) { for (int j=0; connections[j] != nullptr; ++j) { const char* const connection(connections[j]); CARLA_SAFE_ASSERT_CONTINUE(connection != nullptr && connection[0] != '\0'); const PortNameToId& targetPort(fUsedPorts.getPortNameToId(connection)); CARLA_SAFE_ASSERT_CONTINUE(targetPort.group > 0); CARLA_SAFE_ASSERT_CONTINUE(targetPort.port > 0); std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", thisPort.group, thisPort.port, targetPort.group, targetPort.port); strBuf[STR_MAX] = '\0'; ConnectionToId connectionToId; connectionToId.setData(++fUsedConnections.lastId, thisPort.group, thisPort.port, targetPort.group, targetPort.port); callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); fUsedConnections.list.append(connectionToId); } jackbridge_free(connections); } } jackbridge_free(ports); } } void addPatchbayJackPort(const bool sendHost, const bool sendOSC, const uint groupId, const CarlaJackPortHints& jackPortHints, const char* const shortPortName, const char* const fullPortName) { uint canvasPortFlags = 0x0; canvasPortFlags |= jackPortHints.isInput ? PATCHBAY_PORT_IS_INPUT : 0x0; /**/ if (jackPortHints.isCV) canvasPortFlags |= PATCHBAY_PORT_TYPE_CV; else if (jackPortHints.isOSC) canvasPortFlags |= PATCHBAY_PORT_TYPE_OSC; else if (jackPortHints.isAudio) canvasPortFlags |= PATCHBAY_PORT_TYPE_AUDIO; else if (jackPortHints.isMIDI) canvasPortFlags |= PATCHBAY_PORT_TYPE_MIDI; PortNameToId portNameToId; portNameToId.setData(groupId, ++fUsedPorts.lastId, shortPortName, fullPortName); callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, portNameToId.group, static_cast(portNameToId.port), static_cast(canvasPortFlags), 0, 0.0f, portNameToId.name); fUsedPorts.list.append(portNameToId); } #endif // ------------------------------------------------------------------- void processPlugin(CarlaPlugin* const plugin, const uint32_t nframes) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaEngineJackClient* const client = (CarlaEngineJackClient*)plugin->getEngineClient(); CarlaEngineJackCVSourcePorts& cvSourcePorts(client->getCVSourcePorts()); const CarlaRecursiveMutexTryLocker crmtl(cvSourcePorts.getMutex(), fFreewheel); // const CarlaRecursiveMutexLocker crml(cvSourcePorts.getMutex()); #endif /* const uint32_t audioInCount = client->getPortCount(kEnginePortTypeAudio, true); const uint32_t audioOutCount = client->getPortCount(kEnginePortTypeAudio, false); const uint32_t cvInCount = client->getPortCount(kEnginePortTypeCV, true); const uint32_t cvOutCount = client->getPortCount(kEnginePortTypeCV, false); */ const uint32_t audioInCount = plugin->getAudioInCount(); const uint32_t audioOutCount = plugin->getAudioOutCount(); const uint32_t cvInCount = plugin->getCVInCount(); const uint32_t cvOutCount = plugin->getCVOutCount(); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH const uint32_t cvsInCount = crmtl.wasLocked() ? cvSourcePorts.getPortCount() : 0; #else const uint32_t cvsInCount = 0; #endif const float* audioIn[audioInCount]; /* */ float* audioOut[audioOutCount]; const float* cvIn[cvInCount+cvsInCount]; /* */ float* cvOut[cvOutCount]; for (uint32_t i=0; i < audioInCount; ++i) { if (CarlaEngineAudioPort* const port = plugin->getAudioInPort(i)) audioIn[i] = port->getBuffer(); else audioIn[i] = nullptr; } for (uint32_t i=0; i < audioOutCount; ++i) { if (CarlaEngineAudioPort* const port = plugin->getAudioOutPort(i)) audioOut[i] = port->getBuffer(); else audioOut[i] = nullptr; } for (uint32_t i=0; i < cvInCount; ++i) { if (CarlaEngineCVPort* const port = plugin->getCVInPort(i)) cvIn[i] = port->getBuffer(); else cvIn[i] = nullptr; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH for (uint32_t i=cvInCount, j=0; j < cvsInCount; ++i, ++j) { if (CarlaEngineCVPort* const port = cvSourcePorts.getPort(j)) { port->initBuffer(); cvIn[i] = port->getBuffer(); } else { cvIn[i] = nullptr; } } #endif for (uint32_t i=0; i < cvOutCount; ++i) { if (CarlaEngineCVPort* const port = plugin->getCVOutPort(i)) cvOut[i] = port->getBuffer(); else cvOut[i] = nullptr; } float inPeaks[2] = { 0.0f }; float outPeaks[2] = { 0.0f }; for (uint32_t i=0; i < audioInCount && i < 2; ++i) { for (uint32_t j=0; j < nframes; ++j) { const float absV(std::abs(audioIn[i][j])); if (absV > inPeaks[i]) inPeaks[i] = absV; } } plugin->process(audioIn, audioOut, cvIn, cvOut, nframes); for (uint32_t i=0; i < audioOutCount && i < 2; ++i) { for (uint32_t j=0; j < nframes; ++j) { const float absV(std::abs(audioOut[i][j])); if (absV > outPeaks[i]) outPeaks[i] = absV; } } setPluginPeaksRT(plugin->getId(), inPeaks, outPeaks); } #ifndef BUILD_BRIDGE // ------------------------------------------------------------------- struct PostPonedJackEvent { enum Type { kTypeNull = 0, kTypeClientUnregister, kTypePortRegister, kTypePortUnregister, kTypePortConnect, kTypePortDisconnect, kTypePortRename }; Type type; union { struct { char name[STR_MAX+1]; } clientUnregister; struct { char shortName[STR_MAX+1]; char fullName[STR_MAX+1]; CarlaJackPortHints hints; } portRegister; struct { char fullName[STR_MAX+1]; } portUnregister; struct { char oldFullName[STR_MAX+1]; char newFullName[STR_MAX+1]; char newShortName[STR_MAX+1]; } portRename; struct { char portNameA[STR_MAX+1]; char portNameB[STR_MAX+1]; } portConnect; struct { char portNameA[STR_MAX+1]; char portNameB[STR_MAX+1]; } portDisconnect; }; }; LinkedList fPostPonedEvents; CarlaMutex fPostPonedEventsMutex; bool fIsInternalClient; void postPoneJackCallback(PostPonedJackEvent& ev) { const CarlaMutexLocker cml(fPostPonedEventsMutex); fPostPonedEvents.append(ev); } void run() override { LinkedList events; PostPonedJackEvent nullEvent; carla_zeroStruct(nullEvent); for (; ! shouldThreadExit();) { if (fIsInternalClient) idle(); { const CarlaMutexLocker cml(fPostPonedEventsMutex); if (fPostPonedEvents.count() > 0) fPostPonedEvents.moveTo(events); } if (fClient == nullptr) break; if (events.count() == 0) { carla_msleep(fIsInternalClient ? 50 : 200); continue; } for (LinkedList::Itenerator it = events.begin2(); it.valid(); it.next()) { const PostPonedJackEvent& ev(it.getValue(nullEvent)); CARLA_SAFE_ASSERT_CONTINUE(ev.type != PostPonedJackEvent::kTypeNull); switch (ev.type) { case PostPonedJackEvent::kTypeNull: break; case PostPonedJackEvent::kTypeClientUnregister: handleJackClientUnregistrationCallback(ev.clientUnregister.name); break; case PostPonedJackEvent::kTypePortRegister: handleJackPortRegistrationCallback(ev.portRegister.fullName, ev.portRegister.shortName, ev.portRegister.hints); break; case PostPonedJackEvent::kTypePortUnregister: handleJackPortUnregistrationCallback(ev.portUnregister.fullName); break; case PostPonedJackEvent::kTypePortConnect: handleJackPortConnectCallback(ev.portConnect.portNameA, ev.portConnect.portNameB); break; case PostPonedJackEvent::kTypePortDisconnect: handleJackPortDisconnectCallback(ev.portDisconnect.portNameA, ev.portDisconnect.portNameB); break; case PostPonedJackEvent::kTypePortRename: handleJackPortRenameCallback(ev.portRename.oldFullName, ev.portRename.newFullName, ev.portRename.newShortName); break; } } events.clear(); } events.clear(); } #endif // BUILD_BRIDGE // ------------------------------------------------------------------- // disable -Wattributes warnings #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wattributes" #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wattributes" #endif #define handlePtr ((CarlaEngineJack*)arg) static void JACKBRIDGE_API carla_jack_thread_init_callback(void*) { #ifdef __SSE2_MATH__ // Set FTZ and DAZ flags _mm_setcsr(_mm_getcsr() | 0x8040); #endif } static int JACKBRIDGE_API carla_jack_bufsize_callback(jack_nframes_t newBufferSize, void* arg) { handlePtr->handleJackBufferSizeCallback(newBufferSize); return 0; } static int JACKBRIDGE_API carla_jack_srate_callback(jack_nframes_t newSampleRate, void* arg) { handlePtr->handleJackSampleRateCallback(newSampleRate); return 0; } static void JACKBRIDGE_API carla_jack_freewheel_callback(int starting, void* arg) { handlePtr->handleJackFreewheelCallback(bool(starting)); } static void JACKBRIDGE_API carla_jack_latency_callback(jack_latency_callback_mode_t mode, void* arg) { handlePtr->handleJackLatencyCallback(mode); } static int JACKBRIDGE_API carla_jack_process_callback(jack_nframes_t nframes, void* arg) __attribute__((annotate("realtime"))) { handlePtr->handleJackProcessCallback(nframes); return 0; } #ifndef BUILD_BRIDGE static void JACKBRIDGE_API carla_jack_timebase_callback(jack_transport_state_t, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg) __attribute__((annotate("realtime"))) { handlePtr->handleJackTimebaseCallback(nframes, pos, new_pos); } static void JACKBRIDGE_API carla_jack_client_registration_callback(const char* name, int reg, void* arg) { // ignored if (reg != 0) return; PostPonedJackEvent ev; carla_zeroStruct(ev); ev.type = PostPonedJackEvent::kTypeClientUnregister; std::strncpy(ev.clientUnregister.name, name, STR_MAX); handlePtr->postPoneJackCallback(ev); } static void JACKBRIDGE_API carla_jack_port_registration_callback(jack_port_id_t port_id, int reg, void* arg) { const jack_port_t* const port = jackbridge_port_by_id(handlePtr->fClient, port_id); CARLA_SAFE_ASSERT_RETURN(port != nullptr,); const char* const fullName = jackbridge_port_name(port); CARLA_SAFE_ASSERT_RETURN(fullName != nullptr && fullName[0] != '\0',); PostPonedJackEvent ev; carla_zeroStruct(ev); if (reg != 0) { const char* const shortName = jackbridge_port_short_name(port); CARLA_SAFE_ASSERT_RETURN(shortName != nullptr && shortName[0] != '\0',); ev.type = PostPonedJackEvent::kTypePortRegister; std::strncpy(ev.portRegister.fullName, fullName, STR_MAX); std::strncpy(ev.portRegister.shortName, shortName, STR_MAX); ev.portRegister.hints = CarlaJackPortHints::fromPort(port); } else { ev.type = PostPonedJackEvent::kTypePortUnregister; std::strncpy(ev.portUnregister.fullName, fullName, STR_MAX); } handlePtr->postPoneJackCallback(ev); } static void JACKBRIDGE_API carla_jack_port_connect_callback(jack_port_id_t a, jack_port_id_t b, int connect, void* arg) { const jack_port_t* const portA = jackbridge_port_by_id(handlePtr->fClient, a); CARLA_SAFE_ASSERT_RETURN(portA != nullptr,); const jack_port_t* const portB = jackbridge_port_by_id(handlePtr->fClient, b); CARLA_SAFE_ASSERT_RETURN(portB != nullptr,); const char* const fullNameA = jackbridge_port_name(portA); CARLA_SAFE_ASSERT_RETURN(fullNameA != nullptr && fullNameA[0] != '\0',); const char* const fullNameB = jackbridge_port_name(portB); CARLA_SAFE_ASSERT_RETURN(fullNameB != nullptr && fullNameB[0] != '\0',); PostPonedJackEvent ev; carla_zeroStruct(ev); if (connect != 0) { ev.type = PostPonedJackEvent::kTypePortConnect; std::strncpy(ev.portConnect.portNameA, fullNameA, STR_MAX); std::strncpy(ev.portConnect.portNameB, fullNameB, STR_MAX); } else { ev.type = PostPonedJackEvent::kTypePortDisconnect; std::strncpy(ev.portDisconnect.portNameA, fullNameA, STR_MAX); std::strncpy(ev.portDisconnect.portNameB, fullNameB, STR_MAX); } handlePtr->postPoneJackCallback(ev); } static void JACKBRIDGE_API carla_jack_port_rename_callback(jack_port_id_t port_id, const char* oldName, const char* newName, void* arg) { const jack_port_t* const port = jackbridge_port_by_id(handlePtr->fClient, port_id); CARLA_SAFE_ASSERT_RETURN(port != nullptr,); const char* const shortName = jackbridge_port_short_name(port); CARLA_SAFE_ASSERT_RETURN(shortName != nullptr && shortName[0] != '\0',); PostPonedJackEvent ev; carla_zeroStruct(ev); ev.type = PostPonedJackEvent::kTypePortRename; std::strncpy(ev.portRename.oldFullName, oldName, STR_MAX); std::strncpy(ev.portRename.newFullName, newName, STR_MAX); std::strncpy(ev.portRename.newShortName, shortName, STR_MAX); handlePtr->postPoneJackCallback(ev); } static int JACKBRIDGE_API carla_jack_xrun_callback(void* arg) { ++(handlePtr->pData->xruns); return 0; } #endif static void JACKBRIDGE_API carla_jack_shutdown_callback(void* arg) { handlePtr->handleJackShutdownCallback(); } #undef handlePtr // ------------------------------------------------------------------- #ifndef BUILD_BRIDGE static int JACKBRIDGE_API carla_jack_process_callback_plugin(jack_nframes_t nframes, void* arg) __attribute__((annotate("realtime"))) { CarlaPlugin* const plugin((CarlaPlugin*)arg); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr && plugin->isEnabled(), 0); CarlaEngineJack* const engine((CarlaEngineJack*)plugin->getEngine()); CARLA_SAFE_ASSERT_RETURN(engine != nullptr, 0); if (plugin->tryLock(engine->fFreewheel)) { plugin->initBuffers(); engine->processPlugin(plugin, nframes); plugin->unlock(); } return 0; } /* static int JACKBRIDGE_API carla_jack_bufsize_callback_plugin(jack_nframes_t nframes, void* arg) { CarlaPlugin* const plugin((CarlaPlugin*)arg); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr && plugin->isEnabled(), 0); plugin->bufferSizeChanged(nframes); return 1; } static int JACKBRIDGE_API carla_jack_srate_callback_plugin(jack_nframes_t nframes, void* arg) { CarlaPlugin* const plugin((CarlaPlugin*)arg); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr && plugin->isEnabled(), 0); plugin->sampleRateChanged(nframes); return 1; } */ static void JACKBRIDGE_API carla_jack_latency_callback_plugin(jack_latency_callback_mode_t /*mode*/, void* /*arg*/) { // TODO } static void JACKBRIDGE_API carla_jack_shutdown_callback_plugin(void* arg) { CarlaPlugin* const plugin((CarlaPlugin*)arg); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); CarlaEngineJack* const engine((CarlaEngineJack*)plugin->getEngine()); CARLA_SAFE_ASSERT_RETURN(engine != nullptr,); engine->handlePluginJackShutdownCallback(plugin); } #endif // enable -Wattributes again #if defined(__clang__) # pragma clang diagnostic pop #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic pop #endif CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJack) }; // ----------------------------------------------------------------------- CarlaEngine* CarlaEngine::newJack() { carla_debug("CarlaEngine::newJack()"); return new CarlaEngineJack(); } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE #if defined(JACKBRIDGE_DIRECT) && !defined(BUILD_BRIDGE) // ----------------------------------------------------------------------- // internal jack client CARLA_EXPORT int jack_initialize (jack_client_t *client, const char *load_init); CARLA_EXPORT void jack_finish(void *arg); #ifdef CARLA_OS_UNIX # include "ThreadSafeFFTW.hpp" static ThreadSafeFFTW sThreadSafeFFTW; #endif // ----------------------------------------------------------------------- CARLA_EXPORT int jack_initialize(jack_client_t* const client, const char* const load_init) { CARLA_BACKEND_USE_NAMESPACE EngineProcessMode mode; if (load_init != nullptr && std::strcmp(load_init, "rack") == 0) mode = ENGINE_PROCESS_MODE_CONTINUOUS_RACK; else mode = ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS; #ifdef USING_JUCE juce::initialiseJuce_GUI(); #endif CarlaEngineJack* const engine = new CarlaEngineJack(); engine->setOption(ENGINE_OPTION_FORCE_STEREO, 1, nullptr); engine->setOption(ENGINE_OPTION_AUDIO_DRIVER, 0, "JACK"); engine->setOption(ENGINE_OPTION_AUDIO_DEVICE, 0, "Auto-Connect ON"); engine->setOption(ENGINE_OPTION_OSC_ENABLED, 1, nullptr); engine->setOption(ENGINE_OPTION_OSC_PORT_TCP, 22752, nullptr); engine->setOption(ENGINE_OPTION_OSC_PORT_UDP, 22752, nullptr); engine->setOption(ENGINE_OPTION_PROCESS_MODE, mode, nullptr); engine->setOption(ENGINE_OPTION_TRANSPORT_MODE, ENGINE_TRANSPORT_MODE_JACK, nullptr); // FIXME engine->setOption(ENGINE_OPTION_PATH_BINARIES, 0, "/usr/lib/carla"); engine->setOption(ENGINE_OPTION_PATH_RESOURCES, 0, "/usr/share/resources"); if (engine->initInternal(client)) { #ifdef CARLA_OS_UNIX sThreadSafeFFTW.init(); #endif return 0; } else { delete engine; #ifdef USING_JUCE juce::shutdownJuce_GUI(); #endif return 1; } } CARLA_EXPORT void jack_finish(void *arg) { CARLA_BACKEND_USE_NAMESPACE CarlaEngineJack* const engine = (CarlaEngineJack*)arg;; CARLA_SAFE_ASSERT_RETURN(engine != nullptr,); #ifdef CARLA_OS_UNIX const ThreadSafeFFTW::Deinitializer tsfftwde(sThreadSafeFFTW); #endif engine->setAboutToClose(); engine->removeAllPlugins(); engine->close(); delete engine; #ifdef USING_JUCE juce::shutdownJuce_GUI(); #endif } // ----------------------------------------------------------------------- #endif // defined(JACKBRIDGE_DIRECT) && !defined(BUILD_BRIDGE) Carla-2.1/source/backend/engine/CarlaEngineJuce.cpp000066400000000000000000001042241364475620200222310ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the GPL.txt file */ #include "CarlaEngineGraph.hpp" #include "CarlaEngineInternal.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaStringList.hpp" #include "RtLinkedList.hpp" #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wcast-qual" # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wdouble-promotion" # pragma GCC diagnostic ignored "-Weffc++" # pragma GCC diagnostic ignored "-Wfloat-equal" # pragma GCC diagnostic ignored "-Wsign-conversion" # pragma GCC diagnostic ignored "-Wundef" # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" # if __GNUC__ > 7 # pragma GCC diagnostic ignored "-Wclass-memaccess" # endif #endif #include "AppConfig.h" #include "juce_audio_devices/juce_audio_devices.h" #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic pop #endif CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- struct MidiInPort { juce::MidiInput* port; char name[STR_MAX+1]; }; struct MidiOutPort { juce::MidiOutput* port; char name[STR_MAX+1]; }; struct RtMidiEvent { uint64_t time; // needs to compare to internal time uint8_t size; uint8_t data[EngineMidiEvent::kDataSize]; }; // ------------------------------------------------------------------------------------------------------------------- // Fallback data static const MidiInPort kMidiInPortFallback = { nullptr, { '\0' } }; static /* */ MidiInPort kMidiInPortFallbackNC = { nullptr, { '\0' } }; static const MidiOutPort kMidiOutPortFallback = { nullptr, { '\0' } }; static /* */ MidiOutPort kMidiOutPortFallbackNC = { nullptr, { '\0' } }; static const RtMidiEvent kRtMidiEventFallback = { 0, 0, { 0 } }; // ------------------------------------------------------------------------------------------------------------------- // Global static data static CharStringListPtr gDeviceNames; static juce::OwnedArray gDeviceTypes; struct JuceCleanup : public juce::DeletedAtShutdown { JuceCleanup() noexcept {} ~JuceCleanup() { gDeviceTypes.clear(true); } }; // ------------------------------------------------------------------------------------------------------------------- // Cleanup struct AudioIODeviceTypeComparator { static int compareElements (const juce::AudioIODeviceType* d1, const juce::AudioIODeviceType* d2) noexcept { return d1->getTypeName().compareNatural (d2->getTypeName()); } }; static void initJuceDevicesIfNeeded() { static juce::AudioDeviceManager sDeviceManager; if (gDeviceTypes.size() != 0) return; sDeviceManager.createAudioDeviceTypes(gDeviceTypes); CARLA_SAFE_ASSERT_RETURN(gDeviceTypes.size() != 0,); new JuceCleanup(); // remove JACK from device list for (int i=0, count=gDeviceTypes.size(); i < count; ++i) { if (gDeviceTypes[i]->getTypeName() == "JACK") { gDeviceTypes.remove(i, true); break; } } AudioIODeviceTypeComparator comp; gDeviceTypes.sort(comp); } // ------------------------------------------------------------------------------------------------------------------- // Juce Engine class CarlaEngineJuce : public CarlaEngine, public juce::AudioIODeviceCallback, public juce::MidiInputCallback { public: CarlaEngineJuce(juce::AudioIODeviceType* const devType) : CarlaEngine(), juce::AudioIODeviceCallback(), fDevice(), fDeviceType(devType), fMidiIns(), fMidiInEvents(), fMidiOuts(), fMidiOutMutex() { carla_debug("CarlaEngineJuce::CarlaEngineJuce(%p)", devType); // just to make sure pData->options.transportMode = ENGINE_TRANSPORT_MODE_INTERNAL; } ~CarlaEngineJuce() override { carla_debug("CarlaEngineJuce::~CarlaEngineJuce()"); } // ------------------------------------- bool init(const char* const clientName) override { CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false); carla_debug("CarlaEngineJuce::init(\"%s\")", clientName); if (pData->options.processMode != ENGINE_PROCESS_MODE_CONTINUOUS_RACK && pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY) { setLastError("Invalid process mode"); return false; } juce::String deviceName; if (pData->options.audioDevice != nullptr && pData->options.audioDevice[0] != '\0') { deviceName = pData->options.audioDevice; } else { const int defaultIndex = fDeviceType->getDefaultDeviceIndex(false); juce::StringArray deviceNames(fDeviceType->getDeviceNames()); if (defaultIndex >= 0 && defaultIndex < deviceNames.size()) deviceName = deviceNames[defaultIndex]; } if (deviceName.isEmpty()) { setLastError("Audio device has not been selected yet and a default one is not available"); return false; } fDevice = fDeviceType->createDevice(deviceName, deviceName); if (fDevice == nullptr) { setLastError("Failed to create device"); return false; } juce::StringArray inputNames(fDevice->getInputChannelNames()); juce::StringArray outputNames(fDevice->getOutputChannelNames()); if (inputNames.size() < 0 || outputNames.size() <= 0) { setLastError("Selected device does not have any outputs"); return false; } juce::BigInteger inputChannels; inputChannels.setRange(0, inputNames.size(), true); juce::BigInteger outputChannels; outputChannels.setRange(0, outputNames.size(), true); juce::String error = fDevice->open(inputChannels, outputChannels, pData->options.audioSampleRate, static_cast(pData->options.audioBufferSize)); if (error.isNotEmpty()) { setLastError(error.toUTF8()); fDevice = nullptr; return false; } if (! pData->init(clientName)) { close(); setLastError("Failed to init internal data"); return false; } pData->bufferSize = static_cast(fDevice->getCurrentBufferSizeSamples()); pData->sampleRate = fDevice->getCurrentSampleRate(); pData->initTime(pData->options.transportExtra); pData->graph.create(static_cast(inputNames.size()), static_cast(outputNames.size()), 0, 0); fDevice->start(this); patchbayRefresh(true, false, false); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) refreshExternalGraphPorts(pData->graph.getPatchbayGraph(), false, false); callback(true, true, ENGINE_CALLBACK_ENGINE_STARTED, 0, pData->options.processMode, pData->options.transportMode, static_cast(pData->bufferSize), static_cast(pData->sampleRate), getCurrentDriverName()); return true; } bool close() override { carla_debug("CarlaEngineJuce::close()"); bool hasError = false; // stop stream first if (fDevice != nullptr && fDevice->isPlaying()) fDevice->stop(); // clear engine data CarlaEngine::close(); pData->graph.destroy(); for (LinkedList::Itenerator it = fMidiIns.begin2(); it.valid(); it.next()) { MidiInPort& inPort(it.getValue(kMidiInPortFallbackNC)); CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr); inPort.port->stop(); delete inPort.port; } fMidiIns.clear(); fMidiInEvents.clear(); fMidiOutMutex.lock(); for (LinkedList::Itenerator it = fMidiOuts.begin2(); it.valid(); it.next()) { MidiOutPort& outPort(it.getValue(kMidiOutPortFallbackNC)); CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); outPort.port->stopBackgroundThread(); delete outPort.port; } fMidiOuts.clear(); fMidiOutMutex.unlock(); // close stream if (fDevice != nullptr) { if (fDevice->isOpen()) fDevice->close(); fDevice = nullptr; } return !hasError; } bool isRunning() const noexcept override { return fDevice != nullptr && fDevice->isOpen(); } bool isOffline() const noexcept override { return false; } EngineType getType() const noexcept override { return kEngineTypeJuce; } const char* getCurrentDriverName() const noexcept override { return fDeviceType->getTypeName().toRawUTF8(); } /* float getDSPLoad() const noexcept override { return 0.0f; } */ uint32_t getTotalXruns() const noexcept override { const int xruns = fDevice->getXRunCount(); if (xruns <= 0) return 0; const uint uxruns = static_cast(xruns); if (uxruns <= pData->xruns) return 0; return uxruns - pData->xruns; } void clearXruns() const noexcept override { const int xruns = fDevice->getXRunCount(); pData->xruns = xruns > 0 ? static_cast(xruns) : 0; } bool setBufferSizeAndSampleRate(const uint bufferSize, const double sampleRate) override { CARLA_SAFE_ASSERT_RETURN(fDevice != nullptr, false); juce::StringArray inputNames(fDevice->getInputChannelNames()); juce::StringArray outputNames(fDevice->getOutputChannelNames()); if (inputNames.size() < 0 || outputNames.size() <= 0) { setLastError("Selected device does not have any outputs"); return false; } juce::BigInteger inputChannels; inputChannels.setRange(0, inputNames.size(), true); juce::BigInteger outputChannels; outputChannels.setRange(0, outputNames.size(), true); // stop stream first if (fDevice->isPlaying()) fDevice->stop(); if (fDevice->isOpen()) fDevice->close(); juce::String error = fDevice->open(inputChannels, outputChannels, sampleRate, static_cast(bufferSize)); if (error.isNotEmpty()) { setLastError(error.toUTF8()); // try to roll back error = fDevice->open(inputChannels, outputChannels, pData->sampleRate, static_cast(pData->bufferSize)); // if we failed, we are screwed... if (error.isNotEmpty()) { fDevice = nullptr; close(); } return false; } const uint32_t newBufferSize = static_cast(fDevice->getCurrentBufferSizeSamples()); const double newSampleRate = fDevice->getCurrentSampleRate(); if (carla_isNotEqual(pData->sampleRate, newSampleRate)) { pData->sampleRate = newSampleRate; sampleRateChanged(newSampleRate); } if (pData->bufferSize != newBufferSize) { pData->bufferSize = newBufferSize; bufferSizeChanged(newBufferSize); } fDevice->start(this); return true; } bool showDeviceControlPanel() const noexcept override { try { return fDevice->showControlPanel(); } CARLA_SAFE_EXCEPTION_RETURN("showDeviceControlPanel", false); } // ------------------------------------------------------------------- // Patchbay template bool refreshExternalGraphPorts(Graph* const graph, const bool sendHost, const bool sendOSC) { CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); char strBuf[STR_MAX]; ExternalGraph& extGraph(graph->extGraph); // --------------------------------------------------------------- // clear last ports extGraph.clear(); // --------------------------------------------------------------- // fill in new ones // Audio In { juce::StringArray inputNames(fDevice->getInputChannelNames()); for (int i=0, count=inputNames.size(); igetOutputChannelNames()); for (int i=0, count=outputNames.size(); igetName()); if (deviceName.isNotEmpty()) deviceName = deviceName.dropLastCharacters(deviceName.fromFirstOccurrenceOf(", ", true, false).length()); graph->refresh(sendHost, sendOSC, true, deviceName.toRawUTF8()); } // --------------------------------------------------------------- // add midi connections for (LinkedList::Itenerator it=fMidiIns.begin2(); it.valid(); it.next()) { const MidiInPort& inPort(it.getValue(kMidiInPortFallback)); CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr); const uint portId(extGraph.midiPorts.getPortId(true, inPort.name)); CARLA_SAFE_ASSERT_CONTINUE(portId < extGraph.midiPorts.ins.count()); ConnectionToId connectionToId; connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupMidiIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiIn); std::snprintf(strBuf, STR_MAX-1, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB); strBuf[STR_MAX-1] = '\0'; callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); extGraph.connections.list.append(connectionToId); } fMidiOutMutex.lock(); for (LinkedList::Itenerator it=fMidiOuts.begin2(); it.valid(); it.next()) { const MidiOutPort& outPort(it.getValue(kMidiOutPortFallback)); CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); const uint portId(extGraph.midiPorts.getPortId(false, outPort.name)); CARLA_SAFE_ASSERT_CONTINUE(portId < extGraph.midiPorts.outs.count()); ConnectionToId connectionToId; connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiOut, kExternalGraphGroupMidiOut, portId); std::snprintf(strBuf, STR_MAX-1, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB); strBuf[STR_MAX-1] = '\0'; callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); extGraph.connections.list.append(connectionToId); } fMidiOutMutex.unlock(); return true; } bool patchbayRefresh(const bool sendHost, const bool sendOSC, const bool external) override { CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(), false); if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) return refreshExternalGraphPorts(pData->graph.getRackGraph(), sendHost, sendOSC); if (sendHost) pData->graph.setUsingExternalHost(external); if (sendOSC) pData->graph.setUsingExternalOSC(external); if (external) return refreshExternalGraphPorts(pData->graph.getPatchbayGraph(), sendHost, sendOSC); return CarlaEngine::patchbayRefresh(sendHost, sendOSC, false); } // ------------------------------------------------------------------- protected: void audioDeviceIOCallback(const float** inputChannelData, int numInputChannels, float** outputChannelData, int numOutputChannels, int numSamples) override { CARLA_SAFE_ASSERT_RETURN(numSamples >= 0,); const uint32_t nframes(static_cast(numSamples)); const PendingRtEventsRunner prt(this, nframes, true); // FIXME remove dspCalc after updating juce // assert juce buffers CARLA_SAFE_ASSERT_RETURN(numInputChannels >= 0,); CARLA_SAFE_ASSERT_RETURN(numOutputChannels > 0,); CARLA_SAFE_ASSERT_RETURN(outputChannelData != nullptr,); CARLA_SAFE_ASSERT_RETURN(numSamples == static_cast(pData->bufferSize),); // initialize juce output for (int i=0; i < numOutputChannels; ++i) carla_zeroFloats(outputChannelData[i], nframes); // initialize events carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount); carla_zeroStructs(pData->events.out, kMaxEngineEventInternalCount); if (fMidiInEvents.mutex.tryLock()) { uint32_t engineEventIndex = 0; fMidiInEvents.splice(); for (LinkedList::Itenerator it = fMidiInEvents.data.begin2(); it.valid(); it.next()) { const RtMidiEvent& midiEvent(it.getValue(kRtMidiEventFallback)); CARLA_SAFE_ASSERT_CONTINUE(midiEvent.size > 0); EngineEvent& engineEvent(pData->events.in[engineEventIndex++]); if (midiEvent.time < pData->timeInfo.frame) { engineEvent.time = 0; } else if (midiEvent.time >= pData->timeInfo.frame + nframes) { carla_stderr("MIDI Event in the future!, %i vs %i", engineEvent.time, pData->timeInfo.frame); engineEvent.time = static_cast(pData->timeInfo.frame) + nframes - 1; } else engineEvent.time = static_cast(midiEvent.time - pData->timeInfo.frame); engineEvent.fillFromMidiData(midiEvent.size, midiEvent.data, 0); if (engineEventIndex >= kMaxEngineEventInternalCount) break; } fMidiInEvents.data.clear(); fMidiInEvents.mutex.unlock(); } pData->graph.process(pData, inputChannelData, outputChannelData, nframes); fMidiOutMutex.lock(); if (fMidiOuts.count() > 0) { uint8_t size = 0; uint8_t data[3] = { 0, 0, 0 }; const uint8_t* dataPtr = data; for (ushort i=0; i < kMaxEngineEventInternalCount; ++i) { const EngineEvent& engineEvent(pData->events.out[i]); if (engineEvent.type == kEngineEventTypeNull) break; else if (engineEvent.type == kEngineEventTypeControl) { const EngineControlEvent& ctrlEvent(engineEvent.ctrl); ctrlEvent.convertToMidiData(engineEvent.channel, data); dataPtr = data; } else if (engineEvent.type == kEngineEventTypeMidi) { const EngineMidiEvent& midiEvent(engineEvent.midi); size = midiEvent.size; if (size > EngineMidiEvent::kDataSize && midiEvent.dataExt != nullptr) dataPtr = midiEvent.dataExt; else dataPtr = midiEvent.data; } else { continue; } if (size > 0) { juce::MidiMessage message(static_cast(dataPtr), static_cast(size), static_cast(engineEvent.time)/nframes); for (LinkedList::Itenerator it=fMidiOuts.begin2(); it.valid(); it.next()) { MidiOutPort& outPort(it.getValue(kMidiOutPortFallbackNC)); CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); outPort.port->sendMessageNow(message); } } } } fMidiOutMutex.unlock(); } void audioDeviceAboutToStart(juce::AudioIODevice* /*device*/) override { } void audioDeviceStopped() override { } void audioDeviceError(const juce::String& errorMessage) override { callback(true, true, ENGINE_CALLBACK_ERROR, 0, 0, 0, 0, 0.0f, errorMessage.toRawUTF8()); } // ------------------------------------------------------------------- void handleIncomingMidiMessage(juce::MidiInput* /*source*/, const juce::MidiMessage& message) override { const int messageSize(message.getRawDataSize()); if (messageSize <= 0 || messageSize > EngineMidiEvent::kDataSize) return; const uint8_t* const messageData(message.getRawData()); RtMidiEvent midiEvent; midiEvent.time = 0; // TODO midiEvent.size = static_cast(messageSize); int i=0; for (; i < messageSize; ++i) midiEvent.data[i] = messageData[i]; for (; i < EngineMidiEvent::kDataSize; ++i) midiEvent.data[i] = 0; fMidiInEvents.append(midiEvent); } // ------------------------------------------------------------------- bool connectExternalGraphPort(const uint connectionType, const uint portId, const char* const portName) override { CARLA_SAFE_ASSERT_RETURN(connectionType != 0 || (portName != nullptr && portName[0] != '\0'), false); carla_stdout("CarlaEngineJuce::connectExternalGraphPort(%u, %u, \"%s\")", connectionType, portId, portName); switch (connectionType) { case kExternalGraphConnectionAudioIn1: case kExternalGraphConnectionAudioIn2: case kExternalGraphConnectionAudioOut1: case kExternalGraphConnectionAudioOut2: return CarlaEngine::connectExternalGraphPort(connectionType, portId, portName); case kExternalGraphConnectionMidiInput: { juce::StringArray midiIns(juce::MidiInput::getDevices()); if (! midiIns.contains(portName)) return false; juce::MidiInput* const juceMidiIn(juce::MidiInput::openDevice(midiIns.indexOf(portName), this)); juceMidiIn->start(); MidiInPort midiPort; midiPort.port = juceMidiIn; std::strncpy(midiPort.name, portName, STR_MAX); midiPort.name[STR_MAX] = '\0'; fMidiIns.append(midiPort); return true; } break; case kExternalGraphConnectionMidiOutput: { juce::StringArray midiOuts(juce::MidiOutput::getDevices()); if (! midiOuts.contains(portName)) return false; juce::MidiOutput* const juceMidiOut(juce::MidiOutput::openDevice(midiOuts.indexOf(portName))); juceMidiOut->startBackgroundThread(); MidiOutPort midiPort; midiPort.port = juceMidiOut; std::strncpy(midiPort.name, portName, STR_MAX); midiPort.name[STR_MAX] = '\0'; const CarlaMutexLocker cml(fMidiOutMutex); fMidiOuts.append(midiPort); return true; } break; } return false; } bool disconnectExternalGraphPort(const uint connectionType, const uint portId, const char* const portName) override { CARLA_SAFE_ASSERT_RETURN(connectionType != 0 || (portName != nullptr && portName[0] != '\0'), false); carla_debug("CarlaEngineJuce::disconnectExternalGraphPort(%u, %u, \"%s\")", connectionType, portId, portName); switch (connectionType) { case kExternalGraphConnectionAudioIn1: case kExternalGraphConnectionAudioIn2: case kExternalGraphConnectionAudioOut1: case kExternalGraphConnectionAudioOut2: return CarlaEngine::disconnectExternalGraphPort(connectionType, portId, portName); case kExternalGraphConnectionMidiInput: for (LinkedList::Itenerator it=fMidiIns.begin2(); it.valid(); it.next()) { MidiInPort& inPort(it.getValue(kMidiInPortFallbackNC)); CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr); if (std::strcmp(inPort.name, portName) != 0) continue; inPort.port->stop(); delete inPort.port; fMidiIns.remove(it); return true; } break; case kExternalGraphConnectionMidiOutput: { const CarlaMutexLocker cml(fMidiOutMutex); for (LinkedList::Itenerator it=fMidiOuts.begin2(); it.valid(); it.next()) { MidiOutPort& outPort(it.getValue(kMidiOutPortFallbackNC)); CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); if (std::strcmp(outPort.name, portName) != 0) continue; outPort.port->stopBackgroundThread(); delete outPort.port; fMidiOuts.remove(it); return true; } } break; } return false; } // ------------------------------------- private: CarlaScopedPointer fDevice; juce::AudioIODeviceType* const fDeviceType; struct RtMidiEvents { CarlaMutex mutex; RtLinkedList::Pool dataPool; RtLinkedList data; RtLinkedList dataPending; RtMidiEvents() : mutex(), dataPool(512, 512), data(dataPool), dataPending(dataPool) {} ~RtMidiEvents() { clear(); } void append(const RtMidiEvent& event) { mutex.lock(); dataPending.append(event); mutex.unlock(); } void clear() { mutex.lock(); data.clear(); dataPending.clear(); mutex.unlock(); } void splice() { if (dataPending.count() > 0) dataPending.moveTo(data, true /* append */); } }; LinkedList fMidiIns; RtMidiEvents fMidiInEvents; LinkedList fMidiOuts; CarlaMutex fMidiOutMutex; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJuce) }; // ----------------------------------------- CarlaEngine* CarlaEngine::newJuce(const AudioApi api) { initJuceDevicesIfNeeded(); juce::String juceApi; switch (api) { case AUDIO_API_NULL: case AUDIO_API_OSS: case AUDIO_API_PULSEAUDIO: break; case AUDIO_API_JACK: juceApi = "JACK"; break; case AUDIO_API_ALSA: juceApi = "ALSA"; break; case AUDIO_API_COREAUDIO: juceApi = "CoreAudio"; break; case AUDIO_API_ASIO: juceApi = "ASIO"; break; case AUDIO_API_DIRECTSOUND: juceApi = "DirectSound"; break; case AUDIO_API_WASAPI: juceApi = "Windows Audio"; break; } if (juceApi.isEmpty()) return nullptr; juce::AudioIODeviceType* deviceType = nullptr; for (int i=0, count=gDeviceTypes.size(); i < count; ++i) { deviceType = gDeviceTypes[i]; if (deviceType == nullptr || deviceType->getTypeName() == juceApi) break; } if (deviceType == nullptr) return nullptr; deviceType->scanForDevices(); return new CarlaEngineJuce(deviceType); } uint CarlaEngine::getJuceApiCount() { initJuceDevicesIfNeeded(); return static_cast(gDeviceTypes.size()); } const char* CarlaEngine::getJuceApiName(const uint uindex) { initJuceDevicesIfNeeded(); const int index(static_cast(uindex)); CARLA_SAFE_ASSERT_RETURN(index < gDeviceTypes.size(), nullptr); juce::AudioIODeviceType* const deviceType(gDeviceTypes[index]); CARLA_SAFE_ASSERT_RETURN(deviceType != nullptr, nullptr); return deviceType->getTypeName().toRawUTF8(); } const char* const* CarlaEngine::getJuceApiDeviceNames(const uint uindex) { initJuceDevicesIfNeeded(); const int index(static_cast(uindex)); CARLA_SAFE_ASSERT_RETURN(index < gDeviceTypes.size(), nullptr); juce::AudioIODeviceType* const deviceType(gDeviceTypes[index]); CARLA_SAFE_ASSERT_RETURN(deviceType != nullptr, nullptr); deviceType->scanForDevices(); juce::StringArray juceDeviceNames(deviceType->getDeviceNames()); const int juceDeviceNameCount(juceDeviceNames.size()); if (juceDeviceNameCount <= 0) return nullptr; CarlaStringList devNames; for (int i=0; i < juceDeviceNameCount; ++i) devNames.append(juceDeviceNames[i].toRawUTF8()); gDeviceNames = devNames.toCharStringListPtr(); return gDeviceNames; } const EngineDriverDeviceInfo* CarlaEngine::getJuceDeviceInfo(const uint uindex, const char* const deviceName) { initJuceDevicesIfNeeded(); const int index(static_cast(uindex)); CARLA_SAFE_ASSERT_RETURN(index < gDeviceTypes.size(), nullptr); juce::AudioIODeviceType* const deviceType(gDeviceTypes[index]); CARLA_SAFE_ASSERT_RETURN(deviceType != nullptr, nullptr); deviceType->scanForDevices(); CarlaScopedPointer device(deviceType->createDevice(deviceName, deviceName)); if (device == nullptr) return nullptr; static EngineDriverDeviceInfo devInfo = { 0x0, nullptr, nullptr }; static uint32_t dummyBufferSizes[11] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 0 }; static double dummySampleRates[14] = { 22050.0, 32000.0, 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0, 0.0 }; // reset devInfo.hints = ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE | ENGINE_DRIVER_DEVICE_VARIABLE_SAMPLE_RATE; // cleanup if (devInfo.bufferSizes != nullptr && devInfo.bufferSizes != dummyBufferSizes) { delete[] devInfo.bufferSizes; devInfo.bufferSizes = nullptr; } if (devInfo.sampleRates != nullptr && devInfo.sampleRates != dummySampleRates) { delete[] devInfo.sampleRates; devInfo.sampleRates = nullptr; } if (device->hasControlPanel()) devInfo.hints |= ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL; juce::Array juceBufferSizes = device->getAvailableBufferSizes(); if (int bufferSizesCount = juceBufferSizes.size()) { uint32_t* const bufferSizes(new uint32_t[bufferSizesCount+1]); for (int i=0; i < bufferSizesCount; ++i) bufferSizes[i] = static_cast(juceBufferSizes[i]); bufferSizes[bufferSizesCount] = 0; devInfo.bufferSizes = bufferSizes; } else { devInfo.bufferSizes = dummyBufferSizes; } juce::Array juceSampleRates = device->getAvailableSampleRates(); if (int sampleRatesCount = juceSampleRates.size()) { double* const sampleRates(new double[sampleRatesCount+1]); for (int i=0; i < sampleRatesCount; ++i) sampleRates[i] = juceSampleRates[i]; sampleRates[sampleRatesCount] = 0.0; devInfo.sampleRates = sampleRates; } else { devInfo.sampleRates = dummySampleRates; } return &devInfo; } bool CarlaEngine::showJuceDeviceControlPanel(const uint uindex, const char* const deviceName) { const int index(static_cast(uindex)); CARLA_SAFE_ASSERT_RETURN(index < gDeviceTypes.size(), false); juce::AudioIODeviceType* const deviceType(gDeviceTypes[index]); CARLA_SAFE_ASSERT_RETURN(deviceType != nullptr, false); deviceType->scanForDevices(); CarlaScopedPointer device(deviceType->createDevice(deviceName, deviceName)); CARLA_SAFE_ASSERT_RETURN(device != nullptr, false); return device->showControlPanel(); } // ----------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/engine/CarlaEngineNative.cpp000066400000000000000000002777261364475620200226130ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaDefines.h" #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH # error This file should not be compiled if building alternative-arch bridges #endif #include "CarlaEngineInternal.hpp" #include "CarlaPlugin.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaBase64Utils.hpp" #include "CarlaBinaryUtils.hpp" #include "CarlaMathUtils.hpp" #include "CarlaStateUtils.hpp" #include "CarlaExternalUI.hpp" #include "CarlaHost.h" #include "CarlaNative.hpp" #include "CarlaNativePlugin.h" #if defined(USING_JUCE) && ! (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Weffc++" # pragma GCC diagnostic ignored "-Wsign-conversion" # pragma GCC diagnostic ignored "-Wundef" # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" # endif # include "AppConfig.h" # include "juce_events/juce_events.h" # define USE_JUCE_MESSAGE_THREAD # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic pop # endif #endif #include "water/files/File.h" #include "water/streams/MemoryOutputStream.h" #include "water/xml/XmlDocument.h" #include "water/xml/XmlElement.h" using water::File; using water::MemoryOutputStream; using water::String; using water::XmlDocument; using water::XmlElement; CARLA_BACKEND_START_NAMESPACE static const uint32_t kNumInParams = 100; static const uint32_t kNumOutParams = 10; // ----------------------------------------------------------------------- #ifdef USE_JUCE_MESSAGE_THREAD static int numScopedInitInstances = 0; class SharedJuceMessageThread : public juce::Thread { public: SharedJuceMessageThread() : juce::Thread ("SharedJuceMessageThread"), initialised (false) {} ~SharedJuceMessageThread() { CARLA_SAFE_ASSERT(numScopedInitInstances == 0); // in case something fails juce::MessageManager::getInstance()->stopDispatchLoop(); waitForThreadToExit (5000); } void incRef() { if (numScopedInitInstances++ == 0) { startThread (7); while (! initialised) juce::Thread::sleep (1); } } void decRef() { if (--numScopedInitInstances == 0) { juce::MessageManager::getInstance()->stopDispatchLoop(); waitForThreadToExit (5000); } } protected: void run() override { const juce::ScopedJuceInitialiser_GUI juceInitialiser; juce::MessageManager::getInstance()->setCurrentThreadAsMessageThread(); initialised = true; juce::MessageManager::getInstance()->runDispatchLoop(); } private: volatile bool initialised; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SharedJuceMessageThread); }; #endif // ----------------------------------------------------------------------- class CarlaEngineNative; class CarlaEngineNativeUI : public CarlaExternalUI { public: CarlaEngineNativeUI(CarlaEngineNative* const engine) : fEngine(engine) { carla_debug("CarlaEngineNativeUI::CarlaEngineNativeUI(%p)", engine); } ~CarlaEngineNativeUI() noexcept override { carla_debug("CarlaEngineNativeUI::~CarlaEngineNativeUI()"); } protected: bool msgReceived(const char* const msg) noexcept override; private: CarlaEngineNative* const fEngine; void _updateParamValues(CarlaPlugin* const plugin, const uint32_t pluginId, const bool sendCallback, const bool sendPluginHost) const noexcept; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNativeUI) }; // ----------------------------------------------------------------------- class CarlaEngineNative : public CarlaEngine { public: CarlaEngineNative(const NativeHostDescriptor* const host, const bool isPatchbay, const bool withMidiOut, const uint32_t inChan = 2, uint32_t outChan = 2, const uint32_t cvIns = 0, const uint32_t cvOuts = 0) : CarlaEngine(), pHost(host), #ifdef USE_JUCE_MESSAGE_THREAD // if not running inside Carla, we will have to run event loop ourselves kNeedsJuceMsgThread(host->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_INTERNAL_PLUGIN, 0, 0, nullptr, 0.0f) == 0), fJuceMsgThread(), #endif kIsPatchbay(isPatchbay), kHasMidiOut(withMidiOut), fIsActive(false), fIsRunning(false), fUiServer(this), fOptionsForced(false) { carla_debug("CarlaEngineNative::CarlaEngineNative()"); carla_zeroFloats(fParameters, kNumInParams+kNumOutParams); #ifdef USE_JUCE_MESSAGE_THREAD if (kNeedsJuceMsgThread) fJuceMsgThread->incRef(); #endif pData->bufferSize = pHost->get_buffer_size(pHost->handle); pData->sampleRate = pHost->get_sample_rate(pHost->handle); pData->initTime(nullptr); #ifndef BUILD_BRIDGE // Forced OSC setup when running as plugin pData->options.oscEnabled = true; pData->options.oscPortTCP = -1; pData->options.oscPortUDP = 0; #endif if (outChan == 0) outChan = inChan; // set-up engine if (kIsPatchbay) { pData->options.processMode = ENGINE_PROCESS_MODE_PATCHBAY; pData->options.transportMode = ENGINE_TRANSPORT_MODE_PLUGIN; pData->options.forceStereo = false; pData->options.preferPluginBridges = false; pData->options.preferUiBridges = false; init("Carla-Patchbay"); pData->graph.create(inChan, outChan, cvIns, cvOuts); } else { CARLA_SAFE_ASSERT(inChan == 2); CARLA_SAFE_ASSERT(outChan == 2); pData->options.processMode = ENGINE_PROCESS_MODE_CONTINUOUS_RACK; pData->options.transportMode = ENGINE_TRANSPORT_MODE_PLUGIN; pData->options.forceStereo = true; pData->options.preferPluginBridges = false; pData->options.preferUiBridges = false; init("Carla-Rack"); pData->graph.create(0, 0, 0, 0); // FIXME? } if (pData->options.resourceDir != nullptr) delete[] pData->options.resourceDir; if (pData->options.binaryDir != nullptr) delete[] pData->options.binaryDir; pData->options.resourceDir = carla_strdup(pHost->resourceDir); pData->options.binaryDir = carla_strdup(carla_get_library_folder()); setCallback(_ui_server_callback, this); setFileCallback(_ui_file_callback, this); } ~CarlaEngineNative() override { CARLA_SAFE_ASSERT(! fIsActive); carla_debug("CarlaEngineNative::~CarlaEngineNative() - START"); pData->aboutToClose = true; fIsRunning = false; removeAllPlugins(); //runPendingRtEvents(); close(); pData->graph.destroy(); #ifdef USE_JUCE_MESSAGE_THREAD if (kNeedsJuceMsgThread) fJuceMsgThread->decRef(); #endif carla_debug("CarlaEngineNative::~CarlaEngineNative() - END"); } // ------------------------------------- // CarlaEngine virtual calls bool init(const char* const clientName) override { carla_debug("CarlaEngineNative::init(\"%s\")", clientName); fIsRunning = true; if (! pData->init(clientName)) { close(); setLastError("Failed to init internal data"); return false; } pData->bufferSize = pHost->get_buffer_size(pHost->handle); pData->sampleRate = pHost->get_sample_rate(pHost->handle); return true; } bool close() override { fIsRunning = false; CarlaEngine::close(); return true; } bool isRunning() const noexcept override { return fIsRunning; } bool isOffline() const noexcept override { return pHost->is_offline(pHost->handle); } bool usesConstantBufferSize() const noexcept override { // TODO LV2 hosts can report this, till then we allow this return true; } EngineType getType() const noexcept override { return kEngineTypePlugin; } const char* getCurrentDriverName() const noexcept override { return "Plugin"; } void callback(const bool sendHost, const bool sendOsc, const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const int value3, const float valuef, const char* const valueStr) noexcept override { CarlaEngine::callback(sendHost, sendOsc, action, pluginId, value1, value2, value3, valuef, valueStr); switch (action) { case ENGINE_CALLBACK_IDLE: if (! pData->aboutToClose) pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_HOST_IDLE, 0, 0, nullptr, 0.0f); break; case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED: if (sendHost && value1 >= 0) { uint32_t rindex = static_cast(value1); if (_getRealIndexForPluginParameter(pluginId, rindex)) { fParameters[rindex] = valuef; pHost->ui_parameter_changed(pHost->handle, rindex, valuef); } } break; default: break; } } // ------------------------------------------------------------------- void touchPluginParameter(const uint id, const uint32_t parameterId, const bool touch) noexcept override { setParameterTouchFromUI(id, parameterId, touch); } // ------------------------------------------------------------------- void setParameterValueFromUI(const uint32_t pluginId, const uint32_t index, const float value) { uint32_t rindex = index; if (_getRealIndexForPluginParameter(pluginId, rindex)) { fParameters[rindex] = value; pHost->ui_parameter_changed(pHost->handle, rindex, value); } } void setParameterTouchFromUI(const uint32_t pluginId, const uint32_t index, const bool touch) { uint32_t rindex = index; if (_getRealIndexForPluginParameter(pluginId, rindex)) { pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER, static_cast(rindex), touch ? 1 : 0, nullptr, 0.0f); } } void reloadFromUI() { carla_zeroFloats(fParameters, kNumInParams+kNumOutParams); pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_RELOAD_PARAMETERS, 0, 0, nullptr, 0.0f); } protected: // ------------------------------------------------------------------- void bufferSizeChanged(const uint32_t newBufferSize) { if (pData->bufferSize == newBufferSize) return; { const CarlaMutexLocker cml(fUiServer.getPipeLock()); if (fUiServer.writeAndFixMessage("buffer-size")) { char tmpBuf[STR_MAX+1]; carla_zeroChars(tmpBuf, STR_MAX+1); std::snprintf(tmpBuf, STR_MAX, "%i\n", newBufferSize); if (fUiServer.writeMessage(tmpBuf)) fUiServer.flushMessages(); } } pData->bufferSize = newBufferSize; CarlaEngine::bufferSizeChanged(newBufferSize); } void sampleRateChanged(const double newSampleRate) { if (carla_isEqual(pData->sampleRate, newSampleRate)) return; { const CarlaMutexLocker cml(fUiServer.getPipeLock()); if (fUiServer.writeAndFixMessage("sample-rate")) { char tmpBuf[STR_MAX+1]; carla_zeroChars(tmpBuf, STR_MAX+1); { const CarlaScopedLocale csl; std::snprintf(tmpBuf, STR_MAX, "%.12g\n", newSampleRate); } if (fUiServer.writeMessage(tmpBuf)) fUiServer.flushMessages(); } } pData->sampleRate = newSampleRate; CarlaEngine::sampleRateChanged(newSampleRate); } // ------------------------------------------------------------------- void uiServerSendPluginInfo(CarlaPlugin* const plugin) { char tmpBuf[STR_MAX+1]; carla_zeroChars(tmpBuf, STR_MAX+1); const CarlaMutexLocker cml(fUiServer.getPipeLock()); const uint pluginId(plugin->getId()); std::snprintf(tmpBuf, STR_MAX, "PLUGIN_INFO_%i\n", pluginId); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%i:%i:%i:" P_INT64 ":%i:%i\n", plugin->getType(), plugin->getCategory(), plugin->getHints(), plugin->getUniqueId(), plugin->getOptionsAvailable(), plugin->getOptionsEnabled()); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); if (const char* const filename = plugin->getFilename()) { std::snprintf(tmpBuf, STR_MAX, "%s", filename); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } if (const char* const name = plugin->getName()) { std::snprintf(tmpBuf, STR_MAX, "%s", name); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } if (const char* const iconName = plugin->getIconName()) { std::snprintf(tmpBuf, STR_MAX, "%s", iconName); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } if (plugin->getRealName(tmpBuf)) { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } if (plugin->getLabel(tmpBuf)) { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } if (plugin->getMaker(tmpBuf)) { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } if (plugin->getCopyright(tmpBuf)) { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } std::snprintf(tmpBuf, STR_MAX, "AUDIO_COUNT_%i:%i:%i\n", pluginId, plugin->getAudioInCount(), plugin->getAudioOutCount()); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "MIDI_COUNT_%i:%i:%i\n", pluginId, plugin->getMidiInCount(), plugin->getMidiOutCount()); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); fUiServer.flushMessages(); } void uiServerSendPluginParameters(CarlaPlugin* const plugin) { char tmpBuf[STR_MAX+1]; carla_zeroChars(tmpBuf, STR_MAX+1); const CarlaMutexLocker cml(fUiServer.getPipeLock()); const CarlaScopedLocale csl; const uint pluginId(plugin->getId()); for (int32_t i=PARAMETER_ACTIVE; i>PARAMETER_MAX; --i) { std::snprintf(tmpBuf, STR_MAX, "PARAMVAL_%u:%i\n", pluginId, i); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%.12g\n", static_cast(plugin->getInternalParameterValue(i))); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); fUiServer.flushMessages(); } uint32_t ins, outs, count; plugin->getParameterCountInfo(ins, outs); count = plugin->getParameterCount(); std::snprintf(tmpBuf, STR_MAX, "PARAMETER_COUNT_%i:%i:%i:%i\n", pluginId, ins, outs, count); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); for (uint32_t i=0; igetParameterData(i)); const ParameterRanges& paramRanges(plugin->getParameterRanges(i)); std::snprintf(tmpBuf, STR_MAX, "PARAMETER_DATA_%i:%i\n", pluginId, i); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%i:%i:%i:%i\n", paramData.type, paramData.hints, paramData.mappedControlIndex, paramData.midiChannel); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%.12g:%.12g\n", static_cast(paramData.mappedMinimum), static_cast(paramData.mappedMaximum)); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); if (plugin->getParameterName(i, tmpBuf)) { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } if (plugin->getParameterUnit(i, tmpBuf)) { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } if (plugin->getParameterComment(i, tmpBuf)) { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } if (plugin->getParameterGroupName(i, tmpBuf)) { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } std::snprintf(tmpBuf, STR_MAX, "PARAMETER_RANGES_%i:%i\n", pluginId, i); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%.12g:%.12g:%.12g:%.12g:%.12g:%.12g\n", static_cast(paramRanges.def), static_cast(paramRanges.min), static_cast(paramRanges.max), static_cast(paramRanges.step), static_cast(paramRanges.stepSmall), static_cast(paramRanges.stepLarge)); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "PARAMVAL_%u:%u\n", pluginId, i); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%.12g\n", static_cast(plugin->getParameterValue(i))); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); } fUiServer.flushMessages(); } void uiServerSendPluginPrograms(CarlaPlugin* const plugin) { char tmpBuf[STR_MAX+1]; carla_zeroChars(tmpBuf, STR_MAX+1); const CarlaMutexLocker cml(fUiServer.getPipeLock()); const uint pluginId(plugin->getId()); uint32_t count = plugin->getProgramCount(); std::snprintf(tmpBuf, STR_MAX, "PROGRAM_COUNT_%i:%i:%i\n", pluginId, count, plugin->getCurrentProgram()); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); for (uint32_t i=0; igetProgramName(i, tmpBuf)) { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } } fUiServer.flushMessages(); count = plugin->getMidiProgramCount(); std::snprintf(tmpBuf, STR_MAX, "MIDI_PROGRAM_COUNT_%i:%i:%i\n", pluginId, count, plugin->getCurrentMidiProgram()); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); for (uint32_t i=0; igetMidiProgramData(i)); std::snprintf(tmpBuf, STR_MAX, "%i:%i\n", mpData.bank, mpData.program); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%s", mpData.name); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); } fUiServer.flushMessages(); } void uiServerSendPluginProperties(CarlaPlugin* const plugin) { char tmpBuf[STR_MAX+1]; carla_zeroChars(tmpBuf, STR_MAX+1); const CarlaMutexLocker cml(fUiServer.getPipeLock()); const uint pluginId(plugin->getId()); uint32_t count = plugin->getCustomDataCount(); std::snprintf(tmpBuf, STR_MAX, "CUSTOM_DATA_COUNT_%i:%i\n", pluginId, count); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); for (uint32_t i=0; igetCustomData(i)); CARLA_SAFE_ASSERT_CONTINUE(customData.isValid()); if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_PROPERTY) != 0) continue; std::snprintf(tmpBuf, STR_MAX, "CUSTOM_DATA_%i:%i\n", pluginId, i); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(customData.type),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(customData.key),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(customData.value),); } fUiServer.flushMessages(); } void uiServerCallback(const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const int value3, const float valuef, const char* const valueStr) { if (! fIsRunning) return; if (! fUiServer.isPipeRunning()) return; CarlaPlugin* plugin; switch (action) { case ENGINE_CALLBACK_UPDATE: plugin = getPlugin(pluginId); if (plugin != nullptr && plugin->isEnabled()) { CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId); uiServerSendPluginProperties(plugin); } break; case ENGINE_CALLBACK_RELOAD_INFO: plugin = getPlugin(pluginId); if (plugin != nullptr && plugin->isEnabled()) { CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId); uiServerSendPluginInfo(plugin); } break; case ENGINE_CALLBACK_RELOAD_PARAMETERS: plugin = getPlugin(pluginId); if (plugin != nullptr && plugin->isEnabled()) { CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId); uiServerSendPluginParameters(plugin); } break; case ENGINE_CALLBACK_RELOAD_PROGRAMS: plugin = getPlugin(pluginId); if (plugin != nullptr && plugin->isEnabled()) { CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId); uiServerSendPluginPrograms(plugin); } break; case ENGINE_CALLBACK_RELOAD_ALL: case ENGINE_CALLBACK_PLUGIN_ADDED: case ENGINE_CALLBACK_PLUGIN_RENAMED: plugin = getPlugin(pluginId); if (plugin != nullptr && plugin->isEnabled()) { CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId); uiServerSendPluginInfo(plugin); uiServerSendPluginParameters(plugin); uiServerSendPluginPrograms(plugin); uiServerSendPluginProperties(plugin); } break; default: break; } char tmpBuf[STR_MAX+1]; carla_zeroChars(tmpBuf, STR_MAX+1); const CarlaMutexLocker cml(fUiServer.getPipeLock()); std::snprintf(tmpBuf, STR_MAX, "ENGINE_CALLBACK_%i\n", int(action)); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%u\n", pluginId); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%i\n", value1); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%i\n", value2); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%i\n", value3); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); { const CarlaScopedLocale csl; std::snprintf(tmpBuf, STR_MAX, "%.12g\n", static_cast(valuef)); } CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); if (valueStr != nullptr) { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(valueStr),); } else { CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } fUiServer.flushMessages(); } const char* uiFileCallback(FileCallbackOpcode action, bool isDir, const char* title, const char* filter) { switch (action) { case FILE_CALLBACK_DEBUG: return nullptr; case FILE_CALLBACK_OPEN: return pHost->ui_open_file(pHost->handle, isDir, title, filter); case FILE_CALLBACK_SAVE: return pHost->ui_save_file(pHost->handle, isDir, title, filter); } return nullptr; } void uiServerInfo() { CARLA_SAFE_ASSERT_RETURN(fIsRunning,); CARLA_SAFE_ASSERT_RETURN(fUiServer.isPipeRunning(),); char tmpBuf[STR_MAX+1]; carla_zeroChars(tmpBuf, STR_MAX+1); const CarlaMutexLocker cml(fUiServer.getPipeLock()); #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("osc-urls\n"),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(pData->osc.getServerPathTCP()),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(pData->osc.getServerPathUDP()),); #endif CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("max-plugin-number\n"),); std::snprintf(tmpBuf, STR_MAX, "%i\n", pData->maxPluginNumber); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("buffer-size\n"),); std::snprintf(tmpBuf, STR_MAX, "%i\n", pData->bufferSize); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("sample-rate\n"),); { const CarlaScopedLocale csl; std::snprintf(tmpBuf, STR_MAX, "%.12g\n", pData->sampleRate); } CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); fUiServer.flushMessages(); } void uiServerOptions() { CARLA_SAFE_ASSERT_RETURN(fIsRunning,); CARLA_SAFE_ASSERT_RETURN(fUiServer.isPipeRunning(),); char tmpBuf[STR_MAX+1]; carla_zeroChars(tmpBuf, STR_MAX+1); const EngineOptions& options(pData->options); const CarlaMutexLocker cml(fUiServer.getPipeLock()); const char* const optionsForcedStr(fOptionsForced ? "true\n" : "false\n"); const std::size_t optionsForcedStrSize(fOptionsForced ? 5 : 6); std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PROCESS_MODE); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),); std::snprintf(tmpBuf, STR_MAX, "%i\n", options.processMode); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); fUiServer.flushMessages(); std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_TRANSPORT_MODE); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),); std::snprintf(tmpBuf, STR_MAX, "%i\n", options.transportMode); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); fUiServer.flushMessages(); std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_FORCE_STEREO); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(options.forceStereo ? "true\n" : "false\n"),); fUiServer.flushMessages(); std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PREFER_PLUGIN_BRIDGES); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(options.preferPluginBridges ? "true\n" : "false\n"),); fUiServer.flushMessages(); std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PREFER_UI_BRIDGES); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(options.preferUiBridges ? "true\n" : "false\n"),); fUiServer.flushMessages(); std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_UIS_ALWAYS_ON_TOP); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(options.uisAlwaysOnTop ? "true\n" : "false\n"),); fUiServer.flushMessages(); std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_MAX_PARAMETERS); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),); std::snprintf(tmpBuf, STR_MAX, "%i\n", options.maxParameters); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); fUiServer.flushMessages(); std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_UI_BRIDGES_TIMEOUT); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),); std::snprintf(tmpBuf, STR_MAX, "%i\n", options.uiBridgesTimeout); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); fUiServer.flushMessages(); std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PATH_BINARIES); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("true\n", 5),); std::snprintf(tmpBuf, STR_MAX, "%s\n", options.binaryDir); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); fUiServer.flushMessages(); std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PATH_RESOURCES); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("true\n", 5),); std::snprintf(tmpBuf, STR_MAX, "%s\n", options.resourceDir); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); fUiServer.flushMessages(); } // ------------------------------------------------------------------- // Plugin parameter calls uint32_t getParameterCount() const { return kNumInParams + kNumOutParams; } const NativeParameter* getParameterInfo(const uint32_t index) const { static NativeParameter param; static char strBufName[STR_MAX+1]; static char strBufUnit[STR_MAX+1]; static char strBufComment[STR_MAX+1]; static char strBufGroupName[STR_MAX+1]; carla_zeroChars(strBufName, STR_MAX+1); carla_zeroChars(strBufUnit, STR_MAX+1); carla_zeroChars(strBufComment, STR_MAX+1); carla_zeroChars(strBufGroupName, STR_MAX+1); uint32_t rindex = index; if (CarlaPlugin* const plugin = _getPluginForParameterIndex(rindex)) { const ParameterData& paramData(plugin->getParameterData(rindex)); const ParameterRanges& paramRanges(plugin->getParameterRanges(rindex)); if (! plugin->getParameterName(rindex, strBufName)) strBufName[0] = '\0'; if (! plugin->getParameterUnit(rindex, strBufUnit)) strBufUnit[0] = '\0'; if (! plugin->getParameterComment(rindex, strBufComment)) strBufComment[0] = '\0'; if (! plugin->getParameterGroupName(rindex, strBufGroupName)) std::snprintf(strBufGroupName, STR_MAX, "%u:%s", plugin->getId(), plugin->getName()); uint hints = 0x0; if (paramData.hints & PARAMETER_IS_BOOLEAN) hints |= NATIVE_PARAMETER_IS_BOOLEAN; if (paramData.hints & PARAMETER_IS_INTEGER) hints |= NATIVE_PARAMETER_IS_INTEGER; if (paramData.hints & PARAMETER_IS_LOGARITHMIC) hints |= NATIVE_PARAMETER_IS_LOGARITHMIC; if (paramData.hints & PARAMETER_IS_AUTOMABLE) hints |= NATIVE_PARAMETER_IS_AUTOMABLE; if (paramData.hints & PARAMETER_USES_SAMPLERATE) hints |= NATIVE_PARAMETER_USES_SAMPLE_RATE; if (paramData.hints & PARAMETER_USES_SCALEPOINTS) hints |= NATIVE_PARAMETER_USES_SCALEPOINTS; if (paramData.type == PARAMETER_INPUT || paramData.type == PARAMETER_OUTPUT) { if (paramData.hints & PARAMETER_IS_ENABLED) hints |= NATIVE_PARAMETER_IS_ENABLED; if (paramData.type == PARAMETER_OUTPUT) hints |= NATIVE_PARAMETER_IS_OUTPUT; } param.hints = static_cast(hints); param.name = strBufName; param.unit = strBufUnit; param.comment = strBufComment; param.groupName = strBufGroupName; param.ranges.def = paramRanges.def; param.ranges.min = paramRanges.min; param.ranges.max = paramRanges.max; param.ranges.step = paramRanges.step; param.ranges.stepSmall = paramRanges.stepSmall; param.ranges.stepLarge = paramRanges.stepLarge; param.scalePointCount = 0; // TODO param.scalePoints = nullptr; return ¶m; } param.hints = index < kNumInParams ? static_cast(0x0) : NATIVE_PARAMETER_IS_OUTPUT; param.name = "Unused"; param.unit = ""; param.ranges.def = 0.0f; param.ranges.min = 0.0f; param.ranges.max = 1.0f; param.ranges.step = 0.01f; param.ranges.stepSmall = 0.001f; param.ranges.stepLarge = 0.1f; param.scalePointCount = 0; param.scalePoints = nullptr; return ¶m; } float getParameterValue(const uint32_t index) const { uint32_t rindex = index; if (CarlaPlugin* const plugin = _getPluginForParameterIndex(rindex)) return plugin->getParameterValue(rindex); return fParameters[index]; } // ------------------------------------------------------------------- // Plugin state calls void setParameterValue(const uint32_t index, const float value) { uint32_t rindex = index; if (CarlaPlugin* const plugin = _getPluginForParameterIndex(rindex)) plugin->setParameterValueRT(rindex, value, false); fParameters[index] = value; } // ------------------------------------------------------------------- // Plugin process calls void activate() { #if 0 for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin == nullptr || ! plugin->isEnabled()) continue; plugin->setActive(true, true, false); } #endif fIsActive = true; } void deactivate() { fIsActive = false; #if 0 for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin == nullptr || ! plugin->isEnabled()) continue; plugin->setActive(false, true, false); } #endif // just in case //runPendingRtEvents(); } void process(const float* const* const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) { if (frames > pData->bufferSize) { carla_stderr2("Host is calling process with too high number of frames! %u vs %u", frames, pData->bufferSize); deactivate(); bufferSizeChanged(frames); activate(); } const PendingRtEventsRunner prt(this, frames, true); // --------------------------------------------------------------- // Time Info const NativeTimeInfo* const timeInfo(pHost->get_time_info(pHost->handle)); pData->timeInfo.playing = timeInfo->playing; pData->timeInfo.frame = timeInfo->frame; pData->timeInfo.usecs = timeInfo->usecs; pData->timeInfo.bbt.valid = timeInfo->bbt.valid; if (timeInfo->bbt.valid) { pData->timeInfo.bbt.bar = timeInfo->bbt.bar; pData->timeInfo.bbt.beat = timeInfo->bbt.beat; pData->timeInfo.bbt.tick = timeInfo->bbt.tick; pData->timeInfo.bbt.barStartTick = timeInfo->bbt.barStartTick; pData->timeInfo.bbt.beatsPerBar = timeInfo->bbt.beatsPerBar; pData->timeInfo.bbt.beatType = timeInfo->bbt.beatType; pData->timeInfo.bbt.ticksPerBeat = timeInfo->bbt.ticksPerBeat; pData->timeInfo.bbt.beatsPerMinute = timeInfo->bbt.beatsPerMinute; } // --------------------------------------------------------------- // Do nothing if no plugins and rack mode if (pData->curPluginCount == 0 && ! kIsPatchbay) { if (outBuffer[0] != inBuffer[0]) carla_copyFloats(outBuffer[0], inBuffer[0], frames); if (outBuffer[1] != inBuffer[1]) carla_copyFloats(outBuffer[1], inBuffer[1], frames); for (uint32_t i=0; i < midiEventCount; ++i) { if (! pHost->write_midi_event(pHost->handle, &midiEvents[i])) break; } return; } // --------------------------------------------------------------- // initialize events carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount); carla_zeroStructs(pData->events.out, kMaxEngineEventInternalCount); // --------------------------------------------------------------- // events input (before processing) { uint32_t engineEventIndex = 0; for (uint32_t i=0; i < midiEventCount && engineEventIndex < kMaxEngineEventInternalCount; ++i) { const NativeMidiEvent& midiEvent(midiEvents[i]); EngineEvent& engineEvent(pData->events.in[engineEventIndex++]); engineEvent.time = midiEvent.time; engineEvent.fillFromMidiData(midiEvent.size, midiEvent.data, 0); if (engineEventIndex >= kMaxEngineEventInternalCount) break; } } if (kIsPatchbay) { // ----------------------------------------------------------- // process pData->graph.process(pData, inBuffer, outBuffer, frames); } else { // ----------------------------------------------------------- // create audio buffers const float* inBuf[2] = { inBuffer[0], inBuffer[1] }; /* */ float* outBuf[2] = { outBuffer[0], outBuffer[1] }; // ----------------------------------------------------------- // process pData->graph.processRack(pData, inBuf, outBuf, frames); } // --------------------------------------------------------------- // events output (after processing) carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount); if (kHasMidiOut) { NativeMidiEvent midiEvent; for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i) { const EngineEvent& engineEvent(pData->events.out[i]); if (engineEvent.type == kEngineEventTypeNull) break; carla_zeroStruct(midiEvent); midiEvent.time = engineEvent.time; /**/ if (engineEvent.type == kEngineEventTypeControl) { midiEvent.port = 0; midiEvent.size = engineEvent.ctrl.convertToMidiData(engineEvent.channel, midiEvent.data); } else if (engineEvent.type == kEngineEventTypeMidi) { if (engineEvent.midi.size > 4) continue; midiEvent.port = engineEvent.midi.port; midiEvent.size = engineEvent.midi.size; midiEvent.data[0] = static_cast(engineEvent.midi.data[0] | (engineEvent.channel & MIDI_CHANNEL_BIT)); for (uint8_t j=1; j < midiEvent.size; ++j) midiEvent.data[j] = engineEvent.midi.data[j]; } else { continue; } if (midiEvent.size > 0) pHost->write_midi_event(pHost->handle, &midiEvent); } } } // ------------------------------------------------------------------- // Plugin UI calls void uiShow(const bool show) { if (show) { if (fUiServer.isPipeRunning()) { fUiServer.writeFocusMessage(); return; } CarlaString path(pHost->resourceDir); if (kIsPatchbay) path += CARLA_OS_SEP_STR "carla-plugin-patchbay"; else path += CARLA_OS_SEP_STR "carla-plugin"; #ifdef CARLA_OS_WIN path += ".exe"; #endif carla_stdout("Trying to start carla-plugin using \"%s\"", path.buffer()); fUiServer.setData(path, pData->sampleRate, pHost->uiName); if (! fUiServer.startPipeServer(false)) { pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f); return; } uiServerInfo(); uiServerOptions(); uiServerCallback(ENGINE_CALLBACK_ENGINE_STARTED, pData->curPluginCount, pData->options.processMode, pData->options.transportMode, static_cast(pData->bufferSize), static_cast(pData->sampleRate), "Plugin"); fUiServer.writeShowMessage(); for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin != nullptr && plugin->isEnabled()) { uiServerCallback(ENGINE_CALLBACK_PLUGIN_ADDED, i, 0, 0, 0, 0.0f, plugin->getName()); } } if (kIsPatchbay) patchbayRefresh(true, false, false); } else { fUiServer.stopPipeServer(2000); // hide all custom uis for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin != nullptr && plugin->isEnabled()) { if (plugin->getHints() & PLUGIN_HAS_CUSTOM_UI) { try { plugin->showCustomUI(false); } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin showCustomUI (hide)"); } } } } } void uiIdle() { for (uint i=0; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin(pData->plugins[i].plugin); if (plugin != nullptr && plugin->isEnabled()) { const uint hints(plugin->getHints()); if ((hints & PLUGIN_HAS_CUSTOM_UI) != 0 && (hints & PLUGIN_NEEDS_UI_MAIN_THREAD) != 0) { try { plugin->uiIdle(); } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin uiIdle"); } } } idlePipe(); switch (fUiServer.getAndResetUiState()) { case CarlaExternalUI::UiNone: case CarlaExternalUI::UiShow: break; case CarlaExternalUI::UiCrashed: pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f); break; case CarlaExternalUI::UiHide: pHost->ui_closed(pHost->handle); fUiServer.stopPipeServer(1000); break; } } void uiSetParameterValue(const uint32_t index, const float value) { uint32_t rindex = index; if (CarlaPlugin* const plugin = _getPluginForParameterIndex(rindex)) { if (plugin->getHints() & PLUGIN_HAS_CUSTOM_UI) plugin->uiParameterChange(rindex, value); if (index >= kNumInParams || ! fUiServer.isPipeRunning()) return; uiServerCallback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, plugin->getId(), static_cast(rindex), 0, 0, value, nullptr); } } void idlePipe() { if (! fUiServer.isPipeRunning()) return; fUiServer.idlePipe(); char tmpBuf[STR_MAX+1]; carla_zeroChars(tmpBuf, STR_MAX+1); const CarlaMutexLocker cml(fUiServer.getPipeLock()); const CarlaScopedLocale csl; const EngineTimeInfo& timeInfo(pData->timeInfo); // ------------------------------------------------------------------------------------------------------------ // send engine info CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage("runtime-info"),); std::snprintf(tmpBuf, STR_MAX, "%.12g:0\n", static_cast(getDSPLoad())); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); fUiServer.flushMessages(); // ------------------------------------------------------------------------------------------------------------ // send transport CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage("transport"),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(timeInfo.playing ? "true\n" : "false\n"),); if (timeInfo.bbt.valid) { std::snprintf(tmpBuf, STR_MAX, P_UINT64 ":%i:%i:%i\n", timeInfo.frame, timeInfo.bbt.bar, timeInfo.bbt.beat, static_cast(timeInfo.bbt.tick + 0.5)); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%.12g\n", timeInfo.bbt.beatsPerMinute); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); } else { std::snprintf(tmpBuf, STR_MAX, P_UINT64 ":0:0:0\n", timeInfo.frame); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("0.0\n"),); } fUiServer.flushMessages(); // ------------------------------------------------------------------------------------------------------------ // send peaks and param outputs for all plugins for (uint i=0; i < pData->curPluginCount; ++i) { const EnginePluginData& plugData(pData->plugins[i]); const CarlaPlugin* const plugin(pData->plugins[i].plugin); std::snprintf(tmpBuf, STR_MAX, "PEAKS_%i\n", i); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%.12g:%.12g:%.12g:%.12g\n", static_cast(plugData.peaks[0]), static_cast(plugData.peaks[1]), static_cast(plugData.peaks[2]), static_cast(plugData.peaks[3])); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); fUiServer.flushMessages(); for (uint32_t j=0, count=plugin->getParameterCount(); j < count; ++j) { if (! plugin->isParameterOutput(j)) continue; std::snprintf(tmpBuf, STR_MAX, "PARAMVAL_%u:%u\n", i, j); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%.12g\n", static_cast(plugin->getParameterValue(j))); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); fUiServer.flushMessages(); } } } // ------------------------------------------------------------------- // Plugin state calls char* getState() const { MemoryOutputStream out; saveProjectInternal(out); return strdup(out.toString().toRawUTF8()); } void setState(const char* const data) { // remove all plugins from UI side for (uint i=0, count=pData->curPluginCount; i < count; ++i) CarlaEngine::callback(true, true, ENGINE_CALLBACK_PLUGIN_REMOVED, count-i-1, 0, 0, 0, 0.0f, nullptr); // remove all plugins from backend, no lock fIsRunning = false; removeAllPlugins(); fIsRunning = true; // stopped during removeAllPlugins() if (! pData->thread.isThreadRunning()) pData->thread.startThread(); fOptionsForced = true; const String state(data); XmlDocument xml(state); loadProjectInternal(xml); reloadFromUI(); } // ------------------------------------------------------------------- public: #define handlePtr ((CarlaEngineNative*)handle) static NativePluginHandle _instantiateRack(const NativeHostDescriptor* host) { return new CarlaEngineNative(host, false, true); } static NativePluginHandle _instantiateRackNoMidiOut(const NativeHostDescriptor* host) { return new CarlaEngineNative(host, false, false); } static NativePluginHandle _instantiatePatchbay(const NativeHostDescriptor* host) { return new CarlaEngineNative(host, true, true); } static NativePluginHandle _instantiatePatchbay3s(const NativeHostDescriptor* host) { return new CarlaEngineNative(host, true, true, 3, 2); } static NativePluginHandle _instantiatePatchbay16(const NativeHostDescriptor* host) { return new CarlaEngineNative(host, true, true, 16, 16); } static NativePluginHandle _instantiatePatchbay32(const NativeHostDescriptor* host) { return new CarlaEngineNative(host, true, true, 32, 32); } static NativePluginHandle _instantiatePatchbay64(const NativeHostDescriptor* host) { return new CarlaEngineNative(host, true, true, 64, 64); } static NativePluginHandle _instantiatePatchbayCV(const NativeHostDescriptor* host) { return new CarlaEngineNative(host, true, true, 2, 2, 5, 5); } static void _cleanup(NativePluginHandle handle) { delete handlePtr; } static uint32_t _get_parameter_count(NativePluginHandle handle) { return handlePtr->getParameterCount(); } static const NativeParameter* _get_parameter_info(NativePluginHandle handle, uint32_t index) { return handlePtr->getParameterInfo(index); } static float _get_parameter_value(NativePluginHandle handle, uint32_t index) { return handlePtr->getParameterValue(index); } static void _set_parameter_value(NativePluginHandle handle, uint32_t index, float value) { handlePtr->setParameterValue(index, value); } static void _ui_show(NativePluginHandle handle, bool show) { handlePtr->uiShow(show); } static void _ui_idle(NativePluginHandle handle) { handlePtr->uiIdle(); } static void _ui_set_parameter_value(NativePluginHandle handle, uint32_t index, float value) { handlePtr->uiSetParameterValue(index, value); } static void _activate(NativePluginHandle handle) { handlePtr->activate(); } static void _deactivate(NativePluginHandle handle) { handlePtr->deactivate(); } // FIXME for v3.0, use const for the input buffer static void _process(NativePluginHandle handle, float** inBuffer, float** outBuffer, const uint32_t frames, const NativeMidiEvent* midiEvents, uint32_t midiEventCount) { handlePtr->process(inBuffer, outBuffer, frames, midiEvents, midiEventCount); } static char* _get_state(NativePluginHandle handle) { return handlePtr->getState(); } static void _set_state(NativePluginHandle handle, const char* data) { handlePtr->setState(data); } static intptr_t _dispatcher(NativePluginHandle handle, NativePluginDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt) { switch(opcode) { case NATIVE_PLUGIN_OPCODE_NULL: return 0; case NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED: CARLA_SAFE_ASSERT_RETURN(value > 0, 0); handlePtr->bufferSizeChanged(static_cast(value)); return 0; case NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED: CARLA_SAFE_ASSERT_RETURN(opt > 0.0f, 0); handlePtr->sampleRateChanged(static_cast(opt)); return 0; case NATIVE_PLUGIN_OPCODE_OFFLINE_CHANGED: handlePtr->offlineModeChanged(value != 0); return 0; case NATIVE_PLUGIN_OPCODE_UI_NAME_CHANGED: //handlePtr->uiNameChanged(static_cast(ptr)); return 0; case NATIVE_PLUGIN_OPCODE_GET_INTERNAL_HANDLE: { CarlaEngineNative* const engine = handlePtr; return (intptr_t)(CarlaEngine*)engine; } case NATIVE_PLUGIN_OPCODE_IDLE: //handlePtr->idle(); return 0; } return 0; // unused (void)index; (void)ptr; } // ------------------------------------------------------------------- static void _ui_server_callback(void* handle, EngineCallbackOpcode action, uint pluginId, int value1, int value2, int value3, float valuef, const char* valueStr) { handlePtr->uiServerCallback(action, pluginId, value1, value2, value3, valuef, valueStr); } static const char* _ui_file_callback(void* handle, FileCallbackOpcode action, bool isDir, const char* title, const char* filter) { return handlePtr->uiFileCallback(action, isDir, title, filter); } // ------------------------------------------------------------------- #undef handlePtr private: const NativeHostDescriptor* const pHost; #ifdef USE_JUCE_MESSAGE_THREAD const bool kNeedsJuceMsgThread; const juce::SharedResourcePointer fJuceMsgThread; #endif const bool kIsPatchbay; // rack if false const bool kHasMidiOut; bool fIsActive, fIsRunning; CarlaEngineNativeUI fUiServer; float fParameters[kNumInParams+kNumOutParams]; bool fOptionsForced; CarlaPlugin* _getPluginForParameterIndex(uint32_t& index) const noexcept { if (pData->curPluginCount == 0 || pData->plugins == nullptr) return nullptr; CarlaPlugin* plugin; for (uint32_t i=0; icurPluginCount; ++i) { plugin = pData->plugins[i].plugin; if (plugin == nullptr || ! plugin->isEnabled()) break; if (const uint32_t paramCount = plugin->getParameterCount()) { if (index >= paramCount) { index -= paramCount; continue; } return plugin; } } return nullptr; } bool _getRealIndexForPluginParameter(const uint32_t pluginId, uint32_t& rindex) const noexcept { if (pData->curPluginCount == 0 || pluginId >= pData->curPluginCount || pData->plugins == nullptr) return false; CarlaPlugin* plugin; for (uint32_t i=0; iplugins[i].plugin; if (plugin == nullptr || ! plugin->isEnabled()) return false; rindex += plugin->getParameterCount(); } if (rindex >= kNumInParams) return false; return true; } CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNative) }; // ----------------------------------------------------------------------- bool CarlaEngineNativeUI::msgReceived(const char* const msg) noexcept { if (CarlaExternalUI::msgReceived(msg)) return true; bool ok = true; if (std::strcmp(msg, "set_engine_option") == 0) { uint32_t option; int32_t value; const char* valueStr = nullptr; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(option), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(value), true); readNextLineAsString(valueStr, false); // can be null try { fEngine->setOption(static_cast(option), value, valueStr); } CARLA_SAFE_EXCEPTION("setOption"); } else if (std::strcmp(msg, "clear_engine_xruns") == 0) { fEngine->clearXruns(); } else if (std::strcmp(msg, "cancel_engine_action") == 0) { fEngine->setActionCanceled(true); } else if (std::strcmp(msg, "load_file") == 0) { const char* filename; CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename, false), true); try { ok = fEngine->loadFile(filename); } CARLA_SAFE_EXCEPTION("loadFile"); } else if (std::strcmp(msg, "load_project") == 0) { const char* filename; CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename, false), true); try { ok = fEngine->loadProject(filename, true); } CARLA_SAFE_EXCEPTION("loadProject"); } else if (std::strcmp(msg, "save_project") == 0) { const char* filename; CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename, false), true); try { ok = fEngine->saveProject(filename, true); } CARLA_SAFE_EXCEPTION("saveProject"); } else if (std::strcmp(msg, "clear_project_filename") == 0) { fEngine->clearCurrentProjectFilename(); } else if (std::strcmp(msg, "patchbay_connect") == 0) { bool external; uint32_t groupA, portA, groupB, portB; CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(external), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(groupA), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(portA), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(groupB), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(portB), true); try { ok = fEngine->patchbayConnect(external, groupA, portA, groupB, portB); } CARLA_SAFE_EXCEPTION("patchbayConnect"); } else if (std::strcmp(msg, "patchbay_disconnect") == 0) { bool external; uint32_t connectionId; CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(external), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(connectionId), true); try { ok = fEngine->patchbayDisconnect(external, connectionId); } CARLA_SAFE_EXCEPTION("patchbayDisconnect"); } else if (std::strcmp(msg, "patchbay_refresh") == 0) { bool external; CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(external), true); try { ok = fEngine->patchbayRefresh(true, false, external); } CARLA_SAFE_EXCEPTION("patchbayRefresh"); } else if (std::strcmp(msg, "transport_play") == 0) { fEngine->transportPlay(); } else if (std::strcmp(msg, "transport_pause") == 0) { fEngine->transportPause(); } else if (std::strcmp(msg, "transport_bpm") == 0) { double bpm; CARLA_SAFE_ASSERT_RETURN(readNextLineAsDouble(bpm), true); fEngine->transportBPM(bpm); } else if (std::strcmp(msg, "transport_relocate") == 0) { uint64_t frame; CARLA_SAFE_ASSERT_RETURN(readNextLineAsULong(frame), true); fEngine->transportRelocate(frame); } else if (std::strcmp(msg, "add_plugin") == 0) { uint32_t btype, ptype; const char* filename = nullptr; const char* name; const char* label; int64_t uniqueId; uint options; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(btype), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(ptype), true); readNextLineAsString(filename, true); // can be null CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(name, true), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(label, true), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsLong(uniqueId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(options), true); if (filename != nullptr && std::strcmp(filename, "(null)") == 0) { delete[] filename; filename = nullptr; } if (std::strcmp(name, "(null)") == 0) { delete[] name; name = nullptr; } ok = fEngine->addPlugin(static_cast(btype), static_cast(ptype), filename, name, label, uniqueId, nullptr, options); if (filename != nullptr) delete[] filename; if (name != nullptr) delete[] name; delete[] label; fEngine->reloadFromUI(); } else if (std::strcmp(msg, "remove_plugin") == 0) { uint32_t pluginId; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); ok = fEngine->removePlugin(pluginId); fEngine->reloadFromUI(); } else if (std::strcmp(msg, "remove_all_plugins") == 0) { ok = fEngine->removeAllPlugins(); fEngine->reloadFromUI(); } else if (std::strcmp(msg, "rename_plugin") == 0) { uint32_t pluginId; const char* newName; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(newName, false), true); ok = fEngine->renamePlugin(pluginId, newName); } else if (std::strcmp(msg, "clone_plugin") == 0) { uint32_t pluginId; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); ok = fEngine->clonePlugin(pluginId); } else if (std::strcmp(msg, "replace_plugin") == 0) { uint32_t pluginId; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); ok = fEngine->replacePlugin(pluginId); } else if (std::strcmp(msg, "switch_plugins") == 0) { uint32_t pluginIdA, pluginIdB; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginIdA), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginIdB), true); ok = fEngine->switchPlugins(pluginIdA, pluginIdB); fEngine->reloadFromUI(); } else if (std::strcmp(msg, "load_plugin_state") == 0) { uint32_t pluginId; const char* filename; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename, false), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) { plugin->loadStateFromFile(filename); _updateParamValues(plugin, pluginId, false, true); } } else if (std::strcmp(msg, "save_plugin_state") == 0) { uint32_t pluginId; const char* filename; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename, false), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->saveStateToFile(filename); } else if (std::strcmp(msg, "set_option") == 0) { uint32_t pluginId, option; bool yesNo; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(option), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(yesNo), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->setOption(option, yesNo, false); } else if (std::strcmp(msg, "set_active") == 0) { uint32_t pluginId; bool onOff; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(onOff), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->setActive(onOff, true, false); } else if (std::strcmp(msg, "set_drywet") == 0) { uint32_t pluginId; float value; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->setDryWet(value, true, false); } else if (std::strcmp(msg, "set_volume") == 0) { uint32_t pluginId; float value; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->setVolume(value, true, false); } else if (std::strcmp(msg, "set_balance_left") == 0) { uint32_t pluginId; float value; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->setBalanceLeft(value, true, false); } else if (std::strcmp(msg, "set_balance_right") == 0) { uint32_t pluginId; float value; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->setBalanceRight(value, true, false); } else if (std::strcmp(msg, "set_panning") == 0) { uint32_t pluginId; float value; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->setPanning(value, true, false); } else if (std::strcmp(msg, "set_ctrl_channel") == 0) { uint32_t pluginId; int32_t channel; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(channel), true); CARLA_SAFE_ASSERT_RETURN(channel >= -1 && channel < MAX_MIDI_CHANNELS, true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->setCtrlChannel(int8_t(channel), true, false); } else if (std::strcmp(msg, "set_parameter_value") == 0) { uint32_t pluginId, parameterId; float value; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) { plugin->setParameterValue(parameterId, value, true, true, false); fEngine->setParameterValueFromUI(pluginId, parameterId, value); } } else if (std::strcmp(msg, "set_parameter_midi_channel") == 0) { uint32_t pluginId, parameterId, channel; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(channel), true); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->setParameterMidiChannel(parameterId, static_cast(channel), true, false); } else if (std::strcmp(msg, "set_parameter_mapped_control_index") == 0) { uint32_t pluginId, parameterId; int32_t ctrl; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(ctrl), true); CARLA_SAFE_ASSERT_RETURN(ctrl >= CONTROL_INDEX_NONE && ctrl <= CONTROL_INDEX_MAX_ALLOWED, true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->setParameterMappedControlIndex(parameterId, static_cast(ctrl), true, false); } else if (std::strcmp(msg, "set_parameter_mapped_range") == 0) { uint32_t pluginId, parameterId; float minimum, maximum; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(minimum), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(maximum), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->setParameterMappedRange(parameterId, minimum, maximum, true, false); } else if (std::strcmp(msg, "set_parameter_touch") == 0) { uint32_t pluginId, parameterId; bool touching; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(touching), true); if (fEngine->getPlugin(pluginId) != nullptr) fEngine->setParameterTouchFromUI(pluginId, parameterId, touching); } else if (std::strcmp(msg, "set_program") == 0) { uint32_t pluginId; int32_t index; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) { plugin->setProgram(index, true, true, false); _updateParamValues(plugin, pluginId, true, true); } } else if (std::strcmp(msg, "set_midi_program") == 0) { uint32_t pluginId; int32_t index; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) { plugin->setMidiProgram(index, true, true, false); _updateParamValues(plugin, pluginId, true, true); } } else if (std::strcmp(msg, "set_custom_data") == 0) { uint32_t pluginId; const char* type; const char* key; const char* value; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(type, true), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(key, true), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(value, false), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->setCustomData(type, key, value, true); delete[] type; delete[] key; } else if (std::strcmp(msg, "set_chunk_data") == 0) { uint32_t pluginId; const char* cdata; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(cdata, false), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) { std::vector chunk(carla_getChunkFromBase64String(cdata)); #ifdef CARLA_PROPER_CPP11_SUPPORT plugin->setChunkData(chunk.data(), chunk.size()); #else plugin->setChunkData(&chunk.front(), chunk.size()); #endif _updateParamValues(plugin, pluginId, false, true); } } else if (std::strcmp(msg, "prepare_for_save") == 0) { uint32_t pluginId; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->prepareForSave(); } else if (std::strcmp(msg, "reset_parameters") == 0) { uint32_t pluginId; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) { plugin->resetParameters(); _updateParamValues(plugin, pluginId, false, true); } } else if (std::strcmp(msg, "randomize_parameters") == 0) { uint32_t pluginId; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) { plugin->randomizeParameters(); _updateParamValues(plugin, pluginId, false, true); } } else if (std::strcmp(msg, "send_midi_note") == 0) { uint32_t pluginId, channel, note, velocity; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(channel), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(note), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(velocity), true); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, true); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_VALUE, true); CARLA_SAFE_ASSERT_RETURN(velocity < MAX_MIDI_VALUE, true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->sendMidiSingleNote(static_cast(channel), static_cast(note), static_cast(velocity), true, true, false); } else if (std::strcmp(msg, "show_custom_ui") == 0) { uint32_t pluginId; bool yesNo; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(yesNo), true); if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) plugin->showCustomUI(yesNo); } else { carla_stderr("CarlaEngineNativeUI::msgReceived : %s", msg); return false; } if (! ok) { const CarlaMutexLocker cml(getPipeLock()); if (writeMessage("error\n", 6) && writeAndFixMessage(fEngine->getLastError())) flushMessages(); } return true; } void CarlaEngineNativeUI::_updateParamValues(CarlaPlugin* const plugin, const uint32_t pluginId, const bool sendCallback, const bool sendPluginHost) const noexcept { float value; for (uint32_t i=0, count=plugin->getParameterCount(); igetParameterValue(i); if (sendCallback) { fEngine->callback(true, true, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pluginId, static_cast(i), 0, 0, value, nullptr); } if (sendPluginHost) { carla_stdout("_updateParamValues"); fEngine->setParameterValueFromUI(pluginId, i, value); } } } // ----------------------------------------------------------------------- static const NativePluginDescriptor carlaRackDesc = { /* category */ NATIVE_PLUGIN_CATEGORY_OTHER, /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH |NATIVE_PLUGIN_HAS_UI |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD |NATIVE_PLUGIN_USES_STATE |NATIVE_PLUGIN_USES_TIME), /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING), /* audioIns */ 2, /* audioOuts */ 2, /* midiIns */ 1, /* midiOuts */ 1, /* paramIns */ kNumInParams, /* paramOuts */ kNumOutParams, /* name */ "Carla-Rack", /* label */ "carlarack", /* maker */ "falkTX", /* copyright */ "GNU GPL v2+", CarlaEngineNative::_instantiateRack, CarlaEngineNative::_cleanup, CarlaEngineNative::_get_parameter_count, CarlaEngineNative::_get_parameter_info, CarlaEngineNative::_get_parameter_value, /* _get_midi_program_count */ nullptr, /* _get_midi_program_info */ nullptr, CarlaEngineNative::_set_parameter_value, /* _set_midi_program */ nullptr, /* _set_custom_data */ nullptr, CarlaEngineNative::_ui_show, CarlaEngineNative::_ui_idle, CarlaEngineNative::_ui_set_parameter_value, /* _ui_set_midi_program */ nullptr, /* _ui_set_custom_data */ nullptr, CarlaEngineNative::_activate, CarlaEngineNative::_deactivate, CarlaEngineNative::_process, CarlaEngineNative::_get_state, CarlaEngineNative::_set_state, CarlaEngineNative::_dispatcher, /* _render_inline_dsplay */ nullptr, /* cvIns */ 0, /* cvOuts */ 0, /* _get_buffer_port_name */ nullptr, /* _get_buffer_port_range */ nullptr }; static const NativePluginDescriptor carlaRackNoMidiOutDesc = { /* category */ NATIVE_PLUGIN_CATEGORY_OTHER, /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH |NATIVE_PLUGIN_HAS_UI |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD |NATIVE_PLUGIN_USES_STATE |NATIVE_PLUGIN_USES_TIME), /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING), /* audioIns */ 2, /* audioOuts */ 2, /* midiIns */ 1, /* midiOuts */ 0, /* paramIns */ kNumInParams, /* paramOuts */ kNumOutParams, /* name */ "Carla-Rack (no midi out)", /* label */ "carlarack-nomidiout", /* maker */ "falkTX", /* copyright */ "GNU GPL v2+", CarlaEngineNative::_instantiateRackNoMidiOut, CarlaEngineNative::_cleanup, CarlaEngineNative::_get_parameter_count, CarlaEngineNative::_get_parameter_info, CarlaEngineNative::_get_parameter_value, /* _get_midi_program_count */ nullptr, /* _get_midi_program_info */ nullptr, CarlaEngineNative::_set_parameter_value, /* _set_midi_program */ nullptr, /* _set_custom_data */ nullptr, CarlaEngineNative::_ui_show, CarlaEngineNative::_ui_idle, CarlaEngineNative::_ui_set_parameter_value, /* _ui_set_midi_program */ nullptr, /* _ui_set_custom_data */ nullptr, CarlaEngineNative::_activate, CarlaEngineNative::_deactivate, CarlaEngineNative::_process, CarlaEngineNative::_get_state, CarlaEngineNative::_set_state, CarlaEngineNative::_dispatcher, /* _render_inline_dsplay */ nullptr, /* cvIns */ 0, /* cvOuts */ 0, /* _get_buffer_port_name */ nullptr, /* _get_buffer_port_range */ nullptr }; static const NativePluginDescriptor carlaPatchbayDesc = { /* category */ NATIVE_PLUGIN_CATEGORY_OTHER, /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH |NATIVE_PLUGIN_HAS_UI |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD |NATIVE_PLUGIN_USES_STATE |NATIVE_PLUGIN_USES_TIME), /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING), /* audioIns */ 2, /* audioOuts */ 2, /* midiIns */ 1, /* midiOuts */ 1, /* paramIns */ kNumInParams, /* paramOuts */ kNumOutParams, /* name */ "Carla-Patchbay", /* label */ "carlapatchbay", /* maker */ "falkTX", /* copyright */ "GNU GPL v2+", CarlaEngineNative::_instantiatePatchbay, CarlaEngineNative::_cleanup, CarlaEngineNative::_get_parameter_count, CarlaEngineNative::_get_parameter_info, CarlaEngineNative::_get_parameter_value, /* _get_midi_program_count */ nullptr, /* _get_midi_program_info */ nullptr, CarlaEngineNative::_set_parameter_value, /* _set_midi_program */ nullptr, /* _set_custom_data */ nullptr, CarlaEngineNative::_ui_show, CarlaEngineNative::_ui_idle, CarlaEngineNative::_ui_set_parameter_value, /* _ui_set_midi_program */ nullptr, /* _ui_set_custom_data */ nullptr, CarlaEngineNative::_activate, CarlaEngineNative::_deactivate, CarlaEngineNative::_process, CarlaEngineNative::_get_state, CarlaEngineNative::_set_state, CarlaEngineNative::_dispatcher, /* _render_inline_dsplay */ nullptr, /* cvIns */ 0, /* cvOuts */ 0, /* _get_buffer_port_name */ nullptr, /* _get_buffer_port_range */ nullptr }; static const NativePluginDescriptor carlaPatchbay3sDesc = { /* category */ NATIVE_PLUGIN_CATEGORY_OTHER, /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH |NATIVE_PLUGIN_HAS_UI |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD |NATIVE_PLUGIN_USES_STATE |NATIVE_PLUGIN_USES_TIME), /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING), /* audioIns */ 3, /* audioOuts */ 2, /* midiIns */ 1, /* midiOuts */ 1, /* paramIns */ kNumInParams, /* paramOuts */ kNumOutParams, /* name */ "Carla-Patchbay (sidechain)", /* label */ "carlapatchbay3s", /* maker */ "falkTX", /* copyright */ "GNU GPL v2+", CarlaEngineNative::_instantiatePatchbay3s, CarlaEngineNative::_cleanup, CarlaEngineNative::_get_parameter_count, CarlaEngineNative::_get_parameter_info, CarlaEngineNative::_get_parameter_value, /* _get_midi_program_count */ nullptr, /* _get_midi_program_info */ nullptr, CarlaEngineNative::_set_parameter_value, /* _set_midi_program */ nullptr, /* _set_custom_data */ nullptr, CarlaEngineNative::_ui_show, CarlaEngineNative::_ui_idle, CarlaEngineNative::_ui_set_parameter_value, /* _ui_set_midi_program */ nullptr, /* _ui_set_custom_data */ nullptr, CarlaEngineNative::_activate, CarlaEngineNative::_deactivate, CarlaEngineNative::_process, CarlaEngineNative::_get_state, CarlaEngineNative::_set_state, CarlaEngineNative::_dispatcher, /* _render_inline_dsplay */ nullptr, /* cvIns */ 0, /* cvOuts */ 0, /* _get_buffer_port_name */ nullptr, /* _get_buffer_port_range */ nullptr }; static const NativePluginDescriptor carlaPatchbay16Desc = { /* category */ NATIVE_PLUGIN_CATEGORY_OTHER, /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH |NATIVE_PLUGIN_HAS_UI |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD |NATIVE_PLUGIN_USES_STATE |NATIVE_PLUGIN_USES_TIME), /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING), /* audioIns */ 16, /* audioOuts */ 16, /* midiIns */ 1, /* midiOuts */ 1, /* paramIns */ kNumInParams, /* paramOuts */ kNumOutParams, /* name */ "Carla-Patchbay (16chan)", /* label */ "carlapatchbay16", /* maker */ "falkTX", /* copyright */ "GNU GPL v2+", CarlaEngineNative::_instantiatePatchbay16, CarlaEngineNative::_cleanup, CarlaEngineNative::_get_parameter_count, CarlaEngineNative::_get_parameter_info, CarlaEngineNative::_get_parameter_value, /* _get_midi_program_count */ nullptr, /* _get_midi_program_info */ nullptr, CarlaEngineNative::_set_parameter_value, /* _set_midi_program */ nullptr, /* _set_custom_data */ nullptr, CarlaEngineNative::_ui_show, CarlaEngineNative::_ui_idle, CarlaEngineNative::_ui_set_parameter_value, /* _ui_set_midi_program */ nullptr, /* _ui_set_custom_data */ nullptr, CarlaEngineNative::_activate, CarlaEngineNative::_deactivate, CarlaEngineNative::_process, CarlaEngineNative::_get_state, CarlaEngineNative::_set_state, CarlaEngineNative::_dispatcher, /* _render_inline_dsplay */ nullptr, /* cvIns */ 0, /* cvOuts */ 0, /* _get_buffer_port_name */ nullptr, /* _get_buffer_port_range */ nullptr }; static const NativePluginDescriptor carlaPatchbay32Desc = { /* category */ NATIVE_PLUGIN_CATEGORY_OTHER, /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH |NATIVE_PLUGIN_HAS_UI |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD |NATIVE_PLUGIN_USES_STATE |NATIVE_PLUGIN_USES_TIME), /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING), /* audioIns */ 32, /* audioOuts */ 32, /* midiIns */ 1, /* midiOuts */ 1, /* paramIns */ kNumInParams, /* paramOuts */ kNumOutParams, /* name */ "Carla-Patchbay (32chan)", /* label */ "carlapatchbay32", /* maker */ "falkTX", /* copyright */ "GNU GPL v2+", CarlaEngineNative::_instantiatePatchbay32, CarlaEngineNative::_cleanup, CarlaEngineNative::_get_parameter_count, CarlaEngineNative::_get_parameter_info, CarlaEngineNative::_get_parameter_value, /* _get_midi_program_count */ nullptr, /* _get_midi_program_info */ nullptr, CarlaEngineNative::_set_parameter_value, /* _set_midi_program */ nullptr, /* _set_custom_data */ nullptr, CarlaEngineNative::_ui_show, CarlaEngineNative::_ui_idle, CarlaEngineNative::_ui_set_parameter_value, /* _ui_set_midi_program */ nullptr, /* _ui_set_custom_data */ nullptr, CarlaEngineNative::_activate, CarlaEngineNative::_deactivate, CarlaEngineNative::_process, CarlaEngineNative::_get_state, CarlaEngineNative::_set_state, CarlaEngineNative::_dispatcher, /* _render_inline_dsplay */ nullptr, /* cvIns */ 0, /* cvOuts */ 0, /* _get_buffer_port_name */ nullptr, /* _get_buffer_port_range */ nullptr }; static const NativePluginDescriptor carlaPatchbay64Desc = { /* category */ NATIVE_PLUGIN_CATEGORY_OTHER, /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH |NATIVE_PLUGIN_HAS_UI |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD |NATIVE_PLUGIN_USES_STATE |NATIVE_PLUGIN_USES_TIME), /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING), /* audioIns */ 64, /* audioOuts */ 64, /* midiIns */ 1, /* midiOuts */ 1, /* paramIns */ kNumInParams, /* paramOuts */ kNumOutParams, /* name */ "Carla-Patchbay (64chan)", /* label */ "carlapatchbay64", /* maker */ "falkTX", /* copyright */ "GNU GPL v2+", CarlaEngineNative::_instantiatePatchbay64, CarlaEngineNative::_cleanup, CarlaEngineNative::_get_parameter_count, CarlaEngineNative::_get_parameter_info, CarlaEngineNative::_get_parameter_value, /* _get_midi_program_count */ nullptr, /* _get_midi_program_info */ nullptr, CarlaEngineNative::_set_parameter_value, /* _set_midi_program */ nullptr, /* _set_custom_data */ nullptr, CarlaEngineNative::_ui_show, CarlaEngineNative::_ui_idle, CarlaEngineNative::_ui_set_parameter_value, /* _ui_set_midi_program */ nullptr, /* _ui_set_custom_data */ nullptr, CarlaEngineNative::_activate, CarlaEngineNative::_deactivate, CarlaEngineNative::_process, CarlaEngineNative::_get_state, CarlaEngineNative::_set_state, CarlaEngineNative::_dispatcher, /* _render_inline_dsplay */ nullptr, /* cvIns */ 0, /* cvOuts */ 0, /* _get_buffer_port_name */ nullptr, /* _get_buffer_port_range */ nullptr }; static const NativePluginDescriptor carlaPatchbayCVDesc = { /* category */ NATIVE_PLUGIN_CATEGORY_OTHER, /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH |NATIVE_PLUGIN_HAS_UI |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD |NATIVE_PLUGIN_USES_CONTROL_VOLTAGE |NATIVE_PLUGIN_USES_STATE |NATIVE_PLUGIN_USES_TIME), /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING), /* audioIns */ 2, /* audioOuts */ 2, /* midiIns */ 1, /* midiOuts */ 1, /* paramIns */ kNumInParams, /* paramOuts */ kNumOutParams, /* name */ "Carla-Patchbay (CV)", /* label */ "carlapatchbaycv", /* maker */ "falkTX", /* copyright */ "GNU GPL v2+", CarlaEngineNative::_instantiatePatchbayCV, CarlaEngineNative::_cleanup, CarlaEngineNative::_get_parameter_count, CarlaEngineNative::_get_parameter_info, CarlaEngineNative::_get_parameter_value, /* _get_midi_program_count */ nullptr, /* _get_midi_program_info */ nullptr, CarlaEngineNative::_set_parameter_value, /* _set_midi_program */ nullptr, /* _set_custom_data */ nullptr, CarlaEngineNative::_ui_show, CarlaEngineNative::_ui_idle, CarlaEngineNative::_ui_set_parameter_value, /* _ui_set_midi_program */ nullptr, /* _ui_set_custom_data */ nullptr, CarlaEngineNative::_activate, CarlaEngineNative::_deactivate, CarlaEngineNative::_process, CarlaEngineNative::_get_state, CarlaEngineNative::_set_state, CarlaEngineNative::_dispatcher, /* _render_inline_dsplay */ nullptr, /* cvIns */ 5, /* cvOuts */ 5, /* _get_buffer_port_name */ nullptr, /* _get_buffer_port_range */ nullptr }; CARLA_BACKEND_END_NAMESPACE // ----------------------------------------------------------------------- CARLA_EXPORT void carla_register_native_plugin_carla(); void carla_register_native_plugin_carla() { CARLA_BACKEND_USE_NAMESPACE; carla_register_native_plugin(&carlaRackDesc); carla_register_native_plugin(&carlaRackNoMidiOutDesc); carla_register_native_plugin(&carlaPatchbayDesc); carla_register_native_plugin(&carlaPatchbay3sDesc); carla_register_native_plugin(&carlaPatchbay16Desc); carla_register_native_plugin(&carlaPatchbay32Desc); carla_register_native_plugin(&carlaPatchbay64Desc); carla_register_native_plugin(&carlaPatchbayCVDesc); } // ----------------------------------------------------------------------- const NativePluginDescriptor* carla_get_native_rack_plugin() { CARLA_BACKEND_USE_NAMESPACE; return &carlaRackDesc; } const NativePluginDescriptor* carla_get_native_patchbay_plugin() { CARLA_BACKEND_USE_NAMESPACE; return &carlaPatchbayDesc; } const NativePluginDescriptor* carla_get_native_patchbay16_plugin() { CARLA_BACKEND_USE_NAMESPACE; return &carlaPatchbay16Desc; } const NativePluginDescriptor* carla_get_native_patchbay32_plugin() { CARLA_BACKEND_USE_NAMESPACE; return &carlaPatchbay32Desc; } const NativePluginDescriptor* carla_get_native_patchbay64_plugin() { CARLA_BACKEND_USE_NAMESPACE; return &carlaPatchbay64Desc; } const NativePluginDescriptor* carla_get_native_patchbay_cv_plugin() { CARLA_BACKEND_USE_NAMESPACE; return &carlaPatchbayCVDesc; } // ----------------------------------------------------------------------- // Extra stuff for linking purposes #ifdef CARLA_PLUGIN_EXPORT CARLA_BACKEND_START_NAMESPACE CarlaEngine* CarlaEngine::newJack() { return nullptr; } # ifdef USING_JUCE CarlaEngine* CarlaEngine::newJuce(const AudioApi) { return nullptr; } uint CarlaEngine::getJuceApiCount() { return 0; } const char* CarlaEngine::getJuceApiName(const uint) { return nullptr; } const char* const* CarlaEngine::getJuceApiDeviceNames(const uint) { return nullptr; } const EngineDriverDeviceInfo* CarlaEngine::getJuceDeviceInfo(const uint, const char* const) { return nullptr; } bool CarlaEngine::showJuceDeviceControlPanel(const uint, const char* const) { return false; } # else CarlaEngine* CarlaEngine::newRtAudio(const AudioApi) { return nullptr; } uint CarlaEngine::getRtAudioApiCount() { return 0; } const char* CarlaEngine::getRtAudioApiName(const uint) { return nullptr; } const char* const* CarlaEngine::getRtAudioApiDeviceNames(const uint) { return nullptr; } const EngineDriverDeviceInfo* CarlaEngine::getRtAudioDeviceInfo(const uint, const char* const) { return nullptr; } # endif CARLA_BACKEND_END_NAMESPACE #define CARLA_PLUGIN_UI_CLASS_PREFIX EngineNative #include "CarlaHostCommon.cpp" #include "CarlaPluginUI.cpp" #include "CarlaDssiUtils.cpp" #include "CarlaMacUtils.cpp" #include "CarlaPatchbayUtils.cpp" #include "CarlaPipeUtils.cpp" #include "CarlaStateUtils.cpp" #endif // ----------------------------------------------------------------------- Carla-2.1/source/backend/engine/CarlaEngineOsc.cpp000066400000000000000000000143621364475620200220720ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaEngineOsc.hpp" #ifdef HAVE_LIBLO #include "CarlaEngine.hpp" CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- CarlaEngineOsc::CarlaEngineOsc(CarlaEngine* const engine) noexcept : fEngine(engine), fControlDataTCP(), fControlDataUDP(), fName(), fServerPathTCP(), fServerPathUDP(), fServerTCP(nullptr), fServerUDP(nullptr) { CARLA_SAFE_ASSERT(engine != nullptr); carla_debug("CarlaEngineOsc::CarlaEngineOsc(%p)", engine); } CarlaEngineOsc::~CarlaEngineOsc() noexcept { CARLA_SAFE_ASSERT(fName.isEmpty()); CARLA_SAFE_ASSERT(fServerPathTCP.isEmpty()); CARLA_SAFE_ASSERT(fServerPathUDP.isEmpty()); CARLA_SAFE_ASSERT(fServerTCP == nullptr); CARLA_SAFE_ASSERT(fServerUDP == nullptr); carla_debug("CarlaEngineOsc::~CarlaEngineOsc()"); } // ----------------------------------------------------------------------- void CarlaEngineOsc::init(const char* const name, int tcpPort, int udpPort) noexcept { CARLA_SAFE_ASSERT_RETURN(fName.isEmpty(),); CARLA_SAFE_ASSERT_RETURN(fServerPathTCP.isEmpty(),); CARLA_SAFE_ASSERT_RETURN(fServerPathUDP.isEmpty(),); CARLA_SAFE_ASSERT_RETURN(fServerTCP == nullptr,); CARLA_SAFE_ASSERT_RETURN(fServerUDP == nullptr,); CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); carla_debug("CarlaEngineOsc::init(\"%s\")", name); fName = name; fName.toBasic(); if (fEngine->getType() != kEngineTypePlugin) { const char* const tcpPortEnv = std::getenv("CARLA_OSC_TCP_PORT"); const char* const udpPortEnv = std::getenv("CARLA_OSC_UDP_PORT"); if (tcpPortEnv != nullptr) tcpPort = std::atoi(tcpPortEnv); if (udpPortEnv != nullptr) udpPort = std::atoi(udpPortEnv); } // port == 0 means to pick a random one // port < 0 will get osc disabled static const int kRetryAttempts = 5; // ---------------------------------------------------------------------------------------------------------------- if (tcpPort == 0) { for (int i=0; i < kRetryAttempts && fServerTCP == nullptr; ++i) fServerTCP = lo_server_new_with_proto(nullptr, LO_TCP, osc_error_handler_TCP); } else if (tcpPort >= 1024) { char strBuf[0xff]; for (int i=0; i < kRetryAttempts && tcpPort < 32767 && fServerTCP == nullptr; ++i, ++tcpPort) { std::snprintf(strBuf, 0xff-1, "%d", tcpPort); strBuf[0xff-1] = '\0'; fServerTCP = lo_server_new_with_proto(strBuf, LO_TCP, osc_error_handler_TCP); } } if (fServerTCP != nullptr) { if (char* const tmpServerPathTCP = lo_server_get_url(fServerTCP)) { fServerPathTCP = tmpServerPathTCP; fServerPathTCP += fName; std::free(tmpServerPathTCP); } lo_server_add_method(fServerTCP, nullptr, nullptr, osc_message_handler_TCP, this); carla_debug("OSC TCP server running and listening at %s", fServerPathTCP.buffer()); } // ---------------------------------------------------------------------------------------------------------------- if (udpPort == 0) { for (int i=0; i < kRetryAttempts && fServerUDP == nullptr; ++i) fServerUDP = lo_server_new_with_proto(nullptr, LO_UDP, osc_error_handler_UDP); } else if (udpPort >= 1024) { char strBuf[0xff]; for (int i=0; i < kRetryAttempts && udpPort < 32768 && fServerUDP == nullptr; ++i, ++udpPort) { std::snprintf(strBuf, 0xff-1, "%d", udpPort); strBuf[0xff-1] = '\0'; fServerUDP = lo_server_new_with_proto(strBuf, LO_UDP, osc_error_handler_UDP); } } if (fServerUDP != nullptr) { if (char* const tmpServerPathUDP = lo_server_get_url(fServerUDP)) { fServerPathUDP = tmpServerPathUDP; fServerPathUDP += fName; std::free(tmpServerPathUDP); } lo_server_add_method(fServerUDP, nullptr, nullptr, osc_message_handler_UDP, this); carla_debug("OSC UDP server running and listening at %s", fServerPathUDP.buffer()); } // ---------------------------------------------------------------------------------------------------------------- CARLA_SAFE_ASSERT(fName.isNotEmpty()); } void CarlaEngineOsc::idle() const noexcept { if (fServerTCP != nullptr) { for (;;) { try { if (lo_server_recv_noblock(fServerTCP, 0) == 0) break; } CARLA_SAFE_EXCEPTION_CONTINUE("OSC idle TCP") } } if (fServerUDP != nullptr) { for (;;) { try { if (lo_server_recv_noblock(fServerUDP, 0) == 0) break; } CARLA_SAFE_EXCEPTION_CONTINUE("OSC idle UDP") } } } void CarlaEngineOsc::close() noexcept { carla_debug("CarlaEngineOsc::close()"); if (fControlDataTCP.target != nullptr) sendExit(); fName.clear(); if (fServerTCP != nullptr) { lo_server_del_method(fServerTCP, nullptr, nullptr); lo_server_free(fServerTCP); fServerTCP = nullptr; } if (fServerUDP != nullptr) { lo_server_del_method(fServerUDP, nullptr, nullptr); lo_server_free(fServerUDP); fServerUDP = nullptr; } fServerPathTCP.clear(); fServerPathUDP.clear(); fControlDataTCP.clear(); fControlDataUDP.clear(); } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE #endif // HAVE_LIBLO Carla-2.1/source/backend/engine/CarlaEngineOsc.hpp000066400000000000000000000216531364475620200221000ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_ENGINE_OSC_HPP_INCLUDED #define CARLA_ENGINE_OSC_HPP_INCLUDED #include "CarlaDefines.h" #ifdef HAVE_LIBLO #include "CarlaBackend.h" #include "CarlaJuceUtils.hpp" #include "CarlaOscUtils.hpp" #include "CarlaString.hpp" #define CARLA_ENGINE_OSC_HANDLE_ARGS CarlaPlugin* const plugin, const int argc, const lo_arg* const* const argv, const char* const types #define CARLA_ENGINE_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ /* check argument count */ \ if (argc != argcToCompare) \ { \ carla_stderr("CarlaEngineOsc::%s() - argument count mismatch: %i != %i", __FUNCTION__, argc, argcToCompare); \ return 1; \ } \ if (argc > 0) \ { \ /* check for nullness */ \ if (types == nullptr || typesToCompare == nullptr) \ { \ carla_stderr("CarlaEngineOsc::%s() - argument types are null", __FUNCTION__); \ return 1; \ } \ /* check argument types */ \ if (std::strcmp(types, typesToCompare) != 0) \ { \ carla_stderr("CarlaEngineOsc::%s() - argument types mismatch: '%s' != '%s'", __FUNCTION__, types, typesToCompare); \ return 1; \ } \ } CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- class CarlaEngineOsc { public: CarlaEngineOsc(CarlaEngine* engine) noexcept; ~CarlaEngineOsc() noexcept; void init(const char* name, int tcpPort, int udpPort) noexcept; void idle() const noexcept; void close() noexcept; // ------------------------------------------------------------------- const CarlaString& getServerPathTCP() const noexcept { return fServerPathTCP; } const CarlaString& getServerPathUDP() const noexcept { return fServerPathUDP; } // ------------------------------------------------------------------- bool isControlRegisteredForTCP() const noexcept { return fControlDataTCP.target != nullptr; } bool isControlRegisteredForUDP() const noexcept { return fControlDataUDP.target != nullptr; } // ------------------------------------------------------------------- // TCP void sendCallback(EngineCallbackOpcode action, uint pluginId, int value1, int value2, int value3, float valuef, const char* valueStr) const noexcept; void sendPluginInfo(const CarlaPlugin* plugin) const noexcept; void sendPluginPortCount(const CarlaPlugin* plugin) const noexcept; void sendPluginParameterInfo(const CarlaPlugin* plugin, uint32_t index) const noexcept; void sendPluginDataCount(const CarlaPlugin* plugin) const noexcept; void sendPluginProgramCount(const CarlaPlugin* plugin) const noexcept; void sendPluginProgram(const CarlaPlugin* plugin, uint32_t index) const noexcept; void sendPluginMidiProgram(const CarlaPlugin* plugin, uint32_t index) const noexcept; void sendPluginCustomData(const CarlaPlugin* plugin, uint32_t index) const noexcept; void sendPluginInternalParameterValues(const CarlaPlugin* plugin) const noexcept; void sendPing() const noexcept; void sendResponse(int messageId, const char* error) const noexcept; void sendExit() const noexcept; // ------------------------------------------------------------------- // UDP void sendRuntimeInfo() const noexcept; void sendParameterValue(uint pluginId, uint32_t index, float value) const noexcept; void sendPeaks(uint pluginId, const float peaks[4]) const noexcept; // ------------------------------------------------------------------- private: CarlaEngine* const fEngine; // for carla-control CarlaOscData fControlDataTCP; CarlaOscData fControlDataUDP; CarlaString fName; CarlaString fServerPathTCP; CarlaString fServerPathUDP; lo_server fServerTCP; lo_server fServerUDP; // ------------------------------------------------------------------- int handleMessage(bool isTCP, const char* path, int argc, const lo_arg* const* argv, const char* types, lo_message msg); int handleMsgRegister(bool isTCP, int argc, const lo_arg* const* argv, const char* types); int handleMsgUnregister(bool isTCP, int argc, const lo_arg* const* argv, const char* types); int handleMsgControl(const char* method, int argc, const lo_arg* const* argv, const char* types); // Internal methods int handleMsgSetActive(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgSetDryWet(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgSetVolume(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgSetBalanceLeft(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgSetParameterMappedControlIndex(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgSetParameterMappedRange(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgSetParameterMidiChannel(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgNoteOn(CARLA_ENGINE_OSC_HANDLE_ARGS); int handleMsgNoteOff(CARLA_ENGINE_OSC_HANDLE_ARGS); // ----------------------------------------------------------------------- static void osc_error_handler_TCP(int num, const char* msg, const char* path) { carla_stderr("CarlaEngineOsc::osc_error_handler_TCP(%i, \"%s\", \"%s\")", num, msg, path); } static void osc_error_handler_UDP(int num, const char* msg, const char* path) { carla_stderr("CarlaEngineOsc::osc_error_handler_UDP(%i, \"%s\", \"%s\")", num, msg, path); } static int osc_message_handler_TCP(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* userData) { return ((CarlaEngineOsc*)userData)->handleMessage(true, path, argc, argv, types, msg); } static int osc_message_handler_UDP(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* userData) { return ((CarlaEngineOsc*)userData)->handleMessage(false, path, argc, argv, types, msg); } CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineOsc) }; // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE #endif // HAVE_LIBLO #endif // CARLA_ENGINE_OSC_HPP_INCLUDED Carla-2.1/source/backend/engine/CarlaEngineOscHandlers.cpp000066400000000000000000000607311364475620200235540ustar00rootroot00000000000000 /* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaEngineOsc.hpp" #ifdef HAVE_LIBLO #include "CarlaEngineInternal.hpp" #include "CarlaPlugin.hpp" #include "CarlaMIDI.h" #include CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- int CarlaEngineOsc::handleMessage(const bool isTCP, const char* const path, const int argc, const lo_arg* const* const argv, const char* const types, const lo_message msg) { CARLA_SAFE_ASSERT_RETURN(fName.isNotEmpty(), 1); CARLA_SAFE_ASSERT_RETURN(path != nullptr && path[0] != '\0', 1); #ifdef DEBUG if (std::strstr(path, "/bridge_pong") == nullptr) { carla_debug("CarlaEngineOsc::handleMessage(%s, \"%s\", %i, %p, \"%s\", %p)", bool2str(isTCP), path, argc, argv, types, msg); } #endif if (isTCP) { CARLA_SAFE_ASSERT_RETURN(fServerPathTCP.isNotEmpty(), 1); CARLA_SAFE_ASSERT_RETURN(fServerTCP != nullptr, 1); } else { CARLA_SAFE_ASSERT_RETURN(fServerPathUDP.isNotEmpty(), 1); CARLA_SAFE_ASSERT_RETURN(fServerUDP != nullptr, 1); } // Initial path check if (std::strcmp(path, "/register") == 0) return handleMsgRegister(isTCP, argc, argv, types); if (std::strcmp(path, "/unregister") == 0) return handleMsgUnregister(isTCP, argc, argv, types); if (std::strncmp(path, "/ctrl/", 6) == 0) { CARLA_SAFE_ASSERT_RETURN(isTCP, 1); return handleMsgControl(path + 6, argc, argv, types); } const std::size_t nameSize(fName.length()); // Check if message is for this client if (std::strlen(path) <= nameSize || std::strncmp(path+1, fName, nameSize) != 0) { carla_stderr("CarlaEngineOsc::handleMessage() - message not for this client -> '%s' != '/%s/'", path, fName.buffer()); return 1; } // Get plugin id from path, "/carla/23/method" -> 23 uint pluginId = 0; std::size_t offset; if (std::isdigit(path[nameSize+2])) { if (std::isdigit(path[nameSize+3])) { if (std::isdigit(path[nameSize+5])) { carla_stderr2("CarlaEngineOsc::handleMessage() - invalid plugin id, over 999? (value: \"%s\")", path+(nameSize+1)); return 1; } else if (std::isdigit(path[nameSize+4])) { // 3 digits, /xyz/method offset = 6; pluginId += uint(path[nameSize+2]-'0')*100; pluginId += uint(path[nameSize+3]-'0')*10; pluginId += uint(path[nameSize+4]-'0'); } else { // 2 digits, /xy/method offset = 5; pluginId += uint(path[nameSize+2]-'0')*10; pluginId += uint(path[nameSize+3]-'0'); } } else { // single digit, /x/method offset = 4; pluginId += uint(path[nameSize+2]-'0'); } } else { carla_stderr("CarlaEngineOsc::handleMessage() - invalid message '%s'", path); return 1; } if (pluginId > fEngine->getCurrentPluginCount()) { carla_stderr("CarlaEngineOsc::handleMessage() - failed to get plugin, wrong id '%i'", pluginId); return 0; } // Get plugin CarlaPlugin* const plugin(fEngine->getPluginUnchecked(pluginId)); if (plugin == nullptr || plugin->getId() != pluginId) { carla_stderr("CarlaEngineOsc::handleMessage() - invalid plugin id '%i', probably has been removed (path: '%s')", pluginId, path); return 0; } // Get method from path, "/Carla/i/method" -> "method" char method[32+1]; method[32] = '\0'; std::strncpy(method, path + (nameSize + offset), 32); if (method[0] == '\0') { carla_stderr("CarlaEngineOsc::handleMessage(%s, \"%s\", ...) - received message without method", bool2str(isTCP), path); return 0; } // Internal methods if (std::strcmp(method, "set_option") == 0) return 0; //handleMsgSetOption(plugin, argc, argv, types); // TODO if (std::strcmp(method, "set_active") == 0) return handleMsgSetActive(plugin, argc, argv, types); if (std::strcmp(method, "set_drywet") == 0) return handleMsgSetDryWet(plugin, argc, argv, types); if (std::strcmp(method, "set_volume") == 0) return handleMsgSetVolume(plugin, argc, argv, types); if (std::strcmp(method, "set_balance_left") == 0) return handleMsgSetBalanceLeft(plugin, argc, argv, types); if (std::strcmp(method, "set_balance_right") == 0) return handleMsgSetBalanceRight(plugin, argc, argv, types); if (std::strcmp(method, "set_panning") == 0) return handleMsgSetPanning(plugin, argc, argv, types); if (std::strcmp(method, "set_ctrl_channel") == 0) return 0; //handleMsgSetControlChannel(plugin, argc, argv, types); // TODO if (std::strcmp(method, "set_parameter_value") == 0) return handleMsgSetParameterValue(plugin, argc, argv, types); if (std::strcmp(method, "set_parameter_mapped_control_index") == 0) return handleMsgSetParameterMappedControlIndex(plugin, argc, argv, types); if (std::strcmp(method, "set_parameter_mapped_range") == 0) return handleMsgSetParameterMappedRange(plugin, argc, argv, types); if (std::strcmp(method, "set_parameter_midi_channel") == 0) return handleMsgSetParameterMidiChannel(plugin, argc, argv, types); if (std::strcmp(method, "set_program") == 0) return handleMsgSetProgram(plugin, argc, argv, types); if (std::strcmp(method, "set_midi_program") == 0) return handleMsgSetMidiProgram(plugin, argc, argv, types); if (std::strcmp(method, "set_custom_data") == 0) return 0; //handleMsgSetCustomData(plugin, argc, argv, types); // TODO if (std::strcmp(method, "set_chunk") == 0) return 0; //handleMsgSetChunk(plugin, argc, argv, types); // TODO if (std::strcmp(method, "note_on") == 0) return handleMsgNoteOn(plugin, argc, argv, types); if (std::strcmp(method, "note_off") == 0) return handleMsgNoteOff(plugin, argc, argv, types); // Send all other methods to plugins, TODO plugin->handleOscMessage(method, argc, argv, types, msg); return 0; } // ----------------------------------------------------------------------- int CarlaEngineOsc::handleMsgRegister(const bool isTCP, const int argc, const lo_arg* const* const argv, const char* const types) { carla_debug("CarlaEngineOsc::handleMsgRegister()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "s"); const char* const url = &argv[0]->s; const lo_address addr = lo_address_new_from_url(url); CarlaOscData& oscData(isTCP ? fControlDataTCP : fControlDataUDP); if (oscData.owner != nullptr) { carla_stderr("OSC backend already registered to %s", oscData.owner); char* const path = lo_url_get_path(url); char targetPath[std::strlen(path)+18]; std::strcpy(targetPath, path); std::strcat(targetPath, "/exit-error"); lo_send_from(addr, isTCP ? fServerTCP : fServerUDP, LO_TT_IMMEDIATE, targetPath, "s", "OSC already registered to another client"); free(path); } else { carla_stdout("OSC backend registered to %s", url); const char* const host = lo_address_get_hostname(addr); const char* const port = lo_address_get_port(addr); const lo_address target = lo_address_new_with_proto(isTCP ? LO_TCP : LO_UDP, host, port); oscData.owner = carla_strdup_safe(url); oscData.path = carla_strdup_free(lo_url_get_path(url)); oscData.target = target; if (isTCP) { const EngineOptions& opts(fEngine->getOptions()); fEngine->callback(false, true, ENGINE_CALLBACK_ENGINE_STARTED, fEngine->getCurrentPluginCount(), opts.processMode, opts.transportMode, static_cast(fEngine->getBufferSize()), static_cast(fEngine->getSampleRate()), fEngine->getCurrentDriverName()); for (uint i=0, count=fEngine->getCurrentPluginCount(); i < count; ++i) { CarlaPlugin* const plugin(fEngine->getPluginUnchecked(i)); CARLA_SAFE_ASSERT_CONTINUE(plugin != nullptr); fEngine->callback(false, true, ENGINE_CALLBACK_PLUGIN_ADDED, i, 0, 0, 0, 0.0f, plugin->getName()); } fEngine->patchbayRefresh(false, true, fEngine->pData->graph.isUsingExternalOSC()); } } lo_address_free(addr); return 0; } int CarlaEngineOsc::handleMsgUnregister(const bool isTCP, const int argc, const lo_arg* const* const argv, const char* const types) { carla_debug("CarlaEngineOsc::handleMsgUnregister()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "s"); CarlaOscData& oscData(isTCP ? fControlDataTCP : fControlDataUDP); if (oscData.owner == nullptr) { carla_stderr("OSC backend is not registered yet, unregister failed"); return 0; } const char* const url = &argv[0]->s; if (std::strcmp(oscData.owner, url) == 0) { carla_stdout("OSC client %s unregistered", url); oscData.clear(); return 0; } carla_stderr("OSC backend unregister failed, current owner %s does not match requested %s", oscData.owner, url); return 0; } int CarlaEngineOsc::handleMsgControl(const char* const method, const int argc, const lo_arg* const* const argv, const char* const types) { carla_debug("CarlaEngineOsc::handleMsgControl()"); CARLA_SAFE_ASSERT_RETURN(method != nullptr && method[0] != '\0', 0); CARLA_SAFE_ASSERT_RETURN(types != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(types[0] == 'i', 0); if (fControlDataTCP.owner == nullptr) { carla_stderr("OSC backend is not registered yet, control failed"); return 0; } const int32_t messageId = argv[0]->i; bool ok; #define CARLA_SAFE_ASSERT_RETURN_OSC_ERR(cond) \ if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); sendResponse(messageId, #cond); return 0; } /**/ if (std::strcmp(method, "clear_engine_xruns") == 0) { ok = true; fEngine->clearXruns(); } else if (std::strcmp(method, "cancel_engine_action") == 0) { ok = true; fEngine->setActionCanceled(true); } else if (std::strcmp(method, "patchbay_connect") == 0) { CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 6); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i'); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[2] == 'i'); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[3] == 'i'); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[4] == 'i'); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[5] == 'i'); const bool external = argv[1]->i != 0; const int32_t groupA = argv[2]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(groupA >= 0); const int32_t portA = argv[3]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(portA >= 0); const int32_t groupB = argv[4]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(groupB >= 0); const int32_t portB = argv[5]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(portB >= 0); ok = fEngine->patchbayConnect(external, static_cast(groupA), static_cast(portA), static_cast(groupB), static_cast(portB)); } else if (std::strcmp(method, "patchbay_disconnect") == 0) { CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 3); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i'); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[2] == 'i'); const bool external = argv[1]->i != 0; const int32_t connectionId = argv[2]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(connectionId >= 0); ok = fEngine->patchbayDisconnect(external, static_cast(connectionId)); } else if (std::strcmp(method, "patchbay_refresh") == 0) { CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 2); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i'); const bool external = argv[1]->i != 0; ok = fEngine->patchbayRefresh(false, true, external); } else if (std::strcmp(method, "transport_play") == 0) { ok = true; fEngine->transportPlay(); } else if (std::strcmp(method, "transport_pause") == 0) { ok = true; fEngine->transportPause(); } else if (std::strcmp(method, "transport_bpm") == 0) { CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 2); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'f'); const double bpm = argv[1]->f; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(bpm >= 0.0); ok = true; fEngine->transportBPM(bpm); } else if (std::strcmp(method, "transport_relocate") == 0) { CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 2); uint64_t frame; /**/ if (types[1] == 'i') { const int32_t i = argv[1]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(i >= 0); frame = static_cast(i); } else if (types[1] == 'h') { const int64_t h = argv[1]->h; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(h >= 0); frame = static_cast(h); } else { carla_stderr2("Wrong OSC type used for '%s'", method); sendResponse(messageId, "Wrong OSC type"); return 0; } ok = true; fEngine->transportRelocate(frame); } else if (std::strcmp(method, "add_plugin") == 0) { CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 8); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i'); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[2] == 'i'); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[3] == 's'); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[4] == 's'); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[5] == 's'); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[7] == 'i'); int32_t btype = argv[1]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(btype >= 0); const int32_t ptype = argv[2]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(ptype >= 0); // Force binary type to be native in some cases switch (ptype) { case PLUGIN_INTERNAL: case PLUGIN_LV2: case PLUGIN_SF2: case PLUGIN_SFZ: case PLUGIN_JACK: btype = BINARY_NATIVE; break; } const char* filename = &argv[3]->s; if (filename != nullptr && std::strcmp(filename, "(null)") == 0) filename = nullptr; const char* name = &argv[4]->s; if (name != nullptr && std::strcmp(name, "(null)") == 0) name = nullptr; const char* const label = &argv[5]->s; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(label != nullptr && label[0] != '\0'); int64_t uniqueId; /**/ if (types[6] == 'i') { uniqueId = argv[6]->i; } else if (types[6] == 'h') { uniqueId = argv[6]->h; } else { carla_stderr2("Wrong OSC type used for '%s' uniqueId", method); sendResponse(messageId, "Wrong OSC type"); return 0; } const int32_t options = argv[7]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(options >= 0); ok = fEngine->addPlugin(static_cast(btype), static_cast(ptype), filename, name, label, uniqueId, nullptr, static_cast(options)); } else if (std::strcmp(method, "remove_plugin") == 0) { CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 2); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i'); const int32_t id = argv[1]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(id >= 0); ok = fEngine->removePlugin(static_cast(id)); } else if (std::strcmp(method, "remove_all_plugins") == 0) { ok = fEngine->removeAllPlugins(); } else if (std::strcmp(method, "rename_plugin") == 0) { CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 3); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i'); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[2] == 's'); const int32_t id = argv[1]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(id >= 0); const char* const newName = &argv[2]->s; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(newName != nullptr && newName[0] != '\0'); ok = fEngine->renamePlugin(static_cast(id), newName); } else if (std::strcmp(method, "clone_plugin") == 0) { CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 2); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i'); const int32_t id = argv[1]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(id >= 0); ok = fEngine->clonePlugin(static_cast(id)); } else if (std::strcmp(method, "replace_plugin") == 0) { CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 2); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i'); const int32_t id = argv[1]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(id >= 0); ok = fEngine->replacePlugin(static_cast(id)); } else if (std::strcmp(method, "switch_plugins") == 0) { CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 3); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i'); CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[2] == 'i'); const int32_t idA = argv[1]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(idA >= 0); const int32_t idB = argv[2]->i; CARLA_SAFE_ASSERT_RETURN_OSC_ERR(idB >= 0); ok = fEngine->switchPlugins(static_cast(idA), static_cast(idB)); } else { carla_stderr2("Unhandled OSC control for '%s'", method); sendResponse(messageId, "Unhandled OSC control method"); return 0; } #undef CARLA_SAFE_ASSERT_RETURN_OSC_ERR sendResponse(messageId, ok ? "" : fEngine->getLastError()); return 0; } // ----------------------------------------------------------------------- int CarlaEngineOsc::handleMsgSetActive(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgSetActive()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i"); const bool active = (argv[0]->i != 0); plugin->setActive(active, false, true); return 0; } int CarlaEngineOsc::handleMsgSetDryWet(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgSetDryWet()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); const float value = argv[0]->f; plugin->setDryWet(value, false, true); return 0; } int CarlaEngineOsc::handleMsgSetVolume(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgSetVolume()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); const float value = argv[0]->f; plugin->setVolume(value, false, true); return 0; } int CarlaEngineOsc::handleMsgSetBalanceLeft(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgSetBalanceLeft()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); const float value = argv[0]->f; plugin->setBalanceLeft(value, false, true); return 0; } int CarlaEngineOsc::handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgSetBalanceRight()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); const float value = argv[0]->f; plugin->setBalanceRight(value, false, true); return 0; } int CarlaEngineOsc::handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgSetPanning()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); const float value = argv[0]->f; plugin->setPanning(value, false, true); return 0; } int CarlaEngineOsc::handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgSetParameterValue()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "if"); const int32_t index = argv[0]->i; const float value = argv[1]->f; CARLA_SAFE_ASSERT_RETURN(index >= 0, 0); plugin->setParameterValue(static_cast(index), value, true, false, true); return 0; } int CarlaEngineOsc::handleMsgSetParameterMappedControlIndex(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgSetParameterMappedIndex()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii"); const int32_t index = argv[0]->i; const int32_t ctrl = argv[1]->i; CARLA_SAFE_ASSERT_RETURN(index >= 0, 0); CARLA_SAFE_ASSERT_RETURN(ctrl >= CONTROL_INDEX_NONE && ctrl <= CONTROL_INDEX_MAX_ALLOWED, 0); plugin->setParameterMappedControlIndex(static_cast(index), static_cast(ctrl), false, true); return 0; } int CarlaEngineOsc::handleMsgSetParameterMappedRange(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgSetParameterMappedRange()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "iff"); const int32_t index = argv[0]->i; const float minimum = argv[1]->f; const float maximum = argv[2]->f; CARLA_SAFE_ASSERT_RETURN(index >= 0, 0); plugin->setParameterMappedRange(static_cast(index), minimum, maximum, false, true); return 0; } int CarlaEngineOsc::handleMsgSetParameterMidiChannel(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgSetParameterMidiChannel()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii"); const int32_t index = argv[0]->i; const int32_t channel = argv[1]->i; CARLA_SAFE_ASSERT_RETURN(index >= 0, 0); CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0); plugin->setParameterMidiChannel(static_cast(index), static_cast(channel), false, true); return 0; } int CarlaEngineOsc::handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgSetProgram()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i"); const int32_t index = argv[0]->i; CARLA_SAFE_ASSERT_RETURN(index >= -1, 0); plugin->setProgram(index, true, false, true); return 0; } int CarlaEngineOsc::handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgSetMidiProgram()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i"); const int32_t index = argv[0]->i; CARLA_SAFE_ASSERT_RETURN(index >= -1, 0); plugin->setMidiProgram(index, true, false, true); return 0; } int CarlaEngineOsc::handleMsgNoteOn(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgNoteOn()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(3, "iii"); const int32_t channel = argv[0]->i; const int32_t note = argv[1]->i; const int32_t velo = argv[2]->i; CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0); CARLA_SAFE_ASSERT_RETURN(note >= 0 && note < MAX_MIDI_NOTE, 0); CARLA_SAFE_ASSERT_RETURN(velo >= 0 && velo < MAX_MIDI_VALUE, 0); plugin->sendMidiSingleNote(static_cast(channel), static_cast(note), static_cast(velo), true, false, true); return 0; } int CarlaEngineOsc::handleMsgNoteOff(CARLA_ENGINE_OSC_HANDLE_ARGS) { carla_debug("CarlaEngineOsc::handleMsgNoteOff()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii"); const int32_t channel = argv[0]->i; const int32_t note = argv[1]->i; CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0); CARLA_SAFE_ASSERT_RETURN(note >= 0 && note < MAX_MIDI_NOTE, 0); plugin->sendMidiSingleNote(static_cast(channel), static_cast(note), 0, true, false, true); return 0; } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE #endif // HAVE_LIBLO Carla-2.1/source/backend/engine/CarlaEngineOscSend.cpp000066400000000000000000000424311364475620200227020ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaEngineOsc.hpp" #ifdef HAVE_LIBLO #include "CarlaBackendUtils.hpp" #include "CarlaEngine.hpp" #include "CarlaPlugin.hpp" CARLA_BACKEND_START_NAMESPACE static const char* const kNullString = ""; // ----------------------------------------------------------------------- void CarlaEngineOsc::sendCallback(const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const int value3, const float valuef, const char* const valueStr) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); carla_stdout("CarlaEngineOsc::sendCallback(%i:%s, %i, %i, %i, %i, %f, \"%s\")", action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3, static_cast(valuef), valueStr); char targetPath[std::strlen(fControlDataTCP.path)+10]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/cb"); try_lo_send(fControlDataTCP.target, targetPath, "iiiiifs", action, pluginId, value1, value2, value3, static_cast(valuef), valueStr != nullptr ? valueStr : kNullString); } void CarlaEngineOsc::sendPluginInfo(const CarlaPlugin* const plugin) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_stdout("CarlaEngineOsc::sendPluginInfo(%p)", plugin); char bufRealName[STR_MAX+1], bufLabel[STR_MAX+1], bufMaker[STR_MAX+1], bufCopyright[STR_MAX+1]; carla_zeroChars(bufRealName, STR_MAX+1); carla_zeroChars(bufLabel, STR_MAX+1); carla_zeroChars(bufMaker, STR_MAX+1); carla_zeroChars(bufCopyright, STR_MAX+1); if (! plugin->getRealName(bufRealName)) bufRealName[0] = '\0'; if (! plugin->getLabel(bufLabel)) bufLabel[0] = '\0'; if (! plugin->getMaker(bufMaker)) bufMaker[0] = '\0'; if (! plugin->getCopyright(bufCopyright)) bufCopyright[0] = '\0'; const char* name = plugin->getName(); const char* filename = plugin->getFilename(); const char* iconName = plugin->getIconName(); if (name == nullptr) name = kNullString; if (filename == nullptr) filename = kNullString; if (iconName == nullptr) iconName = kNullString; char targetPath[std::strlen(fControlDataTCP.path)+10]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/info"); try_lo_send(fControlDataTCP.target, targetPath, "iiiihiisssssss", static_cast(plugin->getId()), static_cast(plugin->getType()), static_cast(plugin->getCategory()), static_cast(plugin->getHints()), static_cast(plugin->getUniqueId()), static_cast(plugin->getOptionsAvailable()), static_cast(plugin->getOptionsEnabled()), name, filename, iconName, bufRealName, bufLabel, bufMaker, bufCopyright); } void CarlaEngineOsc::sendPluginPortCount(const CarlaPlugin* const plugin) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_stdout("CarlaEngineOsc::sendPluginPortCount(%p)", plugin); uint32_t paramIns, paramOuts; plugin->getParameterCountInfo(paramIns, paramOuts); if (paramIns > 49) paramIns = 49; if (paramOuts > 49) paramOuts = 49; char targetPath[std::strlen(fControlDataTCP.path)+7]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/ports"); try_lo_send(fControlDataTCP.target, targetPath, "iiiiiiii", static_cast(plugin->getId()), static_cast(plugin->getAudioInCount()), static_cast(plugin->getAudioOutCount()), static_cast(plugin->getMidiInCount()), static_cast(plugin->getMidiOutCount()), static_cast(paramIns), static_cast(paramOuts), static_cast(plugin->getParameterCount())); } void CarlaEngineOsc::sendPluginParameterInfo(const CarlaPlugin* const plugin, const uint32_t index) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("CarlaEngineOsc::sendPluginParameterInfo(%p, %u)", plugin, index); char bufName[STR_MAX+1], bufUnit[STR_MAX+1], bufComment[STR_MAX+1], bufGroupName[STR_MAX+1]; carla_zeroChars(bufName, STR_MAX+1); carla_zeroChars(bufUnit, STR_MAX+1); carla_zeroChars(bufComment, STR_MAX+1); carla_zeroChars(bufGroupName, STR_MAX+1); if (! plugin->getParameterName(index, bufName)) bufName[0] = '\0'; if (! plugin->getParameterUnit(index, bufUnit)) bufUnit[0] = '\0'; if (! plugin->getParameterComment(index, bufComment)) bufComment[0] = '\0'; if (! plugin->getParameterGroupName(index, bufGroupName)) bufGroupName[0] = '\0'; const ParameterData& paramData(plugin->getParameterData(index)); const ParameterRanges& paramRanges(plugin->getParameterRanges(index)); const int32_t pluginId = static_cast(plugin->getId()); const int32_t paramId = static_cast(index); char targetPath[std::strlen(fControlDataTCP.path)+24]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/paramInfo"); try_lo_send(fControlDataTCP.target, targetPath, "iissss", pluginId, paramId, bufName, bufUnit, bufComment, bufGroupName); std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/paramData"); try_lo_send(fControlDataTCP.target, targetPath, "iiiiiifff", pluginId, paramId, static_cast(paramData.type), static_cast(paramData.hints), static_cast(paramData.midiChannel), static_cast(paramData.mappedControlIndex), static_cast(paramData.mappedMinimum), static_cast(paramData.mappedMaximum), static_cast(plugin->getParameterValue(index))); std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/paramRanges"); try_lo_send(fControlDataTCP.target, targetPath, "iiffffff", pluginId, paramId, static_cast(paramRanges.def), static_cast(paramRanges.min), static_cast(paramRanges.max), static_cast(paramRanges.step), static_cast(paramRanges.stepSmall), static_cast(paramRanges.stepLarge)); } void CarlaEngineOsc::sendPluginDataCount(const CarlaPlugin* const plugin) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_stdout("CarlaEngineOsc::sendPluginDataCount(%p)", plugin); char targetPath[std::strlen(fControlDataTCP.path)+7]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/count"); try_lo_send(fControlDataTCP.target, targetPath, "iiiiii", static_cast(plugin->getId()), static_cast(plugin->getProgramCount()), static_cast(plugin->getMidiProgramCount()), static_cast(plugin->getCustomDataCount()), static_cast(plugin->getCurrentProgram()), static_cast(plugin->getCurrentMidiProgram())); } void CarlaEngineOsc::sendPluginProgramCount(const CarlaPlugin* const plugin) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_stdout("CarlaEngineOsc::sendPluginDataCount(%p)", plugin); char targetPath[std::strlen(fControlDataTCP.path)+7]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/pcount"); try_lo_send(fControlDataTCP.target, targetPath, "iii", static_cast(plugin->getId()), static_cast(plugin->getProgramCount()), static_cast(plugin->getMidiProgramCount())); } void CarlaEngineOsc::sendPluginProgram(const CarlaPlugin* const plugin, const uint32_t index) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); carla_stdout("CarlaEngineOsc::sendPluginProgram(%p, %u)", plugin, index); char strBuf[STR_MAX+1]; carla_zeroChars(strBuf, STR_MAX+1); if (! plugin->getProgramName(index, strBuf)) strBuf[0] = '\0'; char targetPath[std::strlen(fControlDataTCP.path)+6]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/prog"); try_lo_send(fControlDataTCP.target, targetPath, "iis", static_cast(plugin->getId()), static_cast(index), strBuf); } void CarlaEngineOsc::sendPluginMidiProgram(const CarlaPlugin* const plugin, const uint32_t index) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); carla_stdout("CarlaEngineOsc::sendPluginProgram(%p, %u)", plugin, index); const MidiProgramData& mpdata(plugin->getMidiProgramData(index)); CARLA_SAFE_ASSERT_RETURN(mpdata.name != nullptr,); char targetPath[std::strlen(fControlDataTCP.path)+7]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/mprog"); try_lo_send(fControlDataTCP.target, targetPath, "iiiis", static_cast(plugin->getId()), static_cast(index), static_cast(mpdata.bank), static_cast(mpdata.program), mpdata.name); } void CarlaEngineOsc::sendPluginCustomData(const CarlaPlugin* const plugin, const uint32_t index) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); carla_stdout("CarlaEngineOsc::sendPluginCustomData(%p, %u)", plugin, index); const CustomData& cdata(plugin->getCustomData(index)); CARLA_SAFE_ASSERT_RETURN(cdata.isValid(),); char targetPath[std::strlen(fControlDataTCP.path)+7]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/cdata"); try_lo_send(fControlDataTCP.target, targetPath, "iisss", static_cast(plugin->getId()), static_cast(index), cdata.type, cdata.key, cdata.value); } void CarlaEngineOsc::sendPluginInternalParameterValues(const CarlaPlugin* const plugin) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); carla_debug("CarlaEngineOsc::sendPluginInternalParameterValues(%p)", plugin); #ifdef CARLA_PROPER_CPP11_SUPPORT static_assert(PARAMETER_ACTIVE == -2 && PARAMETER_MAX == -9, "Incorrect data"); #endif double iparams[7]; for (int32_t i = 0; i < 7; ++i) iparams[i] = plugin->getInternalParameterValue(PARAMETER_ACTIVE - i); char targetPath[std::strlen(fControlDataTCP.path)+18]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/iparams"); try_lo_send(fControlDataTCP.target, targetPath, "ifffffff", static_cast(plugin->getId()), iparams[0], // PARAMETER_ACTIVE iparams[1], // PARAMETER_DRYWET iparams[2], // PARAMETER_VOLUME iparams[3], // PARAMETER_BALANCE_LEFT iparams[4], // PARAMETER_BALANCE_RIGHT iparams[5], // PARAMETER_PANNING iparams[6] // PARAMETER_CTRL_CHANNEL ); } // ----------------------------------------------------------------------- void CarlaEngineOsc::sendPing() const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); char targetPath[std::strlen(fControlDataTCP.path)+6]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/ping"); try_lo_send(fControlDataTCP.target, targetPath, ""); } void CarlaEngineOsc::sendResponse(const int messageId, const char* const error) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); carla_debug("CarlaEngineOsc::sendResponse()"); char targetPath[std::strlen(fControlDataTCP.path)+6]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/resp"); try_lo_send(fControlDataTCP.target, targetPath, "is", messageId, error); } void CarlaEngineOsc::sendExit() const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,); carla_debug("CarlaEngineOsc::sendExit()"); char targetPath[std::strlen(fControlDataTCP.path)+6]; std::strcpy(targetPath, fControlDataTCP.path); std::strcat(targetPath, "/exit"); try_lo_send(fControlDataTCP.target, targetPath, ""); } // ----------------------------------------------------------------------- void CarlaEngineOsc::sendRuntimeInfo() const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.path != nullptr && fControlDataUDP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.target != nullptr,); const EngineTimeInfo timeInfo(fEngine->getTimeInfo()); char targetPath[std::strlen(fControlDataUDP.path)+18]; std::strcpy(targetPath, fControlDataUDP.path); std::strcat(targetPath, "/runtime"); try_lo_send(fControlDataUDP.target, targetPath, "fiihiiif", static_cast(fEngine->getDSPLoad()), static_cast(fEngine->getTotalXruns()), timeInfo.playing ? 1 : 0, static_cast(timeInfo.frame), static_cast(timeInfo.bbt.bar), static_cast(timeInfo.bbt.beat), static_cast(timeInfo.bbt.tick), timeInfo.bbt.beatsPerMinute); } void CarlaEngineOsc::sendParameterValue(const uint pluginId, const uint32_t index, const float value) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.path != nullptr && fControlDataUDP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.target != nullptr,); char targetPath[std::strlen(fControlDataUDP.path)+21]; std::strcpy(targetPath, fControlDataUDP.path); std::strcat(targetPath, "/param"); try_lo_send(fControlDataUDP.target, targetPath, "iif", static_cast(pluginId), index, static_cast(value)); } void CarlaEngineOsc::sendPeaks(const uint pluginId, const float peaks[4]) const noexcept { CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.path != nullptr && fControlDataUDP.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.target != nullptr,); char targetPath[std::strlen(fControlDataUDP.path)+11]; std::strcpy(targetPath, fControlDataUDP.path); std::strcat(targetPath, "/peaks"); try_lo_send(fControlDataUDP.target, targetPath, "iffff", static_cast(pluginId), static_cast(peaks[0]), static_cast(peaks[1]), static_cast(peaks[2]), static_cast(peaks[3])); } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE #endif // HAVE_LIBLO Carla-2.1/source/backend/engine/CarlaEnginePorts.cpp000066400000000000000000000420331364475620200224510ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaEnginePorts.hpp" #include "CarlaEngineGraph.hpp" #include "CarlaEngineUtils.hpp" #include "CarlaMathUtils.hpp" #include "CarlaMIDI.h" #include "lv2/lv2.h" CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // Fallback data static const EngineEvent kFallbackEngineEvent = { kEngineEventTypeNull, 0, 0, {{ kEngineControlEventTypeNull, 0, 0.0f }} }; //static CarlaEngineEventCV kFallbackEngineEventCV = { nullptr, (uint32_t)-1, 0.0f }; // ----------------------------------------------------------------------- // Carla Engine port (Abstract) CarlaEnginePort::CarlaEnginePort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept : kClient(client), kIsInput(isInputPort), kIndexOffset(indexOffset) { carla_debug("CarlaEnginePort::CarlaEnginePort(%s)", bool2str(isInputPort)); } CarlaEnginePort::~CarlaEnginePort() noexcept { carla_debug("CarlaEnginePort::~CarlaEnginePort()"); } void CarlaEnginePort::setMetaData(const char*, const char*, const char*) { } // ----------------------------------------------------------------------- // Carla Engine Audio port CarlaEngineAudioPort::CarlaEngineAudioPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept : CarlaEnginePort(client, isInputPort, indexOffset), fBuffer(nullptr) { carla_debug("CarlaEngineAudioPort::CarlaEngineAudioPort(%s)", bool2str(isInputPort)); } CarlaEngineAudioPort::~CarlaEngineAudioPort() noexcept { carla_debug("CarlaEngineAudioPort::~CarlaEngineAudioPort()"); } void CarlaEngineAudioPort::initBuffer() noexcept { } // ----------------------------------------------------------------------- // Carla Engine CV port CarlaEngineCVPort::CarlaEngineCVPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept : CarlaEnginePort(client, isInputPort, indexOffset), fBuffer(nullptr), fMinimum(-1.0f), fMaximum(1.0f) { carla_debug("CarlaEngineCVPort::CarlaEngineCVPort(%s)", bool2str(isInputPort)); } CarlaEngineCVPort::~CarlaEngineCVPort() noexcept { carla_debug("CarlaEngineCVPort::~CarlaEngineCVPort()"); } void CarlaEngineCVPort::initBuffer() noexcept { } void CarlaEngineCVPort::setRange(const float min, const float max) noexcept { fMinimum = min; fMaximum = max; char strBufMin[STR_MAX]; char strBufMax[STR_MAX]; carla_zeroChars(strBufMin, STR_MAX); carla_zeroChars(strBufMax, STR_MAX); { const CarlaScopedLocale csl; std::snprintf(strBufMin, STR_MAX-1, "%.12g", static_cast(min)); std::snprintf(strBufMax, STR_MAX-1, "%.12g", static_cast(max)); } setMetaData(LV2_CORE__minimum, strBufMin, ""); setMetaData(LV2_CORE__maximum, strBufMax, ""); } // ----------------------------------------------------------------------- // Carla Engine Event port CarlaEngineEventPort::CarlaEngineEventPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept : CarlaEnginePort(client, isInputPort, indexOffset), kProcessMode(client.getEngine().getProccessMode()), fBuffer(nullptr) { carla_debug("CarlaEngineEventPort::CarlaEngineEventPort(%s)", bool2str(isInputPort)); if (kProcessMode == ENGINE_PROCESS_MODE_PATCHBAY) { fBuffer = new EngineEvent[kMaxEngineEventInternalCount]; carla_zeroStructs(fBuffer, kMaxEngineEventInternalCount); } } CarlaEngineEventPort::~CarlaEngineEventPort() noexcept { carla_debug("CarlaEngineEventPort::~CarlaEngineEventPort()"); if (kProcessMode == ENGINE_PROCESS_MODE_PATCHBAY) { CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,); delete[] fBuffer; fBuffer = nullptr; } } void CarlaEngineEventPort::initBuffer() noexcept { if (kProcessMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == ENGINE_PROCESS_MODE_BRIDGE) fBuffer = kClient.getEngine().getInternalEventBuffer(kIsInput); else if (kProcessMode == ENGINE_PROCESS_MODE_PATCHBAY && ! kIsInput) carla_zeroStructs(fBuffer, kMaxEngineEventInternalCount); } uint32_t CarlaEngineEventPort::getEventCount() const noexcept { CARLA_SAFE_ASSERT_RETURN(kIsInput, 0); CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(kProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && kProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, 0); uint32_t i=0; for (; i < kMaxEngineEventInternalCount; ++i) { if (fBuffer[i].type == kEngineEventTypeNull) break; } return i; } const EngineEvent& CarlaEngineEventPort::getEvent(const uint32_t index) const noexcept { CARLA_SAFE_ASSERT_RETURN(kIsInput, kFallbackEngineEvent); CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, kFallbackEngineEvent); CARLA_SAFE_ASSERT_RETURN(kProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && kProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, kFallbackEngineEvent); CARLA_SAFE_ASSERT_RETURN(index < kMaxEngineEventInternalCount, kFallbackEngineEvent); return fBuffer[index]; } const EngineEvent& CarlaEngineEventPort::getEventUnchecked(const uint32_t index) const noexcept { return fBuffer[index]; } bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEvent& ctrl) noexcept { return writeControlEvent(time, channel, ctrl.type, ctrl.param, ctrl.value); } bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const float value) noexcept { CARLA_SAFE_ASSERT_RETURN(! kIsInput, false); CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false); CARLA_SAFE_ASSERT_RETURN(kProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && kProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false); CARLA_SAFE_ASSERT_RETURN(type != kEngineControlEventTypeNull, false); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f); if (type == kEngineControlEventTypeParameter) { CARLA_SAFE_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param)); } for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i) { EngineEvent& event(fBuffer[i]); if (event.type != kEngineEventTypeNull) continue; event.type = kEngineEventTypeControl; event.time = time; event.channel = channel; event.ctrl.type = type; event.ctrl.param = param; event.ctrl.value = carla_fixedValue(0.0f, 1.0f, value); return true; } carla_stderr2("CarlaEngineEventPort::writeControlEvent() - buffer full"); return false; } bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t size, const uint8_t* const data) noexcept { return writeMidiEvent(time, uint8_t(MIDI_GET_CHANNEL_FROM_DATA(data)), size, data); } bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const EngineMidiEvent& midi) noexcept { CARLA_SAFE_ASSERT(midi.port == kIndexOffset); return writeMidiEvent(time, channel, midi.size, midi.data); } bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t size, const uint8_t* const data) noexcept { CARLA_SAFE_ASSERT_RETURN(! kIsInput, false); CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false); CARLA_SAFE_ASSERT_RETURN(kProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && kProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); CARLA_SAFE_ASSERT_RETURN(size > 0 && size <= EngineMidiEvent::kDataSize, false); CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i) { EngineEvent& event(fBuffer[i]); if (event.type != kEngineEventTypeNull) continue; event.time = time; event.channel = channel; const uint8_t status(uint8_t(MIDI_GET_STATUS_FROM_DATA(data))); if (status == MIDI_STATUS_CONTROL_CHANGE) { CARLA_SAFE_ASSERT_RETURN(size >= 2, true); switch (data[1]) { case MIDI_CONTROL_BANK_SELECT: case MIDI_CONTROL_BANK_SELECT__LSB: CARLA_SAFE_ASSERT_RETURN(size >= 3, true); event.type = kEngineEventTypeControl; event.ctrl.type = kEngineControlEventTypeMidiBank; event.ctrl.param = data[2]; event.ctrl.value = 0.0f; return true; case MIDI_CONTROL_ALL_SOUND_OFF: event.type = kEngineEventTypeControl; event.ctrl.type = kEngineControlEventTypeAllSoundOff; event.ctrl.param = 0; event.ctrl.value = 0.0f; return true; case MIDI_CONTROL_ALL_NOTES_OFF: event.type = kEngineEventTypeControl; event.ctrl.type = kEngineControlEventTypeAllNotesOff; event.ctrl.param = 0; event.ctrl.value = 0.0f; return true; } } if (status == MIDI_STATUS_PROGRAM_CHANGE) { CARLA_SAFE_ASSERT_RETURN(size >= 2, true); event.type = kEngineEventTypeControl; event.ctrl.type = kEngineControlEventTypeMidiProgram; event.ctrl.param = data[1]; event.ctrl.value = 0.0f; return true; } event.type = kEngineEventTypeMidi; event.midi.size = size; if (kIndexOffset < 0xFF /* uint8_t max */) { event.midi.port = static_cast(kIndexOffset); } else { event.midi.port = 0; carla_safe_assert_uint("kIndexOffset < 0xFF", __FILE__, __LINE__, kIndexOffset); } event.midi.data[0] = status; uint8_t j=1; for (; j < size; ++j) event.midi.data[j] = data[j]; for (; j < EngineMidiEvent::kDataSize; ++j) event.midi.data[j] = 0; return true; } carla_stderr2("CarlaEngineEventPort::writeMidiEvent() - buffer full"); return false; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // ----------------------------------------------------------------------- // Carla Engine Meta CV port CarlaEngineCVSourcePorts::CarlaEngineCVSourcePorts() : pData(new ProtectedData()) { carla_debug("CarlaEngineCVSourcePorts::CarlaEngineCVSourcePorts()"); } CarlaEngineCVSourcePorts::~CarlaEngineCVSourcePorts() { carla_debug("CarlaEngineCVSourcePorts::~CarlaEngineCVSourcePorts()"); delete pData; } bool CarlaEngineCVSourcePorts::addCVSource(CarlaEngineCVPort* const port, const uint32_t portIndexOffset) { CARLA_SAFE_ASSERT_RETURN(port != nullptr, false); CARLA_SAFE_ASSERT_RETURN(port->isInput(), false); carla_debug("CarlaEngineCVSourcePorts::addCVSource(%p)", port); { const CarlaRecursiveMutexLocker crml(pData->rmutex); const CarlaEngineEventCV ecv = { port, portIndexOffset, 0.0f }; if (! pData->cvs.add(ecv)) return false; if (pData->graph != nullptr && pData->plugin != nullptr) pData->graph->reconfigureForCV(pData->plugin, static_cast(pData->cvs.size()-1), true); } return true; } bool CarlaEngineCVSourcePorts::removeCVSource(const uint32_t portIndexOffset) { carla_debug("CarlaEngineCVSourcePorts::removeCVSource(%u)", portIndexOffset); { const CarlaRecursiveMutexLocker crml(pData->rmutex); for (int i = pData->cvs.size(); --i >= 0;) { const CarlaEngineEventCV& ecv(pData->cvs[i]); if (ecv.indexOffset == portIndexOffset) { delete ecv.cvPort; pData->cvs.remove(i); if (pData->graph != nullptr && pData->plugin != nullptr) pData->graph->reconfigureForCV(pData->plugin, static_cast(i), false); carla_stdout("found cv source to remove %u", portIndexOffset); return true; } } } carla_stdout("did NOT found cv source to remove %u", portIndexOffset); return false; } void CarlaEngineCVSourcePorts::initPortBuffers(const float* const* const buffers, const uint32_t frames, const bool sampleAccurate, CarlaEngineEventPort* const eventPort) { CARLA_SAFE_ASSERT_RETURN(buffers != nullptr,); CARLA_SAFE_ASSERT_RETURN(eventPort != nullptr,); const CarlaRecursiveMutexTryLocker crmtl(pData->rmutex); if (! crmtl.wasLocked()) return; const int numCVs = pData->cvs.size(); if (numCVs == 0) return; EngineEvent* const buffer = eventPort->fBuffer; CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,); uint32_t eventCount = 0; float v, min, max; for (; eventCount < kMaxEngineEventInternalCount; ++eventCount) { if (buffer[eventCount].type == kEngineEventTypeNull) break; } if (eventCount == kMaxEngineEventInternalCount) return; // TODO be sample accurate if (true || ! sampleAccurate) { const uint32_t eventFrame = eventCount == 0 ? 0 : std::min(buffer[eventCount-1].time, frames-1U); for (int i = 0; i < numCVs && eventCount < kMaxEngineEventInternalCount; ++i) { CarlaEngineEventCV& ecv(pData->cvs.getReference(i)); CARLA_SAFE_ASSERT_CONTINUE(ecv.cvPort != nullptr); CARLA_SAFE_ASSERT_CONTINUE(buffers[i] != nullptr); float previousValue = ecv.previousValue; ecv.cvPort->getRange(min, max); v = buffers[i][eventFrame]; if (carla_isNotEqual(v, previousValue)) { previousValue = v; EngineEvent& event(buffer[eventCount++]); event.type = kEngineEventTypeControl; event.time = eventFrame; event.channel = kEngineEventNonMidiChannel; event.ctrl.type = kEngineControlEventTypeParameter; event.ctrl.param = static_cast(ecv.indexOffset); event.ctrl.value = carla_fixedValue(0.0f, 1.0f, (v - min) / (max - min)); } ecv.previousValue = previousValue; } } } bool CarlaEngineCVSourcePorts::setCVSourceRange(const uint32_t portIndexOffset, const float minimum, const float maximum) { const CarlaRecursiveMutexLocker crml(pData->rmutex); for (int i = pData->cvs.size(); --i >= 0;) { CarlaEngineEventCV& ecv(pData->cvs.getReference(i)); if (ecv.indexOffset == portIndexOffset) { CARLA_SAFE_ASSERT_RETURN(ecv.cvPort != nullptr, false); ecv.cvPort->setRange(minimum, maximum); return true; } } return false; } void CarlaEngineCVSourcePorts::cleanup() { pData->cleanup(); } /* void CarlaEngineCVSourcePorts::mixWithCvBuffer(const float* const buffer, const uint32_t frames, const uint32_t indexOffset) noexcept { for (LinkedList::Itenerator it = pData->cvs.begin2(); it.valid(); it.next()) { CarlaEngineEventCV& ecv(it.getValue(kFallbackEngineEventCV)); if (ecv.indexOffset != indexOffset) continue; CARLA_SAFE_ASSERT_RETURN(ecv.cvPort != nullptr,); float previousValue = ecv.previousValue; ecv.cvPort->getRange(min, max); for (uint32_t i=0; ibuffer[eventIndex++]); event.type = kEngineEventTypeControl; event.time = i; event.channel = kEngineEventNonMidiChannel; event.ctrl.type = kEngineControlEventTypeParameter; event.ctrl.param = static_cast(indexOffset); event.ctrl.value = carla_fixedValue(0.0f, 1.0f, (v - min) / (max - min)); } } ecv.previousValue = previousValue; break; } } */ #endif // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/engine/CarlaEnginePorts.hpp000066400000000000000000000046431364475620200224630ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_ENGINE_PORTS_HPP_INCLUDED #define CARLA_ENGINE_PORTS_HPP_INCLUDED #include "CarlaEngine.hpp" #include "CarlaEngineInternal.hpp" CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // Carla Engine Meta CV Port Protected Data struct CarlaEngineEventCV { CarlaEngineCVPort* cvPort; uint32_t indexOffset; float previousValue; }; struct CarlaEngineCVSourcePorts::ProtectedData { CarlaRecursiveMutex rmutex; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH PatchbayGraph* graph; CarlaPlugin* plugin; #endif water::Array cvs; ProtectedData() noexcept : rmutex(), #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH graph(nullptr), plugin(nullptr), #endif cvs() {} ~ProtectedData() { CARLA_SAFE_ASSERT(cvs.size() == 0); } void cleanup() { const CarlaRecursiveMutexLocker crml(rmutex); for (int i = cvs.size(); --i >= 0;) delete cvs[i].cvPort; cvs.clear(); } CARLA_DECLARE_NON_COPY_STRUCT(ProtectedData) }; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // ----------------------------------------------------------------------- // Carla Engine Meta CV Port class CarlaEngineCVSourcePortsForStandalone : public CarlaEngineCVSourcePorts { public: CarlaEngineCVSourcePortsForStandalone() : CarlaEngineCVSourcePorts() {} ~CarlaEngineCVSourcePortsForStandalone() override {} inline void setGraphAndPlugin(PatchbayGraph* const graph, CarlaPlugin* const plugin) noexcept { pData->graph = graph; pData->plugin = plugin; } }; #endif // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE #endif // CARLA_ENGINE_PORTS_HPP_INCLUDED Carla-2.1/source/backend/engine/CarlaEngineRtAudio.cpp000066400000000000000000001206301364475620200227110ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaEngineGraph.hpp" #include "CarlaEngineInternal.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaMathUtils.hpp" #include "CarlaStringList.hpp" #include "RtLinkedList.hpp" #include "jackbridge/JackBridge.hpp" #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wconversion" # pragma clang diagnostic ignored "-Weffc++" #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Weffc++" # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" #endif #include "rtaudio/RtAudio.h" #include "rtmidi/RtMidi.h" #if defined(__clang__) # pragma clang diagnostic pop #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic pop #endif CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- // Global static data static CharStringListPtr gDeviceNames; static std::vector gRtAudioApis; // ------------------------------------------------------------------------------------------------------------------- static void initRtAudioAPIsIfNeeded() { static bool needsInit = true; if (! needsInit) return; needsInit = false; // get APIs in a local var, and pass wanted ones into gRtAudioApis std::vector apis; RtAudio::getCompiledApi(apis); for (std::vector::const_iterator it = apis.begin(), end=apis.end(); it != end; ++it) { const RtAudio::Api& api(*it); if (api == RtAudio::UNIX_JACK) { #if defined(CARLA_OS_LINUX) || defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) if ( ! jackbridge_is_ok()) continue; #else /* NOTE * RtMidi doesn't have a native MIDI backend for these OSes, * Using RtAudio JACK funcitonality is only useful when we need to access the native MIDI APIs. * (JACK audio + ALSA MIDI, or JACK audio + CoreMidi, or JACK audio + Windows MIDI) * Because RtMidi has no native MIDI support outside of win/mac/linux, we skip these RtAudio APIs. * Those OSes can use Carla's JACK support directly, which is much better than RtAudio classes. */ continue; #endif } gRtAudioApis.push_back(api); } } static const char* getRtAudioApiName(const RtAudio::Api api) noexcept { switch (api) { case RtAudio::UNSPECIFIED: return "Unspecified"; case RtAudio::LINUX_ALSA: return "ALSA"; case RtAudio::LINUX_OSS: return "OSS"; case RtAudio::UNIX_PULSE: return "PulseAudio"; case RtAudio::UNIX_JACK: #if defined(CARLA_OS_LINUX) && defined(__LINUX_ALSA__) return "JACK with ALSA-MIDI"; #elif defined(CARLA_OS_MAC) return "JACK with CoreMidi"; #elif defined(CARLA_OS_WIN) return "JACK with WinMM"; #else return "JACK (RtAudio)"; #endif case RtAudio::MACOSX_CORE: return "CoreAudio"; case RtAudio::WINDOWS_ASIO: return "ASIO"; case RtAudio::WINDOWS_DS: return "DirectSound"; case RtAudio::WINDOWS_WASAPI: return "WASAPI"; case RtAudio::RTAUDIO_DUMMY: return "Dummy"; } carla_stderr("CarlaBackend::getRtAudioApiName(%i) - invalid API", api); return nullptr; } static RtMidi::Api getMatchedAudioMidiAPI(const RtAudio::Api rtApi) noexcept { switch (rtApi) { case RtAudio::UNSPECIFIED: return RtMidi::UNSPECIFIED; case RtAudio::LINUX_ALSA: case RtAudio::LINUX_OSS: return RtMidi::LINUX_ALSA; case RtAudio::UNIX_PULSE: case RtAudio::UNIX_JACK: #if defined(CARLA_OS_LINUX) && defined(__LINUX_ALSA__) return RtMidi::LINUX_ALSA; #elif defined(CARLA_OS_MAC) return RtMidi::MACOSX_CORE; #elif defined(CARLA_OS_WIN) return RtMidi::WINDOWS_MM; #else return RtMidi::RTMIDI_DUMMY; #endif case RtAudio::MACOSX_CORE: return RtMidi::MACOSX_CORE; case RtAudio::WINDOWS_ASIO: case RtAudio::WINDOWS_DS: case RtAudio::WINDOWS_WASAPI: return RtMidi::WINDOWS_MM; case RtAudio::RTAUDIO_DUMMY: return RtMidi::RTMIDI_DUMMY; } return RtMidi::UNSPECIFIED; } // ------------------------------------------------------------------------------------------------------------------- // RtAudio Engine class CarlaEngineRtAudio : public CarlaEngine { public: CarlaEngineRtAudio(const RtAudio::Api api) : CarlaEngine(), fAudio(api), fAudioInterleaved(false), fAudioInCount(0), fAudioOutCount(0), fLastEventTime(0), fDeviceName(), fAudioIntBufIn(nullptr), fAudioIntBufOut(nullptr), fMidiIns(), fMidiInEvents(), fMidiOuts(), fMidiOutMutex(), fMidiOutVector(EngineMidiEvent::kDataSize) { carla_debug("CarlaEngineRtAudio::CarlaEngineRtAudio(%i)", api); // just to make sure pData->options.transportMode = ENGINE_TRANSPORT_MODE_INTERNAL; } ~CarlaEngineRtAudio() override { CARLA_SAFE_ASSERT(fAudioInCount == 0); CARLA_SAFE_ASSERT(fAudioOutCount == 0); CARLA_SAFE_ASSERT(fLastEventTime == 0); carla_debug("CarlaEngineRtAudio::~CarlaEngineRtAudio()"); } // ------------------------------------- bool init(const char* const clientName) override { CARLA_SAFE_ASSERT_RETURN(fAudioInCount == 0, false); CARLA_SAFE_ASSERT_RETURN(fAudioOutCount == 0, false); CARLA_SAFE_ASSERT_RETURN(fLastEventTime == 0, false); CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false); carla_debug("CarlaEngineRtAudio::init(\"%s\")", clientName); if (pData->options.processMode != ENGINE_PROCESS_MODE_CONTINUOUS_RACK && pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY) { setLastError("Invalid process mode"); return false; } const bool isDummy(fAudio.getCurrentApi() == RtAudio::RtAudio::RTAUDIO_DUMMY); bool deviceSet = false; RtAudio::StreamParameters iParams, oParams; if (isDummy) { if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { setLastError("Cannot use dummy driver in Rack mode"); return false; } fDeviceName = "Dummy"; } else { const uint devCount(fAudio.getDeviceCount()); if (devCount == 0) { setLastError("No audio devices available for this driver"); return false; } if (pData->options.audioDevice != nullptr && pData->options.audioDevice[0] != '\0') { for (uint i=0; i < devCount; ++i) { RtAudio::DeviceInfo devInfo(fAudio.getDeviceInfo(i)); if (devInfo.probed && devInfo.outputChannels > 0 && devInfo.name == pData->options.audioDevice) { deviceSet = true; fDeviceName = devInfo.name.c_str(); iParams.deviceId = i; oParams.deviceId = i; iParams.nChannels = devInfo.inputChannels; oParams.nChannels = devInfo.outputChannels; break; } } } if (! deviceSet) { iParams.deviceId = fAudio.getDefaultInputDevice(); oParams.deviceId = fAudio.getDefaultOutputDevice(); iParams.nChannels = fAudio.getDeviceInfo(iParams.deviceId).inputChannels; oParams.nChannels = fAudio.getDeviceInfo(oParams.deviceId).outputChannels; carla_stdout("No device set, using %i inputs and %i outputs", iParams.nChannels, oParams.nChannels); } if (oParams.nChannels == 0 && pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { setLastError("Current audio setup has no outputs, cannot continue"); return false; } iParams.nChannels = carla_fixedValue(0U, 128U, iParams.nChannels); oParams.nChannels = carla_fixedValue(0U, 128U, oParams.nChannels); fAudioInterleaved = fAudio.getCurrentApi() == RtAudio::UNIX_PULSE; } RtAudio::StreamOptions rtOptions; rtOptions.flags = RTAUDIO_MINIMIZE_LATENCY | RTAUDIO_SCHEDULE_REALTIME; rtOptions.numberOfBuffers = pData->options.audioTripleBuffer ? 3 : 2; rtOptions.streamName = clientName; rtOptions.priority = 85; if (fAudio.getCurrentApi() == RtAudio::LINUX_ALSA && ! deviceSet) rtOptions.flags |= RTAUDIO_ALSA_USE_DEFAULT; if (! fAudioInterleaved) rtOptions.flags |= RTAUDIO_NONINTERLEAVED; uint bufferFrames = pData->options.audioBufferSize; try { fAudio.openStream(oParams.nChannels > 0 ? &oParams : nullptr, iParams.nChannels > 0 ? &iParams : nullptr, RTAUDIO_FLOAT32, pData->options.audioSampleRate, &bufferFrames, carla_rtaudio_process_callback, this, &rtOptions, carla_rtaudio_buffer_size_callback); } catch (const RtAudioError& e) { setLastError(e.what()); return false; } if (! pData->init(clientName)) { close(); setLastError("Failed to init internal data"); return false; } pData->bufferSize = bufferFrames; pData->sampleRate = isDummy ? 44100.0 : fAudio.getStreamSampleRate(); pData->initTime(pData->options.transportExtra); fAudioInCount = iParams.nChannels; fAudioOutCount = oParams.nChannels; fLastEventTime = 0; if (fAudioInCount > 0) fAudioIntBufIn = new float[fAudioInCount*bufferFrames]; if (fAudioOutCount > 0) fAudioIntBufOut = new float[fAudioOutCount*bufferFrames]; pData->graph.create(fAudioInCount, fAudioOutCount, 0, 0); try { fAudio.startStream(); } catch (const RtAudioError& e) { close(); setLastError(e.what()); return false; } patchbayRefresh(true, false, false); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) refreshExternalGraphPorts(pData->graph.getPatchbayGraph(), false, false); callback(true, true, ENGINE_CALLBACK_ENGINE_STARTED, 0, pData->options.processMode, pData->options.transportMode, static_cast(pData->bufferSize), static_cast(pData->sampleRate), getCurrentDriverName()); return true; } bool close() override { carla_debug("CarlaEngineRtAudio::close()"); bool hasError = false; // stop stream first if (fAudio.isStreamOpen() && fAudio.isStreamRunning()) { try { fAudio.stopStream(); } catch (const RtAudioError& e) { setLastError(e.what()); hasError = true; } } // clear engine data CarlaEngine::close(); pData->graph.destroy(); for (LinkedList::Itenerator it = fMidiIns.begin2(); it.valid(); it.next()) { static MidiInPort fallback = { nullptr, { '\0' } }; MidiInPort& inPort(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr); inPort.port->cancelCallback(); inPort.port->closePort(); delete inPort.port; } fMidiIns.clear(); fMidiInEvents.clear(); fMidiOutMutex.lock(); for (LinkedList::Itenerator it = fMidiOuts.begin2(); it.valid(); it.next()) { static MidiOutPort fallback = { nullptr, { '\0' } }; MidiOutPort& outPort(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); outPort.port->closePort(); delete outPort.port; } fMidiOuts.clear(); fMidiOutMutex.unlock(); fAudioInCount = 0; fAudioOutCount = 0; fLastEventTime = 0; fDeviceName.clear(); if (fAudioIntBufIn != nullptr) { delete[] fAudioIntBufIn; fAudioIntBufIn = nullptr; } if (fAudioIntBufOut != nullptr) { delete[] fAudioIntBufOut; fAudioIntBufOut = nullptr; } // close stream if (fAudio.isStreamOpen()) fAudio.closeStream(); return !hasError; } bool isRunning() const noexcept override { return fAudio.isStreamOpen(); } bool isOffline() const noexcept override { return false; } EngineType getType() const noexcept override { return kEngineTypeRtAudio; } const char* getCurrentDriverName() const noexcept override { return CarlaBackend::getRtAudioApiName(fAudio.getCurrentApi()); } // ------------------------------------------------------------------- // Patchbay template bool refreshExternalGraphPorts(Graph* const graph, const bool sendHost, const bool sendOSC) { CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); char strBuf[STR_MAX+1U]; strBuf[STR_MAX] = '\0'; ExternalGraph& extGraph(graph->extGraph); // --------------------------------------------------------------- // clear last ports extGraph.clear(); // --------------------------------------------------------------- // fill in new ones // Audio In for (uint i=0; i < fAudioInCount; ++i) { std::snprintf(strBuf, STR_MAX, "capture_%i", i+1); PortNameToId portNameToId; portNameToId.setData(kExternalGraphGroupAudioIn, i+1, strBuf, ""); extGraph.audioPorts.ins.append(portNameToId); } // Audio Out for (uint i=0; i < fAudioOutCount; ++i) { std::snprintf(strBuf, STR_MAX, "playback_%i", i+1); PortNameToId portNameToId; portNameToId.setData(kExternalGraphGroupAudioOut, i+1, strBuf, ""); extGraph.audioPorts.outs.append(portNameToId); } // MIDI In try { RtMidiIn midiIn(getMatchedAudioMidiAPI(fAudio.getCurrentApi()), "carla-discovery-in"); for (uint i=0, count = midiIn.getPortCount(); i < count; ++i) { PortNameToId portNameToId; portNameToId.setData(kExternalGraphGroupMidiIn, i+1, midiIn.getPortName(i).c_str(), ""); extGraph.midiPorts.ins.append(portNameToId); } } CARLA_SAFE_EXCEPTION("RtMidiIn discovery"); // MIDI Out try { RtMidiOut midiOut(getMatchedAudioMidiAPI(fAudio.getCurrentApi()), "carla-discovery-out"); for (uint i=0, count = midiOut.getPortCount(); i < count; ++i) { PortNameToId portNameToId; portNameToId.setData(kExternalGraphGroupMidiOut, i+1, midiOut.getPortName(i).c_str(), ""); extGraph.midiPorts.outs.append(portNameToId); } } CARLA_SAFE_EXCEPTION("RtMidiOut discovery"); // --------------------------------------------------------------- // now refresh if (sendHost || sendOSC) graph->refresh(sendHost, sendOSC, true, fDeviceName.buffer()); // --------------------------------------------------------------- // add midi connections for (LinkedList::Itenerator it=fMidiIns.begin2(); it.valid(); it.next()) { static const MidiInPort fallback = { nullptr, { '\0' } }; const MidiInPort& inPort(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr); const uint portId(extGraph.midiPorts.getPortId(true, inPort.name)); CARLA_SAFE_ASSERT_CONTINUE(portId < extGraph.midiPorts.ins.count()); ConnectionToId connectionToId; connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupMidiIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiIn); std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB); extGraph.connections.list.append(connectionToId); callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); } fMidiOutMutex.lock(); for (LinkedList::Itenerator it=fMidiOuts.begin2(); it.valid(); it.next()) { static const MidiOutPort fallback = { nullptr, { '\0' } }; const MidiOutPort& outPort(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); const uint portId(extGraph.midiPorts.getPortId(false, outPort.name)); CARLA_SAFE_ASSERT_CONTINUE(portId < extGraph.midiPorts.outs.count()); ConnectionToId connectionToId; connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiOut, kExternalGraphGroupMidiOut, portId); std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB); extGraph.connections.list.append(connectionToId); callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0, 0.0f, strBuf); } fMidiOutMutex.unlock(); return true; } bool patchbayRefresh(const bool sendHost, const bool sendOSC, const bool external) override { CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(), false); if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) return refreshExternalGraphPorts(pData->graph.getRackGraph(), sendHost, sendOSC); if (sendHost) pData->graph.setUsingExternalHost(external); if (sendOSC) pData->graph.setUsingExternalOSC(external); if (external) return refreshExternalGraphPorts(pData->graph.getPatchbayGraph(), sendHost, sendOSC); return CarlaEngine::patchbayRefresh(sendHost, sendOSC, false); } // ------------------------------------------------------------------- protected: void handleAudioProcessCallback(void* outputBuffer, void* inputBuffer, uint nframes, double streamTime, RtAudioStreamStatus status) { const PendingRtEventsRunner prt(this, nframes, true); if (status & RTAUDIO_INPUT_OVERFLOW) ++pData->xruns; if (status & RTAUDIO_OUTPUT_UNDERFLOW) ++pData->xruns; // get buffers from RtAudio const float* const insPtr = (const float*)inputBuffer; /* */ float* const outsPtr = (float*)outputBuffer; // assert rtaudio buffers CARLA_SAFE_ASSERT_RETURN(outputBuffer != nullptr,); // set rtaudio buffers as non-interleaved const float* inBuf[fAudioInCount]; /* */ float* outBuf[fAudioOutCount]; if (fAudioInterleaved) { // FIXME - this looks completely wrong! float* inBuf2[fAudioInCount]; for (uint i=0, count=fAudioInCount; ievents.in, kMaxEngineEventInternalCount); carla_zeroStructs(pData->events.out, kMaxEngineEventInternalCount); if (fMidiInEvents.mutex.tryLock()) { uint32_t engineEventIndex = 0; fMidiInEvents.splice(); for (LinkedList::Itenerator it = fMidiInEvents.data.begin2(); it.valid(); it.next()) { static const RtMidiEvent fallback = { 0, 0, { 0 } }; const RtMidiEvent& midiEvent(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(midiEvent.size > 0); EngineEvent& engineEvent(pData->events.in[engineEventIndex++]); if (midiEvent.time < pData->timeInfo.frame) { engineEvent.time = 0; } else if (midiEvent.time >= pData->timeInfo.frame + nframes) { carla_stderr("MIDI Event in the future!, %i vs %i", engineEvent.time, pData->timeInfo.frame); engineEvent.time = static_cast(pData->timeInfo.frame) + nframes - 1; } else engineEvent.time = static_cast(midiEvent.time - pData->timeInfo.frame); engineEvent.fillFromMidiData(midiEvent.size, midiEvent.data, 0); if (engineEventIndex >= kMaxEngineEventInternalCount) break; } fMidiInEvents.data.clear(); fMidiInEvents.mutex.unlock(); } pData->graph.process(pData, inBuf, outBuf, nframes); fMidiOutMutex.lock(); if (fMidiOuts.count() > 0) { uint8_t size = 0; uint8_t mdata[3] = { 0, 0, 0 }; uint8_t mdataTmp[EngineMidiEvent::kDataSize]; const uint8_t* mdataPtr; for (ushort i=0; i < kMaxEngineEventInternalCount; ++i) { const EngineEvent& engineEvent(pData->events.out[i]); /**/ if (engineEvent.type == kEngineEventTypeNull) { break; } else if (engineEvent.type == kEngineEventTypeControl) { const EngineControlEvent& ctrlEvent(engineEvent.ctrl); size = ctrlEvent.convertToMidiData(engineEvent.channel, mdata); mdataPtr = mdata; } else if (engineEvent.type == kEngineEventTypeMidi) { const EngineMidiEvent& midiEvent(engineEvent.midi); size = midiEvent.size; CARLA_SAFE_ASSERT_CONTINUE(size > 0); if (size > EngineMidiEvent::kDataSize) { CARLA_SAFE_ASSERT_CONTINUE(midiEvent.dataExt != nullptr); mdataPtr = midiEvent.dataExt; } else { // set first byte mdataTmp[0] = static_cast(midiEvent.data[0] | (engineEvent.channel & MIDI_CHANNEL_BIT)); // copy rest carla_copy(mdataTmp+1, midiEvent.data+1, size-1U); // done mdataPtr = mdataTmp; } } else { continue; } if (size > 0) { fMidiOutVector.assign(mdataPtr, mdataPtr + size); for (LinkedList::Itenerator it=fMidiOuts.begin2(); it.valid(); it.next()) { static MidiOutPort fallback = { nullptr, { '\0' } }; MidiOutPort& outPort(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); outPort.port->sendMessage(&fMidiOutVector); } } } } fMidiOutMutex.unlock(); if (fAudioInterleaved) { for (uint i=0; i < nframes; ++i) for (uint j=0; jbufferSize, newBufferSize); if (pData->bufferSize == newBufferSize) return; if (fAudioInCount > 0) { delete[] fAudioIntBufIn; fAudioIntBufIn = new float[fAudioInCount*newBufferSize]; } if (fAudioOutCount > 0) { delete[] fAudioIntBufOut; fAudioIntBufOut = new float[fAudioOutCount*newBufferSize]; } pData->bufferSize = newBufferSize; bufferSizeChanged(newBufferSize); } void handleMidiCallback(double timeStamp, std::vector* const message) { const size_t messageSize(message->size()); if (messageSize == 0 || messageSize > EngineMidiEvent::kDataSize) return; timeStamp /= 2; if (timeStamp > 0.95) timeStamp = 0.95; else if (timeStamp < 0.0) timeStamp = 0.0; RtMidiEvent midiEvent; midiEvent.time = pData->timeInfo.frame + uint64_t(timeStamp * (double)pData->bufferSize); if (midiEvent.time < fLastEventTime) midiEvent.time = fLastEventTime; else fLastEventTime = midiEvent.time; midiEvent.size = static_cast(messageSize); size_t i=0; for (; i < messageSize; ++i) midiEvent.data[i] = message->at(i); for (; i < EngineMidiEvent::kDataSize; ++i) midiEvent.data[i] = 0; fMidiInEvents.append(midiEvent); } // ------------------------------------------------------------------- bool connectExternalGraphPort(const uint connectionType, const uint portId, const char* const portName) override { CARLA_SAFE_ASSERT_RETURN(connectionType != 0 || (portName != nullptr && portName[0] != '\0'), false); carla_debug("CarlaEngineRtAudio::connectExternalGraphPort(%u, %u, \"%s\")", connectionType, portId, portName); switch (connectionType) { case kExternalGraphConnectionAudioIn1: case kExternalGraphConnectionAudioIn2: case kExternalGraphConnectionAudioOut1: case kExternalGraphConnectionAudioOut2: return CarlaEngine::connectExternalGraphPort(connectionType, portId, portName); case kExternalGraphConnectionMidiInput: { CarlaString newRtMidiPortName; newRtMidiPortName += getName(); newRtMidiPortName += ":"; newRtMidiPortName += portName; RtMidiIn* rtMidiIn; try { rtMidiIn = new RtMidiIn(getMatchedAudioMidiAPI(fAudio.getCurrentApi()), newRtMidiPortName.buffer(), 512); } CARLA_SAFE_EXCEPTION_RETURN("new RtMidiIn", false); rtMidiIn->ignoreTypes(); rtMidiIn->setCallback(carla_rtmidi_callback, this); bool found = false; uint rtMidiPortIndex; for (uint i=0, count=rtMidiIn->getPortCount(); i < count; ++i) { if (rtMidiIn->getPortName(i) == portName) { found = true; rtMidiPortIndex = i; break; } } if (! found) { delete rtMidiIn; return false; } try { rtMidiIn->openPort(rtMidiPortIndex, portName); } catch(...) { delete rtMidiIn; return false; }; MidiInPort midiPort; midiPort.port = rtMidiIn; std::strncpy(midiPort.name, portName, STR_MAX); midiPort.name[STR_MAX] = '\0'; fMidiIns.append(midiPort); return true; } break; case kExternalGraphConnectionMidiOutput: { CarlaString newRtMidiPortName; newRtMidiPortName += getName(); newRtMidiPortName += ":"; newRtMidiPortName += portName; RtMidiOut* rtMidiOut; try { rtMidiOut = new RtMidiOut(getMatchedAudioMidiAPI(fAudio.getCurrentApi()), newRtMidiPortName.buffer()); } CARLA_SAFE_EXCEPTION_RETURN("new RtMidiOut", false); bool found = false; uint rtMidiPortIndex; for (uint i=0, count=rtMidiOut->getPortCount(); i < count; ++i) { if (rtMidiOut->getPortName(i) == portName) { found = true; rtMidiPortIndex = i; break; } } if (! found) { delete rtMidiOut; return false; } try { rtMidiOut->openPort(rtMidiPortIndex, portName); } catch(...) { delete rtMidiOut; return false; }; MidiOutPort midiPort; midiPort.port = rtMidiOut; std::strncpy(midiPort.name, portName, STR_MAX); midiPort.name[STR_MAX] = '\0'; const CarlaMutexLocker cml(fMidiOutMutex); fMidiOuts.append(midiPort); return true; } break; } return false; } bool disconnectExternalGraphPort(const uint connectionType, const uint portId, const char* const portName) override { CARLA_SAFE_ASSERT_RETURN(connectionType != 0 || (portName != nullptr && portName[0] != '\0'), false); carla_debug("CarlaEngineRtAudio::disconnectExternalGraphPort(%u, %u, \"%s\")", connectionType, portId, portName); switch (connectionType) { case kExternalGraphConnectionAudioIn1: case kExternalGraphConnectionAudioIn2: case kExternalGraphConnectionAudioOut1: case kExternalGraphConnectionAudioOut2: return CarlaEngine::disconnectExternalGraphPort(connectionType, portId, portName); case kExternalGraphConnectionMidiInput: for (LinkedList::Itenerator it=fMidiIns.begin2(); it.valid(); it.next()) { static MidiInPort fallback = { nullptr, { '\0' } }; MidiInPort& inPort(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr); if (std::strncmp(inPort.name, portName, STR_MAX) != 0) continue; inPort.port->cancelCallback(); inPort.port->closePort(); delete inPort.port; fMidiIns.remove(it); return true; } break; case kExternalGraphConnectionMidiOutput: { const CarlaMutexLocker cml(fMidiOutMutex); for (LinkedList::Itenerator it=fMidiOuts.begin2(); it.valid(); it.next()) { static MidiOutPort fallback = { nullptr, { '\0' } }; MidiOutPort& outPort(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); if (std::strncmp(outPort.name, portName, STR_MAX) != 0) continue; outPort.port->closePort(); delete outPort.port; fMidiOuts.remove(it); return true; } } break; } return false; } // ------------------------------------------------------------------- private: RtAudio fAudio; // useful info bool fAudioInterleaved; uint fAudioInCount; uint fAudioOutCount; uint64_t fLastEventTime; // current device name CarlaString fDeviceName; // temp buffer for interleaved audio float* fAudioIntBufIn; float* fAudioIntBufOut; struct MidiInPort { RtMidiIn* port; char name[STR_MAX+1]; }; struct MidiOutPort { RtMidiOut* port; char name[STR_MAX+1]; }; struct RtMidiEvent { uint64_t time; // needs to compare to internal time uint8_t size; uint8_t data[EngineMidiEvent::kDataSize]; }; struct RtMidiEvents { CarlaMutex mutex; RtLinkedList::Pool dataPool; RtLinkedList data; RtLinkedList dataPending; RtMidiEvents() : mutex(), dataPool(512, 512), data(dataPool), dataPending(dataPool) {} ~RtMidiEvents() { clear(); } void append(const RtMidiEvent& event) { mutex.lock(); dataPending.append(event); mutex.unlock(); } void clear() { mutex.lock(); data.clear(); dataPending.clear(); mutex.unlock(); } void splice() { if (dataPending.count() > 0) dataPending.moveTo(data, true /* append */); } }; LinkedList fMidiIns; RtMidiEvents fMidiInEvents; LinkedList fMidiOuts; CarlaMutex fMidiOutMutex; std::vector fMidiOutVector; #define handlePtr ((CarlaEngineRtAudio*)userData) static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, uint nframes, double streamTime, RtAudioStreamStatus status, void* userData) { handlePtr->handleAudioProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status); return 0; } static bool carla_rtaudio_buffer_size_callback(unsigned int bufferSize, void* userData) { handlePtr->handleBufferSizeCallback(bufferSize); return true; } static void carla_rtmidi_callback(double timeStamp, std::vector* message, void* userData) { handlePtr->handleMidiCallback(timeStamp, message); } #undef handlePtr CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineRtAudio) }; // ----------------------------------------- CarlaEngine* CarlaEngine::newRtAudio(const AudioApi api) { initRtAudioAPIsIfNeeded(); RtAudio::Api rtApi = RtAudio::UNSPECIFIED; switch (api) { case AUDIO_API_NULL: rtApi = RtAudio::RTAUDIO_DUMMY; break; case AUDIO_API_JACK: rtApi = RtAudio::UNIX_JACK; break; case AUDIO_API_OSS: rtApi = RtAudio::LINUX_OSS; break; case AUDIO_API_ALSA: rtApi = RtAudio::LINUX_ALSA; break; case AUDIO_API_PULSEAUDIO: rtApi = RtAudio::UNIX_PULSE; break; case AUDIO_API_COREAUDIO: rtApi = RtAudio::MACOSX_CORE; break; case AUDIO_API_ASIO: rtApi = RtAudio::WINDOWS_ASIO; break; case AUDIO_API_DIRECTSOUND: rtApi = RtAudio::WINDOWS_DS; break; case AUDIO_API_WASAPI: rtApi = RtAudio::WINDOWS_WASAPI; break; } return new CarlaEngineRtAudio(rtApi); } uint CarlaEngine::getRtAudioApiCount() { initRtAudioAPIsIfNeeded(); return static_cast(gRtAudioApis.size()); } const char* CarlaEngine::getRtAudioApiName(const uint index) { initRtAudioAPIsIfNeeded(); CARLA_SAFE_ASSERT_RETURN(index < gRtAudioApis.size(), nullptr); return CarlaBackend::getRtAudioApiName(gRtAudioApis[index]); } const char* const* CarlaEngine::getRtAudioApiDeviceNames(const uint index) { initRtAudioAPIsIfNeeded(); if (index >= gRtAudioApis.size()) return nullptr; const RtAudio::Api& api(gRtAudioApis[index]); CarlaStringList devNames; try { RtAudio rtAudio(api); const uint devCount(rtAudio.getDeviceCount()); if (devCount == 0) return nullptr; for (uint i=0; i < devCount; ++i) { RtAudio::DeviceInfo devInfo(rtAudio.getDeviceInfo(i)); if (devInfo.probed && devInfo.outputChannels > 0 /*&& (devInfo.nativeFormats & RTAUDIO_FLOAT32) != 0*/) devNames.append(devInfo.name.c_str()); } } CARLA_SAFE_EXCEPTION_RETURN("RtAudio device names", nullptr); gDeviceNames = devNames.toCharStringListPtr(); return gDeviceNames; } const EngineDriverDeviceInfo* CarlaEngine::getRtAudioDeviceInfo(const uint index, const char* const deviceName) { initRtAudioAPIsIfNeeded(); if (index >= gRtAudioApis.size()) return nullptr; static EngineDriverDeviceInfo devInfo = { 0x0, nullptr, nullptr }; static uint32_t dummyBufferSizes[] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 0 }; static double dummySampleRates[] = { 22050.0, 32000.0, 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0, 0.0 }; // reset devInfo.hints = 0x0; // cleanup if (devInfo.bufferSizes != nullptr && devInfo.bufferSizes != dummyBufferSizes) { delete[] devInfo.bufferSizes; devInfo.bufferSizes = nullptr; } if (devInfo.sampleRates != nullptr && devInfo.sampleRates != dummySampleRates) { delete[] devInfo.sampleRates; devInfo.sampleRates = nullptr; } const RtAudio::Api& api(gRtAudioApis[index]); if (api == RtAudio::UNIX_JACK) { devInfo.bufferSizes = nullptr; devInfo.sampleRates = nullptr; return &devInfo; } RtAudio::DeviceInfo rtAudioDevInfo; try { RtAudio rtAudio(api); const uint devCount(rtAudio.getDeviceCount()); if (devCount == 0) return nullptr; uint i; for (i=0; i < devCount; ++i) { rtAudioDevInfo = rtAudio.getDeviceInfo(i); if (rtAudioDevInfo.name == deviceName) break; } if (i == devCount) rtAudioDevInfo = rtAudio.getDeviceInfo(rtAudio.getDefaultOutputDevice()); } CARLA_SAFE_EXCEPTION_RETURN("RtAudio device discovery", nullptr); // a few APIs can do triple buffer switch (api) { case RtAudio::LINUX_ALSA: case RtAudio::LINUX_OSS: case RtAudio::WINDOWS_DS: devInfo.hints |= ENGINE_DRIVER_DEVICE_CAN_TRIPLE_BUFFER; break; default: break; } // always use default buffer sizes devInfo.bufferSizes = dummyBufferSizes; // valid sample rates if (const size_t sampleRatesCount = rtAudioDevInfo.sampleRates.size()) { double* const sampleRates(new double[sampleRatesCount+1]); for (size_t i=0; i < sampleRatesCount; ++i) sampleRates[i] = rtAudioDevInfo.sampleRates[i]; sampleRates[sampleRatesCount] = 0.0; devInfo.sampleRates = sampleRates; } else { devInfo.sampleRates = dummySampleRates; } return &devInfo; } // ----------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/engine/CarlaEngineThread.cpp000066400000000000000000000116341364475620200225540ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaEngineThread.hpp" #include "CarlaEngineInternal.hpp" #include "CarlaPlugin.hpp" #include "water/misc/Time.h" CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- CarlaEngineThread::CarlaEngineThread(CarlaEngine* const engine) noexcept : CarlaThread("CarlaEngineThread"), kEngine(engine) { CARLA_SAFE_ASSERT(engine != nullptr); carla_debug("CarlaEngineThread::CarlaEngineThread(%p)", engine); } CarlaEngineThread::~CarlaEngineThread() noexcept { carla_debug("CarlaEngineThread::~CarlaEngineThread()"); } // ----------------------------------------------------------------------- void CarlaEngineThread::run() noexcept { CARLA_SAFE_ASSERT_RETURN(kEngine != nullptr,); carla_debug("CarlaEngineThread::run()"); const bool kIsPlugin = kEngine->getType() == kEngineTypePlugin; const bool kIsAlwaysRunning = kEngine->getType() == kEngineTypeBridge || kIsPlugin; float value; #if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) // int64_t lastPingTime = 0; const CarlaEngineOsc& engineOsc(kEngine->pData->osc); #endif // thread must do something... CARLA_SAFE_ASSERT_RETURN(kIsAlwaysRunning || kEngine->isRunning(),); for (; (kIsAlwaysRunning || kEngine->isRunning()) && ! shouldThreadExit();) { #if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) const bool oscRegistedForUDP = engineOsc.isControlRegisteredForUDP(); #else const bool oscRegistedForUDP = false; #endif #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (kIsPlugin) engineOsc.idle(); #endif for (uint i=0, count = kEngine->getCurrentPluginCount(); i < count; ++i) { CarlaPlugin* const plugin(kEngine->getPluginUnchecked(i)); CARLA_SAFE_ASSERT_CONTINUE(plugin != nullptr && plugin->isEnabled()); CARLA_SAFE_ASSERT_UINT2(i == plugin->getId(), i, plugin->getId()); const uint hints(plugin->getHints()); const bool updateUI((hints & PLUGIN_HAS_CUSTOM_UI) != 0 && (hints & PLUGIN_NEEDS_UI_MAIN_THREAD) == 0); // ----------------------------------------------------------- // DSP Idle try { plugin->idle(); } CARLA_SAFE_EXCEPTION("idle()") // ----------------------------------------------------------- // Post-poned events if (oscRegistedForUDP || updateUI) { // ------------------------------------------------------- // Update parameter outputs for (uint32_t j=0, pcount=plugin->getParameterCount(); j < pcount; ++j) { if (! plugin->isParameterOutput(j)) continue; value = plugin->getParameterValue(j); #if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) // Update OSC engine client if (oscRegistedForUDP) engineOsc.sendParameterValue(i, j, value); #endif // Update UI if (updateUI) plugin->uiParameterChange(j, value); } if (updateUI) { try { plugin->uiIdle(); } CARLA_SAFE_EXCEPTION("uiIdle()") } } #if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) // ----------------------------------------------------------- // Update OSC control client peaks if (oscRegistedForUDP) engineOsc.sendPeaks(i, kEngine->getPeaks(i)); #endif } #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (oscRegistedForUDP) engineOsc.sendRuntimeInfo(); /* if (engineOsc.isControlRegisteredForTCP()) { const int64_t timeNow = water::Time::currentTimeMillis(); if (timeNow - lastPingTime > 1000) { engineOsc.sendPing(); lastPingTime = timeNow; } } */ #endif carla_msleep(25); } carla_debug("CarlaEngineThread closed"); } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/engine/CarlaEngineThread.hpp000066400000000000000000000026101364475620200225530ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2014 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_ENGINE_THREAD_HPP_INCLUDED #define CARLA_ENGINE_THREAD_HPP_INCLUDED #include "CarlaBackend.h" #include "CarlaThread.hpp" #include "CarlaJuceUtils.hpp" CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // CarlaEngineThread class CarlaEngineThread : public CarlaThread { public: CarlaEngineThread(CarlaEngine* engine) noexcept; ~CarlaEngineThread() noexcept override; protected: void run() noexcept override; private: CarlaEngine* const kEngine; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineThread) }; // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE #endif // CARLA_ENGINE_THREAD_HPP_INCLUDED Carla-2.1/source/backend/engine/Makefile000066400000000000000000000061251364475620200202070ustar00rootroot00000000000000#!/usr/bin/make -f # Makefile for carla-engine # # ------------------------- # # Created by falkTX # CWD=../.. include ../Makefile.mk # Workaround GCC bug ifeq ($(TESTBUILD),true) ifeq ($(USING_JUCE),true) BUILD_CXX_FLAGS += -Wno-undef endif endif # --------------------------------------------------------------------------------------------------------------------- OBJS = \ $(OBJDIR)/CarlaEngine.cpp.o \ $(OBJDIR)/CarlaEngineClient.cpp.o \ $(OBJDIR)/CarlaEngineData.cpp.o \ $(OBJDIR)/CarlaEngineDummy.cpp.o \ $(OBJDIR)/CarlaEngineGraph.cpp.o \ $(OBJDIR)/CarlaEngineInternal.cpp.o \ $(OBJDIR)/CarlaEnginePorts.cpp.o \ $(OBJDIR)/CarlaEngineThread.cpp.o ifeq ($(HAVE_LIBLO),true) OBJS += \ $(OBJDIR)/CarlaEngineOsc.cpp.o \ $(OBJDIR)/CarlaEngineOscHandlers.cpp.o \ $(OBJDIR)/CarlaEngineOscSend.cpp.o endif OBJSa = $(OBJS) \ $(OBJDIR)/CarlaEngineJack.cpp.o \ $(OBJDIR)/CarlaEngineNative.cpp.o ifeq ($(USING_JUCE),true) OBJSa += \ $(OBJDIR)/CarlaEngineJuce.cpp.o else OBJSa += \ $(OBJDIR)/CarlaEngineRtAudio.cpp.o endif OBJSp = $(OBJS) \ $(OBJDIR)/CarlaEngineNative.cpp.exp.o TARGETS = \ $(MODULEDIR)/carla_engine.a \ $(MODULEDIR)/carla_engine_plugin.a # --------------------------------------------------------------------------------------------------------------------- all: $(TARGETS) # --------------------------------------------------------------------------------------------------------------------- clean: rm -f $(OBJSa) $(OBJSp) $(TARGETS) debug: $(MAKE) DEBUG=true # --------------------------------------------------------------------------------------------------------------------- $(MODULEDIR)/carla_engine.a: $(OBJSa) -@mkdir -p $(MODULEDIR) @echo "Creating carla_engine.a" @rm -f $@ @$(AR) crs $@ $^ $(MODULEDIR)/carla_engine_plugin.a: $(OBJSp) -@mkdir -p $(MODULEDIR) @echo "Creating carla_engine_plugin.a" @rm -f $@ @$(AR) crs $@ $^ # --------------------------------------------------------------------------------------------------------------------- $(OBJDIR)/CarlaEngineRtAudio.cpp.o: CarlaEngineRtAudio.cpp -@mkdir -p $(OBJDIR) @echo "Compiling CarlaEngineRtAudio.cpp" @$(CXX) $< $(BUILD_CXX_FLAGS) $(RTAUDIO_FLAGS) $(RTMIDI_FLAGS) -c -o $@ ifeq ($(MACOS),true) $(OBJDIR)/CarlaEngineNative.cpp.exp.o: CarlaEngineNative.cpp -@mkdir -p $(OBJDIR) @echo "Compiling CarlaEngineNative.cpp (plugin)" @$(CXX) $< $(BUILD_CXX_FLAGS) -DCARLA_PLUGIN_EXPORT -ObjC++ -c -o $@ else $(OBJDIR)/CarlaEngineNative.cpp.exp.o: CarlaEngineNative.cpp -@mkdir -p $(OBJDIR) @echo "Compiling CarlaEngineNative.cpp (plugin)" @$(CXX) $< $(BUILD_CXX_FLAGS) -DCARLA_PLUGIN_EXPORT -c -o $@ endif ifeq ($(JACKBRIDGE_DIRECT),true) $(OBJDIR)/CarlaEngineJack.cpp.o: CarlaEngineJack.cpp -@mkdir -p $(OBJDIR) @echo "Compiling CarlaEngineJack.cpp" @$(CXX) $< $(BUILD_CXX_FLAGS) $(JACK_FLAGS) -c -o $@ endif $(OBJDIR)/%.cpp.o: %.cpp -@mkdir -p $(OBJDIR) @echo "Compiling $<" @$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ -include $(OBJSa:%.o=%.d) -include $(OBJDIR)/CarlaEngineNative.cpp.exp.d # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/plugin/000077500000000000000000000000001364475620200165745ustar00rootroot00000000000000Carla-2.1/source/backend/plugin/CarlaPlugin.cpp000066400000000000000000002536451364475620200215200ustar00rootroot00000000000000/* * Carla Plugin * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaPluginInternal.hpp" #include "CarlaEngine.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaBase64Utils.hpp" #include "CarlaMathUtils.hpp" #include "CarlaPluginUI.hpp" #include "CarlaScopeUtils.hpp" #include "CarlaStringList.hpp" #include #include "water/files/File.h" #include "water/streams/MemoryOutputStream.h" #include "water/xml/XmlDocument.h" #include "water/xml/XmlElement.h" using water::CharPointer_UTF8; using water::File; using water::MemoryOutputStream; using water::Result; using water::String; using water::XmlDocument; using water::XmlElement; CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------- // Fallback data static const ParameterData kParameterDataNull = { PARAMETER_UNKNOWN, 0x0, PARAMETER_NULL, -1, 0, CONTROL_INDEX_NONE, 0.0f, 1.0f }; static const ParameterRanges kParameterRangesNull = { 0.0f, 0.0f, 1.0f, 0.01f, 0.0001f, 0.1f }; static const MidiProgramData kMidiProgramDataNull = { 0, 0, nullptr }; static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr }; static /* */ CustomData kCustomDataFallbackNC = { nullptr, nullptr, nullptr }; static const PluginPostRtEvent kPluginPostRtEventFallback = { kPluginPostRtEventNull, false, 0, 0, 0, 0.0f }; // ------------------------------------------------------------------- // ParamSymbol struct, needed for CarlaPlugin::loadStateSave() struct ParamSymbol { int32_t index; const char* symbol; ParamSymbol(const uint32_t i, const char* const s) : index(static_cast(i)), symbol(carla_strdup(s)) {} ~ParamSymbol() noexcept { CARLA_SAFE_ASSERT_RETURN(symbol != nullptr,) delete[] symbol; symbol = nullptr; } #ifdef CARLA_PROPER_CPP11_SUPPORT ParamSymbol() = delete; CARLA_DECLARE_NON_COPY_STRUCT(ParamSymbol) #endif }; // ------------------------------------------------------------------- // Constructor and destructor CarlaPlugin::CarlaPlugin(CarlaEngine* const engine, const uint id) : pData(new ProtectedData(engine, id)) { CARLA_SAFE_ASSERT_RETURN(engine != nullptr,); CARLA_SAFE_ASSERT(id < engine->getMaxPluginNumber()); carla_debug("CarlaPlugin::CarlaPlugin(%p, %i)", engine, id); switch (engine->getProccessMode()) { case ENGINE_PROCESS_MODE_SINGLE_CLIENT: case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS: CARLA_SAFE_ASSERT(id < MAX_DEFAULT_PLUGINS); break; case ENGINE_PROCESS_MODE_CONTINUOUS_RACK: CARLA_SAFE_ASSERT(id < MAX_RACK_PLUGINS); break; case ENGINE_PROCESS_MODE_PATCHBAY: CARLA_SAFE_ASSERT(id < MAX_PATCHBAY_PLUGINS); break; case ENGINE_PROCESS_MODE_BRIDGE: CARLA_SAFE_ASSERT(id == 0); break; } } CarlaPlugin::~CarlaPlugin() { carla_debug("CarlaPlugin::~CarlaPlugin()"); delete pData; } // ------------------------------------------------------------------- // Information (base) uint CarlaPlugin::getId() const noexcept { return pData->id; } uint CarlaPlugin::getHints() const noexcept { return pData->hints; } uint CarlaPlugin::getOptionsEnabled() const noexcept { return pData->options; } bool CarlaPlugin::isEnabled() const noexcept { return pData->enabled; } const char* CarlaPlugin::getName() const noexcept { return pData->name; } const char* CarlaPlugin::getFilename() const noexcept { return pData->filename; } const char* CarlaPlugin::getIconName() const noexcept { return pData->iconName; } PluginCategory CarlaPlugin::getCategory() const noexcept { return getPluginCategoryFromName(pData->name); } int64_t CarlaPlugin::getUniqueId() const noexcept { return 0; } uint32_t CarlaPlugin::getLatencyInFrames() const noexcept { return 0; } // ------------------------------------------------------------------- // Information (count) uint32_t CarlaPlugin::getAudioInCount() const noexcept { return pData->audioIn.count; } uint32_t CarlaPlugin::getAudioOutCount() const noexcept { return pData->audioOut.count; } uint32_t CarlaPlugin::getCVInCount() const noexcept { return pData->cvIn.count; } uint32_t CarlaPlugin::getCVOutCount() const noexcept { return pData->cvOut.count; } uint32_t CarlaPlugin::getMidiInCount() const noexcept { return (pData->extraHints & PLUGIN_EXTRA_HINT_HAS_MIDI_IN) ? 1 : 0; } uint32_t CarlaPlugin::getMidiOutCount() const noexcept { return (pData->extraHints & PLUGIN_EXTRA_HINT_HAS_MIDI_OUT) ? 1 : 0; } uint32_t CarlaPlugin::getParameterCount() const noexcept { return pData->param.count; } uint32_t CarlaPlugin::getParameterScalePointCount(const uint32_t parameterId) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0); return 0; } uint32_t CarlaPlugin::getProgramCount() const noexcept { return pData->prog.count; } uint32_t CarlaPlugin::getMidiProgramCount() const noexcept { return pData->midiprog.count; } uint32_t CarlaPlugin::getCustomDataCount() const noexcept { return static_cast(pData->custom.count()); } // ------------------------------------------------------------------- // Information (current data) int32_t CarlaPlugin::getCurrentProgram() const noexcept { return pData->prog.current; } int32_t CarlaPlugin::getCurrentMidiProgram() const noexcept { return pData->midiprog.current; } const ParameterData& CarlaPlugin::getParameterData(const uint32_t parameterId) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, kParameterDataNull); return pData->param.data[parameterId]; } const ParameterRanges& CarlaPlugin::getParameterRanges(const uint32_t parameterId) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, kParameterRangesNull); return pData->param.ranges[parameterId]; } bool CarlaPlugin::isParameterOutput(const uint32_t parameterId) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); return (pData->param.data[parameterId].type == PARAMETER_OUTPUT); } const MidiProgramData& CarlaPlugin::getMidiProgramData(const uint32_t index) const noexcept { CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count, kMidiProgramDataNull); return pData->midiprog.data[index]; } const CustomData& CarlaPlugin::getCustomData(const uint32_t index) const noexcept { return pData->custom.getAt(index, kCustomDataFallback); } std::size_t CarlaPlugin::getChunkData(void** const dataPtr) noexcept { CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0); CARLA_SAFE_ASSERT(false); // this should never happen return 0; } // ------------------------------------------------------------------- // Information (per-plugin data) uint CarlaPlugin::getOptionsAvailable() const noexcept { CARLA_SAFE_ASSERT(false); // this should never happen return 0x0; } float CarlaPlugin::getParameterValue(const uint32_t parameterId) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), 0.0f); CARLA_SAFE_ASSERT(false); // this should never happen return 0.0f; } float CarlaPlugin::getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), 0.0f); CARLA_SAFE_ASSERT_RETURN(scalePointId < getParameterScalePointCount(parameterId), 0.0f); CARLA_SAFE_ASSERT(false); // this should never happen return 0.0f; } bool CarlaPlugin::getLabel(char* const strBuf) const noexcept { strBuf[0] = '\0'; return false; } bool CarlaPlugin::getMaker(char* const strBuf) const noexcept { strBuf[0] = '\0'; return false; } bool CarlaPlugin::getCopyright(char* const strBuf) const noexcept { strBuf[0] = '\0'; return false; } bool CarlaPlugin::getRealName(char* const strBuf) const noexcept { strBuf[0] = '\0'; return false; } bool CarlaPlugin::getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false); CARLA_SAFE_ASSERT(false); // this should never happen strBuf[0] = '\0'; return false; } bool CarlaPlugin::getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false); strBuf[0] = '\0'; return false; } bool CarlaPlugin::getParameterText(const uint32_t parameterId, char* const strBuf) noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false); CARLA_SAFE_ASSERT(false); // this should never happen strBuf[0] = '\0'; return false; } bool CarlaPlugin::getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false); strBuf[0] = '\0'; return false; } bool CarlaPlugin::getParameterComment(const uint32_t parameterId, char* const strBuf) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false); strBuf[0] = '\0'; return false; } bool CarlaPlugin::getParameterGroupName(const uint32_t parameterId, char* const strBuf) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false); strBuf[0] = '\0'; return false; } bool CarlaPlugin::getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false); CARLA_SAFE_ASSERT_RETURN(scalePointId < getParameterScalePointCount(parameterId), false); CARLA_SAFE_ASSERT(false); // this should never happen strBuf[0] = '\0'; return false; } float CarlaPlugin::getInternalParameterValue(const int32_t parameterId) const noexcept { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT_RETURN(parameterId != PARAMETER_NULL && parameterId > PARAMETER_MAX, 0.0f); switch (parameterId) { case PARAMETER_ACTIVE: return pData->active; case PARAMETER_CTRL_CHANNEL: return pData->ctrlChannel; case PARAMETER_DRYWET: return pData->postProc.dryWet; case PARAMETER_VOLUME: return pData->postProc.volume; case PARAMETER_BALANCE_LEFT: return pData->postProc.balanceLeft; case PARAMETER_BALANCE_RIGHT: return pData->postProc.balanceRight; case PARAMETER_PANNING: return pData->postProc.panning; }; #endif CARLA_SAFE_ASSERT_RETURN(parameterId >= 0, 0.0f); return getParameterValue(static_cast(parameterId)); } bool CarlaPlugin::getProgramName(const uint32_t index, char* const strBuf) const noexcept { CARLA_SAFE_ASSERT_RETURN(index < pData->prog.count, false); CARLA_SAFE_ASSERT_RETURN(pData->prog.names[index] != nullptr, false); std::strncpy(strBuf, pData->prog.names[index], STR_MAX); return true; } bool CarlaPlugin::getMidiProgramName(const uint32_t index, char* const strBuf) const noexcept { CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count, false); CARLA_SAFE_ASSERT_RETURN(pData->midiprog.data[index].name != nullptr, false); std::strncpy(strBuf, pData->midiprog.data[index].name, STR_MAX); return true; } void CarlaPlugin::getParameterCountInfo(uint32_t& ins, uint32_t& outs) const noexcept { ins = 0; outs = 0; for (uint32_t i=0; i < pData->param.count; ++i) { if (pData->param.data[i].type == PARAMETER_INPUT) ++ins; else if (pData->param.data[i].type == PARAMETER_OUTPUT) ++outs; } } // ------------------------------------------------------------------- // Set data (state) void CarlaPlugin::prepareForSave() { } void CarlaPlugin::resetParameters() noexcept { for (uint i=0; i < pData->param.count; ++i) { const ParameterData& paramData(pData->param.data[i]); const ParameterRanges& paramRanges(pData->param.ranges[i]); if (paramData.type != PARAMETER_INPUT) continue; if ((paramData.hints & PARAMETER_IS_ENABLED) == 0) continue; setParameterValue(i, paramRanges.def, true, true, true); } } void CarlaPlugin::randomizeParameters() noexcept { float value, random; char strBuf[STR_MAX+1]; strBuf[STR_MAX] = '\0'; std::srand(static_cast(std::time(nullptr))); for (uint i=0; i < pData->param.count; ++i) { const ParameterData& paramData(pData->param.data[i]); if (paramData.type != PARAMETER_INPUT) continue; if ((paramData.hints & PARAMETER_IS_ENABLED) == 0) continue; if (! getParameterName(i, strBuf)) strBuf[0] = '\0'; if (std::strstr(strBuf, "olume") != nullptr) continue; if (std::strstr(strBuf, "Master") != nullptr) continue; const ParameterRanges& paramRanges(pData->param.ranges[i]); if (paramData.hints & PARAMETER_IS_BOOLEAN) { random = static_cast(std::rand()) / static_cast(RAND_MAX); value = random > 0.5f ? paramRanges.max : paramRanges.min; } else { random = static_cast(std::rand()) / static_cast(RAND_MAX); value = random * (paramRanges.max - paramRanges.min) + paramRanges.min; if (paramData.hints & PARAMETER_IS_INTEGER) value = std::rint(value); } setParameterValue(i, value, true, true, true); } } const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave) { if (callPrepareForSave) prepareForSave(); pData->stateSave.clear(); const PluginType pluginType(getType()); char strBuf[STR_MAX+1]; carla_zeroChars(strBuf, STR_MAX+1); // --------------------------------------------------------------- // Basic info if (! getLabel(strBuf)) strBuf[0] = '\0'; pData->stateSave.type = carla_strdup(getPluginTypeAsString(pluginType)); pData->stateSave.name = carla_strdup(pData->name); pData->stateSave.label = carla_strdup(strBuf); pData->stateSave.uniqueId = getUniqueId(); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->stateSave.options = pData->options; #endif if (pData->filename != nullptr) pData->stateSave.binary = carla_strdup(pData->filename); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // --------------------------------------------------------------- // Internals pData->stateSave.active = pData->active; pData->stateSave.dryWet = pData->postProc.dryWet; pData->stateSave.volume = pData->postProc.volume; pData->stateSave.balanceLeft = pData->postProc.balanceLeft; pData->stateSave.balanceRight = pData->postProc.balanceRight; pData->stateSave.panning = pData->postProc.panning; pData->stateSave.ctrlChannel = pData->ctrlChannel; #endif bool usingChunk = false; // --------------------------------------------------------------- // Chunk if (pData->options & PLUGIN_OPTION_USE_CHUNKS) { void* data = nullptr; const std::size_t dataSize(getChunkData(&data)); if (data != nullptr && dataSize > 0) { pData->stateSave.chunk = CarlaString::asBase64(data, dataSize).dup(); if (pluginType != PLUGIN_INTERNAL) usingChunk = true; } } // --------------------------------------------------------------- // Current Program if (pData->prog.current >= 0 && pluginType != PLUGIN_LV2) { pData->stateSave.currentProgramIndex = pData->prog.current; pData->stateSave.currentProgramName = carla_strdup(pData->prog.names[pData->prog.current]); } // --------------------------------------------------------------- // Current MIDI Program if (pData->midiprog.current >= 0 && pluginType != PLUGIN_LV2 && pluginType != PLUGIN_SF2) { const MidiProgramData& mpData(pData->midiprog.getCurrent()); pData->stateSave.currentMidiBank = static_cast(mpData.bank); pData->stateSave.currentMidiProgram = static_cast(mpData.program); } // --------------------------------------------------------------- // Parameters const float sampleRate(static_cast(pData->engine->getSampleRate())); for (uint32_t i=0; i < pData->param.count; ++i) { const ParameterData& paramData(pData->param.data[i]); if ((paramData.hints & PARAMETER_IS_ENABLED) == 0) continue; const bool dummy = paramData.type != PARAMETER_INPUT || usingChunk; if (dummy && paramData.mappedControlIndex <= CONTROL_INDEX_NONE) continue; CarlaStateSave::Parameter* const stateParameter(new CarlaStateSave::Parameter()); stateParameter->dummy = dummy; stateParameter->index = paramData.index; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH stateParameter->mappedControlIndex = paramData.mappedControlIndex; stateParameter->midiChannel = paramData.midiChannel; if (paramData.hints & PARAMETER_MAPPED_RANGES_SET) { stateParameter->mappedMinimum = paramData.mappedMinimum; stateParameter->mappedMaximum = paramData.mappedMaximum; stateParameter->mappedRangeValid = true; if (paramData.hints & PARAMETER_USES_SAMPLERATE) { stateParameter->mappedMinimum /= sampleRate; stateParameter->mappedMaximum /= sampleRate; } } #endif if (! getParameterName(i, strBuf)) strBuf[0] = '\0'; stateParameter->name = carla_strdup(strBuf); if (! getParameterSymbol(i, strBuf)) strBuf[0] = '\0'; stateParameter->symbol = carla_strdup(strBuf);; if (! dummy) { stateParameter->value = getParameterValue(i); if (paramData.hints & PARAMETER_USES_SAMPLERATE) stateParameter->value /= sampleRate; } pData->stateSave.parameters.append(stateParameter); } // --------------------------------------------------------------- // Custom Data if (pData->hints & PLUGIN_IS_BRIDGE) waitForBridgeSaveSignal(); for (LinkedList::Itenerator it = pData->custom.begin2(); it.valid(); it.next()) { const CustomData& cData(it.getValue(kCustomDataFallback)); CARLA_SAFE_ASSERT_CONTINUE(cData.isValid()); CarlaStateSave::CustomData* stateCustomData(new CarlaStateSave::CustomData()); stateCustomData->type = carla_strdup(cData.type); stateCustomData->key = carla_strdup(cData.key); stateCustomData->value = carla_strdup(cData.value); pData->stateSave.customData.append(stateCustomData); } return pData->stateSave; } void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave) { const bool usesMultiProgs(pData->hints & PLUGIN_USES_MULTI_PROGS); const PluginType pluginType(getType()); char strBuf[STR_MAX+1]; carla_zeroChars(strBuf, STR_MAX+1); // --------------------------------------------------------------- // Part 1 - PRE-set custom data (only those which reload programs) for (CarlaStateSave::CustomDataItenerator it = stateSave.customData.begin2(); it.valid(); it.next()) { const CarlaStateSave::CustomData* const stateCustomData(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(stateCustomData != nullptr); CARLA_SAFE_ASSERT_CONTINUE(stateCustomData->isValid()); const char* const key(stateCustomData->key); /**/ if (pluginType == PLUGIN_DSSI && (std::strcmp (key, "reloadprograms") == 0 || std::strcmp (key, "load" ) == 0 || std::strncmp(key, "patches", 7) == 0 )) pass(); else if (usesMultiProgs && std::strcmp(key, "midiPrograms") == 0) pass(); else continue; setCustomData(stateCustomData->type, key, stateCustomData->value, true); } // --------------------------------------------------------------- // Part 2 - set program if (stateSave.currentProgramIndex >= 0 && stateSave.currentProgramName != nullptr) { int32_t programId = -1; // index < count if (stateSave.currentProgramIndex < static_cast(pData->prog.count)) { programId = stateSave.currentProgramIndex; } // index not valid, try to find by name else { for (uint32_t i=0; i < pData->prog.count; ++i) { if (getProgramName(i, strBuf) && std::strcmp(stateSave.currentProgramName, strBuf) == 0) { programId = static_cast(i); break; } } } // set program now, if valid if (programId >= 0) setProgram(programId, true, true, true); } // --------------------------------------------------------------- // Part 3 - set midi program if (stateSave.currentMidiBank >= 0 && stateSave.currentMidiProgram >= 0 && ! usesMultiProgs) setMidiProgramById(static_cast(stateSave.currentMidiBank), static_cast(stateSave.currentMidiProgram), true, true, true); // --------------------------------------------------------------- // Part 4a - get plugin parameter symbols LinkedList paramSymbols; if (pluginType == PLUGIN_LADSPA || pluginType == PLUGIN_LV2) { for (uint32_t i=0; i < pData->param.count; ++i) { if (getParameterSymbol(i, strBuf)) { ParamSymbol* const paramSymbol(new ParamSymbol(i, strBuf)); paramSymbols.append(paramSymbol); } } } // --------------------------------------------------------------- // Part 4b - set parameter values (carefully) const float sampleRate(static_cast(pData->engine->getSampleRate())); for (CarlaStateSave::ParameterItenerator it = stateSave.parameters.begin2(); it.valid(); it.next()) { CarlaStateSave::Parameter* const stateParameter(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(stateParameter != nullptr); int32_t index = -1; if (pluginType == PLUGIN_LADSPA) { // Try to set by symbol, otherwise use index if (stateParameter->symbol != nullptr && stateParameter->symbol[0] != '\0') { for (LinkedList::Itenerator it2 = paramSymbols.begin2(); it2.valid(); it2.next()) { ParamSymbol* const paramSymbol(it2.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(paramSymbol != nullptr); CARLA_SAFE_ASSERT_CONTINUE(paramSymbol->symbol != nullptr); if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0) { index = paramSymbol->index; break; } } if (index == -1) index = stateParameter->index; } else { index = stateParameter->index; } } else if (pluginType == PLUGIN_LV2) { // Symbol only if (stateParameter->symbol != nullptr && stateParameter->symbol[0] != '\0') { for (LinkedList::Itenerator it2 = paramSymbols.begin2(); it2.valid(); it2.next()) { ParamSymbol* const paramSymbol(it2.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(paramSymbol != nullptr); CARLA_SAFE_ASSERT_CONTINUE(paramSymbol->symbol != nullptr); if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0) { index = paramSymbol->index; break; } } if (index == -1) carla_stderr("Failed to find LV2 parameter symbol '%s' for '%s'", stateParameter->symbol, pData->name); } else { carla_stderr("LV2 Plugin parameter '%s' has no symbol", stateParameter->name); } } else { // Index only index = stateParameter->index; } // Now set parameter if (index >= 0 && index < static_cast(pData->param.count)) { //CARLA_SAFE_ASSERT(stateParameter->isInput == (pData if (! stateParameter->dummy) { if (pData->param.data[index].hints & PARAMETER_USES_SAMPLERATE) stateParameter->value *= sampleRate; setParameterValue(static_cast(index), stateParameter->value, true, true, true); } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (stateParameter->mappedRangeValid) { if (pData->param.data[index].hints & PARAMETER_USES_SAMPLERATE) { stateParameter->mappedMinimum *= sampleRate; stateParameter->mappedMaximum *= sampleRate; } setParameterMappedRange(static_cast(index), stateParameter->mappedMinimum, stateParameter->mappedMaximum, true, true); } setParameterMappedControlIndex(static_cast(index), stateParameter->mappedControlIndex, true, true); setParameterMidiChannel(static_cast(index), stateParameter->midiChannel, true, true); #endif } else carla_stderr("Could not set parameter '%s' value for '%s'", stateParameter->name, pData->name); } // --------------------------------------------------------------- // Part 4c - clear for (LinkedList::Itenerator it = paramSymbols.begin2(); it.valid(); it.next()) { ParamSymbol* const paramSymbol(it.getValue(nullptr)); delete paramSymbol; } paramSymbols.clear(); // --------------------------------------------------------------- // Part 5 - set custom data for (CarlaStateSave::CustomDataItenerator it = stateSave.customData.begin2(); it.valid(); it.next()) { const CarlaStateSave::CustomData* const stateCustomData(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(stateCustomData != nullptr); CARLA_SAFE_ASSERT_CONTINUE(stateCustomData->isValid()); const char* const key(stateCustomData->key); if (pluginType == PLUGIN_DSSI && (std::strcmp (key, "reloadprograms") == 0 || std::strcmp (key, "load" ) == 0 || std::strncmp(key, "patches", 7) == 0 )) continue; if (usesMultiProgs && std::strcmp(key, "midiPrograms") == 0) continue; setCustomData(stateCustomData->type, key, stateCustomData->value, true); } // --------------------------------------------------------------- // Part 5x - set lv2 state if (pluginType == PLUGIN_LV2) { for (LinkedList::Itenerator it = pData->custom.begin2(); it.valid(); it.next()) { const CustomData& customData(it.getValue(kCustomDataFallback)); CARLA_SAFE_ASSERT_CONTINUE(customData.isValid()); if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_PROPERTY) == 0) continue; restoreLV2State(); break; } } // --------------------------------------------------------------- // Part 6 - set chunk if (stateSave.chunk != nullptr && (pData->options & PLUGIN_OPTION_USE_CHUNKS) != 0) { std::vector chunk(carla_getChunkFromBase64String(stateSave.chunk)); #ifdef CARLA_PROPER_CPP11_SUPPORT setChunkData(chunk.data(), chunk.size()); #else setChunkData(&chunk.front(), chunk.size()); #endif } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // --------------------------------------------------------------- // Part 6 - set internal stuff const uint availOptions(getOptionsAvailable()); for (uint i=0; i<10; ++i) // FIXME - get this value somehow... { const uint option(1u << i); if (availOptions & option) setOption(option, (stateSave.options & option) != 0, true); } setDryWet(stateSave.dryWet, true, true); setVolume(stateSave.volume, true, true); setBalanceLeft(stateSave.balanceLeft, true, true); setBalanceRight(stateSave.balanceRight, true, true); setPanning(stateSave.panning, true, true); setCtrlChannel(stateSave.ctrlChannel, true, true); setActive(stateSave.active, true, true); if (! pData->engine->isLoadingProject()) pData->engine->callback(true, true, ENGINE_CALLBACK_UPDATE, pData->id, 0, 0, 0, 0.0f, nullptr); #endif } bool CarlaPlugin::saveStateToFile(const char* const filename) { CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false); carla_debug("CarlaPlugin::saveStateToFile(\"%s\")", filename); MemoryOutputStream out, streamState; getStateSave().dumpToMemoryStream(streamState); out << "\n"; out << "\n"; out << "\n"; out << streamState; out << "\n"; const String jfilename = String(CharPointer_UTF8(filename)); File file(jfilename); if (file.replaceWithData(out.getData(), out.getDataSize())) return true; pData->engine->setLastError("Failed to write file"); return false; } bool CarlaPlugin::loadStateFromFile(const char* const filename) { // TODO set errors CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false); carla_debug("CarlaPlugin::loadStateFromFile(\"%s\")", filename); const String jfilename = String(CharPointer_UTF8(filename)); File file(jfilename); CARLA_SAFE_ASSERT_RETURN(file.existsAsFile(), false); XmlDocument xml(file); CarlaScopedPointer xmlElement(xml.getDocumentElement(true)); CARLA_SAFE_ASSERT_RETURN(xmlElement != nullptr, false); CARLA_SAFE_ASSERT_RETURN(xmlElement->getTagName().equalsIgnoreCase("carla-preset"), false); // completely load file xmlElement = xml.getDocumentElement(false); CARLA_SAFE_ASSERT_RETURN(xmlElement != nullptr, false); if (pData->stateSave.fillFromXmlElement(xmlElement)) { loadStateSave(pData->stateSave); return true; } return false; } bool CarlaPlugin::exportAsLV2(const char* const lv2path) { CARLA_SAFE_ASSERT_RETURN(lv2path != nullptr && lv2path[0] != '\0', false); carla_debug("CarlaPlugin::exportAsLV2(\"%s\")", lv2path); CarlaString bundlepath(lv2path); if (! bundlepath.endsWith(".lv2")) bundlepath += ".lv2"; const File bundlefolder(bundlepath.buffer()); if (bundlefolder.existsAsFile()) { pData->engine->setLastError("Requested filename already exists as file, use a folder instead"); return false; } if (! bundlefolder.exists()) { const Result res(bundlefolder.createDirectory()); if (res.failed()) { pData->engine->setLastError(res.getErrorMessage().toRawUTF8()); return false; } } CarlaString symbol(pData->name); symbol.toBasic(); { const CarlaString pluginFilename(bundlepath + CARLA_OS_SEP_STR + symbol + ".xml"); if (! saveStateToFile(pluginFilename)) return false; } { MemoryOutputStream manifestStream; manifestStream << "@prefix lv2: .\n"; manifestStream << "@prefix rdfs: .\n"; manifestStream << "@prefix ui: .\n"; manifestStream << "\n"; manifestStream << "<" << symbol.buffer() << ".ttl>\n"; manifestStream << " a lv2:Plugin ;\n"; manifestStream << " lv2:binary <" << symbol.buffer() << CARLA_LIB_EXT "> ;\n"; manifestStream << " rdfs:seeAlso <" << symbol.buffer() << ".ttl> .\n"; manifestStream << "\n"; manifestStream << "\n"; manifestStream << " a ;\n"; manifestStream << " ui:binary <" << symbol.buffer() << CARLA_LIB_EXT "> ;\n"; manifestStream << " lv2:extensionData ,\n"; manifestStream << " ;\n"; manifestStream << " lv2:requiredFeature .\n"; manifestStream << "\n"; const CarlaString manifestFilename(bundlepath + CARLA_OS_SEP_STR "manifest.ttl"); const File manifestFile(manifestFilename.buffer()); if (! manifestFile.replaceWithData(manifestStream.getData(), manifestStream.getDataSize())) { pData->engine->setLastError("Failed to write manifest.ttl file"); return false; } } { MemoryOutputStream mainStream; mainStream << "@prefix atom: .\n"; mainStream << "@prefix doap: .\n"; mainStream << "@prefix foaf: .\n"; mainStream << "@prefix lv2: .\n"; mainStream << "@prefix rdfs: .\n"; mainStream << "@prefix ui: .\n"; mainStream << "\n"; mainStream << "<>\n"; mainStream << " a lv2:Plugin ;\n"; mainStream << "\n"; mainStream << " lv2:requiredFeature ,\n"; mainStream << " ,\n"; mainStream << " ;\n"; mainStream << "\n"; if (pData->hints & PLUGIN_HAS_CUSTOM_UI) { mainStream << " ui:ui ;\n"; mainStream << "\n"; } const uint32_t midiIns = getMidiInCount(); const uint32_t midiOuts = getMidiOutCount(); int portIndex = 0; if (midiIns > 0) { mainStream << " lv2:port [\n"; mainStream << " a lv2:InputPort, atom:AtomPort ;\n"; mainStream << " lv2:index 0 ;\n"; mainStream << " lv2:symbol \"clv2_events_in\" ;\n"; mainStream << " lv2:name \"Events Input\" ;\n"; mainStream << " atom:bufferType atom:Sequence ;\n"; mainStream << " atom:supports ,\n"; mainStream << " ;\n"; mainStream << " ] ;\n"; ++portIndex; for (uint32_t i=1; i ;\n"; mainStream << " ] ;\n"; ++portIndex; } for (uint32_t i=0; i ;\n"; mainStream << " ] ;\n"; } mainStream << " lv2:port [\n"; mainStream << " a lv2:InputPort, lv2:ControlPort ;\n"; mainStream << " lv2:index " << String(portIndex++) << " ;\n"; mainStream << " lv2:name \"freewheel\" ;\n"; mainStream << " lv2:symbol \"clv2_freewheel\" ;\n"; mainStream << " lv2:default 0 ;\n"; mainStream << " lv2:minimum 0 ;\n"; mainStream << " lv2:maximum 1 ;\n"; mainStream << " lv2:designation lv2:freeWheeling ;\n"; mainStream << " lv2:portProperty lv2:toggled , lv2:integer ;\n"; mainStream << " lv2:portProperty ;\n"; mainStream << " ] ;\n"; for (uint32_t i=0; iaudioIn.count; ++i) { const String portIndexNum(portIndex++); const String portIndexLabel(i+1); mainStream << " lv2:port [\n"; mainStream << " a lv2:InputPort, lv2:AudioPort ;\n"; mainStream << " lv2:index " << portIndexNum << " ;\n"; mainStream << " lv2:symbol \"clv2_audio_in_" << portIndexLabel << "\" ;\n"; mainStream << " lv2:name \"Audio Input " << portIndexLabel << "\" ;\n"; mainStream << " ] ;\n"; } for (uint32_t i=0; iaudioOut.count; ++i) { const String portIndexNum(portIndex++); const String portIndexLabel(i+1); mainStream << " lv2:port [\n"; mainStream << " a lv2:OutputPort, lv2:AudioPort ;\n"; mainStream << " lv2:index " << portIndexNum << " ;\n"; mainStream << " lv2:symbol \"clv2_audio_out_" << portIndexLabel << "\" ;\n"; mainStream << " lv2:name \"Audio Output " << portIndexLabel << "\" ;\n"; mainStream << " ] ;\n"; } CarlaStringList uniqueSymbolNames; char strBufName[STR_MAX+1]; char strBufSymbol[STR_MAX+1]; carla_zeroChars(strBufName, STR_MAX+1); carla_zeroChars(strBufSymbol, STR_MAX+1); for (uint32_t i=0; iparam.count; ++i) { const ParameterData& paramData(pData->param.data[i]); const ParameterRanges& paramRanges(pData->param.ranges[i]); const String portIndexNum(portIndex++); mainStream << " lv2:port [\n"; if (paramData.type == PARAMETER_INPUT) mainStream << " a lv2:InputPort, lv2:ControlPort ;\n"; else mainStream << " a lv2:OutputPort, lv2:ControlPort ;\n"; if (paramData.hints & PARAMETER_IS_BOOLEAN) mainStream << " lv2:portProperty lv2:toggled ;\n"; if (paramData.hints & PARAMETER_IS_INTEGER) mainStream << " lv2:portProperty lv2:integer ;\n"; // TODO logarithmic, enabled (not on gui), automable, samplerate, scalepoints if (! getParameterName(i, strBufName)) strBufName[0] = '\0'; if (! getParameterSymbol(i, strBufSymbol)) strBufSymbol[0] = '\0'; if (strBufSymbol[0] == '\0') { CarlaString s(strBufName); s.toBasic(); std::memcpy(strBufSymbol, s.buffer(), s.length()+1); if (strBufSymbol[0] >= '0' && strBufSymbol[0] <= '9') { const size_t len(std::strlen(strBufSymbol)); std::memmove(strBufSymbol+1, strBufSymbol, len); strBufSymbol[0] = '_'; strBufSymbol[len+1] = '\0'; } } if (uniqueSymbolNames.contains(strBufSymbol)) std::snprintf(strBufSymbol, STR_MAX, "clv2_param_%d", i+1); mainStream << " lv2:index " << portIndexNum << " ;\n"; mainStream << " lv2:symbol \"" << strBufSymbol << "\" ;\n"; mainStream << " lv2:name \"\"\"" << strBufName << "\"\"\" ;\n"; mainStream << " lv2:default " << String(paramRanges.def) << " ;\n"; mainStream << " lv2:minimum " << String(paramRanges.min) << " ;\n"; mainStream << " lv2:maximum " << String(paramRanges.max) << " ;\n"; // TODO midiCC, midiChannel mainStream << " ] ;\n"; } char strBuf[STR_MAX+1]; carla_zeroChars(strBuf, STR_MAX+1); if (! getMaker(strBuf)) strBuf[0] = '\0'; mainStream << " rdfs:comment \"Plugin generated using Carla LV2 export.\" ;\n"; mainStream << " doap:name \"\"\"" << getName() << "\"\"\" ;\n"; mainStream << " doap:maintainer [ foaf:name \"\"\"" << strBuf << "\"\"\" ] .\n"; mainStream << "\n"; const CarlaString mainFilename(bundlepath + CARLA_OS_SEP_STR + symbol + ".ttl"); const File mainFile(mainFilename.buffer()); if (! mainFile.replaceWithData(mainStream.getData(), mainStream.getDataSize())) { pData->engine->setLastError("Failed to write main plugin ttl file"); return false; } } const CarlaString binaryFilename(bundlepath + CARLA_OS_SEP_STR + symbol + CARLA_LIB_EXT); const File binaryFileSource(File::getSpecialLocation(File::currentExecutableFile).getSiblingFile("carla-bridge-lv2" CARLA_LIB_EXT)); const File binaryFileTarget(binaryFilename.buffer()); const EngineOptions& opts(pData->engine->getOptions()); const CarlaString binFolderTarget(bundlepath + CARLA_OS_SEP_STR + "bin"); const CarlaString resFolderTarget(bundlepath + CARLA_OS_SEP_STR + "res"); if (! binaryFileSource.copyFileTo(binaryFileTarget)) { pData->engine->setLastError("Failed to copy plugin binary"); return false; } #ifdef CARLA_OS_WIN File(opts.resourceDir).copyDirectoryTo(File(resFolderTarget.buffer())); // Copying all the binaries is pointless, just go through the expected needed bits const File binFolder1(opts.binaryDir); const File binFolder2(binFolderTarget.buffer()); binFolder2.createDirectory(); static const char* files[] = { "carla-bridge-native.exe", "carla-bridge-win32.exe", "carla-discovery-win32.exe", "carla-discovery-win64.exe", "libcarla_utils.dll" }; for (int i=0; i<5; ++i) binFolder1.getChildFile(files[i]).copyFileTo(binFolder2.getChildFile(files[i]));; #else File(opts.binaryDir).createSymbolicLink(File(binFolderTarget.buffer()), true); File(opts.resourceDir).createSymbolicLink(File(resFolderTarget.buffer()), true); #endif return true; } // ------------------------------------------------------------------- // Set data (internal stuff) void CarlaPlugin::setId(const uint newId) noexcept { pData->id = newId; } void CarlaPlugin::setName(const char* const newName) { CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0',); if (pData->name != nullptr) delete[] pData->name; pData->name = carla_strdup(newName); } void CarlaPlugin::setOption(const uint option, const bool yesNo, const bool sendCallback) { CARLA_SAFE_ASSERT_UINT2_RETURN(getOptionsAvailable() & option, getOptionsAvailable(), option,); if (yesNo) pData->options |= option; else pData->options &= ~option; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (sendCallback) pData->engine->callback(true, true, ENGINE_CALLBACK_OPTION_CHANGED, pData->id, static_cast(option), yesNo ? 1 : 0, 0, 0.0f, nullptr); #else // unused return; (void)sendCallback; #endif } void CarlaPlugin::setEnabled(const bool yesNo) noexcept { if (pData->enabled == yesNo) return; pData->masterMutex.lock(); pData->enabled = yesNo; if (yesNo && ! pData->client->isActive()) pData->client->activate(); pData->masterMutex.unlock(); } void CarlaPlugin::setActive(const bool active, const bool sendOsc, const bool sendCallback) noexcept { if (pData->engineBridged) { CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,); } else if (pData->enginePlugin) { // nothing here } else { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT } if (pData->active == active) return; { const ScopedSingleProcessLocker spl(this, true); if (active) activate(); else deactivate(); } pData->active = active; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH const float value = active ? 1.0f : 0.0f; pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_ACTIVE, 0, 0, value, nullptr); #endif } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH void CarlaPlugin::setDryWet(const float value, const bool sendOsc, const bool sendCallback) noexcept { if (pData->engineBridged) { CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,); } else { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT } CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f); const float fixedValue(carla_fixedValue(0.0f, 1.0f, value)); if (carla_isEqual(pData->postProc.dryWet, fixedValue)) return; pData->postProc.dryWet = fixedValue; pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_DRYWET, 0, 0, fixedValue, nullptr); } void CarlaPlugin::setVolume(const float value, const bool sendOsc, const bool sendCallback) noexcept { if (pData->engineBridged) { CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,); } else { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT } CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.27f); const float fixedValue(carla_fixedValue(0.0f, 1.27f, value)); if (carla_isEqual(pData->postProc.volume, fixedValue)) return; pData->postProc.volume = fixedValue; pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_VOLUME, 0, 0, fixedValue, nullptr); } void CarlaPlugin::setBalanceLeft(const float value, const bool sendOsc, const bool sendCallback) noexcept { if (pData->engineBridged) { CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,); } else { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT } CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f); const float fixedValue(carla_fixedValue(-1.0f, 1.0f, value)); if (carla_isEqual(pData->postProc.balanceLeft, fixedValue)) return; pData->postProc.balanceLeft = fixedValue; pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_BALANCE_LEFT, 0, 0, fixedValue, nullptr); } void CarlaPlugin::setBalanceRight(const float value, const bool sendOsc, const bool sendCallback) noexcept { if (pData->engineBridged) { CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,); } else { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT } CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f); const float fixedValue(carla_fixedValue(-1.0f, 1.0f, value)); if (carla_isEqual(pData->postProc.balanceRight, fixedValue)) return; pData->postProc.balanceRight = fixedValue; pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_BALANCE_RIGHT, 0, 0, fixedValue, nullptr); } void CarlaPlugin::setPanning(const float value, const bool sendOsc, const bool sendCallback) noexcept { if (pData->engineBridged) { CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,); } else { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT } CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f); const float fixedValue(carla_fixedValue(-1.0f, 1.0f, value)); if (carla_isEqual(pData->postProc.panning, fixedValue)) return; pData->postProc.panning = fixedValue; pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_PANNING, 0, 0, fixedValue, nullptr); } void CarlaPlugin::setDryWetRT(const float value, const bool sendCallbackLater) noexcept { CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f); const float fixedValue(carla_fixedValue(0.0f, 1.0f, value)); if (carla_isEqual(pData->postProc.dryWet, fixedValue)) return; pData->postProc.dryWet = fixedValue; pData->postponeRtEvent(kPluginPostRtEventParameterChange, sendCallbackLater, PARAMETER_DRYWET, 0, 0, fixedValue); } void CarlaPlugin::setVolumeRT(const float value, const bool sendCallbackLater) noexcept { CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.27f); const float fixedValue(carla_fixedValue(0.0f, 1.27f, value)); if (carla_isEqual(pData->postProc.volume, fixedValue)) return; pData->postProc.volume = fixedValue; pData->postponeRtEvent(kPluginPostRtEventParameterChange, sendCallbackLater, PARAMETER_VOLUME, 0, 0, fixedValue); } void CarlaPlugin::setBalanceLeftRT(const float value, const bool sendCallbackLater) noexcept { CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f); const float fixedValue(carla_fixedValue(-1.0f, 1.0f, value)); if (carla_isEqual(pData->postProc.balanceLeft, fixedValue)) return; pData->postProc.balanceLeft = fixedValue; pData->postponeRtEvent(kPluginPostRtEventParameterChange, sendCallbackLater, PARAMETER_BALANCE_LEFT, 0, 0, fixedValue); } void CarlaPlugin::setBalanceRightRT(const float value, const bool sendCallbackLater) noexcept { CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f); const float fixedValue(carla_fixedValue(-1.0f, 1.0f, value)); if (carla_isEqual(pData->postProc.balanceRight, fixedValue)) return; pData->postProc.balanceRight = fixedValue; pData->postponeRtEvent(kPluginPostRtEventParameterChange, sendCallbackLater, PARAMETER_BALANCE_RIGHT, 0, 0, fixedValue); } void CarlaPlugin::setPanningRT(const float value, const bool sendCallbackLater) noexcept { CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f); const float fixedValue(carla_fixedValue(-1.0f, 1.0f, value)); if (carla_isEqual(pData->postProc.panning, fixedValue)) return; pData->postProc.panning = fixedValue; pData->postponeRtEvent(kPluginPostRtEventParameterChange, sendCallbackLater, PARAMETER_PANNING, 0, 0, fixedValue); } #endif // ! BUILD_BRIDGE_ALTERNATIVE_ARCH void CarlaPlugin::setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept { if (pData->engineBridged) { CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,); } else { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT } CARLA_SAFE_ASSERT_RETURN(channel >= -1 && channel < MAX_MIDI_CHANNELS,); if (pData->ctrlChannel == channel) return; pData->ctrlChannel = channel; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH const float channelf = static_cast(channel); pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_CTRL_CHANNEL, 0, 0, channelf, nullptr); #endif } // ------------------------------------------------------------------- // Set data (plugin-specific stuff) void CarlaPlugin::setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept { if (pData->engineBridged) { // NOTE: some LV2 plugins feedback messages to UI on purpose CARLA_SAFE_ASSERT_RETURN(getType() == PLUGIN_LV2 || !sendGui,); } else if (pData->enginePlugin) { // nothing here } else { CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); // never call this from RT } CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0) uiParameterChange(parameterId, value); pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, static_cast(parameterId), 0, 0, value, nullptr); } void CarlaPlugin::setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept { pData->postponeRtEvent(kPluginPostRtEventParameterChange, sendCallbackLater, static_cast(parameterId), 0, 0, value); } void CarlaPlugin::setParameterValueByRealIndex(const int32_t rindex, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT_RETURN(rindex > PARAMETER_MAX && rindex != PARAMETER_NULL,); switch (rindex) { case PARAMETER_ACTIVE: return setActive((value > 0.0f), sendOsc, sendCallback); case PARAMETER_CTRL_CHANNEL: return setCtrlChannel(int8_t(value), sendOsc, sendCallback); case PARAMETER_DRYWET: return setDryWet(value, sendOsc, sendCallback); case PARAMETER_VOLUME: return setVolume(value, sendOsc, sendCallback); case PARAMETER_BALANCE_LEFT: return setBalanceLeft(value, sendOsc, sendCallback); case PARAMETER_BALANCE_RIGHT: return setBalanceRight(value, sendOsc, sendCallback); case PARAMETER_PANNING: return setPanning(value, sendOsc, sendCallback); } #endif CARLA_SAFE_ASSERT_RETURN(rindex >= 0,); for (uint32_t i=0; i < pData->param.count; ++i) { if (pData->param.data[i].rindex == rindex) { //if (carla_isNotEqual(getParameterValue(i), value)) setParameterValue(i, value, sendGui, sendOsc, sendCallback); break; } } } void CarlaPlugin::setParameterMidiChannel(const uint32_t parameterId, const uint8_t channel, const bool sendOsc, const bool sendCallback) noexcept { if (pData->engineBridged) { CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,); } else { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT } CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); if (pData->param.data[parameterId].midiChannel == channel) return; pData->param.data[parameterId].midiChannel = channel; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED, pData->id, static_cast(parameterId), channel, 0, 0.0f, nullptr); #endif } void CarlaPlugin::setParameterMappedControlIndex(const uint32_t parameterId, const int16_t index, const bool sendOsc, const bool sendCallback) noexcept { if (pData->engineBridged) { CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,); } else { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT } CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); CARLA_SAFE_ASSERT_RETURN(index >= CONTROL_INDEX_NONE && index <= CONTROL_INDEX_MAX_ALLOWED,); ParameterData& paramData(pData->param.data[parameterId]); if (paramData.mappedControlIndex == index) return; const ParameterRanges& paramRanges(pData->param.ranges[parameterId]); if ((paramData.hints & PARAMETER_MAPPED_RANGES_SET) == 0x0) setParameterMappedRange(parameterId, paramRanges.min, paramRanges.max, true, true); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH char strBuf[STR_MAX+1]; carla_zeroChars(strBuf, STR_MAX+1); if (! getParameterName(parameterId, strBuf)) std::snprintf(strBuf, STR_MAX, "Param %u", parameterId); const uint portNameSize = pData->engine->getMaxPortNameSize(); if (portNameSize < STR_MAX) strBuf[portNameSize] = '\0'; if (index == CONTROL_INDEX_CV) { CARLA_SAFE_ASSERT_RETURN(pData->event.cvSourcePorts != nullptr,); CARLA_SAFE_ASSERT_RETURN(paramData.type == PARAMETER_INPUT,); CARLA_SAFE_ASSERT_RETURN(paramData.hints & PARAMETER_CAN_BE_CV_CONTROLLED,); CarlaEngineCVPort* const cvPort = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, strBuf, true, parameterId); cvPort->setRange(paramData.mappedMinimum, paramData.mappedMaximum); pData->event.cvSourcePorts->addCVSource(cvPort, parameterId); } else if (paramData.mappedControlIndex == CONTROL_INDEX_CV) { CARLA_SAFE_ASSERT_RETURN(pData->event.cvSourcePorts != nullptr,); CARLA_SAFE_ASSERT(pData->client->removePort(kEnginePortTypeCV, strBuf, true)); CARLA_SAFE_ASSERT(pData->event.cvSourcePorts->removeCVSource(parameterId)); } else if (paramData.mappedControlIndex == CONTROL_INDEX_NONE) { // when doing MIDI CC mapping, ensure ranges are within bounds if (paramData.mappedMinimum < paramRanges.min || paramData.mappedMaximum > paramRanges.max) setParameterMappedRange(parameterId, std::max(paramData.mappedMinimum, paramRanges.min), std::min(paramData.mappedMaximum, paramRanges.max), true, true); } #endif paramData.mappedControlIndex = index; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED, pData->id, static_cast(parameterId), index, 0, 0.0f, nullptr); #endif } void CarlaPlugin::setParameterMappedRange(const uint32_t parameterId, const float minimum, const float maximum, const bool sendOsc, const bool sendCallback) noexcept { if (pData->engineBridged) { CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,); } else { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT } CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); ParameterData& paramData(pData->param.data[parameterId]); if (carla_isEqual(paramData.mappedMinimum, minimum) && carla_isEqual(paramData.mappedMaximum, maximum) && (paramData.hints & PARAMETER_MAPPED_RANGES_SET) != 0x0) return; if (paramData.mappedControlIndex != CONTROL_INDEX_NONE && paramData.mappedControlIndex != CONTROL_INDEX_CV) { const ParameterRanges& paramRanges(pData->param.ranges[parameterId]); CARLA_SAFE_ASSERT_RETURN(minimum >= paramRanges.min,); CARLA_SAFE_ASSERT_RETURN(maximum <= paramRanges.max,); } paramData.hints |= PARAMETER_MAPPED_RANGES_SET; paramData.mappedMinimum = minimum; paramData.mappedMaximum = maximum; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (pData->event.cvSourcePorts != nullptr && paramData.mappedControlIndex == CONTROL_INDEX_CV) pData->event.cvSourcePorts->setCVSourceRange(parameterId, minimum, maximum); char strBuf[STR_MAX+1]; carla_zeroChars(strBuf, STR_MAX+1); std::snprintf(strBuf, STR_MAX, "%.12g:%.12g", static_cast(minimum), static_cast(maximum)); pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED, pData->id, static_cast(parameterId), 0, 0, 0.0f, strBuf); #endif } void CarlaPlugin::setCustomData(const char* const type, const char* const key, const char* const value, const bool) { CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr,); // Ignore some keys if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) == 0) { const PluginType ptype = getType(); if ((ptype == PLUGIN_INTERNAL && std::strncmp(key, "CarlaAlternateFile", 18) == 0) || (ptype == PLUGIN_DSSI && std::strcmp (key, "guiVisible") == 0) || (ptype == PLUGIN_LV2 && std::strncmp(key, "OSC:", 4) == 0)) return; } // Check if we already have this key for (LinkedList::Itenerator it = pData->custom.begin2(); it.valid(); it.next()) { CustomData& customData(it.getValue(kCustomDataFallbackNC)); CARLA_SAFE_ASSERT_CONTINUE(customData.isValid()); if (std::strcmp(customData.key, key) == 0) { if (customData.value != nullptr) delete[] customData.value; customData.value = carla_strdup(value); return; } } // Otherwise store it CustomData customData; customData.type = carla_strdup(type); customData.key = carla_strdup(key); customData.value = carla_strdup(value); pData->custom.append(customData); } void CarlaPlugin::setChunkData(const void* const data, const std::size_t dataSize) { CARLA_SAFE_ASSERT_RETURN(data != nullptr,); CARLA_SAFE_ASSERT_RETURN(dataSize > 0,); CARLA_SAFE_ASSERT(false); // this should never happen } void CarlaPlugin::setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool) noexcept { CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->prog.count),); pData->prog.current = index; pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PROGRAM_CHANGED, pData->id, index, 0, 0, 0.0f, nullptr); // Change default parameter values if (index >= 0) { if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0) uiProgramChange(static_cast(index)); switch (getType()) { case PLUGIN_SF2: case PLUGIN_SFZ: break; default: pData->updateParameterValues(this, sendCallback, sendOsc, true); break; } } } void CarlaPlugin::setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool) noexcept { CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->midiprog.count),); pData->midiprog.current = index; pData->engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED, pData->id, index, 0, 0, 0.0f, nullptr); // Change default parameter values if (index >= 0) { if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0) uiMidiProgramChange(static_cast(index)); switch (getType()) { case PLUGIN_SF2: case PLUGIN_SFZ: break; default: pData->updateParameterValues(this, sendCallback, sendOsc, true); break; } } } void CarlaPlugin::setMidiProgramById(const uint32_t bank, const uint32_t program, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept { for (uint32_t i=0; i < pData->midiprog.count; ++i) { if (pData->midiprog.data[i].bank == bank && pData->midiprog.data[i].program == program) return setMidiProgram(static_cast(i), sendGui, sendOsc, sendCallback); } } void CarlaPlugin::setProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept { CARLA_SAFE_ASSERT_RETURN(uindex < pData->prog.count,); const int32_t index = static_cast(uindex); pData->prog.current = index; // Change default parameter values switch (getType()) { case PLUGIN_SF2: case PLUGIN_SFZ: break; default: pData->updateDefaultParameterValues(this); break; } pData->postponeRtEvent(kPluginPostRtEventProgramChange, sendCallbackLater, index, 0, 0, 0.0f); } void CarlaPlugin::setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept { CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,); const int32_t index = static_cast(uindex); pData->midiprog.current = index; // Change default parameter values switch (getType()) { case PLUGIN_SF2: case PLUGIN_SFZ: break; default: pData->updateDefaultParameterValues(this); break; } pData->postponeRtEvent(kPluginPostRtEventMidiProgramChange, sendCallbackLater, index, 0, 0, 0.0f); } // ------------------------------------------------------------------- // Plugin state void CarlaPlugin::reloadPrograms(const bool) { } // ------------------------------------------------------------------- // Plugin processing void CarlaPlugin::activate() noexcept { CARLA_SAFE_ASSERT(! pData->active); } void CarlaPlugin::deactivate() noexcept { CARLA_SAFE_ASSERT(pData->active); } void CarlaPlugin::bufferSizeChanged(const uint32_t) { } void CarlaPlugin::sampleRateChanged(const double) { } void CarlaPlugin::offlineModeChanged(const bool) { } // ------------------------------------------------------------------- // Misc void CarlaPlugin::idle() { if (! pData->enabled) return; const bool hasUI(pData->hints & PLUGIN_HAS_CUSTOM_UI); const bool needsUiMainThread(pData->hints & PLUGIN_NEEDS_UI_MAIN_THREAD); const uint32_t latency(getLatencyInFrames()); if (pData->latency.frames != latency) { carla_stdout("latency changed to %i samples", latency); const ScopedSingleProcessLocker sspl(this, true); pData->client->setLatency(latency); #ifndef BUILD_BRIDGE pData->latency.recreateBuffers(pData->latency.channels, latency); #else pData->latency.frames = latency; #endif } ProtectedData::PostRtEvents::Access rtEvents(pData->postRtEvents); if (rtEvents.isEmpty()) return; for (RtLinkedList::Itenerator it = rtEvents.getDataIterator(); it.valid(); it.next()) { const PluginPostRtEvent& event(it.getValue(kPluginPostRtEventFallback)); CARLA_SAFE_ASSERT_CONTINUE(event.type != kPluginPostRtEventNull); switch (event.type) { case kPluginPostRtEventNull: { } break; case kPluginPostRtEventDebug: { pData->engine->callback(true, true, ENGINE_CALLBACK_DEBUG, pData->id, event.value1, event.value2, event.value3, event.valuef, nullptr); } break; case kPluginPostRtEventParameterChange: { // Update UI if (event.value1 >= 0 && hasUI) { if (needsUiMainThread) pData->postUiEvents.append(event); else uiParameterChange(static_cast(event.value1), event.valuef); } if (event.sendCallback) { // Update Host pData->engine->callback(true, true, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, event.value1, 0, 0, event.valuef, nullptr); } } break; case kPluginPostRtEventProgramChange: { // Update UI if (event.value1 >= 0 && hasUI) { if (needsUiMainThread) pData->postUiEvents.append(event); else uiProgramChange(static_cast(event.value1)); } // Update param values for (uint32_t j=0; j < pData->param.count; ++j) { const float paramDefault(pData->param.ranges[j].def); const float paramValue(getParameterValue(j)); pData->engine->callback(true, true, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, static_cast(j), 0, 0, paramValue, nullptr); pData->engine->callback(true, true, ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED, pData->id, static_cast(j), 0, 0, paramDefault, nullptr); } if (event.sendCallback) { // Update Host pData->engine->callback(true, true, ENGINE_CALLBACK_PROGRAM_CHANGED, pData->id, event.value1, 0, 0, 0.0f, nullptr); } } break; case kPluginPostRtEventMidiProgramChange: { // Update UI if (event.value1 >= 0 && hasUI) { if (needsUiMainThread) pData->postUiEvents.append(event); else uiMidiProgramChange(static_cast(event.value1)); } // Update param values for (uint32_t j=0; j < pData->param.count; ++j) { const float paramDefault(pData->param.ranges[j].def); const float paramValue(getParameterValue(j)); pData->engine->callback(true, true, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, static_cast(j), 0, 0, paramValue, nullptr); pData->engine->callback(true, true, ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED, pData->id, static_cast(j), 0, 0, paramDefault, nullptr); } if (event.sendCallback) { // Update Host pData->engine->callback(true, true, ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED, pData->id, event.value1, 0, 0, 0.0f, nullptr); } } break; case kPluginPostRtEventNoteOn: { CARLA_SAFE_ASSERT_BREAK(event.value1 >= 0 && event.value1 < MAX_MIDI_CHANNELS); CARLA_SAFE_ASSERT_BREAK(event.value2 >= 0 && event.value2 < MAX_MIDI_NOTE); CARLA_SAFE_ASSERT_BREAK(event.value3 >= 0 && event.value3 < MAX_MIDI_VALUE); const uint8_t channel = static_cast(event.value1); const uint8_t note = static_cast(event.value2); const uint8_t velocity = static_cast(event.value3); // Update UI if (hasUI) { if (needsUiMainThread) pData->postUiEvents.append(event); else uiNoteOn(channel, note, velocity); } if (event.sendCallback) { // Update Host pData->engine->callback(true, true, ENGINE_CALLBACK_NOTE_ON, pData->id, event.value1, event.value2, event.value3, 0.0f, nullptr); } } break; case kPluginPostRtEventNoteOff: { CARLA_SAFE_ASSERT_BREAK(event.value1 >= 0 && event.value1 < MAX_MIDI_CHANNELS); CARLA_SAFE_ASSERT_BREAK(event.value2 >= 0 && event.value2 < MAX_MIDI_NOTE); const uint8_t channel = static_cast(event.value1); const uint8_t note = static_cast(event.value2); // Update UI if (hasUI) { if (needsUiMainThread) pData->postUiEvents.append(event); else uiNoteOff(channel, note); } if (event.sendCallback) { // Update Host pData->engine->callback(true, true, ENGINE_CALLBACK_NOTE_OFF, pData->id, event.value1, event.value2, 0, 0.0f, nullptr); } } break; } } } bool CarlaPlugin::tryLock(const bool forcedOffline) noexcept { if (forcedOffline) { #ifndef STOAT_TEST_BUILD pData->masterMutex.lock(); return true; #endif } return pData->masterMutex.tryLock(); } void CarlaPlugin::unlock() noexcept { pData->masterMutex.unlock(); } // ------------------------------------------------------------------- // Plugin buffers void CarlaPlugin::initBuffers() const noexcept { pData->audioIn.initBuffers(); pData->audioOut.initBuffers(); pData->cvIn.initBuffers(); pData->cvOut.initBuffers(); pData->event.initBuffers(); } void CarlaPlugin::clearBuffers() noexcept { pData->clearBuffers(); } // ------------------------------------------------------------------- // OSC stuff // FIXME void CarlaPlugin::handleOscMessage(const char* const, const int, const void* const, const char* const, const lo_message) { // do nothing } // ------------------------------------------------------------------- // MIDI events void CarlaPlugin::sendMidiSingleNote(const uint8_t channel, const uint8_t note, const uint8_t velo, const bool sendGui, const bool sendOsc, const bool sendCallback) { CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); CARLA_SAFE_ASSERT_RETURN(velo < MAX_MIDI_VALUE,); if (! pData->active) return; ExternalMidiNote extNote; extNote.channel = static_cast(channel); extNote.note = note; extNote.velo = velo; pData->extNotes.appendNonRT(extNote); if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0) { if (velo > 0) uiNoteOn(channel, note, velo); else uiNoteOff(channel, note); } pData->engine->callback(sendCallback, sendOsc, (velo > 0) ? ENGINE_CALLBACK_NOTE_ON : ENGINE_CALLBACK_NOTE_OFF, pData->id, channel, note, velo, 0.0f, nullptr); } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH void CarlaPlugin::postponeRtAllNotesOff() { if (pData->ctrlChannel < 0 || pData->ctrlChannel >= MAX_MIDI_CHANNELS) return; PluginPostRtEvent postEvent = { kPluginPostRtEventNoteOff, true, pData->ctrlChannel, 0, 0, 0.0f }; for (int32_t i=0; i < MAX_MIDI_NOTE; ++i) { postEvent.value2 = i; pData->postRtEvents.appendRT(postEvent); } } #endif // ------------------------------------------------------------------- // UI Stuff void CarlaPlugin::showCustomUI(const bool yesNo) { if (yesNo) { CARLA_SAFE_ASSERT(false); } } void CarlaPlugin::uiIdle() { if (pData->hints & PLUGIN_NEEDS_UI_MAIN_THREAD) { // Update parameter outputs for (uint32_t i=0; i < pData->param.count; ++i) { if (pData->param.data[i].type == PARAMETER_OUTPUT) uiParameterChange(i, getParameterValue(i)); } const CarlaMutexLocker sl(pData->postUiEvents.mutex); for (LinkedList::Itenerator it = pData->postUiEvents.data.begin2(); it.valid(); it.next()) { const PluginPostRtEvent& event(it.getValue(kPluginPostRtEventFallback)); CARLA_SAFE_ASSERT_CONTINUE(event.type != kPluginPostRtEventNull); switch (event.type) { case kPluginPostRtEventNull: case kPluginPostRtEventDebug: break; case kPluginPostRtEventParameterChange: uiParameterChange(static_cast(event.value1), event.valuef); break; case kPluginPostRtEventProgramChange: uiProgramChange(static_cast(event.value1)); break; case kPluginPostRtEventMidiProgramChange: uiMidiProgramChange(static_cast(event.value1)); break; case kPluginPostRtEventNoteOn: uiNoteOn(static_cast(event.value1), static_cast(event.value2), static_cast(event.value3)); break; case kPluginPostRtEventNoteOff: uiNoteOff(static_cast(event.value1), static_cast(event.value2)); break; } } pData->postUiEvents.data.clear(); } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (pData->transientTryCounter == 0) return; if (++pData->transientTryCounter % 10 != 0) return; if (pData->transientTryCounter >= 200) return; carla_stdout("Trying to get window..."); CarlaString uiTitle(pData->name); uiTitle += " (GUI)"; if (CarlaPluginUI::tryTransientWinIdMatch(getUiBridgeProcessId(), uiTitle, pData->engine->getOptions().frontendWinId, pData->transientFirstTry)) { pData->transientTryCounter = 0; pData->transientFirstTry = false; } #endif } void CarlaPlugin::uiParameterChange(const uint32_t index, const float value) noexcept { CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),); return; // unused (void)value; } void CarlaPlugin::uiProgramChange(const uint32_t index) noexcept { CARLA_SAFE_ASSERT_RETURN(index < getProgramCount(),); } void CarlaPlugin::uiMidiProgramChange(const uint32_t index) noexcept { CARLA_SAFE_ASSERT_RETURN(index < getMidiProgramCount(),); } void CarlaPlugin::uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept { CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,); } void CarlaPlugin::uiNoteOff(const uint8_t channel, const uint8_t note) noexcept { CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); } CarlaEngine* CarlaPlugin::getEngine() const noexcept { return pData->engine; } CarlaEngineClient* CarlaPlugin::getEngineClient() const noexcept { return pData->client; } CarlaEngineAudioPort* CarlaPlugin::getAudioInPort(const uint32_t index) const noexcept { return pData->audioIn.ports[index].port; } CarlaEngineAudioPort* CarlaPlugin::getAudioOutPort(const uint32_t index) const noexcept { return pData->audioOut.ports[index].port; } CarlaEngineCVPort* CarlaPlugin::getCVInPort(const uint32_t index) const noexcept { return pData->cvIn.ports[index].port; } CarlaEngineCVPort* CarlaPlugin::getCVOutPort(const uint32_t index) const noexcept { return pData->cvOut.ports[index].port; } CarlaEngineEventPort* CarlaPlugin::getDefaultEventInPort() const noexcept { return pData->event.portIn; } CarlaEngineEventPort* CarlaPlugin::getDefaultEventOutPort() const noexcept { return pData->event.portOut; } void* CarlaPlugin::getNativeHandle() const noexcept { return nullptr; } const void* CarlaPlugin::getNativeDescriptor() const noexcept { return nullptr; } uintptr_t CarlaPlugin::getUiBridgeProcessId() const noexcept { return 0; } // ------------------------------------------------------------------- uint32_t CarlaPlugin::getPatchbayNodeId() const noexcept { return pData->nodeId; } void CarlaPlugin::setPatchbayNodeId(const uint32_t nodeId) noexcept { pData->nodeId = nodeId; } // ------------------------------------------------------------------- void CarlaPlugin::restoreLV2State() noexcept { carla_stderr2("Warning: restoreLV2State() called for non-implemented type"); } void CarlaPlugin::waitForBridgeSaveSignal() noexcept { } // ------------------------------------------------------------------- // Scoped Disabler CarlaPlugin::ScopedDisabler::ScopedDisabler(CarlaPlugin* const plugin) noexcept : fPlugin(plugin), fWasEnabled(false) { CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); CARLA_SAFE_ASSERT_RETURN(plugin->pData != nullptr,); CARLA_SAFE_ASSERT_RETURN(plugin->pData->client != nullptr,); carla_debug("CarlaPlugin::ScopedDisabler(%p)", plugin); plugin->pData->masterMutex.lock(); if (plugin->pData->enabled) { fWasEnabled = true; plugin->pData->enabled = false; if (plugin->pData->client->isActive()) plugin->pData->client->deactivate(); } } CarlaPlugin::ScopedDisabler::~ScopedDisabler() noexcept { CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,); CARLA_SAFE_ASSERT_RETURN(fPlugin->pData != nullptr,); CARLA_SAFE_ASSERT_RETURN(fPlugin->pData->client != nullptr,); carla_debug("CarlaPlugin::~ScopedDisabler()"); if (fWasEnabled) { fPlugin->pData->enabled = true; fPlugin->pData->client->activate(); } fPlugin->pData->masterMutex.unlock(); } // ------------------------------------------------------------------- // Scoped Process Locker CarlaPlugin::ScopedSingleProcessLocker::ScopedSingleProcessLocker(CarlaPlugin* const plugin, const bool block) noexcept : fPlugin(plugin), fBlock(block) { CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,); CARLA_SAFE_ASSERT_RETURN(fPlugin->pData != nullptr,); carla_debug("CarlaPlugin::ScopedSingleProcessLocker(%p, %s)", plugin, bool2str(block)); if (! fBlock) return; plugin->pData->singleMutex.lock(); } CarlaPlugin::ScopedSingleProcessLocker::~ScopedSingleProcessLocker() noexcept { CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,); CARLA_SAFE_ASSERT_RETURN(fPlugin->pData != nullptr,); carla_debug("CarlaPlugin::~ScopedSingleProcessLocker()"); if (! fBlock) return; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (fPlugin->pData->singleMutex.wasTryLockCalled()) fPlugin->pData->needsReset = true; #endif fPlugin->pData->singleMutex.unlock(); } // ------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/plugin/CarlaPluginAU.cpp000066400000000000000000000025601364475620200217320ustar00rootroot00000000000000/* * Carla AU Plugin * Copyright (C) 2014 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaPlugin.hpp" #include "CarlaEngine.hpp" #include "CarlaUtils.hpp" CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- CarlaPlugin* CarlaPlugin::newAU(const Initializer& init) { carla_debug("CarlaPlugin::newAU({%p, \"%s\", \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.label, init.uniqueId); #if defined(CARLA_OS_MAC) return newJuce(init, "AU"); #else init.engine->setLastError("AU support not available"); return nullptr; #endif } // ------------------------------------------------------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/plugin/CarlaPluginBridge.cpp000066400000000000000000003334621364475620200226310ustar00rootroot00000000000000/* * Carla Plugin Bridge * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaPluginInternal.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaBase64Utils.hpp" #include "CarlaBridgeUtils.hpp" #include "CarlaEngineUtils.hpp" #include "CarlaMathUtils.hpp" #include "CarlaPipeUtils.hpp" #include "CarlaScopeUtils.hpp" #include "CarlaShmUtils.hpp" #include "CarlaThread.hpp" #include "jackbridge/JackBridge.hpp" #include #include "water/files/File.h" #include "water/misc/Time.h" #include "water/threads/ChildProcess.h" // --------------------------------------------------------------------------------------------------------------------- using water::ChildProcess; using water::File; using water::String; using water::StringArray; using water::Time; CARLA_BACKEND_START_NAMESPACE // --------------------------------------------------------------------------------------------------------------------- // Fallback data static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 }; // --------------------------------------------------------------------------------------------------------------------- static String findWinePrefix(const String filename, const int recursionLimit = 10) { if (recursionLimit == 0 || filename.length() < 5 || ! filename.contains("/")) return ""; const String path(filename.upToLastOccurrenceOf("/", false, false)); if (File(path + "/dosdevices").isDirectory()) return path; return findWinePrefix(path, recursionLimit-1); } // --------------------------------------------------------------------------------------------------------------------- struct BridgeParamInfo { float value; CarlaString name; CarlaString symbol; CarlaString unit; BridgeParamInfo() noexcept : value(0.0f), name(), symbol(), unit() {} CARLA_DECLARE_NON_COPY_STRUCT(BridgeParamInfo) }; // --------------------------------------------------------------------------------------------------------------------- class CarlaPluginBridgeThread : public CarlaThread { public: CarlaPluginBridgeThread(CarlaEngine* const engine, CarlaPlugin* const plugin) noexcept : CarlaThread("CarlaPluginBridgeThread"), kEngine(engine), kPlugin(plugin), fBinary(), fLabel(), fShmIds(), #ifndef CARLA_OS_WIN fWinePrefix(), #endif fProcess() {} void setData( #ifndef CARLA_OS_WIN const char* const winePrefix, #endif const char* const binary, const char* const label, const char* const shmIds) noexcept { CARLA_SAFE_ASSERT_RETURN(binary != nullptr && binary[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && shmIds[0] != '\0',); CARLA_SAFE_ASSERT(! isThreadRunning()); #ifndef CARLA_OS_WIN fWinePrefix = winePrefix; #endif fBinary = binary; fShmIds = shmIds; if (label != nullptr) fLabel = label; if (fLabel.isEmpty()) fLabel = "\"\""; } uintptr_t getProcessPID() const noexcept { CARLA_SAFE_ASSERT_RETURN(fProcess != nullptr, 0); return (uintptr_t)fProcess->getPID(); } protected: void run() { if (fProcess == nullptr) { fProcess = new ChildProcess(); } else if (fProcess->isRunning()) { carla_stderr("CarlaPluginBridgeThread::run() - already running"); } char strBuf[STR_MAX+1]; strBuf[STR_MAX] = '\0'; const EngineOptions& options(kEngine->getOptions()); String name(kPlugin->getName()); String filename(kPlugin->getFilename()); if (name.isEmpty()) name = "(none)"; if (filename.isEmpty()) filename = "\"\""; StringArray arguments; #ifndef CARLA_OS_WIN // start with "wine" if needed if (fBinary.endsWithIgnoreCase(".exe")) { String wineCMD; if (options.wine.executable != nullptr && options.wine.executable[0] != '\0') { wineCMD = options.wine.executable; if (fBinary.endsWithIgnoreCase("64.exe") && options.wine.executable[0] == CARLA_OS_SEP && File(wineCMD + "64").existsAsFile()) wineCMD += "64"; } else { wineCMD = "wine"; } arguments.add(wineCMD); } #endif // binary arguments.add(fBinary); // plugin type arguments.add(getPluginTypeAsString(kPlugin->getType())); // filename arguments.add(filename); // label arguments.add(fLabel); // uniqueId arguments.add(String(static_cast(kPlugin->getUniqueId()))); bool started; { const ScopedEngineEnvironmentLocker _seel(kEngine); #ifdef CARLA_OS_LINUX const CarlaScopedEnvVar sev1("LD_LIBRARY_PATH", nullptr); const CarlaScopedEnvVar sev2("LD_PRELOAD", nullptr); #endif carla_setenv("ENGINE_OPTION_FORCE_STEREO", bool2str(options.forceStereo)); carla_setenv("ENGINE_OPTION_PREFER_PLUGIN_BRIDGES", bool2str(options.preferPluginBridges)); carla_setenv("ENGINE_OPTION_PREFER_UI_BRIDGES", bool2str(options.preferUiBridges)); carla_setenv("ENGINE_OPTION_UIS_ALWAYS_ON_TOP", bool2str(options.uisAlwaysOnTop)); std::snprintf(strBuf, STR_MAX, "%u", options.maxParameters); carla_setenv("ENGINE_OPTION_MAX_PARAMETERS", strBuf); std::snprintf(strBuf, STR_MAX, "%u", options.uiBridgesTimeout); carla_setenv("ENGINE_OPTION_UI_BRIDGES_TIMEOUT",strBuf); if (options.pathLADSPA != nullptr) carla_setenv("ENGINE_OPTION_PLUGIN_PATH_LADSPA", options.pathLADSPA); else carla_setenv("ENGINE_OPTION_PLUGIN_PATH_LADSPA", ""); if (options.pathDSSI != nullptr) carla_setenv("ENGINE_OPTION_PLUGIN_PATH_DSSI", options.pathDSSI); else carla_setenv("ENGINE_OPTION_PLUGIN_PATH_DSSI", ""); if (options.pathLV2 != nullptr) carla_setenv("ENGINE_OPTION_PLUGIN_PATH_LV2", options.pathLV2); else carla_setenv("ENGINE_OPTION_PLUGIN_PATH_LV2", ""); if (options.pathVST2 != nullptr) carla_setenv("ENGINE_OPTION_PLUGIN_PATH_VST2", options.pathVST2); else carla_setenv("ENGINE_OPTION_PLUGIN_PATH_VST2", ""); if (options.pathVST3 != nullptr) carla_setenv("ENGINE_OPTION_PLUGIN_PATH_VST3", options.pathVST3); else carla_setenv("ENGINE_OPTION_PLUGIN_PATH_VST3", ""); if (options.pathSF2 != nullptr) carla_setenv("ENGINE_OPTION_PLUGIN_PATH_SF2", options.pathSF2); else carla_setenv("ENGINE_OPTION_PLUGIN_PATH_SF2", ""); if (options.pathSFZ != nullptr) carla_setenv("ENGINE_OPTION_PLUGIN_PATH_SFZ", options.pathSFZ); else carla_setenv("ENGINE_OPTION_PLUGIN_PATH_SFZ", ""); if (options.binaryDir != nullptr) carla_setenv("ENGINE_OPTION_PATH_BINARIES", options.binaryDir); else carla_setenv("ENGINE_OPTION_PATH_BINARIES", ""); if (options.resourceDir != nullptr) carla_setenv("ENGINE_OPTION_PATH_RESOURCES", options.resourceDir); else carla_setenv("ENGINE_OPTION_PATH_RESOURCES", ""); carla_setenv("ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR", bool2str(options.preventBadBehaviour)); std::snprintf(strBuf, STR_MAX, P_UINTPTR, options.frontendWinId); carla_setenv("ENGINE_OPTION_FRONTEND_WIN_ID", strBuf); carla_setenv("ENGINE_BRIDGE_SHM_IDS", fShmIds.toRawUTF8()); #ifndef CARLA_OS_WIN if (fWinePrefix.isNotEmpty()) { carla_setenv("WINEDEBUG", "-all"); carla_setenv("WINEPREFIX", fWinePrefix.toRawUTF8()); if (options.wine.rtPrio) { carla_setenv("STAGING_SHARED_MEMORY", "1"); carla_setenv("WINE_RT_POLICY", "FF"); std::snprintf(strBuf, STR_MAX, "%i", options.wine.baseRtPrio); carla_setenv("STAGING_RT_PRIORITY_BASE", strBuf); carla_setenv("WINE_RT", strBuf); carla_setenv("WINE_RT_PRIO", strBuf); std::snprintf(strBuf, STR_MAX, "%i", options.wine.serverRtPrio); carla_setenv("STAGING_RT_PRIORITY_SERVER", strBuf); carla_setenv("WINE_SVR_RT", strBuf); carla_stdout("Using WINEPREFIX '%s', with base RT prio %i and server RT prio %i", fWinePrefix.toRawUTF8(), options.wine.baseRtPrio, options.wine.serverRtPrio); } else { carla_unsetenv("STAGING_SHARED_MEMORY"); carla_unsetenv("WINE_RT_POLICY"); carla_unsetenv("STAGING_RT_PRIORITY_BASE"); carla_unsetenv("STAGING_RT_PRIORITY_SERVER"); carla_unsetenv("WINE_RT"); carla_unsetenv("WINE_RT_PRIO"); carla_unsetenv("WINE_SVR_RT"); carla_stdout("Using WINEPREFIX '%s', without RT priorities", fWinePrefix.toRawUTF8()); } } #endif carla_stdout("Starting plugin bridge, command is:\n%s \"%s\" \"%s\" \"%s\" " P_INT64, fBinary.toRawUTF8(), getPluginTypeAsString(kPlugin->getType()), filename.toRawUTF8(), fLabel.toRawUTF8(), kPlugin->getUniqueId()); started = fProcess->start(arguments); } if (! started) { carla_stdout("failed!"); fProcess = nullptr; return; } for (; fProcess->isRunning() && ! shouldThreadExit();) carla_sleep(1); // we only get here if bridge crashed or thread asked to exit if (fProcess->isRunning() && shouldThreadExit()) { fProcess->waitForProcessToFinish(2000); if (fProcess->isRunning()) { carla_stdout("CarlaPluginBridgeThread::run() - bridge refused to close, force kill now"); fProcess->kill(); } else { carla_stdout("CarlaPluginBridgeThread::run() - bridge auto-closed successfully"); } } else { // forced quit, may have crashed if (fProcess->getExitCode() != 0 /*|| fProcess->exitStatus() == QProcess::CrashExit*/) { carla_stderr("CarlaPluginBridgeThread::run() - bridge crashed"); CarlaString errorString("Plugin '" + CarlaString(kPlugin->getName()) + "' has crashed!\n" "Saving now will lose its current settings.\n" "Please remove this plugin, and not rely on it from this point."); kEngine->callback(true, true, CarlaBackend::ENGINE_CALLBACK_ERROR, kPlugin->getId(), 0, 0, 0, 0.0f, errorString); } } fProcess = nullptr; } private: CarlaEngine* const kEngine; CarlaPlugin* const kPlugin; String fBinary; String fLabel; String fShmIds; #ifndef CARLA_OS_WIN String fWinePrefix; #endif CarlaScopedPointer fProcess; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginBridgeThread) }; // --------------------------------------------------------------------------------------------------------------------- class CarlaPluginBridge : public CarlaPlugin { public: CarlaPluginBridge(CarlaEngine* const engine, const uint id, const BinaryType btype, const PluginType ptype) : CarlaPlugin(engine, id), fBinaryType(btype), fPluginType(ptype), fBridgeVersion(6), // before kPluginBridgeNonRtServerVersion was a thing, API was at 6 fInitiated(false), fInitError(false), fSaved(true), fTimedOut(false), fTimedError(false), fBufferSize(engine->getBufferSize()), fProcWaitTime(0), fBridgeBinary(), fBridgeThread(engine, this), fShmAudioPool(), fShmRtClientControl(), fShmNonRtClientControl(), fShmNonRtServerControl(), #ifndef CARLA_OS_WIN fWinePrefix(), #endif fReceivingParamText(), fInfo(), fUniqueId(0), fLatency(0), fParams(nullptr) { carla_debug("CarlaPluginBridge::CarlaPluginBridge(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype)); pData->hints |= PLUGIN_IS_BRIDGE; } ~CarlaPluginBridge() override { carla_debug("CarlaPluginBridge::~CarlaPluginBridge()"); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // close UI if (pData->hints & PLUGIN_HAS_CUSTOM_UI) pData->transientTryCounter = 0; #endif pData->singleMutex.lock(); pData->masterMutex.lock(); if (pData->client != nullptr && pData->client->isActive()) pData->client->deactivate(); if (pData->active) { deactivate(); pData->active = false; } if (fBridgeThread.isThreadRunning()) { fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientQuit); fShmNonRtClientControl.commitWrite(); fShmRtClientControl.writeOpcode(kPluginBridgeRtClientQuit); fShmRtClientControl.commitWrite(); if (! fTimedOut) waitForClient("stopping", 3000); } fBridgeThread.stopThread(3000); fShmNonRtServerControl.clear(); fShmNonRtClientControl.clear(); fShmRtClientControl.clear(); fShmAudioPool.clear(); clearBuffers(); fInfo.chunk.clear(); } // ------------------------------------------------------------------- // Information (base) BinaryType getBinaryType() const noexcept override { return fBinaryType; } PluginType getType() const noexcept override { return fPluginType; } PluginCategory getCategory() const noexcept override { return fInfo.category; } int64_t getUniqueId() const noexcept override { return fUniqueId; } uint32_t getLatencyInFrames() const noexcept override { return fLatency; } // ------------------------------------------------------------------- // Information (count) uint32_t getMidiInCount() const noexcept override { return fInfo.mIns; } uint32_t getMidiOutCount() const noexcept override { return fInfo.mOuts; } // ------------------------------------------------------------------- // Information (current data) std::size_t getChunkData(void** const dataPtr) noexcept override { CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0); CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0); waitForSaved(); CARLA_SAFE_ASSERT_RETURN(fInfo.chunk.size() > 0, 0); #ifdef CARLA_PROPER_CPP11_SUPPORT *dataPtr = fInfo.chunk.data(); #else *dataPtr = &fInfo.chunk.front(); #endif return fInfo.chunk.size(); } // ------------------------------------------------------------------- // Information (per-plugin data) uint getOptionsAvailable() const noexcept override { return fInfo.optionsAvailable; } float getParameterValue(const uint32_t parameterId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f); return fParams[parameterId].value; } bool getLabel(char* const strBuf) const noexcept override { std::strncpy(strBuf, fInfo.label, STR_MAX); return true; } bool getMaker(char* const strBuf) const noexcept override { std::strncpy(strBuf, fInfo.maker, STR_MAX); return true; } bool getCopyright(char* const strBuf) const noexcept override { std::strncpy(strBuf, fInfo.copyright, STR_MAX); return true; } bool getRealName(char* const strBuf) const noexcept override { std::strncpy(strBuf, fInfo.name, STR_MAX); return true; } bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); std::strncpy(strBuf, fParams[parameterId].name.buffer(), STR_MAX); return true; } bool getParameterText(const uint32_t parameterId, char* const strBuf) noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); CARLA_SAFE_ASSERT_RETURN(! fReceivingParamText.isCurrentlyWaitingData(), false); const int32_t parameterIdi = static_cast(parameterId); fReceivingParamText.setTargetData(parameterIdi, strBuf); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientGetParameterText); fShmNonRtClientControl.writeInt(parameterIdi); fShmNonRtClientControl.commitWrite(); } if (waitForParameterText()) return true; std::snprintf(strBuf, STR_MAX, "%.12g", static_cast(fParams[parameterId].value)); return false; } bool getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); std::strncpy(strBuf, fParams[parameterId].symbol.buffer(), STR_MAX); return true; } bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); std::strncpy(strBuf, fParams[parameterId].unit.buffer(), STR_MAX); return true; } // ------------------------------------------------------------------- // Set data (state) void prepareForSave() noexcept override { fSaved = false; { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPrepareForSave); fShmNonRtClientControl.commitWrite(); } } bool waitForParameterText() { bool success; if (fReceivingParamText.wasDataReceived(&success)) return success; const uint32_t timeoutEnd(Time::getMillisecondCounter() + 500); // 500 ms for (; Time::getMillisecondCounter() < timeoutEnd && fBridgeThread.isThreadRunning();) { if (fReceivingParamText.wasDataReceived(&success)) return success; carla_msleep(5); } carla_stderr("CarlaPluginBridge::waitForParameterText() - Timeout while requesting text"); #if 0 // we waited and blocked for 5 secs, give host idle time now pData->engine->callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (pData->engine->getType() != kEngineTypePlugin) pData->engine->idle(); #endif return false; } void waitForSaved() { if (fSaved) return; // TODO: only wait 1 minute for NI plugins const uint32_t timeoutEnd(Time::getMillisecondCounter() + 60*1000); // 60 secs, 1 minute const bool needsEngineIdle(pData->engine->getType() != kEngineTypePlugin); for (; Time::getMillisecondCounter() < timeoutEnd && fBridgeThread.isThreadRunning();) { pData->engine->callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (needsEngineIdle) pData->engine->idle(); if (fSaved) break; carla_msleep(20); } if (! fBridgeThread.isThreadRunning()) return carla_stderr("CarlaPluginBridge::waitForSaved() - Bridge is not running"); if (! fSaved) return carla_stderr("CarlaPluginBridge::waitForSaved() - Timeout while requesting save state"); } // ------------------------------------------------------------------- // Set data (internal stuff) void setOption(const uint option, const bool yesNo, const bool sendCallback) override { { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetOption); fShmNonRtClientControl.writeUInt(option); fShmNonRtClientControl.writeBool(yesNo); fShmNonRtClientControl.commitWrite(); } CarlaPlugin::setOption(option, yesNo, sendCallback); } void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept override { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetCtrlChannel); fShmNonRtClientControl.writeShort(channel); fShmNonRtClientControl.commitWrite(); } CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback); } // ------------------------------------------------------------------- // Set data (plugin-specific stuff) void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); const float fixedValue(pData->param.getFixedValue(parameterId, value)); fParams[parameterId].value = fixedValue; { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterValue); fShmNonRtClientControl.writeUInt(parameterId); fShmNonRtClientControl.writeFloat(value); fShmNonRtClientControl.commitWrite(); fShmNonRtClientControl.waitIfDataIsReachingLimit(); } CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback); } void setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); const float fixedValue(pData->param.getFixedValue(parameterId, value)); fParams[parameterId].value = fixedValue; { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterValue); fShmNonRtClientControl.writeUInt(parameterId); fShmNonRtClientControl.writeFloat(value); fShmNonRtClientControl.commitWrite(); fShmNonRtClientControl.waitIfDataIsReachingLimit(); } CarlaPlugin::setParameterValueRT(parameterId, fixedValue, sendCallbackLater); } void setParameterMidiChannel(const uint32_t parameterId, const uint8_t channel, const bool sendOsc, const bool sendCallback) noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMidiChannel); fShmNonRtClientControl.writeUInt(parameterId); fShmNonRtClientControl.writeByte(channel); fShmNonRtClientControl.commitWrite(); } CarlaPlugin::setParameterMidiChannel(parameterId, channel, sendOsc, sendCallback); } void setParameterMappedControlIndex(const uint32_t parameterId, const int16_t index, const bool sendOsc, const bool sendCallback) noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); CARLA_SAFE_ASSERT_RETURN(index >= CONTROL_INDEX_NONE && index <= CONTROL_INDEX_MAX_ALLOWED,); CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMappedControlIndex); fShmNonRtClientControl.writeUInt(parameterId); fShmNonRtClientControl.writeShort(index); fShmNonRtClientControl.commitWrite(); } CarlaPlugin::setParameterMappedControlIndex(parameterId, index, sendOsc, sendCallback); } void setParameterMappedRange(const uint32_t parameterId, const float minimum, const float maximum, const bool sendOsc, const bool sendCallback) noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // kPluginBridgeNonRtClientSetParameterMappedRange was added in API 7 if (fBridgeVersion >= 7) { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMappedRange); fShmNonRtClientControl.writeUInt(parameterId); fShmNonRtClientControl.writeFloat(minimum); fShmNonRtClientControl.writeFloat(maximum); fShmNonRtClientControl.commitWrite(); } CarlaPlugin::setParameterMappedRange(parameterId, minimum, maximum, sendOsc, sendCallback); } void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override { CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->prog.count),); CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetProgram); fShmNonRtClientControl.writeInt(index); fShmNonRtClientControl.commitWrite(); } CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback, doingInit); } void setProgramRT(const uint32_t index, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(index < pData->prog.count,); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetProgram); fShmNonRtClientControl.writeInt(static_cast(index)); fShmNonRtClientControl.commitWrite(); } CarlaPlugin::setProgramRT(index, sendCallbackLater); } void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override { CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->midiprog.count),); CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetMidiProgram); fShmNonRtClientControl.writeInt(index); fShmNonRtClientControl.commitWrite(); } CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit); } void setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetMidiProgram); fShmNonRtClientControl.writeInt(static_cast(uindex)); fShmNonRtClientControl.commitWrite(); } CarlaPlugin::setMidiProgramRT(uindex, sendCallbackLater); } void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override { CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr,); if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0) return CarlaPlugin::setCustomData(type, key, value, sendGui); if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) == 0 && std::strcmp(key, "__CarlaPingOnOff__") == 0) { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPingOnOff); fShmNonRtClientControl.writeBool(std::strcmp(value, "true") == 0); fShmNonRtClientControl.commitWrite(); return; } const uint32_t typeLen(static_cast(std::strlen(type))); const uint32_t keyLen(static_cast(std::strlen(key))); const uint32_t valueLen(static_cast(std::strlen(value))); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetCustomData); fShmNonRtClientControl.writeUInt(typeLen); fShmNonRtClientControl.writeCustomData(type, typeLen); fShmNonRtClientControl.writeUInt(keyLen); fShmNonRtClientControl.writeCustomData(key, keyLen); fShmNonRtClientControl.writeUInt(valueLen); if (valueLen > 0) fShmNonRtClientControl.writeCustomData(value, valueLen); fShmNonRtClientControl.commitWrite(); } CarlaPlugin::setCustomData(type, key, value, sendGui); } void setChunkData(const void* const data, const std::size_t dataSize) override { CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,); CARLA_SAFE_ASSERT_RETURN(data != nullptr,); CARLA_SAFE_ASSERT_RETURN(dataSize > 0,); CarlaString dataBase64(CarlaString::asBase64(data, dataSize)); CARLA_SAFE_ASSERT_RETURN(dataBase64.length() > 0,); String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName()); filePath += CARLA_OS_SEP_STR ".CarlaChunk_"; filePath += fShmAudioPool.getFilenameSuffix(); if (File(filePath).replaceWithText(dataBase64.buffer())) { const uint32_t ulength(static_cast(filePath.length())); const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetChunkDataFile); fShmNonRtClientControl.writeUInt(ulength); fShmNonRtClientControl.writeCustomData(filePath.toRawUTF8(), ulength); fShmNonRtClientControl.commitWrite(); } // save data internally as well fInfo.chunk.resize(dataSize); #ifdef CARLA_PROPER_CPP11_SUPPORT std::memcpy(fInfo.chunk.data(), data, dataSize); #else std::memcpy(&fInfo.chunk.front(), data, dataSize); #endif } // ------------------------------------------------------------------- // Set ui stuff void showCustomUI(const bool yesNo) override { { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(yesNo ? kPluginBridgeNonRtClientShowUI : kPluginBridgeNonRtClientHideUI); fShmNonRtClientControl.commitWrite(); } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (yesNo) { pData->tryTransient(); } else { pData->transientTryCounter = 0; } #endif } void idle() override { if (fBridgeThread.isThreadRunning()) { if (fInitiated && fTimedOut && pData->active) setActive(false, true, true); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPing); fShmNonRtClientControl.commitWrite(); } try { handleNonRtData(); } CARLA_SAFE_EXCEPTION("handleNonRtData"); } else if (fInitiated) { fTimedOut = true; fTimedError = true; fInitiated = false; handleProcessStopped(); } CarlaPlugin::idle(); } // ------------------------------------------------------------------- // Plugin state void reload() override { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,); carla_debug("CarlaPluginBridge::reload() - start"); const EngineProcessMode processMode(pData->engine->getProccessMode()); // Safely disable plugin for reload const ScopedDisabler sd(this); // cleanup of previous data pData->audioIn.clear(); pData->audioOut.clear(); pData->cvIn.clear(); pData->cvOut.clear(); pData->event.clear(); bool needsCtrlIn, needsCtrlOut; needsCtrlIn = needsCtrlOut = false; if (fInfo.aIns > 0) { pData->audioIn.createNew(fInfo.aIns); } if (fInfo.aOuts > 0) { pData->audioOut.createNew(fInfo.aOuts); needsCtrlIn = true; } if (fInfo.cvIns > 0) { pData->cvIn.createNew(fInfo.cvIns); } if (fInfo.cvOuts > 0) { pData->cvOut.createNew(fInfo.cvOuts); } if (fInfo.mIns > 0) needsCtrlIn = true; if (fInfo.mOuts > 0) needsCtrlOut = true; const uint portNameSize(pData->engine->getMaxPortNameSize()); CarlaString portName; // Audio Ins for (uint32_t j=0; j < fInfo.aIns; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (fInfo.aInNames != nullptr && fInfo.aInNames[j] != nullptr) { portName += fInfo.aInNames[j]; } else if (fInfo.aIns > 1) { portName += "input_"; portName += CarlaString(j+1); } else portName += "input"; portName.truncate(portNameSize); pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j); pData->audioIn.ports[j].rindex = j; } // Audio Outs for (uint32_t j=0; j < fInfo.aOuts; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (fInfo.aOutNames != nullptr && fInfo.aOutNames[j] != nullptr) { portName += fInfo.aOutNames[j]; } else if (fInfo.aOuts > 1) { portName += "output_"; portName += CarlaString(j+1); } else portName += "output"; portName.truncate(portNameSize); pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j); pData->audioOut.ports[j].rindex = j; } // TODO - MIDI // CV Ins for (uint32_t j=0; j < fInfo.cvIns; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (fInfo.cvInNames != nullptr && fInfo.cvInNames[j] != nullptr) { portName += fInfo.cvInNames[j]; } else if (fInfo.cvIns > 1) { portName += "cv_input_"; portName += CarlaString(j+1); } else portName += "cv_input"; portName.truncate(portNameSize); pData->cvIn.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, true, j); pData->cvIn.ports[j].rindex = j; } // CV Outs for (uint32_t j=0; j < fInfo.cvOuts; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (fInfo.cvOutNames != nullptr && fInfo.cvOutNames[j] != nullptr) { portName += fInfo.cvOutNames[j]; } else if (fInfo.cvOuts > 1) { portName += "cv_output_"; portName += CarlaString(j+1); } else portName += "cv_output"; portName.truncate(portNameSize); pData->cvOut.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, false, j); pData->cvOut.ports[j].rindex = j; } if (needsCtrlIn) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "event-in"; portName.truncate(portNameSize); pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->event.cvSourcePorts = pData->client->createCVSourcePorts(); #endif } if (needsCtrlOut) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "event-out"; portName.truncate(portNameSize); pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0); } // extra plugin hints pData->extraHints = 0x0; if (fInfo.mIns > 0) pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN; if (fInfo.mOuts > 0) pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT; bufferSizeChanged(pData->engine->getBufferSize()); reloadPrograms(true); carla_debug("CarlaPluginBridge::reload() - end"); } // ------------------------------------------------------------------- // Plugin processing void activate() noexcept override { if (! fBridgeThread.isThreadRunning()) { CARLA_SAFE_ASSERT_RETURN(restartBridgeThread(),); } { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientActivate); fShmNonRtClientControl.commitWrite(); } fTimedOut = false; try { waitForClient("activate", 2000); } CARLA_SAFE_EXCEPTION("activate - waitForClient"); } void deactivate() noexcept override { CARLA_SAFE_ASSERT_RETURN(! fTimedError,); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientDeactivate); fShmNonRtClientControl.commitWrite(); } fTimedOut = false; try { waitForClient("deactivate", 2000); } CARLA_SAFE_EXCEPTION("deactivate - waitForClient"); } void process(const float* const* const audioIn, float** const audioOut, const float* const* const cvIn, float** const cvOut, const uint32_t frames) override { // -------------------------------------------------------------------------------------------------------- // Check if active if (fTimedOut || fTimedError || ! pData->active) { // disable any output sound for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(audioOut[i], frames); for (uint32_t i=0; i < pData->cvOut.count; ++i) carla_zeroFloats(cvOut[i], frames); return; } // -------------------------------------------------------------------------------------------------------- // Check if needs reset if (pData->needsReset) { // TODO pData->needsReset = false; } // -------------------------------------------------------------------------------------------------------- // Event Input if (pData->event.portIn != nullptr) { // ---------------------------------------------------------------------------------------------------- // MIDI Input (External) if (pData->extNotes.mutex.tryLock()) { for (RtLinkedList::Itenerator it = pData->extNotes.data.begin2(); it.valid(); it.next()) { const ExternalMidiNote& note(it.getValue(kExternalMidiNoteFallback)); CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); uint8_t data1, data2, data3; data1 = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); data2 = note.note; data3 = note.velo; fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent); fShmRtClientControl.writeUInt(0); // time fShmRtClientControl.writeByte(0); // port fShmRtClientControl.writeByte(3); // size fShmRtClientControl.writeByte(data1); fShmRtClientControl.writeByte(data2); fShmRtClientControl.writeByte(data3); fShmRtClientControl.commitWrite(); } pData->extNotes.data.clear(); pData->extNotes.mutex.unlock(); } // End of MIDI Input (External) // ---------------------------------------------------------------------------------------------------- // Event Input (System) #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH bool allNotesOffSent = false; if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr) { const bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0x0; pData->event.cvSourcePorts->initPortBuffers(cvIn + pData->cvIn.count, frames, isSampleAccurate, pData->event.portIn); } #endif for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i) { const EngineEvent& event(pData->event.portIn->getEvent(i)); // Control change switch (event.type) { case kEngineEventTypeNull: break; case kEngineEventTypeControl: { const EngineControlEvent& ctrlEvent = event.ctrl; switch (ctrlEvent.type) { case kEngineControlEventTypeNull: break; case kEngineControlEventTypeParameter: #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // Control backend stuff if (event.channel == pData->ctrlChannel) { float value; if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0) { value = ctrlEvent.value; setDryWetRT(value, true); } if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0) { value = ctrlEvent.value*127.0f/100.0f; setVolumeRT(value, true); } if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0) { float left, right; value = ctrlEvent.value/0.5f - 1.0f; if (value < 0.0f) { left = -1.0f; right = (value*2.0f)+1.0f; } else if (value > 0.0f) { left = (value*2.0f)-1.0f; right = 1.0f; } else { left = -1.0f; right = 1.0f; } setBalanceLeftRT(left, true); setBalanceRightRT(right, true); } } #endif fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventParameter); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(event.channel); fShmRtClientControl.writeUShort(event.ctrl.param); fShmRtClientControl.writeFloat(event.ctrl.value); fShmRtClientControl.commitWrite(); break; case kEngineControlEventTypeMidiBank: if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventMidiBank); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(event.channel); fShmRtClientControl.writeUShort(event.ctrl.param); fShmRtClientControl.commitWrite(); } else if ((pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) != 0) { // VST2's that use banks usually require both a MSB bank message and a LSB bank message. The MSB bank message can just be 0 fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(0); // port fShmRtClientControl.writeByte(3); // size fShmRtClientControl.writeByte(uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT))); fShmRtClientControl.writeByte(MIDI_CONTROL_BANK_SELECT); fShmRtClientControl.writeByte(0); fShmRtClientControl.commitWrite(); fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(0); // port fShmRtClientControl.writeByte(3); // size fShmRtClientControl.writeByte(uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT))); fShmRtClientControl.writeByte(MIDI_CONTROL_BANK_SELECT__LSB); fShmRtClientControl.writeByte(uint8_t(event.ctrl.param)); fShmRtClientControl.commitWrite(); } break; case kEngineControlEventTypeMidiProgram: if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES || pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventMidiProgram); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(event.channel); fShmRtClientControl.writeUShort(event.ctrl.param); fShmRtClientControl.commitWrite(); } break; case kEngineControlEventTypeAllSoundOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventAllSoundOff); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(event.channel); fShmRtClientControl.commitWrite(); } break; case kEngineControlEventTypeAllNotesOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (event.channel == pData->ctrlChannel && ! allNotesOffSent) { allNotesOffSent = true; postponeRtAllNotesOff(); } #endif fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventAllNotesOff); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(event.channel); fShmRtClientControl.commitWrite(); } break; } // switch (ctrlEvent.type) break; } // case kEngineEventTypeControl case kEngineEventTypeMidi: { const EngineMidiEvent& midiEvent(event.midi); if (midiEvent.size == 0 || midiEvent.size >= MAX_MIDI_VALUE) continue; const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data); uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData)); if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) continue; if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0) continue; if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0) continue; if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) continue; // Fix bad note-off if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0) status = MIDI_STATUS_NOTE_OFF; fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(midiEvent.port); fShmRtClientControl.writeByte(midiEvent.size); fShmRtClientControl.writeByte(uint8_t(midiData[0] | (event.channel & MIDI_CHANNEL_BIT))); for (uint8_t j=1; j < midiEvent.size; ++j) fShmRtClientControl.writeByte(midiData[j]); fShmRtClientControl.commitWrite(); if (status == MIDI_STATUS_NOTE_ON) { pData->postponeRtEvent(kPluginPostRtEventNoteOn, true, event.channel, midiData[1], midiData[2], 0.0f); } else if (status == MIDI_STATUS_NOTE_OFF) { pData->postponeRtEvent(kPluginPostRtEventNoteOff, true, event.channel, midiData[1], 0, 0.0f); } } break; } } pData->postRtEvents.trySplice(); } // End of Event Input if (! processSingle(audioIn, audioOut, cvIn, cvOut, frames)) return; // -------------------------------------------------------------------------------------------------------- // Control and MIDI Output if (pData->event.portOut != nullptr) { float value; for (uint32_t k=0; k < pData->param.count; ++k) { if (pData->param.data[k].type != PARAMETER_OUTPUT) continue; if (pData->param.data[k].mappedControlIndex > 0) { value = pData->param.ranges[k].getNormalizedValue(fParams[k].value); pData->event.portOut->writeControlEvent(0, pData->param.data[k].midiChannel, kEngineControlEventTypeParameter, static_cast(pData->param.data[k].mappedControlIndex), value); } } uint32_t time; uint8_t port, size; const uint8_t* midiData(fShmRtClientControl.data->midiOut); for (std::size_t read=0; readevent.portOut->writeMidiEvent(time, size, data); read += kBridgeBaseMidiOutHeaderSize + size; } // TODO (void)port; } // End of Control and MIDI Output } bool processSingle(const float* const* const audioIn, float** const audioOut, const float* const* const cvIn, float** const cvOut, const uint32_t frames) { CARLA_SAFE_ASSERT_RETURN(! fTimedError, false); CARLA_SAFE_ASSERT_RETURN(frames > 0, false); CARLA_SAFE_ASSERT_RETURN(frames <= fBufferSize, false); if (pData->audioIn.count > 0) { CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false); } if (pData->audioOut.count > 0) { CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false); } if (pData->cvIn.count > 0) { CARLA_SAFE_ASSERT_RETURN(cvIn != nullptr, false); } if (pData->cvOut.count > 0) { CARLA_SAFE_ASSERT_RETURN(cvOut != nullptr, false); } // -------------------------------------------------------------------------------------------------------- // Try lock, silence otherwise #ifndef STOAT_TEST_BUILD if (pData->engine->isOffline()) { pData->singleMutex.lock(); } else #endif if (! pData->singleMutex.tryLock()) { for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(audioOut[i], frames); for (uint32_t i=0; i < pData->cvOut.count; ++i) carla_zeroFloats(cvOut[i], frames); return false; } // -------------------------------------------------------------------------------------------------------- // Reset audio buffers for (uint32_t i=0; i < pData->audioIn.count; ++i) carla_copyFloats(fShmAudioPool.data + (i * fBufferSize), audioIn[i], frames); for (uint32_t i=0; i < pData->cvIn.count; ++i) carla_copyFloats(fShmAudioPool.data + ((pData->audioIn.count + pData->audioOut.count + i) * fBufferSize), cvIn[i], frames); // -------------------------------------------------------------------------------------------------------- // TimeInfo const EngineTimeInfo timeInfo(pData->engine->getTimeInfo()); BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo); bridgeTimeInfo.playing = timeInfo.playing; bridgeTimeInfo.frame = timeInfo.frame; bridgeTimeInfo.usecs = timeInfo.usecs; bridgeTimeInfo.validFlags = timeInfo.bbt.valid ? kPluginBridgeTimeInfoValidBBT : 0x0; if (timeInfo.bbt.valid) { bridgeTimeInfo.bar = timeInfo.bbt.bar; bridgeTimeInfo.beat = timeInfo.bbt.beat; bridgeTimeInfo.tick = timeInfo.bbt.tick; bridgeTimeInfo.beatsPerBar = timeInfo.bbt.beatsPerBar; bridgeTimeInfo.beatType = timeInfo.bbt.beatType; bridgeTimeInfo.ticksPerBeat = timeInfo.bbt.ticksPerBeat; bridgeTimeInfo.beatsPerMinute = timeInfo.bbt.beatsPerMinute; bridgeTimeInfo.barStartTick = timeInfo.bbt.barStartTick; } // -------------------------------------------------------------------------------------------------------- // Run plugin { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientProcess); fShmRtClientControl.writeUInt(frames); fShmRtClientControl.commitWrite(); } waitForClient("process", fProcWaitTime); if (fTimedOut) { pData->singleMutex.unlock(); return false; } for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_copyFloats(audioOut[i], fShmAudioPool.data + ((pData->audioIn.count + i) * fBufferSize), frames); for (uint32_t i=0; i < pData->cvOut.count; ++i) carla_copyFloats(cvOut[i], fShmAudioPool.data + ((pData->audioIn.count + pData->audioOut.count + pData->cvIn.count + i) * fBufferSize), frames); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // -------------------------------------------------------------------------------------------------------- // Post-processing (dry/wet, volume and balance) { const bool doVolume = (pData->hints & PLUGIN_CAN_VOLUME) != 0 && carla_isNotEqual(pData->postProc.volume, 1.0f); const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f); const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f)); const bool isMono = (pData->audioIn.count == 1); bool isPair; float bufValue, oldBufLeft[doBalance ? frames : 1]; for (uint32_t i=0; i < pData->audioOut.count; ++i) { // Dry/Wet if (doDryWet) { const uint32_t c = isMono ? 0 : i; for (uint32_t k=0; k < frames; ++k) { # ifndef BUILD_BRIDGE if (k < pData->latency.frames && pData->latency.buffers != nullptr) bufValue = pData->latency.buffers[c][k]; else if (pData->latency.frames < frames) bufValue = audioIn[c][k-pData->latency.frames]; else # endif bufValue = audioIn[c][k]; audioOut[i][k] = (audioOut[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet)); } } // Balance if (doBalance) { isPair = (i % 2 == 0); if (isPair) { CARLA_ASSERT(i+1 < pData->audioOut.count); carla_copyFloats(oldBufLeft, audioOut[i], frames); } float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f; float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f; for (uint32_t k=0; k < frames; ++k) { if (isPair) { // left audioOut[i][k] = oldBufLeft[k] * (1.0f - balRangeL); audioOut[i][k] += audioOut[i+1][k] * (1.0f - balRangeR); } else { // right audioOut[i][k] = audioOut[i][k] * balRangeR; audioOut[i][k] += oldBufLeft[k] * balRangeL; } } } // Volume (and buffer copy) if (doVolume) { for (uint32_t k=0; k < frames; ++k) audioOut[i][k] *= pData->postProc.volume; } } } // End of Post-processing # ifndef BUILD_BRIDGE // -------------------------------------------------------------------------------------------------------- // Save latency values for next callback if (pData->latency.frames != 0 && pData->latency.buffers != nullptr) { const uint32_t latframes = pData->latency.frames; if (latframes <= frames) { for (uint32_t i=0; i < pData->audioIn.count; ++i) carla_copyFloats(pData->latency.buffers[i], audioIn[i]+(frames-latframes), latframes); } else { const uint32_t diff = latframes - frames; for (uint32_t i=0, k; iaudioIn.count; ++i) { // push back buffer by 'frames' for (k=0; k < diff; ++k) pData->latency.buffers[i][k] = pData->latency.buffers[i][k+frames]; // put current input at the end for (uint32_t j=0; k < latframes; ++j, ++k) pData->latency.buffers[i][k] = audioIn[i][j]; } } } # endif #endif // BUILD_BRIDGE_ALTERNATIVE_ARCH // -------------------------------------------------------------------------------------------------------- pData->singleMutex.unlock(); return true; } void bufferSizeChanged(const uint32_t newBufferSize) override { fBufferSize = newBufferSize; resizeAudioPool(newBufferSize); { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetBufferSize); fShmRtClientControl.writeUInt(newBufferSize); fShmRtClientControl.commitWrite(); } //fProcWaitTime = newBufferSize*1000/pData->engine->getSampleRate(); fProcWaitTime = 1000; waitForClient("buffersize", 1000); } void sampleRateChanged(const double newSampleRate) override { { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetSampleRate); fShmRtClientControl.writeDouble(newSampleRate); fShmRtClientControl.commitWrite(); } //fProcWaitTime = pData->engine->getBufferSize()*1000/newSampleRate; fProcWaitTime = 1000; waitForClient("samplerate", 1000); } void offlineModeChanged(const bool isOffline) override { { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetOnline); fShmRtClientControl.writeBool(isOffline); fShmRtClientControl.commitWrite(); } waitForClient("offline", 1000); } // ------------------------------------------------------------------- // Plugin buffers void clearBuffers() noexcept override { if (fParams != nullptr) { delete[] fParams; fParams = nullptr; } CarlaPlugin::clearBuffers(); } // ------------------------------------------------------------------- // Post-poned UI Stuff void uiParameterChange(const uint32_t index, const float value) noexcept override { CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,); const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiParameterChange); fShmNonRtClientControl.writeUInt(index); fShmNonRtClientControl.writeFloat(value); fShmNonRtClientControl.commitWrite(); } void uiProgramChange(const uint32_t index) noexcept override { CARLA_SAFE_ASSERT_RETURN(index < pData->prog.count,); const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiProgramChange); fShmNonRtClientControl.writeUInt(index); fShmNonRtClientControl.commitWrite(); } void uiMidiProgramChange(const uint32_t index) noexcept override { CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,); const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiMidiProgramChange); fShmNonRtClientControl.writeUInt(index); fShmNonRtClientControl.commitWrite(); } void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override { CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,); const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiNoteOn); fShmNonRtClientControl.writeByte(channel); fShmNonRtClientControl.writeByte(note); fShmNonRtClientControl.writeByte(velo); fShmNonRtClientControl.commitWrite(); } void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override { CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiNoteOff); fShmNonRtClientControl.writeByte(channel); fShmNonRtClientControl.writeByte(note); fShmNonRtClientControl.commitWrite(); } // ------------------------------------------------------------------- // Internal helper functions void restoreLV2State() noexcept override { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientRestoreLV2State); fShmNonRtClientControl.commitWrite(); } void waitForBridgeSaveSignal() noexcept override { // VSTs only save chunks, for which we already have a waitForSaved there if (fPluginType != PLUGIN_VST2) waitForSaved(); } // ------------------------------------------------------------------- void handleNonRtData() { for (; fShmNonRtServerControl.isDataAvailableForReading();) { const PluginBridgeNonRtServerOpcode opcode(fShmNonRtServerControl.readOpcode()); #ifdef DEBUG if (opcode != kPluginBridgeNonRtServerPong && opcode != kPluginBridgeNonRtServerParameterValue2) { carla_debug("CarlaPluginBridge::handleNonRtData() - got opcode: %s", PluginBridgeNonRtServerOpcode2str(opcode)); } #endif switch (opcode) { case kPluginBridgeNonRtServerNull: case kPluginBridgeNonRtServerPong: break; case kPluginBridgeNonRtServerVersion: fBridgeVersion = fShmNonRtServerControl.readUInt(); break; case kPluginBridgeNonRtServerPluginInfo1: { // uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId const uint32_t category = fShmNonRtServerControl.readUInt(); const uint32_t hints = fShmNonRtServerControl.readUInt(); const uint32_t optionAv = fShmNonRtServerControl.readUInt(); const uint32_t optionEn = fShmNonRtServerControl.readUInt(); const int64_t uniqueId = fShmNonRtServerControl.readLong(); if (fUniqueId != 0) { CARLA_SAFE_ASSERT_INT2(fUniqueId == uniqueId, fUniqueId, uniqueId); } pData->hints = hints | PLUGIN_IS_BRIDGE; pData->options = optionEn; fInfo.category = static_cast(category); fInfo.optionsAvailable = optionAv; } break; case kPluginBridgeNonRtServerPluginInfo2: { // uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright) // realName const uint32_t realNameSize(fShmNonRtServerControl.readUInt()); char realName[realNameSize+1]; carla_zeroChars(realName, realNameSize+1); fShmNonRtServerControl.readCustomData(realName, realNameSize); // label const uint32_t labelSize(fShmNonRtServerControl.readUInt()); char label[labelSize+1]; carla_zeroChars(label, labelSize+1); fShmNonRtServerControl.readCustomData(label, labelSize); // maker const uint32_t makerSize(fShmNonRtServerControl.readUInt()); char maker[makerSize+1]; carla_zeroChars(maker, makerSize+1); fShmNonRtServerControl.readCustomData(maker, makerSize); // copyright const uint32_t copyrightSize(fShmNonRtServerControl.readUInt()); char copyright[copyrightSize+1]; carla_zeroChars(copyright, copyrightSize+1); fShmNonRtServerControl.readCustomData(copyright, copyrightSize); fInfo.name = realName; fInfo.label = label; fInfo.maker = maker; fInfo.copyright = copyright; if (pData->name == nullptr) pData->name = pData->engine->getUniquePluginName(realName); } break; case kPluginBridgeNonRtServerAudioCount: { // uint/ins, uint/outs fInfo.clear(); fInfo.aIns = fShmNonRtServerControl.readUInt(); fInfo.aOuts = fShmNonRtServerControl.readUInt(); if (fInfo.aIns > 0) { fInfo.aInNames = new const char*[fInfo.aIns]; carla_zeroPointers(fInfo.aInNames, fInfo.aIns); } if (fInfo.aOuts > 0) { fInfo.aOutNames = new const char*[fInfo.aOuts]; carla_zeroPointers(fInfo.aOutNames, fInfo.aOuts); } } break; case kPluginBridgeNonRtServerMidiCount: { // uint/ins, uint/outs fInfo.mIns = fShmNonRtServerControl.readUInt(); fInfo.mOuts = fShmNonRtServerControl.readUInt(); } break; case kPluginBridgeNonRtServerCvCount: { // uint/ins, uint/outs fInfo.cvIns = fShmNonRtServerControl.readUInt(); fInfo.cvOuts = fShmNonRtServerControl.readUInt(); } break; case kPluginBridgeNonRtServerParameterCount: { // uint/count const uint32_t count = fShmNonRtServerControl.readUInt(); // delete old data pData->param.clear(); if (fParams != nullptr) { delete[] fParams; fParams = nullptr; } if (count > 0) { pData->param.createNew(count, false); fParams = new BridgeParamInfo[count]; // we might not receive all parameter data, so ensure range max is not 0 for (uint32_t i=0; iparam.ranges[i].def = 0.0f; pData->param.ranges[i].min = 0.0f; pData->param.ranges[i].max = 1.0f; pData->param.ranges[i].step = 0.001f; pData->param.ranges[i].stepSmall = 0.0001f; pData->param.ranges[i].stepLarge = 0.1f; } } } break; case kPluginBridgeNonRtServerProgramCount: { // uint/count pData->prog.clear(); if (const uint32_t count = fShmNonRtServerControl.readUInt()) pData->prog.createNew(count); } break; case kPluginBridgeNonRtServerMidiProgramCount: { // uint/count pData->midiprog.clear(); if (const uint32_t count = fShmNonRtServerControl.readUInt()) pData->midiprog.createNew(count); } break; case kPluginBridgeNonRtServerPortName: { // byte/type, uint/index, uint/size, str[] (name) const uint8_t portType = fShmNonRtServerControl.readByte(); const uint32_t index = fShmNonRtServerControl.readUInt(); // name const uint32_t nameSize(fShmNonRtServerControl.readUInt()); char* const name = new char[nameSize+1]; carla_zeroChars(name, nameSize+1); fShmNonRtServerControl.readCustomData(name, nameSize); CARLA_SAFE_ASSERT_BREAK(portType > kPluginBridgePortNull && portType < kPluginBridgePortTypeCount); switch (portType) { case kPluginBridgePortAudioInput: CARLA_SAFE_ASSERT_BREAK(index < fInfo.aIns); fInfo.aInNames[index] = name; break; case kPluginBridgePortAudioOutput: CARLA_SAFE_ASSERT_BREAK(index < fInfo.aOuts); fInfo.aOutNames[index] = name; break; } } break; case kPluginBridgeNonRtServerParameterData1: { // uint/index, int/rindex, uint/type, uint/hints, int/cc const uint32_t index = fShmNonRtServerControl.readUInt(); const int32_t rindex = fShmNonRtServerControl.readInt(); const uint32_t type = fShmNonRtServerControl.readUInt(); const uint32_t hints = fShmNonRtServerControl.readUInt(); const int16_t ctrl = fShmNonRtServerControl.readShort(); CARLA_SAFE_ASSERT_BREAK(ctrl >= CONTROL_INDEX_NONE && ctrl <= CONTROL_INDEX_MAX_ALLOWED); CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count); if (index < pData->param.count) { pData->param.data[index].type = static_cast(type); pData->param.data[index].index = static_cast(index); pData->param.data[index].rindex = rindex; pData->param.data[index].hints = hints; pData->param.data[index].mappedControlIndex = ctrl; } } break; case kPluginBridgeNonRtServerParameterData2: { // uint/index, uint/size, str[] (name), uint/size, str[] (unit) const uint32_t index = fShmNonRtServerControl.readUInt(); // name const uint32_t nameSize(fShmNonRtServerControl.readUInt()); char name[nameSize+1]; carla_zeroChars(name, nameSize+1); fShmNonRtServerControl.readCustomData(name, nameSize); // symbol const uint32_t symbolSize(fShmNonRtServerControl.readUInt()); char symbol[symbolSize+1]; carla_zeroChars(symbol, symbolSize+1); fShmNonRtServerControl.readCustomData(symbol, symbolSize); // unit const uint32_t unitSize(fShmNonRtServerControl.readUInt()); char unit[unitSize+1]; carla_zeroChars(unit, unitSize+1); fShmNonRtServerControl.readCustomData(unit, unitSize); CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count); if (index < pData->param.count) { fParams[index].name = name; fParams[index].symbol = symbol; fParams[index].unit = unit; } } break; case kPluginBridgeNonRtServerParameterRanges: { // uint/index, float/def, float/min, float/max, float/step, float/stepSmall, float/stepLarge const uint32_t index = fShmNonRtServerControl.readUInt(); const float def = fShmNonRtServerControl.readFloat(); const float min = fShmNonRtServerControl.readFloat(); const float max = fShmNonRtServerControl.readFloat(); const float step = fShmNonRtServerControl.readFloat(); const float stepSmall = fShmNonRtServerControl.readFloat(); const float stepLarge = fShmNonRtServerControl.readFloat(); CARLA_SAFE_ASSERT_BREAK(min < max); CARLA_SAFE_ASSERT_BREAK(def >= min); CARLA_SAFE_ASSERT_BREAK(def <= max); CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count); if (index < pData->param.count) { pData->param.ranges[index].def = def; pData->param.ranges[index].min = min; pData->param.ranges[index].max = max; pData->param.ranges[index].step = step; pData->param.ranges[index].stepSmall = stepSmall; pData->param.ranges[index].stepLarge = stepLarge; } } break; case kPluginBridgeNonRtServerParameterValue: { // uint/index, float/value const uint32_t index = fShmNonRtServerControl.readUInt(); const float value = fShmNonRtServerControl.readFloat(); if (index < pData->param.count) { const float fixedValue(pData->param.getFixedValue(index, value)); if (carla_isNotEqual(fParams[index].value, fixedValue)) { fParams[index].value = fixedValue; CarlaPlugin::setParameterValue(index, fixedValue, false, true, true); } } } break; case kPluginBridgeNonRtServerParameterValue2: { // uint/index, float/value const uint32_t index = fShmNonRtServerControl.readUInt(); const float value = fShmNonRtServerControl.readFloat(); if (index < pData->param.count) { const float fixedValue(pData->param.getFixedValue(index, value)); fParams[index].value = fixedValue; } } break; case kPluginBridgeNonRtServerParameterTouch: { // uint/index, bool/touch const uint32_t index = fShmNonRtServerControl.readUInt(); const bool touch = fShmNonRtServerControl.readBool(); pData->engine->touchPluginParameter(pData->id, index, touch); } break; case kPluginBridgeNonRtServerDefaultValue: { // uint/index, float/value const uint32_t index = fShmNonRtServerControl.readUInt(); const float value = fShmNonRtServerControl.readFloat(); if (index < pData->param.count) pData->param.ranges[index].def = value; } break; case kPluginBridgeNonRtServerCurrentProgram: { // int/index const int32_t index = fShmNonRtServerControl.readInt(); CARLA_SAFE_ASSERT_BREAK(index >= -1); CARLA_SAFE_ASSERT_INT2(index < static_cast(pData->prog.count), index, pData->prog.count); CarlaPlugin::setProgram(index, false, true, true); } break; case kPluginBridgeNonRtServerCurrentMidiProgram: { // int/index const int32_t index = fShmNonRtServerControl.readInt(); CARLA_SAFE_ASSERT_BREAK(index >= -1); CARLA_SAFE_ASSERT_INT2(index < static_cast(pData->midiprog.count), index, pData->midiprog.count); CarlaPlugin::setMidiProgram(index, false, true, true); } break; case kPluginBridgeNonRtServerProgramName: { // uint/index, uint/size, str[] (name) const uint32_t index = fShmNonRtServerControl.readUInt(); // name const uint32_t nameSize(fShmNonRtServerControl.readUInt()); char name[nameSize+1]; carla_zeroChars(name, nameSize+1); fShmNonRtServerControl.readCustomData(name, nameSize); CARLA_SAFE_ASSERT_INT2(index < pData->prog.count, index, pData->prog.count); if (index < pData->prog.count) { if (pData->prog.names[index] != nullptr) delete[] pData->prog.names[index]; pData->prog.names[index] = carla_strdup(name); } } break; case kPluginBridgeNonRtServerMidiProgramData: { // uint/index, uint/bank, uint/program, uint/size, str[] (name) const uint32_t index = fShmNonRtServerControl.readUInt(); const uint32_t bank = fShmNonRtServerControl.readUInt(); const uint32_t program = fShmNonRtServerControl.readUInt(); // name const uint32_t nameSize(fShmNonRtServerControl.readUInt()); char name[nameSize+1]; carla_zeroChars(name, nameSize+1); fShmNonRtServerControl.readCustomData(name, nameSize); CARLA_SAFE_ASSERT_INT2(index < pData->midiprog.count, index, pData->midiprog.count); if (index < pData->midiprog.count) { if (pData->midiprog.data[index].name != nullptr) delete[] pData->midiprog.data[index].name; pData->midiprog.data[index].bank = bank; pData->midiprog.data[index].program = program; pData->midiprog.data[index].name = carla_strdup(name); } } break; case kPluginBridgeNonRtServerSetCustomData: { // uint/size, str[], uint/size, str[], uint/size, str[] // type const uint32_t typeSize(fShmNonRtServerControl.readUInt()); char type[typeSize+1]; carla_zeroChars(type, typeSize+1); fShmNonRtServerControl.readCustomData(type, typeSize); // key const uint32_t keySize(fShmNonRtServerControl.readUInt()); char key[keySize+1]; carla_zeroChars(key, keySize+1); fShmNonRtServerControl.readCustomData(key, keySize); // value const uint32_t valueSize(fShmNonRtServerControl.readUInt()); char value[valueSize+1]; carla_zeroChars(value, valueSize+1); if (valueSize > 0) fShmNonRtServerControl.readCustomData(value, valueSize); CarlaPlugin::setCustomData(type, key, value, false); } break; case kPluginBridgeNonRtServerSetChunkDataFile: { // uint/size, str[] (filename) // chunkFilePath const uint32_t chunkFilePathSize(fShmNonRtServerControl.readUInt()); char chunkFilePath[chunkFilePathSize+1]; carla_zeroChars(chunkFilePath, chunkFilePathSize+1); fShmNonRtServerControl.readCustomData(chunkFilePath, chunkFilePathSize); String realChunkFilePath(chunkFilePath); #ifndef CARLA_OS_WIN // Using Wine, fix temp dir if (fBinaryType == BINARY_WIN32 || fBinaryType == BINARY_WIN64) { const StringArray driveLetterSplit(StringArray::fromTokens(realChunkFilePath, ":/", "")); carla_stdout("chunk save path BEFORE => %s", realChunkFilePath.toRawUTF8()); realChunkFilePath = fWinePrefix; realChunkFilePath += "/drive_"; realChunkFilePath += driveLetterSplit[0].toLowerCase(); realChunkFilePath += driveLetterSplit[1]; realChunkFilePath = realChunkFilePath.replace("\\", "/"); carla_stdout("chunk save path AFTER => %s", realChunkFilePath.toRawUTF8()); } #endif File chunkFile(realChunkFilePath); CARLA_SAFE_ASSERT_BREAK(chunkFile.existsAsFile()); fInfo.chunk = carla_getChunkFromBase64String(chunkFile.loadFileAsString().toRawUTF8()); chunkFile.deleteFile(); } break; case kPluginBridgeNonRtServerSetLatency: // uint fLatency = fShmNonRtServerControl.readUInt(); #ifndef BUILD_BRIDGE if (! fInitiated) pData->latency.recreateBuffers(std::max(fInfo.aIns, fInfo.aOuts), fLatency); #endif break; case kPluginBridgeNonRtServerSetParameterText: { const int32_t index = fShmNonRtServerControl.readInt(); const uint32_t textSize(fShmNonRtServerControl.readUInt()); char text[textSize+1]; carla_zeroChars(text, textSize+1); fShmNonRtServerControl.readCustomData(text, textSize); fReceivingParamText.setReceivedData(index, text, textSize); } break; case kPluginBridgeNonRtServerReady: fInitiated = true; break; case kPluginBridgeNonRtServerSaved: fSaved = true; break; case kPluginBridgeNonRtServerUiClosed: #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->transientTryCounter = 0; #endif pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); break; case kPluginBridgeNonRtServerError: { // error const uint32_t errorSize(fShmNonRtServerControl.readUInt()); char error[errorSize+1]; carla_zeroChars(error, errorSize+1); fShmNonRtServerControl.readCustomData(error, errorSize); if (fInitiated) { pData->engine->callback(true, true, ENGINE_CALLBACK_ERROR, pData->id, 0, 0, 0, 0.0f, error); // just in case pData->engine->setLastError(error); fInitError = true; } else { pData->engine->setLastError(error); fInitError = true; fInitiated = true; } } break; } } } // ------------------------------------------------------------------- uintptr_t getUiBridgeProcessId() const noexcept override { return fBridgeThread.getProcessPID(); } const void* getExtraStuff() const noexcept override { return fBridgeBinary.isNotEmpty() ? fBridgeBinary.buffer() : nullptr; } // ------------------------------------------------------------------- bool init(const char* const filename, const char* const name, const char* const label, const int64_t uniqueId, const uint options, const char* const bridgeBinary) { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); // --------------------------------------------------------------- // first checks if (pData->client != nullptr) { pData->engine->setLastError("Plugin client is already registered"); return false; } if (bridgeBinary == nullptr || bridgeBinary[0] == '\0') { pData->engine->setLastError("null bridge binary"); return false; } // --------------------------------------------------------------- // set info if (name != nullptr && name[0] != '\0') pData->name = pData->engine->getUniquePluginName(name); if (filename != nullptr && filename[0] != '\0') pData->filename = carla_strdup(filename); else pData->filename = carla_strdup(""); fUniqueId = uniqueId; fBridgeBinary = bridgeBinary; std::srand(static_cast(std::time(nullptr))); // --------------------------------------------------------------- // init sem/shm if (! fShmAudioPool.initializeServer()) { carla_stderr("Failed to initialize shared memory audio pool"); return false; } if (! fShmRtClientControl.initializeServer()) { carla_stderr("Failed to initialize RT client control"); fShmAudioPool.clear(); return false; } if (! fShmNonRtClientControl.initializeServer()) { carla_stderr("Failed to initialize Non-RT client control"); fShmRtClientControl.clear(); fShmAudioPool.clear(); return false; } if (! fShmNonRtServerControl.initializeServer()) { carla_stderr("Failed to initialize Non-RT server control"); fShmNonRtClientControl.clear(); fShmRtClientControl.clear(); fShmAudioPool.clear(); return false; } #ifndef CARLA_OS_WIN // --------------------------------------------------------------- // set wine prefix if (fBridgeBinary.contains(".exe", true)) { const EngineOptions& engineOptions(pData->engine->getOptions()); if (engineOptions.wine.autoPrefix) fWinePrefix = findWinePrefix(pData->filename); if (fWinePrefix.isEmpty()) { const char* const envWinePrefix(std::getenv("WINEPREFIX")); if (envWinePrefix != nullptr && envWinePrefix[0] != '\0') fWinePrefix = envWinePrefix; else if (engineOptions.wine.fallbackPrefix != nullptr && engineOptions.wine.fallbackPrefix[0] != '\0') fWinePrefix = engineOptions.wine.fallbackPrefix; else fWinePrefix = File::getSpecialLocation(File::userHomeDirectory).getFullPathName() + "/.wine"; } } #endif // --------------------------------------------------------------- // init bridge thread { char shmIdsStr[6*4+1]; carla_zeroChars(shmIdsStr, 6*4+1); std::strncpy(shmIdsStr+6*0, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6); std::strncpy(shmIdsStr+6*1, &fShmRtClientControl.filename[fShmRtClientControl.filename.length()-6], 6); std::strncpy(shmIdsStr+6*2, &fShmNonRtClientControl.filename[fShmNonRtClientControl.filename.length()-6], 6); std::strncpy(shmIdsStr+6*3, &fShmNonRtServerControl.filename[fShmNonRtServerControl.filename.length()-6], 6); fBridgeThread.setData( #ifndef CARLA_OS_WIN fWinePrefix.toRawUTF8(), #endif bridgeBinary, label, shmIdsStr); } if (! restartBridgeThread()) return false; // --------------------------------------------------------------- // register client if (pData->name == nullptr) { if (label != nullptr && label[0] != '\0') pData->name = pData->engine->getUniquePluginName(label); else pData->name = pData->engine->getUniquePluginName("unknown"); } pData->client = pData->engine->addClient(this); if (pData->client == nullptr || ! pData->client->isOk()) { pData->engine->setLastError("Failed to register plugin client"); return false; } // --------------------------------------------------------------- // set options pData->options = 0x0; if ((fInfo.optionsAvailable & PLUGIN_OPTION_FIXED_BUFFERS) == 0x0) pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; else if (isPluginOptionEnabled(options, PLUGIN_OPTION_FIXED_BUFFERS)) pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; if (pData->engine->getOptions().forceStereo) { pData->options |= PLUGIN_OPTION_FORCE_STEREO; } else if (fInfo.optionsAvailable & PLUGIN_OPTION_FORCE_STEREO) { if (options & PLUGIN_OPTION_FORCE_STEREO) pData->options |= PLUGIN_OPTION_FORCE_STEREO; } if (fInfo.optionsAvailable & PLUGIN_OPTION_USE_CHUNKS) if (isPluginOptionEnabled(options, PLUGIN_OPTION_USE_CHUNKS)) pData->options |= PLUGIN_OPTION_USE_CHUNKS; if (fInfo.optionsAvailable & PLUGIN_OPTION_SEND_CONTROL_CHANGES) if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; if (fInfo.optionsAvailable & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)) pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; if (fInfo.optionsAvailable & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)) pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; if (fInfo.optionsAvailable & PLUGIN_OPTION_SEND_PITCHBEND) if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND)) pData->options |= PLUGIN_OPTION_SEND_PITCHBEND; if (fInfo.optionsAvailable & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF)) pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; if (fInfo.optionsAvailable & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) { if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PROGRAM_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES; } else if (fInfo.optionsAvailable & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) { if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES)) pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; } // kPluginBridgeNonRtClientSetOptions was added in API 7 if (fBridgeVersion >= 7) { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetOptions); fShmNonRtClientControl.writeUInt(pData->options); fShmNonRtClientControl.commitWrite(); } return true; } private: const BinaryType fBinaryType; const PluginType fPluginType; uint fBridgeVersion; bool fInitiated; bool fInitError; bool fSaved; bool fTimedOut; bool fTimedError; uint fBufferSize; uint fProcWaitTime; CarlaString fBridgeBinary; CarlaPluginBridgeThread fBridgeThread; BridgeAudioPool fShmAudioPool; BridgeRtClientControl fShmRtClientControl; BridgeNonRtClientControl fShmNonRtClientControl; BridgeNonRtServerControl fShmNonRtServerControl; #ifndef CARLA_OS_WIN String fWinePrefix; #endif class ReceivingParamText { public: ReceivingParamText() noexcept : dataRecv(false), dataOk(false), index(-1), strBuf(nullptr), mutex() {} bool isCurrentlyWaitingData() const noexcept { return index >= 0; } bool wasDataReceived(bool* const success) const noexcept { *success = dataOk; return dataRecv; } void setTargetData(const int32_t i, char* const b) noexcept { const CarlaMutexLocker cml(mutex); dataOk = false; dataRecv = false; index = i; strBuf = b; } void setReceivedData(const int32_t i, const char* const b, const uint blen) noexcept { CarlaScopedValueSetter svs(dataRecv, false, true); const CarlaMutexLocker cml(mutex); // make backup and reset data const int32_t indexCopy = index; char* const strBufCopy = strBuf; index = -1; strBuf = nullptr; CARLA_SAFE_ASSERT_RETURN(indexCopy == i,); CARLA_SAFE_ASSERT_RETURN(strBufCopy != nullptr,); std::strncpy(strBufCopy, b, std::min(blen, STR_MAX-1U)); dataOk = true; } private: bool dataRecv; bool dataOk; int32_t index; char* strBuf; CarlaMutex mutex; CARLA_DECLARE_NON_COPY_CLASS(ReceivingParamText) } fReceivingParamText; struct Info { uint32_t aIns, aOuts; uint32_t cvIns, cvOuts; uint32_t mIns, mOuts; PluginCategory category; uint optionsAvailable; CarlaString name; CarlaString label; CarlaString maker; CarlaString copyright; const char** aInNames; const char** aOutNames; const char** cvInNames; const char** cvOutNames; std::vector chunk; Info() : aIns(0), aOuts(0), cvIns(0), cvOuts(0), mIns(0), mOuts(0), category(PLUGIN_CATEGORY_NONE), optionsAvailable(0), name(), label(), maker(), copyright(), aInNames(nullptr), aOutNames(nullptr), cvInNames(nullptr), cvOutNames(nullptr), chunk() {} ~Info() { clear(); } void clear() { if (aInNames != nullptr) { CARLA_SAFE_ASSERT_INT(aIns > 0, aIns); for (uint32_t i=0; i 0, aOuts); for (uint32_t i=0; i 0, cvIns); for (uint32_t i=0; i 0, cvOuts); for (uint32_t i=0; iactive; pData->active = false; if (wasActive) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->engine->callback(true, true, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_ACTIVE, 0, 0, 0.0f, nullptr); #endif } if (pData->hints & PLUGIN_HAS_CUSTOM_UI) { pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); } } void resizeAudioPool(const uint32_t bufferSize) { fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts, fInfo.cvIns+fInfo.cvOuts); fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool); fShmRtClientControl.writeULong(static_cast(fShmAudioPool.dataSize)); fShmRtClientControl.commitWrite(); waitForClient("resize-pool", 5000); } void waitForClient(const char* const action, const uint msecs) { CARLA_SAFE_ASSERT_RETURN(! fTimedOut,); CARLA_SAFE_ASSERT_RETURN(! fTimedError,); if (fShmRtClientControl.waitForClient(msecs)) return; fTimedOut = true; carla_stderr2("waitForClient(%s) timed out", action); } bool restartBridgeThread() { fInitiated = false; fInitError = false; fTimedError = false; // reset memory fShmRtClientControl.data->procFlags = 0; carla_zeroStruct(fShmRtClientControl.data->timeInfo); carla_zeroBytes(fShmRtClientControl.data->midiOut, kBridgeRtClientDataMidiOutSize); fShmRtClientControl.clearData(); fShmNonRtClientControl.clearData(); fShmNonRtServerControl.clearData(); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientVersion); fShmNonRtClientControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT); fShmNonRtClientControl.writeUInt(static_cast(sizeof(BridgeRtClientData))); fShmNonRtClientControl.writeUInt(static_cast(sizeof(BridgeNonRtClientData))); fShmNonRtClientControl.writeUInt(static_cast(sizeof(BridgeNonRtServerData))); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientInitialSetup); fShmNonRtClientControl.writeUInt(pData->engine->getBufferSize()); fShmNonRtClientControl.writeDouble(pData->engine->getSampleRate()); fShmNonRtClientControl.commitWrite(); if (fShmAudioPool.dataSize != 0) { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool); fShmRtClientControl.writeULong(static_cast(fShmAudioPool.dataSize)); fShmRtClientControl.commitWrite(); } else { // testing dummy message fShmRtClientControl.writeOpcode(kPluginBridgeRtClientNull); fShmRtClientControl.commitWrite(); } fBridgeThread.startThread(); const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH const bool needsCancelableAction = ! pData->engine->isLoadingProject(); if (needsCancelableAction) { pData->engine->setActionCanceled(false); pData->engine->callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, pData->id, 1, 0, 0, 0.0f, "Loading plugin bridge"); } #endif for (;fBridgeThread.isThreadRunning();) { pData->engine->callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (needsEngineIdle) pData->engine->idle(); idle(); if (fInitiated) break; if (pData->engine->isAboutToClose() || pData->engine->wasActionCanceled()) break; carla_msleep(5); } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (needsCancelableAction) { pData->engine->callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, pData->id, 0, 0, 0, 0.0f, "Loading JACK application"); } #endif if (fInitError || ! fInitiated) { fBridgeThread.stopThread(6000); if (! fInitError) pData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n" "(or the plugin crashed on initialization?)"); return false; } if (const size_t dataSize = fInfo.chunk.size()) { #ifdef CARLA_PROPER_CPP11_SUPPORT void* data = fInfo.chunk.data(); #else void* data = &fInfo.chunk.front(); #endif CarlaString dataBase64(CarlaString::asBase64(data, dataSize)); CARLA_SAFE_ASSERT_RETURN(dataBase64.length() > 0, true); String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName()); filePath += CARLA_OS_SEP_STR ".CarlaChunk_"; filePath += fShmAudioPool.getFilenameSuffix(); if (File(filePath).replaceWithText(dataBase64.buffer())) { const uint32_t ulength(static_cast(filePath.length())); const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetChunkDataFile); fShmNonRtClientControl.writeUInt(ulength); fShmNonRtClientControl.writeCustomData(filePath.toRawUTF8(), ulength); fShmNonRtClientControl.commitWrite(); } } return true; } CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginBridge) }; CARLA_BACKEND_END_NAMESPACE // --------------------------------------------------------------------------------------------------------------------- CARLA_BACKEND_START_NAMESPACE CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, PluginType ptype, const char* bridgeBinary) { carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype), bridgeBinary); if (bridgeBinary == nullptr || bridgeBinary[0] == '\0') { init.engine->setLastError("Bridge not possible, bridge-binary not found"); return nullptr; } #ifndef CARLA_OS_WIN // FIXME: somewhere, somehow, we end up with double slashes, wine doesn't like that. if (std::strncmp(bridgeBinary, "//", 2) == 0) ++bridgeBinary; #endif CarlaPluginBridge* const plugin(new CarlaPluginBridge(init.engine, init.id, btype, ptype)); if (! plugin->init(init.filename, init.name, init.label, init.uniqueId, init.options, bridgeBinary)) { delete plugin; return nullptr; } return plugin; } CARLA_BACKEND_END_NAMESPACE // --------------------------------------------------------------------------------------------------------------------- #ifndef BUILD_BRIDGE # include "CarlaBridgeUtils.cpp" #endif // --------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/plugin/CarlaPluginFluidSynth.cpp000066400000000000000000002103731364475620200235210ustar00rootroot00000000000000/* * Carla FluidSynth Plugin * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaPluginInternal.hpp" #include "CarlaEngine.hpp" #ifdef HAVE_FLUIDSYNTH #include "CarlaBackendUtils.hpp" #include "CarlaMathUtils.hpp" #include "water/text/StringArray.h" #include #define FLUID_DEFAULT_POLYPHONY 64 using water::String; using water::StringArray; CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- // Fallback data static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 }; // ------------------------------------------------------------------------------------------------------------------- class CarlaPluginFluidSynth : public CarlaPlugin { public: CarlaPluginFluidSynth(CarlaEngine* const engine, const uint id, const bool use16Outs) : CarlaPlugin(engine, id), kUse16Outs(use16Outs), fSettings(nullptr), fSynth(nullptr), fSynthId(0), fAudio16Buffers(nullptr), fLabel(nullptr) { carla_debug("CarlaPluginFluidSynth::CarlaPluginFluidSynth(%p, %i, %s)", engine, id, bool2str(use16Outs)); carla_zeroFloats(fParamBuffers, FluidSynthParametersMax); carla_fill(fCurMidiProgs, 0, MAX_MIDI_CHANNELS); // create settings fSettings = new_fluid_settings(); CARLA_SAFE_ASSERT_RETURN(fSettings != nullptr,); // define settings fluid_settings_setint(fSettings, "synth.audio-channels", use16Outs ? 16 : 1); fluid_settings_setint(fSettings, "synth.audio-groups", use16Outs ? 16 : 1); fluid_settings_setnum(fSettings, "synth.sample-rate", pData->engine->getSampleRate()); //fluid_settings_setnum(fSettings, "synth.cpu-cores", 2); fluid_settings_setint(fSettings, "synth.parallel-render", 1); fluid_settings_setint(fSettings, "synth.threadsafe-api", 0); // create synth fSynth = new_fluid_synth(fSettings); CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,); initializeFluidDefaultsIfNeeded(); fluid_synth_set_sample_rate(fSynth, (float)pData->engine->getSampleRate()); // set default values fluid_synth_set_reverb_on(fSynth, 1); fluid_synth_set_reverb(fSynth, sFluidDefaults[FluidSynthReverbRoomSize], sFluidDefaults[FluidSynthReverbDamp], sFluidDefaults[FluidSynthReverbWidth], sFluidDefaults[FluidSynthReverbLevel]); fluid_synth_set_chorus_on(fSynth, 1); fluid_synth_set_chorus(fSynth, static_cast(sFluidDefaults[FluidSynthChorusNr] + 0.5f), sFluidDefaults[FluidSynthChorusLevel], sFluidDefaults[FluidSynthChorusSpeedHz], sFluidDefaults[FluidSynthChorusDepthMs], static_cast(sFluidDefaults[FluidSynthChorusType] + 0.5f)); fluid_synth_set_polyphony(fSynth, FLUID_DEFAULT_POLYPHONY); fluid_synth_set_gain(fSynth, 1.0f); for (int i=0; i < MAX_MIDI_CHANNELS; ++i) fluid_synth_set_interp_method(fSynth, i, static_cast(sFluidDefaults[FluidSynthInterpolation] + 0.5f)); } ~CarlaPluginFluidSynth() override { carla_debug("CarlaPluginFluidSynth::~CarlaPluginFluidSynth()"); pData->singleMutex.lock(); pData->masterMutex.lock(); if (pData->client != nullptr && pData->client->isActive()) pData->client->deactivate(); if (pData->active) { deactivate(); pData->active = false; } if (fSynth != nullptr) { delete_fluid_synth(fSynth); fSynth = nullptr; } if (fSettings != nullptr) { delete_fluid_settings(fSettings); fSettings = nullptr; } if (fLabel != nullptr) { delete[] fLabel; fLabel = nullptr; } clearBuffers(); } // ------------------------------------------------------------------- // Information (base) PluginType getType() const noexcept override { return PLUGIN_SF2; } PluginCategory getCategory() const noexcept override { return PLUGIN_CATEGORY_SYNTH; } // ------------------------------------------------------------------- // Information (count) uint32_t getParameterScalePointCount(const uint32_t parameterId) const noexcept override { switch (parameterId) { case FluidSynthChorusType: return 2; case FluidSynthInterpolation: return 4; default: return 0; } } // ------------------------------------------------------------------- // Information (current data) // nothing // ------------------------------------------------------------------- // Information (per-plugin data) uint getOptionsAvailable() const noexcept override { uint options = 0x0; options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; options |= PLUGIN_OPTION_SEND_PITCHBEND; options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; return options; } float getParameterValue(const uint32_t parameterId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f); return fParamBuffers[parameterId]; } float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept override { switch (parameterId) { case FluidSynthChorusType: switch (scalePointId) { case 0: return FLUID_CHORUS_MOD_SINE; case 1: return FLUID_CHORUS_MOD_TRIANGLE; default: return sFluidDefaults[FluidSynthChorusType]; } case FluidSynthInterpolation: switch (scalePointId) { case 0: return FLUID_INTERP_NONE; case 1: return FLUID_INTERP_LINEAR; case 2: return FLUID_INTERP_4THORDER; case 3: return FLUID_INTERP_7THORDER; default: return sFluidDefaults[FluidSynthInterpolation]; } default: return 0.0f; } } bool getLabel(char* const strBuf) const noexcept override { if (fLabel != nullptr) { std::strncpy(strBuf, fLabel, STR_MAX); return true; } return CarlaPlugin::getLabel(strBuf); } bool getMaker(char* const strBuf) const noexcept override { std::strncpy(strBuf, "FluidSynth SF2 engine", STR_MAX); return true; } bool getCopyright(char* const strBuf) const noexcept override { std::strncpy(strBuf, "GNU GPL v2+", STR_MAX); return true; } bool getRealName(char* const strBuf) const noexcept override { return getLabel(strBuf); } bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); switch (parameterId) { case FluidSynthReverbOnOff: std::strncpy(strBuf, "Reverb On/Off", STR_MAX); return true; case FluidSynthReverbRoomSize: std::strncpy(strBuf, "Reverb Room Size", STR_MAX); return true; case FluidSynthReverbDamp: std::strncpy(strBuf, "Reverb Damp", STR_MAX); return true; case FluidSynthReverbLevel: std::strncpy(strBuf, "Reverb Level", STR_MAX); return true; case FluidSynthReverbWidth: std::strncpy(strBuf, "Reverb Width", STR_MAX); return true; case FluidSynthChorusOnOff: std::strncpy(strBuf, "Chorus On/Off", STR_MAX); return true; case FluidSynthChorusNr: std::strncpy(strBuf, "Chorus Voice Count", STR_MAX); return true; case FluidSynthChorusLevel: std::strncpy(strBuf, "Chorus Level", STR_MAX); return true; case FluidSynthChorusSpeedHz: std::strncpy(strBuf, "Chorus Speed", STR_MAX); return true; case FluidSynthChorusDepthMs: std::strncpy(strBuf, "Chorus Depth", STR_MAX); return true; case FluidSynthChorusType: std::strncpy(strBuf, "Chorus Type", STR_MAX); return true; case FluidSynthPolyphony: std::strncpy(strBuf, "Polyphony", STR_MAX); return true; case FluidSynthInterpolation: std::strncpy(strBuf, "Interpolation", STR_MAX); return true; case FluidSynthVoiceCount: std::strncpy(strBuf, "Voice Count", STR_MAX); return true; } return CarlaPlugin::getParameterName(parameterId, strBuf); } bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); switch (parameterId) { case FluidSynthChorusSpeedHz: std::strncpy(strBuf, "Hz", STR_MAX); return true; case FluidSynthChorusDepthMs: std::strncpy(strBuf, "ms", STR_MAX); return true; } return CarlaPlugin::getParameterUnit(parameterId, strBuf); } bool getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); CARLA_SAFE_ASSERT_RETURN(scalePointId < getParameterScalePointCount(parameterId), false); switch (parameterId) { case FluidSynthChorusType: switch (scalePointId) { case 0: std::strncpy(strBuf, "Sine wave", STR_MAX); return true; case 1: std::strncpy(strBuf, "Triangle wave", STR_MAX); return true; } break; case FluidSynthInterpolation: switch (scalePointId) { case 0: std::strncpy(strBuf, "None", STR_MAX); return true; case 1: std::strncpy(strBuf, "Straight-line", STR_MAX); return true; case 2: std::strncpy(strBuf, "Fourth-order", STR_MAX); return true; case 3: std::strncpy(strBuf, "Seventh-order", STR_MAX); return true; } break; } return CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf); } // ------------------------------------------------------------------- // Set data (state) void prepareForSave() override { char strBuf[STR_MAX+1]; std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i", fCurMidiProgs[0], fCurMidiProgs[1], fCurMidiProgs[2], fCurMidiProgs[3], fCurMidiProgs[4], fCurMidiProgs[5], fCurMidiProgs[6], fCurMidiProgs[7], fCurMidiProgs[8], fCurMidiProgs[9], fCurMidiProgs[10], fCurMidiProgs[11], fCurMidiProgs[12], fCurMidiProgs[13], fCurMidiProgs[14], fCurMidiProgs[15]); CarlaPlugin::setCustomData(CUSTOM_DATA_TYPE_STRING, "midiPrograms", strBuf, false); } // ------------------------------------------------------------------- // Set data (internal stuff) void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept override { if (channel >= 0 && channel < MAX_MIDI_CHANNELS) pData->midiprog.current = fCurMidiProgs[channel]; CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback); } // ------------------------------------------------------------------- // Set data (plugin-specific stuff) void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); float fixedValue; { const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); fixedValue = setParameterValueInFluidSynth(parameterId, value); } CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback); } void setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept override { const float fixedValue = setParameterValueInFluidSynth(parameterId, value); CarlaPlugin::setParameterValueRT(parameterId, fixedValue, sendCallbackLater); } float setParameterValueInFluidSynth(const uint32_t parameterId, const float value) noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, value); const float fixedValue(pData->param.getFixedValue(parameterId, value)); fParamBuffers[parameterId] = fixedValue; switch (parameterId) { case FluidSynthReverbOnOff: try { fluid_synth_set_reverb_on(fSynth, (fixedValue > 0.5f) ? 1 : 0); } CARLA_SAFE_EXCEPTION("fluid_synth_set_reverb_on") break; case FluidSynthReverbRoomSize: case FluidSynthReverbDamp: case FluidSynthReverbLevel: case FluidSynthReverbWidth: try { fluid_synth_set_reverb(fSynth, fParamBuffers[FluidSynthReverbRoomSize], fParamBuffers[FluidSynthReverbDamp], fParamBuffers[FluidSynthReverbWidth], fParamBuffers[FluidSynthReverbLevel]); } CARLA_SAFE_EXCEPTION("fluid_synth_set_reverb") break; case FluidSynthChorusOnOff: try { fluid_synth_set_chorus_on(fSynth, (value > 0.5f) ? 1 : 0); } CARLA_SAFE_EXCEPTION("fluid_synth_set_chorus_on") break; case FluidSynthChorusNr: case FluidSynthChorusLevel: case FluidSynthChorusSpeedHz: case FluidSynthChorusDepthMs: case FluidSynthChorusType: try { fluid_synth_set_chorus(fSynth, (int)fParamBuffers[FluidSynthChorusNr], fParamBuffers[FluidSynthChorusLevel], fParamBuffers[FluidSynthChorusSpeedHz], fParamBuffers[FluidSynthChorusDepthMs], (int)fParamBuffers[FluidSynthChorusType]); } CARLA_SAFE_EXCEPTION("fluid_synth_set_chorus") break; case FluidSynthPolyphony: try { fluid_synth_set_polyphony(fSynth, (int)value); } CARLA_SAFE_EXCEPTION("fluid_synth_set_polyphony") break; case FluidSynthInterpolation: for (int i=0; i < MAX_MIDI_CHANNELS; ++i) { try { fluid_synth_set_interp_method(fSynth, i, (int)value); } CARLA_SAFE_EXCEPTION_BREAK("fluid_synth_set_interp_method") } break; default: break; } return fixedValue; } void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override { CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,); CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr && value[0] != '\0',); carla_debug("CarlaPluginFluidSynth::setCustomData(%s, \"%s\", \"%s\", %s)", type, key, value, bool2str(sendGui)); if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0) return CarlaPlugin::setCustomData(type, key, value, sendGui); if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0) return carla_stderr2("CarlaPluginFluidSynth::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui)); if (std::strcmp(key, "midiPrograms") != 0) return carla_stderr2("CarlaPluginFluidSynth::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui)); StringArray midiProgramList(StringArray::fromTokens(value, ":", "")); if (midiProgramList.size() == MAX_MIDI_CHANNELS) { uint8_t channel = 0; for (String *it=midiProgramList.begin(), *end=midiProgramList.end(); it != end; ++it) { const int index(it->getIntValue()); if (index >= 0 && index < static_cast(pData->midiprog.count)) { const uint32_t bank = pData->midiprog.data[index].bank; const uint32_t program = pData->midiprog.data[index].program; fluid_synth_program_select(fSynth, channel, fSynthId, bank, program); fCurMidiProgs[channel] = index; if (pData->ctrlChannel == static_cast(channel)) { pData->midiprog.current = index; pData->engine->callback(true, true, ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED, pData->id, index, 0, 0, 0.0f, nullptr); } } ++channel; } CARLA_SAFE_ASSERT(channel == MAX_MIDI_CHANNELS); } CarlaPlugin::setCustomData(type, key, value, sendGui); } void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override { CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,); CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->midiprog.count),); CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,); if (index >= 0 && pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) { const uint32_t bank = pData->midiprog.data[index].bank; const uint32_t program = pData->midiprog.data[index].program; const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); try { fluid_synth_program_select(fSynth, pData->ctrlChannel, fSynthId, bank, program); } CARLA_SAFE_EXCEPTION("fluid_synth_program_select") fCurMidiProgs[pData->ctrlChannel] = index; } CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit); } // FIXME: this is never used void setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,); CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,); if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) { const uint32_t bank = pData->midiprog.data[uindex].bank; const uint32_t program = pData->midiprog.data[uindex].program; try { fluid_synth_program_select(fSynth, pData->ctrlChannel, fSynthId, bank, program); } CARLA_SAFE_EXCEPTION("fluid_synth_program_select") fCurMidiProgs[pData->ctrlChannel] = static_cast(uindex); } CarlaPlugin::setMidiProgramRT(uindex, sendCallbackLater); } // ------------------------------------------------------------------- // Set ui stuff // nothing // ------------------------------------------------------------------- // Plugin state void reload() override { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,); carla_debug("CarlaPluginFluidSynth::reload() - start"); const EngineProcessMode processMode(pData->engine->getProccessMode()); // Safely disable plugin for reload const ScopedDisabler sd(this); if (pData->active) deactivate(); clearBuffers(); uint32_t aOuts, params; aOuts = kUse16Outs ? 32 : 2; params = FluidSynthParametersMax; pData->audioOut.createNew(aOuts); pData->param.createNew(params, false); const uint portNameSize(pData->engine->getMaxPortNameSize()); CarlaString portName; // --------------------------------------- // Audio Outputs if (kUse16Outs) { for (uint32_t i=0; i < 32; ++i) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "out-"; if ((i+2)/2 < 9) portName += "0"; portName += CarlaString((i+2)/2); if (i % 2 == 0) portName += "L"; else portName += "R"; portName.truncate(portNameSize); pData->audioOut.ports[i].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, i); pData->audioOut.ports[i].rindex = i; } fAudio16Buffers = new float*[aOuts]; for (uint32_t i=0; i < aOuts; ++i) fAudio16Buffers[i] = nullptr; } else { // out-left portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "out-left"; portName.truncate(portNameSize); pData->audioOut.ports[0].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 0); pData->audioOut.ports[0].rindex = 0; // out-right portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "out-right"; portName.truncate(portNameSize); pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 1); pData->audioOut.ports[1].rindex = 1; } // --------------------------------------- // Event Input { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-in"; portName.truncate(portNameSize); pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0); } // --------------------------------------- // Event Output { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-out"; portName.truncate(portNameSize); pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0); } // --------------------------------------- // Parameters { int j; // ---------------------- j = FluidSynthReverbOnOff; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/ | PARAMETER_IS_BOOLEAN; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = 0.0f; pData->param.ranges[j].max = 1.0f; pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 1.0f; pData->param.ranges[j].stepSmall = 1.0f; pData->param.ranges[j].stepLarge = 1.0f; // ---------------------- j = FluidSynthReverbRoomSize; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = 0.0f; pData->param.ranges[j].max = 1.2f; pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 0.01f; pData->param.ranges[j].stepSmall = 0.0001f; pData->param.ranges[j].stepLarge = 0.1f; // ---------------------- j = FluidSynthReverbDamp; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = 0.0f; pData->param.ranges[j].max = 1.0f; pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 0.01f; pData->param.ranges[j].stepSmall = 0.0001f; pData->param.ranges[j].stepLarge = 0.1f; // ---------------------- j = FluidSynthReverbLevel; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.data[j].mappedControlIndex = MIDI_CONTROL_REVERB_SEND_LEVEL; pData->param.ranges[j].min = 0.0f; pData->param.ranges[j].max = 1.0f; pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 0.01f; pData->param.ranges[j].stepSmall = 0.0001f; pData->param.ranges[j].stepLarge = 0.1f; // ---------------------- j = FluidSynthReverbWidth; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = 0.0f; pData->param.ranges[j].max = 10.0f; // should be 100, but that sounds too much pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 0.01f; pData->param.ranges[j].stepSmall = 0.0001f; pData->param.ranges[j].stepLarge = 0.1f; // ---------------------- j = FluidSynthChorusOnOff; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_BOOLEAN; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = 0.0f; pData->param.ranges[j].max = 1.0f; pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 1.0f; pData->param.ranges[j].stepSmall = 1.0f; pData->param.ranges[j].stepLarge = 1.0f; // ---------------------- j = FluidSynthChorusNr; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = 0.0f; pData->param.ranges[j].max = 99.0f; pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 1.0f; pData->param.ranges[j].stepSmall = 1.0f; pData->param.ranges[j].stepLarge = 10.0f; // ---------------------- j = FluidSynthChorusLevel; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = 0.0f; pData->param.ranges[j].max = 10.0f; pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 0.01f; pData->param.ranges[j].stepSmall = 0.0001f; pData->param.ranges[j].stepLarge = 0.1f; // ---------------------- j = FluidSynthChorusSpeedHz; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = 0.29f; pData->param.ranges[j].max = 5.0f; pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 0.01f; pData->param.ranges[j].stepSmall = 0.0001f; pData->param.ranges[j].stepLarge = 0.1f; // ---------------------- j = FluidSynthChorusDepthMs; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = 0.0f; pData->param.ranges[j].max = float(2048.0 * 1000.0 / pData->engine->getSampleRate()); // FIXME? pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 0.01f; pData->param.ranges[j].stepSmall = 0.0001f; pData->param.ranges[j].stepLarge = 0.1f; // ---------------------- j = FluidSynthChorusType; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER | PARAMETER_USES_SCALEPOINTS; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = FLUID_CHORUS_MOD_SINE; pData->param.ranges[j].max = FLUID_CHORUS_MOD_TRIANGLE; pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 1.0f; pData->param.ranges[j].stepSmall = 1.0f; pData->param.ranges[j].stepLarge = 1.0f; // ---------------------- j = FluidSynthPolyphony; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = 1.0f; pData->param.ranges[j].max = 512.0f; // max theoric is 65535 pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 1.0f; pData->param.ranges[j].stepSmall = 1.0f; pData->param.ranges[j].stepLarge = 10.0f; // ---------------------- j = FluidSynthInterpolation; pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER | PARAMETER_USES_SCALEPOINTS; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = FLUID_INTERP_NONE; pData->param.ranges[j].max = FLUID_INTERP_HIGHEST; pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 1.0f; pData->param.ranges[j].stepSmall = 1.0f; pData->param.ranges[j].stepLarge = 1.0f; // ---------------------- j = FluidSynthVoiceCount; pData->param.data[j].type = PARAMETER_OUTPUT; pData->param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE | PARAMETER_IS_INTEGER; pData->param.data[j].index = j; pData->param.data[j].rindex = j; pData->param.ranges[j].min = 0.0f; pData->param.ranges[j].max = 65535.0f; pData->param.ranges[j].def = sFluidDefaults[j]; pData->param.ranges[j].step = 1.0f; pData->param.ranges[j].stepSmall = 1.0f; pData->param.ranges[j].stepLarge = 1.0f; for (j=0; jparam.ranges[j].def; } // --------------------------------------- // plugin hints pData->hints = 0x0; pData->hints |= PLUGIN_IS_SYNTH; pData->hints |= PLUGIN_CAN_VOLUME; pData->hints |= PLUGIN_USES_MULTI_PROGS; if (! kUse16Outs) pData->hints |= PLUGIN_CAN_BALANCE; // extra plugin hints pData->extraHints = 0x0; pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN; bufferSizeChanged(pData->engine->getBufferSize()); reloadPrograms(true); if (pData->active) activate(); carla_debug("CarlaPluginFluidSynth::reload() - end"); } void reloadPrograms(const bool doInit) override { carla_debug("CarlaPluginFluidSynth::reloadPrograms(%s)", bool2str(doInit)); // save drum info in case we have one program for it bool hasDrums = false; uint32_t drumIndex, drumProg; drumIndex = drumProg = 0; // Delete old programs pData->midiprog.clear(); // Query new programs uint32_t count = 0; if (fluid_sfont_t* const f_sfont = fluid_synth_get_sfont_by_id(fSynth, fSynthId)) { #if FLUIDSYNTH_VERSION_MAJOR < 2 fluid_preset_t f_preset; // initial check to know how many midi-programs we have f_sfont->iteration_start(f_sfont); for (; f_sfont->iteration_next(f_sfont, &f_preset);) ++count; // sound kits must always have at least 1 midi-program CARLA_SAFE_ASSERT_RETURN(count > 0,); pData->midiprog.createNew(count); // Update data int tmp; uint32_t i = 0; f_sfont->iteration_start(f_sfont); for (; f_sfont->iteration_next(f_sfont, &f_preset);) { CARLA_SAFE_ASSERT_BREAK(i < count); tmp = f_preset.get_banknum(&f_preset); pData->midiprog.data[i].bank = (tmp >= 0) ? static_cast(tmp) : 0; tmp = f_preset.get_num(&f_preset); pData->midiprog.data[i].program = (tmp >= 0) ? static_cast(tmp) : 0; pData->midiprog.data[i].name = carla_strdup(f_preset.get_name(&f_preset)); #else fluid_preset_t* f_preset; // initial check to know how many midi-programs we have fluid_sfont_iteration_start(f_sfont); for (; fluid_sfont_iteration_next(f_sfont);) ++count; // sound kits must always have at least 1 midi-program CARLA_SAFE_ASSERT_RETURN(count > 0,); pData->midiprog.createNew(count); // Update data int tmp; uint32_t i = 0; fluid_sfont_iteration_start(f_sfont); for (; (f_preset = fluid_sfont_iteration_next(f_sfont));) { CARLA_SAFE_ASSERT_BREAK(i < count); tmp = fluid_preset_get_banknum(f_preset); pData->midiprog.data[i].bank = (tmp >= 0) ? static_cast(tmp) : 0; tmp = fluid_preset_get_num(f_preset); pData->midiprog.data[i].program = (tmp >= 0) ? static_cast(tmp) : 0; pData->midiprog.data[i].name = carla_strdup(fluid_preset_get_name(f_preset)); #endif if (pData->midiprog.data[i].bank == 128 && ! hasDrums) { hasDrums = true; drumIndex = i; drumProg = pData->midiprog.data[i].program; } ++i; } } else { // failing means 0 midi-programs, it shouldn't happen! carla_safe_assert("fluid_sfont_t* const f_sfont = fluid_synth_get_sfont_by_id(fSynth, fSynthId)", __FILE__, __LINE__); return; } if (doInit) { fluid_synth_program_reset(fSynth); // select first program, or 128 for ch10 for (int i=0; i < MAX_MIDI_CHANNELS && i != 9; ++i) { fluid_synth_set_channel_type(fSynth, i, CHANNEL_TYPE_MELODIC); fluid_synth_program_select(fSynth, i, fSynthId, pData->midiprog.data[0].bank, pData->midiprog.data[0].program); fCurMidiProgs[i] = 0; } if (hasDrums) { fluid_synth_set_channel_type(fSynth, 9, CHANNEL_TYPE_DRUM); fluid_synth_program_select(fSynth, 9, fSynthId, 128, drumProg); fCurMidiProgs[9] = static_cast(drumIndex); } else { fluid_synth_set_channel_type(fSynth, 9, CHANNEL_TYPE_MELODIC); fluid_synth_program_select(fSynth, 9, fSynthId, pData->midiprog.data[0].bank, pData->midiprog.data[0].program); fCurMidiProgs[9] = 0; } pData->midiprog.current = 0; } else { pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0f, nullptr); } } // ------------------------------------------------------------------- // Plugin processing void process(const float* const* const, float** const audioOut, const float* const*, float**, const uint32_t frames) override { // -------------------------------------------------------------------------------------------------------- // Check if active if (! pData->active) { // disable any output sound for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(audioOut[i], frames); return; } // -------------------------------------------------------------------------------------------------------- // Check if needs reset if (pData->needsReset) { if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { for (int i=0; i < MAX_MIDI_CHANNELS; ++i) { fluid_synth_all_notes_off(fSynth, i); fluid_synth_all_sounds_off(fSynth, i); } } else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) { for (int i=0; i < MAX_MIDI_NOTE; ++i) fluid_synth_noteoff(fSynth, pData->ctrlChannel, i); } pData->needsReset = false; } // -------------------------------------------------------------------------------------------------------- // Event Input and Processing { // ---------------------------------------------------------------------------------------------------- // MIDI Input (External) if (pData->extNotes.mutex.tryLock()) { for (RtLinkedList::Itenerator it = pData->extNotes.data.begin2(); it.valid(); it.next()) { const ExternalMidiNote& note(it.getValue(kExternalMidiNoteFallback)); CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); if (note.velo > 0) fluid_synth_noteon(fSynth, note.channel, note.note, note.velo); else fluid_synth_noteoff(fSynth,note.channel, note.note); } pData->extNotes.data.clear(); pData->extNotes.mutex.unlock(); } // End of MIDI Input (External) // ---------------------------------------------------------------------------------------------------- // Event Input (System) #ifndef BUILD_BRIDGE bool allNotesOffSent = false; #endif uint32_t timeOffset = 0; uint32_t nextBankIds[MAX_MIDI_CHANNELS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0 }; if (pData->midiprog.current >= 0 && pData->midiprog.count > 0 && pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) nextBankIds[pData->ctrlChannel] = pData->midiprog.data[pData->midiprog.current].bank; for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i) { const EngineEvent& event(pData->event.portIn->getEvent(i)); uint32_t eventTime = event.time; CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames); if (eventTime < timeOffset) { carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'", eventTime, timeOffset, pData->name); eventTime = timeOffset; } else if (eventTime > timeOffset) { if (processSingle(audioOut, eventTime - timeOffset, timeOffset)) { timeOffset = eventTime; if (pData->midiprog.current >= 0 && pData->midiprog.count > 0 && pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) nextBankIds[pData->ctrlChannel] = pData->midiprog.data[pData->midiprog.current].bank; } } // Control change switch (event.type) { case kEngineEventTypeNull: break; case kEngineEventTypeControl: { const EngineControlEvent& ctrlEvent = event.ctrl; switch (ctrlEvent.type) { case kEngineControlEventTypeNull: break; case kEngineControlEventTypeParameter: { float value; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // Control backend stuff if (event.channel == pData->ctrlChannel) { if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0) { value = ctrlEvent.value; setDryWetRT(value, true); } if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0) { value = ctrlEvent.value*127.0f/100.0f; setVolumeRT(value, true); } if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0) { float left, right; value = ctrlEvent.value/0.5f - 1.0f; if (value < 0.0f) { left = -1.0f; right = (value*2.0f)+1.0f; } else if (value > 0.0f) { left = (value*2.0f)-1.0f; right = 1.0f; } else { left = -1.0f; right = 1.0f; } setBalanceLeftRT(left, true); setBalanceRightRT(right, true); } } #endif // Control plugin parameters for (uint32_t k=0; k < pData->param.count; ++k) { if (pData->param.data[k].midiChannel != event.channel) continue; if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) continue; if (pData->param.data[k].hints != PARAMETER_INPUT) continue; if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) continue; value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.value); setParameterValueRT(k, value, true); } if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE) { fluid_synth_cc(fSynth, event.channel, ctrlEvent.param, int(ctrlEvent.value*127.0f)); } break; } case kEngineControlEventTypeMidiBank: if (event.channel < MAX_MIDI_CHANNELS && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0) nextBankIds[event.channel] = ctrlEvent.param; break; case kEngineControlEventTypeMidiProgram: if (event.channel < MAX_MIDI_CHANNELS && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0) { const uint32_t bankId(nextBankIds[event.channel]); const uint32_t progId(ctrlEvent.param); // TODO int32_t midiprog.find(bank, prog) for (uint32_t k=0; k < pData->midiprog.count; ++k) { if (pData->midiprog.data[k].bank == bankId && pData->midiprog.data[k].program == progId) { fluid_synth_program_select(fSynth, event.channel, fSynthId, bankId, progId); fCurMidiProgs[event.channel] = static_cast(k); if (event.channel == pData->ctrlChannel) { pData->postponeRtEvent(kPluginPostRtEventMidiProgramChange, true, static_cast(k), 0, 0, 0.0f); } break; } } } break; case kEngineControlEventTypeAllSoundOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) fluid_synth_all_sounds_off(fSynth, event.channel); break; case kEngineControlEventTypeAllNotesOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { #ifndef BUILD_BRIDGE if (event.channel == pData->ctrlChannel && ! allNotesOffSent) { allNotesOffSent = true; postponeRtAllNotesOff(); } #endif fluid_synth_all_notes_off(fSynth, event.channel); } break; } break; } case kEngineEventTypeMidi: { const EngineMidiEvent& midiEvent(event.midi); if (midiEvent.size > EngineMidiEvent::kDataSize) continue; uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); // Fix bad note-off if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0) status = MIDI_STATUS_NOTE_OFF; switch (status) { case MIDI_STATUS_NOTE_OFF: { const uint8_t note = midiEvent.data[1]; fluid_synth_noteoff(fSynth, event.channel, note); pData->postponeRtEvent(kPluginPostRtEventNoteOff, true, event.channel, note, 0, 0.0f); break; } case MIDI_STATUS_NOTE_ON: { const uint8_t note = midiEvent.data[1]; const uint8_t velo = midiEvent.data[2]; fluid_synth_noteon(fSynth, event.channel, note, velo); pData->postponeRtEvent(kPluginPostRtEventNoteOn, true, event.channel, note, velo, 0.0f); break; } case MIDI_STATUS_POLYPHONIC_AFTERTOUCH: if (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) { //const uint8_t note = midiEvent.data[1]; //const uint8_t pressure = midiEvent.data[2]; // not in fluidsynth API } break; case MIDI_STATUS_CONTROL_CHANGE: if (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) { const uint8_t control = midiEvent.data[1]; const uint8_t value = midiEvent.data[2]; fluid_synth_cc(fSynth, event.channel, control, value); } break; case MIDI_STATUS_CHANNEL_PRESSURE: if (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) { const uint8_t pressure = midiEvent.data[1]; fluid_synth_channel_pressure(fSynth, event.channel, pressure);; } break; case MIDI_STATUS_PITCH_WHEEL_CONTROL: if (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) { const uint8_t lsb = midiEvent.data[1]; const uint8_t msb = midiEvent.data[2]; const int value = ((msb << 7) | lsb); fluid_synth_pitch_bend(fSynth, event.channel, value); } break; default: continue; break; } // switch (status) } break; } // switch (event.type) } pData->postRtEvents.trySplice(); if (frames > timeOffset) processSingle(audioOut, frames - timeOffset, timeOffset); } // End of Event Input and Processing #ifndef BUILD_BRIDGE // -------------------------------------------------------------------------------------------------------- // Control Output { uint32_t k = FluidSynthVoiceCount; fParamBuffers[k] = float(fluid_synth_get_active_voice_count(fSynth)); pData->param.ranges[k].fixValue(fParamBuffers[k]); if (pData->param.data[k].mappedControlIndex > 0) { float value(pData->param.ranges[k].getNormalizedValue(fParamBuffers[k])); pData->event.portOut->writeControlEvent(0, pData->param.data[k].midiChannel, kEngineControlEventTypeParameter, static_cast(pData->param.data[k].mappedControlIndex), value); } } // End of Control Output #endif } bool processSingle(float** const outBuffer, const uint32_t frames, const uint32_t timeOffset) { CARLA_SAFE_ASSERT_RETURN(outBuffer != nullptr, false); CARLA_SAFE_ASSERT_RETURN(frames > 0, false); // -------------------------------------------------------------------------------------------------------- // Try lock, silence otherwise #ifndef STOAT_TEST_BUILD if (pData->engine->isOffline()) { pData->singleMutex.lock(); } else #endif if (! pData->singleMutex.tryLock()) { for (uint32_t i=0; i < pData->audioOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) outBuffer[i][k+timeOffset] = 0.0f; } return false; } // -------------------------------------------------------------------------------------------------------- // Fill plugin buffers and Run plugin if (kUse16Outs) { for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(fAudio16Buffers[i], frames); // FIXME use '32' or '16' instead of outs fluid_synth_process(fSynth, static_cast(frames), 0, nullptr, static_cast(pData->audioOut.count), fAudio16Buffers); } else { fluid_synth_write_float(fSynth, static_cast(frames), outBuffer[0] + timeOffset, 0, 1, outBuffer[1] + timeOffset, 0, 1); } #ifndef BUILD_BRIDGE // -------------------------------------------------------------------------------------------------------- // Post-processing (volume and balance) { // note - balance not possible with kUse16Outs, so we can safely skip fAudioOutBuffers const bool doVolume = (pData->hints & PLUGIN_CAN_VOLUME) != 0 && carla_isNotEqual(pData->postProc.volume, 1.0f); const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f)); float oldBufLeft[doBalance ? frames : 1]; for (uint32_t i=0; i < pData->audioOut.count; ++i) { // Balance if (doBalance) { if (i % 2 == 0) carla_copyFloats(oldBufLeft, outBuffer[i]+timeOffset, frames); float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f; float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f; for (uint32_t k=0; k < frames; ++k) { if (i % 2 == 0) { // left outBuffer[i][k+timeOffset] = oldBufLeft[k] * (1.0f - balRangeL); outBuffer[i][k+timeOffset] += outBuffer[i+1][k+timeOffset] * (1.0f - balRangeR); } else { // right outBuffer[i][k+timeOffset] = outBuffer[i][k+timeOffset] * balRangeR; outBuffer[i][k+timeOffset] += oldBufLeft[k] * balRangeL; } } } // Volume if (kUse16Outs) { for (uint32_t k=0; k < frames; ++k) outBuffer[i][k+timeOffset] = fAudio16Buffers[i][k] * pData->postProc.volume; } else if (doVolume) { for (uint32_t k=0; k < frames; ++k) outBuffer[i][k+timeOffset] *= pData->postProc.volume; } } } // End of Post-processing #else if (kUse16Outs) { for (uint32_t i=0; i < pData->audioOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) outBuffer[i][k+timeOffset] = fAudio16Buffers[i][k]; } } #endif // -------------------------------------------------------------------------------------------------------- pData->singleMutex.unlock(); return true; } void bufferSizeChanged(const uint32_t newBufferSize) override { if (! kUse16Outs) return; for (uint32_t i=0; i < pData->audioOut.count; ++i) { if (fAudio16Buffers[i] != nullptr) delete[] fAudio16Buffers[i]; fAudio16Buffers[i] = new float[newBufferSize]; } } void sampleRateChanged(const double newSampleRate) override { CARLA_SAFE_ASSERT_RETURN(fSettings != nullptr,); fluid_settings_setnum(fSettings, "synth.sample-rate", newSampleRate); CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,); fluid_synth_set_sample_rate(fSynth, float(newSampleRate)); } // ------------------------------------------------------------------- // Plugin buffers void clearBuffers() noexcept override { carla_debug("CarlaPluginFluidSynth::clearBuffers() - start"); if (fAudio16Buffers != nullptr) { for (uint32_t i=0; i < pData->audioOut.count; ++i) { if (fAudio16Buffers[i] != nullptr) { delete[] fAudio16Buffers[i]; fAudio16Buffers[i] = nullptr; } } delete[] fAudio16Buffers; fAudio16Buffers = nullptr; } CarlaPlugin::clearBuffers(); carla_debug("CarlaPluginFluidSynth::clearBuffers() - end"); } // ------------------------------------------------------------------- const void* getExtraStuff() const noexcept override { static const char xtrue[] = "true"; static const char xfalse[] = "false"; return kUse16Outs ? xtrue : xfalse; } // ------------------------------------------------------------------- bool init(const char* const filename, const char* const name, const char* const label, const uint options) { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); // --------------------------------------------------------------- // first checks if (pData->client != nullptr) { pData->engine->setLastError("Plugin client is already registered"); return false; } if (fSynth == nullptr) { pData->engine->setLastError("null synth"); return false; } if (filename == nullptr || filename[0] == '\0') { pData->engine->setLastError("null filename"); return false; } if (label == nullptr || label[0] == '\0') { pData->engine->setLastError("null label"); return false; } // --------------------------------------------------------------- // open soundfont const int synthId(fluid_synth_sfload(fSynth, filename, 0)); if (synthId < 0) { pData->engine->setLastError("Failed to load SoundFont file"); return false; } fSynthId = static_cast(synthId); // --------------------------------------------------------------- // get info CarlaString label2(label); if (kUse16Outs && ! label2.endsWith(" (16 outs)")) label2 += " (16 outs)"; fLabel = label2.dup(); pData->filename = carla_strdup(filename); if (name != nullptr && name[0] != '\0') pData->name = pData->engine->getUniquePluginName(name); else pData->name = pData->engine->getUniquePluginName(label); // --------------------------------------------------------------- // register client pData->client = pData->engine->addClient(this); if (pData->client == nullptr || ! pData->client->isOk()) { pData->engine->setLastError("Failed to register plugin client"); return false; } // --------------------------------------------------------------- // set options pData->options = 0x0; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)) pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND)) pData->options |= PLUGIN_OPTION_SEND_PITCHBEND; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF)) pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES)) pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; return true; } private: void initializeFluidDefaultsIfNeeded() { if (sFluidDefaultsStored) return; sFluidDefaultsStored = true; // reverb defaults sFluidDefaults[FluidSynthReverbOnOff] = 1.0f; #if FLUIDSYNTH_VERSION_MAJOR < 2 sFluidDefaults[FluidSynthReverbRoomSize] = FLUID_REVERB_DEFAULT_ROOMSIZE; sFluidDefaults[FluidSynthReverbDamp] = FLUID_REVERB_DEFAULT_DAMP; sFluidDefaults[FluidSynthReverbLevel] = FLUID_REVERB_DEFAULT_LEVEL; sFluidDefaults[FluidSynthReverbWidth] = FLUID_REVERB_DEFAULT_WIDTH; #else double reverbVal; fluid_settings_getnum_default(fSettings, "synth.reverb.room-size", &reverbVal); sFluidDefaults[FluidSynthReverbRoomSize] = reverbVal; fluid_settings_getnum_default(fSettings, "synth.reverb.damp", &reverbVal); sFluidDefaults[FluidSynthReverbDamp] = reverbVal; fluid_settings_getnum_default(fSettings, "synth.reverb.level", &reverbVal); sFluidDefaults[FluidSynthReverbLevel] = reverbVal; fluid_settings_getnum_default(fSettings, "synth.reverb.width", &reverbVal); sFluidDefaults[FluidSynthReverbWidth] = reverbVal; #endif // chorus defaults sFluidDefaults[FluidSynthChorusOnOff] = 1.0f; #if FLUIDSYNTH_VERSION_MAJOR < 2 sFluidDefaults[FluidSynthChorusNr] = FLUID_CHORUS_DEFAULT_N; sFluidDefaults[FluidSynthChorusLevel] = FLUID_CHORUS_DEFAULT_LEVEL; sFluidDefaults[FluidSynthChorusSpeedHz] = FLUID_CHORUS_DEFAULT_SPEED; sFluidDefaults[FluidSynthChorusDepthMs] = FLUID_CHORUS_DEFAULT_DEPTH; sFluidDefaults[FluidSynthChorusType] = FLUID_CHORUS_DEFAULT_TYPE; #else double chorusVal; fluid_settings_getnum_default(fSettings, "synth.chorus.nr", &chorusVal); sFluidDefaults[FluidSynthChorusNr] = chorusVal; fluid_settings_getnum_default(fSettings, "synth.chorus.level", &chorusVal); sFluidDefaults[FluidSynthChorusLevel] = chorusVal; fluid_settings_getnum_default(fSettings, "synth.chorus.speed", &chorusVal); sFluidDefaults[FluidSynthChorusSpeedHz] = chorusVal; fluid_settings_getnum_default(fSettings, "synth.chorus.depth", &chorusVal); sFluidDefaults[FluidSynthChorusDepthMs] = chorusVal; // There is no settings for chorus default type sFluidDefaults[FluidSynthChorusType] = (float)fluid_synth_get_chorus_type(fSynth); #endif // misc. defaults sFluidDefaults[FluidSynthInterpolation] = FLUID_INTERP_DEFAULT; } enum FluidSynthParameters { FluidSynthReverbOnOff = 0, FluidSynthReverbRoomSize = 1, FluidSynthReverbDamp = 2, FluidSynthReverbLevel = 3, FluidSynthReverbWidth = 4, FluidSynthChorusOnOff = 5, FluidSynthChorusNr = 6, FluidSynthChorusLevel = 7, FluidSynthChorusSpeedHz = 8, FluidSynthChorusDepthMs = 9, FluidSynthChorusType = 10, FluidSynthPolyphony = 11, FluidSynthInterpolation = 12, FluidSynthVoiceCount = 13, FluidSynthParametersMax = 14 }; const bool kUse16Outs; fluid_settings_t* fSettings; fluid_synth_t* fSynth; uint fSynthId; float** fAudio16Buffers; float fParamBuffers[FluidSynthParametersMax]; static bool sFluidDefaultsStored; static float sFluidDefaults[FluidSynthParametersMax]; int32_t fCurMidiProgs[MAX_MIDI_CHANNELS]; const char* fLabel; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginFluidSynth) }; bool CarlaPluginFluidSynth::sFluidDefaultsStored = false; float CarlaPluginFluidSynth::sFluidDefaults[FluidSynthParametersMax] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, }; CARLA_BACKEND_END_NAMESPACE #endif // HAVE_FLUIDSYNTH CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- CarlaPlugin* CarlaPlugin::newFluidSynth(const Initializer& init, const bool use16Outs) { carla_debug("CarlaPlugin::newFluidSynth({%p, \"%s\", \"%s\", \"%s\", " P_INT64 "}, %s)", init.engine, init.filename, init.name, init.label, init.uniqueId, bool2str(use16Outs)); #ifdef HAVE_FLUIDSYNTH if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK && use16Outs) { init.engine->setLastError("Carla's rack mode can only work with Stereo modules," "please choose the 2-channel only SoundFont version"); return nullptr; } if (! fluid_is_soundfont(init.filename)) { init.engine->setLastError("Requested file is not a valid SoundFont"); return nullptr; } CarlaPluginFluidSynth* const plugin(new CarlaPluginFluidSynth(init.engine, init.id, use16Outs)); if (! plugin->init(init.filename, init.name, init.label, init.options)) { delete plugin; return nullptr; } return plugin; #else init.engine->setLastError("fluidsynth support not available"); return nullptr; // unused (void)use16Outs; #endif } // ------------------------------------------------------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/plugin/CarlaPluginInternal.cpp000066400000000000000000000556351364475620200232140ustar00rootroot00000000000000/* * Carla Plugin * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaPluginInternal.hpp" #include "CarlaEngine.hpp" #include "CarlaLibCounter.hpp" #include "CarlaMathUtils.hpp" CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------- // Fallback data static const MidiProgramData kMidiProgramDataNull = { 0, 0, nullptr }; static /* */ CustomData kCustomDataFallbackNC = { nullptr, nullptr, nullptr }; // ----------------------------------------------------------------------- // PluginAudioData PluginAudioData::PluginAudioData() noexcept : count(0), ports(nullptr) {} PluginAudioData::~PluginAudioData() noexcept { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT(ports == nullptr); } void PluginAudioData::createNew(const uint32_t newCount) { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT_RETURN(ports == nullptr,); CARLA_SAFE_ASSERT_RETURN(newCount > 0,); ports = new PluginAudioPort[newCount]; carla_zeroStructs(ports, newCount); count = newCount; } void PluginAudioData::clear() noexcept { if (ports != nullptr) { for (uint32_t i=0; i < count; ++i) { if (ports[i].port != nullptr) { delete ports[i].port; ports[i].port = nullptr; } } delete[] ports; ports = nullptr; } count = 0; } void PluginAudioData::initBuffers() const noexcept { for (uint32_t i=0; i < count; ++i) { if (ports[i].port != nullptr) ports[i].port->initBuffer(); } } // ----------------------------------------------------------------------- // PluginCVData PluginCVData::PluginCVData() noexcept : count(0), ports(nullptr) {} PluginCVData::~PluginCVData() noexcept { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT(ports == nullptr); } void PluginCVData::createNew(const uint32_t newCount) { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT_RETURN(ports == nullptr,); CARLA_SAFE_ASSERT_RETURN(newCount > 0,); ports = new PluginCVPort[newCount]; carla_zeroStructs(ports, newCount); count = newCount; } void PluginCVData::clear() noexcept { if (ports != nullptr) { for (uint32_t i=0; i < count; ++i) { if (ports[i].port != nullptr) { delete ports[i].port; ports[i].port = nullptr; } } delete[] ports; ports = nullptr; } count = 0; } void PluginCVData::initBuffers() const noexcept { for (uint32_t i=0; i < count; ++i) { if (ports[i].port != nullptr) ports[i].port->initBuffer(); } } // ----------------------------------------------------------------------- // PluginEventData PluginEventData::PluginEventData() noexcept : portIn(nullptr), portOut(nullptr) #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH , cvSourcePorts(nullptr) #endif { } PluginEventData::~PluginEventData() noexcept { CARLA_SAFE_ASSERT(portIn == nullptr); CARLA_SAFE_ASSERT(portOut == nullptr); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT(cvSourcePorts == nullptr); #endif } void PluginEventData::clear() noexcept { if (portIn != nullptr) { delete portIn; portIn = nullptr; } if (portOut != nullptr) { delete portOut; portOut = nullptr; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (cvSourcePorts != nullptr) { cvSourcePorts->cleanup(); cvSourcePorts = nullptr; } #endif } void PluginEventData::initBuffers() const noexcept { if (portIn != nullptr) portIn->initBuffer(); if (portOut != nullptr) portOut->initBuffer(); } // ----------------------------------------------------------------------- // PluginParameterData PluginParameterData::PluginParameterData() noexcept : count(0), data(nullptr), ranges(nullptr), special(nullptr) {} PluginParameterData::~PluginParameterData() noexcept { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT(data == nullptr); CARLA_SAFE_ASSERT(ranges == nullptr); CARLA_SAFE_ASSERT(special == nullptr); } void PluginParameterData::createNew(const uint32_t newCount, const bool withSpecial) { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT_RETURN(data == nullptr,); CARLA_SAFE_ASSERT_RETURN(ranges == nullptr,); CARLA_SAFE_ASSERT_RETURN(special == nullptr,); CARLA_SAFE_ASSERT_RETURN(newCount > 0,); data = new ParameterData[newCount]; carla_zeroStructs(data, newCount); for (uint32_t i=0; i < newCount; ++i) { data[i].index = PARAMETER_NULL; data[i].rindex = PARAMETER_NULL; data[i].mappedControlIndex = CONTROL_INDEX_NONE; data[i].mappedMinimum = -1.0f; data[i].mappedMaximum = 1.0f; } ranges = new ParameterRanges[newCount]; carla_zeroStructs(ranges, newCount); if (withSpecial) { special = new SpecialParameterType[newCount]; carla_zeroStructs(special, newCount); } count = newCount; } void PluginParameterData::clear() noexcept { if (data != nullptr) { delete[] data; data = nullptr; } if (ranges != nullptr) { delete[] ranges; ranges = nullptr; } if (special != nullptr) { delete[] special; special = nullptr; } count = 0; } float PluginParameterData::getFixedValue(const uint32_t parameterId, float value) const noexcept { CARLA_SAFE_ASSERT_RETURN(parameterId < count, 0.0f); const uint paramHints (data[parameterId].hints); const ParameterRanges& paramRanges(ranges[parameterId]); // if boolean, return either min or max if (paramHints & PARAMETER_IS_BOOLEAN) { const float middlePoint = paramRanges.min + (paramRanges.max-paramRanges.min)/2.0f; return value >= middlePoint ? paramRanges.max : paramRanges.min; } // if integer, round first if (paramHints & PARAMETER_IS_INTEGER) return paramRanges.getFixedValue(std::round(value)); // normal mode return paramRanges.getFixedValue(value); } // copied from ParameterRanges::getUnnormalizedValue static float _getUnnormalizedValue(const float min, const float max, const float value) noexcept { if (value <= 0.0f) return min; if (value >= 1.0f) return max; return value * (max - min) + min; } // copied from ParameterRanges::getUnnormalizedLogValue static float _getUnnormalizedLogValue(const float min, const float max, const float value) noexcept { if (value <= 0.0f) return min; if (value >= 1.0f) return max; float rmin = min; if (std::abs(min) < std::numeric_limits::epsilon()) rmin = 0.00001f; return rmin * std::pow(max/rmin, value); } float PluginParameterData::getFinalUnnormalizedValue(const uint32_t parameterId, float value) const noexcept { float min, max; if (data[parameterId].mappedControlIndex != CONTROL_INDEX_CV && (data[parameterId].hints & PARAMETER_MAPPED_RANGES_SET) != 0x0) { min = data[parameterId].mappedMinimum; max = data[parameterId].mappedMaximum; } else { min = ranges[parameterId].min; max = ranges[parameterId].max; } if (data[parameterId].hints & PARAMETER_IS_BOOLEAN) { value = (value < 0.5f) ? min : max; } else { if (data[parameterId].hints & PARAMETER_IS_LOGARITHMIC) value = _getUnnormalizedLogValue(min, max, value); else value = _getUnnormalizedValue(min, max, value); if (data[parameterId].hints & PARAMETER_IS_INTEGER) value = std::rint(value); } return value; } // ----------------------------------------------------------------------- // PluginProgramData PluginProgramData::PluginProgramData() noexcept : count(0), current(-1), names(nullptr) {} PluginProgramData::~PluginProgramData() noexcept { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT_INT(current == -1, current); CARLA_SAFE_ASSERT(names == nullptr); } void PluginProgramData::createNew(const uint32_t newCount) { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT_INT(current == -1, current); CARLA_SAFE_ASSERT_RETURN(names == nullptr,); CARLA_SAFE_ASSERT_RETURN(newCount > 0,); names = new ProgramName[newCount]; carla_zeroStructs(names, newCount); count = newCount; current = -1; } void PluginProgramData::clear() noexcept { if (names != nullptr) { for (uint32_t i=0; i < count; ++i) { if (names[i] != nullptr) { delete[] names[i]; names[i] = nullptr; } } delete[] names; names = nullptr; } count = 0; current = -1; } // ----------------------------------------------------------------------- // PluginMidiProgramData PluginMidiProgramData::PluginMidiProgramData() noexcept : count(0), current(-1), data(nullptr) {} PluginMidiProgramData::~PluginMidiProgramData() noexcept { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT_INT(current == -1, current); CARLA_SAFE_ASSERT(data == nullptr); } void PluginMidiProgramData::createNew(const uint32_t newCount) { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT_INT(current == -1, current); CARLA_SAFE_ASSERT_RETURN(data == nullptr,); CARLA_SAFE_ASSERT_RETURN(newCount > 0,); data = new MidiProgramData[newCount]; carla_zeroStructs(data, newCount); count = newCount; current = -1; } void PluginMidiProgramData::clear() noexcept { if (data != nullptr) { for (uint32_t i=0; i < count; ++i) { if (data[i].name != nullptr) { delete[] data[i].name; data[i].name = nullptr; } } delete[] data; data = nullptr; } count = 0; current = -1; } const MidiProgramData& PluginMidiProgramData::getCurrent() const noexcept { CARLA_SAFE_ASSERT_RETURN(current >= 0 && current < static_cast(count), kMidiProgramDataNull); return data[current]; } // ----------------------------------------------------------------------- // ProtectedData::ExternalNotes CarlaPlugin::ProtectedData::ExternalNotes::ExternalNotes() noexcept : mutex(), dataPool(32, 152), data(dataPool) {} CarlaPlugin::ProtectedData::ExternalNotes::~ExternalNotes() noexcept { clear(); } void CarlaPlugin::ProtectedData::ExternalNotes::appendNonRT(const ExternalMidiNote& note) noexcept { mutex.lock(); data.append_sleepy(note); mutex.unlock(); } void CarlaPlugin::ProtectedData::ExternalNotes::clear() noexcept { mutex.lock(); data.clear(); mutex.unlock(); } // ----------------------------------------------------------------------- // ProtectedData::Latency CarlaPlugin::ProtectedData::Latency::Latency() noexcept #ifdef BUILD_BRIDGE : frames(0) {} #else : frames(0), channels(0), buffers(nullptr) {} #endif #ifndef BUILD_BRIDGE CarlaPlugin::ProtectedData::Latency::~Latency() noexcept { clearBuffers(); } void CarlaPlugin::ProtectedData::Latency::clearBuffers() noexcept { if (buffers != nullptr) { for (uint32_t i=0; i < channels; ++i) { CARLA_SAFE_ASSERT_CONTINUE(buffers[i] != nullptr); delete[] buffers[i]; buffers[i] = nullptr; } delete[] buffers; buffers = nullptr; } channels = 0; frames = 0; } void CarlaPlugin::ProtectedData::Latency::recreateBuffers(const uint32_t newChannels, const uint32_t newFrames) { CARLA_SAFE_ASSERT_RETURN(channels != newChannels || frames != newFrames,); const bool retrieveOldBuffer = (channels == newChannels && channels > 0 && frames > 0 && newFrames > 0); float** const oldBuffers = buffers; const uint32_t oldFrames = frames; channels = newChannels; frames = newFrames; if (channels > 0 && frames > 0) { buffers = new float*[channels]; for (uint32_t i=0; i < channels; ++i) { buffers[i] = new float[frames]; if (retrieveOldBuffer) { if (oldFrames > frames) { const uint32_t diff = oldFrames - frames; carla_copyFloats(buffers[i], oldBuffers[i] + diff, frames); } else { const uint32_t diff = frames - oldFrames; carla_zeroFloats(buffers[i], diff); carla_copyFloats(buffers[i] + diff, oldBuffers[i], oldFrames); } } else { carla_zeroFloats(buffers[i], frames); } } } else { buffers = nullptr; } // delete old buffer if (oldBuffers != nullptr) { for (uint32_t i=0; i < channels; ++i) { CARLA_SAFE_ASSERT_CONTINUE(oldBuffers[i] != nullptr); delete[] oldBuffers[i]; oldBuffers[i] = nullptr; } delete[] oldBuffers; } } #endif // ----------------------------------------------------------------------- // ProtectedData::PostRtEvents CarlaPlugin::ProtectedData::PostRtEvents::PostRtEvents() noexcept : dataPool(512, 512), data(dataPool), dataPendingRT(dataPool), dataMutex(), dataPendingMutex() {} CarlaPlugin::ProtectedData::PostRtEvents::~PostRtEvents() noexcept { dataMutex.lock(); dataPendingMutex.lock(); data.clear(); dataPendingRT.clear(); dataMutex.unlock(); dataPendingMutex.unlock(); } void CarlaPlugin::ProtectedData::PostRtEvents::appendRT(const PluginPostRtEvent& e) noexcept { CARLA_SAFE_ASSERT_INT2_RETURN(dataPendingMutex.tryLock(), e.type, e.value1,); dataPendingRT.append(e); dataPendingMutex.unlock(); } void CarlaPlugin::ProtectedData::PostRtEvents::trySplice() noexcept { const CarlaMutexTryLocker cmtl(dataPendingMutex); if (cmtl.wasLocked() && dataPendingRT.isNotEmpty() && dataMutex.tryLock()) { dataPendingRT.moveTo(data, true); dataMutex.unlock(); } } // ----------------------------------------------------------------------- // ProtectedData::PostUiEvents CarlaPlugin::ProtectedData::PostUiEvents::PostUiEvents() noexcept : mutex(), data() {} CarlaPlugin::ProtectedData::PostUiEvents::~PostUiEvents() noexcept { clear(); } void CarlaPlugin::ProtectedData::PostUiEvents::append(const PluginPostRtEvent& e) noexcept { mutex.lock(); data.append(e); mutex.unlock(); } void CarlaPlugin::ProtectedData::PostUiEvents::clear() noexcept { mutex.lock(); data.clear(); mutex.unlock(); } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // ----------------------------------------------------------------------- // ProtectedData::PostProc CarlaPlugin::ProtectedData::PostProc::PostProc() noexcept : dryWet(1.0f), volume(1.0f), balanceLeft(-1.0f), balanceRight(1.0f), panning(0.0f) {} #endif // ----------------------------------------------------------------------- CarlaPlugin::ProtectedData::ProtectedData(CarlaEngine* const eng, const uint idx) noexcept : engine(eng), client(nullptr), id(idx), hints(0x0), options(0x0), nodeId(0), active(false), enabled(false), needsReset(false), engineBridged(eng->getType() == kEngineTypeBridge), enginePlugin(eng->getType() == kEngineTypePlugin), lib(nullptr), uiLib(nullptr), ctrlChannel(0), extraHints(0x0), #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH transientTryCounter(0), transientFirstTry(true), #endif name(nullptr), filename(nullptr), iconName(nullptr), audioIn(), audioOut(), cvIn(), cvOut(), event(), param(), prog(), midiprog(), custom(), masterMutex(), singleMutex(), stateSave(), extNotes(), latency(), postRtEvents(), postUiEvents() #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH , postProc() #endif {} CarlaPlugin::ProtectedData::~ProtectedData() noexcept { CARLA_SAFE_ASSERT(! (active && needsReset)); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT(transientTryCounter == 0); #endif { // mutex MUST have been locked before const bool lockMaster(masterMutex.tryLock()); const bool lockSingle(singleMutex.tryLock()); CARLA_SAFE_ASSERT(! lockMaster); CARLA_SAFE_ASSERT(! lockSingle); } if (client != nullptr) { if (client->isActive()) { // must not happen carla_safe_assert("client->isActive()", __FILE__, __LINE__); client->deactivate(); } clearBuffers(); delete client; client = nullptr; } if (name != nullptr) { delete[] name; name = nullptr; } if (filename != nullptr) { delete[] filename; filename = nullptr; } if (iconName != nullptr) { delete[] iconName; iconName = nullptr; } for (LinkedList::Itenerator it = custom.begin2(); it.valid(); it.next()) { CustomData& customData(it.getValue(kCustomDataFallbackNC)); //CARLA_SAFE_ASSERT_CONTINUE(customData.isValid()); if (customData.type != nullptr) { delete[] customData.type; customData.type = nullptr; } else carla_safe_assert("customData.type != nullptr", __FILE__, __LINE__); if (customData.key != nullptr) { delete[] customData.key; customData.key = nullptr; } else carla_safe_assert("customData.key != nullptr", __FILE__, __LINE__); if (customData.value != nullptr) { delete[] customData.value; customData.value = nullptr; } else carla_safe_assert("customData.value != nullptr", __FILE__, __LINE__); } prog.clear(); midiprog.clear(); custom.clear(); // MUST have been locked before masterMutex.unlock(); singleMutex.unlock(); CARLA_SAFE_ASSERT(uiLib == nullptr); if (lib != nullptr) libClose(); } // ----------------------------------------------------------------------- // Buffer functions void CarlaPlugin::ProtectedData::clearBuffers() noexcept { audioIn.clear(); audioOut.clear(); cvIn.clear(); cvOut.clear(); param.clear(); event.clear(); #ifndef BUILD_BRIDGE latency.clearBuffers(); #endif } // ----------------------------------------------------------------------- // Post-poned events void CarlaPlugin::ProtectedData::postponeRtEvent(const PluginPostRtEvent& rtEvent) noexcept { CARLA_SAFE_ASSERT_RETURN(rtEvent.type != kPluginPostRtEventNull,); postRtEvents.appendRT(rtEvent); } void CarlaPlugin::ProtectedData::postponeRtEvent(const PluginPostRtEventType type, const bool sendCallbackLater, const int32_t value1, const int32_t value2, const int32_t value3, const float valuef) noexcept { CARLA_SAFE_ASSERT_RETURN(type != kPluginPostRtEventNull,); PluginPostRtEvent rtEvent = { type, sendCallbackLater, value1, value2, value3, valuef }; postRtEvents.appendRT(rtEvent); } // ----------------------------------------------------------------------- // Library functions static LibCounter sLibCounter; const char* CarlaPlugin::ProtectedData::libError(const char* const fname) noexcept { return lib_error(fname); } bool CarlaPlugin::ProtectedData::libOpen(const char* const fname) noexcept { lib = sLibCounter.open(fname); return (lib != nullptr); } bool CarlaPlugin::ProtectedData::libClose() noexcept { const bool ret = sLibCounter.close(lib); lib = nullptr; return ret; } void CarlaPlugin::ProtectedData::setCanDeleteLib(const bool canDelete) noexcept { sLibCounter.setCanDelete(lib, canDelete); } bool CarlaPlugin::ProtectedData::uiLibOpen(const char* const fname, const bool canDelete) noexcept { uiLib = sLibCounter.open(fname, canDelete); return (uiLib != nullptr); } bool CarlaPlugin::ProtectedData::uiLibClose() noexcept { const bool ret = sLibCounter.close(uiLib); uiLib = nullptr; return ret; } // ----------------------------------------------------------------------- #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH void CarlaPlugin::ProtectedData::tryTransient() noexcept { if (engine->getOptions().frontendWinId != 0) transientTryCounter = 1; } #endif void CarlaPlugin::ProtectedData::updateParameterValues(CarlaPlugin* const plugin, const bool sendCallback, const bool sendOsc, const bool useDefault) noexcept { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback || useDefault,); for (uint32_t i=0; i < param.count; ++i) { const float value(param.ranges[i].getFixedValue(plugin->getParameterValue(i))); if (useDefault) param.ranges[i].def = value; if (useDefault) { engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED, id, static_cast(i), 0, 0, value, nullptr); } engine->callback(sendCallback, sendOsc, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, id, static_cast(i), 0, 0, value, nullptr); } } void CarlaPlugin::ProtectedData::updateDefaultParameterValues(CarlaPlugin* const plugin) noexcept { for (uint32_t i=0; i < param.count; ++i) param.ranges[i].def = param.ranges[i].getFixedValue(plugin->getParameterValue(i)); } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/plugin/CarlaPluginInternal.hpp000066400000000000000000000302071364475620200232050ustar00rootroot00000000000000/* * Carla Plugin * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_PLUGIN_INTERNAL_HPP_INCLUDED #define CARLA_PLUGIN_INTERNAL_HPP_INCLUDED #include "CarlaPlugin.hpp" #include "CarlaJuceUtils.hpp" #include "CarlaLibUtils.hpp" #include "CarlaStateUtils.hpp" #include "CarlaMIDI.h" #include "CarlaMutex.hpp" #include "CarlaString.hpp" #include "RtLinkedList.hpp" CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // Engine helper macro, sets lastError and returns false/NULL #define CARLA_SAFE_ASSERT_RETURN_ERR(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); pData->engine->setLastError(err); return false; } #define CARLA_SAFE_ASSERT_RETURN_ERRN(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); pData->engine->setLastError(err); return nullptr; } #define CARLA_SAFE_EXCEPTION_RETURN_ERR(excptMsg, errMsg) catch(...) { carla_safe_exception(excptMsg, __FILE__, __LINE__); pData->engine->setLastError(errMsg); return false; } #define CARLA_SAFE_EXCEPTION_RETURN_ERRN(excptMsg, errMsg) catch(...) { carla_safe_exception(excptMsg, __FILE__, __LINE__); pData->engine->setLastError(errMsg); return nullptr; } // ----------------------------------------------------------------------- // Maximum pre-allocated events for some plugin types const ushort kPluginMaxMidiEvents = 512; // ----------------------------------------------------------------------- // Extra parameter hints, hidden from backend const uint PARAMETER_MAPPED_RANGES_SET = 0x1000; const uint PARAMETER_IS_STRICT_BOUNDS = 0x2000; const uint PARAMETER_IS_TRIGGER = 0x4000; // ----------------------------------------------------------------------- // Extra plugin hints, hidden from backend const uint PLUGIN_EXTRA_HINT_HAS_MIDI_IN = 0x01; const uint PLUGIN_EXTRA_HINT_HAS_MIDI_OUT = 0x02; // ----------------------------------------------------------------------- // Special parameters enum SpecialParameterType { PARAMETER_SPECIAL_NULL = 0, PARAMETER_SPECIAL_FREEWHEEL = 1, PARAMETER_SPECIAL_LATENCY = 2, PARAMETER_SPECIAL_SAMPLE_RATE = 3, PARAMETER_SPECIAL_TIME = 4 }; // ----------------------------------------------------------------------- /*! * Post-RT event type. * These are events postponned from within the process function, * * During process, we cannot lock, allocate memory or do UI stuff. * Events have to be postponned to be executed later, on a separate thread. * @see PluginPostRtEvent */ enum PluginPostRtEventType { kPluginPostRtEventNull = 0, kPluginPostRtEventDebug, kPluginPostRtEventParameterChange, // param, (unused), (unused), value kPluginPostRtEventProgramChange, // index kPluginPostRtEventMidiProgramChange, // index kPluginPostRtEventNoteOn, // channel, note, velo kPluginPostRtEventNoteOff // channel, note }; /*! * A Post-RT event. * @see PluginPostRtEventType */ struct PluginPostRtEvent { PluginPostRtEventType type; bool sendCallback; int32_t value1; int32_t value2; int32_t value3; float valuef; }; // ----------------------------------------------------------------------- struct ExternalMidiNote { int8_t channel; // invalid if -1 uint8_t note; // 0 to 127 uint8_t velo; // 1 to 127, 0 for note-off }; // ----------------------------------------------------------------------- struct PluginAudioPort { uint32_t rindex; CarlaEngineAudioPort* port; }; struct PluginAudioData { uint32_t count; PluginAudioPort* ports; PluginAudioData() noexcept; ~PluginAudioData() noexcept; void createNew(uint32_t newCount); void clear() noexcept; void initBuffers() const noexcept; CARLA_DECLARE_NON_COPY_STRUCT(PluginAudioData) }; // ----------------------------------------------------------------------- struct PluginCVPort { uint32_t rindex; //uint32_t param; // FIXME is this needed? CarlaEngineCVPort* port; }; struct PluginCVData { uint32_t count; PluginCVPort* ports; PluginCVData() noexcept; ~PluginCVData() noexcept; void createNew(uint32_t newCount); void clear() noexcept; void initBuffers() const noexcept; CARLA_DECLARE_NON_COPY_STRUCT(PluginCVData) }; // ----------------------------------------------------------------------- struct PluginEventData { CarlaEngineEventPort* portIn; CarlaEngineEventPort* portOut; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaEngineCVSourcePorts* cvSourcePorts; #endif PluginEventData() noexcept; ~PluginEventData() noexcept; void clear() noexcept; void initBuffers() const noexcept; CARLA_DECLARE_NON_COPY_STRUCT(PluginEventData) }; // ----------------------------------------------------------------------- struct PluginParameterData { uint32_t count; ParameterData* data; ParameterRanges* ranges; SpecialParameterType* special; PluginParameterData() noexcept; ~PluginParameterData() noexcept; void createNew(uint32_t newCount, bool withSpecial); void clear() noexcept; float getFixedValue(uint32_t parameterId, float value) const noexcept; float getFinalUnnormalizedValue(uint32_t parameterId, float value) const noexcept; CARLA_DECLARE_NON_COPY_STRUCT(PluginParameterData) }; // ----------------------------------------------------------------------- typedef const char* ProgramName; struct PluginProgramData { uint32_t count; int32_t current; ProgramName* names; PluginProgramData() noexcept; ~PluginProgramData() noexcept; void createNew(uint32_t newCount); void clear() noexcept; CARLA_DECLARE_NON_COPY_STRUCT(PluginProgramData) }; // ----------------------------------------------------------------------- struct PluginMidiProgramData { uint32_t count; int32_t current; MidiProgramData* data; PluginMidiProgramData() noexcept; ~PluginMidiProgramData() noexcept; void createNew(uint32_t newCount); void clear() noexcept; const MidiProgramData& getCurrent() const noexcept; CARLA_DECLARE_NON_COPY_STRUCT(PluginMidiProgramData) }; // ----------------------------------------------------------------------- struct CarlaPlugin::ProtectedData { CarlaEngine* const engine; CarlaEngineClient* client; uint id; uint hints; uint options; uint32_t nodeId; bool active; bool enabled; bool needsReset; bool engineBridged; bool enginePlugin; lib_t lib; lib_t uiLib; // misc int8_t ctrlChannel; uint extraHints; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH uint transientTryCounter; bool transientFirstTry; #endif // data 1 const char* name; const char* filename; const char* iconName; // data 2 PluginAudioData audioIn; PluginAudioData audioOut; PluginCVData cvIn; PluginCVData cvOut; PluginEventData event; PluginParameterData param; PluginProgramData prog; PluginMidiProgramData midiprog; LinkedList custom; CarlaMutex masterMutex; // global master lock CarlaMutex singleMutex; // small lock used only in processSingle() CarlaStateSave stateSave; struct ExternalNotes { CarlaMutex mutex; RtLinkedList::Pool dataPool; RtLinkedList data; ExternalNotes() noexcept; ~ExternalNotes() noexcept; void appendNonRT(const ExternalMidiNote& note) noexcept; void clear() noexcept; CARLA_DECLARE_NON_COPY_STRUCT(ExternalNotes) } extNotes; struct Latency { uint32_t frames; #ifndef BUILD_BRIDGE uint32_t channels; float** buffers; #endif Latency() noexcept; #ifndef BUILD_BRIDGE ~Latency() noexcept; void clearBuffers() noexcept; void recreateBuffers(uint32_t newChannels, uint32_t newFrames); #endif CARLA_DECLARE_NON_COPY_STRUCT(Latency) } latency; class PostRtEvents { public: PostRtEvents() noexcept; ~PostRtEvents() noexcept; void appendRT(const PluginPostRtEvent& event) noexcept; void trySplice() noexcept; struct Access { Access(PostRtEvents& e) : data2(e.dataPool) { const CarlaMutexLocker cml(e.dataMutex); if (e.data.isNotEmpty()) e.data.moveTo(data2, true); } ~Access() { data2.clear(); } inline RtLinkedList::Itenerator getDataIterator() const noexcept { return data2.begin2(); } inline std::size_t isEmpty() const noexcept { return data2.isEmpty(); } private: RtLinkedList data2; }; private: RtLinkedList::Pool dataPool; RtLinkedList data, dataPendingRT; CarlaMutex dataMutex; CarlaMutex dataPendingMutex; CARLA_DECLARE_NON_COPY_CLASS(PostRtEvents) } postRtEvents; struct PostUiEvents { CarlaMutex mutex; LinkedList data; PostUiEvents() noexcept; ~PostUiEvents() noexcept; void append(const PluginPostRtEvent& event) noexcept; void clear() noexcept; CARLA_DECLARE_NON_COPY_STRUCT(PostUiEvents) } postUiEvents; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH struct PostProc { float dryWet; float volume; float balanceLeft; float balanceRight; float panning; PostProc() noexcept; CARLA_DECLARE_NON_COPY_STRUCT(PostProc) } postProc; #endif ProtectedData(CarlaEngine* engine, uint idx) noexcept; ~ProtectedData() noexcept; // ------------------------------------------------------------------- // Buffer functions void clearBuffers() noexcept; // ------------------------------------------------------------------- // Post-poned events void postponeRtEvent(const PluginPostRtEvent& rtEvent) noexcept; void postponeRtEvent(PluginPostRtEventType type, bool sendCallbackLater, int32_t value1, int32_t value2, int32_t value3, float valuef) noexcept; // ------------------------------------------------------------------- // Library functions static const char* libError(const char* filename) noexcept; bool libOpen(const char* filename) noexcept; bool libClose() noexcept; void setCanDeleteLib(bool canDelete) noexcept; bool uiLibOpen(const char* filename, bool canDelete) noexcept; bool uiLibClose() noexcept; template Func libSymbol(const char* symbol) const noexcept { return lib_symbol(lib, symbol); } template Func uiLibSymbol(const char* symbol) const noexcept { return lib_symbol(uiLib, symbol); } // ------------------------------------------------------------------- // Misc #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH void tryTransient() noexcept; #endif void updateParameterValues(CarlaPlugin* plugin, bool sendCallback, bool sendOsc, bool useDefault) noexcept; void updateDefaultParameterValues(CarlaPlugin* plugin) noexcept; // ------------------------------------------------------------------- #ifdef CARLA_PROPER_CPP11_SUPPORT ProtectedData() = delete; CARLA_DECLARE_NON_COPY_STRUCT(ProtectedData); #endif CARLA_LEAK_DETECTOR(ProtectedData); }; CARLA_BACKEND_END_NAMESPACE #endif // CARLA_PLUGIN_INTERNAL_HPP_INCLUDED Carla-2.1/source/backend/plugin/CarlaPluginJack.cpp000066400000000000000000002011371364475620200222760ustar00rootroot00000000000000/* * Carla Plugin JACK * Copyright (C) 2016-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaPluginInternal.hpp" #include "CarlaEngine.hpp" #ifdef CARLA_OS_LINUX #include "CarlaLibJackHints.h" #include "CarlaBackendUtils.hpp" #include "CarlaBridgeUtils.hpp" #include "CarlaEngineUtils.hpp" #include "CarlaMathUtils.hpp" #include "CarlaPipeUtils.hpp" #include "CarlaScopeUtils.hpp" #include "CarlaShmUtils.hpp" #include "CarlaThread.hpp" #ifdef HAVE_LIBLO # include "CarlaOscUtils.hpp" #else # warning No liblo support, NSM (session state) will not be available #endif #include "water/files/File.h" #include "water/misc/Time.h" #include "water/text/StringArray.h" #include "water/threads/ChildProcess.h" #include "jackbridge/JackBridge.hpp" #include #include // ------------------------------------------------------------------------------------------------------------------- using water::ChildProcess; using water::File; using water::String; using water::StringArray; using water::Time; CARLA_BACKEND_START_NAMESPACE static size_t safe_rand(const size_t limit) { const int r = std::rand(); CARLA_SAFE_ASSERT_RETURN(r >= 0, 0); return static_cast(r) % limit; } // ------------------------------------------------------------------------------------------------------------------- // Fallback data static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 }; // ------------------------------------------------------------------------------------------------------------------- class CarlaPluginJackThread : public CarlaThread { public: CarlaPluginJackThread(CarlaEngine* const engine, CarlaPlugin* const plugin) noexcept : CarlaThread("CarlaPluginJackThread"), kEngine(engine), kPlugin(plugin), fShmIds(), fSetupLabel(), #ifdef HAVE_LIBLO fOscClientAddress(nullptr), fOscServer(nullptr), fProject(), #endif fProcess() {} void setData(const char* const shmIds, const char* const setupLabel) noexcept { CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && shmIds[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(setupLabel != nullptr && setupLabel[0] != '\0',); CARLA_SAFE_ASSERT(! isThreadRunning()); fShmIds = shmIds; fSetupLabel = setupLabel; } uintptr_t getProcessID() const noexcept { CARLA_SAFE_ASSERT_RETURN(fProcess != nullptr, 0); return (uintptr_t)fProcess->getPID(); } #ifdef HAVE_LIBLO void nsmSave(const char* const setupLabel) { if (fOscClientAddress == nullptr) return; if (fSetupLabel != setupLabel) fSetupLabel = setupLabel; maybeOpenFirstTime(); lo_send_from(fOscClientAddress, fOscServer, LO_TT_IMMEDIATE, "/nsm/client/save", ""); } void nsmShowGui(const bool yesNo) { if (fOscClientAddress == nullptr) return; lo_send_from(fOscClientAddress, fOscServer, LO_TT_IMMEDIATE, yesNo ? "/nsm/client/show_optional_gui" : "/nsm/client/hide_optional_gui", ""); } #endif char* getEnvVarsToExport() { const EngineOptions& options(kEngine->getOptions()); CarlaString binaryDir(options.binaryDir); #ifdef HAVE_LIBLO const int sessionManager = fSetupLabel[4] - '0'; #endif CarlaString ret; ret += "export LD_LIBRARY_PATH=" + binaryDir + "/jack\n"; #ifdef HAVE_X11 ret += "export LD_PRELOAD=" + binaryDir + "/libcarla_interposer-jack-x11.so\n"; #endif #ifdef HAVE_LIBLO if (sessionManager == LIBJACK_SESSION_MANAGER_NSM) { for (int i=50; fOscServer == nullptr && --i>=0;) carla_msleep(100); ret += "export NSM_URL="; ret += lo_server_get_url(fOscServer); ret += "\n"; } #endif if (kPlugin->getHints() & PLUGIN_HAS_CUSTOM_UI) ret += "export CARLA_FRONTEND_WIN_ID=" + CarlaString(options.frontendWinId) + "\n"; ret += "export CARLA_LIBJACK_SETUP=" + fSetupLabel + "\n"; ret += "export CARLA_SHM_IDS=" + fShmIds + "\n"; return ret.releaseBufferPointer(); } protected: #ifdef HAVE_LIBLO static void _osc_error_handler(int num, const char* msg, const char* path) { carla_stderr2("CarlaPluginJackThread::_osc_error_handler(%i, \"%s\", \"%s\")", num, msg, path); } static int _broadcast_handler(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* data) { CARLA_SAFE_ASSERT_RETURN(data != nullptr, 0); carla_stdout("CarlaPluginJackThread::_broadcast_handler(%s, %s, %p, %i)", path, types, argv, argc); return ((CarlaPluginJackThread*)data)->handleBroadcast(path, types, argv, msg); } void maybeOpenFirstTime() { if (fSetupLabel.length() <= 6) return; if (fProject.path.isNotEmpty() || fProject.init(kEngine->getCurrentProjectFilename(), &fSetupLabel[6])) { carla_stdout("Sending open signal %s %s %s", fProject.path.buffer(), fProject.display.buffer(), fProject.clientName.buffer()); lo_send_from(fOscClientAddress, fOscServer, LO_TT_IMMEDIATE, "/nsm/client/open", "sss", fProject.path.buffer(), fProject.display.buffer(), fProject.clientName.buffer()); } } int handleBroadcast(const char* path, const char* types, lo_arg** argv, lo_message msg) { if (std::strcmp(path, "/nsm/server/announce") == 0) { CARLA_SAFE_ASSERT_RETURN(std::strcmp(types, "sssiii") == 0, 0); const lo_address msgAddress(lo_message_get_source(msg)); CARLA_SAFE_ASSERT_RETURN(msgAddress != nullptr, 0); char* const msgURL(lo_address_get_url(msgAddress)); CARLA_SAFE_ASSERT_RETURN(msgURL != nullptr, 0); if (fOscClientAddress != nullptr) lo_address_free(fOscClientAddress); fOscClientAddress = lo_address_new_from_url(msgURL); CARLA_SAFE_ASSERT_RETURN(fOscClientAddress != nullptr, 0); fProject.appName = &argv[0]->s; static const char* const method = "/nsm/server/announce"; static const char* const message = "Howdy, what took you so long?"; static const char* const smName = "Carla"; static const char* const features = ":server-control:optional-gui:"; lo_send_from(fOscClientAddress, fOscServer, LO_TT_IMMEDIATE, "/reply", "ssss", method, message, smName, features); maybeOpenFirstTime(); } else if (std::strcmp(path, "/reply") == 0) { CARLA_SAFE_ASSERT_RETURN(std::strcmp(types, "ss") == 0, 0); const char* const method = &argv[0]->s; const char* const message = &argv[1]->s; carla_stdout("Got reply of '%s' as '%s'", method, message); if (std::strcmp(method, "/nsm/client/open") == 0) { carla_stdout("Sending 'Session is loaded' to %s", fProject.appName.buffer()); lo_send_from(fOscClientAddress, fOscServer, LO_TT_IMMEDIATE, "/nsm/client/session_is_loaded", ""); } } else if (std::strcmp(path, "/nsm/client/gui_is_shown") == 0) { CARLA_SAFE_ASSERT_RETURN(std::strcmp(types, "") == 0, 0); kEngine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, kPlugin->getId(), 1, 0, 0, 0.0f, nullptr); } else if (std::strcmp(path, "/nsm/client/gui_is_hidden") == 0) { CARLA_SAFE_ASSERT_RETURN(std::strcmp(types, "") == 0, 0); kEngine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, kPlugin->getId(), 0, 0, 0, 0.0f, nullptr); } return 0; } #endif void run() { #ifdef HAVE_LIBLO if (fOscClientAddress != nullptr) { lo_address_free(fOscClientAddress); fOscClientAddress = nullptr; } const int sessionManager = fSetupLabel[4] - '0'; if (sessionManager == LIBJACK_SESSION_MANAGER_NSM) { // NSM support fOscServer = lo_server_new_with_proto(nullptr, LO_UDP, _osc_error_handler); CARLA_SAFE_ASSERT_RETURN(fOscServer != nullptr,); lo_server_add_method(fOscServer, nullptr, nullptr, _broadcast_handler, this); } #endif const bool externalProcess = ((fSetupLabel[5] - '0') & LIBJACK_FLAG_EXTERNAL_START) && ! kEngine->isLoadingProject(); if (! externalProcess) { if (fProcess == nullptr) { fProcess = new ChildProcess(); } else if (fProcess->isRunning()) { carla_stderr("CarlaPluginJackThread::run() - already running"); } String name(kPlugin->getName()); String filename(kPlugin->getFilename()); if (name.isEmpty()) name = "(none)"; CARLA_SAFE_ASSERT_RETURN(filename.isNotEmpty(),); StringArray arguments; // binary arguments.addTokens(filename, true); const EngineOptions& options(kEngine->getOptions()); char winIdStr[STR_MAX+1]; std::snprintf(winIdStr, STR_MAX, P_UINTPTR, options.frontendWinId); winIdStr[STR_MAX] = '\0'; CarlaString libjackdir(options.binaryDir); libjackdir += "/jack"; CarlaString ldpreload; #ifdef HAVE_X11 ldpreload = (CarlaString(options.binaryDir) + "/libcarla_interposer-jack-x11.so"); #endif const ScopedEngineEnvironmentLocker _seel(kEngine); const CarlaScopedEnvVar sev2("LD_LIBRARY_PATH", libjackdir.buffer()); const CarlaScopedEnvVar sev1("LD_PRELOAD", ldpreload.isNotEmpty() ? ldpreload.buffer() : nullptr); #ifdef HAVE_LIBLO const CarlaScopedEnvVar sev3("NSM_URL", lo_server_get_url(fOscServer)); #endif if (kPlugin->getHints() & PLUGIN_HAS_CUSTOM_UI) carla_setenv("CARLA_FRONTEND_WIN_ID", winIdStr); else carla_unsetenv("CARLA_FRONTEND_WIN_ID"); carla_setenv("CARLA_LIBJACK_SETUP", fSetupLabel.buffer()); carla_setenv("CARLA_SHM_IDS", fShmIds.buffer()); if (! fProcess->start(arguments)) { carla_stdout("failed!"); fProcess = nullptr; return; } } for (; (externalProcess || fProcess->isRunning()) && ! shouldThreadExit();) { #ifdef HAVE_LIBLO if (sessionManager == LIBJACK_SESSION_MANAGER_NSM) { lo_server_recv_noblock(fOscServer, 50); } else #endif { carla_msleep(50); } } #ifdef HAVE_LIBLO if (sessionManager == LIBJACK_SESSION_MANAGER_NSM) { lo_server_free(fOscServer); fOscServer = nullptr; if (fOscClientAddress != nullptr) { lo_address_free(fOscClientAddress); fOscClientAddress = nullptr; } } #endif if (! externalProcess) { // we only get here if bridge crashed or thread asked to exit if (fProcess->isRunning() && shouldThreadExit()) { fProcess->waitForProcessToFinish(2000); if (fProcess->isRunning()) { carla_stdout("CarlaPluginJackThread::run() - application refused to close, force kill now"); fProcess->kill(); } } else { // forced quit, may have crashed if (fProcess->getExitCode() != 0 /*|| fProcess->exitStatus() == QProcess::CrashExit*/) { carla_stderr("CarlaPluginJackThread::run() - application crashed"); CarlaString errorString("Plugin '" + CarlaString(kPlugin->getName()) + "' has crashed!\n" "Saving now will lose its current settings.\n" "Please remove this plugin, and not rely on it from this point."); kEngine->callback(true, true, ENGINE_CALLBACK_ERROR, kPlugin->getId(), 0, 0, 0, 0.0f, errorString); } } } fProcess = nullptr; } private: CarlaEngine* const kEngine; CarlaPlugin* const kPlugin; CarlaString fShmIds; CarlaString fSetupLabel; #ifdef HAVE_LIBLO lo_address fOscClientAddress; lo_server fOscServer; struct ProjectData { CarlaString appName; CarlaString path; CarlaString display; CarlaString clientName; ProjectData() : appName(), path(), display(), clientName() {} bool init(const char* const engineProjectFilename, const char* const uniqueCodeID) { CARLA_SAFE_ASSERT_RETURN(engineProjectFilename != nullptr && engineProjectFilename[0] != '\0', false); CARLA_SAFE_ASSERT_RETURN(uniqueCodeID != nullptr && uniqueCodeID[0] != '\0', false); CARLA_SAFE_ASSERT_RETURN(appName.isNotEmpty(), false); const File file(File(engineProjectFilename).withFileExtension(uniqueCodeID)); path = file.getFullPathName().toRawUTF8(); display = file.getFileNameWithoutExtension().toRawUTF8(); clientName = appName + "." + uniqueCodeID; return true; } CARLA_DECLARE_NON_COPY_STRUCT(ProjectData) } fProject; #endif CarlaScopedPointer fProcess; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginJackThread) }; // ------------------------------------------------------------------------------------------------------------------- class CarlaPluginJack : public CarlaPlugin { public: CarlaPluginJack(CarlaEngine* const engine, const uint id) : CarlaPlugin(engine, id), fInitiated(false), fInitError(false), fTimedOut(false), fTimedError(false), fProcCanceled(false), fBufferSize(engine->getBufferSize()), fProcWaitTime(0), fSetupHints(0x0), fBridgeThread(engine, this), fShmAudioPool(), fShmRtClientControl(), fShmNonRtClientControl(), fShmNonRtServerControl(), fInfo() { carla_debug("CarlaPluginJack::CarlaPluginJack(%p, %i)", engine, id); pData->hints |= PLUGIN_IS_BRIDGE; } ~CarlaPluginJack() override { carla_debug("CarlaPluginJack::~CarlaPluginJack()"); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // close UI if (pData->hints & PLUGIN_HAS_CUSTOM_UI) pData->transientTryCounter = 0; #endif pData->singleMutex.lock(); pData->masterMutex.lock(); if (pData->client != nullptr && pData->client->isActive()) pData->client->deactivate(); if (pData->active) { deactivate(); pData->active = false; } if (fBridgeThread.isThreadRunning()) { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientQuit); fShmRtClientControl.commitWrite(); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientQuit); fShmNonRtClientControl.commitWrite(); if (! fTimedOut) waitForClient("stopping", 3000); } fBridgeThread.stopThread(3000); fShmNonRtServerControl.clear(); fShmNonRtClientControl.clear(); fShmRtClientControl.clear(); fShmAudioPool.clear(); clearBuffers(); fInfo.chunk.clear(); } // ------------------------------------------------------------------- // Information (base) PluginType getType() const noexcept override { return PLUGIN_JACK; } PluginCategory getCategory() const noexcept override { return PLUGIN_CATEGORY_NONE; } // ------------------------------------------------------------------- // Information (count) uint32_t getMidiInCount() const noexcept override { return fInfo.mIns; } uint32_t getMidiOutCount() const noexcept override { return fInfo.mOuts; } // ------------------------------------------------------------------- // Information (current data) // ------------------------------------------------------------------- // Information (per-plugin data) uint getOptionsAvailable() const noexcept override { return fInfo.optionsAvailable; } bool getLabel(char* const strBuf) const noexcept override { std::strncpy(strBuf, fInfo.setupLabel, STR_MAX); return true; } bool getMaker(char* const) const noexcept override { return false; } bool getCopyright(char* const) const noexcept override { return false; } bool getRealName(char* const strBuf) const noexcept override { // FIXME std::strncpy(strBuf, "Carla's libjack", STR_MAX); return true; } // ------------------------------------------------------------------- // Set data (state) void prepareForSave() noexcept override { #ifdef HAVE_LIBLO if (fInfo.setupLabel.length() == 6) setupUniqueProjectID(); fBridgeThread.nsmSave(fInfo.setupLabel); #endif { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPrepareForSave); fShmNonRtClientControl.commitWrite(); } } // ------------------------------------------------------------------- // Set data (internal stuff) void setOption(const uint option, const bool yesNo, const bool sendCallback) override { { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetOption); fShmNonRtClientControl.writeUInt(option); fShmNonRtClientControl.writeBool(yesNo); fShmNonRtClientControl.commitWrite(); } CarlaPlugin::setOption(option, yesNo, sendCallback); } void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept override { CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetCtrlChannel); fShmNonRtClientControl.writeShort(channel); fShmNonRtClientControl.commitWrite(); } CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback); } // ------------------------------------------------------------------- // Set data (plugin-specific stuff) void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override { CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr,); if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0) return CarlaPlugin::setCustomData(type, key, value, sendGui); if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) == 0 && std::strcmp(key, "__CarlaPingOnOff__") == 0) { #if 0 const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPingOnOff); fShmNonRtClientControl.writeBool(std::strcmp(value, "true") == 0); fShmNonRtClientControl.commitWrite(); #endif return; } CarlaPlugin::setCustomData(type, key, value, sendGui); } // ------------------------------------------------------------------- // Set ui stuff void showCustomUI(const bool yesNo) override { if (yesNo && ! fBridgeThread.isThreadRunning()) { CARLA_SAFE_ASSERT_RETURN(restartBridgeThread(),); } #ifdef HAVE_LIBLO fBridgeThread.nsmShowGui(yesNo); #endif const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(yesNo ? kPluginBridgeNonRtClientShowUI : kPluginBridgeNonRtClientHideUI); fShmNonRtClientControl.commitWrite(); } void idle() override { if (fBridgeThread.isThreadRunning()) { if (fInitiated && fTimedOut && pData->active) setActive(false, true, true); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPing); fShmNonRtClientControl.commitWrite(); } try { handleNonRtData(); } CARLA_SAFE_EXCEPTION("handleNonRtData"); } else if (fInitiated) { fTimedOut = true; fTimedError = true; fInitiated = false; handleProcessStopped(); } else if (fProcCanceled) { handleProcessStopped(); fProcCanceled = false; } CarlaPlugin::idle(); } // ------------------------------------------------------------------- // Plugin state void reload() override { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,); carla_debug("CarlaPluginJack::reload() - start"); const EngineProcessMode processMode(pData->engine->getProccessMode()); // Safely disable plugin for reload const ScopedDisabler sd(this); // cleanup of previous data pData->audioIn.clear(); pData->audioOut.clear(); pData->event.clear(); bool needsCtrlIn, needsCtrlOut; needsCtrlIn = needsCtrlOut = false; if (fInfo.aIns > 0) { pData->audioIn.createNew(fInfo.aIns); } if (fInfo.aOuts > 0) { pData->audioOut.createNew(fInfo.aOuts); needsCtrlIn = true; } if (fInfo.mIns > 0) needsCtrlIn = true; if (fInfo.mOuts > 0) needsCtrlOut = true; const uint portNameSize(pData->engine->getMaxPortNameSize()); CarlaString portName; // Audio Ins for (uint8_t j=0; j < fInfo.aIns; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (fInfo.aIns > 1) { portName += "audio_in_"; portName += CarlaString(j+1); } else { portName += "audio_in"; } portName.truncate(portNameSize); pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j); pData->audioIn.ports[j].rindex = j; } // Audio Outs for (uint8_t j=0; j < fInfo.aOuts; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (fInfo.aOuts > 1) { portName += "audio_out_"; portName += CarlaString(j+1); } else { portName += "audio_out"; } portName.truncate(portNameSize); pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j); pData->audioOut.ports[j].rindex = j; } if (needsCtrlIn) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "event-in"; portName.truncate(portNameSize); pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0); } if (needsCtrlOut) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "event-out"; portName.truncate(portNameSize); pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0); } // extra plugin hints pData->extraHints = 0x0; if (fInfo.mIns > 0) pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN; if (fInfo.mOuts > 0) pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT; bufferSizeChanged(pData->engine->getBufferSize()); reloadPrograms(true); carla_debug("CarlaPluginJack::reload() - end"); } // ------------------------------------------------------------------- // Plugin processing void activate() noexcept override { if (! fBridgeThread.isThreadRunning()) { CARLA_SAFE_ASSERT_RETURN(restartBridgeThread(),); } CARLA_SAFE_ASSERT_RETURN(! fTimedError,); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientActivate); fShmNonRtClientControl.commitWrite(); } fTimedOut = false; try { waitForClient("activate", 2000); } CARLA_SAFE_EXCEPTION("activate - waitForClient"); } void deactivate() noexcept override { if (! fBridgeThread.isThreadRunning()) return; CARLA_SAFE_ASSERT_RETURN(! fTimedError,); { const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientDeactivate); fShmNonRtClientControl.commitWrite(); } fTimedOut = false; try { waitForClient("deactivate", 2000); } CARLA_SAFE_EXCEPTION("deactivate - waitForClient"); } void process(const float* const* const audioIn, float** const audioOut, const float* const*, float**, const uint32_t frames) override { // -------------------------------------------------------------------------------------------------------- // Check if active if (fProcCanceled || fTimedOut || fTimedError || ! pData->active) { // disable any output sound for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(audioOut[i], frames); return; } // -------------------------------------------------------------------------------------------------------- // Check if needs reset if (pData->needsReset) { // TODO pData->needsReset = false; } // -------------------------------------------------------------------------------------------------------- // Event Input if (pData->event.portIn != nullptr) { // ---------------------------------------------------------------------------------------------------- // MIDI Input (External) if (pData->extNotes.mutex.tryLock()) { for (RtLinkedList::Itenerator it = pData->extNotes.data.begin2(); it.valid(); it.next()) { const ExternalMidiNote& note(it.getValue(kExternalMidiNoteFallback)); CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); uint8_t data1, data2, data3; data1 = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); data2 = note.note; data3 = note.velo; fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent); fShmRtClientControl.writeUInt(0); // time fShmRtClientControl.writeByte(0); // port fShmRtClientControl.writeByte(3); // size fShmRtClientControl.writeByte(data1); fShmRtClientControl.writeByte(data2); fShmRtClientControl.writeByte(data3); fShmRtClientControl.commitWrite(); } pData->extNotes.data.clear(); pData->extNotes.mutex.unlock(); } // End of MIDI Input (External) // ---------------------------------------------------------------------------------------------------- // Event Input (System) #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH bool allNotesOffSent = false; #endif for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i) { const EngineEvent& event(pData->event.portIn->getEvent(i)); // Control change switch (event.type) { case kEngineEventTypeNull: break; case kEngineEventTypeControl: { const EngineControlEvent& ctrlEvent = event.ctrl; switch (ctrlEvent.type) { case kEngineControlEventTypeNull: break; case kEngineControlEventTypeParameter: #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // Control backend stuff if (event.channel == pData->ctrlChannel) { float value; if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0) { value = ctrlEvent.value; setDryWetRT(value, true); } if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0) { value = ctrlEvent.value*127.0f/100.0f; setVolumeRT(value, true); } if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0) { float left, right; value = ctrlEvent.value/0.5f - 1.0f; if (value < 0.0f) { left = -1.0f; right = (value*2.0f)+1.0f; } else if (value > 0.0f) { left = (value*2.0f)-1.0f; right = 1.0f; } else { left = -1.0f; right = 1.0f; } setBalanceLeftRT(left, true); setBalanceRightRT(right, true); } } #endif break; case kEngineControlEventTypeMidiBank: if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventMidiBank); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(event.channel); fShmRtClientControl.writeUShort(event.ctrl.param); fShmRtClientControl.commitWrite(); } break; case kEngineControlEventTypeMidiProgram: if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventMidiProgram); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(event.channel); fShmRtClientControl.writeUShort(event.ctrl.param); fShmRtClientControl.commitWrite(); } break; case kEngineControlEventTypeAllSoundOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventAllSoundOff); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(event.channel); fShmRtClientControl.commitWrite(); } break; case kEngineControlEventTypeAllNotesOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (event.channel == pData->ctrlChannel && ! allNotesOffSent) { allNotesOffSent = true; postponeRtAllNotesOff(); } #endif fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventAllNotesOff); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(event.channel); fShmRtClientControl.commitWrite(); } break; } // switch (ctrlEvent.type) break; } // case kEngineEventTypeControl case kEngineEventTypeMidi: { const EngineMidiEvent& midiEvent(event.midi); if (midiEvent.size == 0 || midiEvent.size >= MAX_MIDI_VALUE) continue; const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data); uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData)); if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) continue; if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0) continue; if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0) continue; if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) continue; // Fix bad note-off if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0) status = MIDI_STATUS_NOTE_OFF; fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent); fShmRtClientControl.writeUInt(event.time); fShmRtClientControl.writeByte(midiEvent.port); fShmRtClientControl.writeByte(midiEvent.size); fShmRtClientControl.writeByte(uint8_t(midiData[0] | (event.channel & MIDI_CHANNEL_BIT))); for (uint8_t j=1; j < midiEvent.size; ++j) fShmRtClientControl.writeByte(midiData[j]); fShmRtClientControl.commitWrite(); if (status == MIDI_STATUS_NOTE_ON) { pData->postponeRtEvent(kPluginPostRtEventNoteOn, true, event.channel, midiData[1], midiData[2], 0.0f); } else if (status == MIDI_STATUS_NOTE_OFF) { pData->postponeRtEvent(kPluginPostRtEventNoteOff, true, event.channel, midiData[1], 0, 0.0f); } } break; } } pData->postRtEvents.trySplice(); } // End of Event Input if (! processSingle(audioIn, audioOut, frames)) return; // -------------------------------------------------------------------------------------------------------- // MIDI Output if (pData->event.portOut != nullptr) { uint32_t time; uint8_t port, size; const uint8_t* midiData(fShmRtClientControl.data->midiOut); for (std::size_t read=0; readevent.portOut->writeMidiEvent(time, size, data); read += kBridgeBaseMidiOutHeaderSize + size; } // TODO (void)port; } // End of Control and MIDI Output } bool processSingle(const float* const* const audioIn, float** const audioOut, const uint32_t frames) { CARLA_SAFE_ASSERT_RETURN(! fTimedError, false); CARLA_SAFE_ASSERT_RETURN(frames > 0, false); CARLA_SAFE_ASSERT_RETURN(frames <= fBufferSize, false); if (pData->audioIn.count > 0) { CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false); } if (pData->audioOut.count > 0) { CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false); } // -------------------------------------------------------------------------------------------------------- // Try lock, silence otherwise #ifndef STOAT_TEST_BUILD if (pData->engine->isOffline()) { pData->singleMutex.lock(); } else #endif if (! pData->singleMutex.tryLock()) { for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(audioOut[i], frames); return false; } // -------------------------------------------------------------------------------------------------------- // Reset audio buffers for (uint32_t i=0; i < fInfo.aIns; ++i) carla_copyFloats(fShmAudioPool.data + (i * fBufferSize), audioIn[i], frames); // -------------------------------------------------------------------------------------------------------- // TimeInfo const EngineTimeInfo timeInfo(pData->engine->getTimeInfo()); BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo); bridgeTimeInfo.playing = timeInfo.playing; bridgeTimeInfo.frame = timeInfo.frame; bridgeTimeInfo.usecs = timeInfo.usecs; bridgeTimeInfo.validFlags = timeInfo.bbt.valid ? kPluginBridgeTimeInfoValidBBT : 0x0; if (timeInfo.bbt.valid) { bridgeTimeInfo.bar = timeInfo.bbt.bar; bridgeTimeInfo.beat = timeInfo.bbt.beat; bridgeTimeInfo.tick = timeInfo.bbt.tick; bridgeTimeInfo.beatsPerBar = timeInfo.bbt.beatsPerBar; bridgeTimeInfo.beatType = timeInfo.bbt.beatType; bridgeTimeInfo.ticksPerBeat = timeInfo.bbt.ticksPerBeat; bridgeTimeInfo.beatsPerMinute = timeInfo.bbt.beatsPerMinute; bridgeTimeInfo.barStartTick = timeInfo.bbt.barStartTick; } // -------------------------------------------------------------------------------------------------------- // Run plugin { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientProcess); fShmRtClientControl.writeUInt(frames); fShmRtClientControl.commitWrite(); } waitForClient("process", fProcWaitTime); if (fTimedOut) { pData->singleMutex.unlock(); return false; } if (fShmRtClientControl.data->procFlags) { fInitiated = false; fProcCanceled = true; } for (uint32_t i=0; i < fInfo.aOuts; ++i) carla_copyFloats(audioOut[i], fShmAudioPool.data + ((i + fInfo.aIns) * fBufferSize), frames); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // -------------------------------------------------------------------------------------------------------- // Post-processing (dry/wet, volume and balance) { const bool doVolume = (pData->hints & PLUGIN_CAN_VOLUME) != 0 && carla_isNotEqual(pData->postProc.volume, 1.0f); const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f); const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f)); const bool isMono = (pData->audioIn.count == 1); bool isPair; float bufValue, oldBufLeft[doBalance ? frames : 1]; for (uint32_t i=0; i < pData->audioOut.count; ++i) { // Dry/Wet if (doDryWet) { const uint32_t c = isMono ? 0 : i; for (uint32_t k=0; k < frames; ++k) { bufValue = audioIn[c][k]; audioOut[i][k] = (audioOut[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet)); } } // Balance if (doBalance) { isPair = (i % 2 == 0); if (isPair) { CARLA_ASSERT(i+1 < pData->audioOut.count); carla_copyFloats(oldBufLeft, audioOut[i], frames); } float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f; float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f; for (uint32_t k=0; k < frames; ++k) { if (isPair) { // left audioOut[i][k] = oldBufLeft[k] * (1.0f - balRangeL); audioOut[i][k] += audioOut[i+1][k] * (1.0f - balRangeR); } else { // right audioOut[i][k] = audioOut[i][k] * balRangeR; audioOut[i][k] += oldBufLeft[k] * balRangeL; } } } // Volume (and buffer copy) if (doVolume) { for (uint32_t k=0; k < frames; ++k) audioOut[i][k] *= pData->postProc.volume; } } } // End of Post-processing #endif // -------------------------------------------------------------------------------------------------------- pData->singleMutex.unlock(); return true; } void bufferSizeChanged(const uint32_t newBufferSize) override { fBufferSize = newBufferSize; resizeAudioPool(newBufferSize); { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetBufferSize); fShmRtClientControl.writeUInt(newBufferSize); fShmRtClientControl.commitWrite(); } //fProcWaitTime = newBufferSize*1000/pData->engine->getSampleRate(); fProcWaitTime = 1000; waitForClient("buffersize", 1000); } void sampleRateChanged(const double newSampleRate) override { { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetSampleRate); fShmRtClientControl.writeDouble(newSampleRate); fShmRtClientControl.commitWrite(); } //fProcWaitTime = pData->engine->getBufferSize()*1000/newSampleRate; fProcWaitTime = 1000; waitForClient("samplerate", 1000); } void offlineModeChanged(const bool isOffline) override { { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetOnline); fShmRtClientControl.writeBool(isOffline); fShmRtClientControl.commitWrite(); } waitForClient("offline", 1000); } // ------------------------------------------------------------------- // Post-poned UI Stuff // ------------------------------------------------------------------- void handleNonRtData() { for (; fShmNonRtServerControl.isDataAvailableForReading();) { const PluginBridgeNonRtServerOpcode opcode(fShmNonRtServerControl.readOpcode()); //#ifdef DEBUG if (opcode != kPluginBridgeNonRtServerPong) { carla_debug("CarlaPluginJack::handleNonRtData() - got opcode: %s", PluginBridgeNonRtServerOpcode2str(opcode)); } //#endif switch (opcode) { case kPluginBridgeNonRtServerNull: case kPluginBridgeNonRtServerPong: case kPluginBridgeNonRtServerPluginInfo1: case kPluginBridgeNonRtServerPluginInfo2: case kPluginBridgeNonRtServerAudioCount: case kPluginBridgeNonRtServerMidiCount: case kPluginBridgeNonRtServerCvCount: case kPluginBridgeNonRtServerParameterCount: case kPluginBridgeNonRtServerProgramCount: case kPluginBridgeNonRtServerMidiProgramCount: case kPluginBridgeNonRtServerPortName: case kPluginBridgeNonRtServerParameterData1: case kPluginBridgeNonRtServerParameterData2: case kPluginBridgeNonRtServerParameterRanges: case kPluginBridgeNonRtServerParameterValue: case kPluginBridgeNonRtServerParameterValue2: case kPluginBridgeNonRtServerParameterTouch: case kPluginBridgeNonRtServerDefaultValue: case kPluginBridgeNonRtServerCurrentProgram: case kPluginBridgeNonRtServerCurrentMidiProgram: case kPluginBridgeNonRtServerProgramName: case kPluginBridgeNonRtServerMidiProgramData: case kPluginBridgeNonRtServerSetCustomData: case kPluginBridgeNonRtServerVersion: break; case kPluginBridgeNonRtServerSetChunkDataFile: // uint/size, str[] (filename) if (const uint32_t chunkFilePathSize = fShmNonRtServerControl.readUInt()) { char chunkFilePath[chunkFilePathSize]; fShmNonRtServerControl.readCustomData(chunkFilePath, chunkFilePathSize); } break; case kPluginBridgeNonRtServerSetLatency: case kPluginBridgeNonRtServerSetParameterText: break; case kPluginBridgeNonRtServerReady: fInitiated = true; break; case kPluginBridgeNonRtServerSaved: break; case kPluginBridgeNonRtServerUiClosed: pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); break; case kPluginBridgeNonRtServerError: { // error const uint32_t errorSize(fShmNonRtServerControl.readUInt()); char error[errorSize+1]; carla_zeroChars(error, errorSize+1); fShmNonRtServerControl.readCustomData(error, errorSize); if (fInitiated) { pData->engine->callback(true, true, ENGINE_CALLBACK_ERROR, pData->id, 0, 0, 0, 0.0f, error); // just in case pData->engine->setLastError(error); fInitError = true; } else { pData->engine->setLastError(error); fInitError = true; fInitiated = true; } } break; } } } // ------------------------------------------------------------------- uintptr_t getUiBridgeProcessId() const noexcept override { return fBridgeThread.getProcessID(); } // ------------------------------------------------------------------- bool init(const char* const filename, const char* const name, const char* const label) { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); // --------------------------------------------------------------- // first checks if (pData->client != nullptr) { pData->engine->setLastError("Plugin client is already registered"); return false; } if (filename == nullptr || filename[0] == '\0') { pData->engine->setLastError("null filename"); return false; } if (label == nullptr || label[0] == '\0') { pData->engine->setLastError("null label"); return false; } // --------------------------------------------------------------- // check setup if (std::strlen(label) < 6) { pData->engine->setLastError("invalid application setup received"); return false; } for (int i=4; --i >= 0;) { CARLA_SAFE_ASSERT_RETURN(label[i] >= '0' && label[i] <= '0'+64, false); } for (int i=6; --i >= 4;) { CARLA_SAFE_ASSERT_RETURN(label[i] >= '0' && label[i] < '0'+0x4f, false); } fInfo.aIns = static_cast(label[0] - '0'); fInfo.aOuts = static_cast(label[1] - '0'); fInfo.mIns = static_cast(carla_minPositive(label[2] - '0', 1)); fInfo.mOuts = static_cast(carla_minPositive(label[3] - '0', 1)); fInfo.setupLabel = label; // --------------------------------------------------------------- // set project unique id if (label[6] == '\0') setupUniqueProjectID(); // --------------------------------------------------------------- // set icon pData->iconName = carla_strdup_safe("application"); // --------------------------------------------------------------- // set info pData->filename = carla_strdup(filename); if (name != nullptr && name[0] != '\0') pData->name = pData->engine->getUniquePluginName(name); else pData->name = pData->engine->getUniquePluginName("Jack Application"); std::srand(static_cast(std::time(nullptr))); // --------------------------------------------------------------- // init sem/shm if (! fShmAudioPool.initializeServer()) { carla_stderr("Failed to initialize shared memory audio pool"); return false; } if (! fShmRtClientControl.initializeServer()) { carla_stderr("Failed to initialize RT client control"); fShmAudioPool.clear(); return false; } if (! fShmNonRtClientControl.initializeServer()) { carla_stderr("Failed to initialize Non-RT client control"); fShmRtClientControl.clear(); fShmAudioPool.clear(); return false; } if (! fShmNonRtServerControl.initializeServer()) { carla_stderr("Failed to initialize Non-RT server control"); fShmNonRtClientControl.clear(); fShmRtClientControl.clear(); fShmAudioPool.clear(); return false; } // --------------------------------------------------------------- // setup hints and options fSetupHints = static_cast(label[5] - '0'); // FIXME dryWet broken pData->hints = PLUGIN_IS_BRIDGE | PLUGIN_OPTION_FIXED_BUFFERS; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->hints |= /*PLUGIN_CAN_DRYWET |*/ PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE; #endif //fInfo.optionsAvailable = optionAv; if (fSetupHints & LIBJACK_FLAG_CONTROL_WINDOW) pData->hints |= PLUGIN_HAS_CUSTOM_UI; // --------------------------------------------------------------- // init bridge thread { char shmIdsStr[6*4+1]; carla_zeroChars(shmIdsStr, 6*4+1); std::strncpy(shmIdsStr+6*0, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6); std::strncpy(shmIdsStr+6*1, &fShmRtClientControl.filename[fShmRtClientControl.filename.length()-6], 6); std::strncpy(shmIdsStr+6*2, &fShmNonRtClientControl.filename[fShmNonRtClientControl.filename.length()-6], 6); std::strncpy(shmIdsStr+6*3, &fShmNonRtServerControl.filename[fShmNonRtServerControl.filename.length()-6], 6); fBridgeThread.setData(shmIdsStr, fInfo.setupLabel); } if (! restartBridgeThread()) return false; // --------------------------------------------------------------- // register client if (pData->name == nullptr) pData->name = pData->engine->getUniquePluginName("unknown"); pData->client = pData->engine->addClient(this); if (pData->client == nullptr || ! pData->client->isOk()) { pData->engine->setLastError("Failed to register plugin client"); return false; } return true; } private: bool fInitiated; bool fInitError; bool fTimedOut; bool fTimedError; bool fProcCanceled; uint fBufferSize; uint fProcWaitTime; uint fSetupHints; CarlaPluginJackThread fBridgeThread; BridgeAudioPool fShmAudioPool; BridgeRtClientControl fShmRtClientControl; BridgeNonRtClientControl fShmNonRtClientControl; BridgeNonRtServerControl fShmNonRtServerControl; struct Info { uint8_t aIns, aOuts; uint8_t mIns, mOuts; uint optionsAvailable; CarlaString setupLabel; std::vector chunk; Info() : aIns(0), aOuts(0), mIns(0), mOuts(0), optionsAvailable(0), setupLabel(), chunk() {} CARLA_DECLARE_NON_COPY_STRUCT(Info) } fInfo; void handleProcessStopped() noexcept { const bool wasActive = pData->active; pData->active = false; if (wasActive) { pData->engine->callback(true, true, ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_ACTIVE, 0, 0, 0.0f, nullptr); } if (pData->hints & PLUGIN_HAS_CUSTOM_UI) pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); } void resizeAudioPool(const uint32_t bufferSize) { fShmAudioPool.resize(bufferSize, static_cast(fInfo.aIns+fInfo.aOuts), 0); fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool); fShmRtClientControl.writeULong(static_cast(fShmAudioPool.dataSize)); fShmRtClientControl.commitWrite(); waitForClient("resize-pool", 5000); } void setupUniqueProjectID() { const char* const engineProjectFilename = pData->engine->getCurrentProjectFilename(); carla_stdout("setupUniqueProjectID %s", engineProjectFilename); if (engineProjectFilename == nullptr || engineProjectFilename[0] == '\0') return; const File file(engineProjectFilename); CARLA_SAFE_ASSERT_RETURN(file.existsAsFile(),); CARLA_SAFE_ASSERT_RETURN(file.getFileExtension().isNotEmpty(),); char code[6]; code[5] = '\0'; for (;;) { static const char* const kValidChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789"; static const size_t kValidCharsLen(std::strlen(kValidChars)-1U); code[0] = kValidChars[safe_rand(kValidCharsLen)]; code[1] = kValidChars[safe_rand(kValidCharsLen)]; code[2] = kValidChars[safe_rand(kValidCharsLen)]; code[3] = kValidChars[safe_rand(kValidCharsLen)]; code[4] = kValidChars[safe_rand(kValidCharsLen)]; const File newFile(file.withFileExtension(code)); if (newFile.existsAsFile()) continue; fInfo.setupLabel += code; carla_stdout("new label %s", fInfo.setupLabel.buffer()); break; } } bool restartBridgeThread() { fInitiated = false; fInitError = false; fTimedError = false; // reset memory fProcCanceled = false; fShmRtClientControl.data->procFlags = 0; carla_zeroStruct(fShmRtClientControl.data->timeInfo); carla_zeroBytes(fShmRtClientControl.data->midiOut, kBridgeRtClientDataMidiOutSize); fShmRtClientControl.clearData(); fShmNonRtClientControl.clearData(); fShmNonRtServerControl.clearData(); // initial values fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientVersion); fShmNonRtClientControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT); fShmNonRtClientControl.writeUInt(static_cast(sizeof(BridgeRtClientData))); fShmNonRtClientControl.writeUInt(static_cast(sizeof(BridgeNonRtClientData))); fShmNonRtClientControl.writeUInt(static_cast(sizeof(BridgeNonRtServerData))); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientInitialSetup); fShmNonRtClientControl.writeUInt(pData->engine->getBufferSize()); fShmNonRtClientControl.writeDouble(pData->engine->getSampleRate()); fShmNonRtClientControl.commitWrite(); if (fShmAudioPool.dataSize != 0) { fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool); fShmRtClientControl.writeULong(static_cast(fShmAudioPool.dataSize)); fShmRtClientControl.commitWrite(); } else { // testing dummy message fShmRtClientControl.writeOpcode(kPluginBridgeRtClientNull); fShmRtClientControl.commitWrite(); } fBridgeThread.startThread(); const bool needsCancelableAction = ! pData->engine->isLoadingProject(); const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin; CarlaString actionName; if (needsCancelableAction) { if (fSetupHints & LIBJACK_FLAG_EXTERNAL_START) { const EngineOptions& options(pData->engine->getOptions()); CarlaString binaryDir(options.binaryDir); char* const hwVars = fBridgeThread.getEnvVarsToExport(); actionName = "Waiting for external JACK application start, please use the following environment variables:\n"; actionName += hwVars; delete[] hwVars; } else { actionName = "Loading JACK application"; } pData->engine->setActionCanceled(false); pData->engine->callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, pData->id, 1, 0, 0, 0.0f, actionName.buffer()); } for (;fBridgeThread.isThreadRunning();) { pData->engine->callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (needsEngineIdle) pData->engine->idle(); idle(); if (fInitiated) break; if (pData->engine->isAboutToClose() || pData->engine->wasActionCanceled()) break; carla_msleep(5); } if (needsCancelableAction) { pData->engine->callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, pData->id, 0, 0, 0, 0.0f, actionName.buffer()); } if (fInitError || ! fInitiated) { fBridgeThread.stopThread(6000); if (! fInitError) pData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n" "(or the plugin crashed on initialization?)"); return false; } return true; } void waitForClient(const char* const action, const uint msecs) { CARLA_SAFE_ASSERT_RETURN(! fTimedOut,); CARLA_SAFE_ASSERT_RETURN(! fTimedError,); if (fShmRtClientControl.waitForClient(msecs)) return; fTimedOut = true; carla_stderr2("waitForClient(%s) timed out", action); } CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginJack) }; CARLA_BACKEND_END_NAMESPACE #endif // CARLA_OS_LINUX // ------------------------------------------------------------------------------------------------------------------- CARLA_BACKEND_START_NAMESPACE CarlaPlugin* CarlaPlugin::newJackApp(const Initializer& init) { carla_debug("CarlaPlugin::newJackApp({%p, \"%s\", \"%s\", \"%s\"})", init.engine, init.filename, init.name, init.label); #ifdef CARLA_OS_LINUX CarlaPluginJack* const plugin(new CarlaPluginJack(init.engine, init.id)); if (! plugin->init(init.filename, init.name, init.label)) { delete plugin; return nullptr; } return plugin; #else init.engine->setLastError("JACK Application support not available"); return nullptr; #endif } CARLA_BACKEND_END_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/plugin/CarlaPluginJuce.cpp000066400000000000000000001464741364475620200223300ustar00rootroot00000000000000/* * Carla Juce Plugin * Copyright (C) 2013-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaPluginInternal.hpp" #include "CarlaEngine.hpp" #if defined(USING_JUCE) #include "CarlaBackendUtils.hpp" #include "CarlaMathUtils.hpp" #include "CarlaScopeUtils.hpp" #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wcast-qual" # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wdouble-promotion" # pragma GCC diagnostic ignored "-Weffc++" # pragma GCC diagnostic ignored "-Wfloat-equal" # pragma GCC diagnostic ignored "-Woverloaded-virtual" # pragma GCC diagnostic ignored "-Wsign-conversion" # pragma GCC diagnostic ignored "-Wundef" # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" # if __GNUC__ > 7 # pragma GCC diagnostic ignored "-Wclass-memaccess" # endif #endif #include "AppConfig.h" #include "juce_audio_processors/juce_audio_processors.h" #include "juce_gui_basics/juce_gui_basics.h" #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic pop #endif #include "JucePluginWindow.hpp" namespace juce { extern bool juce_isRunningInWine(); } CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- // Fallback data static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 }; // ------------------------------------------------------------------------------------------------------------------- class CarlaPluginJuce : public CarlaPlugin, private juce::AudioPlayHead, private juce::AudioProcessorListener { public: CarlaPluginJuce(CarlaEngine* const engine, const uint id) : CarlaPlugin(engine, id), fDesc(), fInstance(nullptr), fFormatManager(), fAudioBuffer(), fMidiBuffer(), fPosInfo(), fChunk(), fFormatName(), fWindow() { carla_debug("CarlaPluginJuce::CarlaPluginJuce(%p, %i)", engine, id); fMidiBuffer.ensureSize(2048); fMidiBuffer.clear(); fPosInfo.resetToDefault(); } ~CarlaPluginJuce() override { carla_debug("CarlaPluginJuce::~CarlaPluginJuce()"); // close UI if (pData->hints & PLUGIN_HAS_CUSTOM_UI) showCustomUI(false); pData->singleMutex.lock(); pData->masterMutex.lock(); if (pData->client != nullptr && pData->client->isActive()) pData->client->deactivate(); if (pData->active) { deactivate(); pData->active = false; } if (fInstance != nullptr) { delete fInstance; fInstance = nullptr; } clearBuffers(); } // ------------------------------------------------------------------- // Information (base) PluginType getType() const noexcept override { return getPluginTypeFromString(fDesc.pluginFormatName.toRawUTF8()); } PluginCategory getCategory() const noexcept override { if (fDesc.isInstrument) return PLUGIN_CATEGORY_SYNTH; return getPluginCategoryFromName(fDesc.category.isNotEmpty() ? fDesc.category.toRawUTF8() : fDesc.name.toRawUTF8()); } int64_t getUniqueId() const noexcept override { return fDesc.uid; } // ------------------------------------------------------------------- // Information (count) // nothing // ------------------------------------------------------------------- // Information (current data) std::size_t getChunkData(void** const dataPtr) noexcept override { CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0); CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0); *dataPtr = nullptr; try { fChunk.reset(); fInstance->getStateInformation(fChunk); } CARLA_SAFE_EXCEPTION_RETURN("CarlaPluginJuce::getChunkData", 0); if (const std::size_t size = fChunk.getSize()) { *dataPtr = fChunk.getData(); return size; } return 0; } // ------------------------------------------------------------------- // Information (per-plugin data) uint getOptionsAvailable() const noexcept override { CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr, 0x0); uint options = 0x0; options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; options |= PLUGIN_OPTION_USE_CHUNKS; if (fInstance->getNumPrograms() > 1) options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; if (fInstance->acceptsMidi()) { options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; options |= PLUGIN_OPTION_SEND_PITCHBEND; options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES; } return options; } float getParameterValue(const uint32_t parameterId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f); CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr, 0.0f); return fInstance->getParameter(static_cast(parameterId)); } bool getLabel(char* const strBuf) const noexcept override { if (fDesc.pluginFormatName == "AU" || fDesc.pluginFormatName == "AudioUnit") std::strncpy(strBuf, fDesc.fileOrIdentifier.toRawUTF8(), STR_MAX); else std::strncpy(strBuf, fDesc.name.toRawUTF8(), STR_MAX); return true; } bool getMaker(char* const strBuf) const noexcept override { std::strncpy(strBuf, fDesc.manufacturerName.toRawUTF8(), STR_MAX); return true; } bool getCopyright(char* const strBuf) const noexcept override { return getMaker(strBuf); } bool getRealName(char* const strBuf) const noexcept override { std::strncpy(strBuf, fDesc.descriptiveName.toRawUTF8(), STR_MAX); return true; } bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr, false); std::strncpy(strBuf, fInstance->getParameterName(static_cast(parameterId), STR_MAX).toRawUTF8(), STR_MAX); return true; } bool getParameterText(const uint32_t parameterId, char* const strBuf) noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr, false); std::strncpy(strBuf, fInstance->getParameterText(static_cast(parameterId), STR_MAX).toRawUTF8(), STR_MAX); return true; } bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr, false); std::strncpy(strBuf, fInstance->getParameterLabel(static_cast(parameterId)).toRawUTF8(), STR_MAX); return true; } // ------------------------------------------------------------------- // Set data (state) // nothing // ------------------------------------------------------------------- // Set data (internal stuff) void setName(const char* const newName) override { CarlaPlugin::setName(newName); if (fWindow != nullptr) { juce::String uiName(pData->name); uiName += " (GUI)"; fWindow->setName(uiName); } } // ------------------------------------------------------------------- // Set data (plugin-specific stuff) void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,); const float fixedValue(pData->param.getFixedValue(parameterId, value)); try { fInstance->setParameter(static_cast(parameterId), value); } CARLA_SAFE_EXCEPTION("setParameter"); CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback); } void setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,); const float fixedValue(pData->param.getFixedValue(parameterId, value)); try { fInstance->setParameter(static_cast(parameterId), value); } CARLA_SAFE_EXCEPTION("setParameter(RT)"); CarlaPlugin::setParameterValueRT(parameterId, fixedValue, sendCallbackLater); } void setChunkData(const void* const data, const std::size_t dataSize) override { CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,); CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,); CARLA_SAFE_ASSERT_RETURN(data != nullptr,); CARLA_SAFE_ASSERT_RETURN(dataSize > 0,); if (isJuceSaveFormat(data, dataSize)) { const ScopedSingleProcessLocker spl(this, true); fInstance->setStateInformation(data, static_cast(dataSize)); } else { uint8_t* const dataCompat = (uint8_t*)std::malloc(dataSize + 160); CARLA_SAFE_ASSERT_RETURN(dataCompat != nullptr,); carla_stdout("NOTE: Loading plugin state in Carla JUCE/VST2 compatibility mode"); std::memset(dataCompat, 0, 160); std::memcpy(dataCompat+160, data, dataSize); int32_t* const set = (int32_t*)dataCompat; set[0] = (int32_t)juce::ByteOrder::littleEndianInt("CcnK"); set[2] = (int32_t)juce::ByteOrder::littleEndianInt("FBCh"); set[3] = fxbSwap(1); set[39] = fxbSwap(static_cast(dataSize)); { const ScopedSingleProcessLocker spl(this, true); fInstance->setStateInformation(dataCompat, static_cast(dataSize+160)); } std::free(dataCompat); } pData->updateParameterValues(this, true, true, false); } void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override { CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,); CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->prog.count),); if (index >= 0) { const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); try { fInstance->setCurrentProgram(index); } CARLA_SAFE_EXCEPTION("setCurrentProgram"); } CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback, doingInit); } void setProgramRT(const uint32_t index, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,); CARLA_SAFE_ASSERT_RETURN(index < pData->prog.count,); try { fInstance->setCurrentProgram(static_cast(index)); } CARLA_SAFE_EXCEPTION("setCurrentProgram"); CarlaPlugin::setProgramRT(index, sendCallbackLater); } // ------------------------------------------------------------------- // Set ui stuff void showCustomUI(const bool yesNo) override { CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,); if (yesNo) { if (fWindow == nullptr) { juce::String uiName(pData->name); uiName += " (GUI)"; fWindow = new JucePluginWindow(pData->engine->getOptions().frontendWinId); fWindow->setName(uiName); } if (juce::AudioProcessorEditor* const editor = fInstance->createEditorIfNeeded()) fWindow->show(editor); } else { if (fWindow != nullptr) fWindow->hide(); if (juce::AudioProcessorEditor* const editor = fInstance->getActiveEditor()) delete editor; fWindow = nullptr; } } void uiIdle() override { if (fWindow != nullptr) { if (fWindow->wasClosedByUser()) { showCustomUI(false); pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); } } CarlaPlugin::uiIdle(); } // ------------------------------------------------------------------- // Plugin state void reload() override { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,); carla_debug("CarlaPluginJuce::reload() - start"); const EngineProcessMode processMode(pData->engine->getProccessMode()); // Safely disable plugin for reload const ScopedDisabler sd(this); if (pData->active) deactivate(); clearBuffers(); fInstance->refreshParameterList(); uint32_t aIns, aOuts, mIns, mOuts, params; mIns = mOuts = 0; bool needsCtrlIn, needsCtrlOut; needsCtrlIn = needsCtrlOut = false; aIns = (fInstance->getTotalNumInputChannels() > 0) ? static_cast(fInstance->getTotalNumInputChannels()) : 0; aOuts = (fInstance->getTotalNumOutputChannels() > 0) ? static_cast(fInstance->getTotalNumOutputChannels()) : 0; params = (fInstance->getNumParameters() > 0) ? static_cast(fInstance->getNumParameters()) : 0; if (fInstance->acceptsMidi()) { mIns = 1; needsCtrlIn = true; } if (fInstance->producesMidi()) { mOuts = 1; needsCtrlOut = true; } if (aIns > 0) { pData->audioIn.createNew(aIns); } if (aOuts > 0) { pData->audioOut.createNew(aOuts); needsCtrlIn = true; } if (params > 0) { pData->param.createNew(params, false); needsCtrlIn = true; } const uint portNameSize(pData->engine->getMaxPortNameSize()); CarlaString portName; // Audio Ins for (uint32_t j=0; j < aIns; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (aIns > 1) { portName += "input_"; portName += CarlaString(j+1); } else portName += "input"; portName.truncate(portNameSize); pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j); pData->audioIn.ports[j].rindex = j; } // Audio Outs for (uint32_t j=0; j < aOuts; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (aOuts > 1) { portName += "output_"; portName += CarlaString(j+1); } else portName += "output"; portName.truncate(portNameSize); pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j); pData->audioOut.ports[j].rindex = j; } for (uint32_t j=0; j < params; ++j) { pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].index = static_cast(j); pData->param.data[j].rindex = static_cast(j); float min, max, def, step, stepSmall, stepLarge; // TODO //const int numSteps(fInstance->getParameterNumSteps(static_cast(j))); { min = 0.0f; max = 1.0f; step = 0.001f; stepSmall = 0.0001f; stepLarge = 0.1f; } pData->param.data[j].hints |= PARAMETER_IS_ENABLED; #ifndef BUILD_BRIDGE pData->param.data[j].hints |= PARAMETER_USES_CUSTOM_TEXT; #endif if (fInstance->isParameterAutomatable(static_cast(j))) { pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE; if (fInstance->isMetaParameter(static_cast(j))) pData->param.data[j].hints |= PARAMETER_CAN_BE_CV_CONTROLLED; } // FIXME? def = fInstance->getParameterDefaultValue(static_cast(j)); if (def < min) def = min; else if (def > max) def = max; pData->param.ranges[j].min = min; pData->param.ranges[j].max = max; pData->param.ranges[j].def = def; pData->param.ranges[j].step = step; pData->param.ranges[j].stepSmall = stepSmall; pData->param.ranges[j].stepLarge = stepLarge; } if (needsCtrlIn) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-in"; portName.truncate(portNameSize); pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->event.cvSourcePorts = pData->client->createCVSourcePorts(); #endif } if (needsCtrlOut) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-out"; portName.truncate(portNameSize); pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0); } // plugin hints pData->hints = 0x0; pData->hints |= PLUGIN_NEEDS_FIXED_BUFFERS; if (fDesc.isInstrument) pData->hints |= PLUGIN_IS_SYNTH; if (fInstance->hasEditor()) { pData->hints |= PLUGIN_HAS_CUSTOM_UI; pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD; } if (aOuts > 0 && (aIns == aOuts || aIns == 1)) pData->hints |= PLUGIN_CAN_DRYWET; if (aOuts > 0) pData->hints |= PLUGIN_CAN_VOLUME; if (aOuts >= 2 && aOuts % 2 == 0) pData->hints |= PLUGIN_CAN_BALANCE; // extra plugin hints pData->extraHints = 0x0; if (mIns > 0) pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN; if (mOuts > 0) pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT; fInstance->setPlayConfigDetails(static_cast(aIns), static_cast(aOuts), pData->engine->getSampleRate(), static_cast(pData->engine->getBufferSize())); bufferSizeChanged(pData->engine->getBufferSize()); reloadPrograms(true); if (pData->active) activate(); carla_debug("CarlaPluginJuce::reload() - end"); } void reloadPrograms(const bool doInit) override { carla_debug("CarlaPluginJuce::reloadPrograms(%s)", bool2str(doInit)); const uint32_t oldCount = pData->prog.count; const int32_t current = pData->prog.current; // Delete old programs pData->prog.clear(); // Query new programs const uint32_t newCount = (fInstance->getNumPrograms() > 0) ? static_cast(fInstance->getNumPrograms()) : 0; if (newCount > 0) { pData->prog.createNew(newCount); // Update names for (uint32_t i=0; i < newCount; ++i) pData->prog.names[i] = carla_strdup(fInstance->getProgramName(static_cast(i)).toRawUTF8()); } if (doInit) { if (newCount > 0) setProgram(0, false, false, false, true); } else { // Check if current program is invalid bool programChanged = false; if (newCount == oldCount+1) { // one program added, probably created by user pData->prog.current = static_cast(oldCount); programChanged = true; } else if (current < 0 && newCount > 0) { // programs exist now, but not before pData->prog.current = 0; programChanged = true; } else if (current >= 0 && newCount == 0) { // programs existed before, but not anymore pData->prog.current = -1; programChanged = true; } else if (current >= static_cast(newCount)) { // current program > count pData->prog.current = 0; programChanged = true; } else { // no change pData->prog.current = current; } if (programChanged) { setProgram(pData->prog.current, true, true, true, false); } else { // Program was changed during update, re-set it if (pData->prog.current >= 0) fInstance->setCurrentProgram(pData->prog.current); } pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0f, nullptr); } } // ------------------------------------------------------------------- // Plugin processing void activate() noexcept override { CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,); try { fInstance->prepareToPlay(pData->engine->getSampleRate(), static_cast(pData->engine->getBufferSize())); } catch(...) {} } void deactivate() noexcept override { CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,); try { fInstance->releaseResources(); } catch(...) {} } void process(const float* const* const audioIn, float** const audioOut, const float* const* const cvIn, float**, const uint32_t frames) override { // -------------------------------------------------------------------------------------------------------- // Check if active if (! pData->active) { // disable any output sound for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(audioOut[i], frames); return; } // -------------------------------------------------------------------------------------------------------- // Check if needs reset if (pData->needsReset) { fInstance->reset(); pData->needsReset = false; } // -------------------------------------------------------------------------------------------------------- // Event Input fMidiBuffer.clear(); if (pData->event.portIn != nullptr) { // ---------------------------------------------------------------------------------------------------- // MIDI Input (External) if (pData->extNotes.mutex.tryLock()) { for (RtLinkedList::Itenerator it = pData->extNotes.data.begin2(); it.valid(); it.next()) { const ExternalMidiNote& note(it.getValue(kExternalMidiNoteFallback)); CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); uint8_t midiEvent[3]; midiEvent[0] = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); midiEvent[1] = note.note; midiEvent[2] = note.velo; fMidiBuffer.addEvent(midiEvent, 3, 0); } pData->extNotes.data.clear(); pData->extNotes.mutex.unlock(); } // End of MIDI Input (External) // ---------------------------------------------------------------------------------------------------- // Event Input (System) #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH bool allNotesOffSent = false; if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr) pData->event.cvSourcePorts->initPortBuffers(cvIn, frames, false, pData->event.portIn); #endif for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i) { const EngineEvent& event(pData->event.portIn->getEvent(i)); if (event.time >= frames) continue; switch (event.type) { case kEngineEventTypeNull: break; case kEngineEventTypeControl: { const EngineControlEvent& ctrlEvent(event.ctrl); switch (ctrlEvent.type) { case kEngineControlEventTypeNull: break; case kEngineControlEventTypeParameter: { float value; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // non-midi if (event.channel == kEngineEventNonMidiChannel) { const uint32_t k = ctrlEvent.param; CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count); value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.value); setParameterValueRT(k, value, true); continue; } // Control backend stuff if (event.channel == pData->ctrlChannel) { if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0) { value = ctrlEvent.value; setDryWetRT(value, true); } if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0) { value = ctrlEvent.value*127.0f/100.0f; setVolumeRT(value, true); } if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0) { float left, right; value = ctrlEvent.value/0.5f - 1.0f; if (value < 0.0f) { left = -1.0f; right = (value*2.0f)+1.0f; } else if (value > 0.0f) { left = (value*2.0f)-1.0f; right = 1.0f; } else { left = -1.0f; right = 1.0f; } setBalanceLeftRT(left, true); setBalanceRightRT(right, true); } } #endif // Control plugin parameters uint32_t k; for (k=0; k < pData->param.count; ++k) { if (pData->param.data[k].midiChannel != event.channel) continue; if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) continue; if (pData->param.data[k].type != PARAMETER_INPUT) continue; if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) continue; value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.value); setParameterValueRT(k, value, true); } if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE) { uint8_t midiData[3]; midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); midiData[1] = uint8_t(ctrlEvent.param); midiData[2] = uint8_t(ctrlEvent.value*127.0f); fMidiBuffer.addEvent(midiData, 3, static_cast(event.time)); } break; } // case kEngineControlEventTypeParameter case kEngineControlEventTypeMidiBank: if ((pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) != 0) { uint8_t midiData[3]; midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); midiData[1] = MIDI_CONTROL_BANK_SELECT; midiData[2] = 0; fMidiBuffer.addEvent(midiData, 3, static_cast(event.time)); midiData[1] = MIDI_CONTROL_BANK_SELECT__LSB; midiData[2] = uint8_t(ctrlEvent.value*127.0f); fMidiBuffer.addEvent(midiData, 3, static_cast(event.time)); } break; case kEngineControlEventTypeMidiProgram: if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0) { if (ctrlEvent.param < pData->prog.count) { setProgramRT(ctrlEvent.param, true); } } else if ((pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) != 0) { uint8_t midiData[3]; midiData[0] = uint8_t(MIDI_STATUS_PROGRAM_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); midiData[1] = uint8_t(ctrlEvent.value*127.0f); fMidiBuffer.addEvent(midiData, 2, static_cast(event.time)); } break; case kEngineControlEventTypeAllSoundOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { uint8_t midiData[3]; midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; midiData[2] = 0; fMidiBuffer.addEvent(midiData, 3, static_cast(event.time)); } break; case kEngineControlEventTypeAllNotesOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (event.channel == pData->ctrlChannel && ! allNotesOffSent) { allNotesOffSent = true; postponeRtAllNotesOff(); } #endif uint8_t midiData[3]; midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; midiData[2] = 0; fMidiBuffer.addEvent(midiData, 3, static_cast(event.time)); } break; } // switch (ctrlEvent.type) break; } // case kEngineEventTypeControl case kEngineEventTypeMidi: { const EngineMidiEvent& midiEvent(event.midi); const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data); uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData)); if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) continue; if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0) continue; if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0) continue; if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) continue; // Fix bad note-off if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0) status = MIDI_STATUS_NOTE_OFF; // put back channel in data uint8_t midiData2[midiEvent.size]; midiData2[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT)); std::memcpy(midiData2+1, midiData+1, static_cast(midiEvent.size-1)); fMidiBuffer.addEvent(midiData2, midiEvent.size, static_cast(event.time)); if (status == MIDI_STATUS_NOTE_ON) { pData->postponeRtEvent(kPluginPostRtEventNoteOn, true, event.channel, midiData[1], midiData[2], 0.0f); } else if (status == MIDI_STATUS_NOTE_OFF) { pData->postponeRtEvent(kPluginPostRtEventNoteOff, true, event.channel, midiData[1], 0, 0.0f); } } break; } // switch (event.type) } pData->postRtEvents.trySplice(); } // End of Event Input // -------------------------------------------------------------------------------------------------------- // Set TimeInfo const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo()); fPosInfo.isPlaying = timeInfo.playing; if (timeInfo.bbt.valid) { CARLA_SAFE_ASSERT_INT(timeInfo.bbt.bar > 0, timeInfo.bbt.bar); CARLA_SAFE_ASSERT_INT(timeInfo.bbt.beat > 0, timeInfo.bbt.beat); const double ppqBar = static_cast(timeInfo.bbt.beatsPerBar) * (timeInfo.bbt.bar - 1); const double ppqBeat = static_cast(timeInfo.bbt.beat - 1); const double ppqTick = timeInfo.bbt.tick / timeInfo.bbt.ticksPerBeat; fPosInfo.bpm = timeInfo.bbt.beatsPerMinute; fPosInfo.timeSigNumerator = static_cast(timeInfo.bbt.beatsPerBar); fPosInfo.timeSigDenominator = static_cast(timeInfo.bbt.beatType); fPosInfo.timeInSamples = static_cast(timeInfo.frame); fPosInfo.timeInSeconds = static_cast(fPosInfo.timeInSamples)/pData->engine->getSampleRate(); fPosInfo.ppqPosition = ppqBar + ppqBeat + ppqTick; fPosInfo.ppqPositionOfLastBarStart = ppqBar; } // -------------------------------------------------------------------------------------------------------- // Process processSingle(audioIn, audioOut, frames); // -------------------------------------------------------------------------------------------------------- #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH return; // unused (void)cvIn; #endif } bool processSingle(const float* const* const inBuffer, float** const outBuffer, const uint32_t frames) { CARLA_SAFE_ASSERT_RETURN(frames > 0, false); if (pData->audioIn.count > 0) { CARLA_SAFE_ASSERT_RETURN(inBuffer != nullptr, false); } if (pData->audioOut.count > 0) { CARLA_SAFE_ASSERT_RETURN(outBuffer != nullptr, false); } // -------------------------------------------------------------------------------------------------------- // Try lock, silence otherwise if (pData->engine->isOffline()) { pData->singleMutex.lock(); } else if (! pData->singleMutex.tryLock()) { for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(outBuffer[i], frames); return false; } // -------------------------------------------------------------------------------------------------------- // Set audio in buffers for (uint32_t i=0; i < pData->audioIn.count; ++i) fAudioBuffer.copyFrom(static_cast(i), 0, inBuffer[i], static_cast(frames)); // -------------------------------------------------------------------------------------------------------- // Run plugin fInstance->processBlock(fAudioBuffer, fMidiBuffer); // -------------------------------------------------------------------------------------------------------- // Set audio out buffers for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_copyFloats(outBuffer[i], fAudioBuffer.getReadPointer(static_cast(i)), frames); // -------------------------------------------------------------------------------------------------------- // Midi out if (! fMidiBuffer.isEmpty()) { if (pData->event.portOut != nullptr) { const uint8_t* midiEventData; int midiEventSize, midiEventPosition; for (juce::MidiBuffer::Iterator i(fMidiBuffer); i.getNextEvent(midiEventData, midiEventSize, midiEventPosition);) { CARLA_SAFE_ASSERT_BREAK(midiEventPosition >= 0 && midiEventPosition < static_cast(frames)); CARLA_SAFE_ASSERT_BREAK(midiEventSize > 0); if (! pData->event.portOut->writeMidiEvent(static_cast(midiEventPosition), static_cast(midiEventSize), midiEventData)) break; } } fMidiBuffer.clear(); } // -------------------------------------------------------------------------------------------------------- pData->singleMutex.unlock(); return true; } void bufferSizeChanged(const uint32_t newBufferSize) override { CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize); carla_debug("CarlaPluginJuce::bufferSizeChanged(%i)", newBufferSize); fAudioBuffer.setSize(static_cast(std::max(pData->audioIn.count, pData->audioOut.count)), static_cast(newBufferSize)); if (pData->active) { deactivate(); activate(); } } void sampleRateChanged(const double newSampleRate) override { CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate); carla_debug("CarlaPluginJuce::sampleRateChanged(%g)", newSampleRate); if (pData->active) { deactivate(); activate(); } } // ------------------------------------------------------------------- // Plugin buffers // nothing // ------------------------------------------------------------------- // Post-poned UI Stuff // nothing // ------------------------------------------------------------------- void* getNativeHandle() const noexcept override { return (fInstance != nullptr) ? fInstance->getPlatformSpecificData() : nullptr; } // ------------------------------------------------------------------- protected: void audioProcessorParameterChanged(juce::AudioProcessor*, int index, float value) override { CARLA_SAFE_ASSERT_RETURN(index >= 0,); const uint32_t uindex(static_cast(index)); const float fixedValue(pData->param.getFixedValue(uindex, value)); CarlaPlugin::setParameterValue(static_cast(index), fixedValue, false, true, true); } void audioProcessorChanged(juce::AudioProcessor*) override { pData->engine->callback(true, true, ENGINE_CALLBACK_UPDATE, pData->id, 0, 0, 0, 0.0f, nullptr); } void audioProcessorParameterChangeGestureBegin(juce::AudioProcessor*, int index) override { CARLA_SAFE_ASSERT_RETURN(index >= 0,); pData->engine->touchPluginParameter(pData->id, static_cast(index), true); } void audioProcessorParameterChangeGestureEnd(juce::AudioProcessor*, int index) override { CARLA_SAFE_ASSERT_RETURN(index >= 0,); pData->engine->touchPluginParameter(pData->id, static_cast(index), false); } bool getCurrentPosition(CurrentPositionInfo& result) override { carla_copyStruct(result, fPosInfo); return true; } // ------------------------------------------------------------------- public: bool init(const char* const filename, const char* const name, const char* const label, const int64_t uniqueId, const uint options, const char* const format) { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); // --------------------------------------------------------------- // first checks if (pData->client != nullptr) { pData->engine->setLastError("Plugin client is already registered"); return false; } if (format == nullptr || format[0] == '\0') { pData->engine->setLastError("null format"); return false; } // AU requires label if (std::strcmp(format, "AU") == 0) { if (label == nullptr || label[0] == '\0') { pData->engine->setLastError("null label"); return false; } } juce::String fileOrIdentifier; if (std::strcmp(format, "AU") == 0) { fileOrIdentifier = label; } else { // VST2 and VST3 require filename if (filename == nullptr || filename[0] == '\0') { pData->engine->setLastError("null filename"); return false; } juce::String jfilename(filename); #ifdef CARLA_OS_WIN // Fix for wine usage if (juce::juce_isRunningInWine() && filename[0] == '/') { jfilename.replace("/", "\\"); jfilename = "Z:" + jfilename; } #endif fileOrIdentifier = jfilename; if (label != nullptr && label[0] != '\0') fDesc.name = label; } fFormatManager.addDefaultFormats(); { juce::OwnedArray pluginDescriptions; juce::KnownPluginList plist; for (int i = 0; i < fFormatManager.getNumFormats(); ++i) plist.scanAndAddFile(fileOrIdentifier, true, pluginDescriptions, *fFormatManager.getFormat(i)); if (pluginDescriptions.size() == 0) { pData->engine->setLastError("Failed to get plugin description"); return false; } fDesc = *pluginDescriptions[0]; } if (uniqueId != 0) fDesc.uid = static_cast(uniqueId); juce::String error; fInstance = fFormatManager.createPluginInstance(fDesc, pData->engine->getSampleRate(), static_cast(pData->engine->getBufferSize()), error); if (fInstance == nullptr) { pData->engine->setLastError(error.toRawUTF8()); return false; } fInstance->fillInPluginDescription(fDesc); fInstance->setPlayHead(this); fInstance->addListener(this); fFormatName = format; // --------------------------------------------------------------- // get info if (name != nullptr && name[0] != '\0') pData->name = pData->engine->getUniquePluginName(name); else pData->name = pData->engine->getUniquePluginName(fInstance->getName().toRawUTF8()); if (filename != nullptr && filename[0] != '\0') pData->filename = carla_strdup(filename); // --------------------------------------------------------------- // register client pData->client = pData->engine->addClient(this); if (pData->client == nullptr || ! pData->client->isOk()) { pData->engine->setLastError("Failed to register plugin client"); return false; } // --------------------------------------------------------------- // set options pData->options = 0x0; pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; pData->options |= PLUGIN_OPTION_USE_CHUNKS; if (fInstance->acceptsMidi()) { if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)) pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)) pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND)) pData->options |= PLUGIN_OPTION_SEND_PITCHBEND; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF)) pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PROGRAM_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES; } if (fInstance->getNumPrograms() > 1 && ((pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) == 0)) { if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES)) pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; } return true; } private: juce::PluginDescription fDesc; juce::AudioPluginInstance* fInstance; juce::AudioPluginFormatManager fFormatManager; juce::AudioSampleBuffer fAudioBuffer; juce::MidiBuffer fMidiBuffer; CurrentPositionInfo fPosInfo; juce::MemoryBlock fChunk; juce::String fFormatName; CarlaScopedPointer fWindow; bool isJuceSaveFormat(const void* const data, const std::size_t dataSize) { if (fFormatName != "VST2") return true; if (dataSize < 160) return false; const int32_t* const set = (const int32_t*)data; if (! compareMagic(set[0], "CcnK")) return false; if (! compareMagic(set[2], "FBCh") && ! compareMagic(set[2], "FJuc")) return false; if (fxbSwap(set[3]) > 1) return false; const int32_t chunkSize = fxbSwap(set[39]); return static_cast(chunkSize + 160) == dataSize; } static bool compareMagic(int32_t magic, const char* name) noexcept { return magic == (int32_t)juce::ByteOrder::littleEndianInt (name) || magic == (int32_t)juce::ByteOrder::bigEndianInt (name); } static int32_t fxbSwap(const int32_t x) noexcept { return (int32_t)juce::ByteOrder::swapIfLittleEndian ((uint32_t) x); } CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginJuce) }; CARLA_BACKEND_END_NAMESPACE #endif // USING_JUCE // ------------------------------------------------------------------------------------------------------------------- CARLA_BACKEND_START_NAMESPACE CarlaPlugin* CarlaPlugin::newJuce(const Initializer& init, const char* const format) { carla_debug("CarlaPlugin::newJuce({%p, \"%s\", \"%s\", \"%s\", " P_INT64 "}, %s)", init.engine, init.filename, init.name, init.label, init.uniqueId, format); #ifdef USING_JUCE CarlaPluginJuce* const plugin(new CarlaPluginJuce(init.engine, init.id)); if (! plugin->init(init.filename, init.name, init.label, init.uniqueId, init.options, format)) { delete plugin; return nullptr; } return plugin; #else init.engine->setLastError("Juce-based plugin not available"); return nullptr; // unused (void)format; #endif } CARLA_BACKEND_END_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/plugin/CarlaPluginLADSPADSSI.cpp000066400000000000000000003450671364475620200230700ustar00rootroot00000000000000/* * Carla Plugin, LADSPA/DSSI implementation * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaPluginInternal.hpp" #include "CarlaEngineUtils.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaLadspaUtils.hpp" #include "CarlaDssiUtils.hpp" #include "CarlaMathUtils.hpp" #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) # include "CarlaOscUtils.hpp" # include "CarlaScopeUtils.hpp" # include "CarlaThread.hpp" # include "water/threads/ChildProcess.h" using water::ChildProcess; #endif using water::String; using water::StringArray; #define CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ /* check argument count */ \ if (argc != argcToCompare) \ { \ carla_stderr("CarlaPluginLADSPADSSI::%s() - argument count mismatch: %i != %i", \ __FUNCTION__, argc, argcToCompare); \ return; \ } \ if (argc > 0) \ { \ /* check for nullness */ \ if (types == nullptr || typesToCompare == nullptr) \ { \ carla_stderr("CarlaPluginLADSPADSSI::%s() - argument types are null", \ __FUNCTION__); \ return; \ } \ /* check argument types */ \ if (std::strcmp(types, typesToCompare) != 0) \ { \ carla_stderr("CarlaPluginLADSPADSSI::%s() - argument types mismatch: '%s' != '%s'", \ __FUNCTION__, types, typesToCompare); \ return; \ } \ } CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------- // Fallback data static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr }; #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) // ------------------------------------------------------------------- class CarlaThreadDSSIUI : public CarlaThread { public: CarlaThreadDSSIUI(CarlaEngine* const engine, CarlaPlugin* const plugin, const CarlaOscData& oscData) noexcept : CarlaThread("CarlaThreadDSSIUI"), kEngine(engine), kPlugin(plugin), fBinary(), fLabel(), fOscData(oscData), fProcess() {} void setData(const char* const binary, const char* const label) noexcept { CARLA_SAFE_ASSERT_RETURN(binary != nullptr && binary[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(label != nullptr /*&& label[0] != '\0'*/,); CARLA_SAFE_ASSERT(! isThreadRunning()); fBinary = binary; fLabel = label; if (fLabel.isEmpty()) fLabel = "\"\""; } uintptr_t getProcessId() const noexcept { CARLA_SAFE_ASSERT_RETURN(fProcess != nullptr, 0); return (uintptr_t)fProcess->getPID(); } void run() { carla_stdout("LADSPA/DSSI UI thread started"); if (fProcess == nullptr) { fProcess = new ChildProcess(); } else if (fProcess->isRunning()) { carla_stderr("CarlaThreadDSSI::run() - already running, giving up..."); fProcess->kill(); fProcess = nullptr; kEngine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, kPlugin->getId(), 0, 0, 0, 0.0f, nullptr); return; } String name(kPlugin->getName()); String filename(kPlugin->getFilename()); if (name.isEmpty()) name = "(none)"; if (filename.isEmpty()) filename = "\"\""; StringArray arguments; // binary arguments.add(fBinary.buffer()); // osc-url arguments.add(String(kEngine->getOscServerPathUDP()) + String("/") + String(kPlugin->getId())); // filename arguments.add(filename); // label arguments.add(fLabel.buffer()); // ui-title arguments.add(name + String(" (GUI)")); bool started; { #ifdef CARLA_OS_LINUX /* * If the frontend uses winId parent, set LD_PRELOAD to auto-map the DSSI UI. * If not, unset LD_PRELOAD. */ const uintptr_t winId(kEngine->getOptions().frontendWinId); // for CARLA_ENGINE_OPTION_FRONTEND_WIN_ID char winIdStr[STR_MAX+1]; winIdStr[STR_MAX] = '\0'; // for LD_PRELOAD CarlaString ldPreloadValue; if (winId != 0) { std::snprintf(winIdStr, STR_MAX, P_UINTPTR, winId); ldPreloadValue = (CarlaString(kEngine->getOptions().binaryDir) + "/libcarla_interposer-x11.so"); } else { winIdStr[0] = '\0'; } const ScopedEngineEnvironmentLocker _seel(kEngine); const CarlaScopedEnvVar _sev1("CARLA_ENGINE_OPTION_FRONTEND_WIN_ID", winIdStr[0] != '\0' ? winIdStr : nullptr); const CarlaScopedEnvVar _sev2("LD_PRELOAD", ldPreloadValue.isNotEmpty() ? ldPreloadValue.buffer() : nullptr); #endif // CARLA_OS_LINUX // start the DSSI UI application carla_stdout("starting DSSI UI..."); started = fProcess->start(arguments); } if (! started) { carla_stdout("failed!"); fProcess = nullptr; return; } if (waitForOscGuiShow()) { for (; fProcess->isRunning() && ! shouldThreadExit();) carla_sleep(1); // we only get here if UI was closed or thread asked to exit if (fProcess->isRunning() && shouldThreadExit()) { fProcess->waitForProcessToFinish(static_cast(kEngine->getOptions().uiBridgesTimeout)); if (fProcess->isRunning()) { carla_stdout("CarlaThreadDSSIUI::run() - UI refused to close, force kill now"); fProcess->kill(); } else { carla_stdout("CarlaThreadDSSIUI::run() - UI auto-closed successfully"); } } else if (fProcess->getExitCode() != 0 /*|| fProcess->exitStatus() == QProcess::CrashExit*/) carla_stderr("CarlaThreadDSSIUI::run() - UI crashed while running"); else carla_stdout("CarlaThreadDSSIUI::run() - UI closed cleanly"); } else { fProcess->kill(); carla_stdout("CarlaThreadDSSIUI::run() - GUI timeout"); } fProcess = nullptr; kEngine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, kPlugin->getId(), 0, 0, 0, 0.0f, nullptr); carla_stdout("LADSPA/DSSI UI thread finished"); } private: CarlaEngine* const kEngine; CarlaPlugin* const kPlugin; CarlaString fBinary; CarlaString fLabel; const CarlaOscData& fOscData; CarlaScopedPointer fProcess; bool waitForOscGuiShow() { carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow()"); const uint uiBridgesTimeout = kEngine->getOptions().uiBridgesTimeout; // wait for UI 'update' call for (uint i=0; i < uiBridgesTimeout/100; ++i) { if (fOscData.target != nullptr) { carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow() - got response, asking UI to show itself now"); osc_send_show(fOscData); return true; } if (fProcess != nullptr && fProcess->isRunning() && ! shouldThreadExit()) carla_msleep(100); else return false; } carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow() - Timeout while waiting for UI to respond" "(waited %u msecs)", uiBridgesTimeout); return false; } CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThreadDSSIUI) }; #endif // ----------------------------------------------------- class CarlaPluginLADSPADSSI : public CarlaPlugin { public: CarlaPluginLADSPADSSI(CarlaEngine* const engine, const uint id) noexcept : CarlaPlugin(engine, id), fHandles(), fDescriptor(nullptr), fDssiDescriptor(nullptr), fRdfDescriptor(nullptr), fAudioInBuffers(nullptr), fAudioOutBuffers(nullptr), fExtraStereoBuffer(), fParamBuffers(nullptr), fLatencyIndex(-1), fForcedStereoIn(false), fForcedStereoOut(false), fNeedsFixedBuffers(false), fUsesCustomData(false) #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) , fOscData(), fThreadUI(engine, this, fOscData), fUiFilename(nullptr) #endif { carla_debug("CarlaPluginLADSPADSSI::CarlaPluginLADSPADSSI(%p, %i)", engine, id); carla_zeroPointers(fExtraStereoBuffer, 2); } ~CarlaPluginLADSPADSSI() noexcept override { carla_debug("CarlaPluginLADSPADSSI::~CarlaPluginLADSPADSSI()"); #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) // close UI if (fUiFilename != nullptr) { showCustomUI(false); delete[] fUiFilename; fUiFilename = nullptr; } #endif pData->singleMutex.lock(); pData->masterMutex.lock(); if (pData->client != nullptr && pData->client->isActive()) pData->client->deactivate(); if (pData->active) { deactivate(); pData->active = false; } if (fDescriptor != nullptr) { if (fDescriptor->cleanup != nullptr) { for (LinkedList::Itenerator it = fHandles.begin2(); it.valid(); it.next()) { LADSPA_Handle const handle(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); try { fDescriptor->cleanup(handle); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup"); } } fHandles.clear(); fDescriptor = nullptr; fDssiDescriptor = nullptr; } if (fRdfDescriptor != nullptr) { delete fRdfDescriptor; fRdfDescriptor = nullptr; } clearBuffers(); } // ------------------------------------------------------------------- // Information (base) PluginType getType() const noexcept override { return fDssiDescriptor != nullptr ? PLUGIN_DSSI : PLUGIN_LADSPA; } PluginCategory getCategory() const noexcept override { if (fRdfDescriptor != nullptr) { const LADSPA_RDF_PluginType category = fRdfDescriptor->Type; // Specific Types if (category & (LADSPA_RDF_PLUGIN_DELAY|LADSPA_RDF_PLUGIN_REVERB)) return PLUGIN_CATEGORY_DELAY; if (category & (LADSPA_RDF_PLUGIN_PHASER|LADSPA_RDF_PLUGIN_FLANGER|LADSPA_RDF_PLUGIN_CHORUS)) return PLUGIN_CATEGORY_MODULATOR; if (category & (LADSPA_RDF_PLUGIN_AMPLIFIER)) return PLUGIN_CATEGORY_DYNAMICS; if (category & (LADSPA_RDF_PLUGIN_UTILITY|LADSPA_RDF_PLUGIN_SPECTRAL|LADSPA_RDF_PLUGIN_FREQUENCY_METER)) return PLUGIN_CATEGORY_UTILITY; // Pre-set LADSPA Types if (LADSPA_RDF_IS_PLUGIN_DYNAMICS(category)) return PLUGIN_CATEGORY_DYNAMICS; if (LADSPA_RDF_IS_PLUGIN_AMPLITUDE(category)) return PLUGIN_CATEGORY_MODULATOR; if (LADSPA_RDF_IS_PLUGIN_EQ(category)) return PLUGIN_CATEGORY_EQ; if (LADSPA_RDF_IS_PLUGIN_FILTER(category)) return PLUGIN_CATEGORY_FILTER; if (LADSPA_RDF_IS_PLUGIN_FREQUENCY(category)) return PLUGIN_CATEGORY_UTILITY; if (LADSPA_RDF_IS_PLUGIN_SIMULATOR(category)) return PLUGIN_CATEGORY_OTHER; if (LADSPA_RDF_IS_PLUGIN_TIME(category)) return PLUGIN_CATEGORY_DELAY; if (LADSPA_RDF_IS_PLUGIN_GENERATOR(category)) return PLUGIN_CATEGORY_SYNTH; } if (fDssiDescriptor != nullptr && fDssiDescriptor->run_synth != nullptr) if (pData->audioIn.count == 0 && pData->audioOut.count > 0) return PLUGIN_CATEGORY_SYNTH; return CarlaPlugin::getCategory(); } int64_t getUniqueId() const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0); return static_cast(fDescriptor->UniqueID); } uint32_t getLatencyInFrames() const noexcept override { if (fLatencyIndex < 0 || fParamBuffers == nullptr) return 0; const float latency(fParamBuffers[fLatencyIndex]); CARLA_SAFE_ASSERT_RETURN(latency >= 0.0f, 0); return static_cast(latency); } // ------------------------------------------------------------------- // Information (count) uint32_t getParameterScalePointCount(const uint32_t parameterId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0); if (fRdfDescriptor == nullptr) return 0; const int32_t rindex(pData->param.data[parameterId].rindex); CARLA_SAFE_ASSERT_RETURN(rindex >= 0, 0); if (rindex >= static_cast(fRdfDescriptor->PortCount)) return 0; const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]); return static_cast(port.ScalePointCount); } // ------------------------------------------------------------------- // Information (current data) std::size_t getChunkData(void** const dataPtr) noexcept override { CARLA_SAFE_ASSERT_RETURN(fUsesCustomData, 0); CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0); CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->get_custom_data != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(fHandles.count() > 0, 0); CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0); *dataPtr = nullptr; int ret = 0; ulong dataSize = 0; try { ret = fDssiDescriptor->get_custom_data(fHandles.getFirst(nullptr), dataPtr, &dataSize); } CARLA_SAFE_EXCEPTION_RETURN("CarlaPluginLADSPADSSI::getChunkData", 0); return (ret != 0) ? dataSize : 0; } // ------------------------------------------------------------------- // Information (per-plugin data) uint getOptionsAvailable() const noexcept override { uint options = 0x0; // can't disable fixed buffers if using latency if (fLatencyIndex == -1 && ! fNeedsFixedBuffers) options |= PLUGIN_OPTION_FIXED_BUFFERS; // can't disable forced stereo if enabled in the engine if (pData->engine->getOptions().forceStereo) pass(); // if inputs or outputs are just 1, then yes we can force stereo else if (pData->audioIn.count == 1 || pData->audioOut.count == 1 || fForcedStereoIn || fForcedStereoOut) options |= PLUGIN_OPTION_FORCE_STEREO; if (fDssiDescriptor != nullptr) { if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr) options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; if (fUsesCustomData) options |= PLUGIN_OPTION_USE_CHUNKS; if (fDssiDescriptor->run_synth != nullptr) { options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; options |= PLUGIN_OPTION_SEND_PITCHBEND; options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; } } return options; } float getParameterValue(const uint32_t parameterId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr, 0.0f); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f); // bad plugins might have set output values out of bounds if (pData->param.data[parameterId].type == PARAMETER_OUTPUT) return pData->param.ranges[parameterId].getFixedValue(fParamBuffers[parameterId]); // not output, should be fine return fParamBuffers[parameterId]; } float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0.0f); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f); const int32_t rindex(pData->param.data[parameterId].rindex); CARLA_SAFE_ASSERT_RETURN(rindex >= 0, 0.0f); CARLA_SAFE_ASSERT_RETURN(rindex < static_cast(fRdfDescriptor->PortCount), 0.0f); const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]); CARLA_SAFE_ASSERT_RETURN(scalePointId < port.ScalePointCount, 0.0f); const LADSPA_RDF_ScalePoint& scalePoint(port.ScalePoints[scalePointId]); return pData->param.ranges[parameterId].getFixedValue(scalePoint.Value); } bool getLabel(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fDescriptor->Label != nullptr, false); std::strncpy(strBuf, fDescriptor->Label, STR_MAX); return true; } bool getMaker(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fDescriptor->Maker != nullptr, false); if (fRdfDescriptor != nullptr && fRdfDescriptor->Creator != nullptr) std::strncpy(strBuf, fRdfDescriptor->Creator, STR_MAX); else std::strncpy(strBuf, fDescriptor->Maker, STR_MAX); return true; } bool getCopyright(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fDescriptor->Copyright != nullptr, false); std::strncpy(strBuf, fDescriptor->Copyright, STR_MAX); return true; } bool getRealName(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fDescriptor->Name != nullptr, false); if (fRdfDescriptor != nullptr && fRdfDescriptor->Title != nullptr) std::strncpy(strBuf, fRdfDescriptor->Title, STR_MAX); else std::strncpy(strBuf, fDescriptor->Name, STR_MAX); return true; } bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); const int32_t rindex(pData->param.data[parameterId].rindex); CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false); CARLA_SAFE_ASSERT_RETURN(rindex < static_cast(fDescriptor->PortCount), false); CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames[rindex] != nullptr, false); if (! getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, true)) std::strncpy(strBuf, fDescriptor->PortNames[rindex], STR_MAX); return true; } bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); const int32_t rindex(pData->param.data[parameterId].rindex); CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false); if (fRdfDescriptor != nullptr && rindex < static_cast(fRdfDescriptor->PortCount)) { const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]); if (LADSPA_RDF_PORT_HAS_UNIT(port.Hints)) { switch (port.Unit) { case LADSPA_RDF_UNIT_DB: std::strncpy(strBuf, "dB", STR_MAX); return true; case LADSPA_RDF_UNIT_COEF: std::strncpy(strBuf, "(coef)", STR_MAX); return true; case LADSPA_RDF_UNIT_HZ: std::strncpy(strBuf, "Hz", STR_MAX); return true; case LADSPA_RDF_UNIT_S: std::strncpy(strBuf, "s", STR_MAX); return true; case LADSPA_RDF_UNIT_MS: std::strncpy(strBuf, "ms", STR_MAX); return true; case LADSPA_RDF_UNIT_MIN: std::strncpy(strBuf, "min", STR_MAX); return true; } } } CARLA_SAFE_ASSERT_RETURN(rindex < static_cast(fDescriptor->PortCount), false); CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames[rindex] != nullptr, false); return getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, false); } bool getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); if (fRdfDescriptor == nullptr) return false; const int32_t rindex(pData->param.data[parameterId].rindex); CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false); if (rindex >= static_cast(fRdfDescriptor->PortCount)) return false; const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]); if (! LADSPA_RDF_PORT_HAS_LABEL(port.Hints)) return false; CARLA_SAFE_ASSERT_RETURN(port.Label != nullptr, false); std::strncpy(strBuf, port.Label, STR_MAX); return true; } bool getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); const int32_t rindex(pData->param.data[parameterId].rindex); CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false); CARLA_SAFE_ASSERT_RETURN(rindex < static_cast(fRdfDescriptor->PortCount), false); const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]); CARLA_SAFE_ASSERT_RETURN(scalePointId < port.ScalePointCount, false); const LADSPA_RDF_ScalePoint& scalePoint(port.ScalePoints[scalePointId]); CARLA_SAFE_ASSERT_RETURN(scalePoint.Label != nullptr, false); std::strncpy(strBuf, scalePoint.Label, STR_MAX); return true; } // ------------------------------------------------------------------- // Set data (state) // nothing // ------------------------------------------------------------------- // Set data (internal stuff) void setId(const uint newId) noexcept override { CarlaPlugin::setId(newId); // UI osc-url uses Id, so we need to close it when it changes // FIXME - must be RT safe showCustomUI(false); } // ------------------------------------------------------------------- // Set data (plugin-specific stuff) void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override { CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); const float fixedValue(pData->param.getFixedValue(parameterId, value)); fParamBuffers[parameterId] = fixedValue; CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback); } void setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); const float fixedValue(pData->param.getFixedValue(parameterId, value)); fParamBuffers[parameterId] = fixedValue; CarlaPlugin::setParameterValueRT(parameterId, fixedValue, sendCallbackLater); } void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override { CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr,); carla_debug("CarlaPluginLADSPADSSI::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui)); if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0) return CarlaPlugin::setCustomData(type, key, value, sendGui); if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0) return carla_stderr2("CarlaPluginLADSPADSSI::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui)); if (fDssiDescriptor->configure != nullptr && fHandles.count() > 0) { for (LinkedList::Itenerator it = fHandles.begin2(); it.valid(); it.next()) { LADSPA_Handle const handle(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); try { fDssiDescriptor->configure(handle, key, value); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI setCustomData"); } } #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (sendGui && fOscData.target != nullptr) osc_send_configure(fOscData, key, value); #endif if (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0) { const ScopedSingleProcessLocker spl(this, true); reloadPrograms(false); } CarlaPlugin::setCustomData(type, key, value, sendGui); } void setChunkData(const void* const data, const std::size_t dataSize) override { CARLA_SAFE_ASSERT_RETURN(fUsesCustomData,); CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,); CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->set_custom_data != nullptr,); CARLA_SAFE_ASSERT_RETURN(data != nullptr,); CARLA_SAFE_ASSERT_RETURN(dataSize > 0,); if (fHandles.count() > 0) { const ScopedSingleProcessLocker spl(this, true); for (LinkedList::Itenerator it = fHandles.begin2(); it.valid(); it.next()) { LADSPA_Handle const handle(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); try { fDssiDescriptor->set_custom_data(handle, const_cast(data), static_cast(dataSize)); } CARLA_SAFE_EXCEPTION("CarlaPluginLADSPADSSI::setChunkData"); } } pData->updateParameterValues(this, true, true, false); } void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override { CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->select_program != nullptr,); CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->midiprog.count),); CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,); if (index >= 0 && fHandles.count() > 0) { const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); setMidiProgramInDSSI(static_cast(index)); } CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit); } void setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->select_program != nullptr,); CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,); setMidiProgramInDSSI(uindex); CarlaPlugin::setMidiProgramRT(uindex, sendCallbackLater); } void setMidiProgramInDSSI(const uint32_t uindex) noexcept { const uint32_t bank(pData->midiprog.data[uindex].bank); const uint32_t program(pData->midiprog.data[uindex].program); for (LinkedList::Itenerator it = fHandles.begin2(); it.valid(); it.next()) { LADSPA_Handle const handle(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); try { fDssiDescriptor->select_program(handle, bank, program); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI setMidiProgram") } } #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) // ------------------------------------------------------------------- // Set ui stuff void showCustomUI(const bool yesNo) override { if (yesNo) { fOscData.clear(); fThreadUI.startThread(); } else { #ifndef BUILD_BRIDGE pData->transientTryCounter = 0; #endif if (fOscData.target != nullptr) { osc_send_hide(fOscData); osc_send_quit(fOscData); fOscData.clear(); } fThreadUI.stopThread(static_cast(pData->engine->getOptions().uiBridgesTimeout * 2)); } } #endif // ------------------------------------------------------------------- // Plugin state void reload() override { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandles.count() > 0,); carla_debug("CarlaPluginLADSPADSSI::reload() - start"); const EngineProcessMode processMode(pData->engine->getProccessMode()); // Safely disable plugin for reload const ScopedDisabler sd(this); if (pData->active) deactivate(); clearBuffers(); const float sampleRate(static_cast(pData->engine->getSampleRate())); const uint32_t portCount(getSafePortCount()); uint32_t aIns, aOuts, mIns, params; aIns = aOuts = mIns = params = 0; bool forcedStereoIn, forcedStereoOut; forcedStereoIn = forcedStereoOut = false; bool needsCtrlIn, needsCtrlOut; needsCtrlIn = needsCtrlOut = false; for (uint32_t i=0; i < portCount; ++i) { const LADSPA_PortDescriptor portType(fDescriptor->PortDescriptors[i]); if (LADSPA_IS_PORT_AUDIO(portType)) { if (LADSPA_IS_PORT_INPUT(portType)) aIns += 1; else if (LADSPA_IS_PORT_OUTPUT(portType)) aOuts += 1; } else if (LADSPA_IS_PORT_CONTROL(portType)) params += 1; } if (pData->options & PLUGIN_OPTION_FORCE_STEREO) { if ((aIns == 1 || aOuts == 1) && fHandles.count() == 1 && addInstance()) { if (aIns == 1) { aIns = 2; forcedStereoIn = true; } if (aOuts == 1) { aOuts = 2; forcedStereoOut = true; } } } if (fDssiDescriptor != nullptr && fDssiDescriptor->run_synth != nullptr) { mIns = 1; needsCtrlIn = true; } if (aIns > 0) { pData->audioIn.createNew(aIns); fAudioInBuffers = new float*[aIns]; for (uint32_t i=0; i < aIns; ++i) fAudioInBuffers[i] = nullptr; } if (aOuts > 0) { pData->audioOut.createNew(aOuts); fAudioOutBuffers = new float*[aOuts]; needsCtrlIn = true; for (uint32_t i=0; i < aOuts; ++i) fAudioOutBuffers[i] = nullptr; } if (params > 0) { pData->param.createNew(params, true); fParamBuffers = new float[params]; carla_zeroFloats(fParamBuffers, params); } const uint portNameSize(pData->engine->getMaxPortNameSize()); CarlaString portName; for (uint32_t i=0, iAudioIn=0, iAudioOut=0, iCtrl=0; i < portCount; ++i) { const LADSPA_PortDescriptor portType = fDescriptor->PortDescriptors[i]; const LADSPA_PortRangeHint portRangeHints = fDescriptor->PortRangeHints[i]; const bool hasPortRDF = (fRdfDescriptor != nullptr && i < fRdfDescriptor->PortCount); if (LADSPA_IS_PORT_AUDIO(portType)) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (fDescriptor->PortNames[i] != nullptr && fDescriptor->PortNames[i][0] != '\0') { portName += fDescriptor->PortNames[i]; } else { if (LADSPA_IS_PORT_INPUT(portType)) { if (aIns > 1) { portName += "audio-in_"; portName += CarlaString(iAudioIn+1); } else portName += "audio-in"; } else { if (aOuts > 1) { portName += "audio-out_"; portName += CarlaString(iAudioOut+1); } else portName += "audio-out"; } } portName.truncate(portNameSize); if (LADSPA_IS_PORT_INPUT(portType)) { const uint32_t j = iAudioIn++; pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j); pData->audioIn.ports[j].rindex = i; if (forcedStereoIn) { portName += "_2"; pData->audioIn.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, 1); pData->audioIn.ports[1].rindex = i; } } else if (LADSPA_IS_PORT_OUTPUT(portType)) { const uint32_t j = iAudioOut++; pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j); pData->audioOut.ports[j].rindex = i; if (forcedStereoOut) { portName += "_2"; pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 1); pData->audioOut.ports[1].rindex = i; } } else carla_stderr2("WARNING - Got a broken Port (Audio, but not input or output)"); } else if (LADSPA_IS_PORT_CONTROL(portType)) { const uint32_t j = iCtrl++; pData->param.data[j].index = static_cast(j); pData->param.data[j].rindex = static_cast(i); const char* const paramName(fDescriptor->PortNames[i] != nullptr ? fDescriptor->PortNames[i] : "unknown"); float min, max, def, step, stepSmall, stepLarge; // min value if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor)) min = portRangeHints.LowerBound; else min = 0.0f; // max value if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor)) max = portRangeHints.UpperBound; else max = 1.0f; if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor)) { min *= sampleRate; max *= sampleRate; pData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE; } if (min >= max) { carla_stderr2("WARNING - Broken plugin parameter '%s': min >= max", paramName); max = min + 0.1f; } // default value if (hasPortRDF && LADSPA_RDF_PORT_HAS_DEFAULT(fRdfDescriptor->Ports[i].Hints)) def = fRdfDescriptor->Ports[i].Default; else def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max); if (def < min) def = min; else if (def > max) def = max; if (LADSPA_IS_HINT_TOGGLED(portRangeHints.HintDescriptor)) { step = max - min; stepSmall = step; stepLarge = step; pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN; } else if (LADSPA_IS_HINT_INTEGER(portRangeHints.HintDescriptor)) { step = 1.0f; stepSmall = 1.0f; stepLarge = 10.0f; pData->param.data[j].hints |= PARAMETER_IS_INTEGER; } else { const float range = max - min; step = range/100.0f; stepSmall = range/1000.0f; stepLarge = range/10.0f; } if (LADSPA_IS_PORT_INPUT(portType)) { pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints |= PARAMETER_IS_ENABLED; pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE; pData->param.data[j].hints |= PARAMETER_CAN_BE_CV_CONTROLLED; needsCtrlIn = true; // MIDI CC value if (fDssiDescriptor != nullptr && fDssiDescriptor->get_midi_controller_for_port != nullptr) { const int ctrl = fDssiDescriptor->get_midi_controller_for_port(fHandles.getFirst(nullptr), i); if (DSSI_CONTROLLER_IS_SET(ctrl) && DSSI_IS_CC(ctrl)) { const int16_t cc = DSSI_CC_NUMBER(ctrl); if (cc < MAX_MIDI_CONTROL && ! MIDI_IS_CONTROL_BANK_SELECT(cc)) pData->param.data[j].mappedControlIndex = cc; } } } else if (LADSPA_IS_PORT_OUTPUT(portType)) { pData->param.data[j].type = PARAMETER_OUTPUT; if (std::strcmp(paramName, "latency") == 0 || std::strcmp(paramName, "_latency") == 0) { min = 0.0f; max = sampleRate; def = 0.0f; step = 1.0f; stepSmall = 1.0f; stepLarge = 1.0f; pData->param.special[j] = PARAMETER_SPECIAL_LATENCY; CARLA_SAFE_ASSERT_INT2(fLatencyIndex == static_cast(j), fLatencyIndex, j); } else { pData->param.data[j].hints |= PARAMETER_IS_ENABLED; pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE; needsCtrlOut = true; } } else { carla_stderr2("WARNING - Got a broken Port (Control, but not input or output)"); } // extra parameter hints if (LADSPA_IS_HINT_LOGARITHMIC(portRangeHints.HintDescriptor)) pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC; // check for scalepoints, require at least 2 to make it useful if (hasPortRDF && fRdfDescriptor->Ports[i].ScalePointCount >= 2) pData->param.data[j].hints |= PARAMETER_USES_SCALEPOINTS; pData->param.ranges[j].min = min; pData->param.ranges[j].max = max; pData->param.ranges[j].def = def; pData->param.ranges[j].step = step; pData->param.ranges[j].stepSmall = stepSmall; pData->param.ranges[j].stepLarge = stepLarge; // Start parameters in their default values fParamBuffers[j] = def; for (LinkedList::Itenerator it = fHandles.begin2(); it.valid(); it.next()) { LADSPA_Handle const handle(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); try { fDescriptor->connect_port(handle, i, &fParamBuffers[j]); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (parameter)"); } } else { // Not Audio or Control carla_stderr2("ERROR - Got a broken Port (neither Audio or Control)"); for (LinkedList::Itenerator it = fHandles.begin2(); it.valid(); it.next()) { LADSPA_Handle const handle(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); try { fDescriptor->connect_port(handle, i, nullptr); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (null)"); } } } if (needsCtrlIn) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-in"; portName.truncate(portNameSize); pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->event.cvSourcePorts = pData->client->createCVSourcePorts(); #endif } if (needsCtrlOut) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-out"; portName.truncate(portNameSize); pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0); } if (forcedStereoIn || forcedStereoOut) pData->options |= PLUGIN_OPTION_FORCE_STEREO; else pData->options &= ~PLUGIN_OPTION_FORCE_STEREO; // plugin hints pData->hints = 0x0; if (LADSPA_IS_HARD_RT_CAPABLE(fDescriptor->Properties)) pData->hints |= PLUGIN_IS_RTSAFE; #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) if (fUiFilename != nullptr) pData->hints |= PLUGIN_HAS_CUSTOM_UI; #endif #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (aOuts > 0 && (aIns == aOuts || aIns == 1)) pData->hints |= PLUGIN_CAN_DRYWET; if (aOuts > 0) pData->hints |= PLUGIN_CAN_VOLUME; if (aOuts >= 2 && aOuts % 2 == 0) pData->hints |= PLUGIN_CAN_BALANCE; #endif // extra plugin hints pData->extraHints = 0x0; if (mIns > 0) pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN; // check initial latency findInitialLatencyValue(aIns, aOuts); fForcedStereoIn = forcedStereoIn; fForcedStereoOut = forcedStereoOut; bufferSizeChanged(pData->engine->getBufferSize()); reloadPrograms(true); if (pData->active) activate(); carla_debug("CarlaPluginLADSPADSSI::reload() - end"); } void findInitialLatencyValue(const uint32_t aIns, const uint32_t aOuts) const { if (fLatencyIndex < 0 || fHandles.count() == 0) return; // we need to pre-run the plugin so it can update its latency control-port const LADSPA_Handle handle(fHandles.getFirst(nullptr)); CARLA_SAFE_ASSERT_RETURN(handle != nullptr,); float tmpIn [(aIns > 0) ? aIns : 1][2]; float tmpOut[(aOuts > 0) ? aOuts : 1][2]; for (uint32_t j=0; j < aIns; ++j) { tmpIn[j][0] = 0.0f; tmpIn[j][1] = 0.0f; try { fDescriptor->connect_port(handle, pData->audioIn.ports[j].rindex, tmpIn[j]); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (latency input)"); } for (uint32_t j=0; j < aOuts; ++j) { tmpOut[j][0] = 0.0f; tmpOut[j][1] = 0.0f; try { fDescriptor->connect_port(handle, pData->audioOut.ports[j].rindex, tmpOut[j]); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (latency output)"); } if (fDescriptor->activate != nullptr) { try { fDescriptor->activate(handle); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency activate"); } try { fDescriptor->run(handle, 2); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency run"); if (fDescriptor->deactivate != nullptr) { try { fDescriptor->deactivate(handle); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency deactivate"); } // done, let's get the value if (const uint32_t latency = getLatencyInFrames()) { pData->client->setLatency(latency); #ifndef BUILD_BRIDGE pData->latency.recreateBuffers(std::max(aIns, aOuts), latency); #endif } } void reloadPrograms(const bool doInit) override { carla_debug("CarlaPluginLADSPADSSI::reloadPrograms(%s)", bool2str(doInit)); const LADSPA_Handle handle(fHandles.getFirst(nullptr)); CARLA_SAFE_ASSERT_RETURN(handle != nullptr,); const uint32_t oldCount = pData->midiprog.count; const int32_t current = pData->midiprog.current; // Delete old programs pData->midiprog.clear(); // nothing to do for simple LADSPA plugins (do we want to bother with lrdf presets?) if (fDssiDescriptor == nullptr) return; // Query new programs uint32_t newCount = 0; if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr) { for (; fDssiDescriptor->get_program(handle, newCount) != nullptr;) ++newCount; } if (newCount > 0) { pData->midiprog.createNew(newCount); // Update data for (uint32_t i=0; i < newCount; ++i) { const DSSI_Program_Descriptor* const pdesc(fDssiDescriptor->get_program(handle, i)); CARLA_SAFE_ASSERT_CONTINUE(pdesc != nullptr); CARLA_SAFE_ASSERT(pdesc->Name != nullptr); pData->midiprog.data[i].bank = static_cast(pdesc->Bank); pData->midiprog.data[i].program = static_cast(pdesc->Program); pData->midiprog.data[i].name = carla_strdup(pdesc->Name); } } if (doInit) { if (newCount > 0) setMidiProgram(0, false, false, false, true); } else { // Check if current program is invalid bool programChanged = false; if (newCount == oldCount+1) { // one midi program added, probably created by user pData->midiprog.current = static_cast(oldCount); programChanged = true; } else if (current < 0 && newCount > 0) { // programs exist now, but not before pData->midiprog.current = 0; programChanged = true; } else if (current >= 0 && newCount == 0) { // programs existed before, but not anymore pData->midiprog.current = -1; programChanged = true; } else if (current >= static_cast(newCount)) { // current midi program > count pData->midiprog.current = 0; programChanged = true; } else { // no change pData->midiprog.current = current; } if (programChanged) setMidiProgram(pData->midiprog.current, true, true, true, false); pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0f, nullptr); } } // ------------------------------------------------------------------- // Plugin processing void activate() noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); if (fDescriptor->activate != nullptr) { for (LinkedList::Itenerator it = fHandles.begin2(); it.valid(); it.next()) { LADSPA_Handle const handle(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); try { fDescriptor->activate(handle); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI activate"); } } } void deactivate() noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); if (fDescriptor->deactivate != nullptr) { for (LinkedList::Itenerator it = fHandles.begin2(); it.valid(); it.next()) { LADSPA_Handle const handle(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); try { fDescriptor->deactivate(handle); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI deactivate"); } } } void process(const float* const* const audioIn, float** const audioOut, const float* const* const cvIn, float**, const uint32_t frames) override { // -------------------------------------------------------------------------------------------------------- // Check if active if (! pData->active) { // disable any output sound for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(audioOut[i], frames); return; } ulong midiEventCount = 0; carla_zeroStructs(fMidiEvents, kPluginMaxMidiEvents); // -------------------------------------------------------------------------------------------------------- // Check if needs reset if (pData->needsReset) { if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { midiEventCount = MAX_MIDI_CHANNELS*2; for (uchar i=0, k=MAX_MIDI_CHANNELS; i < MAX_MIDI_CHANNELS; ++i) { fMidiEvents[i].type = SND_SEQ_EVENT_CONTROLLER; fMidiEvents[i].data.control.channel = i; fMidiEvents[i].data.control.param = MIDI_CONTROL_ALL_NOTES_OFF; fMidiEvents[k+i].type = SND_SEQ_EVENT_CONTROLLER; fMidiEvents[k+i].data.control.channel = i; fMidiEvents[k+i].data.control.param = MIDI_CONTROL_ALL_SOUND_OFF; } } else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) { midiEventCount = MAX_MIDI_NOTE; for (uchar i=0; i < MAX_MIDI_NOTE; ++i) { fMidiEvents[i].type = SND_SEQ_EVENT_NOTEOFF; fMidiEvents[i].data.note.channel = static_cast(pData->ctrlChannel); fMidiEvents[i].data.note.note = i; } } pData->needsReset = false; } // -------------------------------------------------------------------------------------------------------- // Event Input and Processing if (pData->event.portIn != nullptr) { // ---------------------------------------------------------------------------------------------------- // MIDI Input (External) if (pData->extNotes.mutex.tryLock()) { ExternalMidiNote note = { 0, 0, 0 }; for (; midiEventCount < kPluginMaxMidiEvents && ! pData->extNotes.data.isEmpty();) { note = pData->extNotes.data.getFirst(note, true); CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]); seqEvent.type = (note.velo > 0) ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF; seqEvent.data.note.channel = static_cast(note.channel); seqEvent.data.note.note = note.note; seqEvent.data.note.velocity = note.velo; } pData->extNotes.mutex.unlock(); } // End of MIDI Input (External) // ---------------------------------------------------------------------------------------------------- // Event Input (System) #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH bool allNotesOffSent = false; #endif const bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; uint32_t startTime = 0; uint32_t timeOffset = 0; uint32_t nextBankId; if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) nextBankId = pData->midiprog.data[pData->midiprog.current].bank; else nextBankId = 0; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr) pData->event.cvSourcePorts->initPortBuffers(cvIn, frames, isSampleAccurate, pData->event.portIn); #endif for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i) { const EngineEvent& event(pData->event.portIn->getEvent(i)); uint32_t eventTime = event.time; CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames); if (eventTime < timeOffset) { carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'", eventTime, timeOffset, pData->name); eventTime = timeOffset; } if (isSampleAccurate && eventTime > timeOffset) { if (processSingle(audioIn, audioOut, eventTime - timeOffset, timeOffset, midiEventCount)) { startTime = 0; timeOffset = eventTime; midiEventCount = 0; if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) nextBankId = pData->midiprog.data[pData->midiprog.current].bank; else nextBankId = 0; } else startTime += timeOffset; } switch (event.type) { case kEngineEventTypeNull: break; case kEngineEventTypeControl: { const EngineControlEvent& ctrlEvent(event.ctrl); switch (ctrlEvent.type) { case kEngineControlEventTypeNull: break; case kEngineControlEventTypeParameter: { float value; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // non-midi if (event.channel == kEngineEventNonMidiChannel) { const uint32_t k = ctrlEvent.param; CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count); value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.value); setParameterValueRT(k, value, true); continue; } // Control backend stuff if (event.channel == pData->ctrlChannel) { if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0) { value = ctrlEvent.value; setDryWetRT(value, true); } if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0) { value = ctrlEvent.value*127.0f/100.0f; setVolumeRT(value, true); } if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0) { float left, right; value = ctrlEvent.value/0.5f - 1.0f; if (value < 0.0f) { left = -1.0f; right = (value*2.0f)+1.0f; } else if (value > 0.0f) { left = (value*2.0f)-1.0f; right = 1.0f; } else { left = -1.0f; right = 1.0f; } setBalanceLeftRT(left, true); setBalanceRightRT(right, true); } } #endif // Control plugin parameters for (uint32_t k=0; k < pData->param.count; ++k) { if (pData->param.data[k].midiChannel != event.channel) continue; if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) continue; if (pData->param.data[k].type != PARAMETER_INPUT) continue; if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) continue; value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.value); setParameterValueRT(k, value, true); } if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE) { if (midiEventCount >= kPluginMaxMidiEvents) continue; snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]); seqEvent.time.tick = isSampleAccurate ? startTime : eventTime; seqEvent.type = SND_SEQ_EVENT_CONTROLLER; seqEvent.data.control.channel = event.channel; seqEvent.data.control.param = ctrlEvent.param; seqEvent.data.control.value = int8_t(ctrlEvent.value*127.0f); } break; } // case kEngineControlEventTypeParameter case kEngineControlEventTypeMidiBank: if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0) nextBankId = ctrlEvent.param; break; case kEngineControlEventTypeMidiProgram: if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0) { const uint32_t nextProgramId = ctrlEvent.param; for (uint32_t k=0; k < pData->midiprog.count; ++k) { if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId) { setMidiProgramRT(k, true); break; } } } break; case kEngineControlEventTypeAllSoundOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { if (midiEventCount >= kPluginMaxMidiEvents) continue; snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]); seqEvent.time.tick = isSampleAccurate ? startTime : eventTime; seqEvent.type = SND_SEQ_EVENT_CONTROLLER; seqEvent.data.control.channel = event.channel; seqEvent.data.control.param = MIDI_CONTROL_ALL_SOUND_OFF; } break; case kEngineControlEventTypeAllNotesOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (event.channel == pData->ctrlChannel && ! allNotesOffSent) { allNotesOffSent = true; postponeRtAllNotesOff(); } #endif if (midiEventCount >= kPluginMaxMidiEvents) continue; snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]); seqEvent.time.tick = isSampleAccurate ? startTime : eventTime; seqEvent.type = SND_SEQ_EVENT_CONTROLLER; seqEvent.data.control.channel = event.channel; seqEvent.data.control.param = MIDI_CONTROL_ALL_NOTES_OFF; } break; } // switch (ctrlEvent.type) break; } // case kEngineEventTypeControl case kEngineEventTypeMidi: { if (midiEventCount >= kPluginMaxMidiEvents) continue; const EngineMidiEvent& midiEvent(event.midi); if (midiEvent.size > EngineMidiEvent::kDataSize) continue; uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); // Fix bad note-off (per DSSI spec) if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0) status = MIDI_STATUS_NOTE_OFF; snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]); seqEvent.time.tick = isSampleAccurate ? startTime : eventTime; switch (status) { case MIDI_STATUS_NOTE_OFF: { const uint8_t note = midiEvent.data[1]; seqEvent.type = SND_SEQ_EVENT_NOTEOFF; seqEvent.data.note.channel = event.channel; seqEvent.data.note.note = note; pData->postponeRtEvent(kPluginPostRtEventNoteOff, true, event.channel, note, 0, 0.0f); break; } case MIDI_STATUS_NOTE_ON: { const uint8_t note = midiEvent.data[1]; const uint8_t velo = midiEvent.data[2]; seqEvent.type = SND_SEQ_EVENT_NOTEON; seqEvent.data.note.channel = event.channel; seqEvent.data.note.note = note; seqEvent.data.note.velocity = velo; pData->postponeRtEvent(kPluginPostRtEventNoteOn, true, event.channel, note, velo, 0.0f); break; } case MIDI_STATUS_POLYPHONIC_AFTERTOUCH: if (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) { const uint8_t note = midiEvent.data[1]; const uint8_t pressure = midiEvent.data[2]; seqEvent.type = SND_SEQ_EVENT_KEYPRESS; seqEvent.data.note.channel = event.channel; seqEvent.data.note.note = note; seqEvent.data.note.velocity = pressure; } break; case MIDI_STATUS_CONTROL_CHANGE: if (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) { const uint8_t control = midiEvent.data[1]; const uint8_t value = midiEvent.data[2]; seqEvent.type = SND_SEQ_EVENT_CONTROLLER; seqEvent.data.control.channel = event.channel; seqEvent.data.control.param = control; seqEvent.data.control.value = value; } break; case MIDI_STATUS_CHANNEL_PRESSURE: if (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) { const uint8_t pressure = midiEvent.data[1]; seqEvent.type = SND_SEQ_EVENT_CHANPRESS; seqEvent.data.control.channel = event.channel; seqEvent.data.control.value = pressure; } break; case MIDI_STATUS_PITCH_WHEEL_CONTROL: if (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) { const uint8_t lsb = midiEvent.data[1]; const uint8_t msb = midiEvent.data[2]; seqEvent.type = SND_SEQ_EVENT_PITCHBEND; seqEvent.data.control.channel = event.channel; seqEvent.data.control.value = ((msb << 7) | lsb) - 8192; } break; default: --midiEventCount; break; } // switch (status) } break; } // switch (event.type) } pData->postRtEvents.trySplice(); if (frames > timeOffset) processSingle(audioIn, audioOut, frames - timeOffset, timeOffset, midiEventCount); } // End of Event Input and Processing // -------------------------------------------------------------------------------------------------------- // Plugin processing (no events) else { processSingle(audioIn, audioOut, frames, 0, midiEventCount); } // End of Plugin processing (no events) // -------------------------------------------------------------------------------------------------------- // Control Output if (pData->event.portOut != nullptr) { uint8_t channel; uint16_t param; float value; for (uint32_t k=0; k < pData->param.count; ++k) { if (pData->param.data[k].type != PARAMETER_OUTPUT) continue; pData->param.ranges[k].fixValue(fParamBuffers[k]); if (pData->param.data[k].mappedControlIndex > 0) { channel = pData->param.data[k].midiChannel; param = static_cast(pData->param.data[k].mappedControlIndex); value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]); pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value); } } } // End of Control Output #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH return; // unused (void)cvIn; #endif } bool processSingle(const float* const* const audioIn, float** const audioOut, const uint32_t frames, const uint32_t timeOffset, const ulong midiEventCount) { CARLA_SAFE_ASSERT_RETURN(frames > 0, false); if (pData->audioIn.count > 0) { CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false); } if (pData->audioOut.count > 0) { CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false); } // -------------------------------------------------------------------------------------------------------- // Try lock, silence otherwise #ifndef STOAT_TEST_BUILD if (pData->engine->isOffline()) { pData->singleMutex.lock(); } else #endif if (! pData->singleMutex.tryLock()) { for (uint32_t i=0; i < pData->audioOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) audioOut[i][k+timeOffset] = 0.0f; } return false; } // -------------------------------------------------------------------------------------------------------- // Set audio buffers const bool customMonoOut = pData->audioOut.count == 2 && fForcedStereoOut && ! fForcedStereoIn; const bool customStereoOut = pData->audioOut.count == 2 && fForcedStereoIn && ! fForcedStereoOut; if (! customMonoOut) { for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(fAudioOutBuffers[i], frames); } for (uint32_t i=0; i < pData->audioIn.count; ++i) carla_copyFloats(fAudioInBuffers[i], audioIn[i]+timeOffset, frames); // -------------------------------------------------------------------------------------------------------- // Run plugin uint instn = 0; for (LinkedList::Itenerator it = fHandles.begin2(); it.valid(); it.next(), ++instn) { LADSPA_Handle const handle(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); // ---------------------------------------------------------------------------------------------------- // Mixdown for forced stereo if (customMonoOut) carla_zeroFloats(fAudioOutBuffers[instn], frames); // ---------------------------------------------------------------------------------------------------- // Run it if (fDssiDescriptor != nullptr && fDssiDescriptor->run_synth != nullptr) { try { fDssiDescriptor->run_synth(handle, frames, fMidiEvents, midiEventCount); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI run_synth"); } else { try { fDescriptor->run(handle, frames); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI run"); } // ---------------------------------------------------------------------------------------------------- // Mixdown for forced stereo if (customMonoOut) carla_multiply(fAudioOutBuffers[instn], 0.5f, frames); else if (customStereoOut) carla_copyFloats(fExtraStereoBuffer[instn], fAudioOutBuffers[instn], frames); } if (customStereoOut) { carla_copyFloats(fAudioOutBuffers[0], fExtraStereoBuffer[0], frames); carla_copyFloats(fAudioOutBuffers[1], fExtraStereoBuffer[1], frames); } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // -------------------------------------------------------------------------------------------------------- // Post-processing (dry/wet, volume and balance) { const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f); const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f)); const bool isMono = (pData->audioIn.count == 1); bool isPair; float bufValue, oldBufLeft[doBalance ? frames : 1]; for (uint32_t i=0; i < pData->audioOut.count; ++i) { // Dry/Wet if (doDryWet) { const uint32_t c = isMono ? 0 : i; for (uint32_t k=0; k < frames; ++k) { # ifndef BUILD_BRIDGE if (k < pData->latency.frames && pData->latency.buffers != nullptr) bufValue = pData->latency.buffers[c][k]; else if (pData->latency.frames < frames) bufValue = fAudioInBuffers[c][k-pData->latency.frames]; else # endif bufValue = fAudioInBuffers[c][k]; fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet)); } } // Balance if (doBalance) { isPair = (i % 2 == 0); if (isPair) { CARLA_ASSERT(i+1 < pData->audioOut.count); carla_copyFloats(oldBufLeft, fAudioOutBuffers[i], frames); } float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f; float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f; for (uint32_t k=0; k < frames; ++k) { if (isPair) { // left fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL); fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR); } else { // right fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR; fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL; } } } // Volume (and buffer copy) { for (uint32_t k=0; k < frames; ++k) audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k] * pData->postProc.volume; } } } // End of Post-processing # ifndef BUILD_BRIDGE // -------------------------------------------------------------------------------------------------------- // Save latency values for next callback if (pData->latency.frames != 0 && pData->latency.buffers != nullptr) { CARLA_SAFE_ASSERT(timeOffset == 0); const uint32_t latframes = pData->latency.frames; if (latframes <= frames) { for (uint32_t i=0; i < pData->audioIn.count; ++i) carla_copyFloats(pData->latency.buffers[i], audioIn[i]+(frames-latframes), latframes); } else { const uint32_t diff = latframes - frames; for (uint32_t i=0, k; iaudioIn.count; ++i) { // push back buffer by 'frames' for (k=0; k < diff; ++k) pData->latency.buffers[i][k] = pData->latency.buffers[i][k+frames]; // put current input at the end for (uint32_t j=0; k < latframes; ++j, ++k) pData->latency.buffers[i][k] = audioIn[i][j]; } } } # endif #else // BUILD_BRIDGE_ALTERNATIVE_ARCH for (uint32_t i=0; i < pData->audioOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k]; } #endif // -------------------------------------------------------------------------------------------------------- pData->singleMutex.unlock(); return true; } void bufferSizeChanged(const uint32_t newBufferSize) override { CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize); carla_debug("CarlaPluginLADSPADSSI::bufferSizeChanged(%i) - start", newBufferSize); for (uint32_t i=0; i < pData->audioIn.count; ++i) { if (fAudioInBuffers[i] != nullptr) delete[] fAudioInBuffers[i]; fAudioInBuffers[i] = new float[newBufferSize]; carla_zeroFloats(fAudioInBuffers[i], newBufferSize); } for (uint32_t i=0; i < pData->audioOut.count; ++i) { if (fAudioOutBuffers[i] != nullptr) delete[] fAudioOutBuffers[i]; fAudioOutBuffers[i] = new float[newBufferSize]; carla_zeroFloats(fAudioOutBuffers[i], newBufferSize); } if (fExtraStereoBuffer[0] != nullptr) { delete[] fExtraStereoBuffer[0]; fExtraStereoBuffer[0] = nullptr; } if (fExtraStereoBuffer[1] != nullptr) { delete[] fExtraStereoBuffer[1]; fExtraStereoBuffer[1] = nullptr; } if (fForcedStereoIn && pData->audioOut.count == 2) { fExtraStereoBuffer[0] = new float[newBufferSize]; fExtraStereoBuffer[1] = new float[newBufferSize]; carla_zeroFloats(fExtraStereoBuffer[0], newBufferSize); carla_zeroFloats(fExtraStereoBuffer[1], newBufferSize); } reconnectAudioPorts(); carla_debug("CarlaPluginLADSPADSSI::bufferSizeChanged(%i) - end", newBufferSize); } void sampleRateChanged(const double newSampleRate) override { CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate); carla_debug("CarlaPluginLADSPADSSI::sampleRateChanged(%g) - start", newSampleRate); // TODO - handle UI stuff if (pData->active) deactivate(); const std::size_t instanceCount(fHandles.count()); if (fDescriptor->cleanup != nullptr) { for (LinkedList::Itenerator it = fHandles.begin2(); it.valid(); it.next()) { LADSPA_Handle const handle(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); try { fDescriptor->cleanup(handle); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup"); } } fHandles.clear(); for (std::size_t i=0; iactive) activate(); carla_debug("CarlaPluginLADSPADSSI::sampleRateChanged(%g) - end", newSampleRate); } void reconnectAudioPorts() const noexcept { if (fForcedStereoIn) { if (LADSPA_Handle const handle = fHandles.getFirst(nullptr)) { try { fDescriptor->connect_port(handle, pData->audioIn.ports[0].rindex, fAudioInBuffers[0]); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo input, first)"); } if (LADSPA_Handle const handle = fHandles.getLast(nullptr)) { try { fDescriptor->connect_port(handle, pData->audioIn.ports[1].rindex, fAudioInBuffers[1]); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo input, last)"); } } else { for (LinkedList::Itenerator it = fHandles.begin2(); it.valid(); it.next()) { LADSPA_Handle const handle(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); for (uint32_t i=0; i < pData->audioIn.count; ++i) { try { fDescriptor->connect_port(handle, pData->audioIn.ports[i].rindex, fAudioInBuffers[i]); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (audio input)"); } } } if (fForcedStereoOut) { if (LADSPA_Handle const handle = fHandles.getFirst(nullptr)) { try { fDescriptor->connect_port(handle, pData->audioOut.ports[0].rindex, fAudioOutBuffers[0]); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo output, first)"); } if (LADSPA_Handle const handle = fHandles.getLast(nullptr)) { try { fDescriptor->connect_port(handle, pData->audioOut.ports[1].rindex, fAudioOutBuffers[1]); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo output, last)"); } } else { for (LinkedList::Itenerator it = fHandles.begin2(); it.valid(); it.next()) { LADSPA_Handle const handle(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); for (uint32_t i=0; i < pData->audioOut.count; ++i) { try { fDescriptor->connect_port(handle, pData->audioOut.ports[i].rindex, fAudioOutBuffers[i]); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (audio output)"); } } } } // ------------------------------------------------------------------- // Plugin buffers void clearBuffers() noexcept override { carla_debug("CarlaPluginLADSPADSSI::clearBuffers() - start"); if (fAudioInBuffers != nullptr) { for (uint32_t i=0; i < pData->audioIn.count; ++i) { if (fAudioInBuffers[i] != nullptr) { delete[] fAudioInBuffers[i]; fAudioInBuffers[i] = nullptr; } } delete[] fAudioInBuffers; fAudioInBuffers = nullptr; } if (fAudioOutBuffers != nullptr) { for (uint32_t i=0; i < pData->audioOut.count; ++i) { if (fAudioOutBuffers[i] != nullptr) { delete[] fAudioOutBuffers[i]; fAudioOutBuffers[i] = nullptr; } } delete[] fAudioOutBuffers; fAudioOutBuffers = nullptr; } if (fExtraStereoBuffer[0] != nullptr) { delete[] fExtraStereoBuffer[0]; fExtraStereoBuffer[0] = nullptr; } if (fExtraStereoBuffer[1] != nullptr) { delete[] fExtraStereoBuffer[1]; fExtraStereoBuffer[1] = nullptr; } if (fParamBuffers != nullptr) { delete[] fParamBuffers; fParamBuffers = nullptr; } CarlaPlugin::clearBuffers(); carla_debug("CarlaPluginLADSPADSSI::clearBuffers() - end"); } #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) // ------------------------------------------------------------------- // OSC stuff void handleOscMessage(const char* const method, const int argc, const void* const argvx, const char* const types, const lo_message msg) override { const lo_address source(lo_message_get_source(msg)); CARLA_SAFE_ASSERT_RETURN(source != nullptr,); // protocol for DSSI UIs *must* be UDP CARLA_SAFE_ASSERT_RETURN(lo_address_get_protocol(source) == LO_UDP,); if (fOscData.source == nullptr) { // if no UI is registered yet only "configure" and "update" messages are valid CARLA_SAFE_ASSERT_RETURN(std::strcmp(method, "configure") == 0 || std::strcmp(method, "update") == 0,) } else { // make sure message source is the DSSI UI const char* const msghost = lo_address_get_hostname(source); const char* const msgport = lo_address_get_port(source); const char* const ourhost = lo_address_get_hostname(fOscData.source); const char* const ourport = lo_address_get_port(fOscData.source); CARLA_SAFE_ASSERT_RETURN(std::strcmp(msghost, ourhost) == 0,); CARLA_SAFE_ASSERT_RETURN(std::strcmp(msgport, ourport) == 0,); } const lo_arg* const* const argv(static_cast(argvx)); if (std::strcmp(method, "configure") == 0) return handleOscMessageConfigure(argc, argv, types); if (std::strcmp(method, "control") == 0) return handleOscMessageControl(argc, argv, types); if (std::strcmp(method, "program") == 0) return handleOscMessageProgram(argc, argv, types); if (std::strcmp(method, "midi") == 0) return handleOscMessageMIDI(argc, argv, types); if (std::strcmp(method, "update") == 0) return handleOscMessageUpdate(argc, argv, types, lo_message_get_source(msg)); if (std::strcmp(method, "exiting") == 0) return handleOscMessageExiting(); carla_stdout("CarlaPluginLADSPADSSI::handleOscMessage() - unknown method '%s'", method); } void handleOscMessageConfigure(const int argc, const lo_arg* const* const argv, const char* const types) { carla_debug("CarlaPluginLADSPADSSI::handleMsgConfigure()"); CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "ss"); const char* const key = (const char*)&argv[0]->s; const char* const value = (const char*)&argv[1]->s; setCustomData(CUSTOM_DATA_TYPE_STRING, key, value, false); } void handleOscMessageControl(const int argc, const lo_arg* const* const argv, const char* const types) { carla_debug("CarlaPluginLADSPADSSI::handleMsgControl()"); CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "if"); const int32_t rindex = argv[0]->i; const float value = argv[1]->f; setParameterValueByRealIndex(rindex, value, false, true, true); } void handleOscMessageProgram(const int argc, const lo_arg* const* const argv, const char* const types) { carla_debug("CarlaPluginLADSPADSSI::handleMsgProgram()"); CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "ii"); const int32_t bank = argv[0]->i; const int32_t program = argv[1]->i; CARLA_SAFE_ASSERT_RETURN(bank >= 0,); CARLA_SAFE_ASSERT_RETURN(program >= 0,); setMidiProgramById(static_cast(bank), static_cast(program), false, true, true); } void handleOscMessageMIDI(const int argc, const lo_arg* const* const argv, const char* const types) { carla_debug("CarlaPluginLADSPADSSI::handleMsgMidi()"); CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(1, "m"); if (getMidiInCount() == 0) { carla_stderr("CarlaPluginLADSPADSSI::handleMsgMidi() - received midi when plugin has no midi inputs"); return; } const uint8_t* const data = argv[0]->m; uint8_t status = data[1]; uint8_t channel = status & 0x0F; // Fix bad note-off if (MIDI_IS_STATUS_NOTE_ON(status) && data[3] == 0) status = MIDI_STATUS_NOTE_OFF; if (MIDI_IS_STATUS_NOTE_OFF(status)) { const uint8_t note = data[2]; CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); sendMidiSingleNote(channel, note, 0, false, true, true); } else if (MIDI_IS_STATUS_NOTE_ON(status)) { const uint8_t note = data[2]; const uint8_t velo = data[3]; CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); CARLA_SAFE_ASSERT_RETURN(velo < MAX_MIDI_VALUE,); sendMidiSingleNote(channel, note, velo, false, true, true); } } void handleOscMessageUpdate(const int argc, const lo_arg* const* const argv, const char* const types, const lo_address source) { carla_debug("CarlaPluginLADSPADSSI::handleMsgUpdate()"); CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(1, "s"); const char* const url = (const char*)&argv[0]->s; // FIXME - remove debug prints later carla_stdout("CarlaPluginLADSPADSSI::updateOscData(%p, \"%s\")", source, url); fOscData.clear(); const int proto = lo_address_get_protocol(source); { const char* host = lo_address_get_hostname(source); const char* port = lo_address_get_port(source); fOscData.source = lo_address_new_with_proto(proto, host, port); carla_stdout("CarlaPlugin::updateOscData() - source: host \"%s\", port \"%s\"", host, port); } { char* host = lo_url_get_hostname(url); char* port = lo_url_get_port(url); fOscData.path = carla_strdup_free(lo_url_get_path(url)); fOscData.target = lo_address_new_with_proto(proto, host, port); carla_stdout("CarlaPlugin::updateOscData() - target: host \"%s\", port \"%s\", path \"%s\"", host, port, fOscData.path); std::free(host); std::free(port); } osc_send_sample_rate(fOscData, static_cast(pData->engine->getSampleRate())); for (LinkedList::Itenerator it = pData->custom.begin2(); it.valid(); it.next()) { const CustomData& customData(it.getValue(kCustomDataFallback)); CARLA_SAFE_ASSERT_CONTINUE(customData.isValid()); if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_STRING) == 0) osc_send_configure(fOscData, customData.key, customData.value); } if (pData->prog.current >= 0) osc_send_program(fOscData, static_cast(pData->prog.current)); if (pData->midiprog.current >= 0) { const MidiProgramData& curMidiProg(pData->midiprog.getCurrent()); osc_send_program(fOscData, curMidiProg.bank, curMidiProg.program); } for (uint32_t i=0; i < pData->param.count; ++i) osc_send_control(fOscData, pData->param.data[i].rindex, getParameterValue(i)); #ifndef BUILD_BRIDGE if (pData->engine->getOptions().frontendWinId != 0) pData->transientTryCounter = 1; #endif carla_stdout("CarlaPluginLADSPADSSI::updateOscData() - done"); } void handleOscMessageExiting() { carla_debug("CarlaPluginLADSPADSSI::handleMsgExiting()"); // hide UI showCustomUI(false); // tell frontend pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); } // ------------------------------------------------------------------- // Post-poned UI Stuff void uiParameterChange(const uint32_t index, const float value) noexcept override { CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,); if (fOscData.target == nullptr) return; osc_send_control(fOscData, pData->param.data[index].rindex, value); } void uiMidiProgramChange(const uint32_t index) noexcept override { CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,); if (fOscData.target == nullptr) return; osc_send_program(fOscData, pData->midiprog.data[index].bank, pData->midiprog.data[index].program); } void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override { CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,); if (fOscData.target == nullptr) return; #if 0 uint8_t midiData[4]; midiData[0] = 0; midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); midiData[2] = note; midiData[3] = velo; osc_send_midi(fOscData, midiData); #endif } void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override { CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); if (fOscData.target == nullptr) return; #if 0 uint8_t midiData[4]; midiData[0] = 0; midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); midiData[2] = note; midiData[3] = 0; osc_send_midi(fOscData, midiData); #endif } #endif // HAVE_LIBLO && !BUILD_BRIDGE // ------------------------------------------------------------------- const void* getNativeDescriptor() const noexcept override { return fDssiDescriptor != nullptr ? (const void*)fDssiDescriptor : (const void*)fDescriptor; } const void* getExtraStuff() const noexcept override { if (fDssiDescriptor != nullptr) { #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) return fUiFilename; #else return nullptr; #endif } return fRdfDescriptor; } #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) uintptr_t getUiBridgeProcessId() const noexcept override { return fThreadUI.getProcessId(); } #endif // ------------------------------------------------------------------- bool initLADSPA(const char* const filename, const char* name, const char* const label, const uint options, const LADSPA_RDF_Descriptor* const rdfDescriptor) { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); // --------------------------------------------------------------- // first checks if (pData->client != nullptr) { pData->engine->setLastError("Plugin client is already registered"); return false; } if (filename == nullptr || filename[0] == '\0') { pData->engine->setLastError("null filename"); return false; } // --------------------------------------------------------------- // open DLL if (! pData->libOpen(filename)) { pData->engine->setLastError(pData->libError(filename)); return false; } // --------------------------------------------------------------- // get DLL main entry const LADSPA_Descriptor_Function descFn = pData->libSymbol("ladspa_descriptor"); if (descFn == nullptr) { pData->engine->setLastError("Could not find the LASDPA Descriptor in the plugin library"); return false; } // --------------------------------------------------------------- // get descriptor that matches label // if label is null, get first valid plugin const bool nullLabel = (label == nullptr || label[0] == '\0'); for (ulong d=0;; ++d) { try { fDescriptor = descFn(d); } catch(...) { carla_stderr2("Caught exception when trying to get LADSPA descriptor"); fDescriptor = nullptr; break; } if (fDescriptor == nullptr) break; if (fDescriptor->Label == nullptr || fDescriptor->Label[0] == '\0') { carla_stderr2("WARNING - Got an invalid label, will not use this plugin"); fDescriptor = nullptr; break; } if (fDescriptor->run == nullptr) { carla_stderr2("WARNING - Plugin has no run, cannot use it"); fDescriptor = nullptr; break; } if (nullLabel || std::strcmp(fDescriptor->Label, label) == 0) break; } if (fDescriptor == nullptr) { pData->engine->setLastError("Could not find the requested plugin label in the plugin library"); return false; } return init2(filename, name, options, rdfDescriptor); } bool initDSSI(const char* const filename, const char* name, const char* const label, const uint options) { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); // --------------------------------------------------------------- // first checks if (pData->client != nullptr) { pData->engine->setLastError("Plugin client is already registered"); return false; } if (filename == nullptr || filename[0] == '\0') { pData->engine->setLastError("null filename"); return false; } // --------------------------------------------------------------- // open DLL if (! pData->libOpen(filename)) { pData->engine->setLastError(pData->libError(filename)); return false; } // --------------------------------------------------------------- // get DLL main entry const DSSI_Descriptor_Function descFn = pData->libSymbol("dssi_descriptor"); if (descFn == nullptr) { pData->engine->setLastError("Could not find the DSSI Descriptor in the plugin library"); return false; } // --------------------------------------------------------------- // get descriptor that matches label // if label is null, get first valid plugin const bool nullLabel = (label == nullptr || label[0] == '\0'); for (ulong d=0;; ++d) { try { fDssiDescriptor = descFn(d); } catch(...) { carla_stderr2("Caught exception when trying to get DSSI descriptor"); fDescriptor = nullptr; fDssiDescriptor = nullptr; break; } if (fDssiDescriptor == nullptr) break; fDescriptor = fDssiDescriptor->LADSPA_Plugin; if (fDescriptor == nullptr) { carla_stderr2("WARNING - Missing LADSPA interface, will not use this plugin"); fDssiDescriptor = nullptr; break; } if (fDescriptor->Label == nullptr || fDescriptor->Label[0] == '\0') { carla_stderr2("WARNING - Got an invalid label, will not use this plugin"); fDescriptor = nullptr; fDssiDescriptor = nullptr; break; } if (fDescriptor->run == nullptr) { carla_stderr2("WARNING - Plugin has no run, cannot use it"); fDescriptor = nullptr; fDssiDescriptor = nullptr; break; } if (nullLabel || std::strcmp(fDescriptor->Label, label) == 0) break; } if (fDescriptor == nullptr || fDssiDescriptor == nullptr) { pData->engine->setLastError("Could not find the requested plugin label in the plugin library"); return false; } // --------------------------------------------------------------- // check if uses global instance if (fDssiDescriptor->run_synth == nullptr && fDssiDescriptor->run_multiple_synths != nullptr) { pData->engine->setLastError("This plugin requires run_multiple_synths which is not supported"); return false; } return init2(filename, name, options, nullptr); } bool init2(const char* const filename, const char* name, const uint options, const LADSPA_RDF_Descriptor* const rdfDescriptor) { // --------------------------------------------------------------- // check for fixed buffer size requirement fNeedsFixedBuffers = CarlaString(filename).contains("dssi-vst", true); if (fNeedsFixedBuffers && ! pData->engine->usesConstantBufferSize()) { pData->engine->setLastError("Cannot use this plugin under the current engine.\n" "The plugin requires a fixed block size which is not possible right now."); return false; } // --------------------------------------------------------------- // get info if (is_ladspa_rdf_descriptor_valid(rdfDescriptor, fDescriptor)) fRdfDescriptor = ladspa_rdf_dup(rdfDescriptor); if (name == nullptr || name[0] == '\0') { /**/ if (fRdfDescriptor != nullptr && fRdfDescriptor->Title != nullptr && fRdfDescriptor->Title[0] != '\0') name = fRdfDescriptor->Title; else if (fDescriptor->Name != nullptr && fDescriptor->Name[0] != '\0') name = fDescriptor->Name; else name = fDescriptor->Label; } pData->name = pData->engine->getUniquePluginName(name); pData->filename = carla_strdup(filename); // --------------------------------------------------------------- // register client pData->client = pData->engine->addClient(this); if (pData->client == nullptr || ! pData->client->isOk()) { pData->engine->setLastError("Failed to register plugin client"); return false; } // --------------------------------------------------------------- // initialize plugin if (! addInstance()) return false; // --------------------------------------------------------------- // find latency port index for (uint32_t i=0, iCtrl=0, count=getSafePortCount(); iPortDescriptors[i]); if (! LADSPA_IS_PORT_CONTROL(portType)) continue; const uint32_t index(iCtrl++); if (! LADSPA_IS_PORT_OUTPUT(portType)) continue; const char* const portName(fDescriptor->PortNames[i]); CARLA_SAFE_ASSERT_BREAK(portName != nullptr); if (std::strcmp(portName, "latency") == 0 || std::strcmp(portName, "_latency") == 0) { fLatencyIndex = static_cast(index); break; } } // --------------------------------------------------------------- // check for custom data extension if (fDssiDescriptor != nullptr && fDssiDescriptor->configure != nullptr) { if (char* const error = fDssiDescriptor->configure(fHandles.getFirst(nullptr), DSSI_CUSTOMDATA_EXTENSION_KEY, "")) { if (std::strcmp(error, "true") == 0 && fDssiDescriptor->get_custom_data != nullptr && fDssiDescriptor->set_custom_data != nullptr) fUsesCustomData = true; std::free(error); } } // --------------------------------------------------------------- // get engine options const EngineOptions& opts(pData->engine->getOptions()); #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) // --------------------------------------------------------------- // check for gui if (opts.oscEnabled && opts.oscPortUDP >= 0) { if (const char* const guiFilename = find_dssi_ui(filename, fDescriptor->Label)) { fUiFilename = guiFilename; fThreadUI.setData(guiFilename, fDescriptor->Label); } } #endif // --------------------------------------------------------------- // set options pData->options = 0x0; /**/ if (fLatencyIndex >= 0 || fNeedsFixedBuffers) pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; else if (options & PLUGIN_OPTION_FIXED_BUFFERS) pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; /**/ if (opts.forceStereo) pData->options |= PLUGIN_OPTION_FORCE_STEREO; else if (options & PLUGIN_OPTION_FORCE_STEREO) pData->options |= PLUGIN_OPTION_FORCE_STEREO; if (fDssiDescriptor != nullptr) { if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr) if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES)) pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; if (fUsesCustomData) if (isPluginOptionEnabled(options, PLUGIN_OPTION_USE_CHUNKS)) pData->options |= PLUGIN_OPTION_USE_CHUNKS; if (fDssiDescriptor->run_synth != nullptr) { if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)) pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)) pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND)) pData->options |= PLUGIN_OPTION_SEND_PITCHBEND; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF)) pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; } } return true; } // ------------------------------------------------------------------- private: LinkedList fHandles; const LADSPA_Descriptor* fDescriptor; const DSSI_Descriptor* fDssiDescriptor; const LADSPA_RDF_Descriptor* fRdfDescriptor; float** fAudioInBuffers; float** fAudioOutBuffers; float* fExtraStereoBuffer[2]; // used only if forcedStereoIn and audioOut == 2 float* fParamBuffers; snd_seq_event_t fMidiEvents[kPluginMaxMidiEvents]; int32_t fLatencyIndex; // -1 if invalid bool fForcedStereoIn; bool fForcedStereoOut; bool fNeedsFixedBuffers; bool fUsesCustomData; #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) CarlaOscData fOscData; CarlaThreadDSSIUI fThreadUI; const char* fUiFilename; #endif // ------------------------------------------------------------------- bool addInstance() { LADSPA_Handle handle; try { handle = fDescriptor->instantiate(fDescriptor, static_cast(pData->engine->getSampleRate())); } CARLA_SAFE_EXCEPTION_RETURN_ERR("LADSPA/DSSI instantiate", "Plugin failed to initialize"); for (uint32_t i=0, count=pData->param.count; iparam.data[i].rindex); CARLA_SAFE_ASSERT_CONTINUE(rindex >= 0); try { fDescriptor->connect_port(handle, static_cast(rindex), &fParamBuffers[i]); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port"); } if (fHandles.append(handle)) return true; try { fDescriptor->cleanup(handle); } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup"); pData->engine->setLastError("Out of memory"); return false; } uint32_t getSafePortCount() const noexcept { if (fDescriptor->PortCount == 0) return 0; CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortDescriptors != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortRangeHints != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames != nullptr, 0); return static_cast(fDescriptor->PortCount); } bool getSeparatedParameterNameOrUnit(const char* const paramName, char* const strBuf, const bool wantName) const noexcept { if (_getSeparatedParameterNameOrUnitImpl(paramName, strBuf, wantName, true)) return true; if (_getSeparatedParameterNameOrUnitImpl(paramName, strBuf, wantName, false)) return true; return false; } static bool _getSeparatedParameterNameOrUnitImpl(const char* const paramName, char* const strBuf, const bool wantName, const bool useBracket) noexcept { const char* const sepBracketStart = std::strstr(paramName, useBracket ? " [" : " ("); if (sepBracketStart == nullptr) return false; const char* const sepBracketEnd = std::strstr(sepBracketStart, useBracket ? "]" : ")"); if (sepBracketEnd == nullptr) return false; const std::size_t unitSize = static_cast(sepBracketEnd-sepBracketStart-2); if (unitSize > 7) // very unlikely to have such big unit return false; const std::size_t sepIndex = std::strlen(paramName)-unitSize-3; // just in case if (sepIndex > STR_MAX-3) return false; if (wantName) { std::strncpy(strBuf, paramName, sepIndex); strBuf[sepIndex] = '\0'; } else { std::strncpy(strBuf, paramName+(sepIndex+2), unitSize); strBuf[unitSize] = '\0'; } return true; } // ------------------------------------------------------------------- CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginLADSPADSSI) }; // ------------------------------------------------------------------------------------------------------------------- CarlaPlugin* CarlaPlugin::newLADSPA(const Initializer& init, const LADSPA_RDF_Descriptor* const rdfDescriptor) { carla_debug("CarlaPlugin::newLADSPA({%p, \"%s\", \"%s\", \"%s\", " P_INT64 ", %x}, %p)", init.engine, init.filename, init.name, init.label, init.uniqueId, init.options, rdfDescriptor); CarlaPluginLADSPADSSI* const plugin(new CarlaPluginLADSPADSSI(init.engine, init.id)); if (! plugin->initLADSPA(init.filename, init.name, init.label, init.options, rdfDescriptor)) { delete plugin; return nullptr; } return plugin; } CarlaPlugin* CarlaPlugin::newDSSI(const Initializer& init) { carla_debug("CarlaPlugin::newDSSI({%p, \"%s\", \"%s\", \"%s\", " P_INT64 ", %x})", init.engine, init.filename, init.name, init.label, init.uniqueId, init.options); CarlaPluginLADSPADSSI* const plugin(new CarlaPluginLADSPADSSI(init.engine, init.id)); if (! plugin->initDSSI(init.filename, init.name, init.label, init.options)) { delete plugin; return nullptr; } return plugin; } // ------------------------------------------------------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/plugin/CarlaPluginLV2.cpp000066400000000000000000010371501364475620200220340ustar00rootroot00000000000000/* * Carla LV2 Plugin * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ // testing macros // #define LV2_UIS_ONLY_BRIDGES // #define LV2_UIS_ONLY_INPROCESS #include "CarlaPluginInternal.hpp" #include "CarlaEngine.hpp" #include "CarlaLv2Utils.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaBase64Utils.hpp" #include "CarlaEngineUtils.hpp" #include "CarlaPipeUtils.hpp" #include "CarlaPluginUI.hpp" #include "CarlaScopeUtils.hpp" #include "Lv2AtomRingBuffer.hpp" #include "../modules/lilv/config/lilv_config.h" extern "C" { #include "rtmempool/rtmempool-lv2.h" } #include "water/files/File.h" #include "water/misc/Time.h" #include #include using water::File; #define URI_CARLA_ATOM_WORKER_IN "http://kxstudio.sf.net/ns/carla/atomWorkerIn" #define URI_CARLA_ATOM_WORKER_RESP "http://kxstudio.sf.net/ns/carla/atomWorkerResp" CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- // Fallback data static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr }; static /* */ CustomData kCustomDataFallbackNC = { nullptr, nullptr, nullptr }; static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 }; static const char* const kUnmapFallback = "urn:null"; // ------------------------------------------------------------------------------------------------------------------- // Maximum default buffer size const uint MAX_DEFAULT_BUFFER_SIZE = 8192; // 0x2000 // Extra Plugin Hints const uint PLUGIN_HAS_EXTENSION_OPTIONS = 0x01000; const uint PLUGIN_HAS_EXTENSION_PROGRAMS = 0x02000; const uint PLUGIN_HAS_EXTENSION_STATE = 0x04000; const uint PLUGIN_HAS_EXTENSION_WORKER = 0x08000; const uint PLUGIN_HAS_EXTENSION_INLINE_DISPLAY = 0x10000; const uint PLUGIN_HAS_EXTENSION_MIDNAM = 0x20000; // LV2 Event Data/Types const uint CARLA_EVENT_DATA_ATOM = 0x01; const uint CARLA_EVENT_DATA_EVENT = 0x02; const uint CARLA_EVENT_DATA_MIDI_LL = 0x04; const uint CARLA_EVENT_TYPE_MESSAGE = 0x10; // unused const uint CARLA_EVENT_TYPE_MIDI = 0x20; const uint CARLA_EVENT_TYPE_TIME = 0x40; // LV2 URI Map Ids enum CarlaLv2URIDs { kUridNull = 0, kUridAtomBlank, kUridAtomBool, kUridAtomChunk, kUridAtomDouble, kUridAtomEvent, kUridAtomFloat, kUridAtomInt, kUridAtomLiteral, kUridAtomLong, kUridAtomNumber, kUridAtomObject, kUridAtomPath, kUridAtomProperty, kUridAtomResource, kUridAtomSequence, kUridAtomSound, kUridAtomString, kUridAtomTuple, kUridAtomURI, kUridAtomURID, kUridAtomVector, kUridAtomTransferAtom, kUridAtomTransferEvent, kUridBufMaxLength, kUridBufMinLength, kUridBufNominalLength, kUridBufSequenceSize, kUridLogError, kUridLogNote, kUridLogTrace, kUridLogWarning, kUridPatchSet, kUridPatchPoperty, kUridPatchValue, // time base type kUridTimePosition, // time values kUridTimeBar, kUridTimeBarBeat, kUridTimeBeat, kUridTimeBeatUnit, kUridTimeBeatsPerBar, kUridTimeBeatsPerMinute, kUridTimeFrame, kUridTimeFramesPerSecond, kUridTimeSpeed, kUridTimeTicksPerBeat, kUridMidiEvent, kUridParamSampleRate, // ui stuff kUridBackgroundColor, kUridForegroundColor, kUridScaleFactor, kUridWindowTitle, // custom carla props kUridCarlaAtomWorkerIn, kUridCarlaAtomWorkerResp, kUridCarlaTransientWindowId, // count kUridCount }; // LV2 Feature Ids enum CarlaLv2Features { // DSP features kFeatureIdBufSizeBounded = 0, kFeatureIdBufSizeFixed, kFeatureIdBufSizePowerOf2, kFeatureIdEvent, kFeatureIdHardRtCapable, kFeatureIdInPlaceBroken, kFeatureIdIsLive, kFeatureIdLogs, kFeatureIdOptions, kFeatureIdPrograms, kFeatureIdResizePort, kFeatureIdRtMemPool, kFeatureIdRtMemPoolOld, kFeatureIdStateMakePath, kFeatureIdStateMapPath, kFeatureIdStrictBounds, kFeatureIdUriMap, kFeatureIdUridMap, kFeatureIdUridUnmap, kFeatureIdWorker, kFeatureIdInlineDisplay, kFeatureIdMidnam, kFeatureCountPlugin, // UI features kFeatureIdUiDataAccess = kFeatureCountPlugin, kFeatureIdUiInstanceAccess, kFeatureIdUiIdleInterface, kFeatureIdUiFixedSize, kFeatureIdUiMakeResident, kFeatureIdUiMakeResident2, kFeatureIdUiNoUserResize, kFeatureIdUiParent, kFeatureIdUiPortMap, kFeatureIdUiPortSubscribe, kFeatureIdUiResize, kFeatureIdUiRequestValue, kFeatureIdUiTouch, kFeatureIdExternalUi, kFeatureIdExternalUiOld, kFeatureCountAll }; // ------------------------------------------------------------------------------------------------------------------- struct Lv2EventData { uint32_t type; uint32_t rindex; CarlaEngineEventPort* port; union { LV2_Atom_Buffer* atom; LV2_Event_Buffer* event; LV2_MIDI midi; }; Lv2EventData() noexcept : type(0x0), rindex(0), port(nullptr) {} ~Lv2EventData() noexcept { if (port != nullptr) { delete port; port = nullptr; } const uint32_t rtype(type); type = 0x0; if (rtype & CARLA_EVENT_DATA_ATOM) { CARLA_SAFE_ASSERT_RETURN(atom != nullptr,); std::free(atom); atom = nullptr; } else if (rtype & CARLA_EVENT_DATA_EVENT) { CARLA_SAFE_ASSERT_RETURN(event != nullptr,); std::free(event); event = nullptr; } else if (rtype & CARLA_EVENT_DATA_MIDI_LL) { CARLA_SAFE_ASSERT_RETURN(midi.data != nullptr,); delete[] midi.data; midi.data = nullptr; } } CARLA_DECLARE_NON_COPY_STRUCT(Lv2EventData) }; struct CarlaPluginLV2EventData { uint32_t count; Lv2EventData* data; Lv2EventData* ctrl; // default port, either this->data[x] or pData->portIn/Out uint32_t ctrlIndex; CarlaPluginLV2EventData() noexcept : count(0), data(nullptr), ctrl(nullptr), ctrlIndex(0) {} ~CarlaPluginLV2EventData() noexcept { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT(data == nullptr); CARLA_SAFE_ASSERT(ctrl == nullptr); CARLA_SAFE_ASSERT_INT(ctrlIndex == 0, ctrlIndex); } void createNew(const uint32_t newCount) { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT_INT(ctrlIndex == 0, ctrlIndex); CARLA_SAFE_ASSERT_RETURN(data == nullptr,); CARLA_SAFE_ASSERT_RETURN(ctrl == nullptr,); CARLA_SAFE_ASSERT_RETURN(newCount > 0,); data = new Lv2EventData[newCount]; count = newCount; ctrl = nullptr; ctrlIndex = 0; } void clear() noexcept { if (data != nullptr) { for (uint32_t i=0; i < count; ++i) { if (data[i].port != nullptr && ctrl != nullptr && data[i].port == ctrl->port) data[i].port = nullptr; } delete[] data; data = nullptr; } count = 0; ctrl = nullptr; ctrlIndex = 0; } void initBuffers() const noexcept { for (uint32_t i=0; i < count; ++i) { if (data[i].port != nullptr && (ctrl == nullptr || data[i].port != ctrl->port)) data[i].port->initBuffer(); } } CARLA_DECLARE_NON_COPY_STRUCT(CarlaPluginLV2EventData) }; // ------------------------------------------------------------------------------------------------------------------- struct CarlaPluginLV2Options { enum OptIndex { MaxBlockLenth = 0, MinBlockLenth, NominalBlockLenth, SequenceSize, SampleRate, TransientWinId, BackgroundColor, ForegroundColor, ScaleFactor, WindowTitle, Null, Count }; int maxBufferSize; int minBufferSize; int nominalBufferSize; int sequenceSize; float sampleRate; int64_t transientWinId; uint32_t bgColor; uint32_t fgColor; float uiScale; const char* windowTitle; LV2_Options_Option opts[Count]; CarlaPluginLV2Options() noexcept : maxBufferSize(0), minBufferSize(0), nominalBufferSize(0), sequenceSize(MAX_DEFAULT_BUFFER_SIZE), sampleRate(0.0), transientWinId(0), bgColor(0x000000ff), fgColor(0xffffffff), uiScale(1.0f), windowTitle(nullptr) { LV2_Options_Option& optMaxBlockLenth(opts[MaxBlockLenth]); optMaxBlockLenth.context = LV2_OPTIONS_INSTANCE; optMaxBlockLenth.subject = 0; optMaxBlockLenth.key = kUridBufMaxLength; optMaxBlockLenth.size = sizeof(int); optMaxBlockLenth.type = kUridAtomInt; optMaxBlockLenth.value = &maxBufferSize; LV2_Options_Option& optMinBlockLenth(opts[MinBlockLenth]); optMinBlockLenth.context = LV2_OPTIONS_INSTANCE; optMinBlockLenth.subject = 0; optMinBlockLenth.key = kUridBufMinLength; optMinBlockLenth.size = sizeof(int); optMinBlockLenth.type = kUridAtomInt; optMinBlockLenth.value = &minBufferSize; LV2_Options_Option& optNominalBlockLenth(opts[NominalBlockLenth]); optNominalBlockLenth.context = LV2_OPTIONS_INSTANCE; optNominalBlockLenth.subject = 0; optNominalBlockLenth.key = kUridBufNominalLength; optNominalBlockLenth.size = sizeof(int); optNominalBlockLenth.type = kUridAtomInt; optNominalBlockLenth.value = &nominalBufferSize; LV2_Options_Option& optSequenceSize(opts[SequenceSize]); optSequenceSize.context = LV2_OPTIONS_INSTANCE; optSequenceSize.subject = 0; optSequenceSize.key = kUridBufSequenceSize; optSequenceSize.size = sizeof(int); optSequenceSize.type = kUridAtomInt; optSequenceSize.value = &sequenceSize; LV2_Options_Option& optBackgroundColor(opts[BackgroundColor]); optBackgroundColor.context = LV2_OPTIONS_INSTANCE; optBackgroundColor.subject = 0; optBackgroundColor.key = kUridBackgroundColor; optBackgroundColor.size = sizeof(int32_t); optBackgroundColor.type = kUridAtomInt; optBackgroundColor.value = &bgColor; LV2_Options_Option& optForegroundColor(opts[ForegroundColor]); optForegroundColor.context = LV2_OPTIONS_INSTANCE; optForegroundColor.subject = 0; optForegroundColor.key = kUridForegroundColor; optForegroundColor.size = sizeof(int32_t); optForegroundColor.type = kUridAtomInt; optForegroundColor.value = &fgColor; LV2_Options_Option& optScaleFactor(opts[ScaleFactor]); optScaleFactor.context = LV2_OPTIONS_INSTANCE; optScaleFactor.subject = 0; optScaleFactor.key = kUridScaleFactor; optScaleFactor.size = sizeof(float); optScaleFactor.type = kUridAtomFloat; optScaleFactor.value = &uiScale; LV2_Options_Option& optSampleRate(opts[SampleRate]); optSampleRate.context = LV2_OPTIONS_INSTANCE; optSampleRate.subject = 0; optSampleRate.key = kUridParamSampleRate; optSampleRate.size = sizeof(float); optSampleRate.type = kUridAtomFloat; optSampleRate.value = &sampleRate; LV2_Options_Option& optTransientWinId(opts[TransientWinId]); optTransientWinId.context = LV2_OPTIONS_INSTANCE; optTransientWinId.subject = 0; optTransientWinId.key = kUridCarlaTransientWindowId; optTransientWinId.size = sizeof(int64_t); optTransientWinId.type = kUridAtomLong; optTransientWinId.value = &transientWinId; LV2_Options_Option& optWindowTitle(opts[WindowTitle]); optWindowTitle.context = LV2_OPTIONS_INSTANCE; optWindowTitle.subject = 0; optWindowTitle.key = kUridWindowTitle; optWindowTitle.size = 0; optWindowTitle.type = kUridAtomString; optWindowTitle.value = nullptr; LV2_Options_Option& optNull(opts[Null]); optNull.context = LV2_OPTIONS_INSTANCE; optNull.subject = 0; optNull.key = kUridNull; optNull.size = 0; optNull.type = kUridNull; optNull.value = nullptr; } ~CarlaPluginLV2Options() noexcept { LV2_Options_Option& optWindowTitle(opts[WindowTitle]); optWindowTitle.size = 0; optWindowTitle.value = nullptr; if (windowTitle != nullptr) { delete[] windowTitle; windowTitle = nullptr; } } CARLA_DECLARE_NON_COPY_STRUCT(CarlaPluginLV2Options); }; // ------------------------------------------------------------------------------------------------------------------- class CarlaPluginLV2; class CarlaPipeServerLV2 : public CarlaPipeServer { public: enum UiState { UiNone = 0, UiHide, UiShow, UiCrashed }; CarlaPipeServerLV2(CarlaEngine* const engine, CarlaPluginLV2* const plugin) : kEngine(engine), kPlugin(plugin), fFilename(), fPluginURI(), fUiURI(), fUiState(UiNone) {} ~CarlaPipeServerLV2() noexcept override { CARLA_SAFE_ASSERT_INT(fUiState == UiNone, fUiState); } UiState getAndResetUiState() noexcept { const UiState uiState(fUiState); fUiState = UiNone; return uiState; } void setData(const char* const filename, const char* const pluginURI, const char* const uiURI) noexcept { fFilename = filename; fPluginURI = pluginURI; fUiURI = uiURI; } bool startPipeServer(const int size) noexcept { char sampleRateStr[32]; { const CarlaScopedLocale csl; std::snprintf(sampleRateStr, 31, "%.12g", kEngine->getSampleRate()); } sampleRateStr[31] = '\0'; const ScopedEngineEnvironmentLocker _seel(kEngine); const CarlaScopedEnvVar _sev1("LV2_PATH", kEngine->getOptions().pathLV2); #ifdef CARLA_OS_LINUX const CarlaScopedEnvVar _sev2("LD_PRELOAD", nullptr); #endif carla_setenv("CARLA_SAMPLE_RATE", sampleRateStr); return CarlaPipeServer::startPipeServer(fFilename, fPluginURI, fUiURI, size); } void writeUiTitleMessage(const char* const title) const noexcept { CARLA_SAFE_ASSERT_RETURN(title != nullptr && title[0] != '\0',); const CarlaMutexLocker cml(getPipeLock()); if (! _writeMsgBuffer("uiTitle\n", 8)) return; if (! writeAndFixMessage(title)) return; flushMessages(); } protected: // returns true if msg was handled bool msgReceived(const char* const msg) noexcept override; private: CarlaEngine* const kEngine; CarlaPluginLV2* const kPlugin; CarlaString fFilename; CarlaString fPluginURI; CarlaString fUiURI; UiState fUiState; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPipeServerLV2) }; // ------------------------------------------------------------------------------------------------------------------- class CarlaPluginLV2 : public CarlaPlugin, private CarlaPluginUI::Callback { public: CarlaPluginLV2(CarlaEngine* const engine, const uint id) : CarlaPlugin(engine, id), fHandle(nullptr), fHandle2(nullptr), fDescriptor(nullptr), fRdfDescriptor(nullptr), fAudioInBuffers(nullptr), fAudioOutBuffers(nullptr), fCvInBuffers(nullptr), fCvOutBuffers(nullptr), fParamBuffers(nullptr), fNeedsFixedBuffers(false), fNeedsUiClose(false), fInlineDisplayNeedsRedraw(false), fInlineDisplayLastRedrawTime(0), fLatencyIndex(-1), fStrictBounds(-1), fAtomBufferEvIn(), fAtomBufferUiOut(), fAtomBufferWorkerIn(), fAtomBufferWorkerResp(), fAtomForge(), fAtomBufferUiOutTmpData(nullptr), fAtomBufferWorkerInTmpData(nullptr), fEventsIn(), fEventsOut(), fLv2Options(), fPipeServer(engine, this), fCustomURIDs(kUridCount, std::string("urn:null")), fFirstActive(true), fLastStateChunk(nullptr), fLastTimeInfo(), fFilePathURI(), fExt(), fUI() { carla_debug("CarlaPluginLV2::CarlaPluginLV2(%p, %i)", engine, id); CARLA_SAFE_ASSERT(fCustomURIDs.size() == kUridCount); carla_zeroPointers(fFeatures, kFeatureCountAll+1); #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdeprecated-declarations" #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif fAtomForge.Blank = kUridAtomBlank; fAtomForge.Bool = kUridAtomBool; fAtomForge.Chunk = kUridAtomChunk; fAtomForge.Double = kUridAtomDouble; fAtomForge.Float = kUridAtomFloat; fAtomForge.Int = kUridAtomInt; fAtomForge.Literal = kUridAtomLiteral; fAtomForge.Long = kUridAtomLong; fAtomForge.Object = kUridAtomObject; fAtomForge.Path = kUridAtomPath; fAtomForge.Property = kUridAtomProperty; fAtomForge.Resource = kUridAtomResource; fAtomForge.Sequence = kUridAtomSequence; fAtomForge.String = kUridAtomString; fAtomForge.Tuple = kUridAtomTuple; fAtomForge.URI = kUridAtomURI; fAtomForge.URID = kUridAtomURID; fAtomForge.Vector = kUridAtomVector; #if defined(__clang__) # pragma clang diagnostic pop #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic pop #endif } ~CarlaPluginLV2() override { carla_debug("CarlaPluginLV2::~CarlaPluginLV2()"); fInlineDisplayNeedsRedraw = false; // close UI if (fUI.type != UI::TYPE_NULL) { showCustomUI(false); if (fUI.type == UI::TYPE_BRIDGE) { fPipeServer.stopPipeServer(pData->engine->getOptions().uiBridgesTimeout); } else { if (fFeatures[kFeatureIdUiDataAccess] != nullptr && fFeatures[kFeatureIdUiDataAccess]->data != nullptr) delete (LV2_Extension_Data_Feature*)fFeatures[kFeatureIdUiDataAccess]->data; if (fFeatures[kFeatureIdUiPortMap] != nullptr && fFeatures[kFeatureIdUiPortMap]->data != nullptr) delete (LV2UI_Port_Map*)fFeatures[kFeatureIdUiPortMap]->data; if (fFeatures[kFeatureIdUiRequestValue] != nullptr && fFeatures[kFeatureIdUiRequestValue]->data != nullptr) delete (LV2UI_Request_Value*)fFeatures[kFeatureIdUiRequestValue]->data; if (fFeatures[kFeatureIdUiResize] != nullptr && fFeatures[kFeatureIdUiResize]->data != nullptr) delete (LV2UI_Resize*)fFeatures[kFeatureIdUiResize]->data; if (fFeatures[kFeatureIdUiTouch] != nullptr && fFeatures[kFeatureIdUiTouch]->data != nullptr) delete (LV2UI_Touch*)fFeatures[kFeatureIdUiTouch]->data; if (fFeatures[kFeatureIdExternalUi] != nullptr && fFeatures[kFeatureIdExternalUi]->data != nullptr) delete (LV2_External_UI_Host*)fFeatures[kFeatureIdExternalUi]->data; fUI.descriptor = nullptr; pData->uiLibClose(); } #ifndef LV2_UIS_ONLY_BRIDGES if (fUI.window != nullptr) { delete fUI.window; fUI.window = nullptr; } #endif fUI.rdfDescriptor = nullptr; } pData->singleMutex.lock(); pData->masterMutex.lock(); if (pData->client != nullptr && pData->client->isActive()) pData->client->deactivate(); if (pData->active) { deactivate(); pData->active = false; } if (fDescriptor != nullptr) { if (fDescriptor->cleanup != nullptr) { if (fHandle != nullptr) fDescriptor->cleanup(fHandle); if (fHandle2 != nullptr) fDescriptor->cleanup(fHandle2); } fHandle = nullptr; fHandle2 = nullptr; fDescriptor = nullptr; } if (fRdfDescriptor != nullptr) { delete fRdfDescriptor; fRdfDescriptor = nullptr; } if (fFeatures[kFeatureIdEvent] != nullptr && fFeatures[kFeatureIdEvent]->data != nullptr) delete (LV2_Event_Feature*)fFeatures[kFeatureIdEvent]->data; if (fFeatures[kFeatureIdLogs] != nullptr && fFeatures[kFeatureIdLogs]->data != nullptr) delete (LV2_Log_Log*)fFeatures[kFeatureIdLogs]->data; if (fFeatures[kFeatureIdStateMakePath] != nullptr && fFeatures[kFeatureIdStateMakePath]->data != nullptr) delete (LV2_State_Make_Path*)fFeatures[kFeatureIdStateMakePath]->data; if (fFeatures[kFeatureIdStateMapPath] != nullptr && fFeatures[kFeatureIdStateMapPath]->data != nullptr) delete (LV2_State_Map_Path*)fFeatures[kFeatureIdStateMapPath]->data; if (fFeatures[kFeatureIdPrograms] != nullptr && fFeatures[kFeatureIdPrograms]->data != nullptr) delete (LV2_Programs_Host*)fFeatures[kFeatureIdPrograms]->data; if (fFeatures[kFeatureIdResizePort] != nullptr && fFeatures[kFeatureIdResizePort]->data != nullptr) delete (LV2_Resize_Port_Resize*)fFeatures[kFeatureIdResizePort]->data; if (fFeatures[kFeatureIdRtMemPool] != nullptr && fFeatures[kFeatureIdRtMemPool]->data != nullptr) delete (LV2_RtMemPool_Pool*)fFeatures[kFeatureIdRtMemPool]->data; if (fFeatures[kFeatureIdRtMemPoolOld] != nullptr && fFeatures[kFeatureIdRtMemPoolOld]->data != nullptr) delete (LV2_RtMemPool_Pool_Deprecated*)fFeatures[kFeatureIdRtMemPoolOld]->data; if (fFeatures[kFeatureIdUriMap] != nullptr && fFeatures[kFeatureIdUriMap]->data != nullptr) delete (LV2_URI_Map_Feature*)fFeatures[kFeatureIdUriMap]->data; if (fFeatures[kFeatureIdUridMap] != nullptr && fFeatures[kFeatureIdUridMap]->data != nullptr) delete (LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data; if (fFeatures[kFeatureIdUridUnmap] != nullptr && fFeatures[kFeatureIdUridUnmap]->data != nullptr) delete (LV2_URID_Unmap*)fFeatures[kFeatureIdUridUnmap]->data; if (fFeatures[kFeatureIdWorker] != nullptr && fFeatures[kFeatureIdWorker]->data != nullptr) delete (LV2_Worker_Schedule*)fFeatures[kFeatureIdWorker]->data; if (fFeatures[kFeatureIdInlineDisplay] != nullptr && fFeatures[kFeatureIdInlineDisplay]->data != nullptr) delete (LV2_Inline_Display*)fFeatures[kFeatureIdInlineDisplay]->data; for (uint32_t i=0; i < kFeatureCountAll; ++i) { if (fFeatures[i] != nullptr) { delete fFeatures[i]; fFeatures[i] = nullptr; } } if (fLastStateChunk != nullptr) { std::free(fLastStateChunk); fLastStateChunk = nullptr; } if (fAtomBufferUiOutTmpData != nullptr) { delete[] fAtomBufferUiOutTmpData; fAtomBufferUiOutTmpData = nullptr; } if (fAtomBufferWorkerInTmpData != nullptr) { delete[] fAtomBufferWorkerInTmpData; fAtomBufferWorkerInTmpData = nullptr; } clearBuffers(); } // ------------------------------------------------------------------- // Information (base) PluginType getType() const noexcept override { return PLUGIN_LV2; } PluginCategory getCategory() const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, CarlaPlugin::getCategory()); const LV2_Property cat1(fRdfDescriptor->Type[0]); const LV2_Property cat2(fRdfDescriptor->Type[1]); if (LV2_IS_DELAY(cat1, cat2)) return PLUGIN_CATEGORY_DELAY; if (LV2_IS_DISTORTION(cat1, cat2)) return PLUGIN_CATEGORY_OTHER; if (LV2_IS_DYNAMICS(cat1, cat2)) return PLUGIN_CATEGORY_DYNAMICS; if (LV2_IS_EQ(cat1, cat2)) return PLUGIN_CATEGORY_EQ; if (LV2_IS_FILTER(cat1, cat2)) return PLUGIN_CATEGORY_FILTER; if (LV2_IS_GENERATOR(cat1, cat2)) return PLUGIN_CATEGORY_SYNTH; if (LV2_IS_MODULATOR(cat1, cat2)) return PLUGIN_CATEGORY_MODULATOR; if (LV2_IS_REVERB(cat1, cat2)) return PLUGIN_CATEGORY_DELAY; if (LV2_IS_SIMULATOR(cat1, cat2)) return PLUGIN_CATEGORY_OTHER; if (LV2_IS_SPATIAL(cat1, cat2)) return PLUGIN_CATEGORY_OTHER; if (LV2_IS_SPECTRAL(cat1, cat2)) return PLUGIN_CATEGORY_UTILITY; if (LV2_IS_UTILITY(cat1, cat2)) return PLUGIN_CATEGORY_UTILITY; return CarlaPlugin::getCategory(); } uint32_t getLatencyInFrames() const noexcept override { if (fLatencyIndex < 0 || fParamBuffers == nullptr) return 0; const float latency(fParamBuffers[fLatencyIndex]); CARLA_SAFE_ASSERT_RETURN(latency >= 0.0f, 0); return static_cast(latency); } // ------------------------------------------------------------------- // Information (count) uint32_t getMidiInCount() const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0); uint32_t count = 0; for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i) { const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types); if (LV2_IS_PORT_INPUT(portTypes) && LV2_PORT_SUPPORTS_MIDI_EVENT(portTypes)) ++count; } return count; } uint32_t getMidiOutCount() const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0); uint32_t count = 0; for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i) { const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types); if (LV2_IS_PORT_OUTPUT(portTypes) && LV2_PORT_SUPPORTS_MIDI_EVENT(portTypes)) ++count; } return count; } uint32_t getParameterScalePointCount(const uint32_t parameterId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0); const int32_t rindex(pData->param.data[parameterId].rindex); if (rindex < static_cast(fRdfDescriptor->PortCount)) { const LV2_RDF_Port* const port(&fRdfDescriptor->Ports[rindex]); return port->ScalePointCount; } return 0; } // ------------------------------------------------------------------- // Information (current data) // nothing // ------------------------------------------------------------------- // Information (per-plugin data) uint getOptionsAvailable() const noexcept override { uint options = 0x0; // can't disable fixed buffers if using latency or MIDI output if (fLatencyIndex == -1 && getMidiOutCount() == 0 && ! fNeedsFixedBuffers) options |= PLUGIN_OPTION_FIXED_BUFFERS; // can't disable forced stereo if enabled in the engine if (pData->engine->getOptions().forceStereo) pass(); // if inputs or outputs are just 1, then yes we can force stereo else if ((pData->audioIn.count == 1 || pData->audioOut.count == 1) || fHandle2 != nullptr) options |= PLUGIN_OPTION_FORCE_STEREO; if (fExt.programs != nullptr) options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; if (getMidiInCount() != 0) { options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; options |= PLUGIN_OPTION_SEND_PITCHBEND; options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES; } return options; } float getParameterValue(const uint32_t parameterId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr, 0.0f); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f); if (pData->param.data[parameterId].type == PARAMETER_INPUT) { if (pData->param.data[parameterId].hints & PARAMETER_IS_STRICT_BOUNDS) pData->param.ranges[parameterId].fixValue(fParamBuffers[parameterId]); } else { if (fStrictBounds >= 0 && (pData->param.data[parameterId].hints & PARAMETER_IS_STRICT_BOUNDS) == 0) pData->param.ranges[parameterId].fixValue(fParamBuffers[parameterId]); } return fParamBuffers[parameterId]; } float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0.0f); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f); const int32_t rindex(pData->param.data[parameterId].rindex); if (rindex < static_cast(fRdfDescriptor->PortCount)) { const LV2_RDF_Port* const port(&fRdfDescriptor->Ports[rindex]); CARLA_SAFE_ASSERT_RETURN(scalePointId < port->ScalePointCount, 0.0f); const LV2_RDF_PortScalePoint* const portScalePoint(&port->ScalePoints[scalePointId]); return portScalePoint->Value; } return 0.0f; } bool getLabel(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor->URI != nullptr, false); std::strncpy(strBuf, fRdfDescriptor->URI, STR_MAX); return true; } bool getMaker(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); if (fRdfDescriptor->Author != nullptr) { std::strncpy(strBuf, fRdfDescriptor->Author, STR_MAX); return true; } return false; } bool getCopyright(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); if (fRdfDescriptor->License != nullptr) { std::strncpy(strBuf, fRdfDescriptor->License, STR_MAX); return true; } return false; } bool getRealName(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); if (fRdfDescriptor->Name != nullptr) { std::strncpy(strBuf, fRdfDescriptor->Name, STR_MAX); return true; } return false; } bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); int32_t rindex = pData->param.data[parameterId].rindex; CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false); if (rindex < static_cast(fRdfDescriptor->PortCount)) { std::strncpy(strBuf, fRdfDescriptor->Ports[rindex].Name, STR_MAX); return true; } rindex -= static_cast(fRdfDescriptor->PortCount); if (rindex < static_cast(fRdfDescriptor->ParameterCount)) { std::strncpy(strBuf, fRdfDescriptor->Parameters[rindex].Label, STR_MAX); return true; } return CarlaPlugin::getParameterName(parameterId, strBuf); } bool getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); int32_t rindex = pData->param.data[parameterId].rindex; CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false); if (rindex < static_cast(fRdfDescriptor->PortCount)) { std::strncpy(strBuf, fRdfDescriptor->Ports[rindex].Symbol, STR_MAX); return true; } rindex -= static_cast(fRdfDescriptor->PortCount); if (rindex < static_cast(fRdfDescriptor->ParameterCount)) { std::strncpy(strBuf, fRdfDescriptor->Parameters[rindex].URI, STR_MAX); return true; } return CarlaPlugin::getParameterSymbol(parameterId, strBuf); } bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); LV2_RDF_PortUnit* portUnit = nullptr; int32_t rindex = pData->param.data[parameterId].rindex; CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false); if (rindex < static_cast(fRdfDescriptor->PortCount)) { portUnit = &fRdfDescriptor->Ports[rindex].Unit; } else { rindex -= static_cast(fRdfDescriptor->PortCount); if (rindex < static_cast(fRdfDescriptor->ParameterCount)) { portUnit = &fRdfDescriptor->Parameters[rindex].Unit; } } if (portUnit != nullptr) { if (LV2_HAVE_PORT_UNIT_SYMBOL(portUnit->Hints) && portUnit->Symbol != nullptr) { std::strncpy(strBuf, portUnit->Symbol, STR_MAX); return true; } if (LV2_HAVE_PORT_UNIT_UNIT(portUnit->Hints)) { switch (portUnit->Unit) { case LV2_PORT_UNIT_BAR: std::strncpy(strBuf, "bars", STR_MAX); return true; case LV2_PORT_UNIT_BEAT: std::strncpy(strBuf, "beats", STR_MAX); return true; case LV2_PORT_UNIT_BPM: std::strncpy(strBuf, "BPM", STR_MAX); return true; case LV2_PORT_UNIT_CENT: std::strncpy(strBuf, "ct", STR_MAX); return true; case LV2_PORT_UNIT_CM: std::strncpy(strBuf, "cm", STR_MAX); return true; case LV2_PORT_UNIT_COEF: std::strncpy(strBuf, "(coef)", STR_MAX); return true; case LV2_PORT_UNIT_DB: std::strncpy(strBuf, "dB", STR_MAX); return true; case LV2_PORT_UNIT_DEGREE: std::strncpy(strBuf, "deg", STR_MAX); return true; case LV2_PORT_UNIT_FRAME: std::strncpy(strBuf, "frames", STR_MAX); return true; case LV2_PORT_UNIT_HZ: std::strncpy(strBuf, "Hz", STR_MAX); return true; case LV2_PORT_UNIT_INCH: std::strncpy(strBuf, "in", STR_MAX); return true; case LV2_PORT_UNIT_KHZ: std::strncpy(strBuf, "kHz", STR_MAX); return true; case LV2_PORT_UNIT_KM: std::strncpy(strBuf, "km", STR_MAX); return true; case LV2_PORT_UNIT_M: std::strncpy(strBuf, "m", STR_MAX); return true; case LV2_PORT_UNIT_MHZ: std::strncpy(strBuf, "MHz", STR_MAX); return true; case LV2_PORT_UNIT_MIDINOTE: std::strncpy(strBuf, "note", STR_MAX); return true; case LV2_PORT_UNIT_MILE: std::strncpy(strBuf, "mi", STR_MAX); return true; case LV2_PORT_UNIT_MIN: std::strncpy(strBuf, "min", STR_MAX); return true; case LV2_PORT_UNIT_MM: std::strncpy(strBuf, "mm", STR_MAX); return true; case LV2_PORT_UNIT_MS: std::strncpy(strBuf, "ms", STR_MAX); return true; case LV2_PORT_UNIT_OCT: std::strncpy(strBuf, "oct", STR_MAX); return true; case LV2_PORT_UNIT_PC: std::strncpy(strBuf, "%", STR_MAX); return true; case LV2_PORT_UNIT_S: std::strncpy(strBuf, "s", STR_MAX); return true; case LV2_PORT_UNIT_SEMITONE: std::strncpy(strBuf, "semi", STR_MAX); return true; } } } return CarlaPlugin::getParameterUnit(parameterId, strBuf); } bool getParameterComment(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); int32_t rindex = pData->param.data[parameterId].rindex; CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false); if (rindex < static_cast(fRdfDescriptor->PortCount)) { if (const char* const comment = fRdfDescriptor->Ports[rindex].Comment) { std::strncpy(strBuf, comment, STR_MAX); return true; } return false; } rindex -= static_cast(fRdfDescriptor->PortCount); if (rindex < static_cast(fRdfDescriptor->ParameterCount)) { if (const char* const comment = fRdfDescriptor->Parameters[rindex].Comment) { std::strncpy(strBuf, comment, STR_MAX); return true; } return false; } return CarlaPlugin::getParameterComment(parameterId, strBuf); } bool getParameterGroupName(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); int32_t rindex = pData->param.data[parameterId].rindex; CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false); const char* uri = nullptr; if (rindex < static_cast(fRdfDescriptor->PortCount)) { uri = fRdfDescriptor->Ports[rindex].GroupURI; } else { rindex -= static_cast(fRdfDescriptor->PortCount); if (rindex < static_cast(fRdfDescriptor->ParameterCount)) uri = fRdfDescriptor->Parameters[rindex].GroupURI; } if (uri == nullptr) return false; for (uint32_t i=0; iPortGroupCount; ++i) { if (std::strcmp(fRdfDescriptor->PortGroups[i].URI, uri) == 0) { const char* const name = fRdfDescriptor->PortGroups[i].Name; const char* const symbol = fRdfDescriptor->PortGroups[i].Symbol; if (name != nullptr && symbol != nullptr) { std::snprintf(strBuf, STR_MAX, "%s:%s", symbol, name); return true; } return false; } } return false; } bool getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); const int32_t rindex(pData->param.data[parameterId].rindex); CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false); if (rindex < static_cast(fRdfDescriptor->PortCount)) { const LV2_RDF_Port* const port(&fRdfDescriptor->Ports[rindex]); CARLA_SAFE_ASSERT_RETURN(scalePointId < port->ScalePointCount, false); const LV2_RDF_PortScalePoint* const portScalePoint(&port->ScalePoints[scalePointId]); if (portScalePoint->Label != nullptr) { std::strncpy(strBuf, portScalePoint->Label, STR_MAX); return true; } } return CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf); } // ------------------------------------------------------------------- // Set data (state) void prepareForSave() override { CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); if (fExt.state != nullptr && fExt.state->save != nullptr) { fExt.state->save(fHandle, carla_lv2_state_store, this, LV2_STATE_IS_POD, fFeatures); if (fHandle2 != nullptr) fExt.state->save(fHandle2, carla_lv2_state_store, this, LV2_STATE_IS_POD, fFeatures); } } // ------------------------------------------------------------------- // Set data (internal stuff) void setName(const char* const newName) override { CarlaPlugin::setName(newName); if (fLv2Options.windowTitle == nullptr) return; CarlaString guiTitle(pData->name); guiTitle += " (GUI)"; delete[] fLv2Options.windowTitle; fLv2Options.windowTitle = guiTitle.dup(); fLv2Options.opts[CarlaPluginLV2Options::WindowTitle].size = (uint32_t)std::strlen(fLv2Options.windowTitle); fLv2Options.opts[CarlaPluginLV2Options::WindowTitle].value = fLv2Options.windowTitle; if (fFeatures[kFeatureIdExternalUi] != nullptr && fFeatures[kFeatureIdExternalUi]->data != nullptr) ((LV2_External_UI_Host*)fFeatures[kFeatureIdExternalUi]->data)->plugin_human_id = fLv2Options.windowTitle; if (fPipeServer.isPipeRunning()) fPipeServer.writeUiTitleMessage(fLv2Options.windowTitle); #ifndef LV2_UIS_ONLY_BRIDGES if (fUI.window != nullptr) fUI.window->setTitle(fLv2Options.windowTitle); #endif } // ------------------------------------------------------------------- // Set data (plugin-specific stuff) float setParamterValueCommon(const uint32_t parameterId, const float value) noexcept { const float fixedValue(pData->param.getFixedValue(parameterId, value)); fParamBuffers[parameterId] = fixedValue; if (pData->param.data[parameterId].rindex >= static_cast(fRdfDescriptor->PortCount)) { const uint32_t rparamId = static_cast(pData->param.data[parameterId].rindex) - fRdfDescriptor->PortCount; CARLA_SAFE_ASSERT_UINT2_RETURN(rparamId < fRdfDescriptor->ParameterCount, rparamId, fRdfDescriptor->PortCount, fixedValue); uint8_t atomBuf[256]; lv2_atom_forge_set_buffer(&fAtomForge, atomBuf, sizeof(atomBuf)); LV2_Atom_Forge_Frame forgeFrame; lv2_atom_forge_object(&fAtomForge, &forgeFrame, kUridNull, kUridPatchSet); lv2_atom_forge_key(&fAtomForge, kUridPatchPoperty); lv2_atom_forge_urid(&fAtomForge, getCustomURID(fRdfDescriptor->Parameters[rparamId].URI)); lv2_atom_forge_key(&fAtomForge, kUridPatchValue); switch (fRdfDescriptor->Parameters[rparamId].Type) { case LV2_PARAMETER_BOOL: lv2_atom_forge_bool(&fAtomForge, fixedValue > 0.5f); break; case LV2_PARAMETER_INT: lv2_atom_forge_int(&fAtomForge, static_cast(fixedValue + 0.5f)); break; case LV2_PARAMETER_LONG: lv2_atom_forge_long(&fAtomForge, static_cast(fixedValue + 0.5f)); break; case LV2_PARAMETER_FLOAT: lv2_atom_forge_float(&fAtomForge, fixedValue); break; case LV2_PARAMETER_DOUBLE: lv2_atom_forge_double(&fAtomForge, fixedValue); break; default: carla_stderr2("setParameterValue called for invalid parameter, expect issues!"); break; } lv2_atom_forge_pop(&fAtomForge, &forgeFrame); LV2_Atom* const atom((LV2_Atom*)atomBuf); CARLA_SAFE_ASSERT(atom->size < sizeof(atomBuf)); fAtomBufferEvIn.put(atom, fEventsIn.ctrlIndex); } return fixedValue; } void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override { CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); const float fixedValue = setParamterValueCommon(parameterId, value); CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback); } void setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); const float fixedValue = setParamterValueCommon(parameterId, value); CarlaPlugin::setParameterValueRT(parameterId, fixedValue, sendCallbackLater); } void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr,); carla_debug("CarlaPluginLV2::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui)); if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0) return CarlaPlugin::setCustomData(type, key, value, sendGui); CarlaPlugin::setCustomData(type, key, value, sendGui); } void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override { CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->prog.count),); CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); if (index >= 0 && index < static_cast(fRdfDescriptor->PresetCount)) { const LV2_URID_Map* const uridMap = (const LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data; LilvState* const state = Lv2WorldClass::getInstance().getStateFromURI(fRdfDescriptor->Presets[index].URI, uridMap); CARLA_SAFE_ASSERT_RETURN(state != nullptr,); // invalidate midi-program selection CarlaPlugin::setMidiProgram(-1, false, false, sendCallback, false); if (fExt.state != nullptr) { const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); lilv_state_restore(state, fExt.state, fHandle, carla_lilv_set_port_value, this, 0, fFeatures); if (fHandle2 != nullptr) lilv_state_restore(state, fExt.state, fHandle2, carla_lilv_set_port_value, this, 0, fFeatures); } else { lilv_state_emit_port_values(state, carla_lilv_set_port_value, this); } lilv_state_free(state); } CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback, doingInit); } void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override { CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->midiprog.count),); CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,); if (index >= 0 && fExt.programs != nullptr && fExt.programs->select_program != nullptr) { const uint32_t bank(pData->midiprog.data[index].bank); const uint32_t program(pData->midiprog.data[index].program); const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); try { fExt.programs->select_program(fHandle, bank, program); } catch(...) {} if (fHandle2 != nullptr) { try { fExt.programs->select_program(fHandle2, bank, program); } catch(...) {} } } CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit); } void setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,); if (fExt.programs != nullptr && fExt.programs->select_program != nullptr) { const uint32_t bank(pData->midiprog.data[uindex].bank); const uint32_t program(pData->midiprog.data[uindex].program); try { fExt.programs->select_program(fHandle, bank, program); } catch(...) {} if (fHandle2 != nullptr) { try { fExt.programs->select_program(fHandle2, bank, program); } catch(...) {} } } CarlaPlugin::setMidiProgramRT(uindex, sendCallbackLater); } // ------------------------------------------------------------------- // Set ui stuff void showCustomUI(const bool yesNo) override { if (fUI.type == UI::TYPE_NULL) { if (fFilePathURI.isNotEmpty()) { const char* const path = pData->engine->runFileCallback(FILE_CALLBACK_OPEN, false, "Open File", ""); if (path != nullptr && path[0] != '\0') { carla_stdout("LV2 file path to send: '%s'", path); writeAtomPath(path, getCustomURID(fFilePathURI)); } } else { CARLA_SAFE_ASSERT(!yesNo); } pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); return; } const uintptr_t frontendWinId(pData->engine->getOptions().frontendWinId); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (! yesNo) pData->transientTryCounter = 0; #endif if (fUI.type == UI::TYPE_BRIDGE) { if (yesNo) { if (fPipeServer.isPipeRunning()) { fPipeServer.writeFocusMessage(); return; } if (! fPipeServer.startPipeServer(std::min(fLv2Options.sequenceSize, 819200))) { pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); return; } // manually write messages so we can take the lock for ourselves { char tmpBuf[0xff]; tmpBuf[0xfe] = '\0'; const CarlaMutexLocker cml(fPipeServer.getPipeLock()); const CarlaScopedLocale csl; // write URI mappings uint32_t u = 0; for (std::vector::iterator it=fCustomURIDs.begin(), end=fCustomURIDs.end(); it != end; ++it, ++u) { if (u < kUridCount) continue; const std::string& uri(*it); if (! fPipeServer.writeMessage("urid\n", 5)) return; std::snprintf(tmpBuf, 0xfe, "%u\n", u); if (! fPipeServer.writeMessage(tmpBuf)) return; std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast(uri.length())); if (! fPipeServer.writeMessage(tmpBuf)) return; if (! fPipeServer.writeAndFixMessage(uri.c_str())) return; } // write UI options if (! fPipeServer.writeMessage("uiOptions\n", 10)) return; const EngineOptions& opts(pData->engine->getOptions()); std::snprintf(tmpBuf, 0xff, "%g\n", pData->engine->getSampleRate()); if (! fPipeServer.writeMessage(tmpBuf)) return; std::snprintf(tmpBuf, 0xff, "%u\n", opts.bgColor); if (! fPipeServer.writeMessage(tmpBuf)) return; std::snprintf(tmpBuf, 0xff, "%u\n", opts.fgColor); if (! fPipeServer.writeMessage(tmpBuf)) return; std::snprintf(tmpBuf, 0xff, "%.12g\n", static_cast(opts.uiScale)); if (! fPipeServer.writeMessage(tmpBuf)) return; std::snprintf(tmpBuf, 0xff, "%s\n", bool2str(true)); // useTheme if (! fPipeServer.writeMessage(tmpBuf)) return; std::snprintf(tmpBuf, 0xff, "%s\n", bool2str(true)); // useThemeColors if (! fPipeServer.writeMessage(tmpBuf)) return; if (! fPipeServer.writeAndFixMessage(fLv2Options.windowTitle != nullptr ? fLv2Options.windowTitle : "")) return; std::snprintf(tmpBuf, 0xff, P_INTPTR "\n", frontendWinId); if (! fPipeServer.writeMessage(tmpBuf)) return; // write parameter values for (uint32_t i=0; i < pData->param.count; ++i) { if (! fPipeServer.writeMessage("control\n", 8)) return; std::snprintf(tmpBuf, 0xff, "%i\n", pData->param.data[i].rindex); if (! fPipeServer.writeMessage(tmpBuf)) return; std::snprintf(tmpBuf, 0xff, "%.12g\n", static_cast(getParameterValue(i))); if (! fPipeServer.writeMessage(tmpBuf)) return; } // ready to show if (! fPipeServer.writeMessage("show\n", 5)) return; fPipeServer.flushMessages(); } #ifndef BUILD_BRIDGE if (fUI.rdfDescriptor->Type == LV2_UI_MOD) pData->tryTransient(); #endif } else { fPipeServer.stopPipeServer(pData->engine->getOptions().uiBridgesTimeout); } return; } // take some precautions CARLA_SAFE_ASSERT_RETURN(fUI.descriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fUI.rdfDescriptor != nullptr,); if (yesNo) { CARLA_SAFE_ASSERT_RETURN(fUI.descriptor->instantiate != nullptr,); CARLA_SAFE_ASSERT_RETURN(fUI.descriptor->cleanup != nullptr,); } else { if (fUI.handle == nullptr) return; } if (yesNo) { if (fUI.handle == nullptr) { #ifndef LV2_UIS_ONLY_BRIDGES if (fUI.type == UI::TYPE_EMBED && fUI.rdfDescriptor->Type != LV2_UI_NONE && fUI.window == nullptr) { const char* msg = nullptr; switch (fUI.rdfDescriptor->Type) { case LV2_UI_GTK2: case LV2_UI_GTK3: case LV2_UI_QT4: case LV2_UI_QT5: case LV2_UI_EXTERNAL: case LV2_UI_OLD_EXTERNAL: msg = "Invalid UI type"; break; case LV2_UI_COCOA: # ifdef CARLA_OS_MAC fUI.window = CarlaPluginUI::newCocoa(this, frontendWinId, isUiResizable()); # else msg = "UI is for MacOS only"; # endif break; case LV2_UI_WINDOWS: # ifdef CARLA_OS_WIN fUI.window = CarlaPluginUI::newWindows(this, frontendWinId, isUiResizable()); # else msg = "UI is for Windows only"; # endif break; case LV2_UI_X11: # ifdef HAVE_X11 fUI.window = CarlaPluginUI::newX11(this, frontendWinId, isUiResizable()); # else msg = "UI is only for systems with X11"; # endif break; default: msg = "Unknown UI type"; break; } if (fUI.window == nullptr && fExt.uishow == nullptr) return pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, -1, 0, 0, 0.0f, msg); if (fUI.window != nullptr) fFeatures[kFeatureIdUiParent]->data = fUI.window->getPtr(); } #endif fUI.widget = nullptr; fUI.handle = fUI.descriptor->instantiate(fUI.descriptor, fRdfDescriptor->URI, fUI.rdfDescriptor->Bundle, carla_lv2_ui_write_function, this, &fUI.widget, fFeatures); if (fUI.window != nullptr) { if (fUI.widget != nullptr) fUI.window->setChildWindow(fUI.widget); fUI.window->setTitle(fLv2Options.windowTitle); } } CARLA_SAFE_ASSERT(fUI.handle != nullptr); CARLA_SAFE_ASSERT(fUI.type != UI::TYPE_EXTERNAL || fUI.widget != nullptr); if (fUI.handle == nullptr || (fUI.type == UI::TYPE_EXTERNAL && fUI.widget == nullptr)) { fUI.widget = nullptr; if (fUI.handle != nullptr) { fUI.descriptor->cleanup(fUI.handle); fUI.handle = nullptr; } return pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, -1, 0, 0, 0.0f, "Plugin refused to open its own UI"); } updateUi(); #ifndef LV2_UIS_ONLY_BRIDGES if (fUI.type == UI::TYPE_EMBED) { if (fUI.window != nullptr) { fUI.window->show(); } else if (fExt.uishow != nullptr) { fExt.uishow->show(fUI.handle); # ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->tryTransient(); # endif } } else #endif { LV2_EXTERNAL_UI_SHOW((LV2_External_UI_Widget*)fUI.widget); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->tryTransient(); #endif } } else { #ifndef LV2_UIS_ONLY_BRIDGES if (fUI.type == UI::TYPE_EMBED) { if (fUI.window != nullptr) fUI.window->hide(); else if (fExt.uishow != nullptr) fExt.uishow->hide(fUI.handle); } else #endif { CARLA_SAFE_ASSERT(fUI.widget != nullptr); if (fUI.widget != nullptr) LV2_EXTERNAL_UI_HIDE((LV2_External_UI_Widget*)fUI.widget); } fUI.descriptor->cleanup(fUI.handle); fUI.handle = nullptr; fUI.widget = nullptr; } } void idle() override { if (fAtomBufferWorkerIn.isDataAvailableForReading()) { Lv2AtomRingBuffer tmpRingBuffer(fAtomBufferWorkerIn, fAtomBufferWorkerInTmpData); CARLA_SAFE_ASSERT_RETURN(tmpRingBuffer.isDataAvailableForReading(),); CARLA_SAFE_ASSERT_RETURN(fExt.worker != nullptr && fExt.worker->work != nullptr,); uint32_t portIndex; const LV2_Atom* atom; for (; tmpRingBuffer.get(atom, portIndex);) { CARLA_SAFE_ASSERT_CONTINUE(atom->type == kUridCarlaAtomWorkerIn); fExt.worker->work(fHandle, carla_lv2_worker_respond, this, atom->size, LV2_ATOM_BODY_CONST(atom)); } } if (fInlineDisplayNeedsRedraw) { // TESTING CARLA_SAFE_ASSERT(pData->enabled) CARLA_SAFE_ASSERT(!pData->engine->isAboutToClose()); CARLA_SAFE_ASSERT(pData->client->isActive()); if (pData->enabled && !pData->engine->isAboutToClose() && pData->client->isActive()) { const int64_t timeNow = water::Time::currentTimeMillis(); if (timeNow - fInlineDisplayLastRedrawTime > (1000 / 30)) { fInlineDisplayNeedsRedraw = false; fInlineDisplayLastRedrawTime = timeNow; pData->engine->callback(true, true, ENGINE_CALLBACK_INLINE_DISPLAY_REDRAW, pData->id, 0, 0, 0, 0.0f, nullptr); } } } CarlaPlugin::idle(); } void uiIdle() override { if (const char* const fileNeededForURI = fUI.fileNeededForURI) { fUI.fileBrowserOpen = true; fUI.fileNeededForURI = nullptr; const char* const path = pData->engine->runFileCallback(FILE_CALLBACK_OPEN, /* isDir */ false, /* title */ "File open", /* filters */ ""); fUI.fileBrowserOpen = false; if (path != nullptr) { carla_stdout("LV2 requested path to send: '%s'", path); writeAtomPath(path, getCustomURID(fileNeededForURI)); } // this function will be called recursively, stop here return; } if (fAtomBufferUiOut.isDataAvailableForReading()) { Lv2AtomRingBuffer tmpRingBuffer(fAtomBufferUiOut, fAtomBufferUiOutTmpData); CARLA_SAFE_ASSERT(tmpRingBuffer.isDataAvailableForReading()); uint32_t portIndex; const LV2_Atom* atom; const bool hasPortEvent(fUI.handle != nullptr && fUI.descriptor != nullptr && fUI.descriptor->port_event != nullptr); for (; tmpRingBuffer.get(atom, portIndex);) { if (fUI.type == UI::TYPE_BRIDGE) { if (fPipeServer.isPipeRunning()) fPipeServer.writeLv2AtomMessage(portIndex, atom); } else { if (hasPortEvent && ! fNeedsUiClose) fUI.descriptor->port_event(fUI.handle, portIndex, lv2_atom_total_size(atom), kUridAtomTransferEvent, atom); } } } if (fPipeServer.isPipeRunning()) { fPipeServer.idlePipe(); switch (fPipeServer.getAndResetUiState()) { case CarlaPipeServerLV2::UiNone: case CarlaPipeServerLV2::UiShow: break; case CarlaPipeServerLV2::UiHide: fPipeServer.stopPipeServer(2000); // fall through case CarlaPipeServerLV2::UiCrashed: #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->transientTryCounter = 0; #endif pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); break; } } else { // TODO - detect if ui-bridge crashed } if (fNeedsUiClose) { fNeedsUiClose = false; showCustomUI(false); pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); } else if (fUI.handle != nullptr && fUI.descriptor != nullptr) { if (fUI.type == UI::TYPE_EXTERNAL && fUI.widget != nullptr) LV2_EXTERNAL_UI_RUN((LV2_External_UI_Widget*)fUI.widget); #ifndef LV2_UIS_ONLY_BRIDGES else if (fUI.type == UI::TYPE_EMBED && fUI.window != nullptr) fUI.window->idle(); // note: UI might have been closed by window idle if (fNeedsUiClose) { pass(); } else if (fUI.handle != nullptr && fExt.uiidle != nullptr && fExt.uiidle->idle(fUI.handle) != 0) { showCustomUI(false); pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); CARLA_SAFE_ASSERT(fUI.handle == nullptr); } #endif } CarlaPlugin::uiIdle(); } // ------------------------------------------------------------------- // Plugin state void reload() override { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr,); carla_debug("CarlaPluginLV2::reload() - start"); const EngineProcessMode processMode(pData->engine->getProccessMode()); // Safely disable plugin for reload const ScopedDisabler sd(this); if (pData->active) deactivate(); clearBuffers(); const float sampleRate(static_cast(pData->engine->getSampleRate())); const uint32_t portCount(fRdfDescriptor->PortCount); uint32_t aIns, aOuts, cvIns, cvOuts, params; aIns = aOuts = cvIns = cvOuts = params = 0; LinkedList evIns, evOuts; const uint32_t eventBufferSize(static_cast(fLv2Options.sequenceSize)+0xff); bool forcedStereoIn, forcedStereoOut; forcedStereoIn = forcedStereoOut = false; bool needsCtrlIn, needsCtrlOut; needsCtrlIn = needsCtrlOut = false; for (uint32_t i=0; i < portCount; ++i) { const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types); if (LV2_IS_PORT_AUDIO(portTypes)) { if (LV2_IS_PORT_INPUT(portTypes)) aIns += 1; else if (LV2_IS_PORT_OUTPUT(portTypes)) aOuts += 1; } else if (LV2_IS_PORT_CV(portTypes)) { if (LV2_IS_PORT_INPUT(portTypes)) cvIns += 1; else if (LV2_IS_PORT_OUTPUT(portTypes)) cvOuts += 1; } else if (LV2_IS_PORT_ATOM_SEQUENCE(portTypes)) { if (LV2_IS_PORT_INPUT(portTypes)) evIns.append(CARLA_EVENT_DATA_ATOM); else if (LV2_IS_PORT_OUTPUT(portTypes)) evOuts.append(CARLA_EVENT_DATA_ATOM); } else if (LV2_IS_PORT_EVENT(portTypes)) { if (LV2_IS_PORT_INPUT(portTypes)) evIns.append(CARLA_EVENT_DATA_EVENT); else if (LV2_IS_PORT_OUTPUT(portTypes)) evOuts.append(CARLA_EVENT_DATA_EVENT); } else if (LV2_IS_PORT_MIDI_LL(portTypes)) { if (LV2_IS_PORT_INPUT(portTypes)) evIns.append(CARLA_EVENT_DATA_MIDI_LL); else if (LV2_IS_PORT_OUTPUT(portTypes)) evOuts.append(CARLA_EVENT_DATA_MIDI_LL); } else if (LV2_IS_PORT_CONTROL(portTypes)) params += 1; } for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i) { switch (fRdfDescriptor->Parameters[i].Type) { case LV2_PARAMETER_BOOL: case LV2_PARAMETER_INT: // case LV2_PARAMETER_LONG: case LV2_PARAMETER_FLOAT: case LV2_PARAMETER_DOUBLE: params += 1; break; case LV2_PARAMETER_PATH: if (fFilePathURI.isEmpty()) fFilePathURI = fRdfDescriptor->Parameters[i].URI; break; } } if ((pData->options & PLUGIN_OPTION_FORCE_STEREO) != 0 && aIns <= 1 && aOuts <= 1 && fExt.state == nullptr && fExt.worker == nullptr) { if (fHandle2 == nullptr) { try { fHandle2 = fDescriptor->instantiate(fDescriptor, sampleRate, fRdfDescriptor->Bundle, fFeatures); } catch(...) {} } if (fHandle2 != nullptr) { if (aIns == 1) { aIns = 2; forcedStereoIn = true; } if (aOuts == 1) { aOuts = 2; forcedStereoOut = true; } } } if (aIns > 0) { pData->audioIn.createNew(aIns); fAudioInBuffers = new float*[aIns]; for (uint32_t i=0; i < aIns; ++i) fAudioInBuffers[i] = nullptr; } if (aOuts > 0) { pData->audioOut.createNew(aOuts); fAudioOutBuffers = new float*[aOuts]; needsCtrlIn = true; for (uint32_t i=0; i < aOuts; ++i) fAudioOutBuffers[i] = nullptr; } if (cvIns > 0) { pData->cvIn.createNew(cvIns); fCvInBuffers = new float*[cvIns]; for (uint32_t i=0; i < cvIns; ++i) fCvInBuffers[i] = nullptr; } if (cvOuts > 0) { pData->cvOut.createNew(cvOuts); fCvOutBuffers = new float*[cvOuts]; for (uint32_t i=0; i < cvOuts; ++i) fCvOutBuffers[i] = nullptr; } if (params > 0) { pData->param.createNew(params, true); fParamBuffers = new float[params]; carla_zeroFloats(fParamBuffers, params); } if (const uint32_t count = static_cast(evIns.count())) { fEventsIn.createNew(count); for (uint32_t i=0; i < count; ++i) { const uint32_t& type(evIns.getAt(i, 0x0)); if (type == CARLA_EVENT_DATA_ATOM) { fEventsIn.data[i].type = CARLA_EVENT_DATA_ATOM; fEventsIn.data[i].atom = lv2_atom_buffer_new(eventBufferSize, kUridNull, kUridAtomSequence, true); } else if (type == CARLA_EVENT_DATA_EVENT) { fEventsIn.data[i].type = CARLA_EVENT_DATA_EVENT; fEventsIn.data[i].event = lv2_event_buffer_new(eventBufferSize, LV2_EVENT_AUDIO_STAMP); } else if (type == CARLA_EVENT_DATA_MIDI_LL) { fEventsIn.data[i].type = CARLA_EVENT_DATA_MIDI_LL; fEventsIn.data[i].midi.capacity = eventBufferSize; fEventsIn.data[i].midi.data = new uchar[eventBufferSize]; } } } else { fEventsIn.createNew(1); fEventsIn.ctrl = &fEventsIn.data[0]; } if (const uint32_t count = static_cast(evOuts.count())) { fEventsOut.createNew(count); for (uint32_t i=0; i < count; ++i) { const uint32_t& type(evOuts.getAt(i, 0x0)); if (type == CARLA_EVENT_DATA_ATOM) { fEventsOut.data[i].type = CARLA_EVENT_DATA_ATOM; fEventsOut.data[i].atom = lv2_atom_buffer_new(eventBufferSize, kUridNull, kUridAtomSequence, false); } else if (type == CARLA_EVENT_DATA_EVENT) { fEventsOut.data[i].type = CARLA_EVENT_DATA_EVENT; fEventsOut.data[i].event = lv2_event_buffer_new(eventBufferSize, LV2_EVENT_AUDIO_STAMP); } else if (type == CARLA_EVENT_DATA_MIDI_LL) { fEventsOut.data[i].type = CARLA_EVENT_DATA_MIDI_LL; fEventsOut.data[i].midi.capacity = eventBufferSize; fEventsOut.data[i].midi.data = new uchar[eventBufferSize]; } } } const uint portNameSize(pData->engine->getMaxPortNameSize()); CarlaString portName; uint32_t iCtrl = 0; for (uint32_t i=0, iAudioIn=0, iAudioOut=0, iCvIn=0, iCvOut=0, iEvIn=0, iEvOut=0; i < portCount; ++i) { const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types); portName.clear(); if (LV2_IS_PORT_AUDIO(portTypes) || LV2_IS_PORT_CV(portTypes) || LV2_IS_PORT_ATOM_SEQUENCE(portTypes) || LV2_IS_PORT_EVENT(portTypes) || LV2_IS_PORT_MIDI_LL(portTypes)) { if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += fRdfDescriptor->Ports[i].Name; portName.truncate(portNameSize); } if (LV2_IS_PORT_AUDIO(portTypes)) { if (LV2_IS_PORT_INPUT(portTypes)) { const uint32_t j = iAudioIn++; pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j); pData->audioIn.ports[j].rindex = i; if (forcedStereoIn) { portName += "_2"; pData->audioIn.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, 1); pData->audioIn.ports[1].rindex = i; } } else if (LV2_IS_PORT_OUTPUT(portTypes)) { const uint32_t j = iAudioOut++; pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j); pData->audioOut.ports[j].rindex = i; if (forcedStereoOut) { portName += "_2"; pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 1); pData->audioOut.ports[1].rindex = i; } } else carla_stderr2("WARNING - Got a broken Port (Audio, but not input or output)"); } else if (LV2_IS_PORT_CV(portTypes)) { const LV2_RDF_PortPoints portPoints(fRdfDescriptor->Ports[i].Points); float min, max; // min value if (LV2_HAVE_MINIMUM_PORT_POINT(portPoints.Hints)) min = portPoints.Minimum; else min = -1.0f; // max value if (LV2_HAVE_MAXIMUM_PORT_POINT(portPoints.Hints)) max = portPoints.Maximum; else max = 1.0f; if (LV2_IS_PORT_INPUT(portTypes)) { const uint32_t j = iCvIn++; pData->cvIn.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, true, j); pData->cvIn.ports[j].rindex = i; pData->cvIn.ports[j].port->setRange(min, max); } else if (LV2_IS_PORT_OUTPUT(portTypes)) { const uint32_t j = iCvOut++; pData->cvOut.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, false, j); pData->cvOut.ports[j].rindex = i; pData->cvOut.ports[j].port->setRange(min, max); } else carla_stderr("WARNING - Got a broken Port (CV, but not input or output)"); } else if (LV2_IS_PORT_ATOM_SEQUENCE(portTypes)) { if (LV2_IS_PORT_INPUT(portTypes)) { const uint32_t j = iEvIn++; fDescriptor->connect_port(fHandle, i, &fEventsIn.data[j].atom->atoms); if (fHandle2 != nullptr) fDescriptor->connect_port(fHandle2, i, &fEventsIn.data[j].atom->atoms); fEventsIn.data[j].rindex = i; if (portTypes & LV2_PORT_DATA_MIDI_EVENT) fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MIDI; if (portTypes & LV2_PORT_DATA_PATCH_MESSAGE) fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MESSAGE; if (portTypes & LV2_PORT_DATA_TIME_POSITION) fEventsIn.data[j].type |= CARLA_EVENT_TYPE_TIME; if (evIns.count() == 1) { fEventsIn.ctrl = &fEventsIn.data[j]; fEventsIn.ctrlIndex = j; if (portTypes & LV2_PORT_DATA_MIDI_EVENT) needsCtrlIn = true; } else { if (portTypes & LV2_PORT_DATA_MIDI_EVENT) fEventsIn.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, j); if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation)) { fEventsIn.ctrl = &fEventsIn.data[j]; fEventsIn.ctrlIndex = j; } } } else if (LV2_IS_PORT_OUTPUT(portTypes)) { const uint32_t j = iEvOut++; fDescriptor->connect_port(fHandle, i, &fEventsOut.data[j].atom->atoms); if (fHandle2 != nullptr) fDescriptor->connect_port(fHandle2, i, &fEventsOut.data[j].atom->atoms); fEventsOut.data[j].rindex = i; if (portTypes & LV2_PORT_DATA_MIDI_EVENT) fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MIDI; if (portTypes & LV2_PORT_DATA_PATCH_MESSAGE) fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MESSAGE; if (portTypes & LV2_PORT_DATA_TIME_POSITION) fEventsOut.data[j].type |= CARLA_EVENT_TYPE_TIME; if (evOuts.count() == 1) { fEventsOut.ctrl = &fEventsOut.data[j]; fEventsOut.ctrlIndex = j; if (portTypes & LV2_PORT_DATA_MIDI_EVENT) needsCtrlOut = true; } else { if (portTypes & LV2_PORT_DATA_MIDI_EVENT) fEventsOut.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, j); if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation)) { fEventsOut.ctrl = &fEventsOut.data[j]; fEventsOut.ctrlIndex = j; } } } else carla_stderr2("WARNING - Got a broken Port (Atom-Sequence, but not input or output)"); } else if (LV2_IS_PORT_EVENT(portTypes)) { if (LV2_IS_PORT_INPUT(portTypes)) { const uint32_t j = iEvIn++; fDescriptor->connect_port(fHandle, i, fEventsIn.data[j].event); if (fHandle2 != nullptr) fDescriptor->connect_port(fHandle2, i, fEventsIn.data[j].event); fEventsIn.data[j].rindex = i; if (portTypes & LV2_PORT_DATA_MIDI_EVENT) fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MIDI; if (portTypes & LV2_PORT_DATA_PATCH_MESSAGE) fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MESSAGE; if (portTypes & LV2_PORT_DATA_TIME_POSITION) fEventsIn.data[j].type |= CARLA_EVENT_TYPE_TIME; if (evIns.count() == 1) { fEventsIn.ctrl = &fEventsIn.data[j]; fEventsIn.ctrlIndex = j; if (portTypes & LV2_PORT_DATA_MIDI_EVENT) needsCtrlIn = true; } else { if (portTypes & LV2_PORT_DATA_MIDI_EVENT) fEventsIn.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, j); if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation)) { fEventsIn.ctrl = &fEventsIn.data[j]; fEventsIn.ctrlIndex = j; } } } else if (LV2_IS_PORT_OUTPUT(portTypes)) { const uint32_t j = iEvOut++; fDescriptor->connect_port(fHandle, i, fEventsOut.data[j].event); if (fHandle2 != nullptr) fDescriptor->connect_port(fHandle2, i, fEventsOut.data[j].event); fEventsOut.data[j].rindex = i; if (portTypes & LV2_PORT_DATA_MIDI_EVENT) fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MIDI; if (portTypes & LV2_PORT_DATA_PATCH_MESSAGE) fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MESSAGE; if (portTypes & LV2_PORT_DATA_TIME_POSITION) fEventsOut.data[j].type |= CARLA_EVENT_TYPE_TIME; if (evOuts.count() == 1) { fEventsOut.ctrl = &fEventsOut.data[j]; fEventsOut.ctrlIndex = j; if (portTypes & LV2_PORT_DATA_MIDI_EVENT) needsCtrlOut = true; } else { if (portTypes & LV2_PORT_DATA_MIDI_EVENT) fEventsOut.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, j); if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation)) { fEventsOut.ctrl = &fEventsOut.data[j]; fEventsOut.ctrlIndex = j; } } } else carla_stderr2("WARNING - Got a broken Port (Event, but not input or output)"); } else if (LV2_IS_PORT_MIDI_LL(portTypes)) { if (LV2_IS_PORT_INPUT(portTypes)) { const uint32_t j = iEvIn++; fDescriptor->connect_port(fHandle, i, &fEventsIn.data[j].midi); if (fHandle2 != nullptr) fDescriptor->connect_port(fHandle2, i, &fEventsIn.data[j].midi); fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MIDI; fEventsIn.data[j].rindex = i; if (evIns.count() == 1) { needsCtrlIn = true; fEventsIn.ctrl = &fEventsIn.data[j]; fEventsIn.ctrlIndex = j; } else { fEventsIn.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, j); if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation)) { fEventsIn.ctrl = &fEventsIn.data[j]; fEventsIn.ctrlIndex = j; } } } else if (LV2_IS_PORT_OUTPUT(portTypes)) { const uint32_t j = iEvOut++; fDescriptor->connect_port(fHandle, i, &fEventsOut.data[j].midi); if (fHandle2 != nullptr) fDescriptor->connect_port(fHandle2, i, &fEventsOut.data[j].midi); fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MIDI; fEventsOut.data[j].rindex = i; if (evOuts.count() == 1) { needsCtrlOut = true; fEventsOut.ctrl = &fEventsOut.data[j]; fEventsOut.ctrlIndex = j; } else { fEventsOut.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, j); if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation)) { fEventsOut.ctrl = &fEventsOut.data[j]; fEventsOut.ctrlIndex = j; } } } else carla_stderr2("WARNING - Got a broken Port (MIDI, but not input or output)"); } else if (LV2_IS_PORT_CONTROL(portTypes)) { const LV2_Property portProps(fRdfDescriptor->Ports[i].Properties); const LV2_Property portDesignation(fRdfDescriptor->Ports[i].Designation); const LV2_RDF_PortPoints portPoints(fRdfDescriptor->Ports[i].Points); const uint32_t j = iCtrl++; pData->param.data[j].index = static_cast(j); pData->param.data[j].rindex = static_cast(i); float min, max, def, step, stepSmall, stepLarge; // min value if (LV2_HAVE_MINIMUM_PORT_POINT(portPoints.Hints)) min = portPoints.Minimum; else min = 0.0f; // max value if (LV2_HAVE_MAXIMUM_PORT_POINT(portPoints.Hints)) max = portPoints.Maximum; else max = 1.0f; if (LV2_IS_PORT_SAMPLE_RATE(portProps)) { min *= sampleRate; max *= sampleRate; pData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE; } // stupid hack for ir.lv2 (broken plugin) if (std::strcmp(fRdfDescriptor->URI, "http://factorial.hu/plugins/lv2/ir") == 0 && std::strncmp(fRdfDescriptor->Ports[i].Name, "FileHash", 8) == 0) { min = 0.0f; max = (float)0xffffff; } if (min >= max) { carla_stderr2("WARNING - Broken plugin parameter '%s': min >= max", fRdfDescriptor->Ports[i].Name); max = min + 0.1f; } // default value if (LV2_HAVE_DEFAULT_PORT_POINT(portPoints.Hints)) { def = portPoints.Default; } else { // no default value if (min < 0.0f && max > 0.0f) def = 0.0f; else def = min; } if (def < min) def = min; else if (def > max) def = max; if (LV2_IS_PORT_TOGGLED(portProps)) { step = max - min; stepSmall = step; stepLarge = step; pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN; } else if (LV2_IS_PORT_INTEGER(portProps)) { step = 1.0f; stepSmall = 1.0f; stepLarge = 10.0f; pData->param.data[j].hints |= PARAMETER_IS_INTEGER; } else { float range = max - min; step = range/100.0f; stepSmall = range/1000.0f; stepLarge = range/10.0f; } if (LV2_IS_PORT_INPUT(portTypes)) { pData->param.data[j].type = PARAMETER_INPUT; if (LV2_IS_PORT_DESIGNATION_LATENCY(portDesignation)) { carla_stderr("Plugin has latency input port, this should not happen!"); } else if (LV2_IS_PORT_DESIGNATION_SAMPLE_RATE(portDesignation)) { def = sampleRate; step = 1.0f; stepSmall = 1.0f; stepLarge = 1.0f; pData->param.special[j] = PARAMETER_SPECIAL_SAMPLE_RATE; } else if (LV2_IS_PORT_DESIGNATION_FREEWHEELING(portDesignation)) { pData->param.special[j] = PARAMETER_SPECIAL_FREEWHEEL; } else if (LV2_IS_PORT_DESIGNATION_TIME(portDesignation)) { pData->param.special[j] = PARAMETER_SPECIAL_TIME; } else { pData->param.data[j].hints |= PARAMETER_IS_ENABLED; pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE; needsCtrlIn = true; if (! LV2_IS_PORT_CAUSES_ARTIFACTS(portProps) && ! LV2_IS_PORT_ENUMERATION(portProps) && ! LV2_IS_PORT_EXPENSIVE(portProps) && ! LV2_IS_PORT_NOT_AUTOMATIC(portProps) && ! LV2_IS_PORT_NOT_ON_GUI(portProps) && ! LV2_IS_PORT_TRIGGER(portProps)) { pData->param.data[j].hints |= PARAMETER_CAN_BE_CV_CONTROLLED; } } // MIDI CC value const LV2_RDF_PortMidiMap& portMidiMap(fRdfDescriptor->Ports[i].MidiMap); if (LV2_IS_PORT_MIDI_MAP_CC(portMidiMap.Type)) { if (portMidiMap.Number < MAX_MIDI_CONTROL && ! MIDI_IS_CONTROL_BANK_SELECT(portMidiMap.Number)) pData->param.data[j].mappedControlIndex = static_cast(portMidiMap.Number); } } else if (LV2_IS_PORT_OUTPUT(portTypes)) { pData->param.data[j].type = PARAMETER_OUTPUT; if (LV2_IS_PORT_DESIGNATION_LATENCY(portDesignation)) { min = 0.0f; max = sampleRate; def = 0.0f; step = 1.0f; stepSmall = 1.0f; stepLarge = 1.0f; pData->param.special[j] = PARAMETER_SPECIAL_LATENCY; CARLA_SAFE_ASSERT_INT2(fLatencyIndex == static_cast(j), fLatencyIndex, j); } else if (LV2_IS_PORT_DESIGNATION_SAMPLE_RATE(portDesignation)) { def = sampleRate; step = 1.0f; stepSmall = 1.0f; stepLarge = 1.0f; pData->param.special[j] = PARAMETER_SPECIAL_SAMPLE_RATE; } else if (LV2_IS_PORT_DESIGNATION_FREEWHEELING(portDesignation)) { carla_stderr("Plugin has freewheeling output port, this should not happen!"); } else if (LV2_IS_PORT_DESIGNATION_TIME(portDesignation)) { pData->param.special[j] = PARAMETER_SPECIAL_TIME; } else { pData->param.data[j].hints |= PARAMETER_IS_ENABLED; pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE; needsCtrlOut = true; } } else { pData->param.data[j].type = PARAMETER_UNKNOWN; carla_stderr2("WARNING - Got a broken Port (Control, but not input or output)"); } // extra parameter hints if (LV2_IS_PORT_LOGARITHMIC(portProps)) pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC; if (LV2_IS_PORT_TRIGGER(portProps)) pData->param.data[j].hints |= PARAMETER_IS_TRIGGER; if (LV2_IS_PORT_STRICT_BOUNDS(portProps)) pData->param.data[j].hints |= PARAMETER_IS_STRICT_BOUNDS; if (LV2_IS_PORT_ENUMERATION(portProps)) pData->param.data[j].hints |= PARAMETER_USES_SCALEPOINTS; // check if parameter is not enabled or automable if (LV2_IS_PORT_NOT_ON_GUI(portProps)) pData->param.data[j].hints &= ~(PARAMETER_IS_ENABLED|PARAMETER_IS_AUTOMABLE); else if (LV2_IS_PORT_CAUSES_ARTIFACTS(portProps) || LV2_IS_PORT_EXPENSIVE(portProps)) pData->param.data[j].hints &= ~PARAMETER_IS_AUTOMABLE; else if (LV2_IS_PORT_NOT_AUTOMATIC(portProps) || LV2_IS_PORT_NON_AUTOMABLE(portProps)) pData->param.data[j].hints &= ~PARAMETER_IS_AUTOMABLE; pData->param.ranges[j].min = min; pData->param.ranges[j].max = max; pData->param.ranges[j].def = def; pData->param.ranges[j].step = step; pData->param.ranges[j].stepSmall = stepSmall; pData->param.ranges[j].stepLarge = stepLarge; // Start parameters in their default values (except freewheel, which is off by default) if (pData->param.data[j].type == PARAMETER_INPUT && pData->param.special[j] == PARAMETER_SPECIAL_FREEWHEEL) fParamBuffers[j] = min; else fParamBuffers[j] = def; fDescriptor->connect_port(fHandle, i, &fParamBuffers[j]); if (fHandle2 != nullptr) fDescriptor->connect_port(fHandle2, i, &fParamBuffers[j]); } else { // Port Type not supported, but it's optional anyway fDescriptor->connect_port(fHandle, i, nullptr); if (fHandle2 != nullptr) fDescriptor->connect_port(fHandle2, i, nullptr); } } for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i) { const LV2_RDF_Parameter& rdfParam(fRdfDescriptor->Parameters[i]); switch (rdfParam.Type) { case LV2_PARAMETER_BOOL: case LV2_PARAMETER_INT: // case LV2_PARAMETER_LONG: case LV2_PARAMETER_FLOAT: case LV2_PARAMETER_DOUBLE: break; default: continue; } const LV2_RDF_PortPoints& portPoints(rdfParam.Points); const uint32_t j = iCtrl++; pData->param.data[j].index = static_cast(j); pData->param.data[j].rindex = static_cast(fRdfDescriptor->PortCount + i); float min, max, def, step, stepSmall, stepLarge; // min value if (LV2_HAVE_MINIMUM_PORT_POINT(portPoints.Hints)) min = portPoints.Minimum; else min = 0.0f; // max value if (LV2_HAVE_MAXIMUM_PORT_POINT(portPoints.Hints)) max = portPoints.Maximum; else max = 1.0f; if (min >= max) { carla_stderr2("WARNING - Broken plugin parameter '%s': min >= max", rdfParam.Label); max = min + 0.1f; } // default value if (LV2_HAVE_DEFAULT_PORT_POINT(portPoints.Hints)) { def = portPoints.Default; } else { // no default value if (min < 0.0f && max > 0.0f) def = 0.0f; else def = min; } if (def < min) def = min; else if (def > max) def = max; switch (rdfParam.Type) { case LV2_PARAMETER_BOOL: step = max - min; stepSmall = step; stepLarge = step; pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN; break; case LV2_PARAMETER_INT: case LV2_PARAMETER_LONG: step = 1.0f; stepSmall = 1.0f; stepLarge = 10.0f; pData->param.data[j].hints |= PARAMETER_IS_INTEGER; break; default: const float range = max - min; step = range/100.0f; stepSmall = range/1000.0f; stepLarge = range/10.0f; break; } if (rdfParam.Input) { pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].hints |= PARAMETER_IS_ENABLED; pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE; needsCtrlIn = true; } else { pData->param.data[j].type = PARAMETER_OUTPUT; pData->param.data[j].hints |= PARAMETER_IS_ENABLED; pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE; needsCtrlOut = true; } pData->param.ranges[j].min = min; pData->param.ranges[j].max = max; pData->param.ranges[j].def = def; pData->param.ranges[j].step = step; pData->param.ranges[j].stepSmall = stepSmall; pData->param.ranges[j].stepLarge = stepLarge; fParamBuffers[j] = def; } if (needsCtrlIn) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-in"; portName.truncate(portNameSize); pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->event.cvSourcePorts = pData->client->createCVSourcePorts(); #endif } if (needsCtrlOut) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-out"; portName.truncate(portNameSize); pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0); } if (fExt.worker != nullptr && fEventsIn.ctrl != nullptr) { fAtomBufferWorkerIn.createBuffer(eventBufferSize); fAtomBufferWorkerResp.createBuffer(eventBufferSize); fAtomBufferWorkerInTmpData = new uint8_t[fAtomBufferWorkerIn.getSize()]; } if (fRdfDescriptor->ParameterCount > 0 || (fUI.type != UI::TYPE_NULL && fEventsIn.count > 0 && (fEventsIn.data[0].type & CARLA_EVENT_DATA_ATOM) != 0)) fAtomBufferEvIn.createBuffer(eventBufferSize); if (fUI.type != UI::TYPE_NULL && fEventsOut.count > 0 && (fEventsOut.data[0].type & CARLA_EVENT_DATA_ATOM) != 0) { fAtomBufferUiOut.createBuffer(std::min(eventBufferSize*32, 1638400U)); fAtomBufferUiOutTmpData = new uint8_t[fAtomBufferUiOut.getSize()]; } if (fEventsIn.ctrl != nullptr && fEventsIn.ctrl->port == nullptr) fEventsIn.ctrl->port = pData->event.portIn; if (fEventsOut.ctrl != nullptr && fEventsOut.ctrl->port == nullptr) fEventsOut.ctrl->port = pData->event.portOut; if (fEventsIn.ctrl != nullptr && fExt.midnam != nullptr) { if (char* const midnam = fExt.midnam->midnam(fHandle)) { fEventsIn.ctrl->port->setMetaData("http://www.midi.org/dtds/MIDINameDocument10.dtd", midnam, "text/xml"); if (fExt.midnam->free != nullptr) fExt.midnam->free(midnam); } } if (forcedStereoIn || forcedStereoOut) pData->options |= PLUGIN_OPTION_FORCE_STEREO; else pData->options &= ~PLUGIN_OPTION_FORCE_STEREO; // plugin hints pData->hints = (pData->hints & PLUGIN_HAS_INLINE_DISPLAY) ? PLUGIN_HAS_INLINE_DISPLAY : 0 | (pData->hints & PLUGIN_NEEDS_UI_MAIN_THREAD) ? PLUGIN_NEEDS_UI_MAIN_THREAD : 0; if (isRealtimeSafe()) pData->hints |= PLUGIN_IS_RTSAFE; if (fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty()) { pData->hints |= PLUGIN_HAS_CUSTOM_UI; if (fUI.type == UI::TYPE_EMBED || fUI.type == UI::TYPE_EXTERNAL) pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD; } if (LV2_IS_GENERATOR(fRdfDescriptor->Type[0], fRdfDescriptor->Type[1])) pData->hints |= PLUGIN_IS_SYNTH; if (aOuts > 0 && (aIns == aOuts || aIns == 1)) pData->hints |= PLUGIN_CAN_DRYWET; if (aOuts > 0) pData->hints |= PLUGIN_CAN_VOLUME; if (aOuts >= 2 && aOuts % 2 == 0) pData->hints |= PLUGIN_CAN_BALANCE; // extra plugin hints pData->extraHints = 0x0; // check initial latency findInitialLatencyValue(aIns, cvIns, aOuts, cvOuts); bufferSizeChanged(pData->engine->getBufferSize()); reloadPrograms(true); evIns.clear(); evOuts.clear(); if (pData->active) activate(); carla_debug("CarlaPluginLV2::reload() - end"); } void findInitialLatencyValue(const uint32_t aIns, const uint32_t cvIns, const uint32_t aOuts, const uint32_t cvOuts) const { if (fLatencyIndex < 0) return; // we need to pre-run the plugin so it can update its latency control-port const uint32_t bufferSize = static_cast(fLv2Options.nominalBufferSize); float tmpIn [( aIns+cvIns > 0) ? aIns+cvIns : 1][bufferSize]; float tmpOut[(aOuts+cvOuts > 0) ? aOuts+cvOuts : 1][bufferSize]; { uint32_t i=0; for (; i < aIns; ++i) { carla_zeroFloats(tmpIn[i], bufferSize); try { fDescriptor->connect_port(fHandle, pData->audioIn.ports[i].rindex, tmpIn[i]); } CARLA_SAFE_EXCEPTION("LV2 connect_port latency audio input"); } for (uint32_t j=0; j < cvIns; ++i, ++j) { carla_zeroFloats(tmpIn[i], bufferSize); try { fDescriptor->connect_port(fHandle, pData->cvIn.ports[j].rindex, tmpIn[i]); } CARLA_SAFE_EXCEPTION("LV2 connect_port latency cv input"); } } { uint32_t i=0; for (; i < aOuts; ++i) { carla_zeroFloats(tmpOut[i], bufferSize); try { fDescriptor->connect_port(fHandle, pData->audioOut.ports[i].rindex, tmpOut[i]); } CARLA_SAFE_EXCEPTION("LV2 connect_port latency audio output"); } for (uint32_t j=0; j < cvOuts; ++i, ++j) { carla_zeroFloats(tmpOut[i], bufferSize); try { fDescriptor->connect_port(fHandle, pData->cvOut.ports[j].rindex, tmpOut[i]); } CARLA_SAFE_EXCEPTION("LV2 connect_port latency cv output"); } } if (fDescriptor->activate != nullptr) { try { fDescriptor->activate(fHandle); } CARLA_SAFE_EXCEPTION("LV2 latency activate"); } try { fDescriptor->run(fHandle, bufferSize); } CARLA_SAFE_EXCEPTION("LV2 latency run"); if (fDescriptor->deactivate != nullptr) { try { fDescriptor->deactivate(fHandle); } CARLA_SAFE_EXCEPTION("LV2 latency deactivate"); } // done, let's get the value if (const uint32_t latency = getLatencyInFrames()) { pData->client->setLatency(latency); #ifndef BUILD_BRIDGE pData->latency.recreateBuffers(std::max(aIns, aOuts), latency); #endif } } void reloadPrograms(const bool doInit) override { carla_debug("CarlaPluginLV2::reloadPrograms(%s)", bool2str(doInit)); const uint32_t oldCount = pData->midiprog.count; const int32_t current = pData->midiprog.current; // special LV2 programs handling if (doInit) { pData->prog.clear(); const uint32_t presetCount(fRdfDescriptor->PresetCount); if (presetCount > 0) { pData->prog.createNew(presetCount); for (uint32_t i=0; i < presetCount; ++i) pData->prog.names[i] = carla_strdup(fRdfDescriptor->Presets[i].Label); } } // Delete old programs pData->midiprog.clear(); // Query new programs uint32_t newCount = 0; if (fExt.programs != nullptr && fExt.programs->get_program != nullptr && fExt.programs->select_program != nullptr) { for (; fExt.programs->get_program(fHandle, newCount);) ++newCount; } if (newCount > 0) { pData->midiprog.createNew(newCount); // Update data for (uint32_t i=0; i < newCount; ++i) { const LV2_Program_Descriptor* const pdesc(fExt.programs->get_program(fHandle, i)); CARLA_SAFE_ASSERT_CONTINUE(pdesc != nullptr); CARLA_SAFE_ASSERT(pdesc->name != nullptr); pData->midiprog.data[i].bank = pdesc->bank; pData->midiprog.data[i].program = pdesc->program; pData->midiprog.data[i].name = carla_strdup(pdesc->name); } } if (doInit) { if (newCount > 0) { setMidiProgram(0, false, false, false, true); } else { // load default state if (LilvState* const state = Lv2WorldClass::getInstance().getStateFromURI(fDescriptor->URI, (const LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data)) { lilv_state_restore(state, fExt.state, fHandle, carla_lilv_set_port_value, this, 0, fFeatures); if (fHandle2 != nullptr) lilv_state_restore(state, fExt.state, fHandle2, carla_lilv_set_port_value, this, 0, fFeatures); lilv_state_free(state); } } } else { // Check if current program is invalid bool programChanged = false; if (newCount == oldCount+1) { // one midi program added, probably created by user pData->midiprog.current = static_cast(oldCount); programChanged = true; } else if (current < 0 && newCount > 0) { // programs exist now, but not before pData->midiprog.current = 0; programChanged = true; } else if (current >= 0 && newCount == 0) { // programs existed before, but not anymore pData->midiprog.current = -1; programChanged = true; } else if (current >= static_cast(newCount)) { // current midi program > count pData->midiprog.current = 0; programChanged = true; } else { // no change pData->midiprog.current = current; } if (programChanged) setMidiProgram(pData->midiprog.current, true, true, true, false); pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0f, nullptr); } } // ------------------------------------------------------------------- // Plugin processing void activate() noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); if (fDescriptor->activate != nullptr) { try { fDescriptor->activate(fHandle); } CARLA_SAFE_EXCEPTION("LV2 activate"); if (fHandle2 != nullptr) { try { fDescriptor->activate(fHandle2); } CARLA_SAFE_EXCEPTION("LV2 activate #2"); } } fFirstActive = true; } void deactivate() noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); if (fDescriptor->deactivate != nullptr) { try { fDescriptor->deactivate(fHandle); } CARLA_SAFE_EXCEPTION("LV2 deactivate"); if (fHandle2 != nullptr) { try { fDescriptor->deactivate(fHandle2); } CARLA_SAFE_EXCEPTION("LV2 deactivate #2"); } } } void process(const float* const* const audioIn, float** const audioOut, const float* const* const cvIn, float** const cvOut, const uint32_t frames) override { // -------------------------------------------------------------------------------------------------------- // Check if active if (! pData->active) { // disable any output sound for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(audioOut[i], frames); for (uint32_t i=0; i < pData->cvOut.count; ++i) carla_zeroFloats(cvOut[i], frames); return; } // -------------------------------------------------------------------------------------------------------- // Event itenerators from different APIs (input) LV2_Atom_Buffer_Iterator evInAtomIters[fEventsIn.count]; LV2_Event_Iterator evInEventIters[fEventsIn.count]; LV2_MIDIState evInMidiStates[fEventsIn.count]; for (uint32_t i=0; i < fEventsIn.count; ++i) { if (fEventsIn.data[i].type & CARLA_EVENT_DATA_ATOM) { lv2_atom_buffer_reset(fEventsIn.data[i].atom, true); lv2_atom_buffer_begin(&evInAtomIters[i], fEventsIn.data[i].atom); } else if (fEventsIn.data[i].type & CARLA_EVENT_DATA_EVENT) { lv2_event_buffer_reset(fEventsIn.data[i].event, LV2_EVENT_AUDIO_STAMP, fEventsIn.data[i].event->data); lv2_event_begin(&evInEventIters[i], fEventsIn.data[i].event); } else if (fEventsIn.data[i].type & CARLA_EVENT_DATA_MIDI_LL) { fEventsIn.data[i].midi.event_count = 0; fEventsIn.data[i].midi.size = 0; evInMidiStates[i].midi = &fEventsIn.data[i].midi; evInMidiStates[i].frame_count = frames; evInMidiStates[i].position = 0; } } for (uint32_t i=0; i < fEventsOut.count; ++i) { if (fEventsOut.data[i].type & CARLA_EVENT_DATA_ATOM) { lv2_atom_buffer_reset(fEventsOut.data[i].atom, false); } else if (fEventsOut.data[i].type & CARLA_EVENT_DATA_EVENT) { lv2_event_buffer_reset(fEventsOut.data[i].event, LV2_EVENT_AUDIO_STAMP, fEventsOut.data[i].event->data); } else if (fEventsOut.data[i].type & CARLA_EVENT_DATA_MIDI_LL) { // not needed } } // -------------------------------------------------------------------------------------------------------- // Check if needs reset if (pData->needsReset) { if (fEventsIn.ctrl != nullptr && (fEventsIn.ctrl->type & CARLA_EVENT_TYPE_MIDI) != 0) { const uint32_t j = fEventsIn.ctrlIndex; CARLA_ASSERT(j < fEventsIn.count); uint8_t midiData[3] = { 0, 0, 0 }; if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { for (uint8_t i=0; i < MAX_MIDI_CHANNELS; ++i) { midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (i & MIDI_CHANNEL_BIT)); midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) lv2_atom_buffer_write(&evInAtomIters[j], 0, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT) lv2_event_write(&evInEventIters[j], 0, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) lv2midi_put_event(&evInMidiStates[j], 0.0, 3, midiData); midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (i & MIDI_CHANNEL_BIT)); midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) lv2_atom_buffer_write(&evInAtomIters[j], 0, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT) lv2_event_write(&evInEventIters[j], 0, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) lv2midi_put_event(&evInMidiStates[j], 0.0, 3, midiData); } } else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) { for (uint8_t k=0; k < MAX_MIDI_NOTE; ++k) { midiData[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (pData->ctrlChannel & MIDI_CHANNEL_BIT)); midiData[1] = k; if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) lv2_atom_buffer_write(&evInAtomIters[j], 0, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT) lv2_event_write(&evInEventIters[j], 0, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) lv2midi_put_event(&evInMidiStates[j], 0.0, 3, midiData); } } } pData->needsReset = false; } // -------------------------------------------------------------------------------------------------------- // TimeInfo const EngineTimeInfo timeInfo(pData->engine->getTimeInfo()); if (fFirstActive || fLastTimeInfo != timeInfo) { bool doPostRt; int32_t rindex; const double barBeat = static_cast(timeInfo.bbt.beat - 1) + (timeInfo.bbt.tick / timeInfo.bbt.ticksPerBeat); // update input ports for (uint32_t k=0; k < pData->param.count; ++k) { if (pData->param.data[k].type != PARAMETER_INPUT) continue; if (pData->param.special[k] != PARAMETER_SPECIAL_TIME) continue; doPostRt = false; rindex = pData->param.data[k].rindex; CARLA_SAFE_ASSERT_CONTINUE(rindex >= 0 && rindex < static_cast(fRdfDescriptor->PortCount)); switch (fRdfDescriptor->Ports[rindex].Designation) { // Non-BBT case LV2_PORT_DESIGNATION_TIME_SPEED: if (fLastTimeInfo.playing != timeInfo.playing) { fParamBuffers[k] = timeInfo.playing ? 1.0f : 0.0f; doPostRt = true; } break; case LV2_PORT_DESIGNATION_TIME_FRAME: if (fLastTimeInfo.frame != timeInfo.frame) { fParamBuffers[k] = static_cast(timeInfo.frame); doPostRt = true; } break; case LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND: break; // BBT case LV2_PORT_DESIGNATION_TIME_BAR: if (timeInfo.bbt.valid && fLastTimeInfo.bbt.bar != timeInfo.bbt.bar) { fParamBuffers[k] = static_cast(timeInfo.bbt.bar - 1); doPostRt = true; } break; case LV2_PORT_DESIGNATION_TIME_BAR_BEAT: if (timeInfo.bbt.valid && (carla_isNotEqual(fLastTimeInfo.bbt.tick, timeInfo.bbt.tick) || fLastTimeInfo.bbt.beat != timeInfo.bbt.beat)) { fParamBuffers[k] = static_cast(barBeat); doPostRt = true; } break; case LV2_PORT_DESIGNATION_TIME_BEAT: if (timeInfo.bbt.valid && fLastTimeInfo.bbt.beat != timeInfo.bbt.beat) { fParamBuffers[k] = static_cast(timeInfo.bbt.beat - 1); doPostRt = true; } break; case LV2_PORT_DESIGNATION_TIME_BEAT_UNIT: if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.beatType, timeInfo.bbt.beatType)) { fParamBuffers[k] = timeInfo.bbt.beatType; doPostRt = true; } break; case LV2_PORT_DESIGNATION_TIME_BEATS_PER_BAR: if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.beatsPerBar, timeInfo.bbt.beatsPerBar)) { fParamBuffers[k] = timeInfo.bbt.beatsPerBar; doPostRt = true; } break; case LV2_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE: if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.beatsPerMinute, timeInfo.bbt.beatsPerMinute)) { fParamBuffers[k] = static_cast(timeInfo.bbt.beatsPerMinute); doPostRt = true; } break; case LV2_PORT_DESIGNATION_TIME_TICKS_PER_BEAT: if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.ticksPerBeat, timeInfo.bbt.ticksPerBeat)) { fParamBuffers[k] = static_cast(timeInfo.bbt.ticksPerBeat); doPostRt = true; } break; } if (doPostRt) pData->postponeRtEvent(kPluginPostRtEventParameterChange, true, static_cast(k), 0, 0, fParamBuffers[k]); } for (uint32_t i=0; i < fEventsIn.count; ++i) { if ((fEventsIn.data[i].type & CARLA_EVENT_DATA_ATOM) == 0 || (fEventsIn.data[i].type & CARLA_EVENT_TYPE_TIME) == 0) continue; uint8_t timeInfoBuf[256]; lv2_atom_forge_set_buffer(&fAtomForge, timeInfoBuf, sizeof(timeInfoBuf)); LV2_Atom_Forge_Frame forgeFrame; lv2_atom_forge_object(&fAtomForge, &forgeFrame, kUridNull, kUridTimePosition); lv2_atom_forge_key(&fAtomForge, kUridTimeSpeed); lv2_atom_forge_float(&fAtomForge, timeInfo.playing ? 1.0f : 0.0f); lv2_atom_forge_key(&fAtomForge, kUridTimeFrame); lv2_atom_forge_long(&fAtomForge, static_cast(timeInfo.frame)); if (timeInfo.bbt.valid) { lv2_atom_forge_key(&fAtomForge, kUridTimeBar); lv2_atom_forge_long(&fAtomForge, timeInfo.bbt.bar - 1); lv2_atom_forge_key(&fAtomForge, kUridTimeBarBeat); lv2_atom_forge_float(&fAtomForge, static_cast(barBeat)); lv2_atom_forge_key(&fAtomForge, kUridTimeBeat); lv2_atom_forge_double(&fAtomForge, timeInfo.bbt.beat - 1); lv2_atom_forge_key(&fAtomForge, kUridTimeBeatUnit); lv2_atom_forge_int(&fAtomForge, static_cast(timeInfo.bbt.beatType)); lv2_atom_forge_key(&fAtomForge, kUridTimeBeatsPerBar); lv2_atom_forge_float(&fAtomForge, timeInfo.bbt.beatsPerBar); lv2_atom_forge_key(&fAtomForge, kUridTimeBeatsPerMinute); lv2_atom_forge_float(&fAtomForge, static_cast(timeInfo.bbt.beatsPerMinute)); lv2_atom_forge_key(&fAtomForge, kUridTimeTicksPerBeat); lv2_atom_forge_double(&fAtomForge, timeInfo.bbt.ticksPerBeat); } lv2_atom_forge_pop(&fAtomForge, &forgeFrame); LV2_Atom* const atom((LV2_Atom*)timeInfoBuf); CARLA_SAFE_ASSERT_BREAK(atom->size < 256); // send only deprecated blank object for now lv2_atom_buffer_write(&evInAtomIters[i], 0, 0, kUridAtomBlank, atom->size, LV2_ATOM_BODY_CONST(atom)); // for atom:object //lv2_atom_buffer_write(&evInAtomIters[i], 0, 0, atom->type, atom->size, LV2_ATOM_BODY_CONST(atom)); } pData->postRtEvents.trySplice(); fLastTimeInfo = timeInfo; } // -------------------------------------------------------------------------------------------------------- // Event Input and Processing if (fEventsIn.ctrl != nullptr) { // ---------------------------------------------------------------------------------------------------- // Message Input if (fAtomBufferEvIn.tryLock()) { if (fAtomBufferEvIn.isDataAvailableForReading()) { const LV2_Atom* atom; uint32_t j, portIndex; for (; fAtomBufferEvIn.get(atom, portIndex);) { j = (portIndex < fEventsIn.count) ? portIndex : fEventsIn.ctrlIndex; if (! lv2_atom_buffer_write(&evInAtomIters[j], 0, 0, atom->type, atom->size, LV2_ATOM_BODY_CONST(atom))) { carla_stderr2("Event input buffer full, at least 1 message lost"); continue; } } } fAtomBufferEvIn.unlock(); } if (fExt.worker != nullptr && fAtomBufferWorkerIn.tryLock()) { if (fAtomBufferWorkerIn.isDataAvailableForReading()) { const LV2_Atom* atom; uint32_t portIndex; for (; fAtomBufferWorkerIn.get(atom, portIndex);) { CARLA_SAFE_ASSERT_CONTINUE(atom->type == kUridCarlaAtomWorkerIn); fExt.worker->work(fHandle, carla_lv2_worker_respond, this, atom->size, LV2_ATOM_BODY_CONST(atom)); } } fAtomBufferWorkerIn.unlock(); } // ---------------------------------------------------------------------------------------------------- // MIDI Input (External) if (pData->extNotes.mutex.tryLock()) { if ((fEventsIn.ctrl->type & CARLA_EVENT_TYPE_MIDI) == 0) { // does not handle MIDI pData->extNotes.data.clear(); } else { const uint32_t j = fEventsIn.ctrlIndex; for (RtLinkedList::Itenerator it = pData->extNotes.data.begin2(); it.valid(); it.next()) { const ExternalMidiNote& note(it.getValue(kExternalMidiNoteFallback)); CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); uint8_t midiEvent[3]; midiEvent[0] = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); midiEvent[1] = note.note; midiEvent[2] = note.velo; if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) lv2_atom_buffer_write(&evInAtomIters[j], 0, 0, kUridMidiEvent, 3, midiEvent); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT) lv2_event_write(&evInEventIters[j], 0, 0, kUridMidiEvent, 3, midiEvent); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) lv2midi_put_event(&evInMidiStates[j], 0.0, 3, midiEvent); } pData->extNotes.data.clear(); } pData->extNotes.mutex.unlock(); } // End of MIDI Input (External) // ---------------------------------------------------------------------------------------------------- // Event Input (System) #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH bool allNotesOffSent = false; #endif bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; uint32_t startTime = 0; uint32_t timeOffset = 0; uint32_t nextBankId; if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) nextBankId = pData->midiprog.data[pData->midiprog.current].bank; else nextBankId = 0; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr) pData->event.cvSourcePorts->initPortBuffers(cvIn + pData->cvIn.count, frames, isSampleAccurate, pData->event.portIn); #endif const uint32_t numEvents = (fEventsIn.ctrl->port != nullptr) ? fEventsIn.ctrl->port->getEventCount() : 0; for (uint32_t i=0; i < numEvents; ++i) { const EngineEvent& event(fEventsIn.ctrl->port->getEvent(i)); uint32_t eventTime = event.time; CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames); if (eventTime < timeOffset) { carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'", eventTime, timeOffset, pData->name); eventTime = timeOffset; } if (isSampleAccurate && eventTime > timeOffset) { if (processSingle(audioIn, audioOut, cvIn, cvOut, eventTime - timeOffset, timeOffset)) { startTime = 0; timeOffset = eventTime; if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) nextBankId = pData->midiprog.data[pData->midiprog.current].bank; else nextBankId = 0; for (uint32_t j=0; j < fEventsIn.count; ++j) { if (fEventsIn.data[j].type & CARLA_EVENT_DATA_ATOM) { lv2_atom_buffer_reset(fEventsIn.data[j].atom, true); lv2_atom_buffer_begin(&evInAtomIters[j], fEventsIn.data[j].atom); } else if (fEventsIn.data[j].type & CARLA_EVENT_DATA_EVENT) { lv2_event_buffer_reset(fEventsIn.data[j].event, LV2_EVENT_AUDIO_STAMP, fEventsIn.data[j].event->data); lv2_event_begin(&evInEventIters[j], fEventsIn.data[j].event); } else if (fEventsIn.data[j].type & CARLA_EVENT_DATA_MIDI_LL) { fEventsIn.data[j].midi.event_count = 0; fEventsIn.data[j].midi.size = 0; evInMidiStates[j].position = eventTime; } } for (uint32_t j=0; j < fEventsOut.count; ++j) { if (fEventsOut.data[j].type & CARLA_EVENT_DATA_ATOM) { lv2_atom_buffer_reset(fEventsOut.data[j].atom, false); } else if (fEventsOut.data[j].type & CARLA_EVENT_DATA_EVENT) { lv2_event_buffer_reset(fEventsOut.data[j].event, LV2_EVENT_AUDIO_STAMP, fEventsOut.data[j].event->data); } else if (fEventsOut.data[j].type & CARLA_EVENT_DATA_MIDI_LL) { // not needed } } } else { startTime += timeOffset; } } switch (event.type) { case kEngineEventTypeNull: break; case kEngineEventTypeControl: { const EngineControlEvent& ctrlEvent(event.ctrl); switch (ctrlEvent.type) { case kEngineControlEventTypeNull: break; case kEngineControlEventTypeParameter: { float value; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // non-midi if (event.channel == kEngineEventNonMidiChannel) { const uint32_t k = ctrlEvent.param; CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count); value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.value); setParameterValueRT(k, value, true); continue; } // Control backend stuff if (event.channel == pData->ctrlChannel) { if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0) { value = ctrlEvent.value; setDryWetRT(value, true); } if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0) { value = ctrlEvent.value*127.0f/100.0f; setVolumeRT(value, true); } if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0) { float left, right; value = ctrlEvent.value/0.5f - 1.0f; if (value < 0.0f) { left = -1.0f; right = (value*2.0f)+1.0f; } else if (value > 0.0f) { left = (value*2.0f)-1.0f; right = 1.0f; } else { left = -1.0f; right = 1.0f; } setBalanceLeftRT(left, true); setBalanceRightRT(right, true); } } #endif // Control plugin parameters uint32_t k; for (k=0; k < pData->param.count; ++k) { if (pData->param.data[k].midiChannel != event.channel) continue; if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) continue; if (pData->param.data[k].type != PARAMETER_INPUT) continue; if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) continue; value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.value); setParameterValueRT(k, value, true); } if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE) { uint8_t midiData[3]; midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); midiData[1] = uint8_t(ctrlEvent.param); midiData[2] = uint8_t(ctrlEvent.value*127.0f); const uint32_t mtime(isSampleAccurate ? startTime : eventTime); if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) lv2_atom_buffer_write(&evInAtomIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT) lv2_event_write(&evInEventIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) lv2midi_put_event(&evInMidiStates[fEventsIn.ctrlIndex], mtime, 3, midiData); } break; } // case kEngineControlEventTypeParameter case kEngineControlEventTypeMidiBank: if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) { if (event.channel == pData->ctrlChannel) nextBankId = ctrlEvent.param; } else if (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) { uint8_t midiData[3]; midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); midiData[1] = MIDI_CONTROL_BANK_SELECT; midiData[2] = uint8_t(ctrlEvent.param); const uint32_t mtime(isSampleAccurate ? startTime : eventTime); if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) lv2_atom_buffer_write(&evInAtomIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT) lv2_event_write(&evInEventIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) lv2midi_put_event(&evInMidiStates[fEventsIn.ctrlIndex], mtime, 3, midiData); } break; case kEngineControlEventTypeMidiProgram: if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) { if (event.channel == pData->ctrlChannel) { const uint32_t nextProgramId(ctrlEvent.param); for (uint32_t k=0; k < pData->midiprog.count; ++k) { if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId) { setMidiProgramRT(k, true); break; } } } } else if (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) { uint8_t midiData[2]; midiData[0] = uint8_t(MIDI_STATUS_PROGRAM_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); midiData[1] = uint8_t(ctrlEvent.param); const uint32_t mtime(isSampleAccurate ? startTime : eventTime); if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) lv2_atom_buffer_write(&evInAtomIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 2, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT) lv2_event_write(&evInEventIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 2, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) lv2midi_put_event(&evInMidiStates[fEventsIn.ctrlIndex], mtime, 2, midiData); } break; case kEngineControlEventTypeAllSoundOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { const uint32_t mtime(isSampleAccurate ? startTime : eventTime); uint8_t midiData[3]; midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; midiData[2] = 0; if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) lv2_atom_buffer_write(&evInAtomIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT) lv2_event_write(&evInEventIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) lv2midi_put_event(&evInMidiStates[fEventsIn.ctrlIndex], mtime, 3, midiData); } break; case kEngineControlEventTypeAllNotesOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (event.channel == pData->ctrlChannel && ! allNotesOffSent) { allNotesOffSent = true; postponeRtAllNotesOff(); } #endif const uint32_t mtime(isSampleAccurate ? startTime : eventTime); uint8_t midiData[3]; midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; midiData[2] = 0; if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) lv2_atom_buffer_write(&evInAtomIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT) lv2_event_write(&evInEventIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) lv2midi_put_event(&evInMidiStates[fEventsIn.ctrlIndex], mtime, 3, midiData); } break; } // switch (ctrlEvent.type) break; } // case kEngineEventTypeControl case kEngineEventTypeMidi: { const EngineMidiEvent& midiEvent(event.midi); const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data); uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData)); if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) continue; if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0) continue; if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0) continue; if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) continue; // Fix bad note-off (per LV2 spec) if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0) status = MIDI_STATUS_NOTE_OFF; const uint32_t j = fEventsIn.ctrlIndex; const uint32_t mtime = isSampleAccurate ? startTime : eventTime; // put back channel in data uint8_t midiData2[midiEvent.size]; midiData2[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT)); std::memcpy(midiData2+1, midiData+1, static_cast(midiEvent.size-1)); if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) lv2_atom_buffer_write(&evInAtomIters[j], mtime, 0, kUridMidiEvent, midiEvent.size, midiData2); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT) lv2_event_write(&evInEventIters[j], mtime, 0, kUridMidiEvent, midiEvent.size, midiData2); else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) lv2midi_put_event(&evInMidiStates[j], mtime, midiEvent.size, midiData2); if (status == MIDI_STATUS_NOTE_ON) { pData->postponeRtEvent(kPluginPostRtEventNoteOn, true, event.channel, midiData[1], midiData[2], 0.0f); } else if (status == MIDI_STATUS_NOTE_OFF) { pData->postponeRtEvent(kPluginPostRtEventNoteOff, true, event.channel, midiData[1], 0, 0.0f); } } break; } // switch (event.type) } pData->postRtEvents.trySplice(); if (frames > timeOffset) processSingle(audioIn, audioOut, cvIn, cvOut, frames - timeOffset, timeOffset); } // End of Event Input and Processing // -------------------------------------------------------------------------------------------------------- // Plugin processing (no events) else { processSingle(audioIn, audioOut, cvIn, cvOut, frames, 0); } // End of Plugin processing (no events) // -------------------------------------------------------------------------------------------------------- // Events/MIDI Output for (uint32_t i=0; i < fEventsOut.count; ++i) { uint32_t lastFrame = 0; Lv2EventData& evData(fEventsOut.data[i]); if (evData.type & CARLA_EVENT_DATA_ATOM) { const LV2_Atom_Event* ev; LV2_Atom_Buffer_Iterator iter; uint8_t* data; lv2_atom_buffer_begin(&iter, evData.atom); for (;;) { data = nullptr; ev = lv2_atom_buffer_get(&iter, &data); if (ev == nullptr || ev->body.size == 0 || data == nullptr) break; if (ev->body.type == kUridMidiEvent) { if (evData.port != nullptr) { CARLA_SAFE_ASSERT_CONTINUE(ev->time.frames >= 0); CARLA_SAFE_ASSERT_CONTINUE(ev->body.size < 0xFF); uint32_t currentFrame = static_cast(ev->time.frames); if (currentFrame < lastFrame) currentFrame = lastFrame; else if (currentFrame >= frames) currentFrame = frames - 1; evData.port->writeMidiEvent(currentFrame, static_cast(ev->body.size), data); } } else if (fAtomBufferUiOutTmpData != nullptr) { fAtomBufferUiOut.put(&ev->body, evData.rindex); } lv2_atom_buffer_increment(&iter); } } else if ((evData.type & CARLA_EVENT_DATA_EVENT) != 0 && evData.port != nullptr) { const LV2_Event* ev; LV2_Event_Iterator iter; uint8_t* data; lv2_event_begin(&iter, evData.event); for (;;) { data = nullptr; ev = lv2_event_get(&iter, &data); if (ev == nullptr || data == nullptr) break; uint32_t currentFrame = ev->frames; if (currentFrame < lastFrame) currentFrame = lastFrame; else if (currentFrame >= frames) currentFrame = frames - 1; if (ev->type == kUridMidiEvent) { CARLA_SAFE_ASSERT_CONTINUE(ev->size < 0xFF); evData.port->writeMidiEvent(currentFrame, static_cast(ev->size), data); } lv2_event_increment(&iter); } } else if ((evData.type & CARLA_EVENT_DATA_MIDI_LL) != 0 && evData.port != nullptr) { LV2_MIDIState state = { &evData.midi, frames, 0 }; uint32_t eventSize; double eventTime; uchar* eventData; for (;;) { eventSize = 0; eventTime = 0.0; eventData = nullptr; lv2midi_get_event(&state, &eventTime, &eventSize, &eventData); if (eventData == nullptr || eventSize == 0) break; CARLA_SAFE_ASSERT_CONTINUE(eventSize < 0xFF); CARLA_SAFE_ASSERT_CONTINUE(eventTime >= 0.0); evData.port->writeMidiEvent(static_cast(eventTime), static_cast(eventSize), eventData); lv2midi_step(&state); } } } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // -------------------------------------------------------------------------------------------------------- // Control Output if (pData->event.portOut != nullptr) { uint8_t channel; uint16_t param; float value; for (uint32_t k=0; k < pData->param.count; ++k) { if (pData->param.data[k].type != PARAMETER_OUTPUT) continue; if (fStrictBounds >= 0 && (pData->param.data[k].hints & PARAMETER_IS_STRICT_BOUNDS) != 0) // plugin is responsible to ensure correct bounds pData->param.ranges[k].fixValue(fParamBuffers[k]); if (pData->param.data[k].mappedControlIndex > 0) { channel = pData->param.data[k].midiChannel; param = static_cast(pData->param.data[k].mappedControlIndex); value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]); pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value); } } } // End of Control Output #endif // -------------------------------------------------------------------------------------------------------- // Final work if (fEventsIn.ctrl != nullptr && fExt.worker != nullptr && fAtomBufferWorkerResp.tryLock()) { if (fAtomBufferWorkerResp.isDataAvailableForReading()) { const LV2_Atom* atom; uint32_t portIndex; for (; fAtomBufferWorkerResp.get(atom, portIndex);) { CARLA_SAFE_ASSERT_CONTINUE(atom->type == kUridCarlaAtomWorkerResp); fExt.worker->work_response(fHandle, atom->size, LV2_ATOM_BODY_CONST(atom)); } } fAtomBufferWorkerResp.unlock(); } if (fExt.worker != nullptr && fExt.worker->end_run != nullptr) { fExt.worker->end_run(fHandle); if (fHandle2 != nullptr) fExt.worker->end_run(fHandle2); } fFirstActive = false; // -------------------------------------------------------------------------------------------------------- } bool processSingle(const float* const* const audioIn, float** const audioOut, const float* const* const cvIn, float** const cvOut, const uint32_t frames, const uint32_t timeOffset) { CARLA_SAFE_ASSERT_RETURN(frames > 0, false); if (pData->audioIn.count > 0) { CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fAudioInBuffers != nullptr, false); } if (pData->audioOut.count > 0) { CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fAudioOutBuffers != nullptr, false); } if (pData->cvIn.count > 0) { CARLA_SAFE_ASSERT_RETURN(cvIn != nullptr, false); } if (pData->cvOut.count > 0) { CARLA_SAFE_ASSERT_RETURN(cvOut != nullptr, false); } // -------------------------------------------------------------------------------------------------------- // Try lock, silence otherwise #ifndef STOAT_TEST_BUILD if (pData->engine->isOffline()) { pData->singleMutex.lock(); } else #endif if (! pData->singleMutex.tryLock()) { for (uint32_t i=0; i < pData->audioOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) audioOut[i][k+timeOffset] = 0.0f; } for (uint32_t i=0; i < pData->cvOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) cvOut[i][k+timeOffset] = 0.0f; } return false; } // -------------------------------------------------------------------------------------------------------- // Set audio buffers for (uint32_t i=0; i < pData->audioIn.count; ++i) carla_copyFloats(fAudioInBuffers[i], audioIn[i]+timeOffset, frames); for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(fAudioOutBuffers[i], frames); // -------------------------------------------------------------------------------------------------------- // Set CV buffers for (uint32_t i=0; i < pData->cvIn.count; ++i) carla_copyFloats(fCvInBuffers[i], cvIn[i]+timeOffset, frames); for (uint32_t i=0; i < pData->cvOut.count; ++i) carla_zeroFloats(fCvOutBuffers[i], frames); // -------------------------------------------------------------------------------------------------------- // Run plugin fDescriptor->run(fHandle, frames); if (fHandle2 != nullptr) fDescriptor->run(fHandle2, frames); // -------------------------------------------------------------------------------------------------------- // Handle trigger parameters for (uint32_t k=0; k < pData->param.count; ++k) { if (pData->param.data[k].type != PARAMETER_INPUT) continue; if (pData->param.data[k].hints & PARAMETER_IS_TRIGGER) { if (carla_isNotEqual(fParamBuffers[k], pData->param.ranges[k].def)) { fParamBuffers[k] = pData->param.ranges[k].def; pData->postponeRtEvent(kPluginPostRtEventParameterChange, true, static_cast(k), 1, 0, fParamBuffers[k]); } } } pData->postRtEvents.trySplice(); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // -------------------------------------------------------------------------------------------------------- // Post-processing (dry/wet, volume and balance) { const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f); const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f)); const bool isMono = (pData->audioIn.count == 1); bool isPair; float bufValue, oldBufLeft[doBalance ? frames : 1]; for (uint32_t i=0; i < pData->audioOut.count; ++i) { // Dry/Wet if (doDryWet) { const uint32_t c = isMono ? 0 : i; for (uint32_t k=0; k < frames; ++k) { # ifndef BUILD_BRIDGE if (k < pData->latency.frames && pData->latency.buffers != nullptr) bufValue = pData->latency.buffers[c][k]; else if (pData->latency.frames < frames) bufValue = fAudioInBuffers[c][k-pData->latency.frames]; else # endif bufValue = fAudioInBuffers[c][k]; fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet)); } } // Balance if (doBalance) { isPair = (i % 2 == 0); if (isPair) { CARLA_ASSERT(i+1 < pData->audioOut.count); carla_copyFloats(oldBufLeft, fAudioOutBuffers[i], frames); } float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f; float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f; for (uint32_t k=0; k < frames; ++k) { if (isPair) { // left fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL); fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR); } else { // right fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR; fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL; } } } // Volume (and buffer copy) { for (uint32_t k=0; k < frames; ++k) audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k] * pData->postProc.volume; } } } // End of Post-processing # ifndef BUILD_BRIDGE // -------------------------------------------------------------------------------------------------------- // Save latency values for next callback if (pData->latency.frames != 0 && pData->latency.buffers != nullptr) { CARLA_SAFE_ASSERT(timeOffset == 0); const uint32_t latframes = pData->latency.frames; if (latframes <= frames) { for (uint32_t i=0; i < pData->audioIn.count; ++i) carla_copyFloats(pData->latency.buffers[i], audioIn[i]+(frames-latframes), latframes); } else { const uint32_t diff = latframes - frames; for (uint32_t i=0, k; iaudioIn.count; ++i) { // push back buffer by 'frames' for (k=0; k < diff; ++k) pData->latency.buffers[i][k] = pData->latency.buffers[i][k+frames]; // put current input at the end for (uint32_t j=0; k < latframes; ++j, ++k) pData->latency.buffers[i][k] = audioIn[i][j]; } } } # endif #else // BUILD_BRIDGE_ALTERNATIVE_ARCH for (uint32_t i=0; i < pData->audioOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k]; } #endif for (uint32_t i=0; i < pData->cvOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) cvOut[i][k+timeOffset] = fCvOutBuffers[i][k]; } // -------------------------------------------------------------------------------------------------------- pData->singleMutex.unlock(); return true; } void bufferSizeChanged(const uint32_t newBufferSize) override { CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize); carla_debug("CarlaPluginLV2::bufferSizeChanged(%i) - start", newBufferSize); for (uint32_t i=0; i < pData->audioIn.count; ++i) { if (fAudioInBuffers[i] != nullptr) delete[] fAudioInBuffers[i]; fAudioInBuffers[i] = new float[newBufferSize]; } for (uint32_t i=0; i < pData->audioOut.count; ++i) { if (fAudioOutBuffers[i] != nullptr) delete[] fAudioOutBuffers[i]; fAudioOutBuffers[i] = new float[newBufferSize]; } if (fHandle2 == nullptr) { for (uint32_t i=0; i < pData->audioIn.count; ++i) { CARLA_ASSERT(fAudioInBuffers[i] != nullptr); fDescriptor->connect_port(fHandle, pData->audioIn.ports[i].rindex, fAudioInBuffers[i]); } for (uint32_t i=0; i < pData->audioOut.count; ++i) { CARLA_ASSERT(fAudioOutBuffers[i] != nullptr); fDescriptor->connect_port(fHandle, pData->audioOut.ports[i].rindex, fAudioOutBuffers[i]); } } else { if (pData->audioIn.count > 0) { CARLA_ASSERT(pData->audioIn.count == 2); CARLA_ASSERT(fAudioInBuffers[0] != nullptr); CARLA_ASSERT(fAudioInBuffers[1] != nullptr); fDescriptor->connect_port(fHandle, pData->audioIn.ports[0].rindex, fAudioInBuffers[0]); fDescriptor->connect_port(fHandle2, pData->audioIn.ports[1].rindex, fAudioInBuffers[1]); } if (pData->audioOut.count > 0) { CARLA_ASSERT(pData->audioOut.count == 2); CARLA_ASSERT(fAudioOutBuffers[0] != nullptr); CARLA_ASSERT(fAudioOutBuffers[1] != nullptr); fDescriptor->connect_port(fHandle, pData->audioOut.ports[0].rindex, fAudioOutBuffers[0]); fDescriptor->connect_port(fHandle2, pData->audioOut.ports[1].rindex, fAudioOutBuffers[1]); } } for (uint32_t i=0; i < pData->cvIn.count; ++i) { if (fCvInBuffers[i] != nullptr) delete[] fCvInBuffers[i]; fCvInBuffers[i] = new float[newBufferSize]; fDescriptor->connect_port(fHandle, pData->cvIn.ports[i].rindex, fCvInBuffers[i]); if (fHandle2 != nullptr) fDescriptor->connect_port(fHandle2, pData->cvIn.ports[i].rindex, fCvInBuffers[i]); } for (uint32_t i=0; i < pData->cvOut.count; ++i) { if (fCvOutBuffers[i] != nullptr) delete[] fCvOutBuffers[i]; fCvOutBuffers[i] = new float[newBufferSize]; fDescriptor->connect_port(fHandle, pData->cvOut.ports[i].rindex, fCvOutBuffers[i]); if (fHandle2 != nullptr) fDescriptor->connect_port(fHandle2, pData->cvOut.ports[i].rindex, fCvOutBuffers[i]); } const int newBufferSizeInt(static_cast(newBufferSize)); if (fLv2Options.maxBufferSize != newBufferSizeInt || (fLv2Options.minBufferSize != 1 && fLv2Options.minBufferSize != newBufferSizeInt)) { fLv2Options.maxBufferSize = fLv2Options.nominalBufferSize = newBufferSizeInt; if (fLv2Options.minBufferSize != 1) fLv2Options.minBufferSize = newBufferSizeInt; if (fExt.options != nullptr && fExt.options->set != nullptr) { fExt.options->set(fHandle, &fLv2Options.opts[CarlaPluginLV2Options::MaxBlockLenth]); fExt.options->set(fHandle, &fLv2Options.opts[CarlaPluginLV2Options::NominalBlockLenth]); if (fLv2Options.minBufferSize != 1) fExt.options->set(fHandle, &fLv2Options.opts[CarlaPluginLV2Options::MinBlockLenth]); } } carla_debug("CarlaPluginLV2::bufferSizeChanged(%i) - end", newBufferSize); } void sampleRateChanged(const double newSampleRate) override { CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate); carla_debug("CarlaPluginLV2::sampleRateChanged(%g) - start", newSampleRate); const float sampleRatef = static_cast(newSampleRate); if (carla_isNotEqual(fLv2Options.sampleRate, sampleRatef)) { fLv2Options.sampleRate = sampleRatef; if (fExt.options != nullptr && fExt.options->set != nullptr) { LV2_Options_Option options[2]; carla_zeroStructs(options, 2); LV2_Options_Option& optSampleRate(options[0]); optSampleRate.context = LV2_OPTIONS_INSTANCE; optSampleRate.subject = 0; optSampleRate.key = kUridParamSampleRate; optSampleRate.size = sizeof(float); optSampleRate.type = kUridAtomFloat; optSampleRate.value = &fLv2Options.sampleRate; fExt.options->set(fHandle, options); } } for (uint32_t k=0; k < pData->param.count; ++k) { if (pData->param.data[k].type != PARAMETER_INPUT) continue; if (pData->param.special[k] != PARAMETER_SPECIAL_SAMPLE_RATE) continue; fParamBuffers[k] = sampleRatef; pData->postponeRtEvent(kPluginPostRtEventParameterChange, true, static_cast(k), 0, 0, fParamBuffers[k]); break; } carla_debug("CarlaPluginLV2::sampleRateChanged(%g) - end", newSampleRate); } void offlineModeChanged(const bool isOffline) override { for (uint32_t k=0; k < pData->param.count; ++k) { if (pData->param.data[k].type == PARAMETER_INPUT && pData->param.special[k] == PARAMETER_SPECIAL_FREEWHEEL) { fParamBuffers[k] = isOffline ? pData->param.ranges[k].max : pData->param.ranges[k].min; pData->postponeRtEvent(kPluginPostRtEventParameterChange, true, static_cast(k), 0, 0, fParamBuffers[k]); break; } } } // ------------------------------------------------------------------- // Plugin buffers void initBuffers() const noexcept override { fEventsIn.initBuffers(); fEventsOut.initBuffers(); CarlaPlugin::initBuffers(); } void clearBuffers() noexcept override { carla_debug("CarlaPluginLV2::clearBuffers() - start"); if (fAudioInBuffers != nullptr) { for (uint32_t i=0; i < pData->audioIn.count; ++i) { if (fAudioInBuffers[i] != nullptr) { delete[] fAudioInBuffers[i]; fAudioInBuffers[i] = nullptr; } } delete[] fAudioInBuffers; fAudioInBuffers = nullptr; } if (fAudioOutBuffers != nullptr) { for (uint32_t i=0; i < pData->audioOut.count; ++i) { if (fAudioOutBuffers[i] != nullptr) { delete[] fAudioOutBuffers[i]; fAudioOutBuffers[i] = nullptr; } } delete[] fAudioOutBuffers; fAudioOutBuffers = nullptr; } if (fCvInBuffers != nullptr) { for (uint32_t i=0; i < pData->cvIn.count; ++i) { if (fCvInBuffers[i] != nullptr) { delete[] fCvInBuffers[i]; fCvInBuffers[i] = nullptr; } } delete[] fCvInBuffers; fCvInBuffers = nullptr; } if (fCvOutBuffers != nullptr) { for (uint32_t i=0; i < pData->cvOut.count; ++i) { if (fCvOutBuffers[i] != nullptr) { delete[] fCvOutBuffers[i]; fCvOutBuffers[i] = nullptr; } } delete[] fCvOutBuffers; fCvOutBuffers = nullptr; } if (fParamBuffers != nullptr) { delete[] fParamBuffers; fParamBuffers = nullptr; } fEventsIn.clear(); fEventsOut.clear(); CarlaPlugin::clearBuffers(); carla_debug("CarlaPluginLV2::clearBuffers() - end"); } // ------------------------------------------------------------------- // Post-poned UI Stuff void uiParameterChange(const uint32_t index, const float value) noexcept override { CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty(),); CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,); if (fUI.type == UI::TYPE_BRIDGE) { if (fPipeServer.isPipeRunning()) fPipeServer.writeControlMessage(static_cast(pData->param.data[index].rindex), value); } else { if (fUI.handle != nullptr && fUI.descriptor != nullptr && fUI.descriptor->port_event != nullptr && ! fNeedsUiClose) { CARLA_SAFE_ASSERT_RETURN(pData->param.data[index].rindex >= 0,); fUI.descriptor->port_event(fUI.handle, static_cast(pData->param.data[index].rindex), sizeof(float), kUridNull, &value); } } } void uiMidiProgramChange(const uint32_t index) noexcept override { CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty(),); CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,); if (fUI.type == UI::TYPE_BRIDGE) { if (fPipeServer.isPipeRunning()) fPipeServer.writeMidiProgramMessage(pData->midiprog.data[index].bank, pData->midiprog.data[index].program); } else { if (fExt.uiprograms != nullptr && fExt.uiprograms->select_program != nullptr && ! fNeedsUiClose) fExt.uiprograms->select_program(fUI.handle, pData->midiprog.data[index].bank, pData->midiprog.data[index].program); } } void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override { CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty(),); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,); #if 0 if (fUI.type == UI::TYPE_BRIDGE) { if (fPipeServer.isPipeRunning()) fPipeServer.writeMidiNoteMessage(false, channel, note, velo); } else { if (fUI.handle != nullptr && fUI.descriptor != nullptr && fUI.descriptor->port_event != nullptr && fEventsIn.ctrl != nullptr && ! fNeedsUiClose) { LV2_Atom_MidiEvent midiEv; midiEv.atom.type = kUridMidiEvent; midiEv.atom.size = 3; midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); midiEv.data[1] = note; midiEv.data[2] = velo; fUI.descriptor->port_event(fUI.handle, fEventsIn.ctrl->rindex, lv2_atom_total_size(midiEv), kUridAtomTransferEvent, &midiEv); } } #endif } void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override { CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty(),); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); #if 0 if (fUI.type == UI::TYPE_BRIDGE) { if (fPipeServer.isPipeRunning()) fPipeServer.writeMidiNoteMessage(false, channel, note, 0); } else { if (fUI.handle != nullptr && fUI.descriptor != nullptr && fUI.descriptor->port_event != nullptr && fEventsIn.ctrl != nullptr && ! fNeedsUiClose) { LV2_Atom_MidiEvent midiEv; midiEv.atom.type = kUridMidiEvent; midiEv.atom.size = 3; midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & MIDI_CHANNEL_BIT)); midiEv.data[1] = note; midiEv.data[2] = 0; fUI.descriptor->port_event(fUI.handle, fEventsIn.ctrl->rindex, lv2_atom_total_size(midiEv), kUridAtomTransferEvent, &midiEv); } } #endif } // ------------------------------------------------------------------- // Internal helper functions void restoreLV2State() noexcept override { if (fExt.state == nullptr) return; LV2_State_Status status = LV2_STATE_ERR_UNKNOWN; { const ScopedSingleProcessLocker spl(this, true); try { status = fExt.state->restore(fHandle, carla_lv2_state_retrieve, this, 0, fFeatures); } catch(...) {} if (fHandle2 != nullptr) { try { fExt.state->restore(fHandle, carla_lv2_state_retrieve, this, 0, fFeatures); } catch(...) {} } } switch (status) { case LV2_STATE_SUCCESS: carla_debug("CarlaPluginLV2::updateLV2State() - success"); break; case LV2_STATE_ERR_UNKNOWN: carla_stderr("CarlaPluginLV2::updateLV2State() - unknown error"); break; case LV2_STATE_ERR_BAD_TYPE: carla_stderr("CarlaPluginLV2::updateLV2State() - error, bad type"); break; case LV2_STATE_ERR_BAD_FLAGS: carla_stderr("CarlaPluginLV2::updateLV2State() - error, bad flags"); break; case LV2_STATE_ERR_NO_FEATURE: carla_stderr("CarlaPluginLV2::updateLV2State() - error, missing feature"); break; case LV2_STATE_ERR_NO_PROPERTY: carla_stderr("CarlaPluginLV2::updateLV2State() - error, missing property"); break; case LV2_STATE_ERR_NO_SPACE: carla_stderr("CarlaPluginLV2::updateLV2State() - error, insufficient space"); break; } } // ------------------------------------------------------------------- bool isRealtimeSafe() const noexcept { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); for (uint32_t i=0; i < fRdfDescriptor->FeatureCount; ++i) { if (std::strcmp(fRdfDescriptor->Features[i].URI, LV2_CORE__hardRTCapable) == 0) return true; } return false; } // ------------------------------------------------------------------- bool isUiBridgeable(const uint32_t uiId) const noexcept { CARLA_SAFE_ASSERT_RETURN(uiId < fRdfDescriptor->UICount, false); #ifndef LV2_UIS_ONLY_INPROCESS const LV2_RDF_UI* const rdfUI(&fRdfDescriptor->UIs[uiId]); for (uint32_t i=0; i < rdfUI->FeatureCount; ++i) { const LV2_RDF_Feature& feat(rdfUI->Features[i]); if (! feat.Required) continue; if (std::strcmp(feat.URI, LV2_INSTANCE_ACCESS_URI) == 0) return false; if (std::strcmp(feat.URI, LV2_DATA_ACCESS_URI) == 0) return false; } // Calf UIs are mostly useless without their special graphs // but they can be crashy under certain conditions, so follow user preferences if (std::strstr(rdfUI->URI, "http://calf.sourceforge.net/plugins/gui/") != nullptr) return pData->engine->getOptions().preferUiBridges; // LSP-Plugins UIs make heavy use of URIDs, for which carla right now is very slow // FIXME after some optimization, remove this if (std::strstr(rdfUI->URI, "http://lsp-plug.in/ui/lv2/") != nullptr) return false; return true; #else return false; #endif } bool isUiResizable() const noexcept { CARLA_SAFE_ASSERT_RETURN(fUI.rdfDescriptor != nullptr, false); for (uint32_t i=0; i < fUI.rdfDescriptor->FeatureCount; ++i) { if (std::strcmp(fUI.rdfDescriptor->Features[i].URI, LV2_UI__fixedSize) == 0) return false; if (std::strcmp(fUI.rdfDescriptor->Features[i].URI, LV2_UI__noUserResize) == 0) return false; } return true; } const char* getUiBridgeBinary(const LV2_Property type) const { CarlaString bridgeBinary(pData->engine->getOptions().binaryDir); if (bridgeBinary.isEmpty()) return nullptr; switch (type) { case LV2_UI_GTK2: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-gtk2"; break; case LV2_UI_GTK3: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-gtk3"; break; case LV2_UI_QT4: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-qt4"; break; case LV2_UI_QT5: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-qt5"; break; case LV2_UI_COCOA: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-cocoa"; break; case LV2_UI_WINDOWS: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-windows"; break; case LV2_UI_X11: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-x11"; break; case LV2_UI_MOD: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-modgui"; break; #if 0 case LV2_UI_EXTERNAL: case LV2_UI_OLD_EXTERNAL: bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-external"; break; #endif default: return nullptr; } #ifdef CARLA_OS_WIN bridgeBinary += ".exe"; #endif if (! File(bridgeBinary.buffer()).existsAsFile()) return nullptr; return bridgeBinary.dupSafe(); } // ------------------------------------------------------------------- void recheckExtensions() { CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr,); carla_debug("CarlaPluginLV2::recheckExtensions()"); fExt.options = nullptr; fExt.programs = nullptr; fExt.state = nullptr; fExt.worker = nullptr; fExt.inlineDisplay = nullptr; for (uint32_t i=0; i < fRdfDescriptor->ExtensionCount; ++i) { const char* const extension = fRdfDescriptor->Extensions[i]; CARLA_SAFE_ASSERT_CONTINUE(extension != nullptr); /**/ if (std::strcmp(extension, LV2_OPTIONS__interface) == 0) pData->hints |= PLUGIN_HAS_EXTENSION_OPTIONS; else if (std::strcmp(extension, LV2_PROGRAMS__Interface) == 0) pData->hints |= PLUGIN_HAS_EXTENSION_PROGRAMS; else if (std::strcmp(extension, LV2_STATE__interface) == 0) pData->hints |= PLUGIN_HAS_EXTENSION_STATE; else if (std::strcmp(extension, LV2_WORKER__interface) == 0) pData->hints |= PLUGIN_HAS_EXTENSION_WORKER; else if (std::strcmp(extension, LV2_INLINEDISPLAY__interface) == 0) pData->hints |= PLUGIN_HAS_EXTENSION_INLINE_DISPLAY; else if (std::strcmp(extension, LV2_MIDNAM__interface) == 0) pData->hints |= PLUGIN_HAS_EXTENSION_MIDNAM; else carla_stdout("Plugin '%s' has non-supported extension: '%s'", fRdfDescriptor->URI, extension); } // Fix for broken plugins, nasty! for (uint32_t i=0; i < fRdfDescriptor->FeatureCount; ++i) { const LV2_RDF_Feature& feature(fRdfDescriptor->Features[i]); if (std::strcmp(feature.URI, LV2_INLINEDISPLAY__queue_draw) == 0) { if (pData->hints & PLUGIN_HAS_EXTENSION_INLINE_DISPLAY) break; carla_stdout("Plugin '%s' uses inline-display but does not set extension data, nasty!", fRdfDescriptor->URI); pData->hints |= PLUGIN_HAS_EXTENSION_INLINE_DISPLAY; } else if (std::strcmp(feature.URI, LV2_MIDNAM__update) == 0) { if (pData->hints & PLUGIN_HAS_EXTENSION_MIDNAM) break; carla_stdout("Plugin '%s' uses midnam but does not set extension data, nasty!", fRdfDescriptor->URI); pData->hints |= PLUGIN_HAS_EXTENSION_MIDNAM; } } if (fDescriptor->extension_data != nullptr) { if (pData->hints & PLUGIN_HAS_EXTENSION_OPTIONS) fExt.options = (const LV2_Options_Interface*)fDescriptor->extension_data(LV2_OPTIONS__interface); if (pData->hints & PLUGIN_HAS_EXTENSION_PROGRAMS) fExt.programs = (const LV2_Programs_Interface*)fDescriptor->extension_data(LV2_PROGRAMS__Interface); if (pData->hints & PLUGIN_HAS_EXTENSION_STATE) fExt.state = (const LV2_State_Interface*)fDescriptor->extension_data(LV2_STATE__interface); if (pData->hints & PLUGIN_HAS_EXTENSION_WORKER) fExt.worker = (const LV2_Worker_Interface*)fDescriptor->extension_data(LV2_WORKER__interface); if (pData->hints & PLUGIN_HAS_EXTENSION_INLINE_DISPLAY) fExt.inlineDisplay = (const LV2_Inline_Display_Interface*)fDescriptor->extension_data(LV2_INLINEDISPLAY__interface); if (pData->hints & PLUGIN_HAS_EXTENSION_MIDNAM) fExt.midnam = (const LV2_Midnam_Interface*)fDescriptor->extension_data(LV2_MIDNAM__interface); // check if invalid if (fExt.options != nullptr && fExt.options->get == nullptr && fExt.options->set == nullptr) fExt.options = nullptr; if (fExt.programs != nullptr && (fExt.programs->get_program == nullptr || fExt.programs->select_program == nullptr)) fExt.programs = nullptr; if (fExt.state != nullptr && (fExt.state->save == nullptr || fExt.state->restore == nullptr)) fExt.state = nullptr; if (fExt.worker != nullptr && fExt.worker->work == nullptr) fExt.worker = nullptr; if (fExt.inlineDisplay != nullptr) { if (fExt.inlineDisplay->render != nullptr) { pData->hints |= PLUGIN_HAS_INLINE_DISPLAY; pData->setCanDeleteLib(false); } else { fExt.inlineDisplay = nullptr; } } if (fExt.midnam != nullptr && fExt.midnam->midnam == nullptr) fExt.midnam = nullptr; } CARLA_SAFE_ASSERT_RETURN(fLatencyIndex == -1,); int32_t iCtrl=0; for (uint32_t i=0, count=fRdfDescriptor->PortCount; iPorts[i].Types); if (! LV2_IS_PORT_CONTROL(portTypes)) continue; const CarlaScopedValueSetter svs(iCtrl, iCtrl, iCtrl+1); if (! LV2_IS_PORT_OUTPUT(portTypes)) continue; const LV2_Property portDesignation(fRdfDescriptor->Ports[i].Designation); if (! LV2_IS_PORT_DESIGNATION_LATENCY(portDesignation)) continue; fLatencyIndex = iCtrl; break; } } // ------------------------------------------------------------------- void updateUi() { CARLA_SAFE_ASSERT_RETURN(fUI.handle != nullptr,); CARLA_SAFE_ASSERT_RETURN(fUI.descriptor != nullptr,); carla_debug("CarlaPluginLV2::updateUi()"); // update midi program if (fExt.uiprograms != nullptr && pData->midiprog.count > 0 && pData->midiprog.current >= 0) { const MidiProgramData& curData(pData->midiprog.getCurrent()); fExt.uiprograms->select_program(fUI.handle, curData.bank, curData.program); } // update control ports if (fUI.descriptor->port_event != nullptr) { float value; for (uint32_t i=0; i < pData->param.count; ++i) { value = getParameterValue(i); fUI.descriptor->port_event(fUI.handle, static_cast(pData->param.data[i].rindex), sizeof(float), kUridNull, &value); } } } // ------------------------------------------------------------------- LV2_URID getCustomURID(const char* const uri) { CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', kUridNull); carla_debug("CarlaPluginLV2::getCustomURID(\"%s\")", uri); const std::string s_uri(uri); const std::ptrdiff_t s_pos(std::find(fCustomURIDs.begin(), fCustomURIDs.end(), s_uri) - fCustomURIDs.begin()); if (s_pos <= 0 || s_pos >= INT32_MAX) return kUridNull; const LV2_URID urid = static_cast(s_pos); const LV2_URID uriCount = static_cast(fCustomURIDs.size()); if (urid < uriCount) return urid; CARLA_SAFE_ASSERT(urid == uriCount); fCustomURIDs.push_back(uri); if (fUI.type == UI::TYPE_BRIDGE && fPipeServer.isPipeRunning()) fPipeServer.writeLv2UridMessage(urid, uri); return urid; } const char* getCustomURIDString(const LV2_URID urid) const noexcept { CARLA_SAFE_ASSERT_RETURN(urid != kUridNull, kUnmapFallback); CARLA_SAFE_ASSERT_RETURN(urid < fCustomURIDs.size(), kUnmapFallback); carla_debug("CarlaPluginLV2::getCustomURIString(%i)", urid); return fCustomURIDs[urid].c_str(); } // ------------------------------------------------------------------- void handleProgramChanged(const int32_t index) { CARLA_SAFE_ASSERT_RETURN(index >= -1,); carla_debug("CarlaPluginLV2::handleProgramChanged(%i)", index); if (index == -1) { const ScopedSingleProcessLocker spl(this, true); return reloadPrograms(false); } if (index < static_cast(pData->midiprog.count) && fExt.programs != nullptr && fExt.programs->get_program != nullptr) { if (const LV2_Program_Descriptor* const progDesc = fExt.programs->get_program(fHandle, static_cast(index))) { CARLA_SAFE_ASSERT_RETURN(progDesc->name != nullptr,); if (pData->midiprog.data[index].name != nullptr) delete[] pData->midiprog.data[index].name; pData->midiprog.data[index].name = carla_strdup(progDesc->name); if (index == pData->midiprog.current) pData->engine->callback(true, true, ENGINE_CALLBACK_UPDATE, pData->id, 0, 0, 0, 0.0, nullptr); else pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0, nullptr); } } } // ------------------------------------------------------------------- LV2_Resize_Port_Status handleResizePort(const uint32_t index, const size_t size) { CARLA_SAFE_ASSERT_RETURN(size > 0, LV2_RESIZE_PORT_ERR_UNKNOWN); carla_debug("CarlaPluginLV2::handleResizePort(%i, " P_SIZE ")", index, size); // TODO return LV2_RESIZE_PORT_ERR_NO_SPACE; (void)index; } // ------------------------------------------------------------------- LV2_State_Status handleStateStore(const uint32_t key, const void* const value, const size_t size, const uint32_t type, const uint32_t flags) { CARLA_SAFE_ASSERT_RETURN(key != kUridNull, LV2_STATE_ERR_NO_PROPERTY); CARLA_SAFE_ASSERT_RETURN(value != nullptr, LV2_STATE_ERR_NO_PROPERTY); CARLA_SAFE_ASSERT_RETURN(size > 0, LV2_STATE_ERR_NO_PROPERTY); CARLA_SAFE_ASSERT_RETURN(type != kUridNull, LV2_STATE_ERR_BAD_TYPE); // FIXME linuxsampler does not set POD flag // CARLA_SAFE_ASSERT_RETURN(flags & LV2_STATE_IS_POD, LV2_STATE_ERR_BAD_FLAGS); carla_debug("CarlaPluginLV2::handleStateStore(%i:\"%s\", %p, " P_SIZE ", %i:\"%s\", %i)", key, carla_lv2_urid_unmap(this, key), value, size, type, carla_lv2_urid_unmap(this, type), flags); const char* const skey(carla_lv2_urid_unmap(this, key)); const char* const stype(carla_lv2_urid_unmap(this, type)); CARLA_SAFE_ASSERT_RETURN(skey != nullptr && skey != kUnmapFallback, LV2_STATE_ERR_BAD_TYPE); CARLA_SAFE_ASSERT_RETURN(stype != nullptr && stype != kUnmapFallback, LV2_STATE_ERR_BAD_TYPE); // Check if we already have this key for (LinkedList::Itenerator it = pData->custom.begin2(); it.valid(); it.next()) { CustomData& cData(it.getValue(kCustomDataFallbackNC)); CARLA_SAFE_ASSERT_CONTINUE(cData.isValid()); if (std::strcmp(cData.key, skey) == 0) { // found it delete[] cData.value; if (type == kUridAtomString || type == kUridAtomPath) cData.value = carla_strdup((const char*)value); else cData.value = CarlaString::asBase64(value, size).dup(); return LV2_STATE_SUCCESS; } } // Otherwise store it CustomData newData; newData.type = carla_strdup(stype); newData.key = carla_strdup(skey); if (type == kUridAtomString || type == kUridAtomPath) newData.value = carla_strdup((const char*)value); else newData.value = CarlaString::asBase64(value, size).dup(); pData->custom.append(newData); return LV2_STATE_SUCCESS; // unused (void)flags; } const void* handleStateRetrieve(const uint32_t key, size_t* const size, uint32_t* const type, uint32_t* const flags) { CARLA_SAFE_ASSERT_RETURN(key != kUridNull, nullptr); CARLA_SAFE_ASSERT_RETURN(size != nullptr, nullptr); CARLA_SAFE_ASSERT_RETURN(type != nullptr, nullptr); CARLA_SAFE_ASSERT_RETURN(flags != nullptr, nullptr); carla_debug("CarlaPluginLV2::handleStateRetrieve(%i, %p, %p, %p)", key, size, type, flags); const char* const skey(carla_lv2_urid_unmap(this, key)); CARLA_SAFE_ASSERT_RETURN(skey != nullptr && skey != kUnmapFallback, nullptr); const char* stype = nullptr; const char* stringData = nullptr; for (LinkedList::Itenerator it = pData->custom.begin2(); it.valid(); it.next()) { const CustomData& cData(it.getValue(kCustomDataFallback)); CARLA_SAFE_ASSERT_CONTINUE(cData.isValid()); if (std::strcmp(cData.key, skey) == 0) { stype = cData.type; stringData = cData.value; break; } } if (stype == nullptr || stringData == nullptr) { carla_stderr("Plugin requested value for '%s' which is not available", skey); *size = *type = *flags = 0; return nullptr; } *type = carla_lv2_urid_map(this, stype); *flags = LV2_STATE_IS_POD; if (*type == kUridAtomString || *type == kUridAtomPath) { *size = std::strlen(stringData); return stringData; } if (fLastStateChunk != nullptr) { std::free(fLastStateChunk); fLastStateChunk = nullptr; } std::vector chunk(carla_getChunkFromBase64String(stringData)); CARLA_SAFE_ASSERT_RETURN(chunk.size() > 0, nullptr); fLastStateChunk = std::malloc(chunk.size()); CARLA_SAFE_ASSERT_RETURN(fLastStateChunk != nullptr, nullptr); #ifdef CARLA_PROPER_CPP11_SUPPORT std::memcpy(fLastStateChunk, chunk.data(), chunk.size()); #else std::memcpy(fLastStateChunk, &chunk.front(), chunk.size()); #endif *size = chunk.size(); return fLastStateChunk; } // ------------------------------------------------------------------- LV2_Worker_Status handleWorkerSchedule(const uint32_t size, const void* const data) { CARLA_SAFE_ASSERT_RETURN(fExt.worker != nullptr && fExt.worker->work != nullptr, LV2_WORKER_ERR_UNKNOWN); CARLA_SAFE_ASSERT_RETURN(fEventsIn.ctrl != nullptr, LV2_WORKER_ERR_UNKNOWN); carla_debug("CarlaPluginLV2::handleWorkerSchedule(%i, %p)", size, data); if (pData->engine->isOffline()) { fExt.worker->work(fHandle, carla_lv2_worker_respond, this, size, data); return LV2_WORKER_SUCCESS; } LV2_Atom atom; atom.size = size; atom.type = kUridCarlaAtomWorkerIn; return fAtomBufferWorkerIn.putChunk(&atom, data, fEventsOut.ctrlIndex) ? LV2_WORKER_SUCCESS : LV2_WORKER_ERR_NO_SPACE; } LV2_Worker_Status handleWorkerRespond(const uint32_t size, const void* const data) { CARLA_SAFE_ASSERT_RETURN(fExt.worker != nullptr && fExt.worker->work_response != nullptr, LV2_WORKER_ERR_UNKNOWN); carla_debug("CarlaPluginLV2::handleWorkerRespond(%i, %p)", size, data); LV2_Atom atom; atom.size = size; atom.type = kUridCarlaAtomWorkerResp; return fAtomBufferWorkerResp.putChunk(&atom, data, fEventsIn.ctrlIndex) ? LV2_WORKER_SUCCESS : LV2_WORKER_ERR_NO_SPACE; } // ------------------------------------------------------------------- void handleInlineDisplayQueueRedraw() { fInlineDisplayNeedsRedraw = true; } const LV2_Inline_Display_Image_Surface* renderInlineDisplay(const uint32_t width, const uint32_t height) { CARLA_SAFE_ASSERT_RETURN(fExt.inlineDisplay != nullptr && fExt.inlineDisplay->render != nullptr, nullptr); CARLA_SAFE_ASSERT_RETURN(width > 0, nullptr); CARLA_SAFE_ASSERT_RETURN(height > 0, nullptr); return fExt.inlineDisplay->render(fHandle, width, height); } // ------------------------------------------------------------------- void handleMidnamUpdate() { CARLA_SAFE_ASSERT_RETURN(fExt.midnam != nullptr,); if (fEventsIn.ctrl == nullptr) return; char* const midnam = fExt.midnam->midnam(fHandle); CARLA_SAFE_ASSERT_RETURN(midnam != nullptr,); fEventsIn.ctrl->port->setMetaData("http://www.midi.org/dtds/MIDINameDocument10.dtd", midnam, "text/xml"); if (fExt.midnam->free != nullptr) fExt.midnam->free(midnam); } // ------------------------------------------------------------------- void handleExternalUIClosed() { CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EXTERNAL,); carla_debug("CarlaPluginLV2::handleExternalUIClosed()"); fNeedsUiClose = true; } void handlePluginUIClosed() override { CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EMBED,); CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,); carla_debug("CarlaPluginLV2::handlePluginUIClosed()"); fNeedsUiClose = true; } void handlePluginUIResized(const uint width, const uint height) override { CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EMBED,); CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,); carla_debug("CarlaPluginLV2::handlePluginUIResized(%u, %u)", width, height); if (fUI.handle != nullptr && fExt.uiresize != nullptr) fExt.uiresize->ui_resize(fUI.handle, static_cast(width), static_cast(height)); } // ------------------------------------------------------------------- uint32_t handleUIPortMap(const char* const symbol) const noexcept { CARLA_SAFE_ASSERT_RETURN(symbol != nullptr && symbol[0] != '\0', LV2UI_INVALID_PORT_INDEX); carla_debug("CarlaPluginLV2::handleUIPortMap(\"%s\")", symbol); for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i) { if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, symbol) == 0) return i; } return LV2UI_INVALID_PORT_INDEX; } LV2UI_Request_Value_Status handleUIRequestValue(const LV2_URID key, const LV2_URID type, const LV2_Feature* const* features) { CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL, LV2UI_REQUEST_VALUE_ERR_UNKNOWN); carla_debug("CarlaPluginLV2::handleUIRequestValue(%u, %u, %p)", key, type, features); if (type != kUridAtomPath) return LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED; const char* const uri = getCustomURIDString(key); CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri != kUnmapFallback, LV2UI_REQUEST_VALUE_ERR_UNKNOWN); // check if a file browser is already open if (fUI.fileNeededForURI != nullptr || fUI.fileBrowserOpen) return LV2UI_REQUEST_VALUE_BUSY; for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i) { if (fRdfDescriptor->Parameters[i].Type != LV2_PARAMETER_PATH) continue; if (std::strcmp(fRdfDescriptor->Parameters[i].URI, uri) != 0) continue; // TODO file browser filters, also store label to use for title fUI.fileNeededForURI = uri; return LV2UI_REQUEST_VALUE_SUCCESS; } return LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED; // may be unused (void)features; } int handleUIResize(const int width, const int height) { CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr, 1); CARLA_SAFE_ASSERT_RETURN(width > 0, 1); CARLA_SAFE_ASSERT_RETURN(height > 0, 1); carla_debug("CarlaPluginLV2::handleUIResize(%i, %i)", width, height); fUI.window->setSize(static_cast(width), static_cast(height), true); return 0; } void handleUITouch(const uint32_t rindex, const bool touch) { carla_debug("CarlaPluginLV2::handleUITouch(%u, %s)", rindex, bool2str(touch)); uint32_t index = LV2UI_INVALID_PORT_INDEX; for (uint32_t i=0; i < pData->param.count; ++i) { if (pData->param.data[i].rindex != static_cast(rindex)) continue; index = i; break; } CARLA_SAFE_ASSERT_RETURN(index != LV2UI_INVALID_PORT_INDEX,); pData->engine->touchPluginParameter(pData->id, index, touch); } void handleUIWrite(const uint32_t rindex, const uint32_t bufferSize, const uint32_t format, const void* const buffer) { CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,); CARLA_SAFE_ASSERT_RETURN(bufferSize > 0,); carla_debug("CarlaPluginLV2::handleUIWrite(%i, %i, %i, %p)", rindex, bufferSize, format, buffer); uint32_t index = LV2UI_INVALID_PORT_INDEX; switch (format) { case kUridNull: { CARLA_SAFE_ASSERT_RETURN(rindex < fRdfDescriptor->PortCount,); CARLA_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),); for (uint32_t i=0; i < pData->param.count; ++i) { if (pData->param.data[i].rindex != static_cast(rindex)) continue; index = i; break; } CARLA_SAFE_ASSERT_RETURN(index != LV2UI_INVALID_PORT_INDEX,); const float value(*(const float*)buffer); // check if we should feedback message back to UI bool sendGui = false; if (const uint32_t notifCount = fUI.rdfDescriptor->PortNotificationCount) { const char* const portSymbol = fRdfDescriptor->Ports[rindex].Symbol; for (uint32_t i=0; i < notifCount; ++i) { const LV2_RDF_UI_PortNotification& portNotif(fUI.rdfDescriptor->PortNotifications[i]); if (portNotif.Protocol != LV2_UI_PORT_PROTOCOL_FLOAT) continue; if (portNotif.Symbol != nullptr) { if (std::strcmp(portNotif.Symbol, portSymbol) != 0) continue; } else if (portNotif.Index != rindex) { continue; } sendGui = true; break; } } setParameterValue(index, value, sendGui, true, true); } break; case kUridAtomTransferAtom: case kUridAtomTransferEvent: { CARLA_SAFE_ASSERT_RETURN(bufferSize >= sizeof(LV2_Atom),); const LV2_Atom* const atom((const LV2_Atom*)buffer); // plugins sometimes fail on this, not good... const uint32_t totalSize = lv2_atom_total_size(atom); const uint32_t paddedSize = lv2_atom_pad_size(totalSize); if (bufferSize != totalSize && bufferSize != paddedSize) carla_stderr2("Warning: LV2 UI sending atom with invalid size %u! size: %u, padded-size: %u", bufferSize, totalSize, paddedSize); for (uint32_t i=0; i < fEventsIn.count; ++i) { if (fEventsIn.data[i].rindex != rindex) continue; index = i; break; } // for bad plugins if (index == LV2UI_INVALID_PORT_INDEX) { CARLA_SAFE_ASSERT(index != LV2UI_INVALID_PORT_INDEX); // FIXME index = fEventsIn.ctrlIndex; } fAtomBufferEvIn.put(atom, index); } break; default: carla_stdout("CarlaPluginLV2::handleUIWrite(%i, %i, %i:\"%s\", %p) - unknown format", rindex, bufferSize, format, carla_lv2_urid_unmap(this, format), buffer); break; } } // ------------------------------------------------------------------- void handleLilvSetPortValue(const char* const portSymbol, const void* const value, const uint32_t size, const uint32_t type) { CARLA_SAFE_ASSERT_RETURN(portSymbol != nullptr && portSymbol[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr,); CARLA_SAFE_ASSERT_RETURN(size > 0,); CARLA_SAFE_ASSERT_RETURN(type != kUridNull,); carla_debug("CarlaPluginLV2::handleLilvSetPortValue(\"%s\", %p, %i, %i)", portSymbol, value, size, type); int32_t rindex = -1; for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i) { if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, portSymbol) == 0) { rindex = static_cast(i); break; } } CARLA_SAFE_ASSERT_RETURN(rindex >= 0,); float paramValue; switch (type) { case kUridAtomBool: CARLA_SAFE_ASSERT_RETURN(size == sizeof(bool),); paramValue = (*(const bool*)value) ? 1.0f : 0.0f; break; case kUridAtomDouble: CARLA_SAFE_ASSERT_RETURN(size == sizeof(double),); paramValue = static_cast((*(const double*)value)); break; case kUridAtomFloat: CARLA_SAFE_ASSERT_RETURN(size == sizeof(float),); paramValue = (*(const float*)value); break; case kUridAtomInt: CARLA_SAFE_ASSERT_RETURN(size == sizeof(int32_t),); paramValue = static_cast((*(const int32_t*)value)); break; case kUridAtomLong: CARLA_SAFE_ASSERT_RETURN(size == sizeof(int64_t),); paramValue = static_cast((*(const int64_t*)value)); break; default: carla_stdout("CarlaPluginLV2::handleLilvSetPortValue(\"%s\", %p, %i, %i:\"%s\") - unknown type", portSymbol, value, size, type, carla_lv2_urid_unmap(this, type)); return; } for (uint32_t i=0; i < pData->param.count; ++i) { if (pData->param.data[i].rindex == rindex) { setParameterValueRT(i, paramValue, true); break; } } } // ------------------------------------------------------------------- void* getNativeHandle() const noexcept override { return fHandle; } const void* getNativeDescriptor() const noexcept override { return fDescriptor; } uintptr_t getUiBridgeProcessId() const noexcept override { return fPipeServer.isPipeRunning() ? fPipeServer.getPID() : 0; } // ------------------------------------------------------------------- public: bool init(const char* const name, const char* const uri, const uint options) { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); // --------------------------------------------------------------- // first checks if (pData->client != nullptr) { pData->engine->setLastError("Plugin client is already registered"); return false; } if (uri == nullptr || uri[0] == '\0') { pData->engine->setLastError("null uri"); return false; } const EngineOptions& opts(pData->engine->getOptions()); // --------------------------------------------------------------- // Init LV2 World if needed, sets LV2_PATH for lilv Lv2WorldClass& lv2World(Lv2WorldClass::getInstance()); if (opts.pathLV2 != nullptr && opts.pathLV2[0] != '\0') lv2World.initIfNeeded(opts.pathLV2); else if (const char* const LV2_PATH = std::getenv("LV2_PATH")) lv2World.initIfNeeded(LV2_PATH); else lv2World.initIfNeeded(LILV_DEFAULT_LV2_PATH); // --------------------------------------------------------------- // get plugin from lv2_rdf (lilv) fRdfDescriptor = lv2_rdf_new(uri, true); if (fRdfDescriptor == nullptr) { pData->engine->setLastError("Failed to find the requested plugin"); return false; } // --------------------------------------------------------------- // open DLL if (! pData->libOpen(fRdfDescriptor->Binary)) { pData->engine->setLastError(pData->libError(fRdfDescriptor->Binary)); return false; } // --------------------------------------------------------------- // try to get DLL main entry via new mode if (const LV2_Lib_Descriptor_Function libDescFn = pData->libSymbol("lv2_lib_descriptor")) { // ----------------------------------------------------------- // all ok, get lib descriptor const LV2_Lib_Descriptor* const libDesc = libDescFn(fRdfDescriptor->Bundle, nullptr); if (libDesc == nullptr) { pData->engine->setLastError("Could not find the LV2 Descriptor"); return false; } // ----------------------------------------------------------- // get descriptor that matches URI (new mode) uint32_t i = 0; while ((fDescriptor = libDesc->get_plugin(libDesc->handle, i++))) { if (std::strcmp(fDescriptor->URI, uri) == 0) break; } } else { // ----------------------------------------------------------- // get DLL main entry (old mode) const LV2_Descriptor_Function descFn = pData->libSymbol("lv2_descriptor"); if (descFn == nullptr) { pData->engine->setLastError("Could not find the LV2 Descriptor in the plugin library"); return false; } // ----------------------------------------------------------- // get descriptor that matches URI (old mode) uint32_t i = 0; while ((fDescriptor = descFn(i++))) { if (std::strcmp(fDescriptor->URI, uri) == 0) break; } } if (fDescriptor == nullptr) { pData->engine->setLastError("Could not find the requested plugin URI in the plugin library"); return false; } // --------------------------------------------------------------- // check supported port-types and features bool canContinue = true; // Check supported ports for (uint32_t j=0; j < fRdfDescriptor->PortCount; ++j) { const LV2_Property portTypes(fRdfDescriptor->Ports[j].Types); if (! is_lv2_port_supported(portTypes)) { if (! LV2_IS_PORT_OPTIONAL(fRdfDescriptor->Ports[j].Properties)) { pData->engine->setLastError("Plugin requires a port type that is not currently supported"); canContinue = false; break; } } } // Check supported features for (uint32_t j=0; j < fRdfDescriptor->FeatureCount && canContinue; ++j) { const LV2_RDF_Feature& feature(fRdfDescriptor->Features[j]); if (std::strcmp(feature.URI, LV2_DATA_ACCESS_URI) == 0 || std::strcmp(feature.URI, LV2_INSTANCE_ACCESS_URI) == 0) { carla_stderr("Plugin DSP wants UI feature '%s', ignoring this", feature.URI); } else if (std::strcmp(feature.URI, LV2_BUF_SIZE__fixedBlockLength) == 0) { fNeedsFixedBuffers = true; } else if (std::strcmp(feature.URI, LV2_PORT_PROPS__supportsStrictBounds) == 0) { fStrictBounds = feature.Required ? 1 : 0; } else if (feature.Required && ! is_lv2_feature_supported(feature.URI)) { CarlaString msg("Plugin wants a feature that is not supported:\n"); msg += feature.URI; canContinue = false; pData->engine->setLastError(msg); break; } } if (! canContinue) { // error already set return false; } if (fNeedsFixedBuffers && ! pData->engine->usesConstantBufferSize()) { pData->engine->setLastError("Cannot use this plugin under the current engine.\n" "The plugin requires a fixed block size which is not possible right now."); return false; } // --------------------------------------------------------------- // set icon if (std::strncmp(fDescriptor->URI, "http://distrho.sf.net/", 22) == 0) pData->iconName = carla_strdup_safe("distrho"); // --------------------------------------------------------------- // set info if (name != nullptr && name[0] != '\0') pData->name = pData->engine->getUniquePluginName(name); else pData->name = pData->engine->getUniquePluginName(fRdfDescriptor->Name); // --------------------------------------------------------------- // register client pData->client = pData->engine->addClient(this); if (pData->client == nullptr || ! pData->client->isOk()) { pData->engine->setLastError("Failed to register plugin client"); return false; } // --------------------------------------------------------------- // initialize options const int bufferSize = static_cast(pData->engine->getBufferSize()); fLv2Options.minBufferSize = fNeedsFixedBuffers ? bufferSize : 1; fLv2Options.maxBufferSize = bufferSize; fLv2Options.nominalBufferSize = bufferSize; fLv2Options.sampleRate = static_cast(pData->engine->getSampleRate()); fLv2Options.transientWinId = static_cast(opts.frontendWinId); uint32_t eventBufferSize = MAX_DEFAULT_BUFFER_SIZE; for (uint32_t j=0; j < fRdfDescriptor->PortCount; ++j) { const LV2_Property portTypes(fRdfDescriptor->Ports[j].Types); if (LV2_IS_PORT_ATOM_SEQUENCE(portTypes) || LV2_IS_PORT_EVENT(portTypes) || LV2_IS_PORT_MIDI_LL(portTypes)) { if (fRdfDescriptor->Ports[j].MinimumSize > eventBufferSize) eventBufferSize = fRdfDescriptor->Ports[j].MinimumSize; } } fLv2Options.sequenceSize = static_cast(eventBufferSize); fLv2Options.bgColor = opts.bgColor; fLv2Options.fgColor = opts.fgColor; fLv2Options.uiScale = opts.uiScale; // --------------------------------------------------------------- // initialize features (part 1) LV2_Event_Feature* const eventFt = new LV2_Event_Feature; eventFt->callback_data = this; eventFt->lv2_event_ref = carla_lv2_event_ref; eventFt->lv2_event_unref = carla_lv2_event_unref; LV2_Log_Log* const logFt = new LV2_Log_Log; logFt->handle = this; logFt->printf = carla_lv2_log_printf; logFt->vprintf = carla_lv2_log_vprintf; LV2_State_Make_Path* const stateMakePathFt = new LV2_State_Make_Path; stateMakePathFt->handle = this; stateMakePathFt->path = carla_lv2_state_make_path; LV2_State_Map_Path* const stateMapPathFt = new LV2_State_Map_Path; stateMapPathFt->handle = this; stateMapPathFt->abstract_path = carla_lv2_state_map_abstract_path; stateMapPathFt->absolute_path = carla_lv2_state_map_absolute_path; LV2_Programs_Host* const programsFt = new LV2_Programs_Host; programsFt->handle = this; programsFt->program_changed = carla_lv2_program_changed; LV2_Resize_Port_Resize* const rsPortFt = new LV2_Resize_Port_Resize; rsPortFt->data = this; rsPortFt->resize = carla_lv2_resize_port; LV2_RtMemPool_Pool* const rtMemPoolFt = new LV2_RtMemPool_Pool; lv2_rtmempool_init(rtMemPoolFt); LV2_RtMemPool_Pool_Deprecated* const rtMemPoolOldFt = new LV2_RtMemPool_Pool_Deprecated; lv2_rtmempool_init_deprecated(rtMemPoolOldFt); LV2_URI_Map_Feature* const uriMapFt = new LV2_URI_Map_Feature; uriMapFt->callback_data = this; uriMapFt->uri_to_id = carla_lv2_uri_to_id; LV2_URID_Map* const uridMapFt = new LV2_URID_Map; uridMapFt->handle = this; uridMapFt->map = carla_lv2_urid_map; LV2_URID_Unmap* const uridUnmapFt = new LV2_URID_Unmap; uridUnmapFt->handle = this; uridUnmapFt->unmap = carla_lv2_urid_unmap; LV2_Worker_Schedule* const workerFt = new LV2_Worker_Schedule; workerFt->handle = this; workerFt->schedule_work = carla_lv2_worker_schedule; LV2_Inline_Display* const inlineDisplay = new LV2_Inline_Display; inlineDisplay->handle = this; inlineDisplay->queue_draw = carla_lv2_inline_display_queue_draw; LV2_Midnam* const midnam = new LV2_Midnam; midnam->handle = this; midnam->update = carla_lv2_midnam_update; // --------------------------------------------------------------- // initialize features (part 2) for (uint32_t j=0; j < kFeatureCountPlugin; ++j) fFeatures[j] = new LV2_Feature; fFeatures[kFeatureIdBufSizeBounded]->URI = LV2_BUF_SIZE__boundedBlockLength; fFeatures[kFeatureIdBufSizeBounded]->data = nullptr; fFeatures[kFeatureIdBufSizeFixed]->URI = fNeedsFixedBuffers ? LV2_BUF_SIZE__fixedBlockLength : LV2_BUF_SIZE__boundedBlockLength; fFeatures[kFeatureIdBufSizeFixed]->data = nullptr; fFeatures[kFeatureIdBufSizePowerOf2]->URI = LV2_BUF_SIZE__powerOf2BlockLength; fFeatures[kFeatureIdBufSizePowerOf2]->data = nullptr; fFeatures[kFeatureIdEvent]->URI = LV2_EVENT_URI; fFeatures[kFeatureIdEvent]->data = eventFt; fFeatures[kFeatureIdHardRtCapable]->URI = LV2_CORE__hardRTCapable; fFeatures[kFeatureIdHardRtCapable]->data = nullptr; fFeatures[kFeatureIdInPlaceBroken]->URI = LV2_CORE__inPlaceBroken; fFeatures[kFeatureIdInPlaceBroken]->data = nullptr; fFeatures[kFeatureIdIsLive]->URI = LV2_CORE__isLive; fFeatures[kFeatureIdIsLive]->data = nullptr; fFeatures[kFeatureIdLogs]->URI = LV2_LOG__log; fFeatures[kFeatureIdLogs]->data = logFt; fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options; fFeatures[kFeatureIdOptions]->data = fLv2Options.opts; fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host; fFeatures[kFeatureIdPrograms]->data = programsFt; fFeatures[kFeatureIdResizePort]->URI = LV2_RESIZE_PORT__resize; fFeatures[kFeatureIdResizePort]->data = rsPortFt; fFeatures[kFeatureIdRtMemPool]->URI = LV2_RTSAFE_MEMORY_POOL__Pool; fFeatures[kFeatureIdRtMemPool]->data = rtMemPoolFt; fFeatures[kFeatureIdRtMemPoolOld]->URI = LV2_RTSAFE_MEMORY_POOL_DEPRECATED_URI; fFeatures[kFeatureIdRtMemPoolOld]->data = rtMemPoolOldFt; fFeatures[kFeatureIdStateMakePath]->URI = LV2_STATE__makePath; fFeatures[kFeatureIdStateMakePath]->data = stateMakePathFt; fFeatures[kFeatureIdStateMapPath]->URI = LV2_STATE__mapPath; fFeatures[kFeatureIdStateMapPath]->data = stateMapPathFt; fFeatures[kFeatureIdStrictBounds]->URI = LV2_PORT_PROPS__supportsStrictBounds; fFeatures[kFeatureIdStrictBounds]->data = nullptr; fFeatures[kFeatureIdUriMap]->URI = LV2_URI_MAP_URI; fFeatures[kFeatureIdUriMap]->data = uriMapFt; fFeatures[kFeatureIdUridMap]->URI = LV2_URID__map; fFeatures[kFeatureIdUridMap]->data = uridMapFt; fFeatures[kFeatureIdUridUnmap]->URI = LV2_URID__unmap; fFeatures[kFeatureIdUridUnmap]->data = uridUnmapFt; fFeatures[kFeatureIdWorker]->URI = LV2_WORKER__schedule; fFeatures[kFeatureIdWorker]->data = workerFt; fFeatures[kFeatureIdInlineDisplay]->URI = LV2_INLINEDISPLAY__queue_draw; fFeatures[kFeatureIdInlineDisplay]->data = inlineDisplay; fFeatures[kFeatureIdMidnam]->URI = LV2_MIDNAM__update; fFeatures[kFeatureIdMidnam]->data = midnam; // --------------------------------------------------------------- // initialize plugin try { fHandle = fDescriptor->instantiate(fDescriptor, pData->engine->getSampleRate(), fRdfDescriptor->Bundle, fFeatures); } catch(...) {} if (fHandle == nullptr) { pData->engine->setLastError("Plugin failed to initialize"); return false; } recheckExtensions(); // --------------------------------------------------------------- // set options pData->options = 0x0; if (fLatencyIndex >= 0 || getMidiOutCount() != 0 || fNeedsFixedBuffers) pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; else if (options & PLUGIN_OPTION_FIXED_BUFFERS) pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; if (opts.forceStereo) pData->options |= PLUGIN_OPTION_FORCE_STEREO; else if (options & PLUGIN_OPTION_FORCE_STEREO) pData->options |= PLUGIN_OPTION_FORCE_STEREO; if (getMidiInCount() != 0) { if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)) pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)) pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND)) pData->options |= PLUGIN_OPTION_SEND_PITCHBEND; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF)) pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PROGRAM_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES; } if (fExt.programs != nullptr && (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) == 0) { if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES)) pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; } // --------------------------------------------------------------- // gui stuff if (fRdfDescriptor->UICount != 0) initUi(); return true; } // ------------------------------------------------------------------- void initUi() { // --------------------------------------------------------------- // find the most appropriate ui int eQt4, eQt5, eGtk2, eGtk3, eCocoa, eWindows, eX11, eMod, iCocoa, iWindows, iX11, iExt, iFinal; eQt4 = eQt5 = eGtk2 = eGtk3 = eCocoa = eWindows = eX11 = eMod = iCocoa = iWindows = iX11 = iExt = iFinal = -1; #if defined(LV2_UIS_ONLY_BRIDGES) const bool preferUiBridges = true; #elif defined(BUILD_BRIDGE) const bool preferUiBridges = false; #else const bool preferUiBridges = pData->engine->getOptions().preferUiBridges; #endif bool hasShowInterface = false; for (uint32_t i=0; i < fRdfDescriptor->UICount; ++i) { CARLA_SAFE_ASSERT_CONTINUE(fRdfDescriptor->UIs[i].URI != nullptr); const int ii(static_cast(i)); switch (fRdfDescriptor->UIs[i].Type) { case LV2_UI_QT4: if (isUiBridgeable(i)) eQt4 = ii; break; case LV2_UI_QT5: if (isUiBridgeable(i)) eQt5 = ii; break; case LV2_UI_GTK2: if (isUiBridgeable(i)) eGtk2 = ii; break; case LV2_UI_GTK3: if (isUiBridgeable(i)) eGtk3 = ii; break; #ifdef CARLA_OS_MAC case LV2_UI_COCOA: if (isUiBridgeable(i) && preferUiBridges) eCocoa = ii; iCocoa = ii; break; #endif #ifdef CARLA_OS_WIN case LV2_UI_WINDOWS: if (isUiBridgeable(i) && preferUiBridges) eWindows = ii; iWindows = ii; break; #endif case LV2_UI_X11: if (isUiBridgeable(i) && preferUiBridges) eX11 = ii; iX11 = ii; break; case LV2_UI_EXTERNAL: case LV2_UI_OLD_EXTERNAL: iExt = ii; break; case LV2_UI_MOD: eMod = ii; break; default: break; } } /**/ if (eQt4 >= 0) iFinal = eQt4; else if (eQt5 >= 0) iFinal = eQt5; else if (eGtk2 >= 0) iFinal = eGtk2; else if (eGtk3 >= 0) iFinal = eGtk3; #ifdef CARLA_OS_MAC else if (eCocoa >= 0) iFinal = eCocoa; #endif #ifdef CARLA_OS_WIN else if (eWindows >= 0) iFinal = eWindows; #endif #ifdef HAVE_X11 else if (eX11 >= 0) iFinal = eX11; #endif #ifndef LV2_UIS_ONLY_BRIDGES # ifdef CARLA_OS_MAC else if (iCocoa >= 0) iFinal = iCocoa; # endif # ifdef CARLA_OS_WIN else if (iWindows >= 0) iFinal = iWindows; # endif # ifdef HAVE_X11 else if (iX11 >= 0) iFinal = iX11; # endif #endif else if (iExt >= 0) iFinal = iExt; #ifndef BUILD_BRIDGE if (iFinal < 0) #endif { // no suitable UI found, see if there's one which supports ui:showInterface for (uint32_t i=0; i < fRdfDescriptor->UICount && ! hasShowInterface; ++i) { LV2_RDF_UI* const ui(&fRdfDescriptor->UIs[i]); for (uint32_t j=0; j < ui->ExtensionCount; ++j) { CARLA_SAFE_ASSERT_CONTINUE(ui->Extensions[j] != nullptr); if (std::strcmp(ui->Extensions[j], LV2_UI__showInterface) != 0) continue; iFinal = static_cast(i); hasShowInterface = true; break; } } if (iFinal < 0) { if (eMod < 0) { carla_stderr("Failed to find an appropriate LV2 UI for this plugin"); return; } // use MODGUI as last resort iFinal = eMod; } } fUI.rdfDescriptor = &fRdfDescriptor->UIs[iFinal]; // --------------------------------------------------------------- // check supported ui features bool canContinue = true; bool canDelete = true; for (uint32_t i=0; i < fUI.rdfDescriptor->FeatureCount; ++i) { const char* const uri(fUI.rdfDescriptor->Features[i].URI); CARLA_SAFE_ASSERT_CONTINUE(uri != nullptr && uri[0] != '\0'); if (! is_lv2_ui_feature_supported(uri)) { if (fUI.rdfDescriptor->Features[i].Required) { carla_stderr("Plugin UI requires a feature that is not supported:\n%s", uri); canContinue = false; break; } carla_stderr("Plugin UI wants a feature that is not supported (ignored):\n%s", uri); } if (std::strcmp(uri, LV2_UI__makeResident) == 0 || std::strcmp(uri, LV2_UI__makeSONameResident) == 0) canDelete = false; else if (std::strcmp(uri, LV2_UI__requestValue) == 0) pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD; } if (! canContinue) { fUI.rdfDescriptor = nullptr; return; } // --------------------------------------------------------------- // initialize ui according to type const LV2_Property uiType(fUI.rdfDescriptor->Type); if ( (iFinal == eQt4 || iFinal == eQt5 || iFinal == eGtk2 || iFinal == eGtk3 || iFinal == eCocoa || iFinal == eWindows || iFinal == eX11 || iFinal == eMod) #ifdef BUILD_BRIDGE && ! hasShowInterface #endif ) { // ----------------------------------------------------------- // initialize ui-bridge if (const char* const bridgeBinary = getUiBridgeBinary(uiType)) { carla_stdout("Will use UI-Bridge for '%s', binary: \"%s\"", pData->name, bridgeBinary); CarlaString guiTitle(pData->name); guiTitle += " (GUI)"; fLv2Options.windowTitle = guiTitle.dup(); fUI.type = UI::TYPE_BRIDGE; fPipeServer.setData(bridgeBinary, fRdfDescriptor->URI, fUI.rdfDescriptor->URI); delete[] bridgeBinary; return; } if (iFinal == eQt4 || iFinal == eQt5 || iFinal == eGtk2 || iFinal == eGtk3 || iFinal == eMod) { carla_stderr2("Failed to find UI bridge binary for '%s', cannot use UI", pData->name); fUI.rdfDescriptor = nullptr; return; } } #ifdef LV2_UIS_ONLY_BRIDGES carla_stderr2("Failed to get an UI working, canBridge:%s", bool2str(isUiBridgeable(static_cast(iFinal)))); fUI.rdfDescriptor = nullptr; return; #endif // --------------------------------------------------------------- // open UI DLL if (! pData->uiLibOpen(fUI.rdfDescriptor->Binary, canDelete)) { carla_stderr2("Could not load UI library, error was:\n%s", pData->libError(fUI.rdfDescriptor->Binary)); fUI.rdfDescriptor = nullptr; return; } // --------------------------------------------------------------- // get UI DLL main entry LV2UI_DescriptorFunction uiDescFn = pData->uiLibSymbol("lv2ui_descriptor"); if (uiDescFn == nullptr) { carla_stderr2("Could not find the LV2UI Descriptor in the UI library"); pData->uiLibClose(); fUI.rdfDescriptor = nullptr; return; } // --------------------------------------------------------------- // get UI descriptor that matches UI URI uint32_t i = 0; while ((fUI.descriptor = uiDescFn(i++))) { if (std::strcmp(fUI.descriptor->URI, fUI.rdfDescriptor->URI) == 0) break; } if (fUI.descriptor == nullptr) { carla_stderr2("Could not find the requested GUI in the plugin UI library"); pData->uiLibClose(); fUI.rdfDescriptor = nullptr; return; } // --------------------------------------------------------------- // check if ui is usable switch (uiType) { case LV2_UI_NONE: carla_stdout("Will use LV2 Show Interface for '%s'", pData->name); fUI.type = UI::TYPE_EMBED; break; case LV2_UI_QT4: carla_stdout("Will use LV2 Qt4 UI for '%s', NOT!", pData->name); fUI.type = UI::TYPE_EMBED; break; case LV2_UI_QT5: carla_stdout("Will use LV2 Qt5 UI for '%s', NOT!", pData->name); fUI.type = UI::TYPE_EMBED; break; case LV2_UI_GTK2: carla_stdout("Will use LV2 Gtk2 UI for '%s', NOT!", pData->name); fUI.type = UI::TYPE_EMBED; break; case LV2_UI_GTK3: carla_stdout("Will use LV2 Gtk3 UI for '%s', NOT!", pData->name); fUI.type = UI::TYPE_EMBED; break; #ifdef CARLA_OS_MAC case LV2_UI_COCOA: carla_stdout("Will use LV2 Cocoa UI for '%s'", pData->name); fUI.type = UI::TYPE_EMBED; break; #endif #ifdef CARLA_OS_WIN case LV2_UI_WINDOWS: carla_stdout("Will use LV2 Windows UI for '%s'", pData->name); fUI.type = UI::TYPE_EMBED; break; #endif case LV2_UI_X11: #ifdef HAVE_X11 carla_stdout("Will use LV2 X11 UI for '%s'", pData->name); #else carla_stdout("Will use LV2 X11 UI for '%s', NOT!", pData->name); #endif fUI.type = UI::TYPE_EMBED; break; case LV2_UI_EXTERNAL: case LV2_UI_OLD_EXTERNAL: carla_stdout("Will use LV2 External UI for '%s'", pData->name); fUI.type = UI::TYPE_EXTERNAL; break; } if (fUI.type == UI::TYPE_NULL) { pData->uiLibClose(); fUI.descriptor = nullptr; fUI.rdfDescriptor = nullptr; return; } // --------------------------------------------------------------- // initialize ui data CarlaString guiTitle(pData->name); guiTitle += " (GUI)"; fLv2Options.windowTitle = guiTitle.dup(); fLv2Options.opts[CarlaPluginLV2Options::WindowTitle].size = (uint32_t)std::strlen(fLv2Options.windowTitle); fLv2Options.opts[CarlaPluginLV2Options::WindowTitle].value = fLv2Options.windowTitle; // --------------------------------------------------------------- // initialize ui features (part 1) LV2_Extension_Data_Feature* const uiDataFt = new LV2_Extension_Data_Feature; uiDataFt->data_access = fDescriptor->extension_data; LV2UI_Port_Map* const uiPortMapFt = new LV2UI_Port_Map; uiPortMapFt->handle = this; uiPortMapFt->port_index = carla_lv2_ui_port_map; LV2UI_Request_Value* const uiRequestValueFt = new LV2UI_Request_Value; uiRequestValueFt->handle = this; uiRequestValueFt->request = carla_lv2_ui_request_value; LV2UI_Resize* const uiResizeFt = new LV2UI_Resize; uiResizeFt->handle = this; uiResizeFt->ui_resize = carla_lv2_ui_resize; LV2UI_Touch* const uiTouchFt = new LV2UI_Touch; uiTouchFt->handle = this; uiTouchFt->touch = carla_lv2_ui_touch; LV2_External_UI_Host* const uiExternalHostFt = new LV2_External_UI_Host; uiExternalHostFt->ui_closed = carla_lv2_external_ui_closed; uiExternalHostFt->plugin_human_id = fLv2Options.windowTitle; // --------------------------------------------------------------- // initialize ui features (part 2) for (uint32_t j=kFeatureCountPlugin; j < kFeatureCountAll; ++j) fFeatures[j] = new LV2_Feature; fFeatures[kFeatureIdUiDataAccess]->URI = LV2_DATA_ACCESS_URI; fFeatures[kFeatureIdUiDataAccess]->data = uiDataFt; fFeatures[kFeatureIdUiInstanceAccess]->URI = LV2_INSTANCE_ACCESS_URI; fFeatures[kFeatureIdUiInstanceAccess]->data = fHandle; fFeatures[kFeatureIdUiIdleInterface]->URI = LV2_UI__idleInterface; fFeatures[kFeatureIdUiIdleInterface]->data = nullptr; fFeatures[kFeatureIdUiFixedSize]->URI = LV2_UI__fixedSize; fFeatures[kFeatureIdUiFixedSize]->data = nullptr; fFeatures[kFeatureIdUiMakeResident]->URI = LV2_UI__makeResident; fFeatures[kFeatureIdUiMakeResident]->data = nullptr; fFeatures[kFeatureIdUiMakeResident2]->URI = LV2_UI__makeSONameResident; fFeatures[kFeatureIdUiMakeResident2]->data = nullptr; fFeatures[kFeatureIdUiNoUserResize]->URI = LV2_UI__noUserResize; fFeatures[kFeatureIdUiNoUserResize]->data = nullptr; fFeatures[kFeatureIdUiParent]->URI = LV2_UI__parent; fFeatures[kFeatureIdUiParent]->data = nullptr; fFeatures[kFeatureIdUiPortMap]->URI = LV2_UI__portMap; fFeatures[kFeatureIdUiPortMap]->data = uiPortMapFt; fFeatures[kFeatureIdUiPortSubscribe]->URI = LV2_UI__portSubscribe; fFeatures[kFeatureIdUiPortSubscribe]->data = nullptr; fFeatures[kFeatureIdUiRequestValue]->URI = LV2_UI__requestValue; fFeatures[kFeatureIdUiRequestValue]->data = uiRequestValueFt; fFeatures[kFeatureIdUiResize]->URI = LV2_UI__resize; fFeatures[kFeatureIdUiResize]->data = uiResizeFt; fFeatures[kFeatureIdUiTouch]->URI = LV2_UI__touch; fFeatures[kFeatureIdUiTouch]->data = uiTouchFt; fFeatures[kFeatureIdExternalUi]->URI = LV2_EXTERNAL_UI__Host; fFeatures[kFeatureIdExternalUi]->data = uiExternalHostFt; fFeatures[kFeatureIdExternalUiOld]->URI = LV2_EXTERNAL_UI_DEPRECATED_URI; fFeatures[kFeatureIdExternalUiOld]->data = uiExternalHostFt; // --------------------------------------------------------------- // initialize ui extensions if (fUI.descriptor->extension_data == nullptr) return; fExt.uiidle = (const LV2UI_Idle_Interface*)fUI.descriptor->extension_data(LV2_UI__idleInterface); fExt.uishow = (const LV2UI_Show_Interface*)fUI.descriptor->extension_data(LV2_UI__showInterface); fExt.uiresize = (const LV2UI_Resize*)fUI.descriptor->extension_data(LV2_UI__resize); fExt.uiprograms = (const LV2_Programs_UI_Interface*)fUI.descriptor->extension_data(LV2_PROGRAMS__UIInterface); // check if invalid if (fExt.uiidle != nullptr && fExt.uiidle->idle == nullptr) fExt.uiidle = nullptr; if (fExt.uishow != nullptr && (fExt.uishow->show == nullptr || fExt.uishow->hide == nullptr)) fExt.uishow = nullptr; if (fExt.uiresize != nullptr && fExt.uiresize->ui_resize == nullptr) fExt.uiresize = nullptr; if (fExt.uiprograms != nullptr && fExt.uiprograms->select_program == nullptr) fExt.uiprograms = nullptr; // don't use uiidle if external if (fUI.type == UI::TYPE_EXTERNAL) fExt.uiidle = nullptr; } // ------------------------------------------------------------------- void handleTransferAtom(const uint32_t portIndex, const LV2_Atom* const atom) { CARLA_SAFE_ASSERT_RETURN(atom != nullptr,); carla_debug("CarlaPluginLV2::handleTransferAtom(%i, %p)", portIndex, atom); fAtomBufferEvIn.put(atom, portIndex); } void handleUridMap(const LV2_URID urid, const char* const uri) { CARLA_SAFE_ASSERT_RETURN(urid != kUridNull,); CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',); carla_debug("CarlaPluginLV2::handleUridMap(%i v " P_SIZE ", \"%s\")", urid, fCustomURIDs.size()-1, uri); const std::size_t uriCount(fCustomURIDs.size()); if (urid < uriCount) { const char* const ourURI(carla_lv2_urid_unmap(this, urid)); CARLA_SAFE_ASSERT_RETURN(ourURI != nullptr && ourURI != kUnmapFallback,); if (std::strcmp(ourURI, uri) != 0) { carla_stderr2("PLUGIN :: wrong URI '%s' vs '%s'", ourURI, uri); } } else { CARLA_SAFE_ASSERT_RETURN(urid == uriCount,); fCustomURIDs.push_back(uri); } } // ------------------------------------------------------------------- void writeAtomPath(const char* const path, const LV2_URID urid) { uint8_t atomBuf[4096]; lv2_atom_forge_set_buffer(&fAtomForge, atomBuf, sizeof(atomBuf)); LV2_Atom_Forge_Frame forgeFrame; lv2_atom_forge_object(&fAtomForge, &forgeFrame, kUridNull, kUridPatchSet); lv2_atom_forge_key(&fAtomForge, kUridPatchPoperty); lv2_atom_forge_urid(&fAtomForge, urid); lv2_atom_forge_key(&fAtomForge, kUridPatchValue); lv2_atom_forge_path(&fAtomForge, path, static_cast(std::strlen(path))); lv2_atom_forge_pop(&fAtomForge, &forgeFrame); LV2_Atom* const atom((LV2_Atom*)atomBuf); CARLA_SAFE_ASSERT(atom->size < sizeof(atomBuf)); fAtomBufferEvIn.put(atom, fEventsIn.ctrlIndex); } // ------------------------------------------------------------------- private: LV2_Handle fHandle; LV2_Handle fHandle2; LV2_Feature* fFeatures[kFeatureCountAll+1]; const LV2_Descriptor* fDescriptor; const LV2_RDF_Descriptor* fRdfDescriptor; float** fAudioInBuffers; float** fAudioOutBuffers; float** fCvInBuffers; float** fCvOutBuffers; float* fParamBuffers; bool fNeedsFixedBuffers; bool fNeedsUiClose; bool fInlineDisplayNeedsRedraw; int64_t fInlineDisplayLastRedrawTime; int32_t fLatencyIndex; // -1 if invalid int fStrictBounds; // -1 unsupported, 0 optional, 1 required Lv2AtomRingBuffer fAtomBufferEvIn; Lv2AtomRingBuffer fAtomBufferUiOut; Lv2AtomRingBuffer fAtomBufferWorkerIn; Lv2AtomRingBuffer fAtomBufferWorkerResp; LV2_Atom_Forge fAtomForge; uint8_t* fAtomBufferUiOutTmpData; uint8_t* fAtomBufferWorkerInTmpData; CarlaPluginLV2EventData fEventsIn; CarlaPluginLV2EventData fEventsOut; CarlaPluginLV2Options fLv2Options; CarlaPipeServerLV2 fPipeServer; std::vector fCustomURIDs; bool fFirstActive; // first process() call after activate() void* fLastStateChunk; EngineTimeInfo fLastTimeInfo; // if plugin provides path parameter, use it as fake "gui" CarlaString fFilePathURI; struct Extensions { const LV2_Options_Interface* options; const LV2_State_Interface* state; const LV2_Worker_Interface* worker; const LV2_Inline_Display_Interface* inlineDisplay; const LV2_Midnam_Interface* midnam; const LV2_Programs_Interface* programs; const LV2UI_Idle_Interface* uiidle; const LV2UI_Show_Interface* uishow; const LV2UI_Resize* uiresize; const LV2_Programs_UI_Interface* uiprograms; Extensions() : options(nullptr), state(nullptr), worker(nullptr), inlineDisplay(nullptr), midnam(nullptr), programs(nullptr), uiidle(nullptr), uishow(nullptr), uiresize(nullptr), uiprograms(nullptr) {} CARLA_DECLARE_NON_COPY_STRUCT(Extensions); } fExt; struct UI { enum Type { TYPE_NULL = 0, TYPE_BRIDGE, TYPE_EMBED, TYPE_EXTERNAL }; Type type; LV2UI_Handle handle; LV2UI_Widget widget; const LV2UI_Descriptor* descriptor; const LV2_RDF_UI* rdfDescriptor; bool fileBrowserOpen; const char* fileNeededForURI; CarlaPluginUI* window; UI() : type(TYPE_NULL), handle(nullptr), widget(nullptr), descriptor(nullptr), rdfDescriptor(nullptr), fileBrowserOpen(false), fileNeededForURI(nullptr), window(nullptr) {} ~UI() { CARLA_SAFE_ASSERT(handle == nullptr); CARLA_SAFE_ASSERT(widget == nullptr); CARLA_SAFE_ASSERT(descriptor == nullptr); CARLA_SAFE_ASSERT(rdfDescriptor == nullptr); CARLA_SAFE_ASSERT(! fileBrowserOpen); CARLA_SAFE_ASSERT(fileNeededForURI == nullptr); CARLA_SAFE_ASSERT(window == nullptr); } CARLA_DECLARE_NON_COPY_STRUCT(UI); } fUI; // ------------------------------------------------------------------- // Event Feature static uint32_t carla_lv2_event_ref(LV2_Event_Callback_Data callback_data, LV2_Event* event) { CARLA_SAFE_ASSERT_RETURN(callback_data != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(event != nullptr, 0); carla_debug("carla_lv2_event_ref(%p, %p)", callback_data, event); return 0; } static uint32_t carla_lv2_event_unref(LV2_Event_Callback_Data callback_data, LV2_Event* event) { CARLA_SAFE_ASSERT_RETURN(callback_data != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(event != nullptr, 0); carla_debug("carla_lv2_event_unref(%p, %p)", callback_data, event); return 0; } // ------------------------------------------------------------------- // Logs Feature static int carla_lv2_log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(type != kUridNull, 0); CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0); #ifndef DEBUG if (type == kUridLogTrace) return 0; #endif va_list args; va_start(args, fmt); const int ret(carla_lv2_log_vprintf(handle, type, fmt, args)); va_end(args); return ret; } static int carla_lv2_log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list ap) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(type != kUridNull, 0); CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0); int ret = 0; switch (type) { case kUridLogError: std::fprintf(stderr, "\x1b[31m"); ret = std::vfprintf(stderr, fmt, ap); std::fprintf(stderr, "\x1b[0m"); break; case kUridLogNote: ret = std::vfprintf(stdout, fmt, ap); break; case kUridLogTrace: #ifdef DEBUG std::fprintf(stdout, "\x1b[30;1m"); ret = std::vfprintf(stdout, fmt, ap); std::fprintf(stdout, "\x1b[0m"); #endif break; case kUridLogWarning: ret = std::vfprintf(stderr, fmt, ap); break; default: break; } return ret; } // ------------------------------------------------------------------- // Programs Feature static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr,); carla_debug("carla_lv2_program_changed(%p, %i)", handle, index); ((CarlaPluginLV2*)handle)->handleProgramChanged(index); } // ------------------------------------------------------------------- // Resize Port Feature static LV2_Resize_Port_Status carla_lv2_resize_port(LV2_Resize_Port_Feature_Data data, uint32_t index, size_t size) { CARLA_SAFE_ASSERT_RETURN(data != nullptr, LV2_RESIZE_PORT_ERR_UNKNOWN); carla_debug("carla_lv2_program_changed(%p, %i, " P_SIZE ")", data, index, size); return ((CarlaPluginLV2*)data)->handleResizePort(index, size); } // ------------------------------------------------------------------- // State Feature static char* carla_lv2_state_make_path(LV2_State_Make_Path_Handle handle, const char* path) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr); CARLA_SAFE_ASSERT_RETURN(path != nullptr && path[0] != '\0', nullptr); carla_debug("carla_lv2_state_make_path(%p, \"%s\")", handle, path); File file; if (File::isAbsolutePath(path)) file = File(path); else file = File::getCurrentWorkingDirectory().getChildFile(path); file.getParentDirectory().createDirectory(); return strdup(file.getFullPathName().toRawUTF8()); } static char* carla_lv2_state_map_abstract_path(LV2_State_Map_Path_Handle handle, const char* absolute_path) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, strdup("")); CARLA_SAFE_ASSERT_RETURN(absolute_path != nullptr && absolute_path[0] != '\0', strdup("")); carla_debug("carla_lv2_state_map_abstract_path(%p, \"%s\")", handle, absolute_path); // may already be an abstract path if (! File::isAbsolutePath(absolute_path)) return strdup(absolute_path); return strdup(File(absolute_path).getRelativePathFrom(File::getCurrentWorkingDirectory()).toRawUTF8()); } static char* carla_lv2_state_map_absolute_path(LV2_State_Map_Path_Handle handle, const char* abstract_path) { const char* const cwd(File::getCurrentWorkingDirectory().getFullPathName().toRawUTF8()); CARLA_SAFE_ASSERT_RETURN(handle != nullptr, strdup(cwd)); CARLA_SAFE_ASSERT_RETURN(abstract_path != nullptr && abstract_path[0] != '\0', strdup(cwd)); carla_debug("carla_lv2_state_map_absolute_path(%p, \"%s\")", handle, abstract_path); // may already be an absolute path if (File::isAbsolutePath(abstract_path)) return strdup(abstract_path); return strdup(File::getCurrentWorkingDirectory().getChildFile(abstract_path).getFullPathName().toRawUTF8()); } static LV2_State_Status carla_lv2_state_store(LV2_State_Handle handle, uint32_t key, const void* value, size_t size, uint32_t type, uint32_t flags) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2_STATE_ERR_UNKNOWN); carla_debug("carla_lv2_state_store(%p, %i, %p, " P_SIZE ", %i, %i)", handle, key, value, size, type, flags); return ((CarlaPluginLV2*)handle)->handleStateStore(key, value, size, type, flags); } static const void* carla_lv2_state_retrieve(LV2_State_Handle handle, uint32_t key, size_t* size, uint32_t* type, uint32_t* flags) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr); carla_debug("carla_lv2_state_retrieve(%p, %i, %p, %p, %p)", handle, key, size, type, flags); return ((CarlaPluginLV2*)handle)->handleStateRetrieve(key, size, type, flags); } // ------------------------------------------------------------------- // URI-Map Feature static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data, const char* map, const char* uri) { carla_debug("carla_lv2_uri_to_id(%p, \"%s\", \"%s\")", data, map, uri); return carla_lv2_urid_map((LV2_URID_Map_Handle*)data, uri); // unused (void)map; } // ------------------------------------------------------------------- // URID Feature static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, kUridNull); CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', kUridNull); carla_debug("carla_lv2_urid_map(%p, \"%s\")", handle, uri); // Atom types if (std::strcmp(uri, LV2_ATOM__Blank) == 0) return kUridAtomBlank; if (std::strcmp(uri, LV2_ATOM__Bool) == 0) return kUridAtomBool; if (std::strcmp(uri, LV2_ATOM__Chunk) == 0) return kUridAtomChunk; if (std::strcmp(uri, LV2_ATOM__Double) == 0) return kUridAtomDouble; if (std::strcmp(uri, LV2_ATOM__Event) == 0) return kUridAtomEvent; if (std::strcmp(uri, LV2_ATOM__Float) == 0) return kUridAtomFloat; if (std::strcmp(uri, LV2_ATOM__Int) == 0) return kUridAtomInt; if (std::strcmp(uri, LV2_ATOM__Literal) == 0) return kUridAtomLiteral; if (std::strcmp(uri, LV2_ATOM__Long) == 0) return kUridAtomLong; if (std::strcmp(uri, LV2_ATOM__Number) == 0) return kUridAtomNumber; if (std::strcmp(uri, LV2_ATOM__Object) == 0) return kUridAtomObject; if (std::strcmp(uri, LV2_ATOM__Path) == 0) return kUridAtomPath; if (std::strcmp(uri, LV2_ATOM__Property) == 0) return kUridAtomProperty; if (std::strcmp(uri, LV2_ATOM__Resource) == 0) return kUridAtomResource; if (std::strcmp(uri, LV2_ATOM__Sequence) == 0) return kUridAtomSequence; if (std::strcmp(uri, LV2_ATOM__Sound) == 0) return kUridAtomSound; if (std::strcmp(uri, LV2_ATOM__String) == 0) return kUridAtomString; if (std::strcmp(uri, LV2_ATOM__Tuple) == 0) return kUridAtomTuple; if (std::strcmp(uri, LV2_ATOM__URI) == 0) return kUridAtomURI; if (std::strcmp(uri, LV2_ATOM__URID) == 0) return kUridAtomURID; if (std::strcmp(uri, LV2_ATOM__Vector) == 0) return kUridAtomVector; if (std::strcmp(uri, LV2_ATOM__atomTransfer) == 0) return kUridAtomTransferAtom; if (std::strcmp(uri, LV2_ATOM__eventTransfer) == 0) return kUridAtomTransferEvent; // BufSize types if (std::strcmp(uri, LV2_BUF_SIZE__maxBlockLength) == 0) return kUridBufMaxLength; if (std::strcmp(uri, LV2_BUF_SIZE__minBlockLength) == 0) return kUridBufMinLength; if (std::strcmp(uri, LV2_BUF_SIZE__nominalBlockLength) == 0) return kUridBufNominalLength; if (std::strcmp(uri, LV2_BUF_SIZE__sequenceSize) == 0) return kUridBufSequenceSize; // Log types if (std::strcmp(uri, LV2_LOG__Error) == 0) return kUridLogError; if (std::strcmp(uri, LV2_LOG__Note) == 0) return kUridLogNote; if (std::strcmp(uri, LV2_LOG__Trace) == 0) return kUridLogTrace; if (std::strcmp(uri, LV2_LOG__Warning) == 0) return kUridLogWarning; // Patch types if (std::strcmp(uri, LV2_PATCH__Set) == 0) return kUridPatchSet; if (std::strcmp(uri, LV2_PATCH__property) == 0) return kUridPatchPoperty; if (std::strcmp(uri, LV2_PATCH__value) == 0) return kUridPatchValue; // Time types if (std::strcmp(uri, LV2_TIME__Position) == 0) return kUridTimePosition; if (std::strcmp(uri, LV2_TIME__bar) == 0) return kUridTimeBar; if (std::strcmp(uri, LV2_TIME__barBeat) == 0) return kUridTimeBarBeat; if (std::strcmp(uri, LV2_TIME__beat) == 0) return kUridTimeBeat; if (std::strcmp(uri, LV2_TIME__beatUnit) == 0) return kUridTimeBeatUnit; if (std::strcmp(uri, LV2_TIME__beatsPerBar) == 0) return kUridTimeBeatsPerBar; if (std::strcmp(uri, LV2_TIME__beatsPerMinute) == 0) return kUridTimeBeatsPerMinute; if (std::strcmp(uri, LV2_TIME__frame) == 0) return kUridTimeFrame; if (std::strcmp(uri, LV2_TIME__framesPerSecond) == 0) return kUridTimeFramesPerSecond; if (std::strcmp(uri, LV2_TIME__speed) == 0) return kUridTimeSpeed; if (std::strcmp(uri, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0) return kUridTimeTicksPerBeat; // Others if (std::strcmp(uri, LV2_MIDI__MidiEvent) == 0) return kUridMidiEvent; if (std::strcmp(uri, LV2_PARAMETERS__sampleRate) == 0) return kUridParamSampleRate; if (std::strcmp(uri, LV2_UI__backgroundColor) == 0) return kUridBackgroundColor; if (std::strcmp(uri, LV2_UI__foregroundColor) == 0) return kUridForegroundColor; if (std::strcmp(uri, LV2_UI__scaleFactor) == 0) return kUridScaleFactor; if (std::strcmp(uri, LV2_UI__windowTitle) == 0) return kUridWindowTitle; // Custom Carla types if (std::strcmp(uri, URI_CARLA_ATOM_WORKER_IN) == 0) return kUridCarlaAtomWorkerIn; if (std::strcmp(uri, URI_CARLA_ATOM_WORKER_RESP) == 0) return kUridCarlaAtomWorkerResp; if (std::strcmp(uri, LV2_KXSTUDIO_PROPERTIES__TransientWindowId) == 0) return kUridCarlaTransientWindowId; // Custom plugin types return ((CarlaPluginLV2*)handle)->getCustomURID(uri); } static const char* carla_lv2_urid_unmap(LV2_URID_Map_Handle handle, LV2_URID urid) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr); CARLA_SAFE_ASSERT_RETURN(urid != kUridNull, nullptr); carla_debug("carla_lv2_urid_unmap(%p, %i)", handle, urid); switch (urid) { // Atom types case kUridAtomBlank: return LV2_ATOM__Blank; case kUridAtomBool: return LV2_ATOM__Bool; case kUridAtomChunk: return LV2_ATOM__Chunk; case kUridAtomDouble: return LV2_ATOM__Double; case kUridAtomEvent: return LV2_ATOM__Event; case kUridAtomFloat: return LV2_ATOM__Float; case kUridAtomInt: return LV2_ATOM__Int; case kUridAtomLiteral: return LV2_ATOM__Literal; case kUridAtomLong: return LV2_ATOM__Long; case kUridAtomNumber: return LV2_ATOM__Number; case kUridAtomObject: return LV2_ATOM__Object; case kUridAtomPath: return LV2_ATOM__Path; case kUridAtomProperty: return LV2_ATOM__Property; case kUridAtomResource: return LV2_ATOM__Resource; case kUridAtomSequence: return LV2_ATOM__Sequence; case kUridAtomSound: return LV2_ATOM__Sound; case kUridAtomString: return LV2_ATOM__String; case kUridAtomTuple: return LV2_ATOM__Tuple; case kUridAtomURI: return LV2_ATOM__URI; case kUridAtomURID: return LV2_ATOM__URID; case kUridAtomVector: return LV2_ATOM__Vector; case kUridAtomTransferAtom: return LV2_ATOM__atomTransfer; case kUridAtomTransferEvent: return LV2_ATOM__eventTransfer; // BufSize types case kUridBufMaxLength: return LV2_BUF_SIZE__maxBlockLength; case kUridBufMinLength: return LV2_BUF_SIZE__minBlockLength; case kUridBufNominalLength: return LV2_BUF_SIZE__nominalBlockLength; case kUridBufSequenceSize: return LV2_BUF_SIZE__sequenceSize; // Log types case kUridLogError: return LV2_LOG__Error; case kUridLogNote: return LV2_LOG__Note; case kUridLogTrace: return LV2_LOG__Trace; case kUridLogWarning: return LV2_LOG__Warning; // Patch types case kUridPatchSet: return LV2_PATCH__Set; case kUridPatchPoperty: return LV2_PATCH__property; case kUridPatchValue: return LV2_PATCH__value; // Time types case kUridTimePosition: return LV2_TIME__Position; case kUridTimeBar: return LV2_TIME__bar; case kUridTimeBarBeat: return LV2_TIME__barBeat; case kUridTimeBeat: return LV2_TIME__beat; case kUridTimeBeatUnit: return LV2_TIME__beatUnit; case kUridTimeBeatsPerBar: return LV2_TIME__beatsPerBar; case kUridTimeBeatsPerMinute: return LV2_TIME__beatsPerMinute; case kUridTimeFrame: return LV2_TIME__frame; case kUridTimeFramesPerSecond: return LV2_TIME__framesPerSecond; case kUridTimeSpeed: return LV2_TIME__speed; case kUridTimeTicksPerBeat: return LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat; // Others case kUridMidiEvent: return LV2_MIDI__MidiEvent; case kUridParamSampleRate: return LV2_PARAMETERS__sampleRate; case kUridBackgroundColor: return LV2_UI__backgroundColor; case kUridForegroundColor: return LV2_UI__foregroundColor; case kUridScaleFactor: return LV2_UI__scaleFactor; case kUridWindowTitle: return LV2_UI__windowTitle; // Custom Carla types case kUridCarlaAtomWorkerIn: return URI_CARLA_ATOM_WORKER_IN; case kUridCarlaAtomWorkerResp: return URI_CARLA_ATOM_WORKER_RESP; case kUridCarlaTransientWindowId: return LV2_KXSTUDIO_PROPERTIES__TransientWindowId; } // Custom plugin types return ((CarlaPluginLV2*)handle)->getCustomURIDString(urid); } // ------------------------------------------------------------------- // Worker Feature static LV2_Worker_Status carla_lv2_worker_schedule(LV2_Worker_Schedule_Handle handle, uint32_t size, const void* data) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2_WORKER_ERR_UNKNOWN); carla_debug("carla_lv2_worker_schedule(%p, %i, %p)", handle, size, data); return ((CarlaPluginLV2*)handle)->handleWorkerSchedule(size, data); } static LV2_Worker_Status carla_lv2_worker_respond(LV2_Worker_Respond_Handle handle, uint32_t size, const void* data) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2_WORKER_ERR_UNKNOWN); carla_debug("carla_lv2_worker_respond(%p, %i, %p)", handle, size, data); return ((CarlaPluginLV2*)handle)->handleWorkerRespond(size, data); } // ------------------------------------------------------------------- // Inline Display Feature static void carla_lv2_inline_display_queue_draw(LV2_Inline_Display_Handle handle) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr,); // carla_debug("carla_lv2_inline_display_queue_draw(%p)", handle); ((CarlaPluginLV2*)handle)->handleInlineDisplayQueueRedraw(); } // ------------------------------------------------------------------- // Midnam Feature static void carla_lv2_midnam_update(LV2_Midnam_Handle handle) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr,); carla_stdout("carla_lv2_midnam_update(%p)", handle); ((CarlaPluginLV2*)handle)->handleMidnamUpdate(); } // ------------------------------------------------------------------- // External UI Feature static void carla_lv2_external_ui_closed(LV2UI_Controller controller) { CARLA_SAFE_ASSERT_RETURN(controller != nullptr,); carla_debug("carla_lv2_external_ui_closed(%p)", controller); ((CarlaPluginLV2*)controller)->handleExternalUIClosed(); } // ------------------------------------------------------------------- // UI Port-Map Feature static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_INVALID_PORT_INDEX); carla_debug("carla_lv2_ui_port_map(%p, \"%s\")", handle, symbol); return ((CarlaPluginLV2*)handle)->handleUIPortMap(symbol); } // ---------------------------------------------------------------------------------------------------------------- // UI Request Parameter Feature static LV2UI_Request_Value_Status carla_lv2_ui_request_value(LV2UI_Feature_Handle handle, LV2_URID key, LV2_URID type, const LV2_Feature* const* features) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_REQUEST_VALUE_ERR_UNKNOWN); carla_debug("carla_lv2_ui_request_value(%p, %u, %u, %p)", handle, key, type, features); return ((CarlaPluginLV2*)handle)->handleUIRequestValue(key, type, features); } // ------------------------------------------------------------------- // UI Resize Feature static int carla_lv2_ui_resize(LV2UI_Feature_Handle handle, int width, int height) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 1); carla_debug("carla_lv2_ui_resize(%p, %i, %i)", handle, width, height); return ((CarlaPluginLV2*)handle)->handleUIResize(width, height); } // ------------------------------------------------------------------- // UI Touch Feature static void carla_lv2_ui_touch(LV2UI_Feature_Handle handle, uint32_t port_index, bool touch) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr,); carla_debug("carla_lv2_ui_touch(%p, %u, %s)", handle, port_index, bool2str(touch)); ((CarlaPluginLV2*)handle)->handleUITouch(port_index, touch); } // ------------------------------------------------------------------- // UI Extension static void carla_lv2_ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer) { CARLA_SAFE_ASSERT_RETURN(controller != nullptr,); carla_debug("carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer); ((CarlaPluginLV2*)controller)->handleUIWrite(port_index, buffer_size, format, buffer); } // ------------------------------------------------------------------- // Lilv State static void carla_lilv_set_port_value(const char* port_symbol, void* user_data, const void* value, uint32_t size, uint32_t type) { CARLA_SAFE_ASSERT_RETURN(user_data != nullptr,); carla_debug("carla_lilv_set_port_value(\"%s\", %p, %p, %i, %i", port_symbol, user_data, value, size, type); ((CarlaPluginLV2*)user_data)->handleLilvSetPortValue(port_symbol, value, size, type); } // ------------------------------------------------------------------- CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginLV2) }; // ------------------------------------------------------------------------------------------------------------------- bool CarlaPipeServerLV2::msgReceived(const char* const msg) noexcept { if (std::strcmp(msg, "exiting") == 0) { closePipeServer(); fUiState = UiHide; return true; } if (std::strcmp(msg, "control") == 0) { uint32_t index; float value; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); try { kPlugin->handleUIWrite(index, sizeof(float), kUridNull, &value); } CARLA_SAFE_EXCEPTION("magReceived control"); return true; } if (std::strcmp(msg, "atom") == 0) { uint32_t index, atomTotalSize, base64Size; const char* base64atom; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(atomTotalSize), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(base64Size), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom, false, base64Size), true); std::vector chunk(carla_getChunkFromBase64String(base64atom)); CARLA_SAFE_ASSERT_UINT2_RETURN(chunk.size() >= sizeof(LV2_Atom), chunk.size(), sizeof(LV2_Atom), true); #ifdef CARLA_PROPER_CPP11_SUPPORT const LV2_Atom* const atom((const LV2_Atom*)chunk.data()); #else const LV2_Atom* const atom((const LV2_Atom*)&chunk.front()); #endif CARLA_SAFE_ASSERT_RETURN(lv2_atom_total_size(atom) == chunk.size(), true); try { kPlugin->handleUIWrite(index, lv2_atom_total_size(atom), kUridAtomTransferEvent, atom); } CARLA_SAFE_EXCEPTION("magReceived atom"); return true; } if (std::strcmp(msg, "program") == 0) { uint32_t index; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); try { kPlugin->setMidiProgram(static_cast(index), false, true, true, false); } CARLA_SAFE_EXCEPTION("msgReceived program"); return true; } if (std::strcmp(msg, "urid") == 0) { uint32_t urid, size; const char* uri; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(urid), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(size), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, false, size), true); if (urid != 0) { try { kPlugin->handleUridMap(urid, uri); } CARLA_SAFE_EXCEPTION("msgReceived urid"); } return true; } if (std::strcmp(msg, "reloadprograms") == 0) { int32_t index; CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index), true); try { kPlugin->handleProgramChanged(index); } CARLA_SAFE_EXCEPTION("handleProgramChanged"); return true; } if (std::strcmp(msg, "requestvalue") == 0) { uint32_t key, type; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(key), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(type), true); if (key != 0) { try { kPlugin->handleUIRequestValue(key, type, nullptr); } CARLA_SAFE_EXCEPTION("msgReceived requestvalue"); } return true; } return false; } // ------------------------------------------------------------------------------------------------------------------- CarlaPlugin* CarlaPlugin::newLV2(const Initializer& init) { carla_debug("CarlaPlugin::newLV2({%p, \"%s\", \"%s\", " P_INT64 "})", init.engine, init.name, init.label, init.uniqueId); CarlaPluginLV2* const plugin(new CarlaPluginLV2(init.engine, init.id)); if (! plugin->init(init.name, init.label, init.options)) { delete plugin; return nullptr; } return plugin; } // used in CarlaStandalone.cpp const void* carla_render_inline_display_lv2(CarlaPlugin* plugin, uint32_t width, uint32_t height); const void* carla_render_inline_display_lv2(CarlaPlugin* plugin, uint32_t width, uint32_t height) { CarlaPluginLV2* const lv2Plugin = (CarlaPluginLV2*)plugin; return lv2Plugin->renderInlineDisplay(width, height); } // ------------------------------------------------------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/plugin/CarlaPluginNative.cpp000066400000000000000000003341241364475620200226570ustar00rootroot00000000000000/* * Carla Native Plugin * Copyright (C) 2012-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaPluginInternal.hpp" #include "CarlaEngine.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaMathUtils.hpp" #include "CarlaNative.h" #include "water/misc/Time.h" #include "water/text/StringArray.h" using water::jmax; using water::String; using water::StringArray; // ----------------------------------------------------------------------- // used in carla-base.cpp std::size_t carla_getNativePluginCount() noexcept; const NativePluginDescriptor* carla_getNativePluginDescriptor(const std::size_t index) noexcept; // ----------------------------------------------------------------------- static LinkedList gPluginDescriptors; void carla_register_native_plugin(const NativePluginDescriptor* desc) { gPluginDescriptors.append(desc); } // ----------------------------------------------------------------------- static class NativePluginInitializer { public: NativePluginInitializer() noexcept : fNeedsInit(true) {} ~NativePluginInitializer() noexcept { gPluginDescriptors.clear(); } void initIfNeeded() noexcept { if (! fNeedsInit) return; fNeedsInit = false; try { carla_register_all_native_plugins(); } CARLA_SAFE_EXCEPTION("carla_register_all_native_plugins") } private: bool fNeedsInit; } sPluginInitializer; // ----------------------------------------------------------------------- std::size_t carla_getNativePluginCount() noexcept { sPluginInitializer.initIfNeeded(); return gPluginDescriptors.count(); } const NativePluginDescriptor* carla_getNativePluginDescriptor(const std::size_t index) noexcept { sPluginInitializer.initIfNeeded(); return gPluginDescriptors.getAt(index, nullptr); } // ----------------------------------------------------------------------- CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------- // Fallback data static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr }; static const EngineEvent kNullEngineEvent = { kEngineEventTypeNull, 0, 0, {} }; // ----------------------------------------------------------------------- struct NativePluginMidiOutData { uint32_t count; uint32_t* indexes; CarlaEngineEventPort** ports; NativePluginMidiOutData() noexcept : count(0), indexes(nullptr), ports(nullptr) {} ~NativePluginMidiOutData() noexcept { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT(indexes == nullptr); CARLA_SAFE_ASSERT(ports == nullptr); } bool createNew(const uint32_t newCount) { CARLA_SAFE_ASSERT_INT(count == 0, count); CARLA_SAFE_ASSERT_RETURN(indexes == nullptr, false); CARLA_SAFE_ASSERT_RETURN(ports == nullptr, false); CARLA_SAFE_ASSERT_RETURN(newCount > 0, false); indexes = new uint32_t[newCount]; ports = new CarlaEngineEventPort*[newCount]; count = newCount; carla_zeroStructs(indexes, newCount); carla_zeroStructs(ports, newCount); return true; } void clear() noexcept { if (ports != nullptr) { for (uint32_t i=0; i < count; ++i) { if (ports[i] != nullptr) { delete ports[i]; ports[i] = nullptr; } } delete[] ports; ports = nullptr; } if (indexes != nullptr) { delete[] indexes; indexes = nullptr; } count = 0; } void initBuffers() const noexcept { for (uint32_t i=0; i < count; ++i) { if (ports[i] != nullptr) ports[i]->initBuffer(); } } CARLA_DECLARE_NON_COPY_STRUCT(NativePluginMidiOutData) }; struct NativePluginMidiInData : NativePluginMidiOutData { struct MultiPortData { uint32_t cachedEventCount; uint32_t usedIndex; }; MultiPortData* multiportData; NativePluginMidiInData() noexcept : NativePluginMidiOutData(), multiportData(nullptr) {} ~NativePluginMidiInData() noexcept { CARLA_SAFE_ASSERT(multiportData == nullptr); } bool createNew(const uint32_t newCount) { if (! NativePluginMidiOutData::createNew(newCount)) return false; multiportData = new MultiPortData[newCount]; carla_zeroStructs(multiportData, newCount); return true; } void clear() noexcept { if (multiportData != nullptr) { delete[] multiportData; multiportData = nullptr; } NativePluginMidiOutData::clear(); } void initBuffers(CarlaEngineEventPort* const port) const noexcept { if (count == 1) { CARLA_SAFE_ASSERT_RETURN(port != nullptr,); carla_zeroStruct(multiportData[0]); multiportData[0].cachedEventCount = port->getEventCount(); return; } for (uint32_t i=0; i < count; ++i) { carla_zeroStruct(multiportData[i]); if (ports[i] != nullptr) { ports[i]->initBuffer(); multiportData[i].cachedEventCount = ports[i]->getEventCount(); } } } CARLA_DECLARE_NON_COPY_STRUCT(NativePluginMidiInData) }; // ----------------------------------------------------- class CarlaPluginNative : public CarlaPlugin { public: CarlaPluginNative(CarlaEngine* const engine, const uint id) : CarlaPlugin(engine, id), fHandle(nullptr), fHandle2(nullptr), fHost(), fDescriptor(nullptr), fIsProcessing(false), fIsOffline(false), fIsUiAvailable(false), fIsUiVisible(false), fNeedsIdle(false), fInlineDisplayNeedsRedraw(false), fInlineDisplayLastRedrawTime(0), fAudioAndCvInBuffers(nullptr), fAudioAndCvOutBuffers(nullptr), fMidiEventInCount(0), fMidiEventOutCount(0), fCurBufferSize(engine->getBufferSize()), fCurSampleRate(engine->getSampleRate()), fMidiIn(), fMidiOut(), fTimeInfo() { carla_debug("CarlaPluginNative::CarlaPluginNative(%p, %i)", engine, id); carla_fill(fCurMidiProgs, 0, MAX_MIDI_CHANNELS); carla_zeroStructs(fMidiInEvents, kPluginMaxMidiEvents); carla_zeroStructs(fMidiOutEvents, kPluginMaxMidiEvents); carla_zeroStruct(fTimeInfo); fHost.handle = this; fHost.resourceDir = carla_strdup(engine->getOptions().resourceDir); fHost.uiName = nullptr; fHost.uiParentId = engine->getOptions().frontendWinId; fHost.get_buffer_size = carla_host_get_buffer_size; fHost.get_sample_rate = carla_host_get_sample_rate; fHost.is_offline = carla_host_is_offline; fHost.get_time_info = carla_host_get_time_info; fHost.write_midi_event = carla_host_write_midi_event; fHost.ui_parameter_changed = carla_host_ui_parameter_changed; fHost.ui_custom_data_changed = carla_host_ui_custom_data_changed; fHost.ui_closed = carla_host_ui_closed; fHost.ui_open_file = carla_host_ui_open_file; fHost.ui_save_file = carla_host_ui_save_file; fHost.dispatcher = carla_host_dispatcher; } ~CarlaPluginNative() override { carla_debug("CarlaPluginNative::~CarlaPluginNative()"); fInlineDisplayNeedsRedraw = false; // close UI if (pData->hints & PLUGIN_HAS_CUSTOM_UI) { if (fIsUiVisible && fDescriptor != nullptr && fDescriptor->ui_show != nullptr && fHandle != nullptr) fDescriptor->ui_show(fHandle, false); #ifndef BUILD_BRIDGE pData->transientTryCounter = 0; #endif } pData->singleMutex.lock(); pData->masterMutex.lock(); if (pData->client != nullptr && pData->client->isActive()) pData->client->deactivate(); CARLA_ASSERT(! fIsProcessing); if (pData->active) { deactivate(); pData->active = false; } if (fDescriptor != nullptr) { if (fDescriptor->cleanup != nullptr) { if (fHandle != nullptr) fDescriptor->cleanup(fHandle); if (fHandle2 != nullptr) fDescriptor->cleanup(fHandle2); } fHandle = nullptr; fHandle2 = nullptr; fDescriptor = nullptr; } if (fHost.resourceDir != nullptr) { delete[] fHost.resourceDir; fHost.resourceDir = nullptr; } if (fHost.uiName != nullptr) { delete[] fHost.uiName; fHost.uiName = nullptr; } clearBuffers(); } // ------------------------------------------------------------------- // Information (base) PluginType getType() const noexcept override { return PLUGIN_INTERNAL; } PluginCategory getCategory() const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, PLUGIN_CATEGORY_NONE); return static_cast(fDescriptor->category); } // ------------------------------------------------------------------- // Information (count) uint32_t getMidiInCount() const noexcept override { return fMidiIn.count; } uint32_t getMidiOutCount() const noexcept override { return fMidiOut.count; } uint32_t getParameterScalePointCount(const uint32_t parameterId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_info != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0); // FIXME - try if (const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)) return param->scalePointCount; carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__, __LINE__); return 0; } // ------------------------------------------------------------------- // Information (current data) // nothing // ------------------------------------------------------------------- // Information (per-plugin data) uint getOptionsAvailable() const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0x0); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, 0x0); bool hasMidiProgs = false; if (fDescriptor->get_midi_program_count != nullptr) { try { hasMidiProgs = fDescriptor->get_midi_program_count(fHandle) > 0; } catch (...) {} } uint options = 0x0; // can't disable fixed buffers if required by the plugin if ((fDescriptor->hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS) == 0x0) options |= PLUGIN_OPTION_FIXED_BUFFERS; // can't disable forced stereo if enabled in the engine, or using CV if (pData->engine->getOptions().forceStereo || pData->cvIn.count != 0 || pData->cvOut.count != 0) pass(); // if inputs or outputs are just 1, then yes we can force stereo else if (pData->audioIn.count == 1 || pData->audioOut.count == 1 || fHandle2 != nullptr) options |= PLUGIN_OPTION_FORCE_STEREO; if (fDescriptor->supports & NATIVE_PLUGIN_SUPPORTS_CONTROL_CHANGES) options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; if (fDescriptor->supports & NATIVE_PLUGIN_SUPPORTS_CHANNEL_PRESSURE) options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; if (fDescriptor->supports & NATIVE_PLUGIN_SUPPORTS_NOTE_AFTERTOUCH) options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; if (fDescriptor->supports & NATIVE_PLUGIN_SUPPORTS_PITCHBEND) options |= PLUGIN_OPTION_SEND_PITCHBEND; if (fDescriptor->supports & NATIVE_PLUGIN_SUPPORTS_ALL_SOUND_OFF) options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; if (fDescriptor->supports & NATIVE_PLUGIN_SUPPORTS_PROGRAM_CHANGES) options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES; else if (hasMidiProgs) options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; return options; } float getParameterValue(const uint32_t parameterId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0.0f); CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_value != nullptr, 0.0f); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, 0.0f); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f); // FIXME - try return fDescriptor->get_parameter_value(fHandle, parameterId); } float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0.0f); CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_info != nullptr, 0.0f); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, 0.0f); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f); // FIXME - try if (const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)) { CARLA_SAFE_ASSERT_RETURN(scalePointId < param->scalePointCount, 0.0f); const NativeParameterScalePoint* scalePoint(¶m->scalePoints[scalePointId]); return scalePoint->value; } carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__, __LINE__); return 0.0f; } bool getLabel(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); if (fDescriptor->label != nullptr) { std::strncpy(strBuf, fDescriptor->label, STR_MAX); return true; } return CarlaPlugin::getLabel(strBuf); } bool getMaker(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); if (fDescriptor->maker != nullptr) { std::strncpy(strBuf, fDescriptor->maker, STR_MAX); return true; } return CarlaPlugin::getMaker(strBuf); } bool getCopyright(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); if (fDescriptor->copyright != nullptr) { std::strncpy(strBuf, fDescriptor->copyright, STR_MAX); return true; } return CarlaPlugin::getCopyright(strBuf); } bool getRealName(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); if (fDescriptor->name != nullptr) { std::strncpy(strBuf, fDescriptor->name, STR_MAX); return true; } return CarlaPlugin::getRealName(strBuf); } bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_info != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); // FIXME - try if (const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)) { if (param->name != nullptr) { std::strncpy(strBuf, param->name, STR_MAX); return true; } carla_safe_assert("param->name != nullptr", __FILE__, __LINE__); return CarlaPlugin::getParameterName(parameterId, strBuf); } carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__, __LINE__); return CarlaPlugin::getParameterName(parameterId, strBuf); } bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_info != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); // FIXME - try if (const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)) { if (param->unit != nullptr) { std::strncpy(strBuf, param->unit, STR_MAX); return true; } return CarlaPlugin::getParameterUnit(parameterId, strBuf); } carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__, __LINE__); return CarlaPlugin::getParameterUnit(parameterId, strBuf); } bool getParameterComment(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_info != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); // FIXME - try if (const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)) { if (param->comment != nullptr) { std::strncpy(strBuf, param->comment, STR_MAX); return true; } return CarlaPlugin::getParameterComment(parameterId, strBuf); } carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__, __LINE__); return CarlaPlugin::getParameterComment(parameterId, strBuf); } bool getParameterGroupName(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_info != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); // FIXME - try if (const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)) { if (param->groupName != nullptr) { std::strncpy(strBuf, param->groupName, STR_MAX); return true; } return CarlaPlugin::getParameterGroupName(parameterId, strBuf); } carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__, __LINE__); return CarlaPlugin::getParameterGroupName(parameterId, strBuf); } bool getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_info != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); // FIXME - try if (const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)) { CARLA_SAFE_ASSERT_RETURN(scalePointId < param->scalePointCount, false); const NativeParameterScalePoint* scalePoint(¶m->scalePoints[scalePointId]); if (scalePoint->label != nullptr) { std::strncpy(strBuf, scalePoint->label, STR_MAX); return true; } carla_safe_assert("scalePoint->label != nullptr", __FILE__, __LINE__); return CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf); } carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__, __LINE__); return CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf); } // ------------------------------------------------------------------- // Set data (state) void prepareForSave() override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); if (pData->midiprog.count > 0 && fDescriptor->category == NATIVE_PLUGIN_CATEGORY_SYNTH) { char strBuf[STR_MAX+1]; std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i", fCurMidiProgs[0], fCurMidiProgs[1], fCurMidiProgs[2], fCurMidiProgs[3], fCurMidiProgs[4], fCurMidiProgs[5], fCurMidiProgs[6], fCurMidiProgs[7], fCurMidiProgs[8], fCurMidiProgs[9], fCurMidiProgs[10], fCurMidiProgs[11], fCurMidiProgs[12], fCurMidiProgs[13], fCurMidiProgs[14], fCurMidiProgs[15]); strBuf[STR_MAX] = '\0'; CarlaPlugin::setCustomData(CUSTOM_DATA_TYPE_STRING, "midiPrograms", strBuf, false); } if (fDescriptor == nullptr || fDescriptor->get_state == nullptr || (fDescriptor->hints & NATIVE_PLUGIN_USES_STATE) == 0) return; if (char* data = fDescriptor->get_state(fHandle)) { CarlaPlugin::setCustomData(CUSTOM_DATA_TYPE_CHUNK, "State", data, false); std::free(data); } } // ------------------------------------------------------------------- // Set data (internal stuff) void setName(const char* const newName) override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0',); char uiName[std::strlen(newName)+6+1]; std::strcpy(uiName, newName); std::strcat(uiName, " (GUI)"); if (fHost.uiName != nullptr) delete[] fHost.uiName; fHost.uiName = carla_strdup(uiName); if (fDescriptor->dispatcher != nullptr && fIsUiVisible) fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_UI_NAME_CHANGED, 0, 0, uiName, 0.0f); CarlaPlugin::setName(newName); } void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept override { if (channel >= 0 && channel < MAX_MIDI_CHANNELS && pData->midiprog.count > 0) pData->midiprog.current = fCurMidiProgs[channel]; CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback); } // ------------------------------------------------------------------- // Set data (plugin-specific stuff) void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fDescriptor->set_parameter_value != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); const float fixedValue(pData->param.getFixedValue(parameterId, value)); // FIXME - try fDescriptor->set_parameter_value(fHandle, parameterId, fixedValue); if (fHandle2 != nullptr) fDescriptor->set_parameter_value(fHandle2, parameterId, fixedValue); CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback); } void setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fDescriptor->set_parameter_value != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); const float fixedValue(pData->param.getFixedValue(parameterId, value)); // FIXME - try fDescriptor->set_parameter_value(fHandle, parameterId, fixedValue); if (fHandle2 != nullptr) fDescriptor->set_parameter_value(fHandle2, parameterId, fixedValue); CarlaPlugin::setParameterValueRT(parameterId, fixedValue, sendCallbackLater); } void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr,); carla_debug("CarlaPluginNative::setCustomData(%s, %s, ..., %s)", type, key, bool2str(sendGui)); if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0) return CarlaPlugin::setCustomData(type, key, value, sendGui); if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0 && std::strcmp(type, CUSTOM_DATA_TYPE_CHUNK) != 0) return carla_stderr2("CarlaPluginNative::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is invalid", type, key, value, bool2str(sendGui)); if (std::strcmp(type, CUSTOM_DATA_TYPE_CHUNK) == 0) { if (fDescriptor->set_state != nullptr && (fDescriptor->hints & NATIVE_PLUGIN_USES_STATE) != 0) { const ScopedSingleProcessLocker spl(this, true); fDescriptor->set_state(fHandle, value); if (fHandle2 != nullptr) fDescriptor->set_state(fHandle2, value); } } else if (std::strcmp(key, "midiPrograms") == 0 && fDescriptor->set_midi_program != nullptr) { StringArray midiProgramList(StringArray::fromTokens(value, ":", "")); if (midiProgramList.size() == MAX_MIDI_CHANNELS) { uint8_t channel = 0; for (String *it=midiProgramList.begin(), *end=midiProgramList.end(); it != end; ++it) { const int index(it->getIntValue()); if (index >= 0 && index < static_cast(pData->midiprog.count)) { const uint32_t bank = pData->midiprog.data[index].bank; const uint32_t program = pData->midiprog.data[index].program; fDescriptor->set_midi_program(fHandle, channel, bank, program); if (fHandle2 != nullptr) fDescriptor->set_midi_program(fHandle2, channel, bank, program); fCurMidiProgs[channel] = index; if (pData->ctrlChannel == static_cast(channel)) { pData->midiprog.current = index; pData->engine->callback(true, true, ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED, pData->id, index, 0, 0, 0.0f, nullptr); } } ++channel; } CARLA_SAFE_ASSERT(channel == MAX_MIDI_CHANNELS); } } else { if (fDescriptor->set_custom_data != nullptr) { fDescriptor->set_custom_data(fHandle, key, value); if (fHandle2 != nullptr) fDescriptor->set_custom_data(fHandle2, key, value); } if (sendGui && fIsUiVisible && fDescriptor->ui_set_custom_data != nullptr) fDescriptor->ui_set_custom_data(fHandle, key, value); } CarlaPlugin::setCustomData(type, key, value, sendGui); } void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->midiprog.count),); CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,); // TODO, put into check below if ((pData->hints & PLUGIN_IS_SYNTH) != 0 && (pData->ctrlChannel < 0 || pData->ctrlChannel >= MAX_MIDI_CHANNELS)) return CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit); if (index >= 0) { const uint8_t channel = uint8_t((pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) ? pData->ctrlChannel : 0); const uint32_t bank = pData->midiprog.data[index].bank; const uint32_t program = pData->midiprog.data[index].program; const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); try { fDescriptor->set_midi_program(fHandle, channel, bank, program); } catch(...) {} if (fHandle2 != nullptr) { try { fDescriptor->set_midi_program(fHandle2, channel, bank, program); } catch(...) {} } fCurMidiProgs[channel] = index; } CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit); } // FIXME: this is never used void setMidiProgramRT(const uint32_t index, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,); // TODO, put into check below if ((pData->hints & PLUGIN_IS_SYNTH) != 0 && (pData->ctrlChannel < 0 || pData->ctrlChannel >= MAX_MIDI_CHANNELS)) return CarlaPlugin::setMidiProgramRT(index, sendCallbackLater); const uint8_t channel = uint8_t((pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) ? pData->ctrlChannel : 0); const uint32_t bank = pData->midiprog.data[index].bank; const uint32_t program = pData->midiprog.data[index].program; try { fDescriptor->set_midi_program(fHandle, channel, bank, program); } catch(...) {} if (fHandle2 != nullptr) { try { fDescriptor->set_midi_program(fHandle2, channel, bank, program); } catch(...) {} } fCurMidiProgs[channel] = static_cast(index); CarlaPlugin::setMidiProgramRT(index, sendCallbackLater); } // ------------------------------------------------------------------- // Set ui stuff void showCustomUI(const bool yesNo) override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); if (fDescriptor->ui_show == nullptr) return; fIsUiAvailable = true; fDescriptor->ui_show(fHandle, yesNo); // UI might not be available, see NATIVE_HOST_OPCODE_UI_UNAVAILABLE if (yesNo && ! fIsUiAvailable) return; fIsUiVisible = yesNo; if (! yesNo) { #ifndef BUILD_BRIDGE pData->transientTryCounter = 0; #endif return; } #ifndef BUILD_BRIDGE if ((fDescriptor->hints & NATIVE_PLUGIN_USES_PARENT_ID) == 0 && std::strstr(fDescriptor->label, "file") == nullptr) pData->tryTransient(); #endif if (fDescriptor->ui_set_custom_data != nullptr) { for (LinkedList::Itenerator it = pData->custom.begin2(); it.valid(); it.next()) { const CustomData& cData(it.getValue(kCustomDataFallback)); CARLA_SAFE_ASSERT_CONTINUE(cData.isValid()); if (std::strcmp(cData.type, CUSTOM_DATA_TYPE_STRING) == 0 && std::strcmp(cData.key, "midiPrograms") != 0) fDescriptor->ui_set_custom_data(fHandle, cData.key, cData.value); } } if (fDescriptor->ui_set_midi_program != nullptr && pData->midiprog.current >= 0 && pData->midiprog.count > 0) { const int32_t index = pData->midiprog.current; const uint8_t channel = uint8_t((pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) ? pData->ctrlChannel : 0); const uint32_t bank = pData->midiprog.data[index].bank; const uint32_t program = pData->midiprog.data[index].program; fDescriptor->ui_set_midi_program(fHandle, channel, bank, program); } if (fDescriptor->ui_set_parameter_value != nullptr) { for (uint32_t i=0; i < pData->param.count; ++i) fDescriptor->ui_set_parameter_value(fHandle, i, fDescriptor->get_parameter_value(fHandle, i)); } } void idle() override { if (fNeedsIdle) { fNeedsIdle = false; fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_IDLE, 0, 0, nullptr, 0.0f); } if (fInlineDisplayNeedsRedraw) { // TESTING CARLA_SAFE_ASSERT(pData->enabled) CARLA_SAFE_ASSERT(!pData->engine->isAboutToClose()); CARLA_SAFE_ASSERT(pData->client->isActive()); if (pData->enabled && !pData->engine->isAboutToClose() && pData->client->isActive()) { const int64_t timeNow = water::Time::currentTimeMillis(); if (timeNow - fInlineDisplayLastRedrawTime > (1000 / 30)) { fInlineDisplayNeedsRedraw = false; fInlineDisplayLastRedrawTime = timeNow; pData->engine->callback(true, true, ENGINE_CALLBACK_INLINE_DISPLAY_REDRAW, pData->id, 0, 0, 0, 0.0f, nullptr); } } } CarlaPlugin::idle(); } void uiIdle() override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); if (fIsUiVisible && fDescriptor->ui_idle != nullptr) fDescriptor->ui_idle(fHandle); CarlaPlugin::uiIdle(); } // ------------------------------------------------------------------- // Plugin state void reload() override { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); carla_debug("CarlaPluginNative::reload() - start"); const EngineProcessMode processMode(pData->engine->getProccessMode()); // Safely disable plugin for reload const ScopedDisabler sd(this); if (pData->active) deactivate(); clearBuffers(); uint32_t aIns, aOuts, cvIns, cvOuts, mIns, mOuts, j; bool forcedStereoIn, forcedStereoOut; forcedStereoIn = forcedStereoOut = false; bool needsCtrlIn, needsCtrlOut; needsCtrlIn = needsCtrlOut = false; aIns = fDescriptor->audioIns; aOuts = fDescriptor->audioOuts; cvIns = fDescriptor->cvIns; cvOuts = fDescriptor->cvOuts; mIns = fDescriptor->midiIns; mOuts = fDescriptor->midiOuts; if ((pData->options & PLUGIN_OPTION_FORCE_STEREO) != 0 && (aIns == 1 || aOuts == 1) && mIns <= 1 && mOuts <= 1) { if (fHandle2 == nullptr) fHandle2 = fDescriptor->instantiate(&fHost); if (fHandle2 != nullptr) { if (aIns == 1) { aIns = 2; forcedStereoIn = true; } if (aOuts == 1) { aOuts = 2; forcedStereoOut = true; } } } if (aIns > 0) { pData->audioIn.createNew(aIns); } if (aOuts > 0) { pData->audioOut.createNew(aOuts); needsCtrlIn = true; } if (cvIns > 0) { pData->cvIn.createNew(cvIns); } if (cvOuts > 0) { pData->cvOut.createNew(cvOuts); } if (const uint32_t acIns = aIns + cvIns) { fAudioAndCvInBuffers = new float*[acIns]; carla_zeroPointers(fAudioAndCvInBuffers, acIns); } if (const uint32_t acOuts = aOuts + cvOuts) { fAudioAndCvOutBuffers = new float*[acOuts]; carla_zeroPointers(fAudioAndCvOutBuffers, acOuts); } if (mIns > 0) { fMidiIn.createNew(mIns); needsCtrlIn = (mIns == 1); } if (mOuts > 0) { fMidiOut.createNew(mOuts); needsCtrlOut = (mOuts == 1); } const uint portNameSize(pData->engine->getMaxPortNameSize()); CarlaString portName; // Audio Ins for (j=0; j < aIns; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (fDescriptor->get_buffer_port_name != nullptr) { portName += fDescriptor->get_buffer_port_name(fHandle, forcedStereoIn ? 0 : j, false); } else if (aIns > 1 && ! forcedStereoIn) { portName += "input_"; portName += CarlaString(j+1); } else portName += "input"; portName.truncate(portNameSize); pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j); pData->audioIn.ports[j].rindex = j; if (forcedStereoIn) { portName += "_2"; pData->audioIn.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, 1); pData->audioIn.ports[1].rindex = j; break; } } // Audio Outs for (j=0; j < aOuts; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (fDescriptor->get_buffer_port_name != nullptr) { portName += fDescriptor->get_buffer_port_name(fHandle, forcedStereoOut ? 0 : j, true); } else if (aOuts > 1 && ! forcedStereoOut) { portName += "output_"; portName += CarlaString(j+1); } else portName += "output"; portName.truncate(portNameSize); pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j); pData->audioOut.ports[j].rindex = j; if (forcedStereoOut) { portName += "_2"; pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 1); pData->audioOut.ports[1].rindex = j; break; } } // CV Ins for (j=0; j < cvIns; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (fDescriptor->get_buffer_port_name != nullptr) { portName += fDescriptor->get_buffer_port_name(fHandle, fDescriptor->audioIns + j, false); } else if (cvIns > 1) { portName += "cv_input_"; portName += CarlaString(j+1); } else portName += "cv_input"; portName.truncate(portNameSize); float min = -1.0f, max = 1.0f; if (fDescriptor->get_buffer_port_range != nullptr) { if (const NativePortRange* const range = fDescriptor->get_buffer_port_range(fHandle, fDescriptor->audioIns + j, false)) { min = range->minimum; max = range->maximum; } } pData->cvIn.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, true, j); pData->cvIn.ports[j].rindex = j; pData->cvIn.ports[j].port->setRange(min, max); } // CV Outs for (j=0; j < cvOuts; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (fDescriptor->get_buffer_port_name != nullptr) { portName += fDescriptor->get_buffer_port_name(fHandle, fDescriptor->audioOuts + j, true); } else if (cvOuts > 1) { portName += "cv_output_"; portName += CarlaString(j+1); } else portName += "cv_output"; portName.truncate(portNameSize); float min = -1.0f, max = 1.0f; if (fDescriptor->get_buffer_port_range != nullptr) { if (const NativePortRange* const range = fDescriptor->get_buffer_port_range(fHandle, fDescriptor->audioOuts + j, true)) { min = range->minimum; max = range->maximum; } } pData->cvOut.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, false, j); pData->cvOut.ports[j].rindex = j; pData->cvOut.ports[j].port->setRange(min, max); } // MIDI Input (only if multiple) if (mIns > 1) { for (j=0; j < mIns; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "midi-in_"; portName += CarlaString(j+1); portName.truncate(portNameSize); fMidiIn.ports[j] = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, j); fMidiIn.indexes[j] = j; } pData->event.portIn = fMidiIn.ports[0]; } // MIDI Output (only if multiple) if (mOuts > 1) { for (j=0; j < mOuts; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "midi-out_"; portName += CarlaString(j+1); portName.truncate(portNameSize); fMidiOut.ports[j] = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, j); fMidiOut.indexes[j] = j; } pData->event.portOut = fMidiOut.ports[0]; } reloadParameters(&needsCtrlIn, &needsCtrlOut); if (needsCtrlIn || mIns == 1) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-in"; portName.truncate(portNameSize); pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->event.cvSourcePorts = pData->client->createCVSourcePorts(); #endif } if (needsCtrlOut || mOuts == 1) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-out"; portName.truncate(portNameSize); pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0); } if (forcedStereoIn || forcedStereoOut) pData->options |= PLUGIN_OPTION_FORCE_STEREO; else pData->options &= ~PLUGIN_OPTION_FORCE_STEREO; // plugin hints pData->hints = 0x0; if (aOuts > 0 && (aIns == aOuts || aIns == 1)) pData->hints |= PLUGIN_CAN_DRYWET; if (aOuts > 0) pData->hints |= PLUGIN_CAN_VOLUME; if (aOuts >= 2 && aOuts % 2 == 0) pData->hints |= PLUGIN_CAN_BALANCE; // native plugin hints if (fDescriptor->hints & NATIVE_PLUGIN_IS_RTSAFE) pData->hints |= PLUGIN_IS_RTSAFE; if (fDescriptor->hints & NATIVE_PLUGIN_IS_SYNTH) pData->hints |= PLUGIN_IS_SYNTH; if (fDescriptor->hints & NATIVE_PLUGIN_HAS_UI) pData->hints |= PLUGIN_HAS_CUSTOM_UI; if (fDescriptor->hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS) pData->hints |= PLUGIN_NEEDS_FIXED_BUFFERS; if (fDescriptor->hints & NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD) pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD; if (fDescriptor->hints & NATIVE_PLUGIN_USES_MULTI_PROGS) pData->hints |= PLUGIN_USES_MULTI_PROGS; if (fDescriptor->hints & NATIVE_PLUGIN_HAS_INLINE_DISPLAY) pData->hints |= PLUGIN_HAS_INLINE_DISPLAY; // extra plugin hints pData->extraHints = 0x0; bufferSizeChanged(pData->engine->getBufferSize()); reloadPrograms(true); if (pData->active) activate(); carla_debug("CarlaPluginNative::reload() - end"); } void reloadParameters(bool* const needsCtrlIn, bool* const needsCtrlOut) { carla_debug("CarlaPluginNative::reloadParameters() - start"); const float sampleRate = static_cast(pData->engine->getSampleRate()); const uint32_t params = (fDescriptor->get_parameter_count != nullptr && fDescriptor->get_parameter_info != nullptr) ? fDescriptor->get_parameter_count(fHandle) : 0; pData->param.clear(); if (params > 0) { pData->param.createNew(params, true); } for (uint32_t j=0; j < params; ++j) { const NativeParameter* const paramInfo(fDescriptor->get_parameter_info(fHandle, j)); CARLA_SAFE_ASSERT_CONTINUE(paramInfo != nullptr); pData->param.data[j].type = PARAMETER_UNKNOWN; pData->param.data[j].index = static_cast(j); pData->param.data[j].rindex = static_cast(j); float min, max, def, step, stepSmall, stepLarge; // min value min = paramInfo->ranges.min; // max value max = paramInfo->ranges.max; if (min > max) max = min; if (carla_isEqual(min, max)) { carla_stderr2("WARNING - Broken plugin parameter '%s': max == min", paramInfo->name); max = min + 0.1f; } // default value def = paramInfo->ranges.def; if (def < min) def = min; else if (def > max) def = max; if (paramInfo->hints & NATIVE_PARAMETER_USES_SAMPLE_RATE) { min *= sampleRate; max *= sampleRate; def *= sampleRate; pData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE; } if (paramInfo->hints & NATIVE_PARAMETER_IS_BOOLEAN) { step = max - min; stepSmall = step; stepLarge = step; pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN; } else if (paramInfo->hints & NATIVE_PARAMETER_IS_INTEGER) { step = 1.0f; stepSmall = 1.0f; stepLarge = 10.0f; pData->param.data[j].hints |= PARAMETER_IS_INTEGER; } else { float range = max - min; step = range/100.0f; stepSmall = range/1000.0f; stepLarge = range/10.0f; } if (paramInfo->hints & NATIVE_PARAMETER_IS_OUTPUT) { pData->param.data[j].type = PARAMETER_OUTPUT; if (needsCtrlOut != nullptr) *needsCtrlOut = true; } else { pData->param.data[j].type = PARAMETER_INPUT; if (needsCtrlIn != nullptr) *needsCtrlIn = true; } // extra parameter hints if (paramInfo->hints & NATIVE_PARAMETER_IS_ENABLED) { pData->param.data[j].hints |= PARAMETER_IS_ENABLED; if (paramInfo->hints & NATIVE_PARAMETER_IS_AUTOMABLE) { pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE; pData->param.data[j].hints |= PARAMETER_CAN_BE_CV_CONTROLLED; } } if (paramInfo->hints & NATIVE_PARAMETER_IS_LOGARITHMIC) pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC; if (paramInfo->hints & NATIVE_PARAMETER_USES_SCALEPOINTS) pData->param.data[j].hints |= PARAMETER_USES_SCALEPOINTS; pData->param.ranges[j].min = min; pData->param.ranges[j].max = max; pData->param.ranges[j].def = def; pData->param.ranges[j].step = step; pData->param.ranges[j].stepSmall = stepSmall; pData->param.ranges[j].stepLarge = stepLarge; } carla_debug("CarlaPluginNative::reloadParameters() - end"); } void reloadPrograms(const bool doInit) override { carla_debug("CarlaPluginNative::reloadPrograms(%s)", bool2str(doInit)); uint32_t i, oldCount = pData->midiprog.count; const int32_t current = pData->midiprog.current; // Delete old programs pData->midiprog.clear(); // Query new programs uint32_t count = 0; if (fDescriptor->get_midi_program_count != nullptr && fDescriptor->get_midi_program_info != nullptr && fDescriptor->set_midi_program != nullptr) count = fDescriptor->get_midi_program_count(fHandle); if (count > 0) { pData->midiprog.createNew(count); // Update data for (i=0; i < count; ++i) { const NativeMidiProgram* const mpDesc(fDescriptor->get_midi_program_info(fHandle, i)); CARLA_SAFE_ASSERT_CONTINUE(mpDesc != nullptr); pData->midiprog.data[i].bank = mpDesc->bank; pData->midiprog.data[i].program = mpDesc->program; pData->midiprog.data[i].name = carla_strdup(mpDesc->name); } } if (doInit) { if (count > 0) setMidiProgram(0, false, false, false, true); } else { // Check if current program is invalid bool programChanged = false; if (count == oldCount+1) { // one midi program added, probably created by user pData->midiprog.current = static_cast(oldCount); programChanged = true; } else if (current < 0 && count > 0) { // programs exist now, but not before pData->midiprog.current = 0; programChanged = true; } else if (current >= 0 && count == 0) { // programs existed before, but not anymore pData->midiprog.current = -1; programChanged = true; } else if (current >= static_cast(count)) { // current midi program > count pData->midiprog.current = 0; programChanged = true; } else { // no change pData->midiprog.current = current; } if (programChanged) setMidiProgram(pData->midiprog.current, true, true, true, false); pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0f, nullptr); } } // ------------------------------------------------------------------- // Plugin processing void activate() noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); if (fDescriptor->activate != nullptr) { try { fDescriptor->activate(fHandle); } catch(...) {} if (fHandle2 != nullptr) { try { fDescriptor->activate(fHandle2); } catch(...) {} } } } void deactivate() noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); if (fDescriptor->deactivate != nullptr) { try { fDescriptor->deactivate(fHandle); } catch(...) {} if (fHandle2 != nullptr) { try { fDescriptor->deactivate(fHandle2); } catch(...) {} } } } const EngineEvent& findNextEvent() { if (fMidiIn.count == 1) { NativePluginMidiInData::MultiPortData& multiportData(fMidiIn.multiportData[0]); if (multiportData.usedIndex == multiportData.cachedEventCount) { const uint32_t eventCount = pData->event.portIn->getEventCount(); CARLA_SAFE_ASSERT_INT2(eventCount == multiportData.cachedEventCount, eventCount, multiportData.cachedEventCount); return kNullEngineEvent; } return pData->event.portIn->getEvent(multiportData.usedIndex++); } uint32_t lowestSampleTime = 9999999; uint32_t portMatching = 0; bool found = false; // process events in order for multiple ports for (uint32_t m=0; m < fMidiIn.count; ++m) { CarlaEngineEventPort* const eventPort(fMidiIn.ports[m]); NativePluginMidiInData::MultiPortData& multiportData(fMidiIn.multiportData[m]); if (multiportData.usedIndex == multiportData.cachedEventCount) continue; const EngineEvent& event(eventPort->getEventUnchecked(multiportData.usedIndex)); if (event.time < lowestSampleTime) { lowestSampleTime = event.time; portMatching = m; found = true; } } if (found) { CarlaEngineEventPort* const eventPort(fMidiIn.ports[portMatching]); NativePluginMidiInData::MultiPortData& multiportData(fMidiIn.multiportData[portMatching]); return eventPort->getEvent(multiportData.usedIndex++); } return kNullEngineEvent; } void process(const float* const* const audioIn, float** const audioOut, const float* const* const cvIn, float** const cvOut, const uint32_t frames) override { // -------------------------------------------------------------------------------------------------------- // Check if active if (! pData->active) { // disable any output sound for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(audioOut[i], frames); for (uint32_t i=0; i < pData->cvOut.count; ++i) carla_zeroFloats(cvOut[i], frames); return; } fMidiEventInCount = fMidiEventOutCount = 0; carla_zeroStructs(fMidiInEvents, kPluginMaxMidiEvents); carla_zeroStructs(fMidiOutEvents, kPluginMaxMidiEvents); // -------------------------------------------------------------------------------------------------------- // Check if needs reset if (pData->needsReset) { if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { fMidiEventInCount = MAX_MIDI_CHANNELS*2; for (uint8_t k=0, i=MAX_MIDI_CHANNELS; k < MAX_MIDI_CHANNELS; ++k) { fMidiInEvents[k].data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT)); fMidiInEvents[k].data[1] = MIDI_CONTROL_ALL_NOTES_OFF; fMidiInEvents[k].data[2] = 0; fMidiInEvents[k].size = 3; fMidiInEvents[k+i].data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT)); fMidiInEvents[k+i].data[1] = MIDI_CONTROL_ALL_SOUND_OFF; fMidiInEvents[k+i].data[2] = 0; fMidiInEvents[k+i].size = 3; } } else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) { fMidiEventInCount = MAX_MIDI_NOTE; for (uint8_t k=0; k < MAX_MIDI_NOTE; ++k) { fMidiInEvents[k].data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (pData->ctrlChannel & MIDI_CHANNEL_BIT)); fMidiInEvents[k].data[1] = k; fMidiInEvents[k].data[2] = 0; fMidiInEvents[k].size = 3; } } pData->needsReset = false; } // -------------------------------------------------------------------------------------------------------- // Set TimeInfo const EngineTimeInfo timeInfo(pData->engine->getTimeInfo()); fTimeInfo.playing = timeInfo.playing; fTimeInfo.frame = timeInfo.frame; fTimeInfo.usecs = timeInfo.usecs; if (timeInfo.bbt.valid) { fTimeInfo.bbt.valid = true; fTimeInfo.bbt.bar = timeInfo.bbt.bar; fTimeInfo.bbt.beat = timeInfo.bbt.beat; fTimeInfo.bbt.tick = timeInfo.bbt.tick; fTimeInfo.bbt.barStartTick = timeInfo.bbt.barStartTick; fTimeInfo.bbt.beatsPerBar = timeInfo.bbt.beatsPerBar; fTimeInfo.bbt.beatType = timeInfo.bbt.beatType; fTimeInfo.bbt.ticksPerBeat = timeInfo.bbt.ticksPerBeat; fTimeInfo.bbt.beatsPerMinute = timeInfo.bbt.beatsPerMinute; } else { fTimeInfo.bbt.valid = false; } #if 0 // This test code has proven to be quite useful // So I am leaving it behind, I might need it again.. if (pData->id == 1) { static int64_t last_frame = timeInfo.frame; static int64_t last_dev_frame = 0; static double last_val = timeInfo.bbt.barStartTick + ((timeInfo.bbt.beat-1) * timeInfo.bbt.ticksPerBeat) + timeInfo.bbt.tick; static double last_dev_val = 0.0; int64_t cur_frame = timeInfo.frame; int64_t cur_dev_frame = cur_frame - last_frame; double cur_val = timeInfo.bbt.barStartTick + ((timeInfo.bbt.beat-1) * timeInfo.bbt.ticksPerBeat) + timeInfo.bbt.tick; double cur_dev_val = cur_val - last_val; if (std::abs(last_dev_val - cur_dev_val) >= 0.0001 || last_dev_frame != cur_dev_frame) { carla_stdout("currently %u at %u => %f : DEV1: %li : DEV2: %f", frames, timeInfo.frame, cur_val, cur_dev_frame, cur_dev_val); } last_val = cur_val; last_dev_val = cur_dev_val; last_frame = cur_frame; last_dev_frame = cur_dev_frame; } #endif // -------------------------------------------------------------------------------------------------------- // Event Input and Processing if (pData->event.portIn != nullptr) { // ---------------------------------------------------------------------------------------------------- // MIDI Input (External) if (pData->extNotes.mutex.tryLock()) { ExternalMidiNote note = { 0, 0, 0 }; for (; fMidiEventInCount < kPluginMaxMidiEvents && ! pData->extNotes.data.isEmpty();) { note = pData->extNotes.data.getFirst(note, true); CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]); nativeEvent.data[0] = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); nativeEvent.data[1] = note.note; nativeEvent.data[2] = note.velo; nativeEvent.size = 3; } pData->extNotes.mutex.unlock(); } // End of MIDI Input (External) // ---------------------------------------------------------------------------------------------------- // Event Input (System) #ifndef BUILD_BRIDGE bool allNotesOffSent = false; #endif const bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; uint32_t startTime = 0; uint32_t timeOffset = 0; uint32_t nextBankId; if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) nextBankId = pData->midiprog.data[pData->midiprog.current].bank; else nextBankId = 0; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr) pData->event.cvSourcePorts->initPortBuffers(cvIn + pData->cvIn.count, frames, isSampleAccurate, pData->event.portIn); #endif for (;;) { const EngineEvent& event(findNextEvent()); if (event.type == kEngineEventTypeNull) break; uint32_t eventTime = event.time; CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames); if (eventTime < timeOffset) { carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'", eventTime, timeOffset, pData->name); eventTime = timeOffset; } if (isSampleAccurate && eventTime > timeOffset) { if (processSingle(audioIn, audioOut, cvIn, cvOut, eventTime - timeOffset, timeOffset)) { startTime = 0; timeOffset = eventTime; if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) nextBankId = pData->midiprog.data[pData->midiprog.current].bank; else nextBankId = 0; if (fMidiEventInCount > 0) { carla_zeroStructs(fMidiInEvents, fMidiEventInCount); fMidiEventInCount = 0; } if (fMidiEventOutCount > 0) { carla_zeroStructs(fMidiOutEvents, fMidiEventOutCount); fMidiEventOutCount = 0; } } else startTime += timeOffset; } // Control change switch (event.type) { case kEngineEventTypeNull: break; case kEngineEventTypeControl: { const EngineControlEvent& ctrlEvent = event.ctrl; switch (ctrlEvent.type) { case kEngineControlEventTypeNull: break; case kEngineControlEventTypeParameter: { float value; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // non-midi if (event.channel == kEngineEventNonMidiChannel) { const uint32_t k = ctrlEvent.param; CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count); value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.value); setParameterValueRT(k, value, true); continue; } // Control backend stuff if (event.channel == pData->ctrlChannel) { if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) > 0) { value = ctrlEvent.value; setDryWetRT(value, true); } if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) > 0) { value = ctrlEvent.value*127.0f/100.0f; setVolumeRT(value, true); } if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) > 0) { float left, right; value = ctrlEvent.value/0.5f - 1.0f; if (value < 0.0f) { left = -1.0f; right = (value*2.0f)+1.0f; } else if (value > 0.0f) { left = (value*2.0f)-1.0f; right = 1.0f; } else { left = -1.0f; right = 1.0f; } setBalanceLeftRT(left, true); setBalanceRightRT(right, true); } } #endif // Control plugin parameters for (uint32_t k=0; k < pData->param.count; ++k) { if (pData->param.data[k].midiChannel != event.channel) continue; if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) continue; if (pData->param.data[k].type != PARAMETER_INPUT) continue; if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) continue; value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.value); setParameterValueRT(k, value, true); } if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE) { if (fMidiEventInCount >= kPluginMaxMidiEvents) continue; NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]); carla_zeroStruct(nativeEvent); nativeEvent.time = isSampleAccurate ? startTime : eventTime; nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); nativeEvent.data[1] = uint8_t(ctrlEvent.param); nativeEvent.data[2] = uint8_t(ctrlEvent.value*127.0f); nativeEvent.size = 3; } break; } // case kEngineControlEventTypeParameter case kEngineControlEventTypeMidiBank: if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) { if (event.channel == pData->ctrlChannel) nextBankId = ctrlEvent.param; } else if (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) { if (fMidiEventInCount >= kPluginMaxMidiEvents) continue; NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]); carla_zeroStruct(nativeEvent); nativeEvent.time = isSampleAccurate ? startTime : eventTime; nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); nativeEvent.data[1] = MIDI_CONTROL_BANK_SELECT; nativeEvent.data[2] = uint8_t(ctrlEvent.param); nativeEvent.size = 3; } break; case kEngineControlEventTypeMidiProgram: if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) { if (event.channel < MAX_MIDI_CHANNELS) { const uint32_t nextProgramId(ctrlEvent.param); for (uint32_t k=0; k < pData->midiprog.count; ++k) { if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId) { fDescriptor->set_midi_program(fHandle, event.channel, nextBankId, nextProgramId); if (fHandle2 != nullptr) fDescriptor->set_midi_program(fHandle2, event.channel, nextBankId, nextProgramId); fCurMidiProgs[event.channel] = static_cast(k); if (event.channel == pData->ctrlChannel) { pData->postponeRtEvent(kPluginPostRtEventMidiProgramChange, true, static_cast(k), 0, 0, 0.0f); } break; } } } } else if (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) { if (fMidiEventInCount >= kPluginMaxMidiEvents) continue; NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]); carla_zeroStruct(nativeEvent); nativeEvent.time = isSampleAccurate ? startTime : eventTime; nativeEvent.data[0] = uint8_t(MIDI_STATUS_PROGRAM_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); nativeEvent.data[1] = uint8_t(ctrlEvent.param); nativeEvent.size = 2; } break; case kEngineControlEventTypeAllSoundOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { if (fMidiEventInCount >= kPluginMaxMidiEvents) continue; NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]); carla_zeroStruct(nativeEvent); nativeEvent.time = isSampleAccurate ? startTime : eventTime; nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); nativeEvent.data[1] = MIDI_CONTROL_ALL_SOUND_OFF; nativeEvent.data[2] = 0; nativeEvent.size = 3; } break; case kEngineControlEventTypeAllNotesOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { #ifndef BUILD_BRIDGE if (event.channel == pData->ctrlChannel && ! allNotesOffSent) { allNotesOffSent = true; postponeRtAllNotesOff(); } #endif if (fMidiEventInCount >= kPluginMaxMidiEvents) continue; NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]); carla_zeroStruct(nativeEvent); nativeEvent.time = isSampleAccurate ? startTime : eventTime; nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); nativeEvent.data[1] = MIDI_CONTROL_ALL_NOTES_OFF; nativeEvent.data[2] = 0; nativeEvent.size = 3; } break; } break; } case kEngineEventTypeMidi: { if (fMidiEventInCount >= kPluginMaxMidiEvents) continue; const EngineMidiEvent& midiEvent(event.midi); if (midiEvent.size > 4) continue; #ifdef CARLA_PROPER_CPP11_SUPPORT static_assert(4 <= EngineMidiEvent::kDataSize, "Incorrect data"); #endif uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) continue; if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0) continue; if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0) continue; if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) continue; // Fix bad note-off if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0) status = MIDI_STATUS_NOTE_OFF; NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]); carla_zeroStruct(nativeEvent); nativeEvent.port = midiEvent.port; nativeEvent.time = isSampleAccurate ? startTime : eventTime; nativeEvent.size = midiEvent.size; nativeEvent.data[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT)); nativeEvent.data[1] = midiEvent.size >= 2 ? midiEvent.data[1] : 0; nativeEvent.data[2] = midiEvent.size >= 3 ? midiEvent.data[2] : 0; nativeEvent.data[3] = midiEvent.size == 4 ? midiEvent.data[3] : 0; if (status == MIDI_STATUS_NOTE_ON) { pData->postponeRtEvent(kPluginPostRtEventNoteOn, true, event.channel, midiEvent.data[1], midiEvent.data[2], 0.0f); } else if (status == MIDI_STATUS_NOTE_OFF) { pData->postponeRtEvent(kPluginPostRtEventNoteOff, true, event.channel, midiEvent.data[1], 0, 0.0f); } } break; } // switch (event.type) } pData->postRtEvents.trySplice(); if (frames > timeOffset) processSingle(audioIn, audioOut, cvIn, cvOut, frames - timeOffset, timeOffset); } // End of Event Input and Processing // -------------------------------------------------------------------------------------------------------- // Plugin processing (no events) else { processSingle(audioIn, audioOut, cvIn, cvOut, frames, 0); } // End of Plugin processing (no events) #ifndef BUILD_BRIDGE // -------------------------------------------------------------------------------------------------------- // Control Output if (pData->event.portOut != nullptr) { float value, curValue; for (uint32_t k=0; k < pData->param.count; ++k) { if (pData->param.data[k].type != PARAMETER_OUTPUT) continue; curValue = fDescriptor->get_parameter_value(fHandle, k); pData->param.ranges[k].fixValue(curValue); if (pData->param.data[k].mappedControlIndex > 0) { value = pData->param.ranges[k].getNormalizedValue(curValue); pData->event.portOut->writeControlEvent(0, pData->param.data[k].midiChannel, kEngineControlEventTypeParameter, static_cast(pData->param.data[k].mappedControlIndex), value); } } } // End of Control Output #endif } bool processSingle(const float* const* const audioIn, float** const audioOut, const float* const* const cvIn, float** const cvOut, const uint32_t frames, const uint32_t timeOffset) { CARLA_SAFE_ASSERT_RETURN(frames > 0, false); if (pData->audioIn.count > 0) { CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false); } if (pData->audioOut.count > 0) { CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false); } if (pData->cvIn.count > 0) { CARLA_SAFE_ASSERT_RETURN(cvIn != nullptr, false); } if (pData->cvOut.count > 0) { CARLA_SAFE_ASSERT_RETURN(cvOut != nullptr, false); } // -------------------------------------------------------------------------------------------------------- // Try lock, silence otherwise if (fIsOffline) { pData->singleMutex.lock(); } else if (! pData->singleMutex.tryLock()) { for (uint32_t i=0; i < pData->audioOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) audioOut[i][k+timeOffset] = 0.0f; } for (uint32_t i=0; i < pData->cvOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) cvOut[i][k+timeOffset] = 0.0f; } return false; } // -------------------------------------------------------------------------------------------------------- // Set audio buffers { for (uint32_t i=0; i < pData->audioIn.count; ++i) carla_copyFloats(fAudioAndCvInBuffers[i], audioIn[i]+timeOffset, frames); for (uint32_t i=0; i < pData->cvIn.count; ++i) carla_copyFloats(fAudioAndCvInBuffers[pData->audioIn.count+i], cvIn[i]+timeOffset, frames); for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(fAudioAndCvOutBuffers[i], frames); for (uint32_t i=0; i < pData->cvOut.count; ++i) carla_zeroFloats(fAudioAndCvOutBuffers[pData->audioOut.count+i], frames); } // -------------------------------------------------------------------------------------------------------- // Run plugin fIsProcessing = true; if (fHandle2 == nullptr) { fDescriptor->process(fHandle, fAudioAndCvInBuffers, fAudioAndCvOutBuffers, frames, fMidiInEvents, fMidiEventInCount); } else { fDescriptor->process(fHandle, (fAudioAndCvInBuffers != nullptr) ? &fAudioAndCvInBuffers[0] : nullptr, (fAudioAndCvOutBuffers != nullptr) ? &fAudioAndCvOutBuffers[0] : nullptr, frames, fMidiInEvents, fMidiEventInCount); fDescriptor->process(fHandle2, (fAudioAndCvInBuffers != nullptr) ? &fAudioAndCvInBuffers[1] : nullptr, (fAudioAndCvOutBuffers != nullptr) ? &fAudioAndCvOutBuffers[1] : nullptr, frames, fMidiInEvents, fMidiEventInCount); } fIsProcessing = false; if (fTimeInfo.playing) fTimeInfo.frame += frames; uint32_t i=0; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // -------------------------------------------------------------------------------------------------------- // Post-processing (dry/wet, volume and balance) { const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f); const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f)); bool isPair; float bufValue, oldBufLeft[doBalance ? frames : 1]; for (; i < pData->audioOut.count; ++i) { // Dry/Wet if (doDryWet) { for (uint32_t k=0; k < frames; ++k) { bufValue = fAudioAndCvInBuffers[(pData->audioIn.count == 1) ? 0 : i][k]; fAudioAndCvOutBuffers[i][k] = (fAudioAndCvOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet)); } } // Balance if (doBalance) { isPair = (i % 2 == 0); if (isPair) { CARLA_ASSERT(i+1 < pData->audioOut.count); carla_copyFloats(oldBufLeft, fAudioAndCvOutBuffers[i], frames); } float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f; float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f; for (uint32_t k=0; k < frames; ++k) { if (isPair) { // left fAudioAndCvOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL); fAudioAndCvOutBuffers[i][k] += fAudioAndCvOutBuffers[i+1][k] * (1.0f - balRangeR); } else { // right fAudioAndCvOutBuffers[i][k] = fAudioAndCvOutBuffers[i][k] * balRangeR; fAudioAndCvOutBuffers[i][k] += oldBufLeft[k] * balRangeL; } } } // Volume (and buffer copy) { for (uint32_t k=0; k < frames; ++k) audioOut[i][k+timeOffset] = fAudioAndCvOutBuffers[i][k] * pData->postProc.volume; } } } // End of Post-processing #else for (; i < pData->audioOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) audioOut[i][k+timeOffset] = fAudioAndCvOutBuffers[i][k]; } #endif // CV stuff too for (; i < pData->cvOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) cvOut[i][k+timeOffset] = fAudioAndCvOutBuffers[pData->audioOut.count+i][k]; } // -------------------------------------------------------------------------------------------------------- // MIDI Output if (pData->event.portOut != nullptr) { for (uint32_t k = 0; k < fMidiEventOutCount; ++k) { const uint8_t channel = uint8_t(MIDI_GET_CHANNEL_FROM_DATA(fMidiOutEvents[k].data)); const uint8_t port = fMidiOutEvents[k].port; if (fMidiOut.count > 1 && port < fMidiOut.count) fMidiOut.ports[port]->writeMidiEvent(fMidiOutEvents[k].time+timeOffset, channel, fMidiOutEvents[k].size, fMidiOutEvents[k].data); else pData->event.portOut->writeMidiEvent(fMidiOutEvents[k].time+timeOffset, channel, fMidiOutEvents[k].size, fMidiOutEvents[k].data); } } // -------------------------------------------------------------------------------------------------------- pData->singleMutex.unlock(); return true; } void bufferSizeChanged(const uint32_t newBufferSize) override { CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize); carla_debug("CarlaPluginNative::bufferSizeChanged(%i)", newBufferSize); for (uint32_t i=0; i < (pData->audioIn.count+pData->cvIn.count); ++i) { if (fAudioAndCvInBuffers[i] != nullptr) delete[] fAudioAndCvInBuffers[i]; fAudioAndCvInBuffers[i] = new float[newBufferSize]; } for (uint32_t i=0; i < (pData->audioOut.count+pData->cvOut.count); ++i) { if (fAudioAndCvOutBuffers[i] != nullptr) delete[] fAudioAndCvOutBuffers[i]; fAudioAndCvOutBuffers[i] = new float[newBufferSize]; } if (fCurBufferSize == newBufferSize) return; fCurBufferSize = newBufferSize; if (fDescriptor != nullptr && fDescriptor->dispatcher != nullptr) { fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, static_cast(newBufferSize), nullptr, 0.0f); if (fHandle2 != nullptr) fDescriptor->dispatcher(fHandle2, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, static_cast(newBufferSize), nullptr, 0.0f); } } void sampleRateChanged(const double newSampleRate) override { CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate); carla_debug("CarlaPluginNative::sampleRateChanged(%g)", newSampleRate); if (carla_isEqual(fCurSampleRate, newSampleRate)) return; fCurSampleRate = newSampleRate; if (fDescriptor != nullptr && fDescriptor->dispatcher != nullptr) { fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, float(newSampleRate)); if (fHandle2 != nullptr) fDescriptor->dispatcher(fHandle2, NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, float(newSampleRate)); } } void offlineModeChanged(const bool isOffline) override { if (fIsOffline == isOffline) return; fIsOffline = isOffline; if (fDescriptor != nullptr && fDescriptor->dispatcher != nullptr) { fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_OFFLINE_CHANGED, 0, isOffline ? 1 : 0, nullptr, 0.0f); if (fHandle2 != nullptr) fDescriptor->dispatcher(fHandle2, NATIVE_PLUGIN_OPCODE_OFFLINE_CHANGED, 0, isOffline ? 1 : 0, nullptr, 0.0f); } } // ------------------------------------------------------------------- // Plugin buffers void initBuffers() const noexcept override { CarlaPlugin::initBuffers(); fMidiIn.initBuffers(pData->event.portIn); fMidiOut.initBuffers(); } void clearBuffers() noexcept override { carla_debug("CarlaPluginNative::clearBuffers() - start"); if (fAudioAndCvInBuffers != nullptr) { for (uint32_t i=0; i < (pData->audioIn.count+pData->cvIn.count); ++i) { if (fAudioAndCvInBuffers[i] != nullptr) { delete[] fAudioAndCvInBuffers[i]; fAudioAndCvInBuffers[i] = nullptr; } } delete[] fAudioAndCvInBuffers; fAudioAndCvInBuffers = nullptr; } if (fAudioAndCvOutBuffers != nullptr) { for (uint32_t i=0; i < (pData->audioOut.count+pData->cvOut.count); ++i) { if (fAudioAndCvOutBuffers[i] != nullptr) { delete[] fAudioAndCvOutBuffers[i]; fAudioAndCvOutBuffers[i] = nullptr; } } delete[] fAudioAndCvOutBuffers; fAudioAndCvOutBuffers = nullptr; } if (fMidiIn.count > 1) pData->event.portIn = nullptr; if (fMidiOut.count > 1) pData->event.portOut = nullptr; fMidiIn.clear(); fMidiOut.clear(); CarlaPlugin::clearBuffers(); carla_debug("CarlaPluginNative::clearBuffers() - end"); } // ------------------------------------------------------------------- // Post-poned UI Stuff void uiParameterChange(const uint32_t index, const float value) noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,); if (! fIsUiVisible) return; if (fDescriptor->ui_set_parameter_value != nullptr) fDescriptor->ui_set_parameter_value(fHandle, index, value); } void uiMidiProgramChange(const uint32_t index) noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,); if (! fIsUiVisible) return; if (index >= pData->midiprog.count) return; if (fDescriptor->ui_set_midi_program != nullptr) fDescriptor->ui_set_midi_program(fHandle, 0, pData->midiprog.data[index].bank, pData->midiprog.data[index].program); } void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,); if (! fIsUiVisible) return; // TODO } void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override { CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); if (! fIsUiVisible) return; if (fDescriptor == nullptr || fHandle == nullptr) return; // TODO } // ------------------------------------------------------------------- const NativeInlineDisplayImageSurface* renderInlineDisplay(const uint32_t width, const uint32_t height) { CARLA_SAFE_ASSERT_RETURN(fDescriptor->hints & NATIVE_PLUGIN_HAS_INLINE_DISPLAY, nullptr); CARLA_SAFE_ASSERT_RETURN(fDescriptor->render_inline_display, nullptr); CARLA_SAFE_ASSERT_RETURN(width > 0, nullptr); CARLA_SAFE_ASSERT_RETURN(height > 0, nullptr); return fDescriptor->render_inline_display(fHandle, width, height); } // ------------------------------------------------------------------- protected: const NativeTimeInfo* handleGetTimeInfo() const noexcept { CARLA_SAFE_ASSERT_RETURN(fIsProcessing, nullptr); return &fTimeInfo; } bool handleWriteMidiEvent(const NativeMidiEvent* const event) { CARLA_SAFE_ASSERT_RETURN(pData->enabled, false); CARLA_SAFE_ASSERT_RETURN(fIsProcessing, false); CARLA_SAFE_ASSERT_RETURN(fMidiOut.count > 0 || pData->event.portOut != nullptr, false); CARLA_SAFE_ASSERT_RETURN(event != nullptr, false); CARLA_SAFE_ASSERT_RETURN(event->data[0] != 0, false); if (fMidiEventOutCount == kPluginMaxMidiEvents) { carla_stdout("CarlaPluginNative::handleWriteMidiEvent(%p) - buffer full", event); return false; } std::memcpy(&fMidiOutEvents[fMidiEventOutCount++], event, sizeof(NativeMidiEvent)); return true; } void handleUiParameterChanged(const uint32_t index, const float value) { setParameterValue(index, value, false, true, true); } void handleUiCustomDataChanged(const char* const key, const char* const value) { setCustomData(CUSTOM_DATA_TYPE_STRING, key, value, false); } void handleUiClosed() { pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); fIsUiVisible = false; } const char* handleUiOpenFile(const bool isDir, const char* const title, const char* const filter) { return pData->engine->runFileCallback(FILE_CALLBACK_OPEN, isDir, title, filter); } const char* handleUiSaveFile(const bool isDir, const char* const title, const char* const filter) { return pData->engine->runFileCallback(FILE_CALLBACK_SAVE, isDir, title, filter); } intptr_t handleDispatcher(const NativeHostDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt) { carla_debug("CarlaPluginNative::handleDispatcher(%i, %i, " P_INTPTR ", %p, %f)", opcode, index, value, ptr, static_cast(opt)); intptr_t ret = 0; switch (opcode) { case NATIVE_HOST_OPCODE_NULL: break; case NATIVE_HOST_OPCODE_UPDATE_PARAMETER: // TODO pData->engine->callback(true, true, ENGINE_CALLBACK_UPDATE, pData->id, -1, 0, 0, 0.0f, nullptr); break; case NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM: // TODO pData->engine->callback(true, true, ENGINE_CALLBACK_UPDATE, pData->id, -1, 0, 0, 0.0f, nullptr); break; case NATIVE_HOST_OPCODE_RELOAD_PARAMETERS: reloadParameters(nullptr, nullptr); pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_ALL, pData->id, -1, 0, 0, 0.0f, nullptr); break; case NATIVE_HOST_OPCODE_RELOAD_MIDI_PROGRAMS: reloadPrograms(false); pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, -1, 0, 0, 0.0f, nullptr); break; case NATIVE_HOST_OPCODE_RELOAD_ALL: reload(); pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_ALL, pData->id, -1, 0, 0, 0.0f, nullptr); break; case NATIVE_HOST_OPCODE_UI_UNAVAILABLE: pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, -1, 0, 0, 0.0f, nullptr); fIsUiAvailable = false; break; case NATIVE_HOST_OPCODE_HOST_IDLE: pData->engine->callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); break; case NATIVE_HOST_OPCODE_INTERNAL_PLUGIN: ret = 1; break; case NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY: fInlineDisplayNeedsRedraw = true; break; case NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER: CARLA_SAFE_ASSERT_RETURN(index >= 0, 0); pData->engine->touchPluginParameter(pData->id, static_cast(index), value != 0); break; case NATIVE_HOST_OPCODE_REQUEST_IDLE: fNeedsIdle = true; break; case NATIVE_HOST_OPCODE_GET_FILE_PATH: CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0); { const EngineOptions& opts(pData->engine->getOptions()); const char* const filetype = (const char*)ptr; if (std::strcmp(filetype, "audio") == 0) return static_cast((uintptr_t)opts.pathAudio); if (std::strcmp(filetype, "midi") == 0) return static_cast((uintptr_t)opts.pathMIDI); } break; } return ret; // unused for now (void)opt; } // ------------------------------------------------------------------- public: void* getNativeHandle() const noexcept override { return fHandle; } const void* getNativeDescriptor() const noexcept override { return fDescriptor; } // ------------------------------------------------------------------- bool init(const char* const name, const char* const label, const uint options) { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); // --------------------------------------------------------------- // first checks if (pData->client != nullptr) { pData->engine->setLastError("Plugin client is already registered"); return false; } if (label == nullptr || label[0] == '\0') { pData->engine->setLastError("null label"); return false; } // --------------------------------------------------------------- // get descriptor that matches label sPluginInitializer.initIfNeeded(); for (LinkedList::Itenerator it = gPluginDescriptors.begin2(); it.valid(); it.next()) { fDescriptor = it.getValue(nullptr); CARLA_SAFE_ASSERT_BREAK(fDescriptor != nullptr); carla_debug("Check vs \"%s\"", fDescriptor->label); if (fDescriptor->label != nullptr && std::strcmp(fDescriptor->label, label) == 0) break; fDescriptor = nullptr; } if (fDescriptor == nullptr) { pData->engine->setLastError("Invalid internal plugin"); return false; } // --------------------------------------------------------------- // set icon /**/ if (std::strcmp(fDescriptor->label, "audiofile") == 0) pData->iconName = carla_strdup_safe("file"); else if (std::strcmp(fDescriptor->label, "midifile") == 0) pData->iconName = carla_strdup_safe("file"); else if (std::strcmp(fDescriptor->label, "3bandeq") == 0) pData->iconName = carla_strdup_safe("distrho"); else if (std::strcmp(fDescriptor->label, "3bandsplitter") == 0) pData->iconName = carla_strdup_safe("distrho"); else if (std::strcmp(fDescriptor->label, "kars") == 0) pData->iconName = carla_strdup_safe("distrho"); else if (std::strcmp(fDescriptor->label, "nekobi") == 0) pData->iconName = carla_strdup_safe("distrho"); else if (std::strcmp(fDescriptor->label, "pingpongpan") == 0) pData->iconName = carla_strdup_safe("distrho"); // --------------------------------------------------------------- // set info if (name != nullptr && name[0] != '\0') pData->name = pData->engine->getUniquePluginName(name); else if (fDescriptor->name != nullptr && fDescriptor->name[0] != '\0') pData->name = pData->engine->getUniquePluginName(fDescriptor->name); else pData->name = pData->engine->getUniquePluginName(label); { CARLA_ASSERT(fHost.uiName == nullptr); char uiName[std::strlen(pData->name)+6+1]; std::strcpy(uiName, pData->name); std::strcat(uiName, " (GUI)"); fHost.uiName = carla_strdup(uiName); } // --------------------------------------------------------------- // register client pData->client = pData->engine->addClient(this); if (pData->client == nullptr || ! pData->client->isOk()) { pData->engine->setLastError("Failed to register plugin client"); return false; } // --------------------------------------------------------------- // initialize plugin fHandle = fDescriptor->instantiate(&fHost); if (fHandle == nullptr) { pData->engine->setLastError("Plugin failed to initialize"); return false; } // --------------------------------------------------------------- // set options bool hasMidiProgs = false; if (fDescriptor->get_midi_program_count != nullptr) { try { hasMidiProgs = fDescriptor->get_midi_program_count(fHandle) > 0; } catch (...) {} } pData->options = 0x0; if (fDescriptor->hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS) pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; else if (options & PLUGIN_OPTION_FIXED_BUFFERS) pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; if (pData->engine->getOptions().forceStereo) pData->options |= PLUGIN_OPTION_FORCE_STEREO; else if (options & PLUGIN_OPTION_FORCE_STEREO) pData->options |= PLUGIN_OPTION_FORCE_STEREO; if (fDescriptor->supports & NATIVE_PLUGIN_SUPPORTS_CONTROL_CHANGES) if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; if (fDescriptor->supports & NATIVE_PLUGIN_SUPPORTS_CHANNEL_PRESSURE) if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)) pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; if (fDescriptor->supports & NATIVE_PLUGIN_SUPPORTS_NOTE_AFTERTOUCH) if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)) pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; if (fDescriptor->supports & NATIVE_PLUGIN_SUPPORTS_PITCHBEND) if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND)) pData->options |= PLUGIN_OPTION_SEND_PITCHBEND; if (fDescriptor->supports & NATIVE_PLUGIN_SUPPORTS_ALL_SOUND_OFF) if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF)) pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; if (fDescriptor->supports & NATIVE_PLUGIN_SUPPORTS_PROGRAM_CHANGES) { if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PROGRAM_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES; // makes no sense for a plugin to set program changes supported, but it has no midi programs CARLA_SAFE_ASSERT(! hasMidiProgs); } else if (hasMidiProgs) { if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES)) pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; } return true; } private: NativePluginHandle fHandle; NativePluginHandle fHandle2; NativeHostDescriptor fHost; const NativePluginDescriptor* fDescriptor; bool fIsProcessing; bool fIsOffline; bool fIsUiAvailable; bool fIsUiVisible; volatile bool fNeedsIdle; bool fInlineDisplayNeedsRedraw; int64_t fInlineDisplayLastRedrawTime; float** fAudioAndCvInBuffers; float** fAudioAndCvOutBuffers; uint32_t fMidiEventInCount; uint32_t fMidiEventOutCount; NativeMidiEvent fMidiInEvents[kPluginMaxMidiEvents]; NativeMidiEvent fMidiOutEvents[kPluginMaxMidiEvents]; int32_t fCurMidiProgs[MAX_MIDI_CHANNELS]; uint32_t fCurBufferSize; double fCurSampleRate; NativePluginMidiInData fMidiIn; NativePluginMidiOutData fMidiOut; NativeTimeInfo fTimeInfo; // ------------------------------------------------------------------- #define handlePtr ((CarlaPluginNative*)handle) static uint32_t carla_host_get_buffer_size(NativeHostHandle handle) noexcept { return handlePtr->fCurBufferSize; } static double carla_host_get_sample_rate(NativeHostHandle handle) noexcept { return handlePtr->fCurSampleRate; } static bool carla_host_is_offline(NativeHostHandle handle) noexcept { return handlePtr->fIsOffline; } static const NativeTimeInfo* carla_host_get_time_info(NativeHostHandle handle) noexcept { return handlePtr->handleGetTimeInfo(); } static bool carla_host_write_midi_event(NativeHostHandle handle, const NativeMidiEvent* event) { return handlePtr->handleWriteMidiEvent(event); } static void carla_host_ui_parameter_changed(NativeHostHandle handle, uint32_t index, float value) { handlePtr->handleUiParameterChanged(index, value); } static void carla_host_ui_custom_data_changed(NativeHostHandle handle, const char* key, const char* value) { handlePtr->handleUiCustomDataChanged(key, value); } static void carla_host_ui_closed(NativeHostHandle handle) { handlePtr->handleUiClosed(); } static const char* carla_host_ui_open_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter) { return handlePtr->handleUiOpenFile(isDir, title, filter); } static const char* carla_host_ui_save_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter) { return handlePtr->handleUiSaveFile(isDir, title, filter); } static intptr_t carla_host_dispatcher(NativeHostHandle handle, NativeHostDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt) { return handlePtr->handleDispatcher(opcode, index, value, ptr, opt); } #undef handlePtr CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginNative) }; // ----------------------------------------------------------------------- CarlaPlugin* CarlaPlugin::newNative(const Initializer& init) { carla_debug("CarlaPlugin::newNative({%p, \"%s\", \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.label, init.uniqueId); CarlaPluginNative* const plugin(new CarlaPluginNative(init.engine, init.id)); if (! plugin->init(init.name, init.label, init.options)) { delete plugin; return nullptr; } return plugin; } // used in CarlaStandalone.cpp const void* carla_render_inline_display_internal(CarlaPlugin* plugin, uint32_t width, uint32_t height); const void* carla_render_inline_display_internal(CarlaPlugin* plugin, uint32_t width, uint32_t height) { CarlaPluginNative* const nativePlugin = (CarlaPluginNative*)plugin; return nativePlugin->renderInlineDisplay(width, height); } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/plugin/CarlaPluginSFZero.cpp000066400000000000000000000656711364475620200226110ustar00rootroot00000000000000/* * Carla SFZero Plugin * Copyright (C) 2018-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaPluginInternal.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaEngine.hpp" #include "sfzero/SFZero.h" #include "water/buffers/AudioSampleBuffer.h" #include "water/files/File.h" #include "water/midi/MidiMessage.h" using water::AudioSampleBuffer; using water::File; using water::MidiMessage; using water::String; // ----------------------------------------------------------------------- CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- // Fallback data static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 }; static void loadingIdleCallbackFunction(void* ptr) { ((CarlaEngine*)ptr)->callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); } // ------------------------------------------------------------------------------------------------------------------- class CarlaPluginSFZero : public CarlaPlugin { public: CarlaPluginSFZero(CarlaEngine* const engine, const uint id) : CarlaPlugin(engine, id), fSynth(), fNumVoices(0.0f), fLabel(nullptr), fRealName(nullptr) { carla_debug("CarlaPluginSFZero::CarlaPluginSFZero(%p, %i)", engine, id); } ~CarlaPluginSFZero() override { carla_debug("CarlaPluginSFZero::~CarlaPluginSFZero()"); pData->singleMutex.lock(); pData->masterMutex.lock(); if (pData->client != nullptr && pData->client->isActive()) pData->client->deactivate(); if (pData->active) { deactivate(); pData->active = false; } if (fLabel != nullptr) { delete[] fLabel; fLabel = nullptr; } if (fRealName != nullptr) { delete[] fRealName; fRealName = nullptr; } clearBuffers(); } // ------------------------------------------------------------------- // Information (base) PluginType getType() const noexcept override { return PLUGIN_SFZ; } PluginCategory getCategory() const noexcept override { return PLUGIN_CATEGORY_SYNTH; } // ------------------------------------------------------------------- // Information (count) // nothing // ------------------------------------------------------------------- // Information (current data) // nothing // ------------------------------------------------------------------- // Information (per-plugin data) uint getOptionsAvailable() const noexcept override { uint options = 0x0; options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; options |= PLUGIN_OPTION_SEND_PITCHBEND; options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; return options; } float getParameterValue(const uint32_t parameterId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId == 0, 0.0f); return fNumVoices; } bool getLabel(char* const strBuf) const noexcept override { if (fLabel != nullptr) { std::strncpy(strBuf, fLabel, STR_MAX); return true; } return CarlaPlugin::getLabel(strBuf); } bool getMaker(char* const strBuf) const noexcept override { std::strncpy(strBuf, "SFZero engine", STR_MAX); return true; } bool getCopyright(char* const strBuf) const noexcept override { std::strncpy(strBuf, "ISC", STR_MAX); return true; } bool getRealName(char* const strBuf) const noexcept override { if (fRealName != nullptr) { std::strncpy(strBuf, fRealName, STR_MAX); return true; } return CarlaPlugin::getRealName(strBuf); } bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(parameterId == 0, false); std::strncpy(strBuf, "Voice Count", STR_MAX); return true; } // ------------------------------------------------------------------- // Set data (state) // nothing // ------------------------------------------------------------------- // Set data (internal stuff) // nothing // ------------------------------------------------------------------- // Set data (plugin-specific stuff) // nothing // ------------------------------------------------------------------- // Set ui stuff // nothing // ------------------------------------------------------------------- // Plugin state void reload() override { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,); carla_debug("CarlaPluginSFZero::reload() - start"); const EngineProcessMode processMode(pData->engine->getProccessMode()); // Safely disable plugin for reload const ScopedDisabler sd(this); if (pData->active) deactivate(); clearBuffers(); pData->audioOut.createNew(2); pData->param.createNew(1, false); const uint portNameSize(pData->engine->getMaxPortNameSize()); CarlaString portName; // --------------------------------------- // Audio Outputs // out-left portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "out-left"; portName.truncate(portNameSize); pData->audioOut.ports[0].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 0); pData->audioOut.ports[0].rindex = 0; // out-right portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "out-right"; portName.truncate(portNameSize); pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 1); pData->audioOut.ports[1].rindex = 1; // --------------------------------------- // Event Input portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-in"; portName.truncate(portNameSize); pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0); // --------------------------------------- // Parameters pData->param.data[0].type = PARAMETER_OUTPUT; pData->param.data[0].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE | PARAMETER_IS_INTEGER; pData->param.data[0].index = 0; pData->param.data[0].rindex = 0; pData->param.ranges[0].min = 0.0f; pData->param.ranges[0].max = 128; pData->param.ranges[0].def = 0.0f; pData->param.ranges[0].step = 1.0f; pData->param.ranges[0].stepSmall = 1.0f; pData->param.ranges[0].stepLarge = 1.0f; // --------------------------------------- // plugin hints pData->hints = 0x0; pData->hints |= PLUGIN_IS_SYNTH; pData->hints |= PLUGIN_CAN_VOLUME; pData->hints |= PLUGIN_CAN_BALANCE; // extra plugin hints pData->extraHints = 0x0; pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN; bufferSizeChanged(pData->engine->getBufferSize()); reloadPrograms(true); if (pData->active) activate(); carla_debug("CarlaPluginSFZero::reload() - end"); } // ------------------------------------------------------------------- // Plugin processing void process(const float* const* const, float** const audioOut, const float* const*, float**, const uint32_t frames) override { // -------------------------------------------------------------------------------------------------------- // Check if active if (! pData->active) { // disable any output sound for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(audioOut[i], frames); fNumVoices = 0.0f; return; } // -------------------------------------------------------------------------------------------------------- // Check if needs reset if (pData->needsReset) { fSynth.allNotesOff(0, false); pData->needsReset = false; } // -------------------------------------------------------------------------------------------------------- // Event Input and Processing { // ---------------------------------------------------------------------------------------------------- // Setup audio buffer AudioSampleBuffer audioOutBuffer(audioOut, 2, frames); // ---------------------------------------------------------------------------------------------------- // MIDI Input (External) if (pData->extNotes.mutex.tryLock()) { for (RtLinkedList::Itenerator it = pData->extNotes.data.begin2(); it.valid(); it.next()) { const ExternalMidiNote& note(it.getValue(kExternalMidiNoteFallback)); CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); if (note.velo > 0) fSynth.noteOn(note.channel+1, note.note, static_cast(note.velo)/127.0f); else fSynth.noteOff(note.channel+1, note.note, static_cast(note.velo)/127.0f, true); } pData->extNotes.data.clear(); pData->extNotes.mutex.unlock(); } // End of MIDI Input (External) // ---------------------------------------------------------------------------------------------------- // Event Input (System) #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH bool allNotesOffSent = false; #endif uint32_t timeOffset = 0; for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i) { const EngineEvent& event(pData->event.portIn->getEvent(i)); uint32_t eventTime = event.time; CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames); if (eventTime < timeOffset) { carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'", eventTime, timeOffset, pData->name); eventTime = timeOffset; } else if (eventTime > timeOffset) { if (processSingle(audioOutBuffer, eventTime - timeOffset, timeOffset)) timeOffset = eventTime; } // Control change switch (event.type) { case kEngineEventTypeNull: break; case kEngineEventTypeControl: { const EngineControlEvent& ctrlEvent = event.ctrl; switch (ctrlEvent.type) { case kEngineControlEventTypeNull: break; case kEngineControlEventTypeParameter: { float value; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // Control backend stuff if (event.channel == pData->ctrlChannel) { if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0) { value = ctrlEvent.value; setDryWetRT(value, true); } if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0) { value = ctrlEvent.value*127.0f/100.0f; setVolumeRT(value, true); } if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0) { float left, right; value = ctrlEvent.value/0.5f - 1.0f; if (value < 0.0f) { left = -1.0f; right = (value*2.0f)+1.0f; } else if (value > 0.0f) { left = (value*2.0f)-1.0f; right = 1.0f; } else { left = -1.0f; right = 1.0f; } setBalanceLeftRT(left, true); setBalanceRightRT(right, true); } } #endif // Control plugin parameters for (uint32_t k=0; k < pData->param.count; ++k) { if (pData->param.data[k].midiChannel != event.channel) continue; if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) continue; if (pData->param.data[k].hints != PARAMETER_INPUT) continue; if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) continue; value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.value); setParameterValueRT(k, value, true); } if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE) { fSynth.handleController(event.channel+1, ctrlEvent.param, int(ctrlEvent.value*127.0f)); } break; } case kEngineControlEventTypeMidiBank: case kEngineControlEventTypeMidiProgram: case kEngineControlEventTypeAllSoundOff: break; case kEngineControlEventTypeAllNotesOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (event.channel == pData->ctrlChannel && ! allNotesOffSent) { allNotesOffSent = true; postponeRtAllNotesOff(); } #endif fSynth.allNotesOff(event.channel+1, true); } break; } break; } case kEngineEventTypeMidi: { const EngineMidiEvent& midiEvent(event.midi); const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data); uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData)); if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) continue; if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0) continue; if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0) continue; if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) continue; // Fix bad note-off if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0) status = MIDI_STATUS_NOTE_OFF; // put back channel in data uint8_t midiData2[midiEvent.size]; midiData2[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT)); std::memcpy(midiData2+1, midiData+1, static_cast(midiEvent.size-1)); const MidiMessage midiMessage(midiData2, static_cast(midiEvent.size), 0.0); fSynth.handleMidiEvent(midiMessage); if (status == MIDI_STATUS_NOTE_ON) { pData->postponeRtEvent(kPluginPostRtEventNoteOn, true, event.channel, midiData[1], midiData[2], 0.0f); } else if (status == MIDI_STATUS_NOTE_OFF) { pData->postponeRtEvent(kPluginPostRtEventNoteOff, true, event.channel, midiData[1], 0, 0.0f); } } break; } } pData->postRtEvents.trySplice(); if (frames > timeOffset) processSingle(audioOutBuffer, frames - timeOffset, timeOffset); } // End of Event Input and Processing // -------------------------------------------------------------------------------------------------------- // Parameter outputs fNumVoices = static_cast(fSynth.numVoicesUsed()); } bool processSingle(AudioSampleBuffer& audioOutBuffer, const uint32_t frames, const uint32_t timeOffset) { CARLA_SAFE_ASSERT_RETURN(frames > 0, false); // -------------------------------------------------------------------------------------------------------- // Try lock, silence otherwise #ifndef STOAT_TEST_BUILD if (pData->engine->isOffline()) { pData->singleMutex.lock(); } else #endif if (! pData->singleMutex.tryLock()) { audioOutBuffer.clear(timeOffset, frames); return false; } // -------------------------------------------------------------------------------------------------------- // Run plugin fSynth.renderVoices(audioOutBuffer, static_cast(timeOffset), static_cast(frames)); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // -------------------------------------------------------------------------------------------------------- // Post-processing (dry/wet, volume and balance) { const bool doVolume = carla_isNotEqual(pData->postProc.volume, 1.0f); //const bool doBalance = carla_isNotEqual(pData->postProc.balanceLeft, -1.0f) || carla_isNotEqual(pData->postProc.balanceRight, 1.0f); float* outBufferL = audioOutBuffer.getWritePointer(0, timeOffset); float* outBufferR = audioOutBuffer.getWritePointer(1, timeOffset); #if 0 if (doBalance) { float oldBufLeft[frames]; // there was a loop here { if (i % 2 == 0) carla_copyFloats(oldBufLeft, outBuffer[i], frames); float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f; float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f; for (uint32_t k=0; k < frames; ++k) { if (i % 2 == 0) { // left outBuffer[i][k] = oldBufLeft[k] * (1.0f - balRangeL); outBuffer[i][k] += outBuffer[i+1][k] * (1.0f - balRangeR); } else { // right outBuffer[i][k] = outBuffer[i][k] * balRangeR; outBuffer[i][k] += oldBufLeft[k] * balRangeL; } } } } #endif if (doVolume) { const float volume = pData->postProc.volume; for (uint32_t k=0; k < frames; ++k) { *outBufferL++ *= volume; *outBufferR++ *= volume; } } } // End of Post-processing #endif // -------------------------------------------------------------------------------------------------------- pData->singleMutex.unlock(); return true; } void sampleRateChanged(const double newSampleRate) override { fSynth.setCurrentPlaybackSampleRate(newSampleRate); } // ------------------------------------------------------------------- // Plugin buffers // nothing // ------------------------------------------------------------------- bool init(const char* const filename, const char* const name, const char* const label, const uint options) { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); // --------------------------------------------------------------- // first checks if (pData->client != nullptr) { pData->engine->setLastError("Plugin client is already registered"); return false; } if (filename == nullptr || filename[0] == '\0') { pData->engine->setLastError("null filename"); return false; } for (int i = 128; --i >=0;) fSynth.addVoice(new sfzero::Voice()); // --------------------------------------------------------------- // Init SFZero stuff fSynth.setCurrentPlaybackSampleRate(pData->engine->getSampleRate()); File file(filename); sfzero::Sound* const sound = new sfzero::Sound(file); sfzero::Sound::LoadingIdleCallback cb = { loadingIdleCallbackFunction, pData->engine, }; sound->loadRegions(); sound->loadSamples(cb); if (fSynth.addSound(sound) == nullptr) { pData->engine->setLastError("Failed to allocate SFZ sounds in memory"); return false; } sound->dumpToConsole(); // --------------------------------------------------------------- const String basename(File(filename).getFileNameWithoutExtension()); CarlaString label2(label != nullptr ? label : basename.toRawUTF8()); fLabel = label2.dup(); fRealName = carla_strdup(basename.toRawUTF8()); pData->filename = carla_strdup(filename); if (name != nullptr && name[0] != '\0') pData->name = pData->engine->getUniquePluginName(name); else if (fRealName[0] != '\0') pData->name = pData->engine->getUniquePluginName(fRealName); else pData->name = pData->engine->getUniquePluginName(fLabel); // --------------------------------------------------------------- // register client pData->client = pData->engine->addClient(this); if (pData->client == nullptr || ! pData->client->isOk()) { pData->engine->setLastError("Failed to register plugin client"); return false; } // --------------------------------------------------------------- // set options pData->options = 0x0; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)) pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)) pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND)) pData->options |= PLUGIN_OPTION_SEND_PITCHBEND; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF)) pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; return true; } // ------------------------------------------------------------------- private: sfzero::Synth fSynth; float fNumVoices; const char* fLabel; const char* fRealName; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginSFZero) }; // ------------------------------------------------------------------------------------------------------------------- CarlaPlugin* CarlaPlugin::newSFZero(const Initializer& init) { carla_debug("CarlaPluginSFZero::newSFZero({%p, \"%s\", \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.label, init.uniqueId); // ------------------------------------------------------------------- // Check if file exists if (! File(init.filename).existsAsFile()) { init.engine->setLastError("Requested file is not valid or does not exist"); return nullptr; } CarlaPluginSFZero* const plugin(new CarlaPluginSFZero(init.engine, init.id)); if (! plugin->init(init.filename, init.name, init.label, init.options)) { delete plugin; return nullptr; } return plugin; } // ------------------------------------------------------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/plugin/CarlaPluginVST2.cpp000066400000000000000000003027321364475620200221670ustar00rootroot00000000000000/* * Carla VST Plugin * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaPluginInternal.hpp" #include "CarlaEngine.hpp" #if defined(USING_JUCE) && (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) # define USE_JUCE_FOR_VST2 #endif #include "CarlaBackendUtils.hpp" #include "CarlaMathUtils.hpp" #include "CarlaScopeUtils.hpp" #include "CarlaVstUtils.hpp" #include "CarlaPluginUI.hpp" #ifdef CARLA_OS_MAC # import #endif #include #include "water/memory/ByteOrder.h" #undef VST_FORCE_DEPRECATED #define VST_FORCE_DEPRECATED 0 #undef kEffectMagic #define kEffectMagic (CCONST( 'V', 's', 't', 'P' )) using water::ByteOrder; CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------- const uint PLUGIN_CAN_PROCESS_REPLACING = 0x1000; const uint PLUGIN_HAS_COCKOS_EXTENSIONS = 0x2000; const uint PLUGIN_USES_OLD_VSTSDK = 0x4000; const uint PLUGIN_WANTS_MIDI_INPUT = 0x8000; static const int32_t kVstMidiEventSize = static_cast(sizeof(VstMidiEvent)); #ifdef PTW32_DLLPORT static const pthread_t kNullThread = {nullptr, 0}; #else static const pthread_t kNullThread = 0; #endif // ----------------------------------------------------- class CarlaPluginVST2 : public CarlaPlugin, private CarlaPluginUI::Callback { public: CarlaPluginVST2(CarlaEngine* const engine, const uint id) : CarlaPlugin(engine, id), fUnique1(1), fEffect(nullptr), fMidiEventCount(0), fTimeInfo(), fNeedIdle(false), fLastChunk(nullptr), fIsInitializing(true), fIsProcessing(false), fChangingValuesThread(kNullThread), fIdleThread(kNullThread), fMainThread(pthread_self()), fProcThread(kNullThread), #ifdef CARLA_OS_MAC fMacBundleRef(nullptr), fMacBundleRefNum(0), #endif fFirstActive(true), fBufferSize(engine->getBufferSize()), fAudioOutBuffers(nullptr), fLastTimeInfo(), fEvents(), fUI(), fUnique2(2) { carla_debug("CarlaPluginVST2::CarlaPluginVST2(%p, %i)", engine, id); carla_zeroStructs(fMidiEvents, kPluginMaxMidiEvents*2); carla_zeroStruct(fTimeInfo); for (ushort i=0; i < kPluginMaxMidiEvents*2; ++i) fEvents.data[i] = (VstEvent*)&fMidiEvents[i]; // make plugin valid srand(id); fUnique1 = fUnique2 = rand(); } ~CarlaPluginVST2() override { carla_debug("CarlaPluginVST2::~CarlaPluginVST2()"); // close UI if (pData->hints & PLUGIN_HAS_CUSTOM_UI) { showCustomUI(false); if (fUI.isOpen) { fUI.isOpen = false; dispatcher(effEditClose); } } pData->singleMutex.lock(); pData->masterMutex.lock(); if (pData->client != nullptr && pData->client->isActive()) pData->client->deactivate(); CARLA_ASSERT(! fIsProcessing); if (pData->active) { deactivate(); pData->active = false; } if (fEffect != nullptr) { dispatcher(effClose); fEffect = nullptr; } // make plugin invalid fUnique2 += 1; if (fLastChunk != nullptr) { std::free(fLastChunk); fLastChunk = nullptr; } clearBuffers(); #ifdef CARLA_OS_MAC if (fMacBundleRef != nullptr) { CFBundleCloseBundleResourceMap(fMacBundleRef, fMacBundleRefNum); if (CFGetRetainCount(fMacBundleRef) == 1) CFBundleUnloadExecutable(fMacBundleRef); if (CFGetRetainCount(fMacBundleRef) > 0) CFRelease(fMacBundleRef); fMacBundleRef = nullptr; } #endif } // ------------------------------------------------------------------- // Information (base) PluginType getType() const noexcept override { return PLUGIN_VST2; } PluginCategory getCategory() const noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, CarlaPlugin::getCategory()); const intptr_t category = dispatcher(effGetPlugCategory); switch (category) { case kPlugCategSynth: return PLUGIN_CATEGORY_SYNTH; case kPlugCategAnalysis: return PLUGIN_CATEGORY_UTILITY; case kPlugCategMastering: return PLUGIN_CATEGORY_DYNAMICS; case kPlugCategRoomFx: return PLUGIN_CATEGORY_DELAY; case kPlugCategRestoration: return PLUGIN_CATEGORY_UTILITY; case kPlugCategGenerator: return PLUGIN_CATEGORY_SYNTH; } if (fEffect->flags & effFlagsIsSynth) return PLUGIN_CATEGORY_SYNTH; return CarlaPlugin::getCategory(); } int64_t getUniqueId() const noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, 0); return static_cast(fEffect->uniqueID); } // ------------------------------------------------------------------- // Information (count) // nothing // ------------------------------------------------------------------- // Information (current data) std::size_t getChunkData(void** const dataPtr) noexcept override { CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0); CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0); *dataPtr = nullptr; try { const intptr_t ret = dispatcher(effGetChunk, 0 /* bank */, 0, dataPtr); CARLA_SAFE_ASSERT_RETURN(ret >= 0, 0); return static_cast(ret); } CARLA_SAFE_EXCEPTION_RETURN("CarlaPluginVST2::getChunkData", 0); } // ------------------------------------------------------------------- // Information (per-plugin data) uint getOptionsAvailable() const noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, 0); uint options = 0x0; // can't disable fixed buffers if using latency or MIDI output if (pData->latency.frames == 0 && ! hasMidiOutput()) options |= PLUGIN_OPTION_FIXED_BUFFERS; if (fEffect->numPrograms > 1) options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; if (fEffect->flags & effFlagsProgramChunks) options |= PLUGIN_OPTION_USE_CHUNKS; if (hasMidiInput()) { options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; options |= PLUGIN_OPTION_SEND_PITCHBEND; options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES; } return options; } float getParameterValue(const uint32_t parameterId) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, 0.0f); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f); return fEffect->getParameter(fEffect, static_cast(parameterId)); } bool getLabel(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, false); strBuf[0] = '\0'; dispatcher(effGetProductString, 0, 0, strBuf); return true; } bool getMaker(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, false); strBuf[0] = '\0'; dispatcher(effGetVendorString, 0, 0, strBuf); return true; } bool getCopyright(char* const strBuf) const noexcept override { return getMaker(strBuf); } bool getRealName(char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, false); strBuf[0] = '\0'; dispatcher(effGetEffectName, 0, 0, strBuf); return true; } bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); strBuf[0] = '\0'; VstParameterProperties prop; carla_zeroStruct(prop); if (dispatcher(effGetParameterProperties, static_cast(parameterId), 0, &prop) == 1 && prop.label[0] != '\0') { std::strncpy(strBuf, prop.label, 64); strBuf[64] = '\0'; return true; } strBuf[0] = '\0'; dispatcher(effGetParamName, static_cast(parameterId), 0, strBuf); return true; } bool getParameterText(const uint32_t parameterId, char* const strBuf) noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); strBuf[0] = '\0'; dispatcher(effGetParamDisplay, static_cast(parameterId), 0, strBuf); if (strBuf[0] == '\0') std::snprintf(strBuf, STR_MAX, "%.12g", static_cast(getParameterValue(parameterId))); return true; } bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, false); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); strBuf[0] = '\0'; dispatcher(effGetParamLabel, static_cast(parameterId), 0, strBuf); return true; } // ------------------------------------------------------------------- // Set data (state) // nothing // ------------------------------------------------------------------- // Set data (internal stuff) void setName(const char* const newName) override { CarlaPlugin::setName(newName); if (fUI.window != nullptr) { CarlaString guiTitle(pData->name); guiTitle += " (GUI)"; fUI.window->setTitle(guiTitle.buffer()); } } // ------------------------------------------------------------------- // Set data (plugin-specific stuff) void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); const float fixedValue(pData->param.getFixedValue(parameterId, value)); fEffect->setParameter(fEffect, static_cast(parameterId), fixedValue); CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback); } void setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,); CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); const float fixedValue(pData->param.getFixedValue(parameterId, value)); fEffect->setParameter(fEffect, static_cast(parameterId), fixedValue); CarlaPlugin::setParameterValueRT(parameterId, fixedValue, sendCallbackLater); } void setChunkData(const void* const data, const std::size_t dataSize) override { CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,); CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,); CARLA_SAFE_ASSERT_RETURN(data != nullptr,); CARLA_SAFE_ASSERT_RETURN(dataSize > 0,); if (loadJuceSaveFormat(data, dataSize)) return; if (fLastChunk != nullptr) std::free(fLastChunk); fLastChunk = std::malloc(dataSize); CARLA_SAFE_ASSERT_RETURN(fLastChunk != nullptr,); std::memcpy(fLastChunk, data, dataSize); { const ScopedSingleProcessLocker spl(this, true); const CarlaScopedValueSetter svs(fChangingValuesThread, pthread_self(), kNullThread); dispatcher(effSetChunk, 0 /* bank */, static_cast(dataSize), fLastChunk); } // simulate an updateDisplay callback handleAudioMasterCallback(audioMasterUpdateDisplay, 0, 0, nullptr, 0.0f); pData->updateParameterValues(this, true, true, false); } void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,); CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->prog.count),); CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,); if (index >= 0) { try { dispatcher(effBeginSetProgram); } CARLA_SAFE_EXCEPTION_RETURN("effBeginSetProgram",); { const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); const CarlaScopedValueSetter svs(fChangingValuesThread, pthread_self(), kNullThread); try { dispatcher(effSetProgram, 0, index); } CARLA_SAFE_EXCEPTION("effSetProgram"); } try { dispatcher(effEndSetProgram); } CARLA_SAFE_EXCEPTION("effEndSetProgram"); } CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback, doingInit); } void setProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,); CARLA_SAFE_ASSERT_RETURN(uindex < pData->prog.count,); try { dispatcher(effBeginSetProgram); } CARLA_SAFE_EXCEPTION_RETURN("effBeginSetProgram",); try { dispatcher(effSetProgram, 0, static_cast(uindex)); } CARLA_SAFE_EXCEPTION("effSetProgram"); try { dispatcher(effEndSetProgram); } CARLA_SAFE_EXCEPTION("effEndSetProgram"); CarlaPlugin::setProgramRT(uindex, sendCallbackLater); } // ------------------------------------------------------------------- // Set ui stuff void showCustomUI(const bool yesNo) override { if (fUI.isVisible == yesNo) return; if (yesNo) { CarlaString uiTitle(pData->name); uiTitle += " (GUI)"; intptr_t value = 0; if (fUI.window == nullptr) { const char* msg = nullptr; const uintptr_t frontendWinId(pData->engine->getOptions().frontendWinId); #if defined(CARLA_OS_MAC) fUI.window = CarlaPluginUI::newCocoa(this, frontendWinId, false); #elif defined(CARLA_OS_WIN) fUI.window = CarlaPluginUI::newWindows(this, frontendWinId, false); #elif defined(HAVE_X11) fUI.window = CarlaPluginUI::newX11(this, frontendWinId, false); #else msg = "Unsupported UI type"; // unused (void)frontendWinId; #endif if (fUI.window == nullptr) return pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, -1, 0, 0, 0.0f, msg); fUI.window->setTitle(uiTitle.buffer()); #ifdef HAVE_X11 value = (intptr_t)fUI.window->getDisplay(); #endif // NOTE: there are far too many broken VST2 plugins, don't bother checking return value if (dispatcher(effEditOpen, 0, value, fUI.window->getPtr()) != 0 || true) { fUI.isOpen = true; ERect* vstRect = nullptr; dispatcher(effEditGetRect, 0, 0, &vstRect); if (vstRect != nullptr) { const int width(vstRect->right - vstRect->left); const int height(vstRect->bottom - vstRect->top); CARLA_SAFE_ASSERT_INT2(width > 1 && height > 1, width, height); if (width > 1 && height > 1) fUI.window->setSize(static_cast(width), static_cast(height), true); } } else { delete fUI.window; fUI.window = nullptr; carla_stderr2("Plugin refused to open its own UI"); return pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, -1, 0, 0, 0.0f, "Plugin refused to open its own UI"); } } fUI.window->show(); fUI.isVisible = true; } else { fUI.isVisible = false; CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,); fUI.window->hide(); } } void idle() override { if (fNeedIdle) { const CarlaScopedValueSetter svs(fIdleThread, pthread_self(), kNullThread); dispatcher(effIdle); } CarlaPlugin::idle(); } void uiIdle() override { if (fUI.window != nullptr) { fUI.window->idle(); if (fUI.isVisible) dispatcher(effEditIdle); } CarlaPlugin::uiIdle(); } // ------------------------------------------------------------------- // Plugin state void reload() override { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,); CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,); carla_debug("CarlaPluginVST2::reload() - start"); const EngineProcessMode processMode(pData->engine->getProccessMode()); // Safely disable plugin for reload const ScopedDisabler sd(this); const CarlaScopedValueSetter svs(fIsInitializing, fIsInitializing, false); if (pData->active) deactivate(); clearBuffers(); uint32_t aIns, aOuts, mIns, mOuts, params; bool needsCtrlIn, needsCtrlOut; needsCtrlIn = needsCtrlOut = false; aIns = (fEffect->numInputs > 0) ? static_cast(fEffect->numInputs) : 0; aOuts = (fEffect->numOutputs > 0) ? static_cast(fEffect->numOutputs) : 0; params = (fEffect->numParams > 0) ? static_cast(fEffect->numParams) : 0; if (hasMidiInput()) { mIns = 1; needsCtrlIn = true; } else mIns = 0; if (hasMidiOutput()) { mOuts = 1; needsCtrlOut = true; } else mOuts = 0; if (aIns > 0) { pData->audioIn.createNew(aIns); } if (aOuts > 0) { pData->audioOut.createNew(aOuts); fAudioOutBuffers = new float*[aOuts]; needsCtrlIn = true; for (uint32_t i=0; i < aOuts; ++i) fAudioOutBuffers[i] = nullptr; } if (params > 0) { pData->param.createNew(params, false); needsCtrlIn = true; } const uint portNameSize(pData->engine->getMaxPortNameSize()); CarlaString portName; // Audio Ins for (uint32_t j=0; j < aIns; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (aIns > 1) { portName += "input_"; portName += CarlaString(j+1); } else portName += "input"; portName.truncate(portNameSize); pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j); pData->audioIn.ports[j].rindex = j; } // Audio Outs for (uint32_t j=0; j < aOuts; ++j) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } if (aOuts > 1) { portName += "output_"; portName += CarlaString(j+1); } else portName += "output"; portName.truncate(portNameSize); pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j); pData->audioOut.ports[j].rindex = j; } for (uint32_t j=0; j < params; ++j) { const int32_t ij = static_cast(j); pData->param.data[j].type = PARAMETER_INPUT; pData->param.data[j].index = ij; pData->param.data[j].rindex = ij; float min, max, def, step, stepSmall, stepLarge; VstParameterProperties prop; carla_zeroStruct(prop); if (pData->hints & PLUGIN_HAS_COCKOS_EXTENSIONS) { double vrange[2] = { 0.0, 1.0 }; bool isInteger = false; if (static_cast(dispatcher(effVendorSpecific, static_cast(0xdeadbef0), ij, vrange)) >= 0xbeef) { min = static_cast(vrange[0]); max = static_cast(vrange[1]); if (min > max) { carla_stderr2("WARNING - Broken plugin parameter min > max (with cockos extensions)"); min = max - 0.1f; } else if (carla_isEqual(min, max)) { carla_stderr2("WARNING - Broken plugin parameter min == max (with cockos extensions)"); max = min + 0.1f; } // only use values as integer if we have a proper range if (max - min >= 1.0f) isInteger = dispatcher(effVendorSpecific, kVstParameterUsesIntStep, ij) >= 0xbeef; } else { min = 0.0f; max = 1.0f; } if (isInteger) { step = 1.0f; stepSmall = 1.0f; stepLarge = 10.0f; } else { const float range = max - min; step = range/100.0f; stepSmall = range/1000.0f; stepLarge = range/10.0f; } } else if (dispatcher(effGetParameterProperties, ij, 0, &prop) == 1) { #if 0 if (prop.flags & kVstParameterUsesIntegerMinMax) { min = static_cast(prop.minInteger); max = static_cast(prop.maxInteger); if (min > max) { carla_stderr2("WARNING - Broken plugin parameter min > max"); min = max - 0.1f; } else if (carla_isEqual(min, max)) { carla_stderr2("WARNING - Broken plugin parameter min == max"); max = min + 0.1f; } } else #endif { min = 0.0f; max = 1.0f; } if (prop.flags & kVstParameterIsSwitch) { step = max - min; stepSmall = step; stepLarge = step; pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN; } else if (prop.flags & kVstParameterUsesIntStep) { step = static_cast(prop.stepInteger); stepSmall = static_cast(prop.stepInteger)/10.0f; stepLarge = static_cast(prop.largeStepInteger); pData->param.data[j].hints |= PARAMETER_IS_INTEGER; } else if (prop.flags & kVstParameterUsesFloatStep) { step = prop.stepFloat; stepSmall = prop.smallStepFloat; stepLarge = prop.largeStepFloat; } else { const float range = max - min; step = range/100.0f; stepSmall = range/1000.0f; stepLarge = range/10.0f; } if (prop.flags & kVstParameterCanRamp) pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC; } else { min = 0.0f; max = 1.0f; step = 0.001f; stepSmall = 0.0001f; stepLarge = 0.1f; } pData->param.data[j].hints |= PARAMETER_IS_ENABLED; pData->param.data[j].hints |= PARAMETER_USES_CUSTOM_TEXT; if ((pData->hints & PLUGIN_USES_OLD_VSTSDK) != 0 || dispatcher(effCanBeAutomated, ij) == 1) { pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE; if ((prop.flags & (kVstParameterIsSwitch|kVstParameterUsesIntStep)) == 0x0) pData->param.data[j].hints |= PARAMETER_CAN_BE_CV_CONTROLLED; } // no such thing as VST default parameters def = fEffect->getParameter(fEffect, ij); if (def < min) def = min; else if (def > max) def = max; pData->param.ranges[j].min = min; pData->param.ranges[j].max = max; pData->param.ranges[j].def = def; pData->param.ranges[j].step = step; pData->param.ranges[j].stepSmall = stepSmall; pData->param.ranges[j].stepLarge = stepLarge; } if (needsCtrlIn) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-in"; portName.truncate(portNameSize); pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->event.cvSourcePorts = pData->client->createCVSourcePorts(); #endif } if (needsCtrlOut) { portName.clear(); if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) { portName = pData->name; portName += ":"; } portName += "events-out"; portName.truncate(portNameSize); pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0); } // plugin hints const intptr_t vstCategory = dispatcher(effGetPlugCategory); pData->hints = 0x0; if (vstCategory == kPlugCategSynth || vstCategory == kPlugCategGenerator) pData->hints |= PLUGIN_IS_SYNTH; if (fEffect->flags & effFlagsHasEditor) { #if defined(CARLA_OS_MAC) && ! defined(CARLA_OS_64BIT) if (static_cast(dispatcher(effCanDo, 0, 0, const_cast("hasCockosViewAsConfig")) & 0xffff0000) == 0xbeef0000) #endif { pData->hints |= PLUGIN_HAS_CUSTOM_UI; } pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD; } if (dispatcher(effGetVstVersion) < kVstVersion) pData->hints |= PLUGIN_USES_OLD_VSTSDK; if ((fEffect->flags & effFlagsCanReplacing) != 0 && fEffect->processReplacing != fEffect->process) pData->hints |= PLUGIN_CAN_PROCESS_REPLACING; if (static_cast(dispatcher(effCanDo, 0, 0, const_cast("hasCockosExtensions"))) == 0xbeef0000) pData->hints |= PLUGIN_HAS_COCKOS_EXTENSIONS; if (aOuts > 0 && (aIns == aOuts || aIns == 1)) pData->hints |= PLUGIN_CAN_DRYWET; if (aOuts > 0) pData->hints |= PLUGIN_CAN_VOLUME; if (aOuts >= 2 && aOuts % 2 == 0) pData->hints |= PLUGIN_CAN_BALANCE; // extra plugin hints pData->extraHints = 0x0; if (mIns > 0) pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN; if (mOuts > 0) pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT; // dummy pre-start to get latency and wantEvents() on old plugins { activate(); deactivate(); } // check initial latency const uint32_t latency = (fEffect->initialDelay > 0) ? static_cast(fEffect->initialDelay) : 0; if (latency != 0) { pData->client->setLatency(latency); #ifndef BUILD_BRIDGE pData->latency.recreateBuffers(std::max(aIns, aOuts), latency); #endif } bufferSizeChanged(pData->engine->getBufferSize()); reloadPrograms(true); if (pData->active) activate(); carla_debug("CarlaPluginVST2::reload() - end"); } void reloadPrograms(const bool doInit) override { carla_debug("CarlaPluginVST2::reloadPrograms(%s)", bool2str(doInit)); const uint32_t oldCount = pData->prog.count; const int32_t current = pData->prog.current; // Delete old programs pData->prog.clear(); // Query new programs uint32_t newCount = (fEffect->numPrograms > 0) ? static_cast(fEffect->numPrograms) : 0; if (newCount > 0) { pData->prog.createNew(newCount); // Update names for (int32_t i=0; i < fEffect->numPrograms; ++i) { char strBuf[STR_MAX+1] = { '\0' }; if (dispatcher(effGetProgramNameIndexed, i, 0, strBuf) != 1) { // program will be [re-]changed later dispatcher(effSetProgram, 0, i); dispatcher(effGetProgramName, 0, 0, strBuf); } pData->prog.names[i] = carla_strdup(strBuf); } } if (doInit) { if (newCount > 0) setProgram(0, false, false, false, true); else dispatcher(effSetProgram, 0, 0); } else { // Check if current program is invalid bool programChanged = false; if (newCount == oldCount+1) { // one program added, probably created by user pData->prog.current = static_cast(oldCount); programChanged = true; } else if (current < 0 && newCount > 0) { // programs exist now, but not before pData->prog.current = 0; programChanged = true; } else if (current >= 0 && newCount == 0) { // programs existed before, but not anymore pData->prog.current = -1; programChanged = true; } else if (current >= static_cast(newCount)) { // current program > count pData->prog.current = 0; programChanged = true; } else { // no change pData->prog.current = current; } if (programChanged) { setProgram(pData->prog.current, true, true, true, false); } else { // Program was changed during update, re-set it if (pData->prog.current >= 0) dispatcher(effSetProgram, 0, pData->prog.current); } pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0f, nullptr); } } // ------------------------------------------------------------------- // Plugin processing void activate() noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,); const int32_t iBufferSize = static_cast(fBufferSize); const float fSampleRate = static_cast(pData->engine->getSampleRate()); dispatcher(effSetProcessPrecision, 0, kVstProcessPrecision32); dispatcher(effSetBlockSizeAndSampleRate, 0, iBufferSize, nullptr, fSampleRate); dispatcher(effSetSampleRate, 0, 0, nullptr, fSampleRate); dispatcher(effSetBlockSize, 0, iBufferSize); try { dispatcher(effMainsChanged, 0, 1); } catch(...) {} try { dispatcher(effStartProcess, 0, 0); } catch(...) {} fFirstActive = true; } void deactivate() noexcept override { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,); try { dispatcher(effStopProcess); } catch(...) {} try { dispatcher(effMainsChanged); } catch(...) {} } void process(const float* const* const audioIn, float** const audioOut, const float* const* const cvIn, float** const, const uint32_t frames) override { const CarlaScopedValueSetter svs(fProcThread, pthread_self(), kNullThread); // -------------------------------------------------------------------------------------------------------- // Check if active if (! pData->active) { // disable any output sound for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(audioOut[i], frames); return; } fMidiEventCount = 0; carla_zeroStructs(fMidiEvents, kPluginMaxMidiEvents*2); // -------------------------------------------------------------------------------------------------------- // Check if needs reset if (pData->needsReset) { if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { fMidiEventCount = MAX_MIDI_CHANNELS*2; for (uint8_t i=0, k=MAX_MIDI_CHANNELS; i < MAX_MIDI_CHANNELS; ++i) { fMidiEvents[k].type = kVstMidiType; fMidiEvents[k].byteSize = kVstMidiEventSize; fMidiEvents[k].midiData[0] = char(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT)); fMidiEvents[k].midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; fMidiEvents[k+i].type = kVstMidiType; fMidiEvents[k+i].byteSize = kVstMidiEventSize; fMidiEvents[k+i].midiData[0] = char(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT)); fMidiEvents[k+i].midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; } } else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) { fMidiEventCount = MAX_MIDI_NOTE; for (uint8_t i=0; i < MAX_MIDI_NOTE; ++i) { fMidiEvents[i].type = kVstMidiType; fMidiEvents[i].byteSize = kVstMidiEventSize; fMidiEvents[i].midiData[0] = char(MIDI_STATUS_NOTE_OFF | (pData->ctrlChannel & MIDI_CHANNEL_BIT)); fMidiEvents[i].midiData[1] = char(i); } } pData->needsReset = false; } // -------------------------------------------------------------------------------------------------------- // Set TimeInfo const EngineTimeInfo timeInfo(pData->engine->getTimeInfo()); fTimeInfo.flags = 0; if (fFirstActive || ! fLastTimeInfo.compareIgnoringRollingFrames(timeInfo, fBufferSize)) { fTimeInfo.flags |= kVstTransportChanged; fLastTimeInfo = timeInfo; } if (timeInfo.playing) fTimeInfo.flags |= kVstTransportPlaying; fTimeInfo.samplePos = double(timeInfo.frame); fTimeInfo.sampleRate = pData->engine->getSampleRate(); if (timeInfo.usecs != 0) { fTimeInfo.nanoSeconds = double(timeInfo.usecs)/1000.0; fTimeInfo.flags |= kVstNanosValid; } if (timeInfo.bbt.valid) { CARLA_SAFE_ASSERT_INT(timeInfo.bbt.bar > 0, timeInfo.bbt.bar); CARLA_SAFE_ASSERT_INT(timeInfo.bbt.beat > 0, timeInfo.bbt.beat); const double ppqBar = static_cast(timeInfo.bbt.beatsPerBar) * (timeInfo.bbt.bar - 1); // const double ppqBeat = static_cast(timeInfo.bbt.beat - 1); // const double ppqTick = timeInfo.bbt.tick / timeInfo.bbt.ticksPerBeat; // PPQ Pos fTimeInfo.ppqPos = fTimeInfo.samplePos / (fTimeInfo.sampleRate * 60 / fTimeInfo.tempo); // fTimeInfo.ppqPos = ppqBar + ppqBeat + ppqTick; fTimeInfo.flags |= kVstPpqPosValid; // Tempo fTimeInfo.tempo = timeInfo.bbt.beatsPerMinute; fTimeInfo.flags |= kVstTempoValid; // Bars fTimeInfo.barStartPos = ppqBar; fTimeInfo.flags |= kVstBarsValid; // Time Signature fTimeInfo.timeSigNumerator = static_cast(timeInfo.bbt.beatsPerBar); fTimeInfo.timeSigDenominator = static_cast(timeInfo.bbt.beatType); fTimeInfo.flags |= kVstTimeSigValid; } else { // Tempo fTimeInfo.tempo = 120.0; fTimeInfo.flags |= kVstTempoValid; // Time Signature fTimeInfo.timeSigNumerator = 4; fTimeInfo.timeSigDenominator = 4; fTimeInfo.flags |= kVstTimeSigValid; // Missing info fTimeInfo.ppqPos = 0.0; fTimeInfo.barStartPos = 0.0; } // -------------------------------------------------------------------------------------------------------- // Event Input and Processing if (pData->event.portIn != nullptr) { // ---------------------------------------------------------------------------------------------------- // MIDI Input (External) if (pData->extNotes.mutex.tryLock()) { ExternalMidiNote note = { 0, 0, 0 }; for (; fMidiEventCount < kPluginMaxMidiEvents*2 && ! pData->extNotes.data.isEmpty();) { note = pData->extNotes.data.getFirst(note, true); CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); VstMidiEvent& vstMidiEvent(fMidiEvents[fMidiEventCount++]); vstMidiEvent.type = kVstMidiType; vstMidiEvent.byteSize = kVstMidiEventSize; vstMidiEvent.midiData[0] = char((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); vstMidiEvent.midiData[1] = char(note.note); vstMidiEvent.midiData[2] = char(note.velo); } pData->extNotes.mutex.unlock(); } // End of MIDI Input (External) // ---------------------------------------------------------------------------------------------------- // Event Input (System) #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH bool allNotesOffSent = false; #endif bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; uint32_t startTime = 0; uint32_t timeOffset = 0; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr) pData->event.cvSourcePorts->initPortBuffers(cvIn, frames, isSampleAccurate, pData->event.portIn); #endif for (uint32_t i=0, numEvents = pData->event.portIn->getEventCount(); i < numEvents; ++i) { const EngineEvent& event(pData->event.portIn->getEvent(i)); uint32_t eventTime = event.time; CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames); if (eventTime < timeOffset) { carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'", eventTime, timeOffset, pData->name); eventTime = timeOffset; } if (isSampleAccurate && eventTime > timeOffset) { if (processSingle(audioIn, audioOut, eventTime - timeOffset, timeOffset)) { startTime = 0; timeOffset = eventTime; if (fMidiEventCount > 0) { carla_zeroStructs(fMidiEvents, fMidiEventCount); fMidiEventCount = 0; } } else startTime += timeOffset; } switch (event.type) { case kEngineEventTypeNull: break; case kEngineEventTypeControl: { const EngineControlEvent& ctrlEvent(event.ctrl); switch (ctrlEvent.type) { case kEngineControlEventTypeNull: break; case kEngineControlEventTypeParameter: { float value; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // non-midi if (event.channel == kEngineEventNonMidiChannel) { const uint32_t k = ctrlEvent.param; CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count); value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.value); setParameterValueRT(k, value, true); continue; } // Control backend stuff if (event.channel == pData->ctrlChannel) { if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0) { value = ctrlEvent.value; setDryWetRT(value, true); } if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0) { value = ctrlEvent.value*127.0f/100.0f; setVolumeRT(value, true); } if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0) { float left, right; value = ctrlEvent.value/0.5f - 1.0f; if (value < 0.0f) { left = -1.0f; right = (value*2.0f)+1.0f; } else if (value > 0.0f) { left = (value*2.0f)-1.0f; right = 1.0f; } else { left = -1.0f; right = 1.0f; } setBalanceLeftRT(left, true); setBalanceRightRT(right, true); } } #endif // Control plugin parameters uint32_t k; for (k=0; k < pData->param.count; ++k) { if (pData->param.data[k].midiChannel != event.channel) continue; if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) continue; if (pData->param.data[k].type != PARAMETER_INPUT) continue; if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) continue; value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.value); setParameterValueRT(k, value, true); } if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE) { if (fMidiEventCount >= kPluginMaxMidiEvents*2) continue; VstMidiEvent& vstMidiEvent(fMidiEvents[fMidiEventCount++]); carla_zeroStruct(vstMidiEvent); vstMidiEvent.type = kVstMidiType; vstMidiEvent.byteSize = kVstMidiEventSize; vstMidiEvent.deltaFrames = static_cast(isSampleAccurate ? startTime : eventTime); vstMidiEvent.midiData[0] = char(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); vstMidiEvent.midiData[1] = char(ctrlEvent.param); vstMidiEvent.midiData[2] = char(ctrlEvent.value*127.0f); } break; } // case kEngineControlEventTypeParameter case kEngineControlEventTypeMidiBank: if ((pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) != 0) { if (fMidiEventCount >= kPluginMaxMidiEvents*2) continue; VstMidiEvent& vstMidiEvent_MSB(fMidiEvents[fMidiEventCount++]); carla_zeroStruct(vstMidiEvent_MSB); vstMidiEvent_MSB.type = kVstMidiType; vstMidiEvent_MSB.byteSize = kVstMidiEventSize; vstMidiEvent_MSB.deltaFrames = static_cast(isSampleAccurate ? startTime : event.time); vstMidiEvent_MSB.midiData[0] = char(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); vstMidiEvent_MSB.midiData[1] = MIDI_CONTROL_BANK_SELECT; vstMidiEvent_MSB.midiData[2] = 0; VstMidiEvent& vstMidiEvent_LSB(fMidiEvents[fMidiEventCount++]); carla_zeroStruct(vstMidiEvent_LSB); vstMidiEvent_LSB.type = kVstMidiType; vstMidiEvent_LSB.byteSize = kVstMidiEventSize; vstMidiEvent_LSB.deltaFrames = static_cast(isSampleAccurate ? startTime : eventTime); vstMidiEvent_LSB.midiData[0] = char(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); vstMidiEvent_LSB.midiData[1] = MIDI_CONTROL_BANK_SELECT__LSB; vstMidiEvent_LSB.midiData[2] = char(ctrlEvent.param); } break; case kEngineControlEventTypeMidiProgram: if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0) { if (ctrlEvent.param < pData->prog.count) { setProgramRT(ctrlEvent.param, true); break; } } else if (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) { if (fMidiEventCount >= kPluginMaxMidiEvents*2) continue; VstMidiEvent& vstMidiEvent(fMidiEvents[fMidiEventCount++]); carla_zeroStruct(vstMidiEvent); vstMidiEvent.type = kVstMidiType; vstMidiEvent.byteSize = kVstMidiEventSize; vstMidiEvent.deltaFrames = static_cast(isSampleAccurate ? startTime : eventTime); vstMidiEvent.midiData[0] = char(MIDI_STATUS_PROGRAM_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); vstMidiEvent.midiData[1] = char(ctrlEvent.param); } break; case kEngineControlEventTypeAllSoundOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { if (fMidiEventCount >= kPluginMaxMidiEvents*2) continue; VstMidiEvent& vstMidiEvent(fMidiEvents[fMidiEventCount++]); carla_zeroStruct(vstMidiEvent); vstMidiEvent.type = kVstMidiType; vstMidiEvent.byteSize = kVstMidiEventSize; vstMidiEvent.deltaFrames = static_cast(isSampleAccurate ? startTime : eventTime); vstMidiEvent.midiData[0] = char(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); vstMidiEvent.midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; } break; case kEngineControlEventTypeAllNotesOff: if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (event.channel == pData->ctrlChannel && ! allNotesOffSent) { allNotesOffSent = true; postponeRtAllNotesOff(); } #endif if (fMidiEventCount >= kPluginMaxMidiEvents*2) continue; VstMidiEvent& vstMidiEvent(fMidiEvents[fMidiEventCount++]); carla_zeroStruct(vstMidiEvent); vstMidiEvent.type = kVstMidiType; vstMidiEvent.byteSize = kVstMidiEventSize; vstMidiEvent.deltaFrames = static_cast(isSampleAccurate ? startTime : eventTime); vstMidiEvent.midiData[0] = char(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); vstMidiEvent.midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; } break; } // switch (ctrlEvent.type) break; } // case kEngineEventTypeControl case kEngineEventTypeMidi: { if (fMidiEventCount >= kPluginMaxMidiEvents*2) continue; const EngineMidiEvent& midiEvent(event.midi); if (midiEvent.size > 3) continue; #ifdef CARLA_PROPER_CPP11_SUPPORT static_assert(3 <= EngineMidiEvent::kDataSize, "Incorrect data"); #endif uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) continue; if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0) continue; if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0) continue; if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) continue; // Fix bad note-off if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0) status = MIDI_STATUS_NOTE_OFF; VstMidiEvent& vstMidiEvent(fMidiEvents[fMidiEventCount++]); carla_zeroStruct(vstMidiEvent); vstMidiEvent.type = kVstMidiType; vstMidiEvent.byteSize = kVstMidiEventSize; vstMidiEvent.deltaFrames = static_cast(isSampleAccurate ? startTime : eventTime); vstMidiEvent.midiData[0] = char(status | (event.channel & MIDI_CHANNEL_BIT)); vstMidiEvent.midiData[1] = char(midiEvent.size >= 2 ? midiEvent.data[1] : 0); vstMidiEvent.midiData[2] = char(midiEvent.size >= 3 ? midiEvent.data[2] : 0); if (status == MIDI_STATUS_NOTE_ON) { pData->postponeRtEvent(kPluginPostRtEventNoteOn, true, event.channel, midiEvent.data[1], midiEvent.data[2], 0.0f); } else if (status == MIDI_STATUS_NOTE_OFF) { pData->postponeRtEvent(kPluginPostRtEventNoteOff, true, event.channel, midiEvent.data[1], 0, 0.0f); } } break; } // switch (event.type) } pData->postRtEvents.trySplice(); if (frames > timeOffset) processSingle(audioIn, audioOut, frames - timeOffset, timeOffset); } // End of Event Input and Processing // -------------------------------------------------------------------------------------------------------- // Plugin processing (no events) else { processSingle(audioIn, audioOut, frames, 0); } // End of Plugin processing (no events) // -------------------------------------------------------------------------------------------------------- // MIDI Output if (pData->event.portOut != nullptr) { // reverse lookup MIDI events for (uint32_t k = (kPluginMaxMidiEvents*2)-1; k >= fMidiEventCount; --k) { if (fMidiEvents[k].type == 0) break; const VstMidiEvent& vstMidiEvent(fMidiEvents[k]); CARLA_SAFE_ASSERT_CONTINUE(vstMidiEvent.deltaFrames >= 0); CARLA_SAFE_ASSERT_CONTINUE(vstMidiEvent.midiData[0] != 0); uint8_t midiData[3]; midiData[0] = static_cast(vstMidiEvent.midiData[0]); midiData[1] = static_cast(vstMidiEvent.midiData[1]); midiData[2] = static_cast(vstMidiEvent.midiData[2]); if (! pData->event.portOut->writeMidiEvent(static_cast(vstMidiEvent.deltaFrames), 3, midiData)) break; } } // End of MIDI Output fFirstActive = false; // -------------------------------------------------------------------------------------------------------- #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH return; // unused (void)cvIn; #endif } bool processSingle(const float* const* const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset) { CARLA_SAFE_ASSERT_RETURN(frames > 0, false); if (pData->audioIn.count > 0) { CARLA_SAFE_ASSERT_RETURN(inBuffer != nullptr, false); } if (pData->audioOut.count > 0) { CARLA_SAFE_ASSERT_RETURN(outBuffer != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fAudioOutBuffers != nullptr, false); } // -------------------------------------------------------------------------------------------------------- // Try lock, silence otherwise #ifndef STOAT_TEST_BUILD if (pData->engine->isOffline()) { pData->singleMutex.lock(); } else #endif if (! pData->singleMutex.tryLock()) { for (uint32_t i=0; i < pData->audioOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) outBuffer[i][k+timeOffset] = 0.0f; } return false; } // -------------------------------------------------------------------------------------------------------- // Set audio buffers float* vstInBuffer[pData->audioIn.count]; for (uint32_t i=0; i < pData->audioIn.count; ++i) vstInBuffer[i] = const_cast(inBuffer[i]+timeOffset); for (uint32_t i=0; i < pData->audioOut.count; ++i) carla_zeroFloats(fAudioOutBuffers[i], frames); // -------------------------------------------------------------------------------------------------------- // Set MIDI events fIsProcessing = true; if (fMidiEventCount > 0) { fEvents.numEvents = static_cast(fMidiEventCount); fEvents.reserved = 0; dispatcher(effProcessEvents, 0, 0, &fEvents, 0.0f); } // -------------------------------------------------------------------------------------------------------- // Run plugin if (pData->hints & PLUGIN_CAN_PROCESS_REPLACING) { fEffect->processReplacing(fEffect, (pData->audioIn.count > 0) ? vstInBuffer : nullptr, (pData->audioOut.count > 0) ? fAudioOutBuffers : nullptr, static_cast(frames)); } else { #if ! VST_FORCE_DEPRECATED fEffect->process(fEffect, (pData->audioIn.count > 0) ? vstInBuffer : nullptr, (pData->audioOut.count > 0) ? fAudioOutBuffers : nullptr, static_cast(frames)); #endif } fIsProcessing = false; fTimeInfo.samplePos += frames; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // -------------------------------------------------------------------------------------------------------- // Post-processing (dry/wet, volume and balance) { const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f); const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f)); const bool isMono = (pData->audioIn.count == 1); bool isPair; float bufValue, oldBufLeft[doBalance ? frames : 1]; for (uint32_t i=0; i < pData->audioOut.count; ++i) { // Dry/Wet if (doDryWet) { const uint32_t c = isMono ? 0 : i; for (uint32_t k=0; k < frames; ++k) { bufValue = inBuffer[c][k+timeOffset]; fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet)); } } // Balance if (doBalance) { isPair = (i % 2 == 0); if (isPair) { CARLA_ASSERT(i+1 < pData->audioOut.count); carla_copyFloats(oldBufLeft, fAudioOutBuffers[i], frames); } float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f; float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f; for (uint32_t k=0; k < frames; ++k) { if (isPair) { // left fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL); fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR); } else { // right fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR; fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL; } } } // Volume (and buffer copy) { for (uint32_t k=0; k < frames; ++k) outBuffer[i][k+timeOffset] = fAudioOutBuffers[i][k] * pData->postProc.volume; } } } // End of Post-processing #else // BUILD_BRIDGE_ALTERNATIVE_ARCH for (uint32_t i=0; i < pData->audioOut.count; ++i) { for (uint32_t k=0; k < frames; ++k) outBuffer[i][k+timeOffset] = fAudioOutBuffers[i][k]; } #endif // -------------------------------------------------------------------------------------------------------- pData->singleMutex.unlock(); return true; } void bufferSizeChanged(const uint32_t newBufferSize) override { CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize); carla_debug("CarlaPluginVST2::bufferSizeChanged(%i)", newBufferSize); fBufferSize = pData->engine->getBufferSize(); if (pData->active) deactivate(); for (uint32_t i=0; i < pData->audioOut.count; ++i) { if (fAudioOutBuffers[i] != nullptr) delete[] fAudioOutBuffers[i]; fAudioOutBuffers[i] = new float[newBufferSize]; } #if ! VST_FORCE_DEPRECATED dispatcher(effSetBlockSizeAndSampleRate, 0, static_cast(newBufferSize), nullptr, static_cast(pData->engine->getSampleRate())); #endif dispatcher(effSetBlockSize, 0, static_cast(newBufferSize), nullptr, 0.0f); if (pData->active) activate(); } void sampleRateChanged(const double newSampleRate) override { CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate); carla_debug("CarlaPluginVST2::sampleRateChanged(%g)", newSampleRate); if (pData->active) deactivate(); #if ! VST_FORCE_DEPRECATED dispatcher(effSetBlockSizeAndSampleRate, 0, static_cast(pData->engine->getBufferSize()), nullptr, static_cast(newSampleRate)); #endif dispatcher(effSetSampleRate, 0, 0, nullptr, static_cast(newSampleRate)); if (pData->active) activate(); } // ------------------------------------------------------------------- // Plugin buffers void clearBuffers() noexcept override { carla_debug("CarlaPluginVST2::clearBuffers() - start"); if (fAudioOutBuffers != nullptr) { for (uint32_t i=0; i < pData->audioOut.count; ++i) { if (fAudioOutBuffers[i] != nullptr) { delete[] fAudioOutBuffers[i]; fAudioOutBuffers[i] = nullptr; } } delete[] fAudioOutBuffers; fAudioOutBuffers = nullptr; } CarlaPlugin::clearBuffers(); carla_debug("CarlaPluginVST2::clearBuffers() - end"); } // ------------------------------------------------------------------- // Post-poned UI Stuff // nothing // ------------------------------------------------------------------- protected: void handlePluginUIClosed() override { CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,); carla_debug("CarlaPluginVST2::handlePluginUIClosed()"); showCustomUI(false); pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr); } void handlePluginUIResized(const uint width, const uint height) override { CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,); carla_debug("CarlaPluginVST2::handlePluginUIResized(%u, %u)", width, height); return; // unused (void)width; (void)height; } // ------------------------------------------------------------------- intptr_t dispatcher(int32_t opcode, int32_t index = 0, intptr_t value = 0, void* ptr = nullptr, float opt = 0.0f) const noexcept { CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, 0); #ifdef DEBUG if (opcode != effIdle && opcode != effEditIdle && opcode != effProcessEvents) carla_debug("CarlaPluginVST2::dispatcher(%02i:%s, %i, " P_INTPTR ", %p, %f)", opcode, vstEffectOpcode2str(opcode), index, value, ptr, static_cast(opt)); #endif try { return fEffect->dispatcher(fEffect, opcode, index, value, ptr, opt); } CARLA_SAFE_EXCEPTION_RETURN("Vst dispatcher", 0); } intptr_t handleAudioMasterCallback(const int32_t opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt) { #ifdef DEBUG if (opcode != audioMasterGetTime) carla_debug("CarlaPluginVST2::handleAudioMasterCallback(%02i:%s, %i, " P_INTPTR ", %p, %f)", opcode, vstMasterOpcode2str(opcode), index, value, ptr, static_cast(opt)); #endif intptr_t ret = 0; switch (opcode) { case audioMasterAutomate: { if (fIsInitializing) { // some plugins can be stupid... if (pData->param.count == 0) break; } else { CARLA_SAFE_ASSERT_BREAK(pData->enabled); } // plugins should never do this: CARLA_SAFE_ASSERT_INT2_BREAK(index >= 0 && index < static_cast(pData->param.count), index, static_cast(pData->param.count)); const uint32_t uindex(static_cast(index)); const float fixedValue(pData->param.getFixedValue(uindex, opt)); const pthread_t thisThread = pthread_self(); if (pthread_equal(thisThread, kNullThread)) { carla_stderr("audioMasterAutomate called with null thread!?"); setParameterValue(uindex, fixedValue, false, true, true); } // Called from plugin process thread, nasty! (likely MIDI learn) else if (pthread_equal(thisThread, fProcThread)) { CARLA_SAFE_ASSERT(fIsProcessing); pData->postponeRtEvent(kPluginPostRtEventParameterChange, true, index, 0, 0, fixedValue); } // Called from effSetChunk or effSetProgram else if (pthread_equal(thisThread, fChangingValuesThread)) { carla_debug("audioMasterAutomate called while setting state"); pData->postponeRtEvent(kPluginPostRtEventParameterChange, true, index, 0, 0, fixedValue); } // Called from effIdle else if (pthread_equal(thisThread, fIdleThread)) { carla_debug("audioMasterAutomate called from idle thread"); pData->postponeRtEvent(kPluginPostRtEventParameterChange, true, index, 0, 0, fixedValue); } // Called from main thread, why? else if (pthread_equal(thisThread, fMainThread)) { if (fFirstActive) { carla_stdout("audioMasterAutomate called while loading, nasty!"); } else { carla_debug("audioMasterAutomate called from main thread"); } CarlaPlugin::setParameterValue(uindex, fixedValue, false, true, true); } // Called from UI? else if (fUI.isVisible) { carla_debug("audioMasterAutomate called while UI visible"); CarlaPlugin::setParameterValue(uindex, fixedValue, false, true, true); } // Unknown else { carla_stdout("audioMasterAutomate called from unknown source"); setParameterValue(uindex, fixedValue, false, true, true); } break; } case audioMasterCurrentId: if (fEffect != nullptr) ret = fEffect->uniqueID; break; case audioMasterIdle: CARLA_SAFE_ASSERT_BREAK(pthread_equal(pthread_self(), fMainThread)); pData->engine->callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); if (pData->engine->getType() != kEngineTypePlugin) pData->engine->idle(); break; #if ! VST_FORCE_DEPRECATED case audioMasterPinConnected: // Deprecated in VST SDK 2.4 // TODO break; case audioMasterWantMidi: // Deprecated in VST SDK 2.4 pData->hints |= PLUGIN_WANTS_MIDI_INPUT; break; #endif case audioMasterGetTime: ret = (intptr_t)&fTimeInfo; break; case audioMasterProcessEvents: CARLA_SAFE_ASSERT_RETURN(pData->enabled, 0); CARLA_SAFE_ASSERT_RETURN(fIsProcessing, 0); CARLA_SAFE_ASSERT_RETURN(pData->event.portOut != nullptr, 0); if (fMidiEventCount >= kPluginMaxMidiEvents*2-1) return 0; if (const VstEvents* const vstEvents = (const VstEvents*)ptr) { for (int32_t i=0; i < vstEvents->numEvents && i < kPluginMaxMidiEvents*2; ++i) { if (vstEvents->events[i] == nullptr) break; const VstMidiEvent* const vstMidiEvent((const VstMidiEvent*)vstEvents->events[i]); if (vstMidiEvent->type != kVstMidiType) continue; // reverse-find first free event, and put it there for (uint32_t j=(kPluginMaxMidiEvents*2)-1; j >= fMidiEventCount; --j) { if (fMidiEvents[j].type == 0) { std::memcpy(&fMidiEvents[j], vstMidiEvent, sizeof(VstMidiEvent)); break; } } } } ret = 1; break; #if ! VST_FORCE_DEPRECATED case audioMasterSetTime: // Deprecated in VST SDK 2.4 break; case audioMasterTempoAt: // Deprecated in VST SDK 2.4 ret = static_cast(fTimeInfo.tempo * 10000); break; case audioMasterGetNumAutomatableParameters: // Deprecated in VST SDK 2.4 ret = static_cast(pData->engine->getOptions().maxParameters); ret = carla_minPositive(ret, fEffect->numParams); break; case audioMasterGetParameterQuantization: // Deprecated in VST SDK 2.4 ret = 1; // full single float precision break; #endif #if 0 case audioMasterIOChanged: CARLA_ASSERT(pData->enabled); // TESTING if (! pData->enabled) { ret = 1; break; } if (x_engine->getOptions().processMode == PROCESS_MODE_CONTINUOUS_RACK) { carla_stderr2("CarlaPluginVST2::handleAudioMasterIOChanged() - plugin asked IO change, but it's not supported in rack mode"); return 0; } engineProcessLock(); m_enabled = false; engineProcessUnlock(); if (m_active) { effect->dispatcher(effect, effStopProcess); effect->dispatcher(effect, effMainsChanged, 0, 0); } reload(); if (m_active) { effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0.0f); effect->dispatcher(effect, effStartProcess); } x_engine->callback(CALLBACK_RELOAD_ALL, m_id, 0, 0, 0, 0.0, nullptr); ret = 1; break; #endif #if ! VST_FORCE_DEPRECATED case audioMasterNeedIdle: // Deprecated in VST SDK 2.4 fNeedIdle = true; ret = 1; break; #endif case audioMasterSizeWindow: CARLA_SAFE_ASSERT_BREAK(fUI.window != nullptr); CARLA_SAFE_ASSERT_BREAK(index > 0); CARLA_SAFE_ASSERT_BREAK(value > 0); fUI.window->setSize(static_cast(index), static_cast(value), true); ret = 1; break; case audioMasterGetSampleRate: ret = static_cast(pData->engine->getSampleRate()); break; case audioMasterGetBlockSize: ret = static_cast(pData->engine->getBufferSize()); break; case audioMasterGetInputLatency: ret = 0; break; case audioMasterGetOutputLatency: ret = 0; break; #if ! VST_FORCE_DEPRECATED case audioMasterGetPreviousPlug: // Deprecated in VST SDK 2.4 // TODO break; case audioMasterGetNextPlug: // Deprecated in VST SDK 2.4 // TODO break; case audioMasterWillReplaceOrAccumulate: // Deprecated in VST SDK 2.4 ret = 1; // replace break; #endif case audioMasterGetCurrentProcessLevel: if (pthread_equal(pthread_self(), fProcThread)) { CARLA_SAFE_ASSERT(fIsProcessing); if (pData->engine->isOffline()) ret = kVstProcessLevelOffline; else ret = kVstProcessLevelRealtime; } else { ret = kVstProcessLevelUser; } break; case audioMasterGetAutomationState: ret = pData->active ? kVstAutomationReadWrite : kVstAutomationOff; break; case audioMasterOfflineStart: case audioMasterOfflineRead: case audioMasterOfflineWrite: case audioMasterOfflineGetCurrentPass: case audioMasterOfflineGetCurrentMetaPass: // TODO break; #if ! VST_FORCE_DEPRECATED case audioMasterSetOutputSampleRate: // Deprecated in VST SDK 2.4 break; case audioMasterGetOutputSpeakerArrangement: // Deprecated in VST SDK 2.4 // TODO break; #endif case audioMasterVendorSpecific: // TODO - cockos extensions break; #if ! VST_FORCE_DEPRECATED case audioMasterSetIcon: // Deprecated in VST SDK 2.4 break; #endif #if ! VST_FORCE_DEPRECATED case audioMasterOpenWindow: case audioMasterCloseWindow: // Deprecated in VST SDK 2.4 // TODO break; #endif case audioMasterGetDirectory: // TODO break; case audioMasterUpdateDisplay: // Update current program if (pData->prog.count > 1) { const int32_t current = static_cast(dispatcher(effGetProgram)); if (current >= 0 && current < static_cast(pData->prog.count)) { char strBuf[STR_MAX+1] = { '\0' }; dispatcher(effGetProgramName, 0, 0, strBuf); if (pData->prog.names[current] != nullptr) delete[] pData->prog.names[current]; pData->prog.names[current] = carla_strdup(strBuf); if (pData->prog.current != current) { pData->prog.current = current; pData->engine->callback(true, true, ENGINE_CALLBACK_PROGRAM_CHANGED, pData->id, current, 0, 0, 0.0f, nullptr); } } } if (! fIsInitializing) pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PARAMETERS, pData->id, 0, 0, 0, 0.0f, nullptr); ret = 1; break; case audioMasterBeginEdit: CARLA_SAFE_ASSERT_BREAK(index >= 0); pData->engine->touchPluginParameter(pData->id, static_cast(index), true); break; case audioMasterEndEdit: CARLA_SAFE_ASSERT_BREAK(index >= 0); pData->engine->touchPluginParameter(pData->id, static_cast(index), false); break; case audioMasterOpenFileSelector: case audioMasterCloseFileSelector: // TODO break; #if ! VST_FORCE_DEPRECATED case audioMasterEditFile: // Deprecated in VST SDK 2.4 // TODO break; case audioMasterGetChunkFile: // Deprecated in VST SDK 2.4 // TODO break; case audioMasterGetInputSpeakerArrangement: // Deprecated in VST SDK 2.4 // TODO break; #endif default: carla_debug("CarlaPluginVST2::handleAudioMasterCallback(%02i:%s, %i, " P_INTPTR ", %p, %f) UNDEF", opcode, vstMasterOpcode2str(opcode), index, value, ptr, static_cast(opt)); break; } return ret; // unused (void)opt; } bool canDo(const char* const feature) const noexcept { try { return (dispatcher(effCanDo, 0, 0, const_cast(feature)) == 1); } CARLA_SAFE_EXCEPTION_RETURN("vstPluginCanDo", false); } bool hasMidiInput() const noexcept { return (fEffect->flags & effFlagsIsSynth) != 0 || (pData->hints & PLUGIN_WANTS_MIDI_INPUT) != 0 || canDo("receiveVstEvents") || canDo("receiveVstMidiEvent"); } bool hasMidiOutput() const noexcept { return canDo("sendVstEvents") || canDo("sendVstMidiEvent"); } // ------------------------------------------------------------------- const void* getNativeDescriptor() const noexcept override { return fEffect; } // ------------------------------------------------------------------- public: bool init(const char* const filename, const char* const name, const int64_t uniqueId, const uint options) { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); // --------------------------------------------------------------- // first checks if (pData->client != nullptr) { pData->engine->setLastError("Plugin client is already registered"); return false; } if (filename == nullptr || filename[0] == '\0') { pData->engine->setLastError("null filename"); return false; } // --------------------------------------------------------------- VST_Function vstFn; #ifdef CARLA_OS_MAC CarlaString filenameCheck(filename); filenameCheck.toLower(); if (filenameCheck.endsWith(".vst") || filenameCheck.endsWith(".vst/")) { // FIXME assert returns, set engine error const CFURLRef urlRef = CFURLCreateFromFileSystemRepresentation(0, (const UInt8*)filename, (CFIndex)strlen(filename), true); CARLA_SAFE_ASSERT_RETURN(urlRef != nullptr, false); fMacBundleRef = CFBundleCreate(kCFAllocatorDefault, urlRef); CFRelease(urlRef); CARLA_SAFE_ASSERT_RETURN(fMacBundleRef != nullptr, false); if (! CFBundleLoadExecutable(fMacBundleRef)) { CFRelease(fMacBundleRef); pData->engine->setLastError("Failed to load VST bundle executable"); return false; } vstFn = (VST_Function)CFBundleGetFunctionPointerForName(fMacBundleRef, CFSTR("main_macho")); if (vstFn == nullptr) vstFn = (VST_Function)CFBundleGetFunctionPointerForName(fMacBundleRef, CFSTR("VSTPluginMain")); if (vstFn == nullptr) { CFBundleUnloadExecutable(fMacBundleRef); CFRelease(fMacBundleRef); pData->engine->setLastError("Not a VST plugin"); return false; } fMacBundleRefNum = CFBundleOpenBundleResourceMap(fMacBundleRef); } else #endif { // ----------------------------------------------------------- // open DLL if (! pData->libOpen(filename)) { pData->engine->setLastError(pData->libError(filename)); return false; } // ----------------------------------------------------------- // get DLL main entry vstFn = pData->libSymbol("VSTPluginMain"); if (vstFn == nullptr) { vstFn = pData->libSymbol("main"); if (vstFn == nullptr) { pData->engine->setLastError("Could not find the VST main entry in the plugin library"); return false; } } } // --------------------------------------------------------------- // initialize plugin (part 1) sCurrentUniqueId = static_cast(uniqueId); sLastCarlaPluginVST2 = this; try { fEffect = vstFn(carla_vst_audioMasterCallback); } CARLA_SAFE_EXCEPTION_RETURN("Vst init", false); sLastCarlaPluginVST2 = nullptr; sCurrentUniqueId = 0; if (fEffect == nullptr) { pData->engine->setLastError("Plugin failed to initialize"); return false; } if (fEffect->magic != kEffectMagic) { pData->engine->setLastError("Plugin is not valid (wrong vst effect magic code)"); return false; } fEffect->ptr1 = this; const int32_t iBufferSize = static_cast(fBufferSize); const float fSampleRate = static_cast(pData->engine->getSampleRate()); dispatcher(effIdentify); dispatcher(effSetProcessPrecision, 0, kVstProcessPrecision32); dispatcher(effSetBlockSizeAndSampleRate, 0, iBufferSize, nullptr, fSampleRate); dispatcher(effSetSampleRate, 0, 0, nullptr, fSampleRate); dispatcher(effSetBlockSize, 0, iBufferSize); dispatcher(effOpen); const bool isShell = (dispatcher(effGetPlugCategory) == kPlugCategShell); if (uniqueId == 0 && isShell) { char strBuf[STR_MAX+1]; carla_zeroChars(strBuf, STR_MAX+1); sCurrentUniqueId = dispatcher(effShellGetNextPlugin, 0, 0, strBuf); dispatcher(effClose); fEffect = nullptr; sLastCarlaPluginVST2 = this; try { fEffect = vstFn(carla_vst_audioMasterCallback); } CARLA_SAFE_EXCEPTION_RETURN("Vst init", false); sLastCarlaPluginVST2 = nullptr; sCurrentUniqueId = 0; dispatcher(effIdentify); dispatcher(effSetProcessPrecision, 0, kVstProcessPrecision32); dispatcher(effSetBlockSizeAndSampleRate, 0, iBufferSize, nullptr, fSampleRate); dispatcher(effSetSampleRate, 0, 0, nullptr, fSampleRate); dispatcher(effSetBlockSize, 0, iBufferSize); dispatcher(effOpen); } if (fEffect->uniqueID == 0 && !isShell) { dispatcher(effClose); fEffect = nullptr; pData->engine->setLastError("Plugin is not valid (no unique ID after being open)"); return false; } // --------------------------------------------------------------- // get info if (name != nullptr && name[0] != '\0') { pData->name = pData->engine->getUniquePluginName(name); } else { char strBuf[STR_MAX+1]; carla_zeroChars(strBuf, STR_MAX+1); dispatcher(effGetEffectName, 0, 0, strBuf); if (strBuf[0] != '\0') pData->name = pData->engine->getUniquePluginName(strBuf); else if (const char* const shortname = std::strrchr(filename, CARLA_OS_SEP)) pData->name = pData->engine->getUniquePluginName(shortname+1); else pData->name = pData->engine->getUniquePluginName("unknown"); } pData->filename = carla_strdup(filename); // --------------------------------------------------------------- // register client pData->client = pData->engine->addClient(this); if (pData->client == nullptr || ! pData->client->isOk()) { pData->engine->setLastError("Failed to register plugin client"); return false; } // --------------------------------------------------------------- // initialize plugin (part 2) for (int i = fEffect->numInputs; --i >= 0;) dispatcher(effConnectInput, i, 1); for (int i = fEffect->numOutputs; --i >= 0;) dispatcher(effConnectOutput, i, 1); if (dispatcher(effGetVstVersion) < kVstVersion) pData->hints |= PLUGIN_USES_OLD_VSTSDK; static const char kHasCockosExtensions[] = "hasCockosExtensions"; if (static_cast(dispatcher(effCanDo, 0, 0, const_cast(kHasCockosExtensions))) == 0xbeef0000) pData->hints |= PLUGIN_HAS_COCKOS_EXTENSIONS; // --------------------------------------------------------------- // set default options pData->options = 0x0; if (pData->latency.frames != 0 || hasMidiOutput() || isPluginOptionEnabled(options, PLUGIN_OPTION_FIXED_BUFFERS)) pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; if (fEffect->flags & effFlagsProgramChunks) if (isPluginOptionEnabled(options, PLUGIN_OPTION_USE_CHUNKS)) pData->options |= PLUGIN_OPTION_USE_CHUNKS; if (hasMidiInput()) { if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)) pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)) pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND)) pData->options |= PLUGIN_OPTION_SEND_PITCHBEND; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF)) pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PROGRAM_CHANGES)) pData->options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES; } if (fEffect->numPrograms > 1 && (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) == 0) if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES)) pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; return true; } private: int fUnique1; AEffect* fEffect; uint32_t fMidiEventCount; VstMidiEvent fMidiEvents[kPluginMaxMidiEvents*2]; VstTimeInfo fTimeInfo; bool fNeedIdle; void* fLastChunk; bool fIsInitializing; bool fIsProcessing; pthread_t fChangingValuesThread; pthread_t fIdleThread; pthread_t fMainThread; pthread_t fProcThread; #ifdef CARLA_OS_MAC CFBundleRef fMacBundleRef; CFBundleRefNum fMacBundleRefNum; #endif bool fFirstActive; // first process() call after activate() uint32_t fBufferSize; float** fAudioOutBuffers; EngineTimeInfo fLastTimeInfo; struct FixedVstEvents { int32_t numEvents; intptr_t reserved; VstEvent* data[kPluginMaxMidiEvents*2]; FixedVstEvents() noexcept : numEvents(0), reserved(0) { carla_zeroPointers(data, kPluginMaxMidiEvents*2); } CARLA_DECLARE_NON_COPY_STRUCT(FixedVstEvents); } fEvents; struct UI { bool isOpen; bool isVisible; CarlaPluginUI* window; UI() noexcept : isOpen(false), isVisible(false), window(nullptr) {} ~UI() { CARLA_ASSERT(! isVisible); if (window != nullptr) { delete window; window = nullptr; } } CARLA_DECLARE_NON_COPY_STRUCT(UI); } fUI; int fUnique2; static intptr_t sCurrentUniqueId; static CarlaPluginVST2* sLastCarlaPluginVST2; // ------------------------------------------------------------------- static bool compareMagic(int32_t magic, const char* name) noexcept { return magic == (int32_t)ByteOrder::littleEndianInt (name) || magic == (int32_t)ByteOrder::bigEndianInt (name); } static int32_t fxbSwap(const int32_t x) noexcept { return (int32_t)ByteOrder::swapIfLittleEndian ((uint32_t) x); } bool loadJuceSaveFormat(const void* const data, const std::size_t dataSize) { if (dataSize < 28) return false; const int32_t* const set = (const int32_t*)data; if (set[1] != 0) return false; if (! compareMagic(set[0], "CcnK")) return false; if (! compareMagic(set[2], "FBCh") && ! compareMagic(set[2], "FJuc")) return false; if (fxbSwap(set[3]) > 1) return false; const int32_t chunkSize = fxbSwap(set[39]); CARLA_SAFE_ASSERT_RETURN(chunkSize > 0, false); if (static_cast(chunkSize + 160) > dataSize) return false; carla_stdout("NOTE: Loading plugin state in VST2/JUCE compatibility mode"); setChunkData(&set[40], static_cast(chunkSize)); return true; } static intptr_t carla_vst_hostCanDo(const char* const feature) { carla_debug("carla_vst_hostCanDo(\"%s\")", feature); if (std::strcmp(feature, "supplyIdle") == 0) return 1; if (std::strcmp(feature, "sendVstEvents") == 0) return 1; if (std::strcmp(feature, "sendVstMidiEvent") == 0) return 1; if (std::strcmp(feature, "sendVstMidiEventFlagIsRealtime") == 0) return 1; if (std::strcmp(feature, "sendVstTimeInfo") == 0) return 1; if (std::strcmp(feature, "receiveVstEvents") == 0) return 1; if (std::strcmp(feature, "receiveVstMidiEvent") == 0) return 1; if (std::strcmp(feature, "receiveVstTimeInfo") == 0) return -1; if (std::strcmp(feature, "reportConnectionChanges") == 0) return -1; if (std::strcmp(feature, "acceptIOChanges") == 0) return 1; if (std::strcmp(feature, "sizeWindow") == 0) return 1; if (std::strcmp(feature, "offline") == 0) return -1; if (std::strcmp(feature, "openFileSelector") == 0) return -1; if (std::strcmp(feature, "closeFileSelector") == 0) return -1; if (std::strcmp(feature, "startStopProcess") == 0) return 1; if (std::strcmp(feature, "supportShell") == 0) return 1; if (std::strcmp(feature, "shellCategory") == 0) return 1; if (std::strcmp(feature, "NIMKPIVendorSpecificCallbacks") == 0) return -1; // unimplemented carla_stderr("carla_vst_hostCanDo(\"%s\") - unknown feature", feature); return 0; } static intptr_t VSTCALLBACK carla_vst_audioMasterCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) { #if defined(DEBUG) && ! defined(CARLA_OS_WIN) if (opcode != audioMasterGetTime && opcode != audioMasterProcessEvents && opcode != audioMasterGetCurrentProcessLevel && opcode != audioMasterGetOutputLatency) carla_debug("carla_vst_audioMasterCallback(%p, %02i:%s, %i, " P_INTPTR ", %p, %f)", effect, opcode, vstMasterOpcode2str(opcode), index, value, ptr, static_cast(opt)); #endif switch (opcode) { case audioMasterVersion: return kVstVersion; case audioMasterCurrentId: if (sCurrentUniqueId != 0) return sCurrentUniqueId; break; case audioMasterGetVendorString: CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0); std::strcpy((char*)ptr, "falkTX"); return 1; case audioMasterGetProductString: CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0); std::strcpy((char*)ptr, "Carla"); return 1; case audioMasterGetVendorVersion: return CARLA_VERSION_HEX; case audioMasterCanDo: CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0); return carla_vst_hostCanDo((const char*)ptr); case audioMasterGetLanguage: return kVstLangEnglish; } // Check if 'resvd1' points to us, otherwise register ourselves if possible CarlaPluginVST2* self = nullptr; if (effect != nullptr) { if (effect->ptr1 != nullptr) { self = (CarlaPluginVST2*)effect->ptr1; if (self->fUnique1 != self->fUnique2) self = nullptr; } if (self != nullptr) { if (self->fEffect == nullptr) self->fEffect = effect; if (self->fEffect != effect) { carla_stderr2("carla_vst_audioMasterCallback() - host pointer mismatch: %p != %p", self->fEffect, effect); self = nullptr; } } else if (sLastCarlaPluginVST2 != nullptr) { effect->ptr1 = sLastCarlaPluginVST2; self = sLastCarlaPluginVST2; } } return (self != nullptr) ? self->handleAudioMasterCallback(opcode, index, value, ptr, opt) : 0; } CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginVST2) }; intptr_t CarlaPluginVST2::sCurrentUniqueId = 0; CarlaPluginVST2* CarlaPluginVST2::sLastCarlaPluginVST2 = nullptr; CARLA_BACKEND_END_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- CARLA_BACKEND_START_NAMESPACE CarlaPlugin* CarlaPlugin::newVST2(const Initializer& init) { carla_debug("CarlaPlugin::newVST2({%p, \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.uniqueId); #ifdef USE_JUCE_FOR_VST2 if (std::getenv("CARLA_DO_NOT_USE_JUCE_FOR_VST2") == nullptr) return newJuce(init, "VST2"); #endif CarlaPluginVST2* const plugin(new CarlaPluginVST2(init.engine, init.id)); if (! plugin->init(init.filename, init.name, init.uniqueId, init.options)) { delete plugin; return nullptr; } return plugin; } // ------------------------------------------------------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/plugin/CarlaPluginVST3.cpp000066400000000000000000000025361364475620200221670ustar00rootroot00000000000000/* * Carla VST3 Plugin * Copyright (C) 2014 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaPlugin.hpp" #include "CarlaEngine.hpp" #include "CarlaUtils.hpp" CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- CarlaPlugin* CarlaPlugin::newVST3(const Initializer& init) { carla_debug("CarlaPlugin::newVST3({%p, \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.uniqueId); #ifdef USING_JUCE return newJuce(init, "VST3"); #else init.engine->setLastError("VST3 support not available"); return nullptr; #endif } // ------------------------------------------------------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE Carla-2.1/source/backend/plugin/Makefile000066400000000000000000000044251364475620200202410ustar00rootroot00000000000000#!/usr/bin/make -f # Makefile for carla-plugin # # ------------------------- # # Created by falkTX # CWD=../.. include ../Makefile.mk # Workaround GCC bug ifeq ($(TESTBUILD),true) ifeq ($(USING_JUCE),true) BUILD_CXX_FLAGS += -Wno-undef endif endif # --------------------------------------------------------------------------------------------------------------------- OBJS = \ $(OBJDIR)/CarlaPlugin.cpp.o \ $(OBJDIR)/CarlaPluginInternal.cpp.o \ $(OBJDIR)/CarlaPluginNative.cpp.o \ $(OBJDIR)/CarlaPluginBridge.cpp.o \ $(OBJDIR)/CarlaPluginLADSPADSSI.cpp.o \ $(OBJDIR)/CarlaPluginLV2.cpp.o \ $(OBJDIR)/CarlaPluginVST2.cpp.o \ $(OBJDIR)/CarlaPluginVST3.cpp.o \ $(OBJDIR)/CarlaPluginAU.cpp.o \ $(OBJDIR)/CarlaPluginJuce.cpp.o \ $(OBJDIR)/CarlaPluginFluidSynth.cpp.o \ $(OBJDIR)/CarlaPluginSFZero.cpp.o \ $(OBJDIR)/CarlaPluginJack.cpp.o TARGETS = \ $(MODULEDIR)/carla_plugin.a # --------------------------------------------------------------------------------------------------------------------- all: $(TARGETS) # --------------------------------------------------------------------------------------------------------------------- clean: rm -f $(OBJS) $(TARGETS) debug: $(MAKE) DEBUG=true # --------------------------------------------------------------------------------------------------------------------- $(MODULEDIR)/carla_plugin.a: $(OBJS) -@mkdir -p $(MODULEDIR) @echo "Creating carla_plugin.a" @rm -f $@ @$(AR) crs $@ $^ # --------------------------------------------------------------------------------------------------------------------- $(OBJDIR)/CarlaPluginFluidSynth.cpp.o: CarlaPluginFluidSynth.cpp -@mkdir -p $(OBJDIR) @echo "Compiling $<" @$(CXX) $< $(BUILD_CXX_FLAGS) $(FLUIDSYNTH_FLAGS) -c -o $@ ifeq ($(MACOS),true) $(OBJDIR)/CarlaPluginVST2.cpp.o: CarlaPluginVST2.cpp -@mkdir -p $(OBJDIR) @echo "Compiling $<" @$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@ $(OBJDIR)/CarlaPluginJuce.cpp.o: CarlaPluginJuce.cpp -@mkdir -p $(OBJDIR) @echo "Compiling $<" @$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@ endif $(OBJDIR)/%.cpp.o: %.cpp -@mkdir -p $(OBJDIR) @echo "Compiling $<" @$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ -include $(OBJS:%.o=%.d) # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/utils/000077500000000000000000000000001364475620200164365ustar00rootroot00000000000000Carla-2.1/source/backend/utils/CachedPlugins.cpp000066400000000000000000000611641364475620200216630ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaUtils.h" #include "CarlaNative.h" #include "CarlaString.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaLv2Utils.hpp" #if defined(USING_JUCE) && defined(CARLA_OS_MAC) # include "AppConfig.h" # include "juce_audio_processors/juce_audio_processors.h" #endif #include "water/containers/Array.h" #include "water/files/File.h" namespace CB = CarlaBackend; using water::Array; using water::File; using water::String; using water::StringArray; // ------------------------------------------------------------------------------------------------------------------- static const char* const gNullCharPtr = ""; static bool isCachedPluginType(const CB::PluginType ptype) { switch (ptype) { case CB::PLUGIN_INTERNAL: case CB::PLUGIN_LV2: case CB::PLUGIN_AU: case CB::PLUGIN_SFZ: return true; default: return false; } } // ------------------------------------------------------------------------------------------------------------------- _CarlaCachedPluginInfo::_CarlaCachedPluginInfo() noexcept : valid(false), category(CB::PLUGIN_CATEGORY_NONE), hints(0x0), audioIns(0), audioOuts(0), cvIns(0), cvOuts(0), midiIns(0), midiOuts(0), parameterIns(0), parameterOuts(0), name(gNullCharPtr), label(gNullCharPtr), maker(gNullCharPtr), copyright(gNullCharPtr) {} // ------------------------------------------------------------------------------------------------------------------- static Array gSFZs; static void findSFZs(const char* const sfzPaths) { CARLA_SAFE_ASSERT_RETURN(sfzPaths != nullptr,); if (sfzPaths[0] == '\0') return; const StringArray splitPaths(StringArray::fromTokens(sfzPaths, CARLA_OS_SPLIT_STR, "")); for (String *it = splitPaths.begin(), *end = splitPaths.end(); it != end; ++it) { Array results; if (File(*it).findChildFiles(results, File::findFiles|File::ignoreHiddenFiles, true, "*.sfz") > 0) gSFZs.addArray(results); } } // ------------------------------------------------------------------------------------------------------------------- static const CarlaCachedPluginInfo* get_cached_plugin_internal(const NativePluginDescriptor& desc) { static CarlaCachedPluginInfo info; info.category = static_cast(desc.category); info.hints = 0x0; if (desc.hints & NATIVE_PLUGIN_IS_RTSAFE) info.hints |= CB::PLUGIN_IS_RTSAFE; if (desc.hints & NATIVE_PLUGIN_IS_SYNTH) info.hints |= CB::PLUGIN_IS_SYNTH; if (desc.hints & NATIVE_PLUGIN_HAS_UI) info.hints |= CB::PLUGIN_HAS_CUSTOM_UI; if (desc.hints & NATIVE_PLUGIN_HAS_INLINE_DISPLAY) info.hints |= CB::PLUGIN_HAS_INLINE_DISPLAY; if (desc.hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS) info.hints |= CB::PLUGIN_NEEDS_FIXED_BUFFERS; if (desc.hints & NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD) info.hints |= CB::PLUGIN_NEEDS_UI_MAIN_THREAD; if (desc.hints & NATIVE_PLUGIN_USES_MULTI_PROGS) info.hints |= CB::PLUGIN_USES_MULTI_PROGS; info.valid = true; info.audioIns = desc.audioIns; info.audioOuts = desc.audioOuts; info.cvIns = desc.cvIns; info.cvOuts = desc.cvOuts; info.midiIns = desc.midiIns; info.midiOuts = desc.midiOuts; info.parameterIns = desc.paramIns; info.parameterOuts = desc.paramOuts; info.name = desc.name; info.label = desc.label; info.maker = desc.maker; info.copyright = desc.copyright; return &info; } // ------------------------------------------------------------------------------------------------------------------- static const CarlaCachedPluginInfo* get_cached_plugin_lv2(Lv2WorldClass& lv2World, Lilv::Plugin& lilvPlugin) { static CarlaCachedPluginInfo info; info.valid = false; bool supported = true; // ---------------------------------------------------------------------------------------------------------------- // text data { static CarlaString suri, sname, smaker, slicense; suri.clear(); sname.clear(); smaker.clear(); slicense.clear(); suri = lilvPlugin.get_uri().as_uri(); if (char* const bundle = lilv_file_uri_parse(lilvPlugin.get_bundle_uri().as_uri(), nullptr)) { File fbundle(bundle); lilv_free(bundle); suri = (fbundle.getFileName() + CARLA_OS_SEP).toRawUTF8() + suri; } else { suri = CARLA_OS_SEP_STR + suri; } #if 0 // def HAVE_FLUIDSYNTH // If we have fluidsynth support built-in, loading these plugins will lead to issues if (suri == "urn:ardour:a-fluidsynth") return &info; if (suri == "http://calf.sourceforge.net/plugins/Fluidsynth") return &info; #endif if (LilvNode* const nameNode = lilv_plugin_get_name(lilvPlugin.me)) { if (const char* const name = lilv_node_as_string(nameNode)) sname = name; lilv_node_free(nameNode); } if (const char* const author = lilvPlugin.get_author_name().as_string()) smaker = author; Lilv::Nodes licenseNodes(lilvPlugin.get_value(lv2World.doap_license)); if (licenseNodes.size() > 0) { if (const char* const license = licenseNodes.get_first().as_string()) slicense = license; } lilv_nodes_free(const_cast(licenseNodes.me)); info.name = sname.buffer(); info.label = suri.buffer(); info.maker = smaker.buffer(); info.copyright = slicense.buffer(); } // ---------------------------------------------------------------------------------------------------------------- // features info.hints = 0x0; if (lilvPlugin.get_uis().size() > 0 || lilvPlugin.get_modgui_resources_directory().as_uri() != nullptr) info.hints |= CB::PLUGIN_HAS_CUSTOM_UI; { Lilv::Nodes lilvRequiredFeatureNodes(lilvPlugin.get_required_features()); LILV_FOREACH(nodes, it, lilvRequiredFeatureNodes) { Lilv::Node lilvFeatureNode(lilvRequiredFeatureNodes.get(it)); const char* const featureURI(lilvFeatureNode.as_uri()); CARLA_SAFE_ASSERT_CONTINUE(featureURI != nullptr); if (! is_lv2_feature_supported(featureURI)) { if (std::strcmp(featureURI, LV2_DATA_ACCESS_URI) == 0 || std::strcmp(featureURI, LV2_INSTANCE_ACCESS_URI) == 0) { // we give a warning about this below continue; } supported = false; carla_stderr("LV2 plugin '%s' requires unsupported feature '%s'", info.label, featureURI); } } lilv_nodes_free(const_cast(lilvRequiredFeatureNodes.me)); } { Lilv::Nodes lilvSupportedFeatureNodes(lilvPlugin.get_supported_features()); LILV_FOREACH(nodes, it, lilvSupportedFeatureNodes) { Lilv::Node lilvFeatureNode(lilvSupportedFeatureNodes.get(it)); const char* const featureURI(lilvFeatureNode.as_uri()); CARLA_SAFE_ASSERT_CONTINUE(featureURI != nullptr); /**/ if (std::strcmp(featureURI, LV2_CORE__hardRTCapable) == 0) { info.hints |= CB::PLUGIN_IS_RTSAFE; } else if (std::strcmp(featureURI, LV2_INLINEDISPLAY__queue_draw) == 0) { info.hints |= CB::PLUGIN_HAS_INLINE_DISPLAY; } else if (std::strcmp(featureURI, LV2_DATA_ACCESS_URI) == 0 || std::strcmp(featureURI, LV2_INSTANCE_ACCESS_URI) == 0) { carla_stderr("LV2 plugin '%s' DSP wants UI feature '%s', ignoring this", info.label, featureURI); } } lilv_nodes_free(const_cast(lilvSupportedFeatureNodes.me)); } // ---------------------------------------------------------------------------------------------------------------- // category info.category = CB::PLUGIN_CATEGORY_NONE; { Lilv::Nodes typeNodes(lilvPlugin.get_value(lv2World.rdf_type)); if (typeNodes.size() > 0) { if (typeNodes.contains(lv2World.class_allpass)) info.category = CB::PLUGIN_CATEGORY_FILTER; if (typeNodes.contains(lv2World.class_amplifier)) info.category = CB::PLUGIN_CATEGORY_DYNAMICS; if (typeNodes.contains(lv2World.class_analyzer)) info.category = CB::PLUGIN_CATEGORY_UTILITY; if (typeNodes.contains(lv2World.class_bandpass)) info.category = CB::PLUGIN_CATEGORY_FILTER; if (typeNodes.contains(lv2World.class_chorus)) info.category = CB::PLUGIN_CATEGORY_MODULATOR; if (typeNodes.contains(lv2World.class_comb)) info.category = CB::PLUGIN_CATEGORY_FILTER; if (typeNodes.contains(lv2World.class_compressor)) info.category = CB::PLUGIN_CATEGORY_DYNAMICS; if (typeNodes.contains(lv2World.class_constant)) info.category = CB::PLUGIN_CATEGORY_OTHER; if (typeNodes.contains(lv2World.class_converter)) info.category = CB::PLUGIN_CATEGORY_UTILITY; if (typeNodes.contains(lv2World.class_delay)) info.category = CB::PLUGIN_CATEGORY_DELAY; if (typeNodes.contains(lv2World.class_distortion)) info.category = CB::PLUGIN_CATEGORY_DISTORTION; if (typeNodes.contains(lv2World.class_dynamics)) info.category = CB::PLUGIN_CATEGORY_DYNAMICS; if (typeNodes.contains(lv2World.class_eq)) info.category = CB::PLUGIN_CATEGORY_EQ; if (typeNodes.contains(lv2World.class_envelope)) info.category = CB::PLUGIN_CATEGORY_DYNAMICS; if (typeNodes.contains(lv2World.class_expander)) info.category = CB::PLUGIN_CATEGORY_DYNAMICS; if (typeNodes.contains(lv2World.class_filter)) info.category = CB::PLUGIN_CATEGORY_FILTER; if (typeNodes.contains(lv2World.class_flanger)) info.category = CB::PLUGIN_CATEGORY_MODULATOR; if (typeNodes.contains(lv2World.class_function)) info.category = CB::PLUGIN_CATEGORY_UTILITY; if (typeNodes.contains(lv2World.class_gate)) info.category = CB::PLUGIN_CATEGORY_DYNAMICS; if (typeNodes.contains(lv2World.class_generator)) info.category = CB::PLUGIN_CATEGORY_OTHER; if (typeNodes.contains(lv2World.class_highpass)) info.category = CB::PLUGIN_CATEGORY_FILTER; if (typeNodes.contains(lv2World.class_limiter)) info.category = CB::PLUGIN_CATEGORY_DYNAMICS; if (typeNodes.contains(lv2World.class_lowpass)) info.category = CB::PLUGIN_CATEGORY_FILTER; if (typeNodes.contains(lv2World.class_mixer)) info.category = CB::PLUGIN_CATEGORY_UTILITY; if (typeNodes.contains(lv2World.class_modulator)) info.category = CB::PLUGIN_CATEGORY_MODULATOR; if (typeNodes.contains(lv2World.class_multiEQ)) info.category = CB::PLUGIN_CATEGORY_EQ; if (typeNodes.contains(lv2World.class_oscillator)) info.category = CB::PLUGIN_CATEGORY_OTHER; if (typeNodes.contains(lv2World.class_paraEQ)) info.category = CB::PLUGIN_CATEGORY_EQ; if (typeNodes.contains(lv2World.class_phaser)) info.category = CB::PLUGIN_CATEGORY_MODULATOR; if (typeNodes.contains(lv2World.class_pitch)) info.category = CB::PLUGIN_CATEGORY_OTHER; if (typeNodes.contains(lv2World.class_reverb)) info.category = CB::PLUGIN_CATEGORY_DELAY; if (typeNodes.contains(lv2World.class_simulator)) info.category = CB::PLUGIN_CATEGORY_OTHER; if (typeNodes.contains(lv2World.class_spatial)) info.category = CB::PLUGIN_CATEGORY_OTHER; if (typeNodes.contains(lv2World.class_spectral)) info.category = CB::PLUGIN_CATEGORY_OTHER; if (typeNodes.contains(lv2World.class_utility)) info.category = CB::PLUGIN_CATEGORY_UTILITY; if (typeNodes.contains(lv2World.class_waveshaper)) info.category = CB::PLUGIN_CATEGORY_DISTORTION; if (typeNodes.contains(lv2World.class_instrument)) { info.category = CB::PLUGIN_CATEGORY_SYNTH; info.hints |= CB::PLUGIN_IS_SYNTH; } } lilv_nodes_free(const_cast(typeNodes.me)); } // ---------------------------------------------------------------------------------------------------------------- // number data info.audioIns = 0; info.audioOuts = 0; info.cvIns = 0; info.cvOuts = 0; info.midiIns = 0; info.midiOuts = 0; info.parameterIns = 0; info.parameterOuts = 0; for (uint i=0, count=lilvPlugin.get_num_ports(); i(supportNodes.me)); } else if (lilvPort.is_a(lv2World.port_event)) { if (lilvPort.supports_event(lv2World.midi_event)) { if (isInput) ++(info.midiIns); else ++(info.midiOuts); } } else if (lilvPort.is_a(lv2World.port_midi)) { if (isInput) ++(info.midiIns); else ++(info.midiOuts); } else { const LilvNode* const symbolNode = lilvPort.get_symbol(); CARLA_SAFE_ASSERT_CONTINUE(symbolNode != nullptr && lilv_node_is_string(symbolNode)); const char* const symbol = lilv_node_as_string(symbolNode); CARLA_SAFE_ASSERT_CONTINUE(symbol != nullptr); supported = false; carla_stderr("LV2 plugin '%s' port '%s' is required but has unsupported type", info.label, symbol); } } if (supported) info.valid = true; return &info; } // ------------------------------------------------------------------------------------------------------------------- #if defined(USING_JUCE) && defined(CARLA_OS_MAC) static juce::StringArray gCachedAuPluginResults; static void findAUs() { if (gCachedAuPluginResults.size() != 0) return; juce::AudioUnitPluginFormat auFormat; gCachedAuPluginResults = auFormat.searchPathsForPlugins(juce::FileSearchPath(), false, false); } static const CarlaCachedPluginInfo* get_cached_plugin_au(const juce::String pluginId) { static CarlaCachedPluginInfo info; static CarlaString sname, slabel, smaker; info.valid = false; juce::AudioUnitPluginFormat auFormat; juce::OwnedArray results; auFormat.findAllTypesForFile(results, pluginId); CARLA_SAFE_ASSERT_RETURN(results.size() > 0, &info); CARLA_SAFE_ASSERT(results.size() == 1); juce::PluginDescription* const desc(results[0]); CARLA_SAFE_ASSERT_RETURN(desc != nullptr, &info); info.category = CB::getPluginCategoryFromName(desc->category.toRawUTF8()); info.hints = 0x0; info.valid = true; if (desc->isInstrument) info.hints |= CB::PLUGIN_IS_SYNTH; if (true) info.hints |= CB::PLUGIN_HAS_CUSTOM_UI; info.audioIns = static_cast(desc->numInputChannels); info.audioOuts = static_cast(desc->numOutputChannels); info.cvIns = 0; info.cvOuts = 0; info.midiIns = desc->isInstrument ? 1 : 0; info.midiOuts = 0; info.parameterIns = 0; info.parameterOuts = 0; sname = desc->name.toRawUTF8(); slabel = desc->fileOrIdentifier.toRawUTF8(); smaker = desc->manufacturerName.toRawUTF8(); info.name = sname; info.label = slabel; info.maker = smaker; info.copyright = gNullCharPtr; return &info; } #endif // ------------------------------------------------------------------------------------------------------------------- static const CarlaCachedPluginInfo* get_cached_plugin_sfz(const File file) { static CarlaCachedPluginInfo info; static CarlaString name, filename; name = file.getFileNameWithoutExtension().toRawUTF8(); name.replace('_',' '); filename = file.getFullPathName().toRawUTF8(); info.category = CB::PLUGIN_CATEGORY_SYNTH; info.hints = CB::PLUGIN_IS_SYNTH; // CB::PLUGIN_IS_RTSAFE info.valid = true; info.audioIns = 0; info.audioOuts = 2; info.cvIns = 0; info.cvOuts = 0; info.midiIns = 1; info.midiOuts = 0; info.parameterIns = 0; info.parameterOuts = 1; info.name = name.buffer(); info.label = filename.buffer(); info.maker = gNullCharPtr; info.copyright = gNullCharPtr; return &info; } // ------------------------------------------------------------------------------------------------------------------- uint carla_get_cached_plugin_count(CB::PluginType ptype, const char* pluginPath) { CARLA_SAFE_ASSERT_RETURN(isCachedPluginType(ptype), 0); carla_debug("carla_get_cached_plugin_count(%i:%s, %s)", ptype, CB::PluginType2Str(ptype), pluginPath); switch (ptype) { case CB::PLUGIN_INTERNAL: { uint32_t count = 0; carla_get_native_plugins_data(&count); return count; } case CB::PLUGIN_LV2: { Lv2WorldClass& lv2World(Lv2WorldClass::getInstance()); lv2World.initIfNeeded(pluginPath); return lv2World.getPluginCount(); } #if defined(USING_JUCE) && defined(CARLA_OS_MAC) case CB::PLUGIN_AU: { findAUs(); return static_cast(gCachedAuPluginResults.size()); } #endif case CB::PLUGIN_SFZ: { findSFZs(pluginPath); return static_cast(gSFZs.size()); } default: return 0; } } const CarlaCachedPluginInfo* carla_get_cached_plugin_info(CB::PluginType ptype, uint index) { carla_debug("carla_get_cached_plugin_info(%i:%s, %i)", ptype, CB::PluginType2Str(ptype), index); switch (ptype) { case CB::PLUGIN_INTERNAL: { uint32_t count = 0; const NativePluginDescriptor* const descs(carla_get_native_plugins_data(&count)); CARLA_SAFE_ASSERT_BREAK(index < count); CARLA_SAFE_ASSERT_BREAK(descs != nullptr); const NativePluginDescriptor& desc(descs[index]); return get_cached_plugin_internal(desc); } case CB::PLUGIN_LV2: { Lv2WorldClass& lv2World(Lv2WorldClass::getInstance()); const LilvPlugin* const cPlugin(lv2World.getPluginFromIndex(index)); CARLA_SAFE_ASSERT_BREAK(cPlugin != nullptr); Lilv::Plugin lilvPlugin(cPlugin); CARLA_SAFE_ASSERT_BREAK(lilvPlugin.get_uri().is_uri()); return get_cached_plugin_lv2(lv2World, lilvPlugin); } #if defined(USING_JUCE) && defined(CARLA_OS_MAC) case CB::PLUGIN_AU: { CARLA_SAFE_ASSERT_BREAK(index < static_cast(gCachedAuPluginResults.size())); return get_cached_plugin_au(gCachedAuPluginResults.strings.getUnchecked(static_cast(index))); } #endif case CB::PLUGIN_SFZ: { CARLA_SAFE_ASSERT_BREAK(index < static_cast(gSFZs.size())); return get_cached_plugin_sfz(gSFZs.getUnchecked(static_cast(index))); } default: break; } static CarlaCachedPluginInfo info; return &info; } // ------------------------------------------------------------------------------------------------------------------- #include "../native-plugins/_data.cpp" // ------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/utils/Information.cpp000066400000000000000000000133571364475620200214400ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaHost.h" #include "CarlaUtils.h" #include "CarlaString.hpp" #ifdef HAVE_FLUIDSYNTH # include #endif #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Weffc++" # pragma GCC diagnostic ignored "-Wsign-conversion" # pragma GCC diagnostic ignored "-Wundef" # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" #endif #ifdef USING_JUCE # include "AppConfig.h" # include "juce_core/juce_core.h" #else # include "rtaudio/RtAudio.h" # include "rtmidi/RtMidi.h" #endif #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic pop #endif #include "water/files/File.h" // ------------------------------------------------------------------------------------------------------------------- const char* carla_get_complete_license_text() { carla_debug("carla_get_complete_license_text()"); static CarlaString retText; if (retText.isEmpty()) { retText = "

This current Carla build is using the following features and 3rd-party code:

" "
    " // Plugin formats "
  • LADSPA plugin support
  • " "
  • DSSI plugin support
  • " "
  • LV2 plugin support
  • " #if defined(USING_JUCE) && (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) "
  • VST2/3 plugin support (using Juce)
  • " #else "
  • VST2 plugin support (using VeSTige header by Javier Serrano Polo)
  • " #endif #if defined(USING_JUCE) && defined(CARLA_OS_MAC) "
  • AU plugin support (using Juce)
  • " #endif // Sample kit libraries #ifdef HAVE_FLUIDSYNTH "
  • FluidSynth library v" FLUIDSYNTH_VERSION " for SF2/3 support
  • " #endif "
  • SFZero module for SFZ support
  • " // misc libs "
  • base64 utilities based on code by Ren\u00E9 Nyffenegger
  • " "
  • liblo library for OSC support
  • " "
  • rtmempool library by Nedko Arnaudov" "
  • serd, sord, sratom and lilv libraries for LV2 discovery
  • " #ifndef USING_JUCE "
  • RtAudio v" RTAUDIO_VERSION " and RtMidi v" RTMIDI_VERSION " for native Audio and MIDI support
  • " #endif // Internal plugins "
  • MIDI Sequencer UI code by Perry Nguyen
  • " // External plugins #ifdef HAVE_EXTERNAL_PLUGINS "
  • Nekobi plugin code based on nekobee by Sean Bolton and others
  • " "
  • VectorJuice and WobbleJuice plugin code by Andre Sklenar
  • " # ifdef HAVE_ZYN_DEPS "
  • ZynAddSubFX plugin code by Mark McCurry and Nasca Octavian Paul
  • " # endif #endif // HAVE_EXTERNAL_PLUGINS // end "
"; } return retText; } const char* carla_get_juce_version() { carla_debug("carla_get_juce_version()"); static CarlaString retVersion; #ifdef USING_JUCE if (retVersion.isEmpty()) { if (const char* const version = juce::SystemStats::getJUCEVersion().toRawUTF8()) retVersion = version+6; else retVersion = "Unknown"; } #endif return retVersion; } const char* const* carla_get_supported_file_extensions() { carla_debug("carla_get_supported_file_extensions()"); // NOTE: please keep in sync with CarlaEngine::loadFile!! static const char* const extensions[] = { // Base types "carxp", "carxs", // plugin files and resources #ifdef HAVE_FLUIDSYNTH "sf2", "sf3", #endif #ifdef HAVE_ZYN_DEPS "xmz", "xiz", #endif #ifdef CARLA_OS_MAC "vst", #else "dll", "so", #endif "vst3", // Audio files #ifdef HAVE_SNDFILE "aif", "aifc", "aiff", "au", "bwf", "flac", "htk", "iff", "mat4", "mat5", "oga", "ogg", "paf", "pvf", "pvf5", "sd2", "sf", "snd", "svx", "vcc", "w64", "wav", "xi", #endif #ifdef HAVE_FFMPEG "3g2", "3gp", "aac", "ac3", "amr", "ape", "mp2", "mp3", "mpc", "wma", # ifndef HAVE_SNDFILE // FFmpeg without sndfile "flac", "oga", "ogg", "w64", "wav", # endif #endif // MIDI files "mid", "midi", // SFZ "sfz", // terminator nullptr }; return extensions; } const char* const* carla_get_supported_features() { carla_debug("carla_get_supported_features()"); static const char* const features[] = { #ifdef HAVE_FLUIDSYNTH "sf2", #endif #ifdef HAVE_HYLIA "link", #endif #ifdef HAVE_LIBLO "osc", #endif #if defined(HAVE_LIBMAGIC) || defined(CARLA_OS_WIN) "bridges", #endif #ifdef HAVE_PYQT "gui", #endif #ifdef USING_JUCE "juce", # if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) "vst3", # endif # if defined(CARLA_OS_MAC) "au", # endif #endif nullptr }; return features; } // ------------------------------------------------------------------------------------------------------------------- #ifndef CARLA_SKIP_HOST_COMMON # include "../CarlaHostCommon.cpp" #endif // ------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/utils/Makefile000066400000000000000000000055161364475620200201050ustar00rootroot00000000000000#!/usr/bin/make -f # Makefile for carla-plugin # # ------------------------- # # Created by falkTX # CWD=../.. include ../Makefile.mk # --------------------------------------------------------------------------------------------------------------------- BUILD_CXX_FLAGS += $(FLUIDSYNTH_FLAGS) # --------------------------------------------------------------------------------------------------------------------- OBJS = \ $(OBJDIR)/CachedPlugins.cpp.o \ $(OBJDIR)/Information.cpp.o \ $(OBJDIR)/PipeClient.cpp.o \ $(OBJDIR)/System.cpp.o \ $(OBJDIR)/Windows.cpp.o TARGETS = $(BINDIR)/libcarla_utils$(LIB_EXT) # --------------------------------------------------------------------------------------------------------------------- LIBS = $(MODULEDIR)/lilv.a LIBS += $(MODULEDIR)/water.files.a ifeq ($(USING_JUCE),true) LIBS += $(MODULEDIR)/juce_audio_basics.a LIBS += $(MODULEDIR)/juce_audio_processors.a LIBS += $(MODULEDIR)/juce_core.a LIBS += $(MODULEDIR)/juce_data_structures.a LIBS += $(MODULEDIR)/juce_events.a LIBS += $(MODULEDIR)/juce_graphics.a LIBS += $(MODULEDIR)/juce_gui_basics.a ifeq ($(MACOS),true) LIBS += $(MODULEDIR)/juce_gui_extra.a endif endif LINK_FLAGS += $(LILV_LIBS) LINK_FLAGS += $(WATER_LIBS) ifeq ($(HAVE_X11),true) LINK_FLAGS += $(X11_LIBS) endif ifneq ($(HAIKU),true) LINK_FLAGS += -lpthread endif ifeq ($(USING_JUCE),true) LINK_FLAGS += $(JUCE_AUDIO_BASICS_LIBS) LINK_FLAGS += $(JUCE_AUDIO_PROCESSORS_LIBS) LINK_FLAGS += $(JUCE_CORE_LIBS) LINK_FLAGS += $(JUCE_DATA_STRUCTURES_LIBS) LINK_FLAGS += $(JUCE_EVENTS_LIBS) LINK_FLAGS += $(JUCE_GRAPHICS_LIBS) LINK_FLAGS += $(JUCE_GUI_BASICS_LIBS) ifeq ($(MACOS),true) LINK_FLAGS += $(JUCE_GUI_EXTRA_LIBS) endif endif # --------------------------------------------------------------------------------------------------------------------- all: $(TARGETS) # --------------------------------------------------------------------------------------------------------------------- clean: rm -f $(OBJS) $(TARGETS) debug: $(MAKE) DEBUG=true # --------------------------------------------------------------------------------------------------------------------- $(BINDIR)/libcarla_utils$(LIB_EXT): $(OBJS) $(LIBS) -@mkdir -p $(BINDIR) @echo "Linking libcarla_utils$(LIB_EXT)" @$(CXX) $(OBJS) $(LIBS_START) $(LIBS) $(LIBS_END) $(LINK_FLAGS) $(LINK_FLAGS) $(SHARED) -o $@ # --------------------------------------------------------------------------------------------------------------------- ifeq ($(MACOS),true) $(OBJDIR)/Windows.cpp.o: Windows.cpp -@mkdir -p $(OBJDIR) @echo "Compiling $<" @$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@ endif $(OBJDIR)/%.cpp.o: %.cpp -@mkdir -p $(OBJDIR) @echo "Compiling $<" @$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ -include $(OBJS:%.o=%.d) # --------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/utils/PipeClient.cpp000066400000000000000000000202761364475620200212050ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaUtils.h" #include "CarlaPipeUtils.hpp" #ifdef CARLA_OS_HAIKU # include "CarlaStringList.hpp" # define CARLA_PIPE_WITHOUT_CALLBACK #endif namespace CB = CarlaBackend; // ------------------------------------------------------------------------------------------------------------------- class ExposedCarlaPipeClient : public CarlaPipeClient { public: ExposedCarlaPipeClient(const CarlaPipeCallbackFunc callbackFunc, void* const callbackPtr) noexcept : CarlaPipeClient(), fCallbackFunc(callbackFunc), fCallbackPtr(callbackPtr), #ifdef CARLA_PIPE_WITHOUT_CALLBACK fMsgsReceived(), fLastMsgReceived(nullptr), #endif fLastReadLine(nullptr) { CARLA_SAFE_ASSERT(fCallbackFunc != nullptr); } ~ExposedCarlaPipeClient() override { if (fLastReadLine != nullptr) { delete[] fLastReadLine; fLastReadLine = nullptr; } #ifdef CARLA_PIPE_WITHOUT_CALLBACK if (fLastMsgReceived != nullptr) { delete[] fLastMsgReceived; fLastMsgReceived = nullptr; } #endif } const char* idlePipeAndReturnMessage() noexcept { CarlaPipeClient::idlePipe(); #ifdef CARLA_PIPE_WITHOUT_CALLBACK if (fMsgsReceived.count() == 0) return nullptr; delete[] fLastMsgReceived; fLastMsgReceived = fMsgsReceived.getAndRemoveFirst(); return fLastMsgReceived; #else return nullptr; #endif } const char* readlineblock(const uint timeout) noexcept { #ifdef CARLA_PIPE_WITHOUT_CALLBACK if (fMsgsReceived.count() != 0) { delete[] fLastMsgReceived; fLastMsgReceived = fMsgsReceived.getAndRemoveFirst(); return fLastMsgReceived; } #endif delete[] fLastReadLine; fLastReadLine = CarlaPipeClient::_readlineblock(true, 0, timeout); return fLastReadLine; } bool readlineblock_bool(const uint timeout) noexcept { #ifdef CARLA_PIPE_WITHOUT_CALLBACK if (fMsgsReceived.count() != 0) { delete[] fLastMsgReceived; fLastMsgReceived = fMsgsReceived.getAndRemoveFirst(); return fLastMsgReceived != nullptr && std::strcmp(fLastMsgReceived, "true") == 0; } #endif if (const char* const line = CarlaPipeClient::_readlineblock(false, 0, timeout)) return std::strcmp(line, "true") == 0; return false; } int readlineblock_int(const uint timeout) noexcept { #ifdef CARLA_PIPE_WITHOUT_CALLBACK if (fMsgsReceived.count() != 0) { delete[] fLastMsgReceived; fLastMsgReceived = fMsgsReceived.getAndRemoveFirst(); return fLastMsgReceived != nullptr && std::strcmp(fLastMsgReceived, "true") == 0; } #endif if (const char* const line = CarlaPipeClient::_readlineblock(false, 0, timeout)) return std::atoi(line); return 0; } double readlineblock_float(const uint timeout) noexcept { #ifdef CARLA_PIPE_WITHOUT_CALLBACK if (fMsgsReceived.count() != 0) { delete[] fLastMsgReceived; fLastMsgReceived = fMsgsReceived.getAndRemoveFirst(); return fLastMsgReceived != nullptr && std::strcmp(fLastMsgReceived, "true") == 0; } #endif if (const char* const line = CarlaPipeClient::_readlineblock(false, 0, timeout)) return std::atof(line); return 0.0; } bool msgReceived(const char* const msg) noexcept override { #ifdef CARLA_PIPE_WITHOUT_CALLBACK fMsgsReceived.append(msg); #else if (fCallbackFunc != nullptr) { try { fCallbackFunc(fCallbackPtr, msg); } CARLA_SAFE_EXCEPTION("msgReceived"); } #endif return true; } private: const CarlaPipeCallbackFunc fCallbackFunc; void* const fCallbackPtr; #ifdef CARLA_PIPE_WITHOUT_CALLBACK CarlaStringList fMsgsReceived; const char* fLastMsgReceived; #endif const char* fLastReadLine; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExposedCarlaPipeClient) }; CarlaPipeClientHandle carla_pipe_client_new(const char* argv[], CarlaPipeCallbackFunc callbackFunc, void* callbackPtr) { carla_debug("carla_pipe_client_new(%p, %p, %p)", argv, callbackFunc, callbackPtr); ExposedCarlaPipeClient* const pipe = new ExposedCarlaPipeClient(callbackFunc, callbackPtr); if (! pipe->initPipeClient(argv)) { delete pipe; return nullptr; } return pipe; } const char* carla_pipe_client_idle(CarlaPipeClientHandle handle) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr); return ((ExposedCarlaPipeClient*)handle)->idlePipeAndReturnMessage(); } bool carla_pipe_client_is_running(CarlaPipeClientHandle handle) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, false); return ((ExposedCarlaPipeClient*)handle)->isPipeRunning(); } void carla_pipe_client_lock(CarlaPipeClientHandle handle) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr,); return ((ExposedCarlaPipeClient*)handle)->lockPipe(); } void carla_pipe_client_unlock(CarlaPipeClientHandle handle) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr,); return ((ExposedCarlaPipeClient*)handle)->unlockPipe(); } const char* carla_pipe_client_readlineblock(CarlaPipeClientHandle handle, uint timeout) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr); return ((ExposedCarlaPipeClient*)handle)->readlineblock(timeout); } bool carla_pipe_client_readlineblock_bool(CarlaPipeClientHandle handle, uint timeout) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, false); return ((ExposedCarlaPipeClient*)handle)->readlineblock_bool(timeout); } int carla_pipe_client_readlineblock_int(CarlaPipeClientHandle handle, uint timeout) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0); return ((ExposedCarlaPipeClient*)handle)->readlineblock_int(timeout); } double carla_pipe_client_readlineblock_float(CarlaPipeClientHandle handle, uint timeout) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0.0); return ((ExposedCarlaPipeClient*)handle)->readlineblock_float(timeout); } bool carla_pipe_client_write_msg(CarlaPipeClientHandle handle, const char* msg) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, false); return ((ExposedCarlaPipeClient*)handle)->writeMessage(msg); } bool carla_pipe_client_write_and_fix_msg(CarlaPipeClientHandle handle, const char* msg) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, false); return ((ExposedCarlaPipeClient*)handle)->writeAndFixMessage(msg); } bool carla_pipe_client_flush(CarlaPipeClientHandle handle) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, false); return ((ExposedCarlaPipeClient*)handle)->flushMessages(); } bool carla_pipe_client_flush_and_unlock(CarlaPipeClientHandle handle) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr, false); ExposedCarlaPipeClient* const pipe = (ExposedCarlaPipeClient*)handle; const bool ret = pipe->flushMessages(); pipe->unlockPipe(); return ret; } void carla_pipe_client_destroy(CarlaPipeClientHandle handle) { CARLA_SAFE_ASSERT_RETURN(handle != nullptr,); carla_debug("carla_pipe_client_destroy(%p)", handle); ExposedCarlaPipeClient* const pipe = (ExposedCarlaPipeClient*)handle; pipe->closePipeClient(); delete pipe; } // ------------------------------------------------------------------------------------------------------------------- #include "CarlaPipeUtils.cpp" // ------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/utils/System.cpp000066400000000000000000000023741364475620200204340ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2018 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaUtils.h" #include "CarlaThread.hpp" // ------------------------------------------------------------------------------------------------------------------- void carla_fflush(bool err) { std::fflush(err ? stderr : stdout); } void carla_fputs(bool err, const char* string) { std::fputs(string, err ? stderr : stdout); } void carla_set_process_name(const char* name) { carla_debug("carla_set_process_name(\"%s\")", name); CarlaThread::setCurrentThreadName(name); } // ------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/backend/utils/Windows.cpp000066400000000000000000000052721364475620200206020ustar00rootroot00000000000000/* * Carla Plugin Host * Copyright (C) 2011-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "CarlaUtils.h" #include "CarlaUtils.hpp" #ifdef CARLA_OS_MAC # import #endif #ifdef HAVE_X11 # include #endif namespace CB = CarlaBackend; // ------------------------------------------------------------------------------------------------------------------- int carla_cocoa_get_window(void* nsViewPtr) { CARLA_SAFE_ASSERT_RETURN(nsViewPtr != nullptr, 0); #ifdef CARLA_OS_MAC NSView* const nsView = (NSView*)nsViewPtr; return [[nsView window] windowNumber]; #else return 0; #endif } void carla_x11_reparent_window(uintptr_t winId1, uintptr_t winId2) { CARLA_SAFE_ASSERT_RETURN(winId1 != 0,); CARLA_SAFE_ASSERT_RETURN(winId2 != 0,); #ifdef HAVE_X11 if (::Display* const disp = XOpenDisplay(nullptr)) { XReparentWindow(disp, winId1, winId2, 0, 0); XMapWindow(disp, winId1); XCloseDisplay(disp); } #endif } void carla_x11_move_window(uintptr_t winId, int x, int y) { CARLA_SAFE_ASSERT_RETURN(winId != 0,); #ifdef HAVE_X11 if (::Display* const disp = XOpenDisplay(nullptr)) { XMoveWindow(disp, winId, x, y); XCloseDisplay(disp); } #else // unused return; (void)x; (void)y; #endif } int* carla_x11_get_window_pos(uintptr_t winId) { static int pos[4]; if (winId == 0) { pos[0] = 0; pos[1] = 0; pos[2] = 0; pos[3] = 0; } #ifdef HAVE_X11 else if (::Display* const disp = XOpenDisplay(nullptr)) { int x, y; Window child; XWindowAttributes xwa; XTranslateCoordinates(disp, winId, XRootWindow(disp, 0), 0, 0, &x, &y, &child); XGetWindowAttributes(disp, winId, &xwa); XCloseDisplay(disp); pos[0] = x - xwa.x; pos[1] = y - xwa.y; pos[2] = xwa.x; pos[3] = xwa.y; } #endif else { pos[0] = 0; pos[1] = 0; pos[2] = 0; pos[3] = 0; } return pos; } // ------------------------------------------------------------------------------------------------------------------- Carla-2.1/source/bridges-plugin/000077500000000000000000000000001364475620200166225ustar00rootroot00000000000000Carla-2.1/source/bridges-plugin/CarlaBridgePlugin.cpp000066400000000000000000000463201364475620200226510ustar00rootroot00000000000000/* * Carla Bridge Plugin * Copyright (C) 2012-2019 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef BUILD_BRIDGE # error This file should not be compiled if not building bridge #endif #include "CarlaEngine.hpp" #include "CarlaHost.h" #include "CarlaBackendUtils.hpp" #include "CarlaJuceUtils.hpp" #include "CarlaMainLoop.hpp" #include "CarlaMIDI.h" #ifdef CARLA_OS_UNIX # include #endif #ifdef CARLA_OS_LINUX # include # define SCHED_RESET_ON_FORK 0x40000000 #endif #ifdef CARLA_OS_WIN # include # include #endif #ifdef HAVE_X11 # include #endif #ifdef USING_JUCE # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Weffc++" # pragma GCC diagnostic ignored "-Wsign-conversion" # pragma GCC diagnostic ignored "-Wundef" # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" # endif # include "AppConfig.h" # if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) # include "juce_gui_basics/juce_gui_basics.h" # else # include "juce_events/juce_events.h" # endif # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic pop # endif #endif #include "jackbridge/JackBridge.hpp" #include "water/files/File.h" using CarlaBackend::CarlaEngine; using CarlaBackend::EngineCallbackOpcode; using CarlaBackend::EngineCallbackOpcode2Str; using CarlaBackend::runMainLoopOnce; using water::CharPointer_UTF8; using water::File; using water::String; // ------------------------------------------------------------------------- static bool gIsInitiated = false; static volatile bool gCloseNow = false; static volatile bool gSaveNow = false; #if defined(CARLA_OS_UNIX) static void closeSignalHandler(int) noexcept { gCloseNow = true; } static void saveSignalHandler(int) noexcept { gSaveNow = true; } #elif defined(CARLA_OS_WIN) static BOOL WINAPI winSignalHandler(DWORD dwCtrlType) noexcept { if (dwCtrlType == CTRL_C_EVENT) { gCloseNow = true; return TRUE; } return FALSE; } #endif static void initSignalHandler() { #if defined(CARLA_OS_UNIX) struct sigaction sig; carla_zeroStruct(sig); sig.sa_handler = closeSignalHandler; sig.sa_flags = SA_RESTART; sigemptyset(&sig.sa_mask); sigaction(SIGTERM, &sig, nullptr); sigaction(SIGINT, &sig, nullptr); sig.sa_handler = saveSignalHandler; sig.sa_flags = SA_RESTART; sigemptyset(&sig.sa_mask); sigaction(SIGUSR1, &sig, nullptr); #elif defined(CARLA_OS_WIN) SetConsoleCtrlHandler(winSignalHandler, TRUE); #endif } // ------------------------------------------------------------------------- static String gProjectFilename; static void gIdle() { carla_engine_idle(); if (gSaveNow) { gSaveNow = false; if (gProjectFilename.isNotEmpty()) { if (! carla_save_plugin_state(0, gProjectFilename.toRawUTF8())) carla_stderr("Plugin preset save failed, error was:\n%s", carla_get_last_error()); } } } // ------------------------------------------------------------------------- #if defined(USING_JUCE) && (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) class CarlaJuceApp : public juce::JUCEApplication, private juce::Timer { public: CarlaJuceApp() {} ~CarlaJuceApp() {} void initialise(const juce::String&) override { startTimer(8); } void shutdown() override { gCloseNow = true; stopTimer(); } const juce::String getApplicationName() override { return "CarlaPlugin"; } const juce::String getApplicationVersion() override { return CARLA_VERSION_STRING; } void timerCallback() override { gIdle(); if (gCloseNow) { quit(); gCloseNow = false; } } }; static juce::JUCEApplicationBase* juce_CreateApplication() { return new CarlaJuceApp(); } #endif // ------------------------------------------------------------------------- class CarlaBridgePlugin { public: CarlaBridgePlugin(const bool useBridge, const char* const clientName, const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName) : fEngine(nullptr), #ifdef USING_JUCE fJuceInitialiser(), #endif fUsingBridge(false), fUsingExec(false) { CARLA_ASSERT(clientName != nullptr && clientName[0] != '\0'); carla_debug("CarlaBridgePlugin::CarlaBridgePlugin(%s, \"%s\", %s, %s, %s, %s)", bool2str(useBridge), clientName, audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); carla_set_engine_callback(callback, this); if (useBridge) { carla_engine_init_bridge(audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName, clientName); } else if (std::getenv("CARLA_BRIDGE_DUMMY") != nullptr) { carla_engine_init("Dummy", clientName); } else { carla_engine_init("JACK", clientName); } fEngine = carla_get_engine(); } ~CarlaBridgePlugin() { carla_debug("CarlaBridgePlugin::~CarlaBridgePlugin()"); if (! fUsingExec) carla_engine_close(); } bool isOk() const noexcept { return (fEngine != nullptr); } // --------------------------------------------------------------------- void exec(const bool useBridge) { fUsingBridge = useBridge; fUsingExec = true; if (! useBridge) { const CarlaPluginInfo* const pInfo(carla_get_plugin_info(0)); CARLA_SAFE_ASSERT_RETURN(pInfo != nullptr,); gProjectFilename = CharPointer_UTF8(pInfo->name); gProjectFilename += ".carxs"; if (! File::isAbsolutePath(gProjectFilename)) gProjectFilename = File::getCurrentWorkingDirectory().getChildFile(gProjectFilename).getFullPathName(); if (File(gProjectFilename).existsAsFile()) { if (carla_load_plugin_state(0, gProjectFilename.toRawUTF8())) carla_stdout("Plugin state loaded successfully"); else carla_stderr("Plugin state load failed, error was:\n%s", carla_get_last_error()); } else { carla_stdout("Previous plugin state in '%s' is non-existent, will start from default state", gProjectFilename.toRawUTF8()); } } gIsInitiated = true; #if defined(USING_JUCE) && (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) # ifndef CARLA_OS_WIN static const int argc = 0; static const char* argv[] = {}; # endif juce::JUCEApplicationBase::createInstance = &juce_CreateApplication; juce::JUCEApplicationBase::main(JUCE_MAIN_FUNCTION_ARGS); #else for (; runMainLoopOnce() && ! gCloseNow;) { gIdle(); # if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) // MacOS and Win32 have event-loops to run, so minimize sleep time carla_msleep(1); # else carla_msleep(5); # endif } #endif carla_engine_close(); } // --------------------------------------------------------------------- protected: void handleCallback(const EngineCallbackOpcode action, const int value1, const int, const int, const float, const char* const) { CARLA_BACKEND_USE_NAMESPACE; switch (action) { case ENGINE_CALLBACK_ENGINE_STOPPED: case ENGINE_CALLBACK_PLUGIN_REMOVED: case ENGINE_CALLBACK_QUIT: gCloseNow = true; break; case ENGINE_CALLBACK_UI_STATE_CHANGED: if (gIsInitiated && value1 != 1 && ! fUsingBridge) gCloseNow = true; break; default: break; } } private: const CarlaEngine* fEngine; #ifdef USING_JUCE const juce::ScopedJuceInitialiser_GUI fJuceInitialiser; #endif bool fUsingBridge; bool fUsingExec; static void callback(void* ptr, EngineCallbackOpcode action, unsigned int pluginId, int value1, int value2, int value3, float valuef, const char* valueStr) { carla_debug("CarlaBridgePlugin::callback(%p, %i:%s, %i, %i, %i, %i, %f, \"%s\")", ptr, action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3, static_cast(valuef), valueStr); // ptr must not be null CARLA_SAFE_ASSERT_RETURN(ptr != nullptr,); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // pluginId must be 0 (first), except for patchbay things if (action < CarlaBackend::ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED || action > CarlaBackend::ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED) #endif { CARLA_SAFE_ASSERT_UINT_RETURN(pluginId == 0, pluginId,); } return ((CarlaBridgePlugin*)ptr)->handleCallback(action, value1, value2, value3, valuef, valueStr); } CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgePlugin) }; // ------------------------------------------------------------------------- int main(int argc, char* argv[]) { // --------------------------------------------------------------------- // Check argument count if (argc != 4 && argc != 5) { carla_stdout("usage: %s

U ICdJẌp*2w.2 j7_!`LoV ^A N{2nɥ bW=O\԰0_Wq5~ySkf,!aU2bcV5m*;Jol@IÕl_{ъo^bbϖ&m|mz'ȧ'jDhݨYS@GEi57<7O.%9ZI,r?ٌh_6#(QI^lW?9߫f iQw8~1W˹Inn`a[@ь y38熩aܶq泎P`UR~h~g|"Q z f)c\!2o8+.h&T^%Dz ;5'<OJ[ G5/S<*@ IjתU :=Joi3̵K(vud v~I華 wV]LdjFLW |% J[fP@3ݩ@L8^q>-l/ 5)r*;#K?R0 '1/3/hVWaf]R$ `x37C!y)=n8DwFo+CE1Io`pT8(> ;l>`< ;IJ7P 0E~--l_!_~ ̞FLj>f7Ŭ9E՝[|)- lB9~ _Њ~`KZ]4ɟPJ[ ltم@?a>p8~aҟpsABIo"acQE$y|`ʕK>zWL}yR4=f`П/=EK ê_ -Xhʢ^hI>@yS$ ퟥ0CZ? 橍?m9ZohHRb&m| + %W>[7vPS>p7^sFX_*h_?\'_ppiZX"^u`37R~#0>s`O3T^NWTs+wZETUwŪÿ` {_fL<#\'[7~ӮeaADXV7$Bi5Ι0p0N{l"7m[|26wZCtg٢Un1AiGn(a$IX Wk_3>`?rGG*@;PwYa[+Km׸k>0zX D +IsdfL̮o(78L\!i8U3L7|`]dj\co?aC>XuS | |m~@_p۾|p¥?3?WWg51#~iNvu~#)bs@0dz}dӰjïv5skeWMȲ6~-N?C~OA)5 \kڗ?󂳎_oO>N{޺o6>p;Z x"ySY;xwX|e̡BKac?JK&"| [g=^1b<::GKA 0{W$FG:u#l4)#8㣅 gڭʋgw %q%w+|`+>0 %tX mo=//<0lߑF9mka2k^pf䯜H`}%Y>0ik_a\D%@Ӧ~`N'Ÿp йnt{ P0q O3i{y o7@@\ 1t F@o?j~;pԫө \?`.H/P87| ڶ~6)]ĩ_]V~&V8P|p3 nj/q4Uhoꑽ*}L0RzpZ]hNpUjwx)ނ̩3{WӾsZ %QǛ՛f9oC/]6'Ȝ3&M!׫3dnZmrg˷8y:ޖůs4Q,q'_$|Mia&-PP^%gO^nܸ۶\p5_܊KzHiJڸyQj@~  Әnd8Ɠ]5?pݩYeC0tsnWz&AdzS[SKoj'cE_eE5W]n-@o.x5l9MsP@;/Ӝ/ULW})`XWuwm~@Gr}MPՇ+6Y0z=+!wQk9{,\OOHYT[ >AΔ.#?>*! >@`yzy5.vO0\rPJ&u<p6t$|MM,K6POA Qɘt `o4`:36tV " X|r=zGg;($^1hڄ4 o}+48E[|`/F>NOp,@W@@a>p8~qڟ/رD"}*`EkYyvy~л}-!BpٰVڣ7F?VϘ/gyn/l3D F(\XS7Fc%/u=s|bT!z  9f0}ޞsnrsul\XDVJ|B? j,T^+F10Ou*0dEӮ ѝe _|3ya)~5ax~sF)|ĸb/"ywQYĒ yB6a4Y4n[@1+J]1(mڼ"pn ֳ6Y֝Prm*΍-dwX~PAY̌ l N(@ռ!4R|A 83q>д쌂gt(O,WXc;534_?aӿhڄvu> >к~@?Mf r@Ilr{I>t-:8p1l8ЋzULqG9Lc%jn[i'R!]@p1)_w88:[˓ Z6NL LoTs_N;9 *3b^)ymhģY,vPO (97ozkï>hcV͓OpGs4Y=f1yE6uɫ4߶&+IDATxq^?theGWլjOĢълFa3Fn-]S;EʐJ^5l"IF0r'/-oNn0]obIU}~Y5/Po˰.`풉|"+(cVq=8dϪM)2lOx3j#aqsZ?0f<??͹kZU73ݙzYi w 1Bs\09F,!gsU2h̫4گ6 Vs$O,`A/=zhwvh"K}oq67bzݖ `]Cj.n1j:>k>0d՗97Dw-zS>ƑU7h+6r&+8J}Q;3@GfuNBz箽~~MtRhYOuԏ^y rS]f`NR~@~pK?K~ $@~ॷH-@,;9º޾jM? 3tOan#p~6uz v{Ÿ}> @{>㐄.8t %^Q(aU tf\s)_/@&czCd7l jt93U x{/D}DzCK,Y8`k~gGaQځ ,b6ޖVq4Ġ)57sxk풚x';ȆsCjNXUnS{v0u#?yN:nC&"QB;'ouN0S3͈sg;n#ZqDr"Q"{F \_'?,in٭g=Q=ӽ[ewPXA;%^1/F$s NdG՟8 I)2+Wo(]K1܈L0I?,8Ίo 蝏IT!WZFcDt/Tx)U2q ,>0jLk M$y7#S jk%\ ? tld}_*8UwOBG||x ؉O?`Tusk'U? y3+{Owv?@GRΘU sW Ƽ0H"7[rpp婒fhʄRKzEF(n,H=M%7d΁d32,>p`8 RGy>oXA9KD+kt۠H_ m>=> Ltqڿ,>`5\A,ƞ8cڔt )%;ht\$VB?倒+a`-ևW}} ꔻ& @(2jV`' jb |HBїHT!DbfD"!sPK0K>j:^Mr٢;,Kׁ?ex{fM|287L$"6#-_ls ק۹v)j~A {iSR-Tjl9NxG+YvAn2lz1x ]ZSj^]ߐkr"yVp '7!Sq3%!y-07SUL3"zv[R*P/3.y]4QJfB 4KotQf=OT!J^OE3?j#WmR\ >t;31 fi oG_{>Ә|\GgZpun5Ri2icG-U C%͊?4~m 1f7q_[H$}]nSLY|[[Fd>~ӓG5r8-&5N7[#~0JUxCpuG-4Dugsm{l> %G~kg[`̸fusV8هxe"Iԕ%1/BK>0sU2MfDppُV֜A_ m>s_ $hl1_5TPb|[z35 |OͱlM] 6Xu!.DnK,j[?u\?.>aŅgN vKdzGVaF͈V.0l]2&9}ɒܟs5ƫ99?\:;%n7߇uem>c:ko_3+D~ځ`y{]g/j/XWlH%˗'dL|Tȟϸq?'?0>j> #a3oMmU7mկ>>)k=fe wj^47fon)L|n:av<*iDtPs2|m2|ysisvZ?XE_ܫ=ݻUzS4nqoK| f?i`-ɘD&6{Kӌ||`Ȕ ~owD m/[C^^y߹Ԧˋs{ٗsj@(1Mt~KhJ( Kq"a,U9t~5;Л"g=)UuS@ 9 @~d}jǓPZv9bfSs|`ռ\E炘B @ܤ J&b%PIѯ0H jnE\NYV;tQ</xOu4/PE~1 r쑀>]tpiȟU<#en]Ys,6[-{~Njad"QER"K& d"Dr3I]%{mٌ?(I_m;$h|Vx݆H'\O}}{ I}T7G}|8$wk֛"`@ьn}k&43. 0DZlG'.ܞ ;I[C?Pep"|p=ز\ps8UeQj+Mlةqk/*涩H6)dZ]p^:BKGܛYdr+DoW!c^L}+&8h}| 2 Mc%:ړxN}c>9Py3ozSt;6ZGv[փMw'.4rSA %4!ttV<6&®Kc8Ps]UbhngYsH9)nk@?@xaёpE&yQ tpͥ;)W&X8었${V#4:f<,>B2d⬕.:d30Θڶx8mxŒ}NZo .;mn#P*9YC,>`65;Qҭq0#N>`T[m9C^<%0lpmM tq~AvXu%G|`y'JW `B|$(*7LqӬe1KS cێ>"Z[f"KɘV۴'VΧc>+^%?! TmkM J~] `V9/+\=xJfr%}O Pn05fjlj0\NdLP3 m53ۖPgijwjNfA%jqNV PhsC mH[C32>Ѯ_0f_%gĺ~x:rl$keD^9t`~Q7JWJ?|/ Bn;\zhQLQ.tX|#LQ_GT_"כ >$*}xVhE('SU `F{-;HbELj?%qrX3dM %r~ND.LEg ;K&΁T>ݥ~|/^VPpku!Q%'>7i9|!-~@_f!CLX4ڭ  l{oCOpmWw.%+&T@;O~4-W|?>P N}|fg3o# nqD"# > p׌j=gSM8p%',Ҏ7EM-<N[/ 7HNtt邧/$ޞ9g'mHҾbNlOhR IjNf/k?2J ~TQ~U[$tWw[ztoH@m:(vr5_pԴ#ewj8tQeT"bH-({rOF}mv~-T#]͚ ;[~ɞRbeVh/{׬Y_s%r$e+*@R~U=0Ҳ>0fCKf9 Mrdž)K-|?~x / b C%{e%ףJ?jspNwOdwXyX:CVsW% Fj+3n;;q^yQ~3`JDx´V >Ѐ$> L3 7+gZ)@%i{p4/I/ɞY{=N}l> SnakD:xdN)x#k |/Qx, I|4b5B?!TZO3yTŸPs0F1@!S?`:h/|$5J$vw`Fi n l#5'?{INzE>O{_}3 Cܓ=?,p |oإ|~.hlHgd%@=HK),GfTY=/ vD*H̴b m?aWf-@mM2,@ ljL_:)wkV_a6g1c z?ՠlku?/|՜ImXUmY3hվgOdNku-5OE, /~~pRX~0cZ]e:e?d jw?&#jNƉ!)wq_ ,+GΗ_3?A7ߗvnG͚Ձa3Ջ €nT%ӄ.z}dQWu^%;^Z]pk٢vEּw.SsZ=o4CѬ}G nP%¨=h>Wz =32{ we̼Kg<~X؋?qO@_),^io"g]{.q_bJ+qFc pf̑v浚:_<G?\׀lgM$OvN80"IGD"@8@$gy`)idb%|Nn)%yE@3]8_8RA[?@Ht 0D³S\]4ƣ"A~$ +N Mh6B7pd ӟiuCX]]?>fH=7/J>  }PE:Me9d5Jz^.K?^ '(o0)EmM 4l57sSZy`Qԫ_7E |r?)J F0U"f ǙE3F &Y{Me.o}F PLrO;Mi0`Q>&_>73n ,W™Ǵ?,~|k۩('zCcw/̜gu0M1Vmk2n?O:Yl6ⶐ_sSZ; H/tgN3D,/fg\`DKS _p'@Lg2~xl]g<77\AтzR'퀂3f8B{@S44 s.IDmK7Z~>>Pyu?x^՝[|G߂cD .(ْ-Z]}aW@tG|_pWQJ|_V]y g汄d!ӫ9ZO]2KWAKZ#!7}ExwC&_wN&--B-#frX-dh0a5^pkэX:C8/2NQs)| Vvp[Ѕ~bJeK͐>{'3"#O : Z-^_/Q.A j$*M?Ц~@-͈Dz?ig:,@ީ'*G)3h5[>_e$%VtߟYs0/Wf]U3 WjnM5N{K,cV=3o̱9.j>= T:q=rzX7׵: o`1-+V݀/ם c8ރVNjv5ף.#;}̋ pCnD _~vg8$QJMmO%rp饒ǍGƥDGD‡c;>js&$NzQIz"kHQA{^EE(lBlBI6׋Ivfg31d݈z}8(qLkq1nBß\)K1 i7xۙFV9?!j^8֗ӟp(0U=n˷zMh#Y_p2 Q>{x' 5@j>b M?t&0R>T0 5 ,@Grܑw$:0S NL%X?%FE?K$| 4& l|C? @VY_#`A;󖋩,iN>x~06˨/}ATMUz}AU cLz5A* 8-PCRQ_qcJ$).7Yv];ق^[?lKU| 8Y曕*|E`|{{Z-eM+Ӕ-͝/ٻ]/H h|3g4䎼< Qx۪vTY)˖ !ɯ{/nں|mi.$\MxNBK>i:`&a^w޻ T螱Y{Vo:r"qJT៺w}jy=|M =#\0|&.Yl0O(~@li{ @oF4.ɖ0>I8^hm.EJ+4?WrEI;@:Ʝҍ gҽ,`0*SRt@yߎkm8A߾e*=ܷ/x55pga}s`7Ij8䎭{$kꬳ7yJ3B DF _6~'ػtG6q|<3S՛ KEl~պJb@*<zOsC)[S5qJ =W|t&pSog ?P <<0a5\JY蚙{W$Ub&@LQ,5R5 /eҘWl1Xx>@/q^H=rDBxP* jgʗ;_NF";D3WzRSهu~='8m F0(L?p#Ohji؀h\V}}m('G .)+Ys;W?E#^7}(QnZ&?xTU1ݑj>ڢ: Rz/Ɇ_ K<]t{m)TDlp[ՎZ)yaɯvc/ݧ .)g/xbK @Hjdq= MnF%~7Pp?+sgyOʓaXKig-fX5RZ5+ۄ{o:(.H<=$/pɖw0bRBd/ D&IL*ԘQLH#)K9QoT<[[gkmRuh%Sz L b?t?غr;S5cb^@>`[W޸X+o׍ޥC3i8ji^Pn q &L~\?27J >$thjB/k tnO !,kG ÞPяC?R0XTxS^1]&+mvq/c X>xo(U?!1=WIaRfayCB\N$.V?ޭ;`{Cd -SH<jVKU@qY@MM $~s͜ŹHh? `V[iRߓ4bKnA aӆ!:eLT?vF ;.ڟ-QK@8N$@yidoQ_,_tng/(+L8Sm%YnSΊWHNEz}~eENz,z @',]*8b;kx,-~YLK4!Wmu=u ,LIJ8R=kij3Ǎ]l)v.l~ Tpʲ U,L33Y`0Uj'[,,9@ t@56i<@~mlҁK ]42& N_G+Ukh1UgoӿW9ցLS.c2 [wa)ԕ`<Vq4GV @l F M`"ʅ&E~)N<(u@r|L< "rnPb|$@~%pxz_3E  T1 ⅚5Y='zW q|` | 高?W_V]z5U| TE6\Ơ`Yt}Ue: pibD| od6|-Ɵp*T|hr?#A,|_.Z2.{3Um$Ka)Ir SZyl~:8z4pN_PUjX~%u_RL|v(j(B@^<]C?;3R_nizU5 T=?sI;)k=PFn8Pr߷[.wC%[/>G2yULO/;k/N'J[.9HgY6^ۄFi1U;FY?Z4yX)AΆ& (Ajkj6|2KzSTI,`wCQG %쓵|Sp RZqF'7c#9="lIu(Q =s: Lp$̽XlMY3UTu>0p{DIG .AfF=8#tkm)@ܱfimG.X6u4bF{r 9[mzD7r6:az16?M@Km?e5 ar*.,7pɔNra*2f- 7-}ý/FvPӟgz @/o?khv6ߟOXX/4Q> W|QH1iB> bw姆~fM:P}t Š^_@4w&؟K*^|h P'?8{eV0 7?لr{V]_Q1_S_4_oɭ@***_ಎ3ŞKHbAp$̽'.ctdZX~zU'Vn lSC]sm\R (JΏ$ @f sM3 Ngtar;SRHYE&) {=ˆi^L7w9J_ n 8z7?gyATj6Oy L2 P#S8 :0MNg݃`l/F8qP]_-FQU_Vn ]v] PQt|jE5d(L-~g}A8fE(D 7H_r6>Ip0&sVH4ҥT~"'2sﹳiNS@Hzh >P?p>pu1=~P@M` Z![x\Y_SIro7KCX K'򇥙/wΑtH``Ф !5${V#yH,8jO ) d2{=3X_m_ePI?S0֟pٓ.1S`$do՟? $~QPsЬ/П0|? Y^l@qd_i)3sm*>pmM>L^-96A}Akk1"WMO~iZ+ҍ|wmYꗨ`hw-F{O$\$$ZTWZ$ҏ\{QBLQKEܔԡ}ٗtP$'rgۏ*{{fyu]xy.NИ)1x'S>c7[Zꫥ&{ȏLc]xGPFiDpb >Qy`z۶~(8k^tO}^ɣ@UH֖:yO(#%g}Р{n)8mUێ8KC6ULu\ |g ޿෍[/`-!oؒvk6#XSLQ#JP[O,[ᤳOuUB8.Qzc(¤2KESmtO2:TZҝ2MPLkAu.i7F <uYU  ?`7cjP2"/`޵ doЮWjRώ3R"\$R?`FYd `J0ɕ^"e%LӲmh0ҘeZWuXgIث ' lGJTZJkصOL+ &Ku!mw#IeST);ܜ:0U* {/;w>QNfh=dՎq1t0nqE=Pq]?0FEY*W_JbњdO d=0E= 7Tx/@NPMP~BDy{`L* &(9XDw4/y@LKi{_d|IY_@'ܫ ˾zdD|7߮ŘrulbbZJO@7z,\^ĵ#3;Ŵ };R_ aEܐPv 7[|Dz|&?r%9FgG% tOm<(2gu2Z?m[ya-‘d2?aEg%| ;F8GuݟpCM'ynԷ,8S왽/`wct4Iϸahi2>dE}@TxK ;sS%$%N'2Mm>|5<Ӕ0 Ά4# i\d!HIbkCh46@Gm ,H}nO9 JܴSAM)MBz@Օ pp}߻LJ50Z@l}Y` CLeHѢ-Y_ @=|hM7֤F{ jgz^q<>'(F)~[_,P2Uio5&'jS?@AbS @ "H~`a~Gױ4n=~8U? / ٖ&X<4~l:e|dO8)9y5ṁ:RQJ*I&)'6X[6z넩 k7Gp$w:*V_x \?E{ʖ7t=R!వD '%Vh5.Q%ywN閖`ظ˷R_-iAK-XK'Kߪ xH{;s1MV`AR]dB@x^%1U(4M_5ourxCgӮGy@3(J@I' Lӎirtý"澶W 9@Nv}3ȜЧ}#1/ |@._rI/cM=i&(7 fA4~d%P?`/T/7pd,FP'/ptWϮcm>б{57jM6k5$|>Q5ߤRw{j {Ʃhm7E@v4~@/(N'5 ^|@֤4x`M0C E~6n^Cxi9ճ#gŬ$-̚Zh:T5RE~dO`Jkn߹YO|N;*=A @U t']%pT# G70LW$oz 00^?^\bZƒ:d @`x0U+_4Vp{iZ>QQӟP,X%ƈg [F{1E1|@7}zujF~@hSso]l~m/ -W6>P0 nBL+O@@^`lCH_l8[鳐#kc$:yM>STOnL1kK$|`r|ྦms׌}OtIU"-I ESA< /64rH5W1UUeo&W_9suF}Ư//px֝7'F KD+ky%^~t%gū\EnZDEHKdpy=N:}m'V)Ӥ VMRh.Gw3ovm}{?e/AZ fdžşy,IU449XT-&>rYx#/|{{o2t鱵|Z -|8]tR{\5t|lWjnfώRw&8l3ss rII$:j("Ud%3׃^{Uݟ}l^_PBٸ:@he3/F$[[Xn@!5hj&@i6v$Z!|TeƁOxv`<g^*XPFθWi 5bTN;>9혦C22I[Fߡ{癢ЏiYu5XOx2a/gʆny~ 8&> F+~QK?0kؙfjIᬖ~]N {N"Me NS,{BIS?s|\%#%࿉)p#!2$9$Mɝ:~gO8aԍD9VUOc0Udo {֢:JiQ= j* g%Bu@t>s͉ޥoX=|smnOغ;.G{5wOxOpVȾN-$=_vԖ=_IӞ3[[V'HSN0HgJqꓸvt]bis&ظ9nS͐Abje5h[ [*_ǖWB}ږ)Ț%f ɜ-Vo(utoKJ86Wn:L[-|l{*8m5M5Sc:xix{rRp㒒&%:L_qVA 翗+7NpOߴ|vQ9BQtOM A}ZSM%SoJ/ 4^^sZJ @#$0&%S|hg}L! jnDj̟)8"V5@?oU I2S!x'YDLw#(I*R#|FU@A0rv\8쾨-R!V4L?<(Li\ۓ/AKJ BE4xlPSWQ>kRϋ C? BveZR$kS,0E{*'OXy`WD򁧘A ϚX@ᶌ;s񗌸>{>v&- NTx`friXkieB ;ߛ/:c O7^>|{ş5j]ിdܴN0UUxת/0ieBQ[kO kfסQP; ~yhlEIpPUPǦLnOF:wtH~:ݍ fJ.0 }ukюިri4ih.0RI'U<ԹoQͰYNcW P$F@xڂ?-Qy! bg~F>|(N$~"v_7䩒$[3E; /4޷0N# 'l䒭IL~ׇLj\U5$ЀI_P¨Ҥ!  Q>])&> F}# Ψ>(}m¨{׿@-pu}t4lc`uyOR /H$n/>ޥD\D7)Qht 9MO2-m%%8A'jrj=&W+;gIuy{rS4I_E}LRrOwFY@7]oQC_mf%aQo[5w:.ӟ yLU5ܻ¿z_Opͫ!x` J.5/|#!g *Z'mD^s3}oc҆pDfBDALVCgkwr.OE#OE1`)R;c=LiLu@-Q@ ~_@BjBQsXW +*X2@ } a *_Ѿ]fLcb5=~`p8@&c~`?gPTLLj>Pbcf&d/_ c}AGG|Oe}uo|ݮG;dj$|`T>P\/ӟ0|`^Q5pW^-V?%=Pfix.hrU~;'`]̟ILR.ʟ_ɽ^] EWJuo亮^AOtWLTVR}"3ᑱ|@TΛ=,vZWniw*)Ê!|[[T-&>mVo8]1,ΉSsJ(qFx.٧Sȿ( H>{ւ-zۓkO |#eQPz1-Dp9 kl=Gs  Gv\&A%@D 1h1ʍEіx# 7.`2lN@xTy @VDgJ,5vmRE>5g&+%ʝ @o ^'@&I⨼#Ӕxd zRZ J@H h&I%G>QQN{$O> 5?!] <] `` q${\ '4 4J oAPQ0"`) `# &0Ыx6i"~d"LkBZZEJʲq=;u@ ?8-~0ƿhػti-i&k%tS 'LyT%y{B4W7a}A Ʒ|@ Ko?]0@}WZv[ –~]y?7 u2 O6j39?K$ 4iZ;c'.%\$$o3|d0 Goz:5>F~]R6%ܟ03w \ !t3V@Ǎ_uNao{ʎ1L@)qMQ'f5ğݟ0z^!'[m%^gOBt9;Uiʏ}^?g2. ~&8}<y֝7s =^x*KSM+γ/ 0U GJ+^*.xki}׎qni2yTx SfM < 1yhp -ʟ`?]gs7$k{g~cI=BrUƢisp}O_d-Rz#S=W4}nqc{;[#%z) ?z&Ux5(BSm渇b -vp|n`&[NM * {>-MpBxBpC]\ ̬rN׍x> xsx")Ir|Q ;BᰐzhB)2I#<T7I $`fUh1#Zxj4:E>g X7b"q ($L<@| T7|5Z54A]q:>`3@tWca~443'loSb${>_>0)s|\%#nСC4YPډAMVNP_/~u˞ k7%8]1 G5@ ̯S\GQWr)ަc* ӢmbiaiL9ڻcin>!KJWtxI?\"ᝎaBj|yq[o NG ;dz=JL!y6<:毗!8S LQn3=Q/Blܸ[Q>E4zt-d/_ `?@d7dOoՕ#S'+"I<4M@@H,<@ e L^6?G8~/) P'=u Bo3'.tROf;z!LSd<_L㾠g->a#mxΊ+:ӺNˀLQ9UK2*LQ ?(/g4&E8/te7*=^{ڮpaU@oΖo$φg"8lMx A&R"4~ bJ5kԁe:`SSZD >|-]L|LQ^4_s~U[DO3Mk_/'|.Wy2U|1"R@LUW'iͶI/%౛hQլ@oTUUZDz(n=/x1U7U$FLVƹ̊|1ܳW uꅃ*co[5wد\&T^WtzbEs3-y[L*ʟSJ1]̰Ho`mu-/J9 ` =1iϜ wy`Rg{ʬcU_frhTƒv|#/ b+'33Ԓ T὾hj V+IoTo&^Yk:pP~jbqݍMnFQMr}Iq{Mka\rxϭ_41Ryvcb5񹘞:%5?/.JL.XnS ;Cǎ?J啅&+\@g~?p[`TG tDbd0M[&C@X?r)hP> zńb`#x0JΛqIm%c xj('_Փ+ezA\9g8}z|WҦ*kGQ#fi/|HkSfM @Y?2**09?7$95m %gᒒڻj]f},K,^$)׻htJR﷚Jx>9GJϬ 5 J88RL&HXâٛ'J^@/8qhw /˖egH*.sܨ>`2Ӹ&cjXz~ 9i4ߙ,{L>t<|T1E=#Xr /?41O9xs|\%#7Çj4bEѿ$85V%@}YOhRc3%io`ުj04W_ųy=hP@1Z-"o}CLV6:amVT_-T٫C?pvWI3OW\)9l=`FN- 81|R/4+*=0=u2pscZ7ՃtZ #%eOv &?yి@8j7ڶؙ߰1ɫ_&w `zC?avtz61-a5Z%e֔#tQ_٫兿PFvZ=s>Q{t(8ut@yy gKm3=R(>jlǨdL'_`<Tb}Y^םF,lZTMlL߽o`迍OqPCFp842E11r& Ζ5J@TGr0@ۡCb`Ap1U?#w ]Sk(Ԥ iUW^)FxԦhk\Kd){;Z"Z~`̗bzZ6N=;3 d7]i_`͑u=l4.RZ6y7sK =f D<`*`h\'JVLQ&Aj?| ͰP0v1@1;i3SH/9 e;A/UTqO QۡCIg2U@rPإIܡ]&?rvIWLx/ [ڷ*'e4?6'T0& /qDJJ#<7EѿX'uM>8B~1VчEgJ7uXY*PxX~:z sܣFQ4b ̰m8I)3_V3cުC?5-_^xvs4hJ_uS[y{?ĴTJDɇs'kC})?dSy/ 7f]7RzwNp`LQB .OSO##--0k\%749ϘD]Iٿ ǖfz6|`K-^@F`w^A8ےo#'^>=7Pau&LoDlC?ْ jnᒓT^=ufvϜPTmamDl4j3[ ra/ǀ(5 {gݟҕwjpL0!g>v{8{$PQj@J R,_v]ޝv 3]OO#ӔG!~#gzO}A%AH -H1|Vn#[wU~*3Ulh#0%SqNj2\`tq Xx۽ g|1x!RZd>6ڪŭЍz9FۡCI[ @lvHiQM> (KϹ w8)_xsqӯJuORzfn $ /`H#} ^KaK/&Bt{a!`{_r]ITQF RX9:| w'N`nf皕ywZfmR+*읿}@(& rr4{WO5B@T?P= s%%5uSoONz&|{*Ko(W| 0ß0| 4)F?0>般IO68|du ;u$|f" "NcڧvzǾ|zY5`81}#LVwOy| lkQ**|;gΛ&Z9+VpI0ޙr0Ōj|YYOk:r4WܠIS15)2Ҽ3?xX|#d#,IDAT;iʟ.1aR_`߈gϽ@3nhr(. S G@Ls]bҾ v'/4K{:ުݯ4׵>=[ |rROgp pVl{M|hzkKI} @l[v y[lwI 8&gK~(ḱNn MJx. jW_ob>0aqf7@?M>Qr]Wp6[T?@-⥆~ ;z􏳾`qx@AF(5 ; BUnX@8^ Kw8~R=Ep'o f@Obr*Bkl%`\5R( g0Uo,Y?^蜏e7hJpht[oP;ms<39+VL p KS ;"WmyoKy UC+ ~2tc,]aAͨ/pQzv8Sd/{ke $ʶj(TMtv2 YLKw_*{7Z_pY ,^]wӬr`>`x|gyos-Love_0Z\\RRԁ|e=0@P bj(4(`@T ϙEP\0gU|9J&w$tÖ鈽KFJ:>Pqbc"Bj,~ΛJ&?52Jpt T6ugxsF/:ѫgJ)zMH8hlxDa}CJ35̱j9 1=T䒬 -vۡCk^j(t3oKLKj*-..3^rpo] ͩ**Ӟ̯WPhLg+~s}g4I Heg5y6ab+p߰r{7nSK?aiUCk\h1-߈ݦHeQ|kݯ^E/kN^g* q\WoHEq1 &UT>R31ksgpǧYd>~#o?Xx~ 30؎G}f3I2 '(3~,?]t ÞTU @8N:z=eZHIiIV!(^B 7W^sC\,s/nbIxq Q:Sp@]ʷZ;2M}҇^ޕq/6Le0eq j/`>b,{o@:m]Q>BKm @6n\鹂 BD g^y/F  \NqC5 $1**ک lm<[=9aLQ‘ ?OmgkTE"ynSK?aJmɫI\Fj`])w?fF61| 1jTzyZ']%'N(^)={VnIcy7sx/8sjq XMп`{ǻx}b '!:$)OP*v7-xv3%,<i` | ZPJ(\5 fAI6%|@N5 ~>|qxiq?Bo*]hT?J|}4uIE37>J)~{NY_ B/^p7>"dzB5S(~@7h f xɾ:p[ɵr@^^VI5Y6[W<~{֍y*w@/[xPaE0ܧlݍ l0M;B12S:сq5Sdkf~ 1--RRzyQwysf2MNLh;4Nx7/7Np\l=Z)~nL 8iL<[ +O-.xD -fdj:`<?z LpI׿{k1?EJJׄ8ƙFߑ5驦s񗌸} ^J(BMLN%S/6?>*ȚD{WJ m"yLϪG\ټ֮V$$ifAo3dS߰\K!F(@k*_do]vu? ;S] c?@ (Yw~ \)oøA!L\JƻUㅉ=4[LO;TQ5 gp}E+-"eO'4KFx Ϸj[5g/8SOΠ%J OC?#ǖLKԩR5rMote/tKNA(yoJkND0TM~xƜ-''Χ8nn}pt䏢3&*g}Ox і2؎qt|@V_`| tp |w<ƥ9{|D|,TLj(l0}RPz*9(͡.|| A0 )~[B8es>^U JyBVB'*! T?t@|p#[j睋lѫ9qrV ?g o^7\0m0A\TuQ҅/fHͦL`zB;B 3lqu#{#`Ԥs J.|.{ {n5QA>So({>T=50?ø$K6 5 ))(>la_0 LUM>@%w;o/6 Mxʩqߖuw8 l} Z0PlHiYn 5@ֶmVzl -gE51 1=S&I:J9SzvO"ucz~@-> W|(PhQfFKF| RZ9Tl*5Y>T'̝CGy7AxRp3u>@+ǻK  ~:FCpfMGFr\Zca\ԢΛK\ ۾emV@@($o~5Z]-V?=t;t^-:S2L)-{߿s)9Ə4r/իoϗI\'}ᚺeWLO@"J3>Oڑ51^J8>@6=;HO1]ZHx$ KlϠԥbZTB IrH tOO?ړZnOk'$0pcy(>cSD3l ̬/sw.:=c3s^]? 8V茏vNn?B .y>^z SΛ|M3g! Tq''LAWj7tZ,Q}~vg =St6BY։5N>a)K}l:JY 8(4vuثLV?^e\>1 , &˳gΊ3^X~Q%hJZu~C~y 4uJdp WFsW;ʤCELx~LQ֘*{=7yt}֍{e`\vP-A|a7荎Lb'dF]N;?A%8!Py5ym;?nLU%kv Sii}y67f^֊D'N?y׫.ILc?$FX7➗=`#>_[8(~L@tLQZ,4NzyJ6~e;!&IK'rN|ߚ Dʗ0 +434M*/L~3kS8~a|-S9>p.ɡ1UPA-d`L iaP:M7s#L wrH=kF Ǯιf X~$M՜߰dQt@--GLC۫_1U4A;L>b{/mW.W/+>}^| g λm8Hi:B8U_{iL9xLvOLOD RV>`V,2=>Rlu3Mg{N3$R .ohr(1{\#@5ո~kqT J-z1h=d0&K7s ?tҐ=1g,U<@D>0+H8(滒dz ΙcbuqtCLR 㒒?d%t1R;?VßPl3 E#_gC+SL5|nEqX[D(Tt8 >Бi2eKOYY6h,3`77ЈYL֖g/{8n SUBX@@xNu(n0`+Zg+8*z}VQ m3 Fܳ+#ۃ{TeO:-ھw@UR(a6Hz3@7_7O@+iЋ#˳-)vfef*LJIZל%%(6һ{X }f/[ xs>3_#<ދyn#}{C@CkZ$R)+*y<y.5 f8g6Z?QN{>48%E/p)8 |-.{^Q' c65(~cV&{"{Z?U2U+*b?|YsK㛀t.wsń3qtf0M3TQϽgt<|{@Kz&cQ/_**sOO`}͑ zSkܱ3"UT/οxc9 K=:g掭̚ MRW0U Td=|QC[ΛP1c3[OԆVnp?|@V} #onhi|wأ|Ep4?k2DYaZ\qfP"@C >4#&e/ੁK$g?@Kkep3ڲ^;G 5BUt¸w }z@ {/˔3BF.7^?♅B[$\샿n?0 M3U7+s ֍{.gF /{)n/Wn1N}OuZէdd10`tq9@e/]=.gKMnkL>0a޿T^y{Ff/}=ǫ/Λz 8n`ٸGV|6 `fR0Ie ɻLE]3rV,mde)+ >]/j>@Dawʛ:}TEzOOεh~/SKVa}qet.(Δ?6Y9.qzUV !w9wr`Bǎ]{_kWDP_1|x|)Ț8V=uz{f[ y<%2sUptFy~T$y,0Pi C(=f;ojtv6 @V[+۵zϛ29Y 콙Ӛp6{t=H(͡6r?Xaxq Q>wDl `˙-^] 4Bmty|/{s5_ûGrR7l03bHb̺j];3 kSq@6~$v8+{ۧjLxcQho拲#F0`c/K}+~m?7;SIw(`#샗.Y0l/#nݿ0&3̍HIEE :vP0ʽ߻O欖5:ltM (̆&̒ xԂi,jYGᚵ.ʾX\\rr;gGnn@|W~%Y8"?=eh?0 f('l=ZY7C:d^1UMQ3ݗ^sկO[f@loYB;i"oߘ]K,Cz~ϛs=sܘ;&=T|`B"{.EB".>gtW3I10Y htp*y]裾 ' '':=|2#5TQS =|`W)f}A-B0S?jSV$n/,oYZ dw }MxƬm%~}KN`C7CiUUw{~B?_ r>{ z4?G"$WWOحbzSՀT^>(aqc5{ D~ڶ㪳N3=549Ϙ_#U 8ڻd: dM4Ht99$UVfM/YZB-tUg {5RD%ݳfo8SRޭq t>`x*M ](y*7V5!߶''?fhhҔD 8zWW2G7?̎j>܂z6o|M> @ )z))װ?|x)%F@k N>pv|GŒLQ"|4K?O BNcһ!VBڷo+9TP:~1)7~ͤ9˗uI?hJB,3ޑep:!i4mN9(0DZ$޸F(8/s4{ vnl?ϔ9>3)t5]*eKj*g PR\'C'n Y9B~/ GV{IrV:Λkey9JDaDLzL[l u5yTߨ@:))y( .y@ 'EʻA/سW1-~ .Duw\Б$*=a؆ip [s0u@ּvc4) |ڱrBEbfo;D渱MKF\k{/v@( @gC (AcLU~rt/>%ea^cX*YCjU}yS~kz}A6EZ5Z???5텅t˷=[yz>vl~'6}bz !RVy(~fyY'vbzzDJVf$$"%f-6Kc0'ݦC6CgiF 3gʚQ^X%GOAE%%e?ELI,3P!(?ѷ7T8KJp%'p깺p>ES3{cf?9oQ6apC?@dwC%JnyIn㟺5:qBOtr3`QZ,N+ H.wޔ?Cp82Ȅͩg!0]!x t\RQ "^N 1 Y<.>+J.C($)_ӔO}xٞdžOhX,ʌƄR_`j7rVHz*(P@@x F`43ŋW2Yzw%mζ_Ίh d``&ny/ϘLB,gδo׮B,X9-reyÇa*{ C BM^m/W ÔHfW|s8nwLY8s_8üK-^M3.g?͕Lܐ@%!B_; [M\?rdYWSQ\Jײ T`,\8P(>% +J^ σaA$?Eq@))y(w4#rVHcrdE"b'|, BAa* #*'Uz2**{b ~ ? r"a \)kϸS渱#&MJ46BaMqŹHHĵ?o^jLU+E+!Z$gv >9#dM~qcjz65*=tuwcS/` T>N1U{--[#LPew|ߴ?L+ -+b̘ck={g?Y~t8Q549/Ujp.ו.A?0iҥbZJ!%`׫y:vl_Kfk(Z>~_3fC" a<͒**LTr=sI-sptf0),o™o.|5N#6`RRQxH9slj0PBD{-F)8YLU%04ohM3@wo 81*WHvv蛤p)% [758tbIt>P `Ie+6L$~\Cg-]_HBtM(T5= ݻ %L} 3WӟjxGo׮ FXM8a*&Efsg/Yk~$^O|܄rd1+~߂3<ƾImLjpLUc L҉pܢ?>*w:s5ݒ[%y@tfeMÌ#GZ 4(og/[f.l{ G7}692hzN3&iYɋ[XtmF taZꟈD<\(@CM Z8|'YoԚ||`/ 4?SUɲǘS)+OD /$`TҲ)S2~٫>S7?|I )R<\ΝIÑHIENDB`Carla-2.1/resources/bitmaps/dial_13d.png000066400000000000000000000011231364475620200201430ustar00rootroot00000000000000PNG  IHDR s pHYs  IDATH?KQG{f 9,6AYRX$YTR-1`&`a\R%DBd-ݹ)FfI_30\CXUf2v/-oҾ%;s>D> GoM< |; ܼhM>FNP<?Q* }և .HJr ** eQQy 숊m n=x9/*rJRT֯[J%Qiqth-iХVꢲUQc7V`jMX[SZALآ5cIp83f~ޟ+jh {VP?-gn6` 1`mDi,hY0`Ff.&-FVAU)k.t1SN.懁198 ! @ؤ"["w?WwgvI j]|_~u֯WÏ-<V3*G-pxo@}@J( YG Q=O|KGlwzoux 7?7{0ZC)A3UF`~Wvx>Y>@+; `zz!pv'?2wulhh7^ó/m@!EaQ/C{ ?H||5Le)R/tFgRdi@D Ɠl'x Ά(@6Q65}+RprmZٞ &15}? aDow>E^tEkc4cZ>Eё=(FM+'WE䊭wuO V 3"7`vu/2?Ob\: (@Vd  2HM)VXT]ܞbwm1Y3Ha:ᢈ|\;G`̭EI?( ,=w]F"O攸K߁44,1 V@gl^?9j}u{VKАrY M4OG,or06tԊ(Q0G.SLm*^ UCEf`WX/UC9 Yi՗ŋE+E7 ШX.>:ϛP R07[ʙdr!Pn\W4AGh6;b{爋> ;plHG eBqnO nW B}|jA)DPƀ5TrBNwAh~UɬKVnq9?Ճ퉔}߷\U}9-޻4b- K 8Db[6.Z#ygZ;lg"?E*Mg3!g{]3L<[vV= U[`H}wY^Z ^(VY^R2VomdK5H 9Ϥʝ2rJ /=붍_˃RMҖ#J;he{фl/O.,*,UWN˵33].4j̀!_' BbcweZ'*\ɧ+{K tak0it (ؘCs;`U (]q|c%8jxeۂ*}#h %tEʓ|lYKĢmC/r3ARX$S֎|R7*۬hAlYP͒X)^+؋>b i.XSVZ𯯠5J+4[}`U U=$j#0qP90b;mY<>]q/lokF:"E|:u9k|J4I⬿o( Z(\}VcHG 0;.L(|UnJ7HE$j]jtő$#]qZ6b=Z'^Ve(~6& 6jMը%~Uny&$3 |oEனBHjP|{%.24 m'j\-+؋݉EqU[۸i]P XyL7'Sؼy<ӯm'DnSSJp:F">+.|K{~j4]͋P7@mզXy>}ĖO@EGS,$?Z^VlC [/aAG\l3۰`u{BTN6$NVc{V}K.|)0opZl }zI梹Hc8e|pTۤꐆRzVfFHqhf+Ӭ%p;)[St>&SA6K)h@D>j!n1.sYnK>Kڛ3{QT¿n)j/YvdQO՘9*p =,`OQ`p 5ԢjjIۛL 0٣i.,7*C\4\SmO'L7#Yɔνa--žgdFXM5~!_"fBses3a[2W%w %mh 2n0H.)3{M`|7:v}|Eܳ{N1H; c`bҧzZČ4Mk;umlbzUm[`&^ګǿ6_'p:p^nنRjF?TɄ/V^+wƋ_} ťU1!XfLRqt 1񏇜?aŋ_} r+tioh}O#{kş]s|ZArQ` O>qintG =zi=ࣕB$ϽSӓs.0W\6@ **@"L&G'SuR67{zB)u.$5 &|ƣ NO1O`?QF#I zz=(=Ezh}Կr?7AZ2 8{&1{t>媾/Ui~ZC+41Ar- | [X φs75}v3Z6ó!8avo<(b`QI(|1$Asڅ|k/Cрb$Jc3K[Y5)Aei?OqPfrm՗ʜ#]iǻѱ~$Ey> f@+ (X+NN0ʧ ks۩ k@\3&lS㧏8h ,L4",OZY}~ xJJSD,oUD$%GkWhYRW4'__\٫rK;#?Y{옓[?X7^!9$.~:僵io;ַͽnyx,.>?}XڣxAG JǶvjј mkːW}Xqq]M90ˬ>YFg}t_[A RFf$jPӒﶆykW_:]d2ǟz|4IUDej٬?@4!֖Źi O>}ߒލ>l߹'x' TOhy&(巢KRhOhVS@j8:b88.ۏ-P[ރsd! p{w7AWC Ǘ[=Cz䟭 ƭRP0NS[2ۙs7oJl4=dc>!z| _}'7?WԣE: Û It4(icgQo2qN/k G`A41ٿ'k}"M -YIENDB`Carla-2.1/resources/bitmaps/kbd_down-green.png000066400000000000000000000126651364475620200214650ustar00rootroot00000000000000PNG  IHDR:$bKGD pHYs B(xtIME $1將BIDATx[s]Ev>-`ɒ/؀6PRS*03|yW K2O^&b006`Ʋd]ew<圃Ξʔ9J,׽V^ݻE'Rrr yIe;6[ߕ ;}=:/I=mO -h}_ؾ3knFjg}GLϣ)}GW[-w桤D!Ȣa"+p,kXhN"$@"UdR#p?swC[kg4)mPbc^ae( f1ZkhѽօRGŅF|W %U٫Bs\.\;cR$IV߳vǗC8}a@aSp),/X( H@F7D*% tSO"溝JO?8Ķũ ~0֥u.Gյ*P%[[>n{.Мjbaa 6 m48}`>T5bVЍ EÜkN,@;>RJ hu\]2/,i$0X]^(Vh-Q !%$@&Ȏı%wq:I/AL7QЎ[ 00 ˩X @>  h:k$|bVFG5]cmV%GnD_Kt;6,PP*"D\MERCФ!"nǗVr#|}׃& Jgs%%TEQ NΓ#@I5>)%RTw# 10d0Q&iKTS"JÆAAh,rwIB@4 t-{ƓO`C|n~ Q7剸!D(TԞ I\A6nG&#dSvZBw|RGiBtWw|l9m W ̾rpxwVoFh@2]P$ vL =d$?NqEc45|LqZ.&\͟~M^WN/a17X)<XSb/yaqdHP|g>N\?@;u?7xAB;QxFQq{T(RrHf^u #_x5 3 MC1 VǏs- }'@qiEDj iP?Т8`:W8Qeq8O5&|€#`2*S[&ӴiZ 0' C,c%}s:&S:3tZ}a;[1)Iw%.L&4 / P Mnv\E-#"0'O$ߟח{e!oS;@4dPVg-Z>h@5(zPo1% 0it^SsU9>Lkp S{] s)?>)a 5&^-wR.Z@N2d')>JC3>pQI|b@JU plV(W J+x*sArNa7BU3i̅z" *"a}~}S7Wi W-e>A]r*}ŶiXߤJjd`JwMiא織{ #\H+;Izq'Ai0%Lic63Jٶ L§9.BL% CTw|T|"˩Ž1@PȧDnR&4(7Rnb”,EB+>i;ce&&Wg*Ui􁊳U1 ks*[YJ9gؗWsbȆzCn^/9:;VEO Ƕs M)'E)턷P?JL/ۼ Tjh6x{YDp!H@Ńt!\dQtE|R|&؋ˇ ӉJ(\0Ssv.pN=EW2mfd#yDe}܈Q:bO$[H,,3 ^tN%SA5ő?7?L&ˀD"Rރ6d @#*'߇|7SVC1,\3fQ?H?EX DUt~Rő e&d HNX' hm@ڀ* hPj;.UɇT qLHD|;Ƅ<&Ch:GiJ &!wQ9\g Q%WO=Y`!h!iOZ[a@Ȓ0#!n`'cO7%fTˇD3,PP%O!ԤAOZCYOBrfl6ڀ:;բk b7 9hAvБ9DAtt||gK!)P?Cʹ/wq_s, ^)ޡa# : 2AO `9]Q4S4P\TPVXm^9|R>Mq#(F!JP+LվIB*fŽ%2ZB85k ܓT5<TJ#qD!"=@,1`#=@K›ѾWr`S=*F}B2\`1wj_[?AUcXJ'/ƃPm$5"!ClI|Т||>3H S `Bx)V42ρ{;Q8;74 $1mPƧ:};U Qz[eyJn`ژ`;G #!XFPrZ}{9B?%}~G)5cz0 :.Q\ͥ@wEE^_Pg|4O޾KU.mq1<B ng>>‚ZĽd!Ry#YǥM:Ċ;gPQ’h>O]QGaE.A8;~}}`$p?yXªA*hmu+Wϥ/;֢f $ofvy6ij bsrb1 y.w|te%$O>3%Vw>S* #'jjU|*` rpNwB7N"[rr?9~҇6B4 GB t:m_;jq&߂e$+nWcB۝n[>SI_ӱ(8'CT/Fr)ysTl/(!K\osiwl 2AW7QoHպ9Qμrs`_u0qAI)?~w?`WԎue/Vk wD cKW \5.B|@q:h>RI-O_<ٵU)VWqG?cJ)x#Í'H_$rqD Bb_C|vN[GM\{ hm{UA>fPB۴pgۿ!?]g.o?$?+qdIza>6oA~K"1/amquK יi-(?z _^ عa?. ݼ~p<:vv(V k}g9w1 OԎsWuD*BEc;>i_^ٓ>wj$ MyNE\N{2?1CXw{G"!%>{[Oo$:-}&^n )%Tcw DJ"B qn=K.4'? XE~W>f3naMژZ>Ɗ=x?V8&6Z?Ϥ \'o'!l*G BŹ/Gq(]3UUE嫪G1(^ Z  10&=l 6Gp3|4,{)I*@rSO0Q X>_ E33f?ᗪn] i:O(?2' Op[QuL, /PlRpu/wIx?G)>8hf{#s=h>.['?A+ncp]v;^>a&!O?|N/Uw~wd߻{ ̌`ۀ)3[ wnxh.`$!wmf!8 wkPY]cR\sMƽ[ۘ~9>;`8[v~tR`F@pIfɟ?|/0{^벶̓IENDB`Carla-2.1/resources/bitmaps/kbd_down-orange.png000066400000000000000000000120101364475620200216200ustar00rootroot00000000000000PNG  IHDR:$bKGD pHYs B(xtIME $ߋOIDATx˯uTu̽wC$ŷ(銦-YXN"*iYgd ^ddc 1@Rˆ-E4$EO "y_3]'n4\s:uΩx>4p7q!hpbo)~'w3.%L;FO ַ GqA+DNgO^Hצu&[Ͽztq!h.)r|u~<>^ہǏ#+YKDR|keX) ۅ.R r#HR`}sG0 v| Y!+*y&Hgr}8oNay>S(b b`Rc<f<~^(g57SX޵D?cϬ ;ko]==ArE1XϬ l]}+{KPJA#P*m a׮% wAo vv6 ^<;wkG0sQ )!"bN=\ "##v7\8=@* FQ D |Ji^v?pt?`c`Dae~>2ih݃"0+R Y@ z,<܋:*$I;>x4RlQ܇Œ&V_܁H# _0 `Y=[1qQr ߑȶCA9^^uArf 4ve$4(rY1`#2ʾ# vF[wF_`<@5;d_ug E! (5;mNBA|qQJCgDǤI54sA3 ;*L&Jb~`s=ly>  "~J9gaEDȞW;їpXCD,W6|bs  f?Vg|lݩQ 0V΃DvzEmɣIEV&fC rJVE^Dr*F03%^)~ۊOW\1 tr&!zv0]ytGF '@xZl"(0RhZY (0R(eG)%N)|}yC@ђy .V^.;> Ү5wV{0B@$S'H#ZJ+럸) Z3\5GBs?:KpF1 Ŗ-{r)[ NlPǽW,hVa# *M1ǛZX*2PJJ*"@*=&Tg @;З[k)ɟ֋D &AK׸sq1>&Ӛ;U&~:JvS]m TS$[N M|:RS>ꃱ\)iH3,(#(#əFɘVTh$3 <>;]ft E ȧS./܅[9nuAGo $k0 C9#M SL](=Q; 8-tE >_OWD(/.ڡ%]}ՑGz&AgR $Ϋ9H (-Q,Z3>3W?m; y>L S.ѴeqhVڧ搪K_)-Mte 4Hˬ4SOG/+ q10GoIFIHߟ"`(?Յ>?NYޡRȧ`a"Ŏe;2s:iK)|߇JP)Jr]LŧFHJH4S}[ _tD1 2:7lV1&?%KA®1m )v } $Uפɛ v"UI3H7\AWͣTǟ!_[$?ցe %2x*`ZHg]U4O!G*' kv(0)>-L3t%YP֕Y|Hkf(A;m8"im U&Uu(,hF5|:bS̈́3W;/i];4/$-/`I@R +}~TAUT;G@\3Yl^ɧ3.R-/ .uPs';:7*`[~ԃ=ϓL)ssxaR ]҉9EfK5yQRraI>Jc),n˞s+SŅ[Rvғ pM3t%8|(4S.vg=v;Oe(QS@7$4N&i֢R},)7l˧rR1+| |ftޖtaF-"-G };9j 65Pټ[}}P4sByW6|:*'Z CK5Ha*#~)Ԡd2 =H$Qz#S[ ЮI"R`p/tk>5oI$j_Ls!?wՎO~7FlRIR+T8S/dtr&!ٺ˗[җqπ0OMꘝjSe6bUԖ'Bho} &j;AOD\Sr늳LթmQQVLFЬ  +&t)RL&)8rY= ' WUobZ>•Sir-g#)F_2ɤZAXz8 /͟11 #)޽16'LP4x@=z M (څd`skQȞ/I<+׉y̙xʙ$)Hd圌'U.mxYxv,Uy;ǘ'37 }S^yBEA?«&x2  hq?H$4ko/^}7 !ebۡY)fY ͽ^O_z?\hؽL#{/l7 ٧N"{ UI~y#n>Sw$^+>5:>A.TT:}7frS-"DQO?~N[w$rR%H Es3ce>˸~~ۭA?.K_= H@{/^z~={+{q {AM(Crs0Xޕ_?= ;󗱼{m 3ci{7wfV8҈=q/č_X?} cH|0|t+UO}҈w7p?{Pȯf dvZ=q/[.@iN ?y\: ^8sgbr/ěrrQ܃ryR:qIq㝏4Ϧ+CI{z e*Ax8pkGcUxێ^p~\}Nx*uT+?Y'c`OƯǭuܻ>-{ģ'p!VZoS `w¹k5Jmdvg|(Y=G/BԛvYtܷO/ױ=g| #q??fo^7v'}C\}a9~pGu0G%b+p1 I 1`/㟾?+XٳqoZy!J\>|g.{Okw7S`J.9k sc.I-|~7pqkP Oٓk(n?qؿt7=Dv-v&5}'BB~{:wS:I](c qnO )CZt]vnv.Hhew&x,5<^uXt[f%_^jӿ_r7Jfj>X6WP.A@=LݠiN>W?P:Z8]\ !uXRGk-hC[7|W_ >LWPLbzht!K._:/H'4)5p]:VvC>WF|\t cz*M_2%-neX\Z7|L+{LΟSZC+eȲ .~<ўsȱr @& ^;8"•~ݹ9,zt @ZsgDGϚ )us%\kR{0I1op6;m/OCz4ɋŪ)< yNDqq%M̼'c )4T'K8bx! 1-_ؑÌIJSJޢ֠4$H=w%"^!iqFi,b[~qmZzm,+u7`ƓIdcC+?Eċ3E:4K̑"5́& 7:4ċ>x?T7o:A}fDcp.yA\Qmn12Jߛī⤊'gX?FWQJ\ xT)Y2[̀F#hh{RxUFMzj? s&w Ez$=4u=ɮŦi^W5/S&gEgձ!I"l~Bz4}U)VP2S,Yv!'!K( 'օQUScol569h7>?O jo&m)0>Ǵ*i*c!:)^σM$As1,_pkHg#` (bwvtL< 3.qܵp&Yx _`U8ұxqdӴ/"8T4Z P`E,}9AG٩LF\b<y'- 4%^Ф>'n?!FNQQw:_^hXh6`!xwl Bw@{"yT/nD X:gjbh-v„hvCl>:CPk t,X wD '+x1GsFC8wn/pJMQ'~R[EP7UaT-U oxx~",Իֲb1YђR' ȶ2ҍFFi f<73 Ih6cs{$%gqx{"弄WD@ |GD£XUk+LBuhG"` 1: ǶF!20LSPx%7A锌ycxOvyj"?!=93ZǍhUxÝNib8B^_D !`&,3a=3pS@Sm$.FhQE|BxÝvQ<fe)qMǩ[=;RBz|zN?]`{sN=N)<(Ql'm" MAp'Җ_)+յkH-n:}2=%xí-n7_d Jn2is?>/n@(Gw֑fFJ^5[[Xvz0(ݚk8}7VWv]Kp T_$y9Wp%N\_[o> >|_ ]39NGdۆ~G>U _j;!MEjUݾ]Ӻ9C;w*FX㇈y/y\_r:? @%wvv=-?I:~sN.?^0n̲hwI%5)ew*wG#ysݍ tVbz={ډ޻z!Ɗű /N4/W{rs^"pkc.S!++nP 1[.awGk;~~Qxye/\@"%ʕ_x9#@K)ܸx|l*~tZIi8B%?s_X^zV*~*B[~Ho]݃ܬſUe$RӾ^?[[w~WjJMiz1͛xwG"}sOkٳA 16c+r+C6 f 書ݻG{{G^:7WD85\8sNȏ-ىH  +a7Td&}2^x$0+TU[)w7nŵ5|9hT2\}y\8{sHK!%7B?YXS2KDhKS xsm Ϝ)8 GE+ sOUCHBf6 < ~{tLM'p'"HsaU\XY)ɿu|E5ṟ5+>.zu7{$spsŕ UpsܹSK_nij++cXp,`wML+??PZL2ª"w,JJlɟɯ+&bX>œƄBLS*5&h ^33qk}@5/Igg+䋺,#=II?]'q AAv)JRuDu&&E̊jGveҀqBLS&ߋS7 ʯt={"33'o :>ěk{N!`&&$8e1|qCF=/Ȳ:z;kD~l(lFoS 2[0Û仑 d%LKr[89݆?Ѱ|p߽Y-p`5q/ oLC~ƐigZ/ tw_~9ZBC{3/?6|M@1 F_%4>fcpދY5R)v̑؉vr=<b:vB92|tf=8C|Hݻ~.Zv 1{> _LLISekx sViIENDB`Carla-2.1/resources/bitmaps/kbd_normal.png000066400000000000000000000025541364475620200207040ustar00rootroot00000000000000PNG  IHDR:M pHYs B(xIDAThnEϻ3kc;mIJe RQ% AU䒌TQT Rh8_Mb{?Ǯ;3UXdd>gϜٝ'4$Q,i]0'+H%Yʽ'@膬pxՊ8 ˲)-%=)Mͺ( I~FHAru,z~zbD Ա{.6>X8gM庯 c)9`̩>ZkIxB٪W]+h0{n ^\\+cTԳBI3IqcQ )@dR1!'m{lkDDѸdr*fu"ձD?6h4 8r"LVp|Qi%h ?6X ɕ0KPG@9yN0(`6W#:]tD'X&PNlA&ܣvvޏ~܌eZ(&G2upM4qh:a be(3UO!l,l1w-lrT bU~TZ[=<#л*ac +.`W&,pX~r̠m*@S5mؕ k]gr#f_T}JUIv,wM& O.Zl >`|ZNh2cPu`:+<|@ڃzZX(^׾BS=$^jl]=]tׅuOϻ~S.j< QemN|~X `Y2M7]{Pl~xأm>z.pؤ}s?xăӣVG_zg,/r~^ Q;QZ+f~+wL/}.{𡣄TYx{݌W0>XgƵ~7\9Qa|t}zp:%\[6sҒ+\AHvsإ+,G3_ zUy-KTO^  9>;f%N7!׬cY/fW"9o?i̮eІD(0B:/?Ϙobq> ڥ93Fg9[Fĵ"[@Xp-K_fZȭuڼxǶ9yYրKƯ8\ 18pöMTTTyYo"u`A~f',?]m.%/5s/gWrËr)y],\&E2W1g[0\J^HM]zo*T],RuYHe"UE.T],RuYHe"UE.T],RuYd3YIENDB`Carla-2.1/resources/bitmaps/keyboard/black_normal.png000066400000000000000000000017171364475620200230200ustar00rootroot00000000000000PNG  IHDR:a.I pHYs B(xIDATxn@E)u6N ꂇxVB}X j"?q1/Ӊ\ńjS[MYA^*"&ZZ0al*ƖkS;X׺zط+u._sJW\R:Թ|+u._sJW\R:Թ|+u._sJW\˳P/=IENDB`Carla-2.1/resources/bitmaps/keyboard/black_on_blue.png000066400000000000000000000033651364475620200231540ustar00rootroot00000000000000PNG  IHDR:PLTE  1:=@A <)@g-Ir-Mw-Pz-P|++Ae4NvC`LjMlMn3.FnD`Omloo5+FoFd[xƪ8,Jt/R}`{zz;,Mw-S`|}},Oz-U\?-Q~-YXĂ-T-\UŅɅC-V-_Uʃ E-X-aU~"G-Z.dV|||#I-\.fVxxy$J-^.iVtuu%K-_.jVqrs&L-`/lWopp.a/mWlmn'N.b/nWijk.c/nWgghcceX``aY]^^ZY[[/kZXWX:qSdlqBtL0z016~M1K/z2/\@q;u5y560v=v0~1w2\8i:s?}??/s0y;s0}2m>-U4dHyIIJIz5e-T/t6e3c0x2b/PBjWWXXV@h/oWWCk+XVAi.c%H.V3]7a9dLR tRNS~#XnvA/ pHYs B(xIDATh3QƏD HIdvE$H H֔E -"/RZ,C[3u6f4y{;=7p`eJ3:BU 6\UuCT |!5#G1B] X H=ZgX]ݱctFkk px}  B |!X 1-'M2uڴS&O@ |wϰimcc=jt%X ;n{9lg1PF_]/Xpys(c/ஓ"Ů8;1PF_%nK=<<=ܗ-a>~˖x3PF_A+BV Y<2: ]fMDxU ѱpwmdTؘuQk(c/ II 3PF_wS6nڼySƔdY7c/nZzFfV-Yi ѱݭ9ylp3:;w`t,k{p1:޷@A؞w.F_':|PAwc/H޽E%G=RR\D9 |AvNzIsNg=Ǭ`EHثFAs^@H4wmmQ C{VORKkGi;m;kk[g' P^[wOo__oO7y!ѱ0Eet,_pF_.HZ X |Ç>|Ç?wWi5CIENDB`Carla-2.1/resources/bitmaps/keyboard/black_on_green.png000066400000000000000000000033451364475620200233230ustar00rootroot00000000000000PNG  IHDR:PLTE 1:=@A<*g9/r=0w=1z=2|=+,e;5vDFRQ[Q[Q[3/n>GSS]owszsz5,o;IU_gƣа8/t<4}?dl;/w<2:D:6>GMEGC?E?F>>;GHA;FGHI8A@FDGKJMINI<3<;:A8<PHO^c`baacb]bFM;;baIP2:_aGN7<H V ] adF tRNS~#XnvA/ pHYs B(xIDATh3QODR$ Ev&DJ!" YʒPh/]YJ*_ѹL9k͜i3w{_3BFa%1dF |*cǍ?nH8c/ 4a$5SLVW4qѱ@Cs4miZS55PF_@H;}YgϚ7cX  5266;@_et,y&ff&(c/஢| lX[)2PF_݅/[jonE (c/2N+V8-wtX@ |wW_fjU+(c/஋Zu׻s[@ |w=<7xyx{m`7m۲͛62PF_mۃCBlca;"""#v2PF_ݝ1vٳ{WlLNX ޸}ؿ/>nP7c/CI9x( et,I79%cGSSI'c/?qF_~N>p1:8y&ybt,{"lNnnlwc/H޽y?G9 |AVXT|BqQ!_X ;BiYyEeeK˘\ZŮq2sĆ7kjoݾq}L`VE0.KruU-+=W;.[Ws!f #-$V=`O8O=ojny%Sd0k&ay*4!-e{鹦ɶ}MVDϝ~#,_"a:v}#Yn64BQ}}PF_@Hѱp |A"iQ$ c/Ç>|Ç>ǔEǕG8@ĒC˛IџKӢMǒ;͗<ēDϚ>Ž<^9w3<ŗP˝RСTӣTŗQjU |!U~ 8F?uU8cc/ 4h搡ZZChgl,$7|z:DP_@H0011YYvvwwww@0022YYsstttt22YYqqrrrrA22YYnnooppB0022YYkkmmmm00hhjjkkeeffggZZbbccdd[[__``aa\\\\]]]]22]]ZZZZZZ<>@@{44;;==AABBBB22>>33553r0077JJLLLLLLKK88q//229966225511EDDYYZZZZZZXXBB22YYEEv..YYCC=KQVYpAv tRNS~#XnvAZ pHYs B(xIDAThWQ/fU6%R,B)mh)ND ZLHBf-;3uι9y_?|X ?ܣGr~.F_P>8q<X SNC |A=}lsgϜ&˜?;_T\RZZR\tdt,…ʋfUU\RɮrrsF@5uu7n^V-jeUԳs^e4465466QYfM#-w&V`9mwtvuuJ=ncH KG3Ң`;;Y^TkB=^."~ɻ^JK iQ־I6'0?}۷_>RWB |![PF_kuѱK(REB0:>|Ç>||i'IENDB`Carla-2.1/resources/bitmaps/keyboard/bright_sprite.png000066400000000000000000000251241364475620200232370ustar00rootroot00000000000000PNG  IHDR\1 pHYs B(x*IDATx}[ֹڛd/}ow-[Rdyb 9HiIa%9bp2V䨥ֵZU˞"]l]UbR>.+_J@(0R 'S|zrΛ/7˾ˮBܸqo6666`&81)ǰ, u]xmc a@07n;#M! ^10ຮVWFrۇܞqFѭիW˲FWs|6k׮acc#jPP#Ƿ ˲2/ťKl6aFq|GTBݻw8\(qp]s]\|f\#U*iWx|<ض`wN'EgV a\.kk4Q;ĵH;_!P.QQVG n0P\c eJRy, rfjG\ ]|1!.qfG.*WIuh4F!IY_VamrryIǁm}‰}mT*\.5iثte1뺰mY.L: ]ƙtǗU9a0 cdfR4|dicM: q&G ڳ3<Ǚt퐤Ϭaӱw|kty0I yLJ(<ȤƒLJ(<ȤƒLJ(<ȤƒLJ(<ȤƒLJ(<ȤƒLJ(<ȤƒLJ(<ȤƒLJ(<ȤƒLJ(<ȤƒLJ(<ȤƒLJ(<Ȥcjڶ=54Λupٶ}gӿ paFۋekZaKVi\AMDBlmmp<8, ;;;}62o{{B\pKXmv&]tCV>]m ˲PJ>_[[[vzӛmۨu2=z46~o^Z6RS7B]nܸ8}~cssW\A4ZRVIUwyZ-s;j5{(JxcWZFuIbR4Mܾ}ׯ_GE׃8Q>_8xh4"J qqm\zN^_~e͕+W"bafUA< ᅬw}nG׽{ *g>ի|B|xwtpzz uGQu .KRc 7o[o?OQJUXT4r9*VvQL}, 1TU+tvQհըp4Ulۆim+++t:t:j܌܎ 8uI+mS*fl6c(XYYI>=>!ABZͬ@KP#q$m{ qrr2q;O/?q$*8iSħ=  2)  2)  2)  D_nzQxi;O/?~q~m`fŧO{B!b{{;IPTTwn//PV3d ?~ Oppp.k8==(>_'OpvvZ8;;Ó'O@)~ќŋzhz.*ŧ;wpzttya8hZ^ܹ3')!>}s B!P*bmmmϞ=_Wz\Y9͗ěeeu !n޼x7>8[X?Vuy^3Ռ1!Dl͛7q-\v-q|WcqNW. !vvvpuZKRJT*t:|p' Kau;;;uDܺu Ϟ=—sҾuwOKLr1xw,eZLzqfG.Y ! Àm(˨T*\ׅm}RöL|e=F8S,y~W ÀG2Ma@J9UM'`K.RJ'_V8[Iy~W8ߪ4Λup-.~RBA&%dRBA&%dRBA&%dRBA&%dRBA&%dRBA&%dRBA&%dRBA&%dRBA&%dRBA&%dRBA&%dRB1Im۞t}:l۾߅vI Nvooͷ6uyy겺ʊ.̛Ox뭷q3s^~=♖ﭷނ>ܹb&vwwqmۙYu7Eöm4M'?An㗿e[ohۙ96~_j޽{cDZ7olQ]coo7n!yhZV3ןPxI PxI PxI PxI PxI PxI Pxpvoj4vjYO__|?cDw^S_Ǚ+8Nd0n:z x)NNN)%NNNSݮƟuprrO>ob~?'''(899|S?㤢>?)ܹ# R È1Mܹsœ!>PT!*n&ãS|~?qö;;xRK$C|ە x/6ٗ >yD}繻JmfzFzh盠B'/5VV` 10U-)./^@ < Rm1`ѳ?|WQ[Y7acH )e{j/^@&~6 !0 cR yz>^.WQ_Y!Ĉa~~xG˗qem vaQ0Ez}WFuBeIIX}7hBX RY*#D@H4yy,˂i(Ura|Hb O].HbEh?8V?0eȬF]rvF]J LN?}B泂v0m;"M˂eY0lI q` .0M5?2Fv|>F7"{aAieDѾAs՞z2zWAjFiscz`LLXc;L$ÿB5*POxO]fU1+X[IYŗQ '&t%;'K|#)0UWfIi#vPcM_$&$P(dDw|_ &n>:tI=t[$uә FMxyILwxmR椩%mN3Lt ˨Ȝ4uFR]\q{p{8 S;>Li<9q|ꨝQ4.XœA8IWIy⇣u|q#iR~GiD,T&"Mu0 IUG㖠349'UϠI(>'rx,*@^1X!F 裥椺GPqKW;$ISuu#F{,N5΄ux͸998gNz-&t& $K79b9Q\10͓M6]J[y6STN?>m>&%? N;9'FeiG7>Ztq~8Y ǔQNȄ>u}QL=`$⫧Ϥ,<fR&y1?:dП&>#D ދO[ׄ=%O~LG0>QMedՀn$zQgq>LUA{PㇷI*UM.OTNiuE\)7*2?bR4 S&]=iqu mx#U}6b &7ndVo,,A`NՍIՍa^:ɤB#Ȩ<u4Q0M`2az4AwGARN.r?ʃ=]+ #(?j`{?>Z1>cH$I ex!+`=rX|<=GjQݟcѺ΁S: ="|S=]ϸP|g )Yj^mx5Ԟ^(dG1ѶV=AMȜ4"]meȕosս8QOY >:sUM! W>tHG`f?:݇CiLb RuEWj a'nSI:MuK]Ȩ#(Ȣa?!~T|<_]F鐴>t ?g0ImQN sё|^C)yM|Ȣ[s>KD:5ʠJȨ ߯ŦAŲ^j dIӀJP=d*>]6t|)qͫ 4H g#=w;L:R^)` R ?hN6*Ax|da%jlǜh.ylQm5IpP _> @T<|ʥRY?s4 |wc2.&ޫAFC,/՞j?_Tt'n4^GٌJɨYPaO|5 i^ҥ$n4j蒦` f?.t.7u@݆Pە)nsvYzz}Xb'< 3:a(Y؀ Vxs@3|e{;FK%B X#&b 0P*&l)q3-?>j5\_maM%~<3JGJK(>Z?l4R2䔤0 ض -3j6۲ 1ASضu !'Fkkv?zg~•UH.h[0oFu7 xAoxI.ʥJaD`&.]~gggp\Ia!/c0Mr0\iG7E, 1\t [[8y| z<} Bj5lQM?D)hK{{Y`OC} `XL!Qma>ecT&w/7ar۶a&xPld>#IM~<DŽ` mhlOzujJLJЀJ^gguh4h?nHV;) c,F^ S:>W2#M6*zɢx">**jvt.? uMKm葿OG)EBpit[ E'&=^g"_*N6/Zy/>'S(>rL'ËS Œ0٤ʣ#Ǯ)fŧ`O)cCvdS|?eī8ӂS L*GH(QE+ 0ŧ?µ+HD@/pU܃Si uX^&1rCJ&J)~sRa(CtJJ3Q|L*1V]? nHɂB"?-!OsI7's <+cF1)>_CFTy>c_[u>`>(>_NVIQFWvJOP{ԠN/ 0Bx#2$ 8>:*Osp%}|,!EHa8^*OsHJtpLsdx} Is4\;R|'>sDӧ=<{:-'l U O@(0b |5!Gs1&ǽ8#صE[mW&e@|QqVfy湌|L8NI .ywEsۧ7 ɌEs.r4[z\66) 6) >2l|ZMlEsz$%~7h$]>sƶmlooT*i'O`1=|yzOν7<‘lV|~Ǘۤs/^{C=<<L8,F'_<7`hĴN/I=խ[G@7|]}4h^47BIR;'(䠅okkG@moxM?3 7^}}d160 7~`|K1䰤C~ S x}BFI PxI PxI PxI PxI PxI PxI PxI PxI PxI PxI G.2Ʈ !>✻199w1Ʈ- ߢ|yϻ\\ŃgϞ^>ҥ|J?J)7v;*I45?}oQ\vMY1L2U}=aaYj1VPHbFfLX]xmm [[[QnPİFPHb2i L}\V^^UV v_~Z |K1r4yzjzBiϛt)o tc|2i3y_7oo7ߢ乌|4ˮBH|i5OE:)e㣑t \6>I0e#.aG%sȤKI0e#.aG&]<0efRXjJa%e䣑t \6>IgeeaFR5xm\:7ߢ乬|ZLZT3,b`}T*|R8[ {1Ů/It|K1Etg51,FvaXM0[ HyL@ZVwvPi4xz` E7R \&0` /6|{plmYxypzcHb2i> )du-y!%Cz|K1]8Ko#=l(|2).j()\&cp%e7ü=J}LWs[5( #n%ee0RG݆m8>0*nͷ(y.;_nJT g &)ѷ,MR R8C@@J.iӑg _}5SEgcg73=sRs!lӄ}@0wtsx zlj&>yss8, RJt^cX)ǧ/I=&+@,3} \|F>ӁU( J8OK< : %\`0ʇVx|rp(`A v 9:hyG3ߠA90DpZY1MV ,h@U0ӧtI\ o}8/^h+1.Xx|ܠһ밚Mƹ@됕 ;zF^a4RL$|zǽ>]B}zfYj{Õ2R@#_sۿY /LzCP/p I9x|wI/.uѓdwgX /?M3)5Oi캼vt}6ŮMHb9QbTi~z 3oEsr@5PxI PxI PxI PxI PxI PxI PxI PxI PxI PxI Qn'IENDB`Carla-2.1/resources/bitmaps/keyboard/export.sh000077500000000000000000000017471364475620200215510ustar00rootroot00000000000000#! /bin/bash # Export several areas in keyboard.svg to optimized PNG. # Dependencies: Inkscape, pngcrush. # IDs of target area rectangles in keyboard.svg: IDs=" white_bright_normal white_bright_hover white_bright_on_red white_bright_on_orange white_bright_on_green white_bright_on_blue white_dark_normal white_dark_hover white_dark_on_red white_dark_on_orange white_dark_on_green white_dark_on_blue black_normal black_hover black_on_red black_on_orange black_on_green black_on_blue " # Export images: for ID in $IDs; do inkscape keyboard.svg --export-id=$ID --export-png=$ID.png done # Optimize opaque images and remove their alpha channels. # pngcrush will not overwrite input files, so use a temp dir # and move/overwrite files afterwards. # pngcrush creates the dir given for -d, if necessary. pngcrush -c 2 -reduce -d crushed white_*.png # Optimize transparent images, keeping their alpha channels: pngcrush -c 6 -reduce -d crushed black_*.png # Cleanup: mv crushed/*.png . rmdir crushed Carla-2.1/resources/bitmaps/keyboard/join.sh000077500000000000000000000010351364475620200211550ustar00rootroot00000000000000#! /bin/bash # Join images vertically, to create a sprite sheet. # Dependencies: Imagemagick (convert) convert white_bright_normal.png \ white_bright_hover.png \ white_bright_on_red.png \ black_normal.png \ black_hover.png \ black_on_red.png \ -append bright_sprite.png # convert white_dark_normal.png \ # white_dark_hover.png \ # white_dark_on_red.png \ # black_normal.png \ # black_hover.png \ # black_on_red.png \ # -append dark_sprite.png Carla-2.1/resources/bitmaps/keyboard/keyboard.svg000066400000000000000000046541141364475620200222200ustar00rootroot00000000000000 image/svg+xml Hover Down External Workaround for https://bugs.launchpad.net/inkscape/+bug/180890.This text extends the area of this layer, which avoids rendering issues. Workaround for https://bugs.launchpad.net/inkscape/+bug/180890.This text extends the area of this layer, which avoids rendering issues. Workaround for https://bugs.launchpad.net/inkscape/+bug/180890.This text extends the area of this layer, which avoids rendering issues. Carla-2.1/resources/bitmaps/keyboard/white_bright_hover.png000066400000000000000000000013221364475620200242460ustar00rootroot00000000000000PNG  IHDR:L& pHYs B(xIDAThO@Ɵ8k`P*".-HBK{GYm{𰧥ePbvzp1dvqgIHQjb0X.w0Jֽʏm=%^'΂p#ʇ0Jۏ?67{~<Ƃ`Źߊ\|CVCfi^J_fq&Q(%UaK#`3[l%9:aA8 %Y.$-JtHG\*JRIU,JfTR4 Y(45REC()V_ףoFr'3"c>c |a:ŠO/h{hRty{=V9~o 0z)g;}c;MOˍ oe3׋(4E./z&qv .6=0D;DauXOF;wcSXc^N#.T%B*iJ%UIP9DYVB*Ybz)$L1N))& p'DOwN1s4- 3l%:,YُEڌΌ׿+Q\;u^?v? {xNIENDB`Carla-2.1/resources/bitmaps/keyboard/white_bright_normal.png000066400000000000000000000015531364475620200244210ustar00rootroot00000000000000PNG  IHDR:L& pHYs B(xIDAThn@gd M$ }^/KTHQo$UEr^`6Zɖ1˿u& PxN!Fݮ "i6ܐDQN>y.Þ" fY]Ιls""'Gk!"Bs>3B8MHI;G]""DebLIFDDy.-_pq椡ӣڲ4 J|r]b(? `92ĥIsiɘtEbABՀ T8/\ HK\5iMZIk*TMZVjҚ U֤UZKphХ0!C[OO}sۋZ+{7SI Do~ R=[ .rW' L4ůOvs6ʿQށsiV'j_?殗$x%CW" &~SvJcxr0`L8Ԫ? 5ig*9|x7 p|O\GcȤ.Ӯ '퐎8:~~͒xunVB3MBg-aM Z}g6D}WeWkҚ U֤L/2ԟ  g.2s~ˬ4iҚ\ruqY*]_,IpS K5 ܲ8 ~E=Y>CEIkLPE-IENDB`Carla-2.1/resources/bitmaps/keyboard/white_bright_on_blue.png000066400000000000000000000073621364475620200245600ustar00rootroot00000000000000PNG  IHDR:DE pHYs B(xIDATx\˒Ǖ=7f=ƋjbSDKe-d#Ɵ6mCv;|TVэl;)u2̛ު}8ʃM|o @P"_=wN%¿rțxݸlJw`|??i DD iш4M\.M֚'o6iE"DXk0; 5k#"@,áCīil&#fq߄FuǽXk13= *qstXWV @|ɭѰr7l,DDDPMjhXk(i-mǣi(LQ*#1(UQ&QE Vv^MÈ.Ҙ> )aUVq,1eJ1aa.)R :ͻZkXl c"D `1\8V^&Z+khl#6Fq0qL7Ri>"7 :ٸ bE$"Jk@DHJ)dIVjgLEJGg-V*"0$֪㥕lڮ.:)S;WD{ljn/1R8D@@rLXO30cg:8^*lׇ D 0zo tqBZ;Eg}+Q}Ɗ>q2uTJF"B !OYIi&H%!OmWBYu#VIyean 8B:xs?Kl%rXouJTg\!"QI' 1;S\(a>ⴛ-x=/d1Bd>7Y!]8 iY++ɜOwS 3ͼlW&4ᜫv}~(d_^p`M)SE &>岅rU}R؇Wÿ^'z$o"g;>?әf ! +edCY啇=ړu*чC E.蒒~W3m<$bl=HL& }wU*+6uHqC`'0hcf^ʓŵy^kIX]X&ӊ(H[Inc󐲳?'īX}]+3yrBw uO^0ŮR \;EfI 'T["$ VV^ ktV}8mF "RZCg qx子z8^+$aa#dhu&*A*Gy6E;WB{v@|h`x(xHꄝ, %?VC⨦uo}]R$+8Wϫ􉵝Rbo$^؝U:Z}sr#_,b\å>fyV(}+ rf!N$/@up˜+ITDm*Mul-'{GJMuZ IV*8Pn0# uL9!3E1^6xYw完Q_0~*mGZ}^sYr NH(G)6"i[6^y-ye8f3ƌ-O -F$%nyJ}$>j .xo()bw#.8f;3U$wܖu߲ 8I.$ȉfXZ4# 2}s*}}<Yc{j#}8 J>ճߣ8п1)ZHjYڝ$C['ګ!AES4чo;7H1{v efp5Ͼ$ y!l?vnѢ+M:@$(䧉'˜Jph|(!?#Di:VZ6RPj VxeQh>eLwo/[L@bJSB) lxN^zWvO@hgF =(bvƊT?~f}<+R*ʼn>K`XO>)ei* >vfTפԪ>ޒ(U]0Ԥ>?^ie"rULt2rټo[6`M&cm54j6rټoGN'cJ-nVhŲ*F\Փ?~t4x)&G>NJvᥔMhl*`HiK*9wzSw߂ݿ!_nNGd6i*BlLUgg?qYj^DSνx᪪nH#wkG?G'_ԕּņ몺sv#OΝƧ'U]1w>/6\Uɝ7qtztrr\%3_B* EYhoy/ibk tvv=ʲƘ¬e@oƝW.iRJ4u]Vt-['*ʂˋ]4+D^_~GGٝ׫T̲ASgo|amq4kSu]UffAǫ( =9ym?R}cZ”UQJ+жé@D 2 ͚Y aJc_//ƣh85i6 ̖ GGGx68&UI2xif&$P*U@v^lXѠ鳉FkEr9px>r-}85g)Y(a? L}|8{}:mYQ i" D`ܭKu\/6p'xm^]H3I3W=CVۭ0I~\<㭛b,:7cͤ;J?0n 8~= '/Ogp'< \']87ܸRAx[8{z=q8ߏ?3@8}8A$\h/;bώ;bvs-"0"қJ=a*{kX*kAd-$Enzp 'VpϰNS$ELW8 b>59*0~OBX4Vtcs1p<哿,yupL0_>gp/2Z,@ܯc>?{rx7y̫Z(<{Xx|-Ԅϻ? >y]sOκox@\%a\'yU/O3 f؅KPX7OoZ){/z1Ƿ?er~`IENDB`Carla-2.1/resources/bitmaps/keyboard/white_bright_on_green.png000066400000000000000000000075421364475620200247310ustar00rootroot00000000000000PNG  IHDR:DE pHYs B(xIDATx\rɑ~HH$;t/cE >>ɼa-G=#҈$@tꧫ@(^kBl|UWYY_}lSg/KQ"P.,׋˝iί˿O.q`՛ū߼^_nu^<>-iTz}F[Tz|uoc1>}6ZiRD $(WZ+u]V i#"1Fk _>>NfJi""Dۃ֘1Ofxjȱ""g\swi^&ѣL# y. t2>*ͬ=cI5)R",l].1777 cc[VJ)k@D;bEQ.7|XTJ)@fƮNW}Ma7]{?<ώGR*x(bQi>WCD j>c"գ1@;#R$AjDTuO߱u]-L5EqB @ջbkŰ,ˈE f4(eQvqb h8J[v ʦ}N%[cژRH׽bkat3cڈ4"+vWLm5Mqv"Z )miǧ}[㵪oѻdv}RʹC[E@H+wA)u8Z+thP* S&uq@ LUD)"R祕QI)V}hD*CyҤp&I\ ]>^v@`s.#(yq6##`b8)8^5Nx_8܊7}~9"@wdqbCO9'sW6#t#fg)qxn&5Fe1j&H"*mzO:l̰Z8^;~}ܣԊ;^"CuHowDc Y>#c8#}H*w3D0A{[ae$ IG랾uܯO1Dy#:*vgx̌,5+91^.wg:l̐a{}4s0lokXY4#ȹ\.3bB &%B Z=W/!b7=&F8X\1%gb*sKlyHą19>r>&BlGD,c¥^9~0q\*iz+/6K\5Q%2`!f~}u=W f3w/`bG?I8=q5e+ BGZU%1Wק !Kr`3!xYBq "{r3ͦX2gm}'P[ ̈uk}-L[y D+(7ruP^lNo<8^6Jp1W tQDΒ OV]?ޤ%Okh+/܃w06֣ rQ̕v8TfItU;b |RYqMrDB8'}<ү';ƣ䰊3qTȷ), @HqPQjy2 IL>_ѧᕱ~}LzIA>B&FSAAp,-3;aJWd"\۠OYN[+{֣OI8{*y_#Sxf$^-o;n/4j\o+,BKnV Gx4}f}bp6hAwaH3瀑3NvE!O.I+דyMR4TJq} S'CҰ+́T!ϸ̼rw?´ A)9>}̞=a &kv u0yծi l!mլ;O":9{it oMy >M|K`Pq<$gV&,c3Y^y֜|Z$rgbnЇ\ O ԯ G#q| 1`'iȫ4>?$EW0U]}"̩RDOrG581HVE˧DLePl!O Y 58q쩱[ym'vgJ;a>=*C!7^$*;8*5"k8CTO7[y!i Ii[EQ)Jѫ \I9aGiSdgOZh0|9U:IE#Olᥴc4ۅd8m"h7 *^4jX=bJpUz6uO>lzUbhg?;xdz4q8iP)=;|b>pl23}:76i-5neNf/Wͭ~vGÙ6j]==uySJ̿N'3>bx)GWoN*M&)߫il!xEBBz@_@ !">q&6==?Uav(ɧϩK'-h6ylt8k; =SC:e y=ϣ|4t0OJ?7=8^rh*9 ~l0̞͟X{>c;I\*C@r`9?;?9>Z,n+A]={vVUհڢ(b',K}vW/X,}\FieʲW(V8Z8y@+jUp,\8?f9 1f>`>'xWe)r< ˡMǫ,J=^!(X[ eY*6wxd`Heʀ6F۲(Ƈ\3ꚹxu}=_jZmÁ8_ *JkmGpRJyȻ2ZAQgx W)qq;}ڮOҪ^Fh4ݪ,m}B^Anݿ8 c6DaᏑp|U_mĹ,7`NryS"j}MpZq~8w&}s3K{c7JC 1wHPzr`py~ C Ec{ր$+ޔ8|דsK߀8?v/o ee݁c[=΃q? O=ΏG%WL!^=ty8&M͵R>bħ#NtE{c;6%)gBK=qpLa՜kF, X@R5s*W{c\|xՠ(Qa/9?'Ň 8 xbXxI04F""=1>\|X._!`% \.?\|xaW7Eˀc%rU{C/_\?߱_MBx3(V>;.1<,z%_8[~()IENDB`Carla-2.1/resources/bitmaps/keyboard/white_bright_on_orange.png000066400000000000000000000073071364475620200251030ustar00rootroot00000000000000PNG  IHDR:DE pHYs B(xyIDATx]KGꞞVX62B>9k8}#0yH8kwg+9ԣSb=*;|+ 3"_: @+?~d"/e.F/7%a2F_<> ڥv&cyU`zQ}>|aYR@Ęj>X_,Vbf<|+N DDF k~?os9(J)D@@@TlYx\s YϖJq1cf~myz<$%珓U.I>w狃dHHb3feYeIDZ7g[Y1uYD@Мa.of)AD$cD0e9(Sj5[ޚL@qtyx+/f>Ȝݜ4)c03guV,G'%# OJer͈XUHݡTUeYu6j8b09 H$""bDX'U #lRX^"|RZx^UuJq}X)XΘ3QD J1)6\z[1kfۯ03gѵ1`tXR0b͊5>Rm+Zg-},*U%q}(  *Q,[""HD 1-fA"y!%׮,rDH5&YS$Dׇ Ɔ->nu3)NW\c1MvS 7ٸWKA^&Q (m^b[dYڼĤ$f\SU Vݷ[@,C3pe7sF @ },$L֧`Wn\HĭIy&x|cԏh&8P%L#S.v.u}MVKOƥSs|8O^wW(nTL0}84BL$>N4ЎPMJ`2 S͎oqhW*y}[blpn*|EK3IdeƇKl`i>}4F.J2m}Z]|vQQ}ZX] FQqRd8V6c"hշ8~- nJcp^b0;~ Fc=o D쨭[qvA jV)S㠍e@Bc7b~^3u=`jVCM}0f\![FWLVH# W1QL~2s01U1>u6; Zح%[pkL{ñ /la-L[+mՁiCv\h}oF78:Nh%-+/v-}Lh"vq|Wi\йd6u |ׯvM_7"ң'[^Ɍ #əJ/icy(>q>?]#L93S;:M8B ((aI+?+QHsL+qxSG }Aoĭ i$)eB zQ^XocBp{zIW ԧgW~46icRfG uR;ryVRwm/m^qê!}سK ,hZcCY04#4^: Z젒b^i&>~WPr rVrXE Ӹ6+Y0蓌_"Wi\(NlqޑUlVZ*]Jb:<^u΀JXl!b3crGyb 4ďnER}q a%wc&}@u{y%k:+qt`g7b.ǭ105ַ$Bw bQڣ=;Dmx>^ItЬWߏC jJ%'c%  ܇KC}2O} uy|]y5xNhRD1Mh4/HbFR/Wd;xnR PRjć(HYQyouu ޼΋cH,$Lo`+U6->c: GyYFƽ&O̧۩ƽU^k(R(HKa4b-WeO#u&Gwo[kR, {e''OG1 rL@5N(/Rj\=VV~r i^{y|u-M},/Rj\?UUzyr:@$>geﯨb\!S+ á8:!Iq|5@sw̯~_{lZȊB)nהO1*Dn>~w'nj:'fv79egRgnk"|R߾0Gn_d5[VeEXuq9Ƿj4p^ngy4y$u6RX pp\TU ??D|sP5]8/n|<3gY^L9H]hxٙ)KcDĘ'It^eDt΋GϞ>-7ƘEL*bM&J1},%L7>A DBbVV%+>}!4z}n)u%1FLeИӧgy1_E1-H )]LOONOb5[?pôx)u6/LH1cQZ+AY>5ERYVt6.ѧV}RC>j~p=εb&Яc#Dra·|q 6|Fo=p ӗ-Pc"~60oFz/5Ž=u;w$tGV:{u*Jf_#~ǹ.8܂C/B=R}jx/ߟQhǡ ccU?8`ZP/Tf J}T4 \7(*D O0}7nG{q?O׏~ '{p9/٤4wv1F J.6g{kW_/Y;yCf8)챍'_z0<=lmqZ_<= `ǹ^8 '''e[DMrsrr\/ _mܱyR q>z?tF 5/f٭'{녃=}V#^2IENDB`Carla-2.1/resources/bitmaps/keyboard/white_bright_on_red.png000066400000000000000000000066031364475620200244000ustar00rootroot00000000000000PNG  IHDR:DE pHYs B(x 5IDATx\r6b!իͱdy;%<|A^'LU*SIHcBpIl5TYF䶚<9vlRJ9IO;8@cw 7or'I|{!P6=0c"VD~{\yNJ!# E),fme/_|5yeY1VDBH)城G$X ZkKϞGG\H -O9#KųgmLb}p|<><R:}_c_b]^~pt4υNbx\bT:<Ju#d0!"""!Z׌JVRzepDLшt8d8$"Yk 5#^* "'u ,=8"$RʟO&gg>H)V*U" ֘[k1]\kJt8Jn`L$Ic5cR[x2҃A>XFp$Їycbj@%I>cZk y7֬JJcmƃJ)۵er)#TRJ]" Pٜa&!ZKD$ñE~F+&N8fn^(T<%0N%"AüT[ɗ3@"c nƀ15(Ws&זyWwڝe:ܣO!Gy"B%7-so5K9z㾸܋tq8>.+wO 0j,&wG͹idyjص UMyE[m^{]J}dx5cpm+ӷh5lL0 ԮO-i+&@˞|YǨ^}"YnT~C} 4,_p^Ү~3}&q@ҩOiw, GG`0.6Aʽ]եߢ]NEm\uo]fq;şؿ 0lQJ/S6^QSќøg๻?m6ܼQ~P-1+/Ʋf~-F £gP06b#!>q>fc=6=].^y0LjЇ=dwE{y>ZJ_) M蕆3o3]( h|zZ}+Da걷oAa0vo _U1 +.֋W5c>U0>5w[A8xO[\ P]W| }.;*uS=78뫉D:Tq6o _;HFN,cԡOƳNG *Bc*Gw]_u콉a>\q#ݥXIqe%~6T +7`K/+>{>ˆI }bngC-=*F$c c z8|n>>{p<[v  ^ٖGBٕp]u@cl|'qG}WH>}>J?.+._K a{+zP/^D0=n}m*6kODzQ/BƩTb6y! M9 ҔoH6 >SM'OK^f}xd2q;ch:}nnYօ)x6Ǘ4/YK"l+T_gl&TDN/y}u}UǓt> R)s}U''d<DU1HT'' G|0h/?gL&''I*)mp*UJ!4}xzXDʍ8~.MIHzcݢ˖%Hwo`_,/[xh:áuB$IdQ>k6%ZK)x2Iǟ<aWM&'GG:I$A>s;"AZre1 ?# {4MBh!m(V /./˷o߮~ J`q1{\Z2s?O?,Fg=ЧZ !.=:bXX%53ZI6}/5=H{F>|$Q$R(xSN5sRJD$AbX.G_h qTJћ۷ׯ'=PnĩX@Uo奄@D$QWzsRXh%"$8ЧW> '1bsp$~7:I@'߶(^-8wGj*,y.*,jusunHzj^7{[جVիW0qZ)7+4^?vspӧ\~i9x A;#{!I8w >} lvvU"IENDB`Carla-2.1/resources/bitmaps/keyboard/white_dark_hover.png000066400000000000000000000016471364475620200237220ustar00rootroot00000000000000PNG  IHDR:L& pHYs B(xYIDAThnP9>9NY@".R)KAX]u*^*XRچ4v>)QK5;_ȍ@VPY(kMĕK ;o)ezg+zo Fbvxp>=P`uq<ya0o Κ2%_Z$%go,`TvF 0kݍD\@ !Zn(KKB@l'?v)tVoiqLs)#B*:#SO%g32!sBӁ8J L&J`j"%Բ Mә%SҊ8@1 L/Ms,Tnfr4 Y47B妹؍.Y)_3͹t"[K<dRSh4;‹s6NDWw\K`Vg/o3 9IŲE֨z)Je89kE|9f U}R_ ~n} ЬEa}5XMmF!X}ZtOUIEUWQbU=)\Qϡz ZvbϷ@StNa(LJ!3^o,gť@S.%NB){7Rnq'RN&Sn4ƏO@'{^0讟~v~nfrTzp_ӡӗf̬֬=HuoODD0~폔s{~:97v&O/9":L8?ݾDkJ&G[hmݰvkB)cI/'ռ;oIENDB`Carla-2.1/resources/bitmaps/keyboard/white_dark_normal.png000066400000000000000000000015731364475620200240650ustar00rootroot00000000000000PNG  IHDR:L& pHYs B(x-IDAThn@;)M R%XB$<@}k$TMaa;=Rjge/vnU)Nz?UcxKi~)b{m)F˧kZ5ٳukċslk  R0xdϷdL]Bg5r^j ޅnD%90'Z$!t\N v{@ ."G Ajl(d0VJsr!"ͱ,+y ")^ykibci"ț(dfjeil2?ϗ(7%YD 9ɱLJL+6CAU6MPimZMk*TmZVjڴ U֦yqX!)P0ug6kθOe8}F'rx1yN{7\,Mcwƞju<)7gZݝi-"=>:/1 8:c+OGon5ižd< )n@dDӷ`@X)NlLmNl ؐ[GJ+N?y|kDMo}琔n#D!h :Ii e{3s6s ۈu9Қ_OHI,ש^XZ߯ݯMk*TmZB/]~m:`YOqչA'iZk:<.̾BC.z뿷]'}eg ~l|Qo~}ikx~Cqe1ӯGe7;J 1IENDB`Carla-2.1/resources/bitmaps/keyboard/white_dark_on_blue.png000066400000000000000000000075171364475620200242240ustar00rootroot00000000000000PNG  IHDR:DE pHYs B(xIDATxMyǟwrwRRl6dIG۲/e$s{>s%0/9E98kq.} "Z)M.;oUO3=#v0ijgWSSݽ@ػqo_3q_ۻ?~tA/ލ׺.?Ǐ>Xk=HbG~- y /3l33!"#VO?~yg_y`g Vvwvdq^}Q&J XXc`+Lzf8]2޸ws~Äw̌f.q w<DĴދb_&#r@Z1("$Bd925f 3%8!]-\SDPDz^@?5iHؼ[ XL?^WKĖ?NW%.-GBÕ~h9ZƬ)}Z HBGS!FۧKcwNWiYUeD _hM&D@Mhq@(.$HLW/w*R̥IVq$M!"w#K_&,/O*Lqд ] .]e PщXb#\'tS!床9>v*M+#]?1rPo)"(!X9pCܟH{,r]er${s`yl#ƭD 7!Ebx XAADD6+=6#عi.l|-"0l3wb~* R`xO7 b3ɰJ ]㛩W]q `JK"7E2NS!6Y.tcb{â,#'UX*b+}KWE4׋4XⓋyhi]0=2V*Q> ~ʢ#~џg1? C' 2Y} 8)=&?{ٸ&7;$U]]աt᢮B&sCZѱӟAճc^a9yi]˶P2B:1qBW"?1/Yץ ӟ +C' 0&XRiWzlHK׼J6Z*S?NWp}]?HQķ$c>$aapwٯ=+cN "ЛǶ8bʝD@"O$.JA蔯B寽]P#aKNi̦iIR>ESfAVoiiEu]#uIUUob*8`?QZ{mB!L]Lno1Gs:pw|畯aTȜ8"J-RΗɱ41UVzZGDD3s9?YK)ƽW׮ME`Pֽc5u ы/}󝛷n*#"O..ӟ v b"DL@CLó珟M~F>_n 779 d4}'OzZ K/wv?s㰪sVXk̈OG}պ33L| ҭ;?xw5~76U]u3O/qp{g3LJuFㇿ}zqS@pwo`Ь̃}s°YJ ^|d:.dzԘ+ڙ}~3fRq҈xzrc<.Ǔw{䚲CR ꪪYi +f*uJӟt:LGl:Ƃ+&z y?=H­xzt2D.֬+4M3hX1k-KqtUxro"23)VZ5M3w/1XlV̕[F1̬ˑ1[æiRD/StqD|8h6po;prg9)X}.֊EVϏE]L iVútZRD4u9D?1 Yw-}5@ZrEl8WÁ58Ъ ҊB&` {$D"`Dt|9묧7CiID@Wd8~ DT<6xMC&`܁gp9s_PPwߊ=}p9*!mᐢ;1c'uùG:ۼNtS .( "1ZYK9$o?{ۓ%Uڠޚ$2zB\,rBb6lZɆT=**% $  ʦgpt|pskwTYD`QR'`c  a͆B{f/fIuݛ۷FXHs&YJ{{eQlv.$ !@$hq fPH@`A 2uBǾH!H֘>WdO֮S``a20Q_bi{(1b28a;zyٿn hyȀ vB '0a V3 8r "y 'cyu*LJ{\>s}_'a$3i`0IFv.PrW'3eܯ'Dq;)&-ͣL+ 0cjMdR^il]}PӹBkcyeFVc*nހCL-3v`ARƆk !Gr/ZmAF 0`K!;j}⾷@@]wab7!!dm#Vnz>>'}>d|ӣǢN+"?`$O 8-ռ}'b}꺌P-}gIDG4!`Qߓa@D rk0vrx&ٸ mZ/eҪaKn&+x22p }[R>NZ%rah?ï#1߻Y$^%Rg.JxEܰѫO0rvYfRa4~*\&HUrd+x%;-H[0G2CaLSzI}[tg塞78K"m}>F)*}BxseOc78h<2p"f 3۳[Ttx%1 r[ˋRHPGG}| s<O%n,D8~Ԗan^Jb仡OD)*ٚ#2u>9ײ7X)C\+LD]Sľ*^H':4ڼ;P{ww>[!䒻 ]`q$@;$I^$2N=@ˋD;Y8jy!Ie4ƽ=~lu8ҺbWb~(G"bowE.M{ g.R#J9&LVb?ކqPRnvsE,F-Ky1㾿VfˁUJ$!c~-i\[P_O"N*}K-/J+e~[plh:")"S>q{[fُ+-Rk= TV}noxiV/86qx#3'~&š^xK7bnx%~fOP^yNarYWvT+jFe2`obx /EQT)zC@ #-^1}jDt!1]UN4q`)IQ@kVuy%2r;׆2BJXO0U9{!EUz|y s\}Ph !ʲz̯WU%c7Dzg9/s\Iǩ$`FWeE]},!AȋGUW z=?Z \Koݝ(T-}[xVK?svQRȖ>2̂Xa旿5e6Q} G0SyYSw bxM"bdc|{vJ| Go5>?p5dA*b7iŬye2CG߈ h|ƍQQI!X{2Ey]T<|8^`( %>WTYWo>W@~gk*| }TKXh*"/ϧgl6_,h[%voުFyey!v30YNtz6kMRJ!3<W(3]WJft:_̌6'/ѭ{UYW{yA^B/>TYjTU,˖cye*GeqnZ}RJTejT&|w>՗z/ QTy1zZ/6/ `c1.ǣȚ *򍑨l>0O'GI)?w 'ZQ y)Ty11TglcUJEZKIE**Sw{> 2|,b [8 <˳,SR !ž2f_1s1;N[adsM8DmF(Y o%qpv߷3~Þ|kWgo7Ww| j88%~>jp }Vhzs8Ne;`;1hp 9)^Nuۿ<#Z*8|~#o91!ZB8QcۧYܪpg Sk1yֳ։Zk]8893s\H/86~}k>_#) Gm LLBY\|vXU3a^FkE^qgZ LkNô~B.f^/?9Y\'ԍ86X?{Rd '=afZkyq<4 3|ogbYWĐ+4M?X|Zr8 nkպbIENDB`Carla-2.1/resources/bitmaps/keyboard/white_dark_on_orange.png000066400000000000000000000071171364475620200245440ustar00rootroot00000000000000PNG  IHDR:DE pHYs B(xIDATx\Ϗ~Uu.w (cK+ %($RE"9pA7K#DD8!Hc{;?ˡgwņ)3}իXkA+>v[YoO/}W~؅w4!&,oTl17x+?ūg"u䌴 |xJJ]{R! Hԫq! ~ŋ?\$R0R̤RZ鄐"5DHQ֚`ZUha ҉AfF@QjFt/E #TJiu:FJ+M'cxq)Fyi4","IL1ѢK " ےC1  1Q#"Bjcx͋2"B@쌰S`1G {H;e0u{2RC,@+K:>P^(Xء]n 0{v8F☥Rչ]K*.sya= 0B ' avSzp: d4FM+E81Ky9gʪ5Ō:xLRWHXX'l7 З;MwcbݚV^햣gëoԩӧ1 ؘ]Ƕ{FQi"nqqVhcqLa 1y1W*b19ǎcZ= K>Po A@@alrTvD~wgd,C%l,^*nE꼘/S[?'=eMs|^ HG G{Gh wa 0쮼\ء%ד.^=SzQyS#Чbt>mB5oD$khL4űaEj+vʥ7Lcꉑs}},xGMlj&Pi/2>1o c&6!e.x^qʁkO+4xay~%0_=I}'6uF#"cZ+:WקWϷ`Wb> =J`c]+⦉61۴ŎSK[oɈ7@eŒLc1 Ɵlt>~ǀBfjVoԍN0zm2{B^ƍ>Ns)1C!;S.Z~[^P-ߊfoWT=0;WT );Y" 5A,G9DgGЇKb䶸,1N&izS3c~>EEN+A* ذ4;ca Sovys} ds}toyL5 vd;/F,kE,^BkՒ a -xҹ$E1:fTms61Qt> aS$ɞ`0?wP' BDD@hUokǓٜko^.skKgU8T(09NhRZ! " ?Kt~.}kcc322h>Ή `.;ӌ Pݿ3::O9}7iݥoKw!)"!d6\Ӄ7V_~c`ee}k' , p5K>L'/^W@mii#"Ey!,|^Og鵫n4UKFpdY>ƞ|:'kW(uoS֮ 6N%YUk:O7?xchwI}k]}s~w*Mhb:N&tyn痂oݸnbƉt8H$Z'M(Ai tx:>ȧ1+k먈H+pҥ;pZJ/Ιt6`f.ڿq$˔MH}d:/fȝ>i, @im0[1E' llM&_\l\FUIDp!}t}kmhag II:\B Y (`Fi6$HQbR)D*M~`:Z[/q4!jBD$©Be EZ(l"}RdORJ )EI ^cl'sTpeue}" , 5A98^#҉J4)e$ v]4%.q N0-oy@rg*8ޜ@˗ Y|uq~Ȳߔ/%αán8oCӇ%Wy(q]kվᵗ8'˙HW:on*o-KcC}1WxS|CX|8'`lPesp̳n#{QB^Ea*8 Gz؍ޜEy R l8Ǿ ⃽ -siD%Η#=phgӭay3̃%T 敌"" ӁĹm8wu[{WNJ+ @>[Np BY[XuUkPal:޿Ĺ8Ɂ91 uwso6sQT5Je&!P䳽{Kۉ3^|78T5Zw?Ĺ8wjTQh>tAMD 9_?Y;e@s7]IENDB`Carla-2.1/resources/bitmaps/keyboard/white_dark_on_red.png000066400000000000000000000066601364475620200240450ustar00rootroot00000000000000PNG  IHDR:DE pHYs B(x bIDATx\o~o ]UӲ +FM"@M(4AR#WSARpk V,grv~|7y3C`~ p[oݸzUֿgz_V9Df W&^s cʘ:*߬'nPJ B@Y6~y+ >y7_}u0J)Rbzm}=suc ֙:M\Y!Om~[~˫áT=; 4 WWBJAβlu}]}zn[޸-0:(˲lf!89:ll$ BJDe@Ehp|VbDqkvƓYgfY&<9:Ë%y0#!!̤TJÝGD% Sis_URh=:N@)EERH(|$jkADz*f86X눨5RqE Yz:MRy1s(IRU} ^/S׋J>b&IGk-ч$RJ!@!LQi-lk$""RXf}K)XY5sJD ^:MI"REY$*^YJ2Y(R 4MŁQe3hҤ2(B4`LQ`f!XZHWͼD11ye} /(j"vJSB:a Cs@<;q ~J 1S`+Q~>W0#' >\|K3YS;ڟg&ԟһb5ȨORp߻D*̬+ӇfFĄ"{2A")yل^} Lv3Y͟؄i{POxT^Kd_vP *9jY"×h.1Z#Hm1}f}Z9hs>1WL֜;aa pKvx.ɍ+#ot=B˫+t%]}>}liƄ.9JnN+v. ܴ{m֧yk Vnʺ\R@'W ƫOJvߘEgS++|sK^뫤BkF]19=&6Ule}u Ĭ +ugob^.SJouMB8֯!0е & MY*tdXde^|R4!+ dU\;B ٗ97 cԤy5z2ap-OCWlxwQ4Pyu>]E%vcWJv1^EZpq:WGo.OfgmOrzf- f^aJ@k:%,ܾt:\v sE0_e}f js,4̮K66p\>; r%h&^}B1+89xj=bX#;ReATU쯀7 Jx]88Vlh}R'Fc8.st؋D +W%ɦ>\B5S57+nޞUU86-VGZt'C.fnL}:EYh7ڳr^ \]ߣ^^lV鰦vS<:̾ R xoE12ՀB*=3g -_vv|:-W!îHyN է]Jfem1d3G,+tĩ3NB;itP<)|w_R+Q Csɬ,3u͢O >n l3sSM9+vf>N#w43xxi$Te*0_ٽez}ᠭ5;)Hkc,ys&Fpp'ijH>9X8+h+*q;84JRj:/D `DJIgK$%Q1Q>9iK9@x)"D a"D +I"?=OsνlnFJI,hEEafԕ"E0?qcws32ùE,h0AiFݻ70R3͛lqI!FDt#dkmmD¹BJ7o~p5O>wk{y5 +umwcw]DFD`sGE~{k+R̽qp(`{Ó߽pO;;;q)s\cl--tkRGwx_yjc#c)8TxQEvw$A(vWH)sgEc+I+Ǔׯ^}L&g+{{I֍t)%888x|hp6wvBDDZ4/'6VJ~R3fxe J?;@5[w"{RƽOq:`0X]_8sqJQo3/)"7AeNڵ}=$D$$xy(4]`m8$8qŕbi fKKa Ni]hȬȌ?vb +CYvؒ% S|~hwf-.q~^8@9[^mV8Ng,M[ycd< f\Ph28<@u|u|58>B@D7<8<MRBL\bX^[^HLIL7<8<DHDHUXSXDHn^^=|~iwwRt=DHtRNS3KTVI4#E3 ==1Fޑ @@(8'>M3M9̊9% 3F%5J? pHYs  ~IDATc````dbfaecgdN.n^n>N_@PHXDTXLSARJZFCVN^AAQIY_EUIA]C3 00((08@SCAK['$4,,,<4DG[AW[/"2*::*&VU0OHLJ34bP361MNIMMI653WcNKHZ)mfckgo"r#/ ьnL@&C!^JTIENDB`Carla-2.1/resources/bitmaps/led_calf_off.png000066400000000000000000000014501364475620200211510ustar00rootroot00000000000000PNG  IHDR7uQtPLTE222---(((###Wj~WkWlWmWmWi|McxMczMd|Me~MeMfMavD[tD]vD^xD^zD_{Da}DaDZq:So:Uq:Ws:Xv:Zz:[|:\~:Sk1Mj1Nl1Pp1Sv1Uz1W~1X1Lf 'Ec'Fg'Jm'Ms'Py'R}'T'Ca=^@bCiGqJwM~P;Z$I(P,X0a5j9r A"C%L:=?769<> @435:;0/146-PҦ pHYs  ~ZIDAT(Ͻ[WqGOBQTn EHȥhm.LbPc E5Jǽufj2BP$ɯ;?N*ŒL>;'2+̋@P¢R^P ˢh4]Y Mf˦fnZ&v;l:=ӱ/: }ϑ Ǒh,E#Љ~8ɳT::K&s3dsB!fD U,]+j|Q*RH!qvu}ss}U&H7f>ѼRLFt!ȐMS$cZ/ϭ'~r7!w'+G_|NHߪIENDB`Carla-2.1/resources/bitmaps/led_calf_on.png000066400000000000000000000015721364475620200210200ustar00rootroot00000000000000PNG  IHDR7uQPLTE222---(((###\^`abccZUWYZ[\\SNPSTVWXLGILNPQRD@CFHKLM= 8;?BEGI5048;?AD-#(,/"'+.!%'*~!$&y} !rt~ j kt{ b b ipw{~ZX ^ d jnqrQ{NxT}Y ^ b d eGrWj{ pHYs  ~gIDAT(c`  vaff0"c`e101KHJIHKIJˁUTTUb  Z:zz:Z`1CCC#cS3s s3Sc#KX ]\=<==\]|$$$$_PXX]$S\RZV^QYYQ^VZR\$S]S[WP_W[S݄$܅$?a }=ݓ oR)IENDB`Carla-2.1/resources/bitmaps/led_green.png000066400000000000000000000012641364475620200205150ustar00rootroot00000000000000PNG  IHDR(;PLTESW:>8 @|| 8 B) D <# <R Lb^^LL < <H HXXHnqx^t^]=|~iwwrRبt;{HtRNS3KTVI4#E3 ==1Fޑ @@(8'>M3M9̊9% 3F%5J? pHYs  ~IDATc````dbfaecgdN.n^n>N_@PHXDTXLSARJZFCVN^AAQIY_EUIA]C3 00((08@SCAK['$4,,,<4DG[AW[/"2*::*&VU0OHLJ34bP361MNIMMI653WcNKHZ)mfckgo"r#/ ьnL@&C!^JTIENDB`Carla-2.1/resources/bitmaps/led_off.png000066400000000000000000000012531364475620200201650ustar00rootroot00000000000000PNG  IHDR(8PLTEm̩Ӵm eknejm\adMRUNTW9>@[ad^cg_cg9=@RWZinqjpsjorPUXX]`qvysy|v{~tz~sx{CJLy~}{DJLgmpSX[x}PDtRNS5KTI#F3:1E Eߎ@>)8' >M31MN?ى3=%KL] pHYs  ~IDATc````dbfaaebcvN.nn.^v_@PHXDTLCARJZFMN^ZAAIYEEMEYAJCOKCAGW? 00(0 XHOA_ $4,<"24@ϐ$*:&6.>:XA],1)9%5Qh|Zzz9" iS+ki#m89 vdbeaqbr2q=IENDB`Carla-2.1/resources/bitmaps/led_red.png000066400000000000000000000012671364475620200201720ustar00rootroot00000000000000PNG  IHDR(>PLTEgS:>Ⱦ8@| | 8BD<<RLb ^ ^ LL <<HHX XHn^i^e=M|~itw~wRbt}'NtHtRNS3KTVI4#E3 ==1Fޑ @@(8'>M3M9̊9% 3F%5J? pHYs  ~IDATc````dbfaecgdN.n^n>N_@PHXDTXLSARJZFCVN^AAQIY_EUIA]C3 00((08@SCAK['$4,,,<4DG[AW[/"2*::*&VU0OHLJ34bP361MNIMKI653WcNLZ)mfckgo"r#/ ьnL@&D!cVqIENDB`Carla-2.1/resources/bitmaps/led_yellow.png000066400000000000000000000012641364475620200207300ustar00rootroot00000000000000PNG  IHDR(;PLTES:8><85@9|o|o82B;D=<7<6RILIbX^T^RLDLB<7<6H@H@XMXOH@n^^=|~iwwRtyHtRNS3KTVI4#E3 ==1Fޑ @@(8'>M3M9̊9% 3F%5J? pHYs  ~IDATc````dbfaecgdN.n^n>N_@PHXDTXLSARJZFCVN^AAQIY_EUIA]C3 00((08@SCAK['$4,,,<4DG[AW[/"2*::*&VU0OHLJ34bP361MNIMMI653WcNKHZ)mfckgo"r#/ ьnL@&C!^JTIENDB`Carla-2.1/resources/bitmaps/logo_calf.png000066400000000000000000000023531364475620200205160ustar00rootroot00000000000000PNG  IHDRG8˫ pHYs B(xIDATXoW<3nBDa,BSb-]٥RhZc0VkӴQ`}a%*bbZ5֐(A16Zm7E n-̬/v:Yf̫{|<Ϥ4`qz|[^$Ug¾F'U7Bs5<7S~jELlPr3 y# V+zZ'31U&p>[ 9dax5(-jmb\\6CD^@nzb}RA{ls,Ap_,T7./r+t:W2;}5EU{< oΆ6SQKk$Xj^=w)9DaL p'A N ^a>^roc0d. IYtĨ!x.+jNzi~ط$6{Ҩ4m春͹HP0eÖXaryW]s + '³hֆö4 Cx[h"+/^u71c{с 5?826kw؃-F ~lgO-ΦeͥP[6U6#B[jUW=qpw`8VlTj*3j U-AeGv$̙GZ;(7~qUV[caq&g/APIENDB`Carla-2.1/resources/bitmaps/meter_calf_off.png000066400000000000000000000021411364475620200215170ustar00rootroot00000000000000PNG  IHDRd QPLTE444''' (Fe(=S(((+Hb*>P.I_,?N1K\.AL4MX0BI8NU3CG;PR5DE>RO7ECASL9FADUH;G>GVE>HJ%08BK!29FM5:IO7<MQ:=QS=>TU??UM@:UB@2U7@+U+@#U @U@ 1 &  0 %!.#","#*!#(%&&$&"' ( !) #*!%+"',#)- #+."$-/#%/0%%11 && 1- &# 1' & 1! & 1 & 1 & 1 & "9 +#6 )$4(%2&'/$(-#)+ !*(! +&"!-###.!#%/$(0%*1!&,3#'/4$'15&(46')67)* 88 ++ 94 +' 9, +# 9% + 9 + 9 + 9 + @.j pHYs+vIDAT8c` `9ZDsaÌB,,,l\<|B"bR2r J*jZ:zF&fV Qjk[;{;G';g;W7;w;O/;o;_?; 0(8$4 ,<.,*.)-.+/,.-/nh,nj.ni-nk/,.-/0x)SM/1x9s/^x%KqXl 땫W^z덛7o޺z띻w޻z냇>z 듧O>{닗/_z 뛷)FeUv7u +IENDB`Carla-2.1/resources/bitmaps/meter_calf_on.png000066400000000000000000000020241364475620200213610ustar00rootroot00000000000000PNG  IHDRN%|PLTE**r***51v?9zJ@~UH`OjWu_f~˜mwǎup̂}hx`mYbQWJMBB:73,,*****}**f*`*O*?*9* ] b"f/#k<-oH5sT>x}aG{umOkzXc}a[pjQdrIX{@K7>/2&% j m O H 5 "  }Y^b+g8)kD1oP:ty]CwqiK|gvT_y]WlfM`nETwp-3w&)~ս՝p}Y\B<+-> pHYs+>IDAT#P׵)(Ee-}d="#BB6E#HBIFI"]R$%eBjtE44IK5'C~Ĕnޢftǜ,=K/ 6ŕÓqpqxGFqt ?qO9)SR9-3B3deyr_xYU~ZC}ߠ-o?~BgQ cdc㘘W|was +Xſmbo8:)S/rKfEIENDB`Carla-2.1/resources/bitmaps/rack_interior_left.png000066400000000000000000000141131364475620200224330ustar00rootroot00000000000000PNG  IHDR<;6R zTXtRaw profile type exifxڭir$ɭ)tqbA:>$E|oFfb Y5K #>Ǭ'5G:|NR~?y$ϯ>)ƻ}|Q}s@2m~~IhZן\ICϏpb^Vy5~ ziKN-CT,]rrecVƻV{tdb9^rٰcԶ+yz[:+Tn&\:݉{qF$h(Ϻ7?^_?/5*X4w68*[8/i'/J2kjɦM"W˺ 5Ԧ#&Z{Z֨ͰIr.fK)(4\-Vf[ih[Ͻ[}9t-YFm1Ɯ93s.]*kn.{=v)vg8Pz<{ͻ][o;&m뿨|VMJyj|Z轅ϔ,TEFR5*5KC銢Y6G|RW~Vo!U7;{tGݾ &| #>{'֏r}B㬛ľ`ޮz\|랚bhJ{noe$>,.f:;_tv>-=qG<׭~ؔB\V]#;a[s~ڊXTU!N\2he VAl>$ J!OAX7?HY-uJd/1TBǶ.u,Рܺlގ=kmʮz]g{U% JiP`ZҲ=_psl^8;\SRszib9 oeJl^%{r`%\lV*vjװv|a%RwBBv9 26X< [v)}U{!;ZP}= eY@u@tdF:Ck õܵ'7:V-חrrq{1d F!vD,dq{nx ل*Xj/.aWF.ijш|LmKʀZ>OcяB;*Px?}C2[Q ʐ;L5?% µ ,]%޶WpֺuH[$"W?p &}n5#q-+HBO#H k\ɏW|*e'z"FӒ'kx dUG  -`P ؏5|Μ^0# A3pdS JZФD!__ )N6:Ah{A~:6`3@ =vd2㢐O) n,9| mc_9^`7BbaUzPW:} @KXF) hb00^f8>AiJPZ:4vj5O s>l9V}mMZY shdP7Cps04Tdb臠;& ;Ez \ :5R]x#QT!q3݇?9\ڲY86L/^o7ă14Wzܴh)z ҝqu{ *GkH PPMWvvWv η\"H4a '^`lo0(41ZqtgBX?"h;Sx!9`eG/I1q1j YgǴI͒rqCiıwux. Ep]0C̓} 54Uc.l=yšDHy}8go 7waQ`0 $?hqOoJmdq{O plBsN0F>f;9 )|PA]` G hj Ÿfj*p0>?R?p!̄7(;XH g_(+8 p;צ:%(:CcSipp~] Cf p$6uUpcDQ^n<bwNged8̱D06 R6M~EaĘ0?gi8(ҌݩN>1 uP:<77Pi>Qe G%p w@G!by۳ Fjp9&lDR7ĉ)1^Gh+!E>Fc;J#(JUlѰ(Zo}% Y{ sxkbc%)^OX>'DAq fLw9G/Aa]=,'FΝ7cBOG< k xz`||3MiD/\K Pa[}p6NBjS9da%EVFbX<b@xbH8;dݶ#-Ml5C؀yc',<[O$Vf 1j8%'cX 2}EA_Jٴ=r?3,k/"&'Qan$_Z<Ș/6+ پ%?f hCch|H!Fb;Bg܃q+2˅7V[$QR`wߘUH3hb3_1@`ZIkc{R>dk_B0vLx R'G"! >]? JƘRM1ϥ EWLJ:7Ds* `eJr;Ee`"~΄PT D4Uct!]g`VJJc\h^4Jezg ' "VI#xRrO&X{䦟Ŀ+o)-TbKGDwww-n pHYs+tIME 62h FIDAThޭY}To 1FF@"tkQUqs?fMj7jmz8snvVj jDlZ]h| M H»?k.Gܛ广=y%B!d:A w)XVAb]0hhТ[O:<$wG{N{N{9QSWSWSG>%7HK@0Dz؟{3B ~HǍ# Iha8[o l =_*S~J?cLcDliL$l@'Dk25Lb0\4\4\$b}11D݊uG$D$D$"4h}c0P|`7d2 zO|aϱs9ivbj1vb%Vb%Xm6Ud+2vJofy1cǬ%?ͱͱ!Iqx,.!lRX| ~]ڤn$IW`Vڴ#ӎL;B ӄi4d`OL;6YZA]4&U`c U+ؤsCgפI_@ҁ0ҫm;8R*\}>YT?b |cjz~vR-$dSr2bzeo<^HNZ"iEl;ߝο1} vUZKPX/7]K\K\KfЙkۮmu^<9D cߏF/QpS /ܾ`pzxԯ4ٚlMӦimڦ>O0$Dǚ,X(W`eeu)U*u~ȸŸŸ%L...m[9rnMMMF[^J;:|`fm3r6Ǎ1]}5jոy=D+5{ͤfmҦ6՘{HPv{~{~{>"e֍]$w%{BOÞbOw{2MrD’ $@Ӭzr= -Ɩd2ՒjIxЙ!Cf?"=D 3rD=p%#jqŚR!~bu/4y#{+U}?`T"b!>gh%zCR&5 whW Q A eFzQ j F:\adZg ]J69:ـtƇ4 [tIis݊ Noaԯ1K%]K%$+a[jUZ֨~K5hD h Z(C7ԁΤ3ߠZ˦HWr̽2 yT444 @K써v}o*JQrUz-xaxskX0`iD:ٔlJ6ťF,Tw¹_.t vr\ i3-|%[P "P]%1hHM&Ґa/Ld===U~D QAX)e-9/mr\\\-%u ' (h h1Į)[;~V{$ i#;.]tҪT?O[(M5ZNaPyk)cb6ȫ zU]XJd SĿNXSXM2uXɭ A}GEzLr']h4udH .|R]}4z1OA 3NS/ESȧXBQlՖ^E@e\PoګO}!wdW M knO ?|: :Ud Os]qƾ/ރnWiO{O/U.\Piq<!T`2;Rs/_LϿ|17Doqqqq^q$:P/o>Yz<@~{@$AdyZdz#} WɚS]Xd1$jx;]wZy޶Γqi2nf|߾ۑ{JI}07{}+z|4`-V ߿ek郒̳ 1[J,{4h9-:`"Sv#g}M%}Q?ū7z3|Ҭ iYRJ-2 kڪfn6oV[k6KG# g$˨>Ƙgf|zrŜ+-_yUW[}57y]w}=O:~)vg^@)|˭~ǝ=W_{7fc5ZtJ׵t-LPRW>fP4mCYSpBwyc_哾oV6mgcma; %:i[h6m(ҌmWXzaigZ-7'NgPxo,2wB (('} ߦj-.E]uj'1hI=ObTgHz֮5 :Jl_J:SKcX9WuV9l^w8 X7,;m뀮ZYK}f11ԨZYVm4_)7=ʢ"r2ًٙ<ʞy4K{noAԉ@}}Jܟ&8ڑKKR)_*ìU ]c'wtV?G.1ա.S~7evmGi'u|6|o )[(02|$0ݹvi7޵n*Plɋ:+0ZRZ5xDk`ײ۹}MTF!2'pa'$͐Ȧ xhJf ,&)$gEFiIjL.]b{B`4& @ P=Zߵ-:ƅ+;^Ѷ$6`D+n{Ph]64Cݹ},S k테xaQfg{^f pү66L|6p`6{1񼰞ӛ 1Z`>y{ $L.u:M)puQ"W %-EM{a\/c ̴bCB*a"T .(&ӺC[CN~&}@jڧ#@ $%SIV#xfJS߅ҪxeF(PS2aƵ vpZi^C?:Go C7\Gۭ4QD霃afjQ}3K0./Pvp|XJO u97  1`tUv&vg =FPRJ%LFHwCS+sh\fp0E?�7CpѸi5ѸP%` 3ώֶ&xu٬ڃnLR< a{Bh$>gDsZ͹#a41)\)D}n@Ƨ׻6cȩN¹ qÈ^N)SM0)m>j_ Y[A @9Ojh7W>)N9o) ezx:ɓ2njŹZk?8yI&E>5B.]YY-bi*)jBjC,j`>I"4Q $:Ȁ]FFr&AMjepq h_%(06k-5ިr T E q>A# 3eoHX, 9F | CULʔoXƘ(:`l#+QWPd:S=䅃De-`pT/F#4xSL*d#b^]GJpr]I XCP ("Wd r ;b0"L\c@yDrۄ t%""b!ADyz@8bC !<%~FB!6;rE`wK5H0?mqpP Kaow1BG{k!/K-f6aOUT Uei(nFedfAD .bTi)2pw|hZ$@FU9؂HK<ŲG+"S\a;3S"D,( 'H=y"n/1P-&CݮGD Uk=G)ŒV 3nL\RU*vmQ ̤.HTO PZƂA:ӕ=H5p=:%1hy<h= %.L5Ag01XСҚ`FL] pJ<>D/&Kw+\+ˍ:ga7R%PtxCpCP:P QF̀e=X<8Z9?t u>5#nuc܀صc|vOTٙ  ߷O~vv'i=1ڿ;aIth_Dʊp#,ar-kBspi^ +:Mu+MErф|#vtSׁR.DttDWP]" ytGtXWa_Gq:P1|:F1 3bp3%>TK pD>lTS'! BVe&H1JQ9V'uCz}WBcFH5YOYOYOِ @k5iN>?}>+x_?8p-g3d%Y mۦ#UM_4}9s[CjPZ`J% B Qp=xxxy'''3bW̯_1p (Y*g6wE3LLSf+ MRT@›& ނ" &,&DYtM&V; ]]amamam7t7t7t|YKʗqqqof`_}O=h&';%P%W\K Ҁ#@|`0PMdY8NS o8??M`D(%NnFQ( EQ^x4G|mW)|_%b\u Tp]xIxa"""N#," j55G@YC'tB'xTTT ĉ0OLL|,Nd#^a"$+-  )Y(>@W__"'=affF8 G{RCA[- Ѐf\p@( n8f7&((5\vQvQvp~C8Ad;V5&5&5&%]R{yyՌ勹bLI0 ΉO8UNIR&yYĕ+g~ 6܆xp (b 'L4aQ2B?=mƘƘtD+s\Q~-sa2SfL5h Z<ꠎvWʂ ~- KudXða v\SExh硝vv8]ۮm{WXK>a0  h!C>a/셽pG'^_ѱ^TݣGuF! yB\p~ƕpS`AᮇlxQȗJ؂ ˊQ!*D.!NÖl)u I}4eUaq?ZϮ̮̮tdjʫ)sgTn,8H$RZmFٍ @`̀_\5/C^h Hbʜ*ʩry8F8 '$P*=ca, l6{J^ w-zhDBBBt-m\c1wێXG#6hِ l}RSJ҃]۲eK 'gjEا_)@|es󩈼%s\ǓpqQSۭ1m5DJ $x2\?,',',S *].G#8vN 5&O ?JyBG51y fAAx ,hأ 2\L.&c999qq M/*GK1N~TSyAp67"XC5~M`(aRS'ɚxކY݈|&u'M&zSo3yi4e[Q>ʇ-9996{VVVEn/ZMn'ϓ2I$w`}u}u}֓[OnQ{DZ=ryBooo5<#CWSjJM"`qq`E2Y,u S!RB6i6 P*_C 0O|CX[[O444x^*Yz>D R"ۋ^ D۽sb)X˥"qF?H-=)[c!l/|noo&l2O'vK^<Ѻo"JX u"h ˏVсsgggkʹʹ$HRtѥE]rdm_g_g_5m貅;:wPg3v=l;iO0a8̸6 zd$ˆ g%%%?+] (/1εs펷hWDvP0x< lnff|ȗ(N>DQAȵ?SNK::tujBuBuBC/xGYpLpLpLod*PPHHoқfYb%NkosbBIWWWáp( )K#fǚkvH[`_`_`Ѳֲֲv777N9Jҧr-'g*XX'@@@k2KRk}2ɠ'<;sI<'=wD'p>Du|bP s<+|5WQQ}hX_"2Q1*FEUs{f'Na?`0ccc7Tb6FBxGASrԾEnư1l 1?J y{NNNLR[n[n[nO;;pN jK#'j ^_%"G'P sω|ko5OOO1F!vggg%XiROiD1:6_j ['kĒoxRϓOQ9*GUGGGs YC֐5d{?88)}j}j}jOgB)Bɝ,9"IK 7L2&(ix@\Wƕ(((|G5QMTS~N_0~I؂-G   ܱ=2ŘbL1!/X~m7|ͦ1#kZ֨59rsd>5ގS:u3 Ϯ]gDDD%G٣Qjm~-(n[-'Xc1{x%K"@TB%T컿ǵǵy8L?~2oWwރD=QO mys.t4>u}TrKs4ӰOØMMMfY5 g c޵6RK$lL2̄&Jmaw.iZKҵ\s򥖞sss4 JP͆,Ȃ,2%KMGQmT3?m& mlxIENDB`Carla-2.1/resources/bitmaps/rack_padding_left.png000066400000000000000000001525731364475620200222230ustar00rootroot00000000000000PNG  IHDRtdNdzTXtRaw profile type exifxڭVm,' )r RnLnVOy)fzTMןE$IެKL :3GYuJ_w~&U^O50Tmෛձ|55}wd7$Hfp%S[0G^$y'"BvAN6br^*|:k83 /ƛ;^0$.XoQMXZ[u-p_9]5' Fo,!/cXܑ11+}j*HwVJ+!Wj%. D^XTks7:oQkK-m,Yu/[c[vm8t tӎ~ ֜]zsыruf a蚠358cEЩt r'g YMy$jPx+?a.us%/X e43oӖE~L43AQ LjRd?uNե2rӂi IWgzev'Mf|E^u V }\N]Տ5m:$ ϲ!"k'Zˏ ؋?ܦ:튤N C:oNҩG|:Zj Ag4nq}9Xk,#A:EpkŔ/8Ȳ;Y{z؂n!874/<"o;* 3#2 }(p<&p, ڕbFQ8pO*\LMāG ~qGcG{~0싡dd'^8@5Ǔǫ<uKk5EU.[/(3{z6^p/EgNDM䒡QI/E v~5#ԘPWiTУnFcJZޤO' frў\@z͒㨉:;ڙ¼piۿ)>+bKGDC pHYs.#.#x?vtIME "5K IDATx,MZk9)sf2 LH)L!e(!)P s23gp>{^ޟ?u=[u+~+n{3RH5u 3\ A:H[$UT$C)7Ah D %-U9bR x`װmIۺB*WӊRܑ Yq:[;p潳U-.--{KK`75v.fDJЩ:].] H qA]y)+7% t~%S)HH2H}K_K=n>l3_0߃)gB.5:ŬmU9f;_yY, hD"ɐgX8ZG@Ăxy o b~q|~>_ߎ߀XVƮClWD(xY~/E/ !c?7L? ak ^5vIPA`Z%4Yku椹=[xwO? ᥄j !\-\0\2K".D>7!Whyx~ MW}pv:p~ts&6L{О2T:X%I|&#؏m03CzKW;Xsv΂ '.?ǟnI0f𯜑3 $[?W0 W-H;i]gx < *;e'C9)'Ah+mAsk\onnUx\Ժpܼ;x(8fyw}H%i&H_yM %e%9%tbطiAU R3 mc_yB`va9ЖN s %\)LL%g7Hq?^%-IC{_mzE} ;nw榙y3}N˃gʙIu d080M)=#di!.]#)y;+z[$XA}:m{`m#HZl Cer  -M&BmtyAH[yd??$hL] RJ=t#f:V?@Z C'V|TZm'xQpēnFsp ;`>qz1/:WA{j+r  qЙzNw .D%]@LJ^ж4E724Ys]I S|sC8'Nx-ZVy.祜^ boCq1_=Z~H{{C.2 %O+C|B|Rkߌg{zO5?ְu`=dB ԃyP> {=UJ S{`vNHH.H( aw;N52Zg²h9j ({d?ؗl[xv]b?a:{!LV 3d vSH]΂ĥ)d =RTv_LSc=sL `L| NЍ g򤔔R@7 dL@I6)pGp^й&} &| %vOCH;.Mf;Hwޤ;8Bk occ^M[v R tz|"ce0H!H %!x*<4 T=3z^ KTJYޒaZ BnYk9 loehyR8 -nۚ Z{w]``2W& _ۚ#\NKNIp$#FOMRIJ47eٵvv]$l [LA. Md#lIY7HQ)]@5bњ&{)ϋA/`$R_;s 8;T LTAd@8"eSifYdjcsO3-!|'_0_s_]i}]F/z?$ i`VSV79$FY/ ܟAЕfI#;Ʈσ$HަE ԗ7"Y 4HelI3 }Z~r Cd/)Cr k"X*~?F;|y< iEӞvO=/)~p'Z'Nmp8-zORSI^üi|%e(m9%gڼB}E)Fb 5Y#aI^QRAk+rCnIP Jt |xN| m@NHݭe7궕L))UP$;vRXR.M@FYROis)y8 ߐ wO@)6d엵 e47hwioed~u=yl4e  4?Ik~gXc74ݬA[?`|ϧO*}xb' Wi< pQ3911ujN c;n2n[*`>l8{5=?#`׳l0-StNу`f\v tRAN Y~ 6vw@d\}&`=i+{Ao\m g Fn_Hn~Uv9Gi) BDP?Bwz !%A˧t @5{^4Ch5II< _Nm( =THWi ) )Ha6;/ F!}Ghhi5:k,do>|9g>x۽[_ş A!MAhDos&΀P=[eBCe!<"aL9D:GF&(Է+h/rFBdF_wwwey  y)1X-aK# (i @2\|8P?o :o#oěC<(^x[@mS'ī{c!/} ^S7v] "<B%B&Bh}hnLKi |,|…™({߂ppu~+< BuC)2] HwܾnCwBN _ppp{BπSʉ:eo7=42L%UfE66pbr9iKI`)88rv;@Jku5H)&ŀY|HRW<Ѕ|)t(H% #9 fV28(g?'U oK rE<N[ >?>/> A68I[%䗒'? )SRJy lֶ[D|(oP {st.]u4cOCR_a{6 Uж7=9 a48uMw3)@juW?{=:Hg2do(\<===1=ܱRJޓ^7o595r@tch$D;EGBv1 ^Nh玕_Kc+xOntl~coA^n ?ʟ:-7ǟ? 6dj\ j7T qI H+Q0aS =9J])S@zɛ: d'Z`+ؿN߰{.?d%)o!F^4~w8#0f؏_=bg  ! a-AJwydmqrC"?nC=Hw-+AIB /KH4['߂kiG:RDܓ4p8TrAWhGC+fٖ6@o[%i/A Hb؁`/v[2K5Y2Ukma[ Vg d52d~92&fL3Og:ã^hhhuٕs.9y:eQc6焳icZj5Ղ q:rU|.X[b@w2d;;8R-\D;$<, kw}kӮpӀ춓. ()l`KΖ`=eHDHnWė7ÿ@>BD8?ezDտճ: C Ylփh w[Cn=~oP? eme د g?qI=lٛ=6]o0q1[:az-7ٽ^P½Bo@hohYh$ Axgoxj{ܙ vkv;Ϛ8Qjj> B Gtp^tI3L'0U/u@ :T d+|(97^Sg3'; r)aWd$Kx '-$N(ipǣY,叕Ղwֱw1@@P/(:C؆vXcw@%s޴4Ab/2+ 3,@>i c@J#@W:Wׁ_/(8` U })?NClOlY,maI (BD!ajr.:47#s HY |,dH)ɖHE#רM _^ȫRC LIuSco4Yr kr2).O=$CANPI *we0)VS2Azvʌېq2h`+ v'BpS6V !F0t`d*3*:v $o$MDrrUjWio  `$ ?SFxޱQ{$+WfIs tՃNCppqn;Aւz7kvT?9&ہ$,S^:Q:`6c.c_[$ zPwWʹ^I_Jpڅw޹{z0hΒr&,Y9Ws2sb͗"!Di>>`L@p 14mPBP^!H *  A%{RMNd^7)wBu:! !(t7T-lTPh [}}BBZm[޺6BB@ji- rF~ytt>`vOͻ 2*AjċL>zJHH^ַ@ %Lv)xd%@|yRrCF\ i"~oթIE?؉[5F; `iA|X??x[ 嚜$ $GcR4E*H`|.#t2  HJ aA9M倷(ֵ'x H^J?@ Sr~jڑ1NpA[hC Li= Aj5}x*܂S7+A= 2PK dAWnR(bw;y=L1kMVAh zQoUZS;kl';dVΠi- iδ !9 IDAT m 8*H%RiK ̢HnbP]Ja2@y >`=xc w(C@34~&'A|Z|q|%+ф}Ȯ!2d Z5 gYOd"DsDANXbybc' ~,^Oo?+5WOC̎D!2U&,9QtNb^6mA\ZR5Y#k@vg jM&}d)fI3|hyTgԣ/B09kǯ~_?  An^ ƀφU/˫^ar_2 dmͲQv=M`)+YNX/ro7H{^3˙L K )RZjKMy zr $Q*qhfpxMnc )"YRC)٠d&(w1ddo? P[}BB^h&]cs`7uL;:GGѮ[ZL6c@g, T[3 YKe.2VF' Ґ R&  @T 2Cks l-uCBM4p*s97{͆C K =($JH=9!auTdDzF> gD&@bĮ!;_!HH%H $NLl I&VK I%ͅ\'_I_& ɋs u rf2Hj7ɀڙ|JQ %eAуL߽gi=/XP dvz4(ȸH -+Dz9xᨇc惇]͆;?lS/ bZJ1㇌<=wFqGQQGd|=(PyJxR\!4lK[ Aˠ)e~>ÂG*e=8}̫5 Rn)}Jҡ7w!Jf.RC5n{'Bftr 1 ]hMՃ:y\x< NyJ!pGE7B SN`Wv9P3DrX.r8D05UO#zfj.RGJL2co[@3!E} r]E):E'|+@ud= vx r AˆeYI'Kj!y@ҋIoA"n:)є)@rJOAȢ"W = g>8IO>`p;;N}B{ 4n'S}܁NOw%kep9; Cdջ~V-Sfثr׸c@!@0W_TTmMC} ) Y%"P@r4Ŵppp\tMvǛ: sBCB !_ ~v!aijD‘%IIpOȟ8}  ߇p,t:twém||'S)wn}ppaNF'N INZDZEZA䭄v ! = [f 8A^P~A1`#oτ@A`_px!,ln 7\jT`H @AK$Ѐ<}  ߂4M<Q6wg8G͇pϼ\kacÀM!$?N ud\F3@jM&hDkOR t 9!kE|#ς̥=aj< 2J~֊ c/$Tii#+%tJ"]9#I8"q $?\$ 䚖[jJ s[ƚ\ m4})*P9 㠁i%:G'A<,ly?m{^@?s9#@ON \;rI.YFAv~W2 9#Џ6qY%[e1H)-e@ k~rN!0s 9) >&ŜYj̒}pб>H7<) ""'> ԦZ m=Jz9Iú@gRm%v7h!v0/!dw(Tڗ m'ڦ VA;gm,0]~gcgR1󜡄TB"T!$QJ!%22D2r~ ֏\뺾M΂xj<ŃpoHI e';&^?Av}l7(-kyZN|SXa~RkM1:Xi&%Y RG:]߸%-i&\69VBE(#< BmBCk^SPo7 Ao7~ޓBhghBN|hJШKX08 J.ta!oMЏrRw=6-`#Vn1OYg7vo0~lz@?B ac9YΑڑz#SdD HHH1&GoG@-AdjKڔDE@#T.hRJ!H>],R=%HI\kr/=t]6wyȝ{MS7vn9yT H'I> _FA_Yh=Ux&]s62mzOpЮ~oŤhQ2 0LS4 )2K47͗`-Avytf$}A{ A rӯLiwm\yHLosn^Ip' "!Z3Z8t-m-i%J\ Ld i 4TײHci*A7w6Ha$;W d<w-7w x<4($-aّ | f_/WmCd\<61?8&d*m,; 5:Og/@klWuap;]~wtʠd,= &Z2祴 2@.IL% &Cy>#L\&I-jeI"J^`^ ;頭"yOЏQ1;v@EtS G:L okn%x \qW\fןAd7ٚ.c_ǖBbS`GY^u!iblmH Hk*}v;g?L?=Qb#C|_޿ ֳj }ή>k:Џ{, QU@h ȷ[ - (dPC+깪ez0 [l.m2]*Jc05U@6hZJ` 2AS Moyt* +hLH iUPw䒾Q`1 CEC r9+ref ?d 2e|QWӫfKJ} ?2z-cVAVɲK|.%H>+>PNVc 'l- /ͲG/ g*HG "Зd;0s_]o JB`ؖ%Ws]K5RW̐%ȿrWy>@K1'{)ON:Y}[Z ԗש '$!,dNE=%@.zRj] dK3 &0q03Cpn#xo;h_;<&oHm,h^ՠkuA:ɓhZ2M&@J I61]'0p4Ehã ^ I x0̦ӟtnO=Orh#&^ cGRd|&8>+6&"pHG--e H[m*)|, :H{W5:Bs2Bڃ4z:"=υ ?wN߹ܞ{9+,u ?6L#4үtIٯ:U^ )9 yt % Jiins ݤ A =zR&aV$z'#tKy(:=w%ЎYi#3%d)NKS )Aq}`O|Й@/nڑv"w6VBdONWRO`7F ْ!w=䖹`_^ !zy=br6Al| ė7ׁ_/W/AFPci$; =7 l]i/AP/'Cp`ܻ3?9rF9krsnAΣcA|l,__׿ 9Cx(]jǁ*7$E d,w+[ֳ5l!HL oAbRQ0l}l`H[O=|poOJI@?( 'rY~VG6s]-/m̅v?ӿ^r@rAH49Z 7 W mr&]9 ,U| c @38 AV$iWjRRU.H#y^g@+= 2ME%5Iв/Lzhm  ZT u (<TMdPl5M{q)6mp n!8d2+J+pe2mpwqen'‰/ː/Q+Qb~y"WǶŷ )`s[6uw U `w0}O D<_, o_ ~jb3;6F | ^A-m[ \SgXf4ҊGR IDATv=um]_n!|+ ne=%{#)=FƆWsf[a0- ?I@*2d,߃6Rd!Zx* L:@byZk}3rUb ;6b6l"#.oC*X,g\yW$\jIt?]^G LulzV|'LL%E5FIdNd|.+Aѣz4ٚ ]6*`oh3d51^^9wn\|} 䘓y@kj5- |7э x4x<\}ڠ=u=RBKQ+;"!Uc.(ƺ: BP<r'jVJnI=~v lN\sʽz"=R~z.$K4#H=z"8NnKoG@יkHY(sA+jK KOOԑVq'A絛!urF΃(\%H2t:$i;,el;%~[6om-- Ѭhh HNJ>|hC~ BPP]0Z^dݭ{Af қ/ M+йi3t PBMЙ*T/UpG yDڀЕM [d;Ld x^YyAn:`t0k{_rӀv"Y/_,)ʠ,Jv1JM,d&@xChe _VYD;T H;Hu̓*ֲ[m= `R%u{=l Cd!'\+;:RK$G HT H)T,d*==@ІR>u 5,A<,m.>(do^4Cupppm gMz6/$IIdER <6|iz;]9kLz M!]A˒ ek`sۼ0f,Uu ) vAàvInWv=7tu 9Cs^/`NY!{$嘜 g]Z?75!abIb.$Z$' CvQp506=kt7uVg٬d]).1w銃V%`7z>n;h7_g:CZ\6Zǯ ҊZ t~fR& =e WеpbWde#X׎1pޡ2PS0Z`ZT1ErUUՌءvm'r&o \ AP=4{қ ,.8 nfׁλpWsςYoen=3f  Wg!f_#qum{` ąm""""#tnRA+^wQ2\^)- *Y/AFr L.QWNq̇CSR T)8I2qLK8 : Y@{V?%,(u3x'33r +3KB+{"6/[614hy%A ,gA )7ЍXOKap[V1`hGOp@12JOڂ{pʺF Bl`O[pϹ=)x(HQ3v# lf܇+n"H+i.퀏I~p]3WtܠU~{W RFr e53f]ln $頃7 }\:Z}s傼^2wZfy sO_@>QX(&q Se| r\vnd=$0/O8vq< ;=NY P(긚x*h4`w/\K .\p׹ݟ^{|`zԤDDfDfӾ"ȗD@:׹<rJ|JR^b=dL %(ЍTi,ɳ /\XI2M3ь5Aa͂PmnL2̮3 C6Brfg˅5jQ0Ae!@H1]u 诺T/ ndEK$gLa>H yJy4պ5N\ ?ChWsV:C:3$ dtnZD$6rO cu[=`sIpii/TֺNw}hD=hDj>Y~a({u]~+6%l gOPs=2\id=))pE\3T:M>'>2A%Gu",e@*CA TSִ9QtгHo(Ć>{ަ$lnb# Jy!M\w:Nޠ56L}QmlA$5 ݀(x5 l õGrPc>9E ?QɐCr_"/y Xyy[(5G:߇-=~(T "iL'Eڂ-灖" p45|b&b^2md{@}N^GB!B^9!0M= G>?sh5irQ.<6ZJHn'Q`Lwe AlK b7umf]zds\ j`I6 B!Q6q #cX ~mC T),I0yG2 hMKi qp2. \!Q .٥` v,JOpP?Ǜg@ġ`w6؉!w̝%!Jv]SM}0+|o4n˄d EA9 n'$ 4y&Ղ?ѝݜ<3y)DߊAk/ =a~s'\AyجN*IK?X5> g'e_[2&@ڔi!c_FvA氌!cVFJ6.}Һ6OM{?K}2geʆ`l06 l7R0ys\Ew+ CUA4[3E`"y xX H_gA;I3rEʿD&J*H;i&@2䬜(CnD^NQЇ)p\,W5?,yf :B BQfy-g4 M͆X(fc!篜9' @Շx{eO7AnqQv;v*$&C;!P`06}YDޓA ard=ȏ2Y 9'߁,g&AT vn`6$* nkRT*S]ۃ- -b+*hzN G$Ky|PY&7S yju0Lcm:Mk&?z3̽ .$ zW9pU%@ x)k&) S$~eAhQo#sGWy95)e<RTkY2S:6R(@ \uxM`ؼ6D`(F_:)6f?u KMtN< YP^®. d̖_@] RBrI+G]@ ]KR4ȫb@,Ӛ䌨>P t);8H#mtCݧ`&f=ڇ];t/x; M|TiBs%u 鮃H\nQ|රn#ؗI K5Oˁ*PR<͠' .9Qt/AjLwV&R dU[+DfԓІ1j!14#;x  v2SκBiynR6@Ѽ( GqUZ;Wv-U4T:TM A_0ԍw+`G/W@lWh(伐36-XRL$Įy9A`b+{L~ t;ھeVmIp\?7&}@% 0ͧQ- fT0OxM:irO2%4\3\6"#" cRͤ r4#r]6Ms]ZY*K5NZQkW;Pp G!!th4xLLTS 撷axi5ۼ} w1qtsg-w\!We玀Lβ{R@ui9H IA Ii(MhC-N2&@r4U.ׁ5"/0~L[=_K-w-v`OHLLxXZ<ēc8_`S`گSzRׂTʒ OHII!rFu~1Rjt Jd 4p{\ ]r. 3sy vHt+?E{}7UЍtn 3tSܴ4L.3XK*< ̀}8EyI^%41v2pS>yU -Sϔib 2C!;nqs;Z|epps_ SVCUS?is4Eu5**Q` "bGy刜Y)3\@~ˬS1q0L[>xmo \FX ^!.7b^t%Mqw@>d ;9 Z]oІ'M?t=t H i}3tVs>'r>}AF.yv:\|p.L[ݯc ӷ?\n7˝WަTwѥC0*(< ?$qm ~ /9BJ~I?{CfXkȹgrٱ  >[~Riyf |LoThHh>^GoHs&/&Mz&'DGG*BI×!|ҝt0dA^^hɨDFM:ѱѡH/{-ѻs=YhR鈁ЅП?1<&0C4G%{gGy[MlzIcD$ILmAђZ45X‡L&n.+g4,Ï_}y>ϰEh$RQFU(TT* IDZV!%{eϸĹ>u7m֐U2߬ +Uu gGB3߀|Cj[s2W> g~L_WhH?~3DwEOqz7}YRH}:USHLJBjI:+/Iτh}T*~_C6\s!8qՉOtO9Nfu|ű}v~VꂽeٻUQpl S՟=e#s:إVTOqU;> ?ћQ J*A Ș{( 2rbX̄pFlDpmlfػ`K{_&Vb`M${_j<^5S=l"qTZTli-e e07A;mm@h Av٧ 9Aֲϳ?GhiMXKYlMUB]' IDATxki3lOA۴v'Wq'Utmpy0(A5>q;][t?(pw^*EWCP+ԁR(PN\ <>OWZf7uP ς;j: jZ jcvzHZ+HG?;݋.~Rѷ"X֥YY!d3+dZ5,Ϟ=r/cȾr\S r~;J>Tvɋ#J2=J^s=K@.uJn/9L(q[ r de䙒K%(_b/d.RYgd'x jJ2{ 2 PgANAVTa?~ ֧Mi,6r8))Upm5;d-utZj`*0hkvf4v2 *,[dU, fp\g[r ~A!oLr$DD=> o~kbP4zrn7hI>#fDrM|# |ǎeUmNH8P5AniUٛ/@Tw7BPn[wΆ+ t*SL G8? uzm:\@YPЗ u@Cv=-}`y+3Ibo]} Xh%۸+bAn0Q3t r ' w u ^Vr@+Q \4R?}:moE*\}Z^Mt%طL/{t!z:raE?ԏAGg?ս_e+Ұ~ 47lw_Zέ*z_iЁn#eiρU]"sgֺU VZ%=:6Zr]ݛ@\VW ߻ ]^wT]([|*(]t(57BqĽP=xHKޝ)R U%U! ҷ8u/צפtvD7}}-P)f2Uw^7>> >M>2O|w7BFv2n5UXXe][\mEanX ]h|bi^u6 OTR׶\A#pV*ҏtIh\ZRRR$ a7 G:>> :ؑcG_+Fúhݩuge5an{ 4No]5}U_ 8YR: & -cs<_/4l9I}MPUՋXr M`{ TQ 8P+^mb&Xi5Rh.v&4~Ǐ:Zȑ~ٸ%uu]~oOv- hh7hh\{ knyq %TYtL@4hM :u;]* `WL;rٰmL7]ᬠË>> v]c7mst3fuh?xt*Bko XskdWme3z&kZ{PmUWUp V )fum Pܬh6}a_|] }r[ A۠lt[8 }bA3fwu}U`9kY|t>] ::`m7ۋRfZH HNH ΐ=um_f 0DOEGw]s5@ApWUL e(դ1+@_SEa`ǭ}+CL})FNbUCx&ml0Xx&ǧ_~$*5{lM)\%;i'h)TO3rΕP1(4z}_@c+w^V@t_7z tTM]1]QbI,,WÓoAQF&iE*>wzs <*jσͲ66E l ^' UAҍ`v]be qςnrNqpQ^v |CƺV}uoCP4갎k5|/@R,pc+{pm[F?^%VC<_Ԝ_DsQ]DWvkF%PaF _nakхQK pOZs<6_h#XGpWʹeZcB+kYV14Lvp#`Xîk J=aڳ(bÌo?\6y=Dգˣ!H_. QhHoOj_)3S!}m:1?ȢoWE@'nanyۦ!"n%/U|#'wLj[~l. V|mQ+Kͷv^**Cr6۱1a c% gF錊|Ua0vUm|+`>ȭsp3oZ%L>,mq^еTJh(X{Mk&6ЊAWXߜšaֆ e_7M ܞ<~}Svm3vc+e,b:> }R}lm 7+@y}Ѷ.;fU*؃6 삻 @:;ʎ. 8EBzjˠ:%bՈe*Cf.S sY!(cY ae">ɇ Q9qA1$%v@ԗe>(7RFBjnT6$^J~|RER[~v:odUn;n[[blh{k`}F{ \'~v AX/O]@AOӟ;ANS5 {= Jokh~֏^6 +A<;ApS8? ]3gk3l!^T2GBȌbG!<7|[mg{2Wok $6JpIv~Inh> u x;޾n*J,h-+: r뀝 p Mi ,lɃP԰趢fMpy/T%H> ]*]ҹ KJՃqW'De5>OBjr:Q~, /k~ 7= GáCӂiPk:L ʤ@!5:К`w]:LKhr 1 +F[ ] Q>]`ݓ? ȔڠzV_@B4:J,= CE>PJpKX ξz 01,k' Z] 뵬>Y!V|`|1g|į@KY=ZCbTA|e|f#ĿXux1'cl B0vŭ@ o CŎĎA)="cv)+g/d77`C;E`5Mcm~XjE-𴵵`NK`kkv5n7= jua7{`4[AQ(V\m. uDM\{,g##@[сh%hg9TSG^$פ$%ɐ>~? z9ՁoàFFAv`,n{@/i^؝"~N.TOtXۦ}o p "2SRCRA~B(Pbe%n__KXC[`V%"m2PiWE28ŮJ`_ ^zV/qAv;mw  @5 H% Xfzq/0 6 o`L0laYXOTeShC7т;#p%ؗn >N-5BO.VY&ݠV `ُ_Ǘ7\۴u%L+me.?}O!n 7A7}#A5yΎyߝ- y%*m?OWCqC@V+`9V;b-!؋|Eݩњnwm]^:ճ`nk z6)z Zs yerh/wSd1=jWRPk&ב `l0\Owkzԛ\ڬATGw(CU ԣ7yUt'm fS^}vZk]iM }p7[AOAPiAVka޼!8~ eh/v 3ۦZ|)zX6N=h0?a]\B;U_S7]vWem5 Vm=uF.TӱîG XXXc86$fq4Xu]bwح{=^˳S6lV'W}\U[b * . .Q6cv==M`4TZ}n[5J媀zz,U6BH,L|N- ,W!⼓W_+o$=7'(xࣂ (Ӣ'@zDjdjy̝ La8p3l?yJF2`'V%a¡a/ R.& }z=5凗]EkO] Cv4m2p׻ǚ,$;8 z4Wn ZhmhiIP+kkm'K`9KN\&?7tݩ֠ڪe@р>#gm8{rM2yʜP<%$"SJJ(IRߔ(H292ckvs{}_~\]f>@f] g:$&o3wRTJxre/H~q$RYdת o2A*u)Co;½B'h N G P(\0Y j)3'@Vo _l I u~2D6пt%P RQ|Q(֙Y2J .i{ilM{!;?vh` XnW %j Ui.M]kzX._Ih4ha}U]|`zV$$YW 4ˀ?+8s ? X,=&=CP;< ?/UA|JXޔf 2\ drA.uкZ G5 ROJJG,]+dH3o4w]sNQ/8f.I1pp? jYI\(i2$K<<|"qIvN;7S#b&`H%'CL|/-hp{̾*SubA '6HI| W_ty_>tRVE`|,:Kg(d"E YZ$ đ;B/\/8oXnђ %Ry ^ݴ/Zx `CZ.v+=eHq.@:YG?6\OY Qny^k&ڦKM;]1 N.!p?r[l [޾N)ϔI p|tyd|(ܐb="ݤ]`؇mGZ v$?\6i^6'TْOV+j^`+ Hd$fv{흷w}.; `D*y`o,0zMoha aP>& ANr$ܕ ݯZ[ yL^ U侖>nqP?Hz'5x=AWeFz(,*7Aj27Z^+~c]RC2%GY.62 !rN`kY R ')t= ow << VDщ# ym[dd RW \ SA ܐT9 !eHK6XO4-,ćKAlJUCgǻWٯof3~-Wǻأֱ[[[9s Yg8?/MvU?~7H/-xxzo/6LrF9vtJS gh }N^Qt~_̕YrT4Uh{߁y´4/םiPНP#CCX8! j\B-H;ambg7ykipkG/” *PYG6&o؁v4{6mɶA~FOk daY&ڠWfhTEPW^nALW5 Hhiibڂ2ͱ`gl]k=?s/a lf| ;@~A0b9XsfD A (d:gBY!`ә!bAƱ2A滙[2ĀY8sf.* FSq" O`j#0MOW nnVZz@P9x"x¾^fW00o_̒v9z0 hv`ї@ V9g{}>mS!x1=#$ A evHs{7g\b&Fz4IӁer} -v& t" eHR 亜i!*i @5kAS5S~E_f{<`g%=npBgCwd8fQg;l`%mvrH2hW43Rpy=䵙`ǒ ;ž &:'am.m[7# . Pz ]` e'K 6VuVӗ/lVfA0:xӿ mcGӍ@+0~g2X=풠*~`# k%I>Qv [9. KfV^up>i@]|q|*GП ip{4+tz^ u)HX Ώ_`Ru~rHZ:_0O@:JH ytZƤ<$*H"‚J{i\ 焜tpw }@ DV %p<q NNvf|H}d`o]@o`fe7hA-m>- y9+5kUI>4)G@5m5^K *d@Oy5 !P{< `=~%NuRo3x%Fx/{U_^M"ַ}[3'-|]2=bh, _DGC͜r O΋[; R|r|ċx+[Ղxsާscec ?6+ |+xWw<1$HGi-#Amqztם@7{ L` VT}ZMŵv9!w B%]^`Zk[ LhPOrēb Y Gd| YOξ;'78 i߷G97ˠ7 Q a)J "RUk3L Y4ntvdV+t:9P #AONf !1;lM7z'OOǿ >?bcb!*%~]?s$*[A{V/6+ -@N^-}\k-R^MA7? qSOFRA> 1pGsr&PHڞ_|m g'r e.qƗ|r|R@,Y:Z3|:F+Jifzx{u}_ ^+eWk𷃿6+8rD6 [?Ss}'? |p4մ6myt) 7>;l=k k%&`Bf9f~jrL$,M02OMԖJ Hy[Vց:wC?>ws˞ J8w޸;p [oպU9S܈&Yj`*= j^=#H.  @%XJ'<"2Lh~F&A~Z tVJ rsЁ<fݢ Yy G$ڜ? gB˄! n6^3C&yܸ{Ёa oI8 %sv۹CY|H@ zJ!QhE+^j` ~^RdX$YIu wFLЗuؔ;4E7{Zqr5yU w/ޞx{;FH۱o A pǻcQ`= @J]rB^p*< zK0SS=%<YTrUM8P@ZJ+iVuՍ3o0tjoЩkg3 4?us% ULg(%A+44T&F!;wKR) qYS4>_..H#6s \qYytb䅠q00xD~gw @.H]iW@6 %/;Xu 5m fN90^n֠u.M%fhkez 1-OQeo`r?B9:h^ RXʃcWȡ!|l쫲o; ۗSl4A*H)2]W 5':ٌ53|0Ar $T^G,Ч5;vmr]%8 D}uԢ18;E\+?vpChXsʆ* Eh G|N C0M':`3 J FRy*cg 4zLi yOzP3AaGgS~m4R 3}[i NJה<)E uJAr7oI1M zL%St +H]9.@M}&ArW9RM^ DBol >|  Af$m a9cZS^we+ݼ]`;N=GS{{ xf<;Xj,=b?؜Xjq+} rX'1ȉFlhaxW_+c=lwiغ@JQX' eس*^kYpbo>o[vͱ?S|i~5k@sxFF`&O̻ hnͫ@5  Fp|!% $&,v, FSA_7yl3OЙ~Vtݱ'b 5_! DO}0o7OC 䓎+9!9wArO.kr ͯOySz;M RD3kpr9eAu8cSc 7:*/E;FApʞ'vp1@>Ts hG_ZAcj'-5=).W@:J]i ^K4)"i ͤM< ;S`īkJAM|D<HHH!Hڟ4r}3 jR!3gB./ב\g!)t,)f'tƇ?(5 rWuqX06^ы`I}dn1/;${ә<οVg-.]Ar+_j4&3T  =aHWe0adta<6#[AIgiZ[0Msu{ܮWNΡ^ZBCuBU@bYgߵe) A_:Fs1$ ܷulwryR@Kn} *t4# )F @oo?%m8 ܷBَ j-}-H(o7V< :M0< n^7px:2 J&5̕s3Hȓp/__ nwI3 : ܕk $ BwgC |!wx9$$O r}t=6܏B#sHNp4GM)Sb-Cƞ̿2w@ ~l^]NuiCx LѲ\ з |RRTH  SzBP+r jYjJJUʁ-oGFW94/>/5c!/V7V^ԇ,*Uf}aΛ!^Nyލ@tPtD?DSգ5!V8^+S^U =k`_`lWlcm `=Yku8s-qƭw;W2,pCBXBn&H8 r'< ܄B>? TPm܆> 6W 8L~o i /OK + |ǦY9+! `d(Μ!Ә򈔐 -<rr%@J-5@gWtIDSd2V]A2@W-q3xl1\/ +kx(kkCT,5vr伟32Y!#'tF9HOHF/M_ җ3!3wSM {Q_{!k;1'*Vq)Z{1u~*7zQs; C$"FƖeMspԓb0(>r\^ /K+i #/haCҤm~KJd/i@E ֲ$[Yc@Y xkIA(Xb??/xZ< bbb!OT$ww@tpt\3u--رx27B,_o􋁭j*_a?S  B.h>; W^bGd} XL[-kT||| RC*K15Ruh'4ҎKޔM^`_\A8“b`%8]"N)1Ƣ™Ugy2畜~Nѐq)sUo`?m7@O , Ԥ&BN)9SLumfdۏ~׵=6&D@=l'DCbf*P >ڃF`lp$韤Eiɇ!uy|ԸMݚnep>tO9h?0K`*&%l`?Pb" wd v 41?L@Z@ r02CB@Fђ$Avo(Aom`%J,sydLi eOhS' Ftak];"mj!>c&ؗm6MU03t, `6]Nt$i:SW dKż 'v ۤ>A|%/ pr%ZbuU/W\%.h:Sr d)]i%]N L9K`v9'A {`C+}_e"zQˁYf֚Z`~4Ct2P&9;d|Y:s 8E5pZdG 'Aִi[!f6 Ns 'Ao!d"{$$CKQ:L{)e"# fjZAԴsp٬.8N7B'C_BhrhRh4И R߂tM* h![k@*׸2LZ[@aSXI~'>0A^|-LY0zdu YοNg#.1s r'׭fv{?3"`08}c`r5c@"RcHf<3 dnAi/EA8 dS9i{l/J\yl;ێ`m0-S׽>{pb 'v0=iK{ _Ho>9vKcu 1`w# @1@{Z"t!Ǵ>Z]] :@iam)/L~:Q+CFcM&"R9R"|&hf;y(*!c@dYN_c3a0ߘ=f7CRV1h&l| F:Xz$Q[H h yI$ ip:;՝_=̔@^2 X?;7x+5>0o$|`+/i,t#_:ŵ>ETb P@j 9c`Ln9 oLXxA CeWū 9erԁEY㲖BN8' bcA HxZ.W[v._SA6_8Ƌ<q`m0M󚙭AI}@K`&dL@dt~ZO\0悔4 : R,/*an3pbx$.[Wxxd`HwbА4V|)t.mj zQ0油.%i;t~smU@6'tI ef@ f7 Ю4.(Y]]w]ݕsI5!xDf1k6 NY<.9ȹ$@M|a*rRU>)h>Зgg>(d3dhMO//oXhh(=WZZ@iFD[Goh4 G{hme= 9~6~C4z{FJ{vتQ(+,H| ZɃ-<u, ,+01Sf΂<Nj<Nb@rByHݐ%=~ 'G '&d-g@ JEG@.3Hv]@1.V4O֑2doA7;hmA6 8!g%ek/\08NkYl&W,3`#3MK05 F?k7@a!! LjwJX a)鶏M]yr@1[h3$RU kr4fv r:u6~hΗv-u^9x1-l= s(3.s _jHy:ZgFgfۀ=.͵Zly[`%N$ЌY,+d.hC?ú\B~ot9¿kUW @A₎u-(JQS(:Sҿn(~VI(^^턒1%HR m =@r'~!yAaFiLCӘB509ۿ@փNu0LJA~uv!Ͽ'%_oy^ddkHf1&&oA2/KN/^]HUBrJR.x1^/ye s~/;BĿ g@ Av`Mф4P3Y 2uA;`MO:KqM3LQ7dz-sdy3dN)D4to>K; i=ҪMwsq9iTps9g΀jZ6?v=̴*d_cf:% )Flo+`7S?6sCv؋6N;Ͼiԓf`؁麦DI! t,Gg?Ot ft#p* VS;){vtKDfY>$M,1oo ?(̓ۊ, t%cJ{ !1>tF{x_Cp1/1 m}D_$%,tu i(hGى, S//A?_[ |-x)}`#))e( RI*=70Y&0!ge9)A6x 2VF0s/kAI{ih28PIDAT|rրa jqfz^} 3v(:8`|sޜ9$8@'ù^IJ{%m"vnNt6@Zɣ2dK:Syd<.A)/ e(Ly^F lp`300'AL7hi)M@IS l#Nj}w*ozNgl!q&@dy@-Zt vѻyv=WZ1@FI a, @/+d<vmfgBbax?%cd<>>қ"Mb1.w6f䴜 +Y ;CA~L%]&IQFRY_N + 洹AO^4 0` o*x6v_vA|yh|3*)'6KbWm,en"~fO;NL> =!X?ukFm K KHS5,m(63 d)2j l`;V o \j.3 Ʒ~ ( zǝ=w?LM‘ M|F)5-'@.KKWIK'Q:#@e6>0Sknv2xtZTc51sČ~+!t< j/FSό0@\?AXK=0Cpowu^s;I+M"#*Jc!mm5 rOH/pHk >1}6y0H!~{'n1S0pv;8kicn4|m7AH#(ƀҊtd,CE`g{*֮S6 օ ?goj7x?zkxK(Djx;ۘ%]%~'A y+/!uꐗ~ -::ş=fs)l!ɱѱQ`v7$$$~ٽt,~@-#`$ Lq1&(H6F@ yI> lpZxyF0IRLrl0t0 6 a4]p2eȼFC:&9{ n/E:I_ݯt+?u^q尤|t R(d?Hm_-<q&]n5GyЫZHIj$&4)S4VIv߂k7Y{^a[`RR%Hjxu^KHmI{^&sCudHKL ?'{";O=`kdՁ(`@.T;7]=`]wmp9NE00U^70 m)PAII%$ @rF.o[ZM7o@*Jֶ3#.=u¥8)t9pϕ6(?|!CX/Vg!8Q炓fm_xAR6+1Pմ̼o\Y2v 2CdpH Z zެdަ#h^(P,3tH|x q 湟)rRWõqf\ T< q*Eifە:P$ dQ#}_>_7/zd̐Are{gkWJ?t5:Ji<p3\0]H&! yS/;&^Yq&ȝriMo}YG-ڂK.e{pl8á7)ka,7g%Aqv`BSlF@ZI+Tjӈ&U?{c-QmO֏WX`灚Lp;sOK[%0p~@eH,N< [0u'C>.yJ:3`ϐ iHUw2 /@:2$G.r`%W)(Se:@鋺[yN@dԗ@k^9UNƄ3ZBf̜Y~Z6fѠ]t}NЧA"RI2A# O_r t ]@e$ :D^ú] 0SNe|YS { L5@9e.B66`I07%n6b(p<D7,З 4IKjT%]{,[ll?ۛ/lP_K]TzR,,^qӞ#\vMv&@ y v: {dt_F5`<#Gn[e 򲴒n]$&YC83^(.&sg3"C"e$=f]] %KK~-97( + (Q]x/z-*(*/WJ땶%JAIJCtchc>yFkFk@43zgvĊbXֳ;m-ˋxe!^ʾD߲ie!;[7l`900-vSv5w$_z\HyTc$mA7LF@%yDi3;']3744 iºa7`Yx*Y-'g@L`X0$ g;+`WA#Qf 3O|ނ(dHe.'@jJOPjIEt΄xp2)#r KesA^i' o8p/|mvWGVB{2;AfVAf̮= {@gYS- !{v즐9"Q͐3c~214s>dTɨqd$2?ӫ7I#5CoH2Zg ϸ2K2ke%Y2 !L'dܟ&#M <s+HG$AbMK;vvGwT_X}`Й:4w)2'f&C%0vwM9${ d݁c4Pϛv@{wCփC8gfH.'tQ0~ ?M;xǛ{{IENDB`Carla-2.1/resources/bitmaps/rack_padding_right.png000066400000000000000000001544751364475620200224110ustar00rootroot00000000000000PNG  IHDRtdNKzTXtRaw profile type exifxڭV[(g$᥈,+v6!g:ӿpD^k%]zi:oQx{箠g O_?=_gscx25}7nH 9ԳE .hnh-H+OE qvډ9-(C_*|[eqfbF^;on\x̒|ro-jyB0’MrjhN\Q)ߘB_>WA,A07pJ+ǂ|,]uj-[wݶ{:R:rc~Ck.^ݼya^e\b}XèY!(g`q  F"% r/p$ͦ<UP(:}fyKx+\ J: oڎJ.c p1 wIƎT #7t,$ںmלvi*hCx {F*s|7/P|,]Ri:(p!yz,18f d$"(|wXHM׊-FmQ0 <-bd]U%cOS[sRc-8u9B/DhuqBrU{֌ } QGَ>g9 ;S:H rKrv !(lbkG&/i_:)E#kHs"FeA ̋ C6O Ra8&sꦥ({}

k+ft9$k`^Kk{G_wgň!_ת)F &ݟb64ٰJr0ay}P c-gc,57YEd:.K8O2D^U ļ~1s!@B@-'^px;ޠaU^_]>;DZ|M.c9;C-*kxR$t8HE|s(O;3Y ܝ{ H |6)_tfkuq;Fb8C}^vXLd폪2[jw> 8B[¨p:;} atV<0^-v!qF c8`y+Ov9۸" ѣܽb1؅&cU1wc߼[#u~Nv83Zp<i͔|ac,𔎜v` z0c6jЎQ;RnIo9OVcp_SF׉-'BczE;VkBth}2D!&VH7yW#n3,JF؜}EA mDupɁDaMeC*$^bo5tQ)p"?W<L/B6uK[PvNJagUPmVOLch-LR,~?DHi?0GG+'f7 Upc8V:}8lĶh7NV_7z3ri; ܻw1a iWy`05}$L \LV~[5~`zI[k|451z?Cjtd\8Ly/~% $ũP奤]^_$w} S8~97t?O d|X_cPη}0Y٣qU "'fލS7r 6ƛ+:qN咼8;MAFKseCjIǰb/*bhN~nT{}'Nc,s\ qF !Ր%sq ' }Ԋ8ZlxuDwB%ս/Љuwb;I.^1D-y{{ U~cyS1 ސ3G縷7 X=I+FᣇWOR1H9asu)dޘd0 %h͉e.9c2R=>jʡʸ,Xt0.ь}S;*8/9VW|?z%-|L9d8q]kJSis,0<0%#Cn6;yM@`Ήb!0&#'la.;M}h*B $R,&xsa+y<>3 u.%`Nnn|@W1Pr(m6zB@O r pӅ](٘8Sl[]غN([iLm!00;%<£E`7%'-w?5#ǘ{+5&HX>-6.Gr*_Sݐxo C d4Z0ۧ Cit_]GD'|c (ڔ(AdKb@>X'#8_OI%Xb χc8@ @yPEؔ4};%߂52 Sr#aYnC6'1Y*r|pg 8ڙGmO0.$urz͇'^nwbh&ь!hWi6,v9b·s KGĘmE]bfM\Z}1&LQ+d1p} ܓjkD'}'"zzf q )v6n;X 6N66٥IL,=ooJwq] ?Jx.q;kM#[ݯ 0ZD1Hz׆:fL-1U@W"OQ?Zx ~&%]?sNLȵTo3&S#6? ze5q6y 7f>2}ra{s֒%a,f~ZNgxzi' 3P5Z# u']&Ȼo=4gO}jd{r|Clz{j<:H9vIpi9-M~ $d;Jt8_ 8YxOD1fD)s`X/t`+/,/k+~f`Ui:2}]t@VĤeݖgw8fyKs:9jyP_Zra4&)ΡK͸JҀ$[ި lG#j( N=&VBDJfD N8f$|bzU/±N1Ym♢ ӫgz9hK4 %|bI $J%Kc5@o 1G1CcXBL Qs2swPu.)hض>xlێ^+|8'I\;]T[K@>81n j{>ڽ H1ckVl__ ~1ɧEXY[2R q )p1qcv{yЌl{!)S>WeOa{ 2a&]xU0P` sz_f]An'R{ǭ ׾~%{\g, gm! m?=Q97(tL֙+^˔9mP}`,Byarc['7y-'ѤE'G=?=8~fx *|rVrXbtF+ sLom?6.ekkCis4|Di?$Xh9]yqTpYkǜ8hcF 'C/JiCv~of%!< FGdJT|~fE`vzrNhW5*NÆ}cES 5@oa(kHxĺI=ZTvO;g% D){P43RNL+dsSH9/w  =!}Ļ{LM` w>>q< )^100Vޔ2ETwF~3F6!8*11<Ƥ8C()`!z ܦ_@^w{1o6 YoT fl~!crٹuu Z45ylR܊ܡYjQK3a§G _nT|D?.v `bcƦB..";n}t<8'txzf́ CR i>OzOd~"a}8쏕s+LMޚ#> P&]|ΘNѩnZ0>:-Aϱ_o .k*d{t%&N. (ΕN^8p]Tf9Ca=^$ q h#ixY9ETՊw?Mi Nr!]+mT!Np8)Vp_(ռ1,Y=\PL!=\+[.r9nڇ[oc 1¾ȴɀYw_xীu‰pga g4UVmc Xmk3p{ORo.ޭb3z7X~T ߾:[0]KcjzbDGka*.٠J$=jYA1 [ )muǔd=Ձ;l2K|+gm}7F!ana+Еu$-Ր0 ܀@H4y4 ZiSYܫu. 1A,[0% !o?:CxK;D qm!Cn]>U#nPr\L[cF{kX 3gjǶm&8WxK-n[̥81)b$##VDO%ncaRr[ |2mpV:*T<:S)KO`x3G1eWL<[vD Y7X1&R+g8u3'Rv|0Jo`{?=YyضbCʤ٬8*O1V{ֱ3:NgΎImyћ#E]8BlNf햝 R>ٟZ{{JI6\׉=ʓR 4qjP؁IՈ!ot8OPYzze\5 Q%ey }P:]ϓxp˚²j.;@Pj~ ?&BbTqCcÇ%SoCL28"}_49`@J- v vOUڬd=Ӵ%07YVo-`g.N (`:1rWͺ.~qyƠUiK- g}-1';3>bq³/f[z_sڬ]8 x4f[bۮ ߿m;ԐjEwRBd6JGLS1޻@Y$;uu)%t8:M;2K+Japɼ GҰ'h(ѭ58bO6ߠ$ŪwU 0sٮJ] R+i7tӠ³eŰvWޠBs)i)✩&Bv$ aWܮ*t{vS^|1:c"ɖ|@qX]gü;l" wv-B&_ϢvjGKRjWxo u`Ή"j-9CΙ՘<JR ጞhfΡ_՘N4GvK$ΉA :&bQq0t֫@BNʮ}P#.bo+;o2lja0k7ګ%ߌ#"yZ*B P(ajxx@R6P?;}8q|XŒWJ[IrT`^V2b7g12a>$Δa <7|-8ۭ$  Brj5L2й`GT诀U:&Rxfհ1<(YXLgzIIq5~.)ǖ7R9#̬ L/ExOUXSD|`Gn%OG>Y{{>7 (!C99Pk:B.j|>{.\/j*GngƑIDAT (Dn#1&:b&7uh؎/xi_c jhrT]ʉAyV3n2efP7WfϪu{W+,,!E1CxG8:yedSxޮb%;N61')1Ң bPJ:N2'|B1rC@;O{j-L~o_7hܮcZ{e=*A ڪf(T)sڥa 1I\x6!H1S<Iľ}8Amw@fD!r);V9=i;͡ҽj e rbq-ԁox7U bܮHU¸J;,cx/WҠ#Gu{g.Z^#*pF XT[V~Ť/- t?c ND+$|)ԊњU~! uP" |aNۗ5~L#G)[JmQ6=EM#1xx>w _e?[10&F+o9/-7< OZ !FFatwf\)FQhML ܗ ;_Nx[sHy쌒@WHɌi/˙2/D50_ƝP x\E+8x,/JRu@6)1dYN eqrC0_{ .U^pK]sߓ*?VD/(_$zoa}νct 0sG6x|L![ ڳlQR$ZM 8}0ʰCS' r/R7 oYu cFgv~Cp0-{w[$KN4ÀW⽈)x˺lq#Cx5a0϶m#ňr]_19~3ς@h~K&]K{KRTyۨҖe)QP1t]oO/'S ؏T':T ,mHП^w(/{-FJ$Ea~4BZf{DO oTM%ƹ0 ֐Ĺz1N r_8ZĶP0TK"Ou"PvM&nϳS0u|DuBmO)]>W^B?yߟV3Hk~7F^ٚe.`ٙ5rRہv_%G2< s%e혦^j]WSHE&yF\4]{_7:jJT`" }褴8sS_5l,#_WجӰҁ%>QИG4|hKy枿_lޙȺju*?nyi(l/83d=ya5VSފ0f/oE_s'N )hW.1۟ ۣ 眊 ΖLS.uOG.,*Vk{?1Ri7e H W? Gxo]BD7 f9?"<SY E\DΩYGc`B'[gM b?z'(RDP g<ZU3OS3,ҀX]@q]SQ. -Qܧ2Jy@u)LJ LtB 9e.pME)0Tpl 농F oR\11ZPfRb7B~3K@Rws|rWxWL愨='2QDHbK-[o.s k;Po`-l.$L 4LN'nKb&}qKsyC``pd9cZ\w$y̗?>gL<Ԅ\j͇1ě<6 =i }o3BbYFɐrgq }7;kDf}$a*B›ӭ:Z޼ 9:O${L[~_P"ʷ/70,bYT@ (8+zO6 O3N)Egjn)? 9}R MG2TvG>IQΣ'g![W|?Of@{:>$ GiGҼ6{Ę |X)#CP֊ol $@AL^/Ի1 nU \7,v /2g.:J}1r_~1|#Ht UA\ӡkn`Kb˩Rw 8M/K/}`] 7jDr?GsءgPCR5 1Qth^@^F:}%KQkP{a |'Dc7{WO<VsF g^5#L#pbl׆g Jsmlޡ!>ZWۍ|4y1"fzslbN(%ݥ-Q96 QiJ>iTm D&LQ=]ge zoӦB&GV޹CY7ܵ1= y‰" #] KXZjrge1ɪ)O*Fos?~!E/zSN?HmgR3?9Jvֈm";rmKP¢؂vk{1!_ m 󃞰 .LCՏ֜!QT? kacmga:u8Op 8 GZbӃn{g@}H_Fe77%!?T>[?/M/?CqasE yַ0%8oyDPNrѧ;xNJWq^huhЊ=xN!8h`h׉w}|aq7"H)i۞9 $l xV9ZL:dz 6pDd tI+G$+wW.pZ+.G,t7G,*CD+|p(C%DDAl`*ٵO'#&:x, 8Q†:"Uh} Fh,"ͱ{ w̉~oܻުT rc^06'^1hlSG&S#>/4ÕV1qSsti EC\ %m0gqZ)ۿ(׍Z+jaB=GqcX.YvJy)>sYSҘ )!OdW0FZQW@'-s9Fi):;P`T4YMbݏyjjѹ1S9Ӹ[Wן,gA0^׎;nBQMը0X^<^}"gMg9>?ZRɏk{J@&vP8:(@&Cu Q-b9H^E1AM.vфHBk/}c6~w}Bgߢ1BE0 \&^w(gEmO\IusB>:\g~L JCf8Q v pFGY*$F>אdqu,!8  @@*@@'*0yco%st:yFʔ!t'xP G5+&0K< :9.]Y!.B'] (=s"TP#Bh'Taaᥭ=U1.D ̺ d_7V1+"ҞЛ>-w 7C >@kxeF cEX!tV=U fŖHs$ Ιa'`_g~{2nrη-D)3Tv]uaog+sm;MΓA>hn3>'1";/DXʟPf8BnˆoMU<ݳ{Ag˟N?kM}Ypضm-nj7"o`2rhe*qӠcNAtblj*,Hh+8vzzVfS(0IqB/HpֵE!H[@oqꍐ20C1ZH+:y4sFV$!P7B6 .* l4 ?쵢t5Ѻ&DQ,:HƳ0' 'T/5dqP }X7l\qIx}ρz]c5'c⺋(PN zqoP1>Mq)pgs6J,=aoDl1]ߔLzbhg}vĔRgQ)'qB! Lv BH6 NymC~_Sp_A7ݐS wlaG7&E0(stb2U37Z%?a1"o.'CʱDjc:z'/3H[BJ/s| cdRƜh zjGoS+T ~hs}A$ْ Eȹ3xDP?Ʀ`cb}>_L.j;{f:~m#=ab>pg};"Q]mjao:͏@ |J75)"^hH8PeU{ybW aKtL9:^-9a%lͩG&KyaPi |THz#6l93  "xtCI#"ha?y I藰Es~`Ή m/< _9 %`3ueҎs+lFk~ZytX|FcC^LlH.< +$m\طN}-U͟T /m"^ 61'ه/@;֦^/&zrN&ߵ'B{Yֻ+VLRDi,pXlѹ/v_yr"Ntr/Z<^"c J-;-JtV)'wVwB飣ѱ-"koN-u~?>s(: .٠eh'p> .$1[CS8 O IY2܆gV5)-hǿ=Ї3"wJ~osryߵ Z9IG@vJe?xm䠡O2խa+i ⚽dIdC\IŎlb`Q]`)&RL>C>w ѕgı(Td>8eWts{ > .8o1*qW˒ Ԃ}4x[A Π{Qu<{Q߿m+q}vI$s;'/Zc@d@P;ǔƋw,T-:ًPmv_ux17; N(2cdSbM;vMɥ)Xv_RĘ,Q:БbFJɺ9&X@<wa`ư^g"o;J)7xc4܊LsuM*KN)Om|d1os4lB+ C(1mMy = '#NSѥ[Ee!^!L D=v&S1⺋I:MV>Z@ދUjN):tUbVjS *k1Sg*=g*;@ØLVȄS̃l ݚ7#9?uM} V2>=Z> )q[CsO5.pYV8q.}`(YtnfNJ=g&v,读 :2Mdzpt*GKjɇ;|d,D*l9~P8 QIvN/.bހVh 9{81<iܵ88yD1AQΊ8˅?;[Ekyp!3ܩV> HicJu_$&{KK@7"ܔzr̞R7)p)<CFL$zňaEeڰojotq4TZ'Q'#LiDLUڨ7Wb[c 4*G~IqxJ~4YT82G.ozߗ^1g@N ſmeDzEo&po6_?x[D}eܫ0p##<͔e2JY-s]:Xݕ U~my}[Km. IqP瞬jxCЯ{hz=cBp+e922AJ7>+WY{H4گE =7ćr_"8N?S^- $nՄ'=;lbVd8Fֶ y{6G&;򡶘MͧDq`;w~㵿8b oO˱7Rs!8/oĔiK~mQ1$zse#֐,_cΎv)gAׁ#oK< :x%#}+4@>C)!<߀(ɉ=3%V: 1b%MsAI~}#/@J5(G(b)iW;Zu]xP 9>}\Plۆ< ѐD9@ysGލBCy"8;)焰 (.¼$83eRQ cNכ3]O İʉyq}E%/ "DXwhҗ-s_|T,C|ŒHֽ<ӋØQ3Tbfĵ8*AUݣ3 ]VBDh"nvS}Q +Sʼn tǔf:[ޅI8SV&>RUSZC o/xɰY8!~߀w6^ѱ_Tܥ `F<弣W$xd*~)'֞ ɱpFvmpD8U`;BČ1BiO [F9J"-Q+F_)3=ubKt2E1=[`TħdczolC0gO?S\$[iX!)T c?^4[hնVaѩ:1JGX$ .2Χ/N@IiP/hwXcvs tt~}7 bJ9-oڑ©WF?ŌҺ靅,A#^)7Zm`R}KJ;E1P[}Ð 1:3 )y޺&K.<ᳵT|+"=~>FbEt{};KÇHfXa12Z︯nN X1ĶheAT0YMC8)d 3e(BVC!GaK; !(x}"m7рGkhT&B].*:r-i-!^CQjE >:󲠱1cjAFp;g,Ak!pB{Gdk^2BZ_Χp׊l]P,mL58žS9zÇDTɘ9?Ciiz)FvRMѵܙ.!Хbh2:Huǿ#ʹY v1YX 擻!B{=K0D0 (~(S-RƨÜvٻo=4^s8ydpJdHDZm!y'ms" C 08?!1$*mZic›FT<ׅ-%1D :p]'L){} xvH8ZSܨ};FX+n&L3rNIa;Of`7];3ݹ,epL3"]$A< :x%켓dbMqX]@~'p{FДBz O#! aDO-8c5R(3,RDx+xy!zv0c/D$]'gBml؀P}#xMS i}0"{3YKN<^VP쿸jt~ql NQCeLg{a (}伣 > ڭx7vf?q<''{|7|rΒ E=)#E 3HjaG#1ç ~S 7o{ YC/c@"92Q9mPZög}pVd,ҾԫbG >0`V*9tƾ <[fF֕M?$V5kzENmLF^7Nl> O|=)F;k'H6i F9[b͝l8'2DZ R3iN/7'&]vi[BtF6VCz}U.k@ov)7 u2[.! FC+9jm':_mtxa{ŭVdjsvr g6BEcjb[uv>ZDs>:8Ӫ;D]H)}[r4Ҋ? !yEq}7,ڴu(q^,-A뼥 {[>P{f zbgmtΒ$sgdF;/o GQ/ ~3]ls$=5 13=H).3?f {9Vun &" : C1u񼥌g\!gBd2]ŀ!K6H>wvm(#i:O7Tk$*YJgT7zq(FeIo!Ghhc;v\ochu`/>:lOϘ申m1zS֘p];dL!. ܊'v9.>/J4ysy+]3{=}y>y ~-wNުxcUj{^췒$*1;jط7p8Dʺbwu{1wja1+W9G qubiOUو ۈ^sqf&+K!,lNEnbH Wlhɢj9_H1Ͼg\wAlgd";FĨ>ʵp#q֐M\$c鱠:3i <13|bJL% w.Fli+R>lwMC} "p9-k ~AS{qz2Hks\3D1~cvxTS6xS3}%;Ko\nyi%*Jh|°}?>3UOUbH2)xRWl9҃EĞ1!Z C~AtXGh[¯p׊"x 9ޡOw̿p>ҨzgmΈQgWV=c3;7|: M_/܆q WEB&2 ar1tںM<&@9 ј12|Vʷ)GZx;:&N&l yR7 7^/L Ze' }.cCeppS5&w~j]lڠ!Z췙+uNq >JM)*Q ^(`vļι6V塘cB\sK׆mKr`&q"^EzC-DcV1;CSEi p@)PwZj:F宂(|c ׎J%1J{ ρ ~FB`8 =T[)>[MyT sB-@UsG,j&Q_G k2؂=DV?i {5"[Ojx1'A:!m~0Z.=Hu.YUi7t}E>F)pd LzF 6R3֔{v!JhfRRxFc!z=JASz!y4(Ģ6JƢ1G !siCN c(ⓤ))OlVd͘ZFD]EŤzj-OLJR؎[\B$ǰ$,Gty UG}]譣 R,]x~J /[Չ10}2CyL܀r^YNҞp/Gfs7aWCgG]X^۱i@h w-bFR*(s9&۶Ếyz.x0CilLcWzhZh@ ̅~`SĹT܁g&t dI :{y 4!GّfQHtt]ؗ'Ûw:dNjg"L+ T[yPqENJ nErvK8r2gBWt>G\WԙgG܅A,kx@yO*Suq_"&m|#Rq G9sl mY!h žw u4l~Ԃ_8}OHޏ/Cl ɁC9#_"Q+ Vfv۞1ĐRo ~7BJF7Iw{Ns8of8V`G"y6-'M"VFt;ۻmcK ZᆈODXKMJ9&pl;΍< =s 3BĄCKckET[?SFX 9QzGh;^_ \T)0P"-@٪aQalN1Ya8P5]kH)!^n:TR̨M]HNqb%xe aq+5{pKʬ6dR %,P@&V{r&P Ɂ hAhI n>x09_ 9%rjÞ pƇ>0>s7`M ix*.C20lg+'/)ge&LcP("%O󏳑ƨ} 0&PJ9eNFz'VC-ZG5 nb4 nN9CgSّQso3T,kq=; 670; gVy.)jŌ9%>pz^A] _>-hJ[Q*]ϗ ܸBV 5Iͯol Aًkydb\Lv4jrfo$"y?`;Sf똦lP>QW~7RH4c;F1aIʟ嘀\`Ukb(PoIShsSw70L=$aq/"Vl-$t\@C]|~%9gBL ue踏(Qi)KF]ؔ7{3.Q^j>x 36p~m4D;k"s>6(qҒ.k4qqo QFH~!by0J99\%iڏ#TCX&^]*)%oV 4(IfGQ2Zg9-_cxF 4l1r[p oJcGyfΎR/PQu$BH \k;&i*`t}q* c),\!X1Ƴ4uХ9 {o/#%8C6#J)IW#'-j.ï孥66"h|D$@|Gr*cXP/b壐㉕(9iŦdw׃y"n~7tL3b}'%6 :!` >g$V,Kw^dCy2lFǃ{Z7͜pAJӡ?n^ "F]b8B11)E^81^@q*tX6(uptdH`4{Vjӽ3_ZC }{xV8LhU! 镆Y@~7(Y X Đp_'|`8^^q1Y_; on|#J..윍r)P%jb %-hC& F!V~saׁ\T-n3뻜z;S$o3ot 0&2pn9Mta70g`*~< C􏇁<+)O~'f 'ewWy/3bgE<Z^C1,V,z}6(x1,*|}]cT O/`-~n{a2ˆVR}; `A9)86`pgR{c6j%ϊxН-Az=QR񞆤=8o%R6TרF7RJDan=[FW]NUxxi1¿t Z4b8 #2>alE 2Xa+go{?|e; 湙>>tLf؄(?"aی'x"eTgA\y_wh@|-v/f)ڢnں+-|jGKgȹg?&;ި+;L=S~=U_欠w'?B8޺2Qa:)c슮׋O}ybk0 ˼]kcRt2.۞qߘ}`^Σ:]FLu9jW; hs7B}c";2pb 0Wܪ i&R \BDREz s+NiR|!4FĘ.jEy`*o9&t!ӳ p̤0p/B@ ;\s R:--KC]\qԊG Nq+Ipݧ 14\U!c9E`AKY]wK۟U=#lX,1jí "^r 2\ r,ȭ *ɰ9;N':Ih ,;b4}`Oʾq1>cQ9,~X*cD l18tt|Jڍ=go\ԉmhc1mst7:^( DB(aHEoȤAwB%7q't8l :|pC"FiPdRh~m(WE :Smswބ?'\|Z ʳI) fËQ{@dg4k8~}aTfȘwMMƿBٝxe&ySG(A- /) 1YMFE-U Vcq^Kk%g/ŋ pLprڐ#_8[v9;;9Is7ȏ~fvfU&"}]!APRQ1yVHNhTS0O~l \`],qB9PKC*)kF]\[c(Óg8q,ReUE9P$CxD*Jbx{ƸIh .'Teٽ8'Bp!Zn/pY/S`J:y~?s Hx N왶jƉwbR[V{1T'tQ=|(S9;o nbU fP#JM3LCAr\[؛e:㓮pc6T-\ rIGm>F4F O^L{ڞN")YH&fC~e5;6mص#wTvPGnT2PGGTZHNPZ|xj3`W8&w<%!r~,)qw}a6n E7{þ$:ڌ`Ή/VXa3yLVH[x[TZxsD bJfV ,RE_60 px}_?xi+"7V4u1y:1>BS0zhb;r=EXMyABgDFضRo0#^N)qm)ho'ƖUT^BÓk%cꘊjH3sGOQ6sDŽ،8v+Ow@4CǪ܀uQy 32  CP|NE9k: q)qI1^Ŗ9bǩӀ|>ɓXOD/V1f3-ap"1ńsB8wd dmV$͎-d^⅚5j3aJcQ[  ,-jHBlNjCipgR c ڳVɇ^/ֹ0Vk?0 hb 1eZ$hoaGY:51,odJM뚶m~[2[kCl`qF>2FWʈA?R]].yq/V+Qk^/K: 64v' ǴI^afP-) OڄxױS:zE)ai}#.DZs.r])xW c6`aߐCB cnM3"ɲZ9*CPIf6*FmP:cHS:EG5qAk᳾c^\%NzҲeaGkRg48RB~툑aU[1&a]? yfnYšߴ|!wEl9#ȼjk] kd*5yk%S t6(G 2.,I5"#3u<68t>Bxۿcr|בgP"0'r~ƜM*&`@9Z0 5R[e^kp|5) GR1 Uqb˴Xcm*|PѴbEҶd.eN'0#s95:qSк+\]&TKG>2]qwiۜʼue̚W3KL+ᖥҨi:p!$~?Z9EPm;Ua 樂 9D wSYJ帾2tr[2E8Uc= j 1J?j$Q'BZuƵA>j\au$dq! "X-u*A:AeNR/ 8PEC|Fo+xpD0?ߢ]r5\r:RYR/rd݅Rr@.x Q[%6x/Tԡ v͡B&" '0"Uln@7:j)X ڻ:h{k;QͲp"e{ d s ceH|Ėo35uRLmOJ2 =: A7>j8,σŁ Zi{tc >F*(T:Sƿ²A],\+O͝g7qu*cŪu4^bFzR#KNjEԺeƒ-1@LGTо9y=9TC=ã^Uˮv4طZ&\vSgtk9ف abܩtL"mQmx/;*׳)ī*r> PѣVN f(®nyȼO12ug -[S3p\oFz)cTZohu)ߘ~h~vgm붱2jb1"*tlv瘔C{CLU";昨"H('Lm)ywcG~I hTɯ/q@++C7L0' 11 [DGx"rT ⱫE__lEtiRV_mURL6Ab-s6%Xfy3Vpx1.gT8ޡ>0Lq qC+^ӝO鴴7@-hGVׁ l
PGްJH|kŲ^C'6˻WdKds!;s1C0lLx1u2ľCo|).c~.L6FϦ׋!ryQy6 *9x<` _#ha/~3֓Q:}HV@kWrch#(,)ef.OB}.-!9*A;n\yj1DzL#`;=e#nBWѐ`xç3cWhyTHYqd`™B |YbuVrPĎUz@IzPV7'ӴP)qoV2T#OgA;\!EGJ}"-E .QHI~f$\ .!{NRʽ ASرZTE/{c?|J }P(Q |dt]:eX;<g38rPu(f1"Og:Dy=Y;["fOIcs# rt7#y昍f Ĝ0b@Ĩ.EJwy/ZDmǺjuO$6Vu6po/09yOe'lh,'2 8f5Dzoiv>| ºՎ ɘ=VV Gbʐ} 1,COf1).~-3'\7aBuLd$za(Iu6:mQs"o MpF*v1›*lЏrx|c>xW3;1̃HpmK$E'jպ'bJ d~ؤgq̈8Mxh# :d#@Q*S׮iŰjHr!Už΋-,bJ=="UX or]Cg2'uv#MLYO]nU _ cyYa<w!hfLXy m Z[QTJ-:[ij"#-d^6ZϿ&|51%7cTY )q$9' { a]ִq jIL]lyl|BY0]N)捑O˺?Ea: BH XGx!:srs]4թ-#IlIJh.p``7ԛiD܎a†hPM9<-H#H!`n^|ܙڑeDǛR{:o$A5ݪt98 #@ }NxP"qdN@'JYmc**h澡}rdHKvp O(XHd-a5bYC);2H K#Ѵ/ЦA\Du >[[jL8U.}B>L2c xz8SYO&X 4ɒ!z- ~?o]8@8ぴ0[<~}äG"v .8J?~lIif&xQP.Lb1Q+sSB׉~⸨[Rbڏ'Y@/loY k: K,ySO\ =sZݣsZgy}혃N>HD\菆mLN\:^(Ib:!>"m2c"H˜NlqS}= 2/(7= γ+C:ƈrƬS'x]y7 n/gwGz?]mxba1e'i YbX.C7jў ub̎x<ڞS$vty^i('Y66R@+kO|RbGM("x|`rD;t4{ *2M%Q9KG<YJgn݅9A\Ouex7M+``]H&{\CZ mZSfPf dT{lDPk'C0ycթ jhc|}PjIvogx_'a0>'DtMl.FyC/㉖7p^}J#@:eꎣ,LLl񐃇S:W.+\hq9*h9`R5ϰr$ߎ/\ܗ:)074%ýnF d>$s%隍jH@4a}1N^a~ǤBLS!^}1nn Vligo# Ld*$&v' ɘE䨪kIۋD놦79p!'3КYQxf $z'^p~lrAnoRQYTx1`x]ZrpVU!xLęf+fm L|<gc|$ێcVa>xC HyCѕ #۞0Ql3b %NM`"P=qO!pA=aau6ܭ@ Z&b̈.Zh)Gܝ'"NbaLѼCfI_wAN ń?$A^*;[5/cy@ua6zuhnps{Ƥ脿 }tBΙ7(vNyt )!]t,Wm۹$(d,h{zO̹񯕑jwh9 .7vGè(r0cvyL}uiJ\^<!mAοocLNs.Siְ5xl[uu2RX )q'! V2|xFܼy"֖*GVr:>Lk@F!z\ggXWLnk ɒP ts#hRB>O!#%9w"jσ3VG(su/]I"~doSj"h,HTc-t|?}ixq?)L傷La'yy1l J]$cbIS'#G@hS)d Хێfy^<ySG5G7׎z7Ęe2Vn}!⏘`S/*Yygv$GGDowΣ}R+yaCfNtG0),'߰ l|FsNzP9lWq|Ղ`9u2,X90NhciI~ft :3թ9OCF.uB9>fXRB &޵`_3qU-};VctBzkქz?oe R]\@0b ڬVM=m*7>X:1>&eiOk5RP˅(WAw %Bwˌ>E4BDzO=c9}»H4dfLJ0mG sRT4"s*>a^xJǰ% NJ%X dSP%hF @1-^CLn?Dciyx= eXX"8xt??f?v~am;q+{2C.RBMlj@O7D>efs~|J`AhFyjM~h)}§Vfc:e@JOz_YlsRDp_o*:lc+ ?vlRc=mFJz} t5nLζ[ԠNN.Fod-Ye* GΘ`dy/$‘/,5!8ְn~J9>Ŕ)TbDiwўC?5fCCfĜ "0'̵ĸ/o6%#@;+[,N<oj1buwLٓ/$>B0-z=`qB$ߣ&RheE}^LP*DOnIqr:طӁ;1nئ9l|T ,0Ls40DŽnSo wO 3!zILdJ9 / ! !PzDp)a6E7yՂc&9+acmϨ:"x9uy G >!D.6s5^/nUqCkO\e͊N'V39g!bsw0s]j Ɣ(ROɀ~*%V[Λy.c8\K4>u(G@lco-+v'>A׿o,~`X$Tv}~6&E.sad,?>?Ӛ~XɏtM}rΣ.d*;z%&^߻;pT~a cxF Wc\fC|ugX,Ie\㋞^*'^. ̱nΜ)oS 'fT>L7=qP2)mL蘣ہƌ$7upTw L7im>D{4FH9@zeC4LBvwpk? C&^ s4!3-8lAO ly' ZcGv?&bL`k2S%nՃW&|)a2)6>BIe,]T`M%?gJh{ACY,U |Ѽ::ShDSR : f^v v>9yT`l'C*6˳0g04  =TC: 8lHs>9X/<#H% L8:p.b3F&Ĵq>'Vv.LGENOmXuGrs_ynˁ;I37c,Pط_x*u˟Jd !e.$:XytYkky?1܊/φ„\X4/ s,* /XUBqDZ„jXr@T1m(խrCU`&9q/ҍ`LN&B&WpwWˍ"Ҷ1c3}PN9А 6f| GP֝UVx԰h| B 'J'g7b^o҂59L/Au3d:J#Rh3QJbȍ9Q lXtb6;BNpC;; # sRzu!zXB̈́< RL#gæ Y 1'\ *wǞwF+ÇTA ؊*_;|C(mo#JzN#ϱY"dF?~:s9_[B4[-D~ Mꢵ5cQ[e;Ti{\{/0NyK$(9R'&Ze#Nԋ8b.M)%׎R+4ƛ*+&إ\2؅ P0)L4O%@2[. Ў^|irQm Xh;sЌ7! w l&k(0DҘC XQA:6wbL1K;HLP4cKInsvw乭"EjtT.Te^gOnu% Tv$ٙh$ !?9x/֞_a ej ^~4D1& bKc9q_b}]2 "`wN$q,/d:umGn@O ϻ-&H."_z3 wbE-+qdtt/ёzWK&pCt<@___)cK~Y>K#02O[R";P#.'A5/y-8G:&di)rY+uww ODCĶH1F TKm+eͿ ~P铣QMy)op7;1 08ׅoL@YZyM'?'ZcjgɲIۆCBnSL&Ƞ1HB*mTv9{q)֢@ql?}W/1[.ZaFeܮV@>UkbIi3RO`wH.!G,Tܐ9;/jS~O :ATwhW;#~:bB0-ܹXǛti)^ԇ"RH!R27 ܍1L*Js1$uBOPuMTl;'/bq*#F}pqV aFj 1$:V+RJc˜11-sbu8-Sϓ: IeYʘb>sv[W|}~]o8O7L ẾĪZ iD8 ma5gG0Wf!v\~(񬚸t|M?$?GukDCȳ /胿O٨$D'c5&ᜍ׋Kfe_!Z z8Ygi{&.eSf1=caa>Jڿ(5\T(V1ʟcTQ:,t)_8"`}S]Q9P:>^S{8kr]̹9OBFLf~;<\r/IPTyvrx0=J7`NBz 2λU6?^ d1LMj5=F%&nE'tYyg[[j 0FCmgG5Զe׉ *\A[{ &ƘLRhL t^>0[u\mDOH:܃(ӥ:rpoTĝYTDP% 1bNuu=}@1-> gK:6{(ɺqmo|?](u CmntY%\AVݏ >\:/cڛ2kQ5{qUxe!ˑPA罉 8V[?C?a:<3 }`XqȤџ?^C*0۫2S3)cA?1_Ƣbx.]S`LQ͕7ʽΜy ~IYm4v)ۤ1Vj9'p]~T~GbtnCYct  S@xB|T̻bPZ_z>W\,e8n_QõG keXT+eiIDATǜ0r4$J'Nc8[H6(3iLzQ;zb;]UE*đBn NZm׍cL%?}?S9GF bp$b\y_ovA%hn"dOq)C\=(/w1\bUQzE UfAg0 J_նR: ︴t1Af *~ |͹Y}DQu9L sT|ġ7#2YAe"щ1؏~Rb5>CFP" B;xGV X*g a<ޞmsEk/ 5xQZw[c>6gUi"[Zp]J U]0}z|0:M.l>9fPԹP5E?t1(6j@Q r,C~ Ӏwt˯Y9"xA_9:e*7k>֋)<&}Q`Vw /!7cd%nԛ`0D~u "r#/8/EHARʐȱh@ i2C<'l)JVP 0d I1Gh<SuDP[Ў8PPeugao;xå87d>}F1sվGCyaƿk%]eWPm'oNA^ wWIq4!ZR_pɴ.Y'&,9&/:3] vÄbqV`zTB(2w {;vôŻ{kc(Ԝ۾>y-mZa8 .LӱorawsYOD-/J>QEaR91H̸ |+94ľmDoLRVG2KFu)gBi 1nj6| ꕨ'4.,5Y`A{ILr;QoV Vfcy0?kYyώsͿ^̥,ZOIX Hh(Oo3;v&a5?+C=p#Fm3// Τ.m"\/*Uy0SEm,EgPK5z횧3 JT/ D/]9"#+t~u\4r H{2d޹R6.%ts$` @.VՔɸl[DD:quU9dU8a6VX K3jB%@ TB i &9&y1>@[TqpGG.%."C1lC( ͌'E"%+aC"@>ZA'tc?1adCqOj=e#B*R,3RZFVSY1d]y>c\OirmXa'jšP;́36h.zLгu0>y:>?saL>wܹ aCw:qbX Np,}ELD(D 1?S$t1,٘:m<Sgv!/\vRن1bsT\v<ׁrlp|@2S 8pM?,1}4PTbg]yE꓌h m$5tpV ׎,&p6G-=>f&QgT4"w+BѾ@Yk_VeEoc fYdIla㚙]yBDdEp4$ /%ykgf\]GƦsgFx,eQKsOCyR<;*V{dDѭ׺墷[Cg5 D$>ݩ\2sN#P 5/7?3eL0 摙*_s ge/8x^Ss ly:qꀻ_8K1iq@}d;0 % @sa^g z}q)wЎc?>mVk|go,. 1A-{ZI>+OQ1i: b{m8ozC>IwHTSRs$Վ{!М;rFk2?7ÉIZ!8o:]cLfl7*Tc}b)ucBډ 8 |q rCවHlߎ߾?}59 ͎eF nbm3qEO ǜ(ax ^r榩Y1%*sZbʂl;G뜝lT trbb*qJ)/ocG [0t'h1vBB9İa28f#&fg3fZ9{do݇}ߑ @u 卮QV}72'e;6#O4k'_wE4EG(BlX$E :"ń>9a;k54čQRCM.ܖǁ+}<6_(u<Vhkt:Wb e+ mGkbGeLp|D/4;.;}3):UdL晑B>؞QLe {Yթ{tqaCЏ^1Uc \t`&OP%Á^Ҏl9E4;AaꃵVkd~'*S<}ڿڃܛp*c\!lNG 9bn2TĀwl uT&5Bp|1>%eI/;:q=8\w8LddU GfU҉=;liGHFV۵(Tttҋ--Ǭ E0"t>oޘ1qR-dbad= &&e(.6K !1mc ;ĉi91fvsSȁU9QFE6laf+lh例]6t  5\uv#|~* {coآ+焘0bUfjCr{tNA|s!'8cHS-9S GF?>YJ9Y1`?xW?i)!"n FO`VIMAp'=Ɩo sޡNKaFV1oncØӂ88rƊc JoQ^,`c`n/!Dg<q js` ƍ6/>+"#n4%D9b !XWەmϘ}>m}1skD6f6Vqv8ip!֙p&_; Uy(֯P/5 «Ql$1RT3[q=cCh:BԦ9Knywm+<?IZfh c7Z W6 S6m7ݿuݶr-%x괩*JhCwu^ U_o}(n2`lm%MiU摘H[:3/lWO X㺩T8'{p+9gh*.8 Mp:ɰS-9G+3ޣt >򣥳 vY ; wL@WW]PƂ!8Xz>J!&v69Q{fZqRE'q?U]9+㷍&cbwoĘmN C-.,o@G,ܩw+O7l!!I:ECgy^4 $ΉwCGe6ɴZ5Rf12q_7 &=dC$>@}Nܴ.Bm !E8_l$Fʸz1̌Z4l+iU"Ǎ2\獴Ew %`#"ƈR hzSq'76f.V7BxZJEUA2E34j}oYLtʏyOJGڴm~~8su.Fi6g!xnX֦b|8?wV}JsbZt uρv0N|1fMEP`V+1[rة_*ׯ}^( RJ/m(Zѻh+Jm던2Jȑ`-g\"/&p^?")tUj[9) PU7 } )H+ԦSci* $ǐ8u b?68WMӶ,UURA@^`Y+6jm;e)yNsGj L1*\'0=U #}8u³fy"m,ř 32S^EڔPG ƴCu 1jc`pWC4!cov|Ǡttm*SsqcZ5,%WB)ׁbMgXUS8ɺYC xoEгcB8esCLzخ ktEO+Zu4l٢B-jT-"f!MOpJJ*o-/#/m%20~,fqڼD՟ύD}+ 5x&\ifR}1&g O&⌈1. :hsoG/fi 6@PB >ĎP01O1jV8eUs" ql;8&dBǾS*xBf{P 8^Z%+S[kp,Rǧʟ=Z)86V4p 9<0'yY{3+BM)~lʰ5}^-Ĕ V<Ĩ@rmS{  >`B_/ƙVȬRs]}nQ_;:$YV8{ycU|&žyDw1A3 b>GC@R?ЌDBlWE81ZAt 9&;5)drDH"S|@8g.ࢇ^ps-qqW~y{eL-BFh/T`^BTx}e>0qš;9QS!A=vxT맓. 7\ws/gG2,;Md^aa߈w!ce,4^/@3 f(l98&~ -̼Q*9sb?/elˤ-8^H! ^hldun;cpnv>"́*>s1"zo'OcHK Áz. vJ >8Haԉ#Bk h/G]Zl牷'LC>݃Ql1S J>yF`E; AdfR}4$X)ֈcK}O}ΰ 0Fjz&”N^ێ)tVѹJ _CL+ DjYEІ!~ O,EAmc\z#BSU]6%Sి~rp!FI40d!p/Ml_;ɘNJ(^H+/H~p]'B 4l󉡈9q:)O\ m19CUǀC+{(`}_jq.bRpn (WG,$o],01dRp~_w *Bʆ1µ3YmDL9G-&8!YR9UAP@AxYdAH*v!l5-᚟ cΉx(l)rF9/"M`h¢ƭ['kNWldžVoqs:ɱOJzlo)a(h齢 <౼׊mp ( t69o0JTD"|c5(Wk1磘 oi<*}0}lN:FEo^/9XD6њ,X&tW9}mfPv?2^q9{JfC<, `Bo ZăX{CY-S<!&h>+'IZ*K^ALabsǧ#3eJBSJH>{6 H1=CχoimJ$ =2oRunAm +EQ(cW=Y[3hyhHZ #o9|xϡlыj2љO>|bkpAEU`1-Sy 1nM7?'يd$ǹdU<Iȱ9lI9oJ3Uӡmv"bhCd(LG.!̢SX{tUȸnւ ',x\f g.pؿ^H[Vjl,(3ltLf!9]riCn]Ma"pl_}1E0rahtRJsuV9 ]yXje[ ȕQBcΎ~"$w0-ӣYM%,liSDo<~NT";z־V1b 8ϋ ) H N!CR`N/w=jmW؃ lF=deE KI,:', ŮڐCJE n>) Dzd).Wy{<5Ե6^2cŮ"G~q:O49RU[mm {Q2F/1Z>'7%Ɓ ؏<b. 1-cKWUk3eF]i6%BF4ZfNlyR\*6F7=EW%x7Vx# M9?ZLӠ$ W#2ĨN~?Mz'oLC ۬ \:~r%xW)<χ u1/{p :}.ȯ8-l g %V9+jHqrN9:^} Op`~%R$-\${odVS@qC=f34 %NL;Q@z^'r~hiLͳ"[5` NZ.k tx0fGOuL ڴvgkISbHH_mvVq 7YTE) C錉v!l%?vL7}b@N jh#Mtv 3*NЕѼs.)ةz);bȉ`(јYPuRfƾӣrZ"z3K ѱ+ٝ}#-aR[f=O\bۙ)Tms%V^64; _,?;c0קv97u4=͝ I䄔'vPA|]ޟ3(uuf癴Tyq1x y= cےq*JSЫhdׂmGEeCUЎm?x,Ήn_,<7zpvI[7Q]!O76O6r)Ro/¡WTw]xNZG Cs- Qje<*#x. 7b¿nV{S#.Mpgqרrl,0@,##~Wnr'|ݜ0bvM0MDdJ~-ّF~Rm6ᱨ]l++dϏ0vۤlx&텺y!ęTtaE=B} %-\yp}&dF jxR/R>LReH}Xi0*v.\!} "6)٩# l=m͌KlV1TGà2oۡh:] ?gΖ i;JAGQQI5Qfk׉m ļ'<)XY~<$Fwi'JRLL_ W[Q+$xkҏ2@܀7B?"V+QxXACO?1jCʉ} j 6^/A8b}B亦j}ĘT9 mu`Aw9<SEEK*\B $-]ٵ>#rĬ C8oޭȓBJ =/Pad^cOCDԛs>BY;zx~ors%Wl{Hj8n b% ~+2ډ@0~wl %b7O\(`(cK;m!@pY'EO 1Z/E:av?̥7M-:Q 3k)b"^D- b?Xbwj-=%#B D FtPZPC5ˍm3W<O9N)blg#a] ebk28d)EoF, k9@1DbL<඀~U3c<<ڂM]O#0ž*S!RA՜T2٬\lfa<<%u$!RxܷʑX!XG/~d#G(x\}|:nJq:l㳅4rx*8` pb錌[{ĝRRum٘2>*CEq'%)CBrNh'qU y>O: E>PQǗX8j=n`]C|IZ/ɈJeJ5Vkh΁~Sxx WLst¨B-1dv]9"qv &Ikr}`)@lY >pФ[?#BC;W; st$K1 Ô\\!eM4!1?*fwIAoÈ=&kc)d2?*jF}jglS>A(^6$.l!TcT EЮt5 hr$a: 6qPEֳdw>#ssςxQ*D*Pw0PKñpCDvva@): B0mM(~sSM޿s#dțh[ankjEZx;d0Wsx=r^i7"XjO+?J[gFpN s_iWѺ߅=ޭہz߬BC;,kXдZL(M!a6ad+ H!vVGQ1>i|)g*Z5"˭_Jhv8Im9nhЩm#ѱHIo&Rfbcvc&eyzޞ0?~-J=*he kML64L bW5 Uo`U +VZVcՄF,di|p쨊r+쪬uMDb-=t bx'rouQ; ][h 'fNUɮڻElysnR0@ )w5(čO/6ܽĸ1xWL@O5{"G/Uac @Pu Zy#627GZ3B=~7\S',a<M@~X^?r:W@-ϨB`{턿*/!G@B~߿Ck>&Pc* eK4lF}T#7yO(S<9Cm4mzU9Nb czPMe/׉o` yTۢ^DZ^4EP}@ C K" SP,!JNS8P r$o ]ZyŀESXYxA/Ċw>N98s:oxj̋Zct La$}Ji # odVZwL; "홃RU`psu9|!(5o6@0DᎩ)}~:0Dq ]*gD 8q)$z8Ra 9XaY0ڴTT[J:+ȓhR-m|hmØ,!= ! C!쫵M#TX]V&E7&Qm.)JS h3%bhޮw/PePFY]>aعyN->w$mEe0lRF0?˿M*$AVPB|t)0-8^j1"ƀg M8mPxlׁ|Yv־2N8lx:C4cö8ߌGP0j*^ !&b| n;+A17p> MM֛m,ip&gFe̵/.dT̕6 y\Rl҆29L.;(\=Dɧ!+6dw&A(!+u1$ldž:fqYd^Lxiဗ~B9}a`L3y U2-biuDDۋITL7Ղ2ۅ<e=k՛siQm4Q ̊IQ97=6IyU[a 9B|(B$^5YmSNlWALٚsWRqg짙8A47{'[z%׊>*QJ7SBHݙ L/K|v]z+؎/bB2n !7ް:>'Zx;Vsx{>G5U &f;s#Ǥn$ j"8eWxTPvǪk%~0TKdJ6@)nvIGӚF꩓ي>RջӥdKdtbC9Ckr8Acݶc@J|,[>~=#[C7y0cNEkVM^81 '- Ψ[eP[GHUjsLVy]I@@*ds)F7l81lc/7Q!6:iDWg~-(C;m;h3O t73::fWQšƄbb'ͬ{t NZL`0].R,EńV6:j}DOXB 9zgsvt*OxPeufu6^zhfV(fQi-T9q&԰@6Q5 N*gQDcr>U (Sd&Sbs֎ݢlfn\Bo2bg-djLx{ܶ-׊;uUƐ!t-W>ubE>S*BDp[ϼ2kYrN֣be0E]d_WeV1o* "Spy6(fժYX]q_oX/SɋyclS&r 5gT[~|Lcv\2 u\|`މ9QPZeOJT).,_, ]on2]S8L(ܠJ'CœgjR b}0C$Z@bAk{;/H13u3#Y<:Ol u&#- ^6 rT?_?;?NZ}Ɛ{/0`?v\Ė^gGP_-y <(-}7Jf_RnFGL Vn /u0R@#-v[D~5RhiC8΋̎=+ps3նg5rgc@7jeH\$f;~iUUkP8BnY}e-Vw!TM(@#$9WSOsbR;U`oiȓg@lK_/]`Pq̭ߏԲFCuT>~7LfIpk͂z;} w97Zoh[?nr[蕹""T0SU:u;+mXj{>]zTQ+O$a4&R+[E;NH3џx΁9f2{׮BOFHBɖ]2BLE@L<8]#R`"L>CtQ4U^xm7rH(r!H9bL=mX|?&;R?y=XHUW fbO2q{uJ867EC*K{,I&ڪʁC0 }M)$* )G bXQ}#TCڌ7Yae9.N3葼m}>G&zu0 (G}es͖.Do\%7;YB P jٝfIo3G1Q[><v//ٙg7:9cm&ӑcL,Bǽ_y3hFmP?CIA0.+Iq~'Mlg<⓲7I(nUB#hZE8x3&mX#H{Z3ypNv`Nȅyxu/Pq"}ѳ2 O][Bnc' iV*ԽZqa!|K%DBj#zQajd 0_״u0h 1p ʡo9z(FΣ!&@*G.l__]Ήv_7$xt\wyk.́)6ʜkk#yJ,7fπ%۞ H @"h>b "Oi}+6'_o'zx>y[}lwP@w:Lդ ^,DLq! 3Pm ƾoow}ob2)0=i9m\DM..xFECN6D=C^ B@tGgnȑ1أN`hWWGVmB徑U]nJq04jX`X=Fx*\k ij?*Of ˆv\s'&4e3\. U2k*Wߞ*XIk?s ?@jkgZ`C[=2їùl=kP:>?tUEĄ)Ô;>@>ߟx ud-(<*9CmV)픵&1D"Fk?[vBl7*P^ɍ}g.@-7Ҷ*aQiDHbԉ! WB8P ٴE :4ЭijeJ.vָe?^ێRZzHBveb+\kal/ivӏF H fg>vYuؠߛI,V:%2P);b]Yxk.m0?%OQۆF ~CQictI@F+g|$'#S)yA&NB+٦ odI^oU&@bH`[RcG[mez4Co%tx88p҆RN8 T9TÓWr^h }b=fiF)sj=@Q3/}T`gƇoʜhLjtڬ%cGnkeaAL4+)ƿ*wެ9gR@0y[5aJT bg4~홦7s.b`XjRUS-B \xJW>bgEGch 1LƂan>*,|نFk℧X3,Sƻ _NLt);^:DyL0$@1 $ m;q^fhAHDѧKAװgQ#Fh9:N__Y( VFRͰ Yt-Z۶zpN0-/ G{iXJiNnm=##8\Q,Q[f4u,D AԿ`Cv[=x2F >0f"}6lkV.pUyPn 8}~r7> <9w] Yb9&I}R{Ł`1],xA+XzYswC_ 0lND_|tK+q\Z˘ 9818#iyVYr֩ G\l ɥ=59 ooH2%v\͕X뾹ћ ".;VkBU.y`e 4AMP lHbtJ9rq#)NSJ&*H>(DDPuF(B" =9_cNSxg ݐcv#ؑl!c f:D컄gq9A-՝bC\-Nw RJ(w3R C٩`hq1ΧkZilaA=(mOWQJW4X:IiPOraj+4 ʌy#m]di1 {Z"VA|t"W 0ywO{\Lt9xc2GZjb/ F+n93y)8xd7rvI=}39Ёi*6NK d Uz:fgr-ct`;?0>%>LgqxX S)+QBvz/pѡ Du"7'|v*=$rQp VDGQ&@ wg}yH[DE-6y O`O* [dq;N5Q/`>e-q g*ml^7UB@ƪ;oӐ+pL^ePT؈a*9:5y@\Lf;HǤh[O\<҃Y/ql>I!>p~2ĉ%xؐoB y#m|SҶ 4XUt1u $R*\F㾱/~@yn@o~YJ(oCi}j`H800iD0t `ژ8Pc<'U[/^*d*[tqV܏I1#F[CTf?;/zTi_&7a䙡Ζ -A]T<9R>h|9dv" gp;WEVmmbj5JO^1c-0ڄt+Xt"3SN+۝3Ӻϛq's>}\Aš7#@JZdO)$xo~2/EU8h/79\H>1kE =,?SEkìWF<]t%zÁ.R|6#N>PΛskF@ uSyMP5bThUQ#`;o6;/FsHf%L벖NE 8`I]kEPؗsQrOs\} Yja}z[GDDG^8tXa~~I 9mCq:u҆rmcf Z=F">D+$h$m F}x^xu=ô|enzSR1;_/׽%n%qj݇XUMejM8=mN hE8ig.#\:Gs}8$4S 3r/$9&hDo;[`ҘArG""0$2ǁ%J_ d(^ g9D+ܡd9Sbt(t%; Gx˂mޱDŽ2Z)IcN:Hd]wI`9x?/FH)ogvް,d a .`== gՌ :&S :r=eg w9r'鳁:jOK>? ӆw]g9M~ ]gcmǘ'|.?8Et%P=7r)%>sYGH7.@f{k/6(|z)謯 ¯,F^cv"V`酳)a*:&RGđ*׎OTz>ӪlM1 ux!'̨ Q ^϶r9o8J{x(#FDΓ`:09)o[u]h"m;zkLuA͘nтBpOx_lu`7B؞p%kimY;EIQI.+?xo>xĸ,3'tZUb|FlmN"h"DOa3HאRW8NF `zX h)~(~# ]4ᆽR/$1xZpl/YHfj P%CF Qys^9$ZY>ղ6蟉jA'u=#8.pQVB_QS1`8sΟD:mvؿJɬn$?Uv>]:V!.%SxJ`}\a N/7:"#?`4AN 7SСa<[8-z"2a R׭ "r;J%*9CHN1Ryնaմe~a:UuWrG!9:Iqr@U3 >I51FF &1D ZeV]M1e4jQy rj0] AC`WKm L݆ѽwx/s:l[f툴iCpcތt@5T֑6},y9DvwXw;}cEWIʑrQ\ ] \NђGgi)%k"g]%M`@VQz{k)lDf\Q"Bm7D(Iv?{x=> ڞJQ!'lC^ְ"dayvUbJu dfs?6Onmwwo*FAe1&LzտФ o_x 61EFю)oF]T)x\1#_xOa7`tNsAcZ֠ \OvZp.TM QrAEp/Z KĞx orj3Ϧ~춱e0 f 93) `Ḅ1e9@c09>:vgڹQY` ˙c@瀟_,#u5ʼojy'1⾰ r2 R &R:s9~|4K"t!vRKAۯ_ߨFS۳h2"(1Sz(I(zU@hodA&2GQ}ذ\.z}Ykǘ|{θ-'dm+>B2^Z-|L'Ap_7}^!Q2\:&TSzZڡ+rHp`c(IH +MOD|(d[Z& DD&ꘈ^Ю̋*[wphl;C䬆BR'׎;r \TDRSS: O}Kt.z!-g6nR@C*2+:t>"Y (H+R9~Fis3׋_0qTf _'k8*}ǟkq ?qU0_H]r`q}vDa! :֬ElP(>1:z}AU] Fm̥։e 0|U;3G@T@ZR[׎ &:k!d(#Ne+P{A9ovsF0uBTfRRyR$ʼ788n֛,e!b 6 lf^[(HFr9o>8;IΪ}Hycu(^/@#BV.%*;嶌w`YV\j]vHvJ<ڎݲtm ,}̮0Fsb|}ǔGUq%2s0ytasjekq^Ȗ201vc}`;Th\_$Ɋ:A籓3_pC }Z0YڣC:GT[L6kVо(v|ZoH)p 9Q%{@ѝ& }VVVcw:&w1~Q%e8L1AqpTϐOЁ6U)ׅ^8}24̓B"_ 9oHy].TsL .`bbsG zhOɠQbKreGJlK8Ϝp-GN!OĄsvX`SNOR:`1Z[m-xNγf`" ?XAbx/*S[ x%:p.3j!Eޠ!F#(^$@0~QhgTUjv^Co8f? fp\/bqm'rS8 ( )rL$6 |Dr{8SXOEqN:aD5/MOƌx)fDJ>!1y2,"JiwӾFŞS~Z9e̝f++xriRpƝĭD)mVNJxfk&r6Gid1X@C9'3msxi'IRfZc*'@sfѫmvWFӘ>"fDC[x4V茙-sx @ׁUĘ 'U0Dwe9S~uҬ6 oG,HQ9'ecA+ma?Jy84ϊZ: cW&81Z3= Ƙ}tQ Q߽oۏ tUs&5q?jo^.ra{l?ANV& ]uq손Gar[L{oz;@ܢy Ԣhko=G=mb'bh-3|~OXON`nƜ(K־t:o/ 9^l0#CE`jb[ >)9NV+n>!o,j^Z+2Db&m*nU>YlNocaR9GɈk`*IbyV&qbƌ41X<G&>8 (IwxA4Xuodp^936R!F*s0 &ڜY;L0z(R蝙5&N}ZEΔ^hs"ZX[ Rs|rZjYq!,o T(BOL-WKv}m'ZTYkOO?cĘؠ9 ąc{؎ hs GrSF[ )xk]?[R'ؑ\ liGN3hsuTP q)"s4D-AS!o1Btc*hJH9a7Dg~LuGҼLOƶ ߾xruEr1Z}r$f,H9瘸mz|n֝'<]m9sau_ ULa:^!L>R9 )5Eadi١aqۮ4jf=8NqCLIz7b+P[ضr71cc\BLUbmk-VLj{/2>|㰡@=8*vT*+[N(W C{y^8^;J@u)E0Ao)xM90v]Hrb+=4O^苰3ԶDNi; Msݙ8a{N m3(-o UPᡬ5@ e tN[<R 5VW u z?WZՒlyLP0Ep)V+;ǰ8}9{Nb2 (ab zi=*#sllË]g̣6T N@B<P~fxBi)Zl_;ɱ`)]b3u>}@LmeiGmH\}Ge6 [ײ H@SbZo m4a^7&dа,0.2)(uXz1$>* JT#ox_oC yYÎ<y`N}z}$4?N(l`,L^д\%SGO#">6=S0༵<_(|p!FJ-%EITV#N)[8KsZ`}a5KJ)C۬}ghpwPˍnB=h U1#| `s 83+!n@֮2/%Xm@p߱'I[4uRU;sP&͒ R-p]甮 Vӝ(1Vn4C j9K:spxR%cͿ|v5>SŒ@C!n]" ' 5}(8;+Qp_'!Ly瘘G_` 16/w&lW)c"N~VC)a +^c΁B LD#;Em >'n뀷c{Rۜ9fؼ r !\u@8ze xTDyz~ 1;u۱b~bXj`2q[xľ ?*&.<e0FR^5s;Nɐ3ޫX@qb )5I@';G~-qn~j9g\ejLN`9HCǜxm f^4gCmG]1@p/G㝓R9'Rd-Vڬʿα0 y_RHls64hcy{Z*}/mCL A>hmL7B_;7KaCyڲX%0P9T<Qү؎6Tu!|\BA~EƼe ,1&:Om2j\\Bʤjθ%V/."aˉ*U.yу!%PkG^dUjH19e 9P@4x~=%S&=x2Кm>wz=BHg>fwAtF;)ׁmxA{6]B:Ş'TuoW(Z` Jz-츨^gl˽#xdÅ ֶ"/|];U8'X:t2oV}!gaNDr_ac#o")16}^,)q$1/ -9fH ^7Iwz7npliV$yOu`67Bڰ%J[yU}i5'nb 6n"hO~hׯ/1'UOl3/Գ4uJL䶸B8Ԣ5dĨCdq{θkM}+ouVj ȣ[-bFȅ:{Le-1ޕZ{<z*[P&/Gv;j(U ׄH\IwOQF%~& Xslپ7(鉀yPE-1!l9Clf: rJ8 Mߘ_S"kVĪ]Fzd@ l!mt;+neUrfbLDb˴V rB,*{yBi'}>WG.8&Whk9?pRѴzf&_-֩Vk6oN?J\ [c$n5s t ͢0`2uLpjaF#̅!pce08gLm QTu 6^T >L:F[~gͽ ?̅,9i tN` /KkŞ_z|ѱ!zOkm^9)]r4x۾Z Q) Cٴ:ۈ<LQ2x.6Drm6k3?ݘ (0=R1 V<JX+Nh11Բ[P(6h) `)Fĥ+6f+ 6b\@GC 7#8y]0@q㾙cUz|)x%jɆ|ζQGx'@( ju'ՏĪnZ?$`R5͹vzWΧBB\NAi'r&}@f! &N}93zG7r&Zz-u{8:c$J7xP4"0xƸ*czT hN˼|]p>B4%Xe ĕX-!/oV!F̒xp}?v.Ɯ¨`P:q `Y')8!,B?tcqe)XB XTB'3 ,Ր߮`y}>#gU1hWB8e5 P ?jz`:'"nkB&qf2QS mbc}]ܢ!-;qk*r":IDATuUPK[$(7[jKI1I6ݰcJjn(~)mX1%Pix,9ӭݾ\c\ͨ<'񑉟1~8^jzzݷ8 -].l1)ȫ#I_[Q ֢֢r_vJ"5 @:'h'aɁZ;r"W$?2 |Opr5M=oΛF١ u}?g R)lHuZ$*m/*[Nw1"x|l8'BbDׁ: M*!qZj!GJrc7[>GX0QaLeJB}HwifDHD'M-oBLv"[u~ੈʨr])@| Vm&sA*>H:K11GrÃױ}Hй}89ǾAacϜ"Z\'udS-DraqO9@42$?stD'ˇS\Ҝ/ ۤ/Z{e cT(v tA9jp[j! ڧ%y=M&z]mFœkʣ`*E~c(kIu3YA&q0s0kFD}_ubmwf=z98[WF ]MCZ ϟo3Oq"=z< 33UZL-}L҈N! ߾vb >{:0z1(&s'0p<䇀i> O)l^J]|+xuN|" 6u1\盧Wchw)3~UI<{b7-8M&p>!Tk=_CUn*D0Fq\ ȃQ&`gmOq6ύsBp~lo`7El[슻ܬ[DZhZGh}2]OՓYx^8s"|:~Ta iq_o3N=+׎.H{b8 oӎL^cWP30`$]YilS*FSv9`  Hc}cC0Y#8o\>syxb\SsPmLnxnm6 6ƺ>B4"8om}GGvmβ<&7N s-3cj况+Tj_'7t׆1f#F:던2FGX#G{ñ8 ǶfH)l,jWi$AupVrvDhc:uj-gy]>='|xmǘ Ow,n}%&{K ©Y/P4)>_nzAT朇%ܷzb$AfL#$7΂M'SP1c4[7 Mӵ/>P1cjn|N ~,p[^x^? vF1|#GzTv}{wfr];OlvjUUe2W"oFH/Gjiۇz cկ:8 Tv2yNM#̴WΆRF$t"r!D$p}=!C:*oP)$1(ͪ NXSHߵ$շ d>P Ki \9ā{GĿO}`V:caQelyq'u#<8xfömu2svLޅ!h|b~{A =icf( ΂YlLQ_Cg=B$ez?ux:݅nWO(F3㙚n;l ߿ F)Z0G%YY`0j1,eK[m&=%.%E|z6x 8`Ex2&9(j4S6碅LR>^ !>[@Qo&@ F⑶Ri:yH†Rl88o{lٲ&L{cG3hk9ןi?('BT,RCR898N3R"J9ts[c(}J7hZGR"sAe>{̰wJ`/NMcSI -J#Ç vE 1 8؞G_]Z(pV\M3Y(zpuXA`3UH`փOUFU3\^Z.#J=1^ -`xVFe]%]JxWaJzBZujjҰ!wg}D:#KM^&b{QDKq~>p)" 9T l E"09^\gqoBn1Z0]d*/ ٮ%5vb5}0 USq!jRTSuJ4%:\_#=?9A\D-'+4kwh 3q^7'Z^hNr{cnJS͊>ɼ$ /FgP/i}$ayHw3c8S< ؅*0qafsy>"DYx!Yw_ 11.)`;U0kF}NcmY+Qsrtu{>p~t!J>ZgU1y62^ TPs`͂?RŻcAx2ur$p>J</cVESk܀Lo7\zk4hGyp\"xܟ/,|N{YE#w`E() U-ib1f&f >J^ L8:bVvLdj]i˄ݷO'8m@Sl)eJa+B3™B]񝣾9tkE"꣛q=@`tĴsԪTQ,nRҞ4K޹,Q co87F&LxŘ2ZewC`k Z9է#-Mӕ̹17C2g‹xF5?eFG62\ P>;fO8pnRcrd<@Y{3Dz6gq~ "7}6n|Ȩgd6ڐΥ LZ`UԠwfk ex1|?_{GMSqWKx>ɧzr4݈N@:Pe> {g@o^83֥;*wd&o{IgӢ=0S0&]}t^&7 .#Go,=ep(zGMJmLajU\&U3CrbK:E ~L!=}  ߻}a))F@cڞ3Z= "~! ̦( A]˷7DzKm#*};v8q8?_ZF!,v8'!XkĔrA `K*=1>_t0R'Ǿ㺬nlPCD(ptekBƒԎ>ѧڈmƬpA.0~cŇo.KyIƸ⨥F >H> 47|(=CD.ƺyŘ:OcW EIpF% oL1t4rQ56­4p/GgѿC\UvV66rS$>%N~g٣3S!}pVzÜHCr)>`Պ@0>`{!0ZAPcp<"vW奘^+CEUYLu1!mZyq+rJ;G[@σpSQ{ŶeT~) Y& LXW8hJ]]rL*Ai7G:* z_"o h5! }͸^ &W+оmpj2ɯHT7 ɁUxՂm`b';QNhs A LĴY `r`dt1}y!)`*LbHۆ"JDՖlQ Q͟h3U)Дd>&7_??s%x/7`[D9Ys%#)!}#ޝG y"6Jp(B ctz#=<vh&  NGq2@*xZ`z S0ݨc"J?Ag&M yO('q:js8Cb|mV5<ѩ\OLt+^"u#mL圽Q9qdit}y IOQp;ӎZo6>T"M& >D'O@b'Պa 5[Kcwӣ ^kdLHC7OhcXy9!8futS,0ăpk~oH{|ة@$-,dBjʶe,w!9*quϞtSPuǑ«_&Z+IAR3`4+ͯ9uAx;`NB+:s( x۝Rx59ʾ*ccm7'fJ3ChI~^2vV 2lbn368s1BĶg!Әpmc80WR0*ܧtSi-SI̘E9[: E00Mۆq5wЗ,)`^DCifNF2D씿(`Fd3$#!S;aRw~< :?"s.\:"]ޘض 1@ީ\ڷ<wy#(hyK~PV 1 }DkS y2_.3 fSr!4]s0a#m?(:/te},'+-D<p᧏d61-͎*& }b8z-Hy±xphf1oti_E+XB3Īffaq:Ѫ]m/b ʛ}g״vO|N p1aJLZ =jm&f>";r^7%/ i1,0] :L۰EI@0 B2pcFm%M1=# mp1M]fNF.Fx˃R~"hH -:PTvWWXJW5zc=V\1K3쥾?JVee"UjKV藨|4WxJgFrэΜOQ̊Oq i~gy tx3<,SIr_AU}X j~HFĠ\ӫ#Eum!ZHkEJbVJsvZ6͑3g7 n`vPKŶGWEZefo1C*B,P-7vPȠVu9HHJ-S*SP>p޾ @ͩ=[`8^3kC׻4L03Z>ɷbY=(HqGv Yx^{߭` iX^L$nM}a])=TH`7>X9Vԋqp8+ Gjo0Oc EԘpWPkX^+DQ;fȚ+(|TbJ$krrSf<h"!0i*0I0%bP/"E-q0!ͤuэ^s~v|F:F}|6srlTV́)]B46Bu_JϬ׊ _rm2ުuupxC;00%*T2xL^A믫0Vh/u3I0S ¤"o>q:sh1X|\bBv<,xjX}4q?q3eUHk:q-Jg!›G,?F1 >D Isj %pfŮ?=_WXBÜ@6Rem ]ͪ4nynziBʘ8ҁfX _@J?O DT".o]@ cN9g&–9b8Z{EWS"F4(; 2J :aqsarQd|@@Ec70y&M ێѫpqb= ,t_ow{o_N CʬIĺFk8̉S4OWdCee\(j>-zh/VcsS5aJ&GTR9db̎bZ!;EDgmn7RQ[At# >P)hw&&B9&Ią\ۋm&Q$3GxFE9`|K̢G)QZ3@!F򒘳Cj:o[d:^$>x8reu,a< NW[AtdV9Rudt!f1H)7&R&;oil1E|eHFNi6IV $8]"WHS-OV۱ wq bHav?:`N2$xP@3GBL)$CLB$q,2ar"Z+1/Ƕe&-="8&qm<ő#Dμޛ$P /nɱc(^s2|-Y!<&9x13 ^Q:F)ד`:Uz\ƔP+ .xxri Z7O"!$e} HXtf}p$">!x8IHJș`sPqTҋ#or~^^$>ӌñضEibT/  !5:WUNW8 >v[fF'=i'ω.rt[&NS(c 1[p5|.9*QK5'7;Jul5U?4SzixedK*0x f^VILz|:  sQ ϼQ@Kee\_ṥ WϮHlҗ|$}x{M g,}1"bk٦)qƚ*j(Mئ7h#auaaDY>$p~.Vf:=cs̤'OI;T}ˇbR^h`<g,yit2ƴL t'bb4Q JՂy" tKV7zZ#\v!:qĕynU-rV Qw8\@-˽!G CevUY߉Cv[ih`DوspNi#JsVåEqH2I$@ B  QΆyoR&|*>նxcHmdͪG7̗(Yr#Bj42DjS}pYLl_]F5ݵr9c$1ֲ\\>26;lCD7 9U11&<[+BYvtA>6_@ c:(]9n("M9 !3fW1qIu~X8ZqO8'z^"s8;O}7l{64ͬS4 5ۆA64ǜ'뼷~x& C4^beR Ѭx,qcKMsDޢw|E]W>x0;M8OK.6τAoFA0u yd 8_SlY98)Psm&uLc:/H)!tج"*T]9JԜOfUq\sPQ)ScZHXJd2M×Ĝ8 }6NNz)xB-t>Ud~1 ڶ8Fԧ*4^: $҃7rʸ҃NRقF{8gqvh fX>w4U1 =9GN SP w|> *9A.:[/\27Ű;Avt39?0IvjhUIGEʽh`Xiu]&<}q- 1@(#=FT X`r.p.tBYwD=+r9+ШERju"$0I?(]N! *ʅh ս4@jAdܬb4ML`OjUZ"P傪_1J{F J)2~܉B f01π(dBrYs2.xOzQIur21 /x&6IK\C`v|8#ûĊPaļKlZGB h7gTf6r rg;'"Y FFrR^9&2֞!E)m]#r3$K Z)6Oo;DSENJҙ:\i0f̈́ t*đjÖ2Vיʝs<9 އEպ~}"6*Ɉݥa1pc.%eFJ$O5u_2wC[":*VLt4ʉ9hAPsЏ6+és덩$ >p}x272ʍm(pw5"*BDϩd 35idM1?X8I]| GV.?<SOE:f0D+"6#8J44 rYzl NA2R ¤x0k˜x(Fv*ݓ`s`uɖ+;5\|Sd҇Q3ؒ2e/kCJh2Vf>ˁUJq uK&TYNBpD#mCcrI!$^L, J]w !0j炩eyʲ -/1y)BUQMŸZŐzGV|.-ݎ=]1\~ozZ:V+P ::T "徰޶ϸyu->1yh43:xnhQڻƯ"fP[i08 ܟ#DVhձž 8M6_ ~T`@:ŘgwL4\ù- S.hwpC!љj24"=C-YuIT,覭7=! <mp_!S.lܑrUlZӰP}g!qcfԆ-mܳЎ-g8ꊷK'ǖ#,+}>{\#o(W2Q11śѿud/> & S_7ҶMrT QV )~}ߜl㚆oB\)m BӎROqVnʃh#$jrT Cpk DS@i: mFߞ1_)$ZOKhYN!i1E B 8>8^oz$iOς-Z|1 (&6k/z 8ڷp`lkmOٿ1Zn.r!:M()؛-: w`ŮRzm+4Vp=UNΌU(l=t"3%.ލ9P`7v!D _)[!:!ќR"[F Z m9g|tj/} A56[|kZ|ߪ!>``@=0d8HhcvsªӵK& Y|)|r9F3)Sz)n8?_:,3)c`iD0Ǜ[N&׋*}cGBl£ hΓYB rC#oP9ĤCL>Cx9y ]SX _w:8jD-00\A<[8P)EAC!n 3hRXpy49sy8oh(58b(.ʮ3:=gKr4 ?;=&c,d8P/xhғ:H}FF1ղ۝8vgrPۇ}R  ћɚ y~!jY.bX3(:8> Kѳ%@H!SMdJ3/fUc_w$37!g\y~XC1~?8Eᦇ]"Ɍ!Bu=}?&'͞C6 ^%Gnq8?_  >.gk[Ux9/*ɺBJzZnQ L&!A :=v@iW^! cWk:wj>3ǺM/(ƌsmEJ;U)>>I`wO+Swm[H͌{m2'7$V].`@j5^=S Wώ(\LZ6tf2'4PƷߘn~Z[:1؍GN y36&VցyѴe|? C[z@F(羉Jw"Q&.ȯoy=cDg#@)9P={HB7V8>kzo?s~];y۸p7< .27T}Mb*EUx;T BHs<7|(4s1߿w'F̰A<,!]1%!Gb齷nmg77_aWF:)Nx/sX*#~K;8#8 (;ĜxxYF [dNC;;\r,"b- Nn5ttJ 9: R 9v>XӤѴe" LPn ƇANphF݅evDfPcvOl[]8n V .̷ n j]Y_mqosAt1(!kA}|'@1Cs>rpp.`$`˟#jdZ{GY48:z5;~rnL# s2{¯L1UΙT,!n򊉆=f0 䩃_\"OMĪ3#,v c,ʈ0k|5R*ґ!hPCSr=cs,'ȻY`n+7GE0A]k߶u""mms/!F8{ŖՌ|WŪRBǝfI#fs&.}O3@JT#%ZgS{y04r~L".|uv܃mJw)LG0}f*_K svY}`})c^ /Ʊm7DeI=@f nsby[XG@#?US8bLR/1 Gm̉^XI<Y j\Z+$弐WЎc{|:8y̟#,um yu.k !1Ա1嶦N[ Ps˷/x4L )H̠ll?7HlˠB @94ah˃j>w#ui~o5Vƈsb?i}HlZ:8硎9N]cő0\4 }<5hT7VX aP-?OiK˳q;>tCT/v&ƿo~>U:8.N%XHesG"NAE)7eq./??tihIRI0mfC/G:x 0IX#:8?z3ys .>_^ov]twٻ)U,Vx>?8:q木kq|B}]Q {p1/$]Mn@1P]nUS)1&ʉ#|ЃUe([Ն\Ơ2-lIOCVj1t4EAv9*]t Ux< ?f(#'^ y"/t ^M*?><8U`@9ud]`+!ϯWy a׮y[YP Qm@i].MAu5Ldt΃bLڻY]>qݕp<shWu]||TӅ9ƟR{@=1&Q腁PsC/Fj=<}O_}^pYغ@< l/$[m iWCzmXFu E?Mp%Ue8zTmGI-'c|Ӂ-qEpppU%.)D^νb }uWVHyC#@ 1:x0/J 3uSˀc\2*#dQf8kfI?*-ƜطwqlL[jmP|}#28ls 0fbBsbr3L6Fylޭzz3eO<8*HrL]@9R68=:ebL%n{kcӭ"9VPE-Fi>1&œ%&:}hn%d\ !?/F]KJ[za}e^ϿR<E植̋3 dV,9w1CtI#UdFv{KSygJ`WL]u>9p4IE{ϿNlw@h9XL;19kCRIi+WT*sĢU.=rp01q#68c"L'=&9 gb[@-7meI>mҞClGĸǖ_Drj!zDp}n}GF+ {>i1\mƜaQJMbЮsE M褺J8vZѩ10PJk|3_yV$A;.kU(s,\":jg<HB%Sl3;Վv7sxv?7v3jz(ϨHtẋUǣ>S ӚKW>@oadCq $ uaeo[|T/2+00XpV4|oPnKbq# oesPz)lqzS>طsʍ1wl#]r3PgDkW3E.|9@!9c#徍U(D螘E2GG.^`tn.eJjid7Đb#U}LY;3.LE3YTv1EENx\bj)N8O\@@@#J-؏SuiӦ;ePQ-7WXxh\kfR@ӆc?;W>w圣^)>j]E;G.Fh8|B!5@=ZK4ҨV/b:= w8?&=1<`.4C9@;gE0'}?1ᔑ\H^*Y;/Y߉G:yCH|s9O8PB@87# J@JT~^GZ{)gxJ1bK$I_׉Hs14 Fkx|;R)s޶m2# p )m!`:\,Έ1|o!8&[V\Z d)۶A+[.r肑@ ڶs-TgQ2ynb& G^IC}++yh0[vwvaf\【T@61EzFmw@?'C&7Ёz9C?uQ9j5d!Ed` LˑA]) ]D2JKNd9!|PڡCɴy{1 OA?}41N0_b nx#й0(R@DS U /?H"vv\3E2"vS)0'rIAoJInPGmߟx{J0?~Cpj<&Rdu|Q1H­;ɘ2~oo)d`d7J_ J mtf} ƷM_Zbm{G&Wf 3p1Ȩ<2o/\/0(+ۨ?+ BBt&@{lڠ$E[舉`vzRbxIMLy|8؄R"? vh+׎`rrѢ4҂4/]0&J;̫| S(+u8fm;uv>h*vS9&8qʅ1!A>U”z?N "4vq*#xO86Tj-c;p>Ffү1.GoEmlq/ΈyifW‡\2 /p m e^T8wa>u{a.xxg̲JQF)=0(!4厌"BJ&\ Z#agLzwiBqY^bi t.两>yp~]6.dj4W@D28H.ɅgfynGo_)}?LƔR"%+r;G/(dX=E>q/\9Alt(h& #`ݜR 5owT93c `B;f|Ϸ@F@D d{^spAp'6C@b\;a,I:;!91!x@<g0N\9CsÂF'$?olۛyF TW9MN'sL !0{戀fϊ R(僔w8I\ _ 13%wZ J™#'AsJ1b?8q^LŪ!'H$/^4b4+SDx8Cs> EVj/oSO(\@T`VuRV]DQAYj^/k$ct^; 6}RUgkv!RW@r}xǨ猄Z:bOS vo^*tKsy=g<lH-'#R g}34G>EӶdG%ԟJ4y"g{qxE)es&lGbǼHlXgxaG+,v2b2Rs ~Naq_ș6h!x؈>&TuLV-*`'R+B k]3^r*ĘPMѱ^(7/1mjb6L6{`,lt`d0qb>*zKn9zĩH7(DHs`Sc}v0ݮP>lE0;{\ %Z: MoP&kQb2rZqlE73ޠK}0Z?uC5-6)"7-ϑ%s`Os)cOYiq3F;HrESp璘Eqd+/#A(Q0 pWF#`ɨ)o"8ecs5z9 j:;B؞]] rJ_g0 coB7e !%ڐbO |)w#)4= 81pض ]HvY"ձ9&^ }N@SLm*ə #欽>L}BiJP!DBBL?FQ7;3T1g(2FI.j '10 X'3Z|wQɨsgWu&B!2X '@)āli#?р|$]y1،q$=Z<9&~]̈́ۊ{J֠.8v+DuI!fL1ss.=1$\6n)6CцMhoG3xw]QZ#nJ,)Z-3a Bg\$KKƮaY ! 1'q}gSKEاH}^&85(4sompj(\rٳ^ܟM'ˢщΡ QweZؚeȽ 9l)aL}1bDIÊC]FXMqz||Cy݌(vaކ+`'^|>/!Z!=1;31(CYnyQ)cv}(,?#:Et(263`N%sYyZ1=˹=|mxr l+Wv3Y i;oke {1w'dh;^@ 6ڀbxcǞi8sDTyNgu]TpMuD.72 8r ԭgEb윮Vmؿ8I ]iăgHR1Ҍz"M c4pjL( !R9MƋ|hG/V->< b7ѮB D\r뤼xCؙV!:B x@;{F9M.L}Rf(Ւe:e6z6b !rIIc S9R@p !q&nqO6 fcc`*Όr4`>'59E[)!AYnl9-7z]JFk&>k'=F}O)cfݹ"|"?"%X9~$ Ni:1.@mp@yzP 4m `ڙFl4t>ƱX/}0pj D tvޭ0*$ }}9cJ*Þ8,Ӏݔ2 ڀ•5;^Ս9cFkc6/ёDPdDxTopޓS L8 1ޙjra7ไ#i ,[k/j㠨ׅ Ρ^!i«CxJӆr}uKlOt-aB yH Ko#)Q4&Q8^,8 sºv>g!f~}>{-f[è̀1!0(Hφ)wvFW2B`fcnG>xp+NU r}O]k"cА;aɝFtpEc}VMh+ZCR&zi&N[JB7NjgMl=1zŖw|GQso}oS{ }΋z1p)?Z :;mPhTjCD r*.BW1ޔ6tmÎ'<3ESzO/Ŗ OT+)r㽓3#bL\D9ڲ=yZ9G;v:LyD3liE.zOrx4ވp{pġmc9R6jX!KΌs:/|~pREx$*dǎIF &MI!D>ϖ1,gc{mlf腅v368zԡj>~ĔT .'TQxQArV@Z3!M3@+7M!`%9 DZGz}.Nu !wd6F<^r{l)*zsXr''#? *:b k(::F9!Hr4'\*s"m{\/ȥg~6Ot9a%>'%=4\Gb< 0i 0FiQv=vjgk!QT9zis?ˉl kLpW4Hg G#Е&r'S# RJh"xkĿ'jJɃd)Rf9< @AFK h} Ѡnb7ļEWP{aW` e1?\Y,.-cbt%oOLTo' U.>h8K >#>}7)fϋ,͉uhC[v36څĪ=g~.Tw$ c%'dnQryu\u[=>= Nً dk ^JZ nb"i hK3? ^ Zi$ΣN`˙-i" bLҨ@JFhq P 1aH~RVD!s:!~gC O #%!7~~>y2 42,[ǽPx0Q:ұaVK{GNX5ߒ ^oX&wӸX5ƪԞ_FMNjO,$.mϓbDL= 9CP=d(Hf\z:qD{ {c(bHTvA;cTN+F9!^oSƘ#FdʶmN}=bvC!>%CVUʱ_r3; Vq+\NLWlD@B>' m4x]=U?1PjY.DŽ 8^oeKaok0V̮\u~>}޸Y]!< )}YXK1~&?a-<^!OJAC)NHU7ЧR e,p!/xt^H.vbA)H@)_~CniIM>O R / 8$Y "F`.Kż%c$*Ƅ>Pz T!%ʁc.]A$)9fMrިSۅM+fohj"&l="E1m[Z}@=/洿^8qQ(6*OvtMeI1F\4 dA9O:p:ElD;?O+j)̶3\ PmA<9-UL% ORT; .&X-QL{W->u(n&R=U,sX2) Mkoen1L'P#cʑm!H{,[;~Y]R Q͵]TtXz='.'6[T`ٔSͺ!Ћ؁r}dnѹkݸIΔm^v{Xq|B̮Pg {s-3X&Pe1@lQ[m\v,Ϩ= ʝUch9Lj1#sk;g*16li4NIBi#VSS QzBpHyeFo8ϓ(~zOz٨.xg޸2k*8^oɋymo3TZf^%מCDRĨ >%Ĕ^8#yNØm ǔ0D7VoctbNJuNtqyUG"$^*6&RLuI4FU~:Sf >'Gv)Ъ:ziYșD]-r3*)3To 89Ape;A:GN!E8'd-p*u*ɯsqH>Ylkl/J\TEy`1儔RfaJ;M:!:iC;{H*2=owv:qr 0jG7.X!&FyƔB!BsTV%E:sS+/X,KDDb4DŽ&McTQ͈e3`DZ^/: 8 JsLyvr%8v ~@2 q*U9p_ȾvTuY(LlsDV.r)aϹTi<0F_! `zg19ki[)h2bgV ض@xr]^'J*m@0lavZbV-y-2-ugf92DfufD4u'i)-loSq$fIj>h{J90>3%1ÉBUF1cqQ+ 1>c2!|* ?_Yk}xH1XVN-Nyxox3:?iCtz h:V:/1Z4VP|,H. (Kٱ|ߘ5ԶBtw =ͤ¬ZbJ/CU ?XaODo Cep˰9{611xi!O30nv+Gdnyy ,s"`eja&=/0\#n9Zdqi|ukXFs:۵[*?ϕf~lv Y_s햋R %jNͥTci(0?Ⱥ[pv>pDe.eTp# Gu2e̗{@ g cz$*8<;$.M`zg|vˆ?F@b܋Aa[bRSUTS+r1^ 6Ac`O٥q[ {G_VXU#62qvr,=J=r: ׋V?/8QIDAT/^PJIXL&׎+v]+>*ߨlHƯyc{^qK,J pg, >D*jm7z2+zVG]T|rڑbBϻ%n%঩q^o}aI~w Sp) d\mq$RZE;x$3:_D,xoÃ=2Y\>7,[\ 'umr7fF*0bIrPΜ͂:ee~x{Exeh>dl.셷 ht ]u*DspglN˔_7Uz_[ Oߏ,S;_Žgj_' F*ᾏ{sZN{l3{ohzq"*Ġ:KDf-LRT=NLgGfWЏp~3uNGq_fl譠Uh1p}Ѫ)͞Ea#%Sy-# >*r3kpqu ~fZ)dE,=ԣ㦜܈C5EΣ79fmmIKs 8#dxZQi` ]9Iak i GʥSHvI5R18`Ô ")QrŌj)(ѿ_Z׫DL9昪rBpjip!+oocB܈!Ҽ)=fk&DroA,|$N!A˘ d?o(؀'?`K7WggG93ĒP\*X$ z6_XvsOM-^fSK=cvcIo ")!XD""FDW*ć`1bxu\W] K%81S#o&fEǸ_:x0:"αvnJW:0*wvn[57H)! ,loZAD+G0f:̻[EJ9/hȌC$;`gql;T<({eGJϘzZtd&`"ii7ABo)$Q3đx+hfBrOCD`$-;^D [ c;c@B<:ρ2L)SNwDDA,MN|zǶ"DދV" єr96hLdžqA\B-\V,^VaYC;T{q7a}ɪ1'lwUDb e7ƜqU!tS\Oi? Ƀ5ʱ5PqSq? ek|шzl ;̯s{'C݌Cj0 T芝?\i56^4%Yb1$IF yC]6X Iv婘^J3pE%*[ 3*-՜)Ger>c4k ch _څ @kX9y۬ʟzA?å1?Bإܦb#a8w<"dǤc"WKwBuvhLDQrbF8&ڬk^6+ez>ss$?}&كlnryp_xGZ]ۀ)Y9ܥb hj¶m6VRp-ao)Z6]K)x_HSo6Z}ARB+73.P!P?:p'vAUЬ"#Je6H2qYL&؏}4ԻC@gOD-A L:nS[ 77lG;ING,l_ϓaIk˸B)οq'=^7=.5j&Xn1l1pӲ;~坮Z9[| ѫ"[,)j)m cT5H"qGC)~nBIA}Bd5_\% ͈dm 'pL({y.h$x9WW:- fUѳlZf %έCJ$Pr('8NSM{.u=OE)7 e! 0d*0G}pIv6O5op{NmֻvB&)@)3V2ӵdӻppm(*o %T-Nmtڌe6>bQJ闉1:/:׶N2bϑ'-m3};( nf̉ o;ZoD:x֑1ôoUp& $p-;!ضW3| 7OuZG9mqL!bS(5g6fC"F[iXp]>t8儴ܼw5 ^a6]P[ 9AE;XQuԉ֛/m k(flI|-ڸiuypج]\G_9Ѕ&!G_* 4L.(]@kPҥbx*m{u+q?'aX]bsw M>SfƜ&fu`6PHSژ/5Aw}J$r%aճpܗ|D_*O|:Yxj %B(CǙiPˍVaYșw}}bD c'3$6m|> D%#{epr䔲_7Bv3wC酟rȈ[oPY.3q'4PaCϲ)穴.:ŌX[7NmG1Ӣ$^Z|:cG@:qQN9T3\Gڀ%zi:iru:>N{Ȟ\8Kibn#۾A`KtW/2+URDUǣz} tpDpDnk=p۞1U ߿;L}yZ)$3Fd9mco;HHJ?1ZuoEK  p^ѱyrʢ'L9RT4>B35еa yO!-eQ *mGWrtGk:b` *uѰrj!#>ƄhIԴZǘ71q1G5ܖUvLsO%LG) hxp=,M\L5R<뗬n P:T8?U4solYvFĜdяHQMRЛ @a0 $6{͈GU>@Uf̳sF/}α˴b߱D`y x oہpNq]7 ЉiQU9Dj V_8_8-qRa JsYT݁x4{xfL|@H7 %/`#=9Yfy8xPfcIs뜰F~|H\pj#>xہLƣg$ooP?\2W0 DI;|3F_  FG2999Jd#@wL4vp@ii`<Cw(wdžz7-:olG/'ЕQٸjB\*|!VTiø^X8Ҟp]ޏh( &A_a欘T B'S ݽ;B"H1`EVcr*RP8tN"?'w)t0NsQW |!gfθ2O/?{19q M]6ްNޣ.@e ňEvQ`fG/㸰29MxW%CqquJ L+3`:$A|ljP -IDitڽ3?~uC{n)"[^q tt̙@(FGXĻYsL\KqS\0:`#o Mf})._;j᜕E !lgV:C>v 9;|v$O0J_N;p6T 2\B;1O qQmj9Vb2xX,h`ux0(g@5`##BH\No5z,~bY9k0FBsf#j Bn xx Ih @X2$.DO iO'e5':|p1(JË>et[wUbɖbcO iŶp> *iNYDw[o, |B?u@{Ú `85c~=p K!jiXg:Fb[p4XoߍcϘ:Ao.ՙ$|AH!"m;} SkB&yܬˠ z 0>h=sn1;^ u8H/V)-NGGyYcV\ׅ/nf4ш~/LdoB1L.PX7j)X+0 jxr x7}v$fIE92[փfz1ל;R[1 {6nf}bqGfr-U@țcb@dh GWK7A!4mFM1R$DL;I񖪨¶^'^ہIu(0A]>2/_B\ evu2ܡHکp閙i!Zկ.1Y74`B5yH[o([&8LնY˓d1xD"pƱΛ"s9G)3'w [6Ș [F*^73}2s79=aRs=WsMarQjZ )T;Hym\Q?1 f~&!ݏ_lKoeF ňR#X] g2T]-?.y/AuFB qb?'qW=l+\7]?='}I; IiY ^dLP (wE'9l`txVqVd^CFW)O'@p nI)~ >P >}ً 1#d3A2zp>F/*KsN$DT0i۞9Hnx#)8 T3w1ImӦf B+X!!DuI4<͉Gj,Hk9[j5 Rwa òBR%vK429XLSos`!FOe=Ziv"<w8 Hi C]n &1vM {0QtB8{GJAӜaV}LQFhN&`;/[%elcxdRJ@>~Fo8 1$z6 jE &=~e'[Q[ohPFE6ML1ް!`˱;F)APobD7̅ $/<-iMIa1 ,w&}sӇњ\7xN3t2i1P1<%ցxbɄmbU)1*wx N.yl:,8-J hRja)JY7fUPsmc֭xsb|2>:'Bw6Q)DQRx-WOzՉ*!$.-D&X ;~bMvR}G-A;.SAEɗ@xy={']>aCܲ|nCFrpEPcbqv 9%L9ଢ଼JfOwe⹈Uj &i>g3(rU*@'O1G#| WN zv7:A|ΓbHp-njB>-Ib(Ę2!f-ݢ1Llc-6;?إP\|٣N>NnlZSS(pfBRs `IarEĭ;wC_o[3>wݖ04F^]t4mQ܅4rNa'EQ{v[G87c6vl6_~vlcLD!$=M\ 2]-ywR@)jY2>_j!Q❧QM@>l`T=P!v0|.l[sZZ 87Ⱥb gKѝy<#(!Yg#A:E?!lw(&pF3=O6 MGq(dN1#X %1]0M}@T6br5yc1zQ躸ÎJ|a*!q,Pꭕi< :yuCj)cj{CfH@1x.jCJ2a'J|sC:rP:]jNr>pWa~axT_^N!˪upA2.pxcU C_,$OA s}܌V&(/"-(9gj)YL f0#mwyY ЄDu'1Н$Ho$yQo %3byqdOFl#Y;B1 8ý}8fG$R)}KJYhIPeznlǁPGLe fl ? #>__aGMptb&sFAkD;[u:I)EV.3;7zUJ!r/RDَ1V#)"ǀnNpik3')ɀsW-&Ұ$q;416&j}7kApʸr#x-jLԫ[l%<žK8ˌI>0<&~ N_|~SJ$|[:f2XꇆZ>~/b ܜ#1G]ڏX9/\F1'18?uI-7gwD 4`= a"UacuWzc`I,̩n{`QhG1x+R 0U%6xw֯<?$CӥPM$1b`xgheI DRXP,si(nUO}0=![bRް}R Rz΄) w+dqKbg_oH}A:뺐S"Ĝ獜CS;w Hd roYP)x3R CFH$3OVi=sŔS&t!iiKE`@x_|J5CvpM=TƦeŤ2ȟ tcׇmM hqx;gbmԳus}"pXxA>tޢj,sqd"7>Ek'j:ajt$ :Vy+-͔MwUsE-k u:zs伨hQ)\'y?4@[> a.h<+ݾ pSc÷2B:Ou<1/ N, Hߡ9$ܭخZρzW-2v1ۀOy8@kfKFX9=lD\jeƅ@N:B:'R 3;.AEܟeC(<~) ?ȿLpb}8ˍWޙ89&~p<uL:?xot4FRHFN`\*1G5>'-^/hxy8 !3jǨ(<giɜ)Ü@i&6_uN"wUcj~B"@x7 6s8^;/G砵au" u@)<4EnZ+eY9)>-f‘@3yJv*$_DVs8R .6;_])q. IݶZ)|>_x( Rf e_GqYq-|3R&꘨W9@~_}0BSMr*4f)w]"K>]CX"j]O@)apm0KUu>Gn^ILw?dz(\o;"LTTuL00tځs!o8ܿORRQ ZB$_-z9>[-vYF6h'a.S8uNF]vs-S~r,"T! 뤿c zn Ŗ1>T:ij$To r} bm;] &%!r6W>%^lńvE}#F`nR۠׍% 0Qb]#M宧 9±P']Sղwl6s- Lׁ0@Dw(Zf1YՋ z_f@7^/:͕ 1b;޸Y"VHoH1A?)AB*=pX/4{@xy$BBB<н0,@sb:G5+g#z6lJe7jqE)3!Sl#8N 9x̽:qcip.;f>!Eß-O_ ߆r~9 6Ze (>fQkA/YudH^9zs8^ T:Ę"r4 GCAR p> s{􊼿b샦LG6+* &D=!2f%g>ǵ ê#V]ԁkr˸8c0 9㚓:dS#aȦr4Ky8bRT*. L a8V(E[#$x>:^ f.|3j5JlhxqDf܏! ͪ /V)LQ&R=I3sY4d(=S ـJf۶?+cc5P ^<}Cm T6l_ə4Y`FIKPh1dKYab -S:E1Ԃ*RWIIK&Zn^H"9] 0iZ)zr_1Oĝi Tevc zELܢp)R.XV+MZ48n`ㄴ1å{I\PGf)^Ўv CdfȩYVT,dSĪ,BM]0&2 }hvTA.NoGoiFx }Љy|71u[. <7Dz @[4Ī.4wvc,p_8 |Q,`pv{\ ۱g$z]Dt:?@"*1G-X4Vp^mci<܏.蒍rJ#؆0CLdAY{2CBk!W;Mp`k0Nw2u.'% lϰw=7}{GVrwϿ  [;u AJjb}8:a|Ѓw6j̃*Ajbh{t{Za獵E:m q;|KV`t7> 1%rN[]D8o[oN :%}Ud|6rF)\ o`ZnĜXi)Ƙ"P?Ԋl?Qe80]7GDb*Ct>C KBG8%-[NGO@M ( S|&Rfo p xh?b?ޖƮEr( X3RaL& fYUԎj_GN?g%ba=Ώu3sx!9z)Eij|o!r;)e`BaD ( %c=g Nw5Nn:*BطV}Ԃ16 pbI?]́_e;ܥ⽿p^'R1g#bR9 Mw8J~e4;^; cNb"d5ωg;ZCGӕ0;o-F/8y)Y#'-lhF!h1Ǜ^9v>7!xS(Ot2⻗'tyB`^PɘY#keC,~]NpPۛd]$d` n)W'?}Zu\1___x߸>_Pl:zNU<ԙ9]or>01/x>xJu,J3%apm/1ưʰrޘ[QMCs̉zA Se XD\ydk_z8D뤞]mq!2s?W0uF`|ibl+tp@6!7V14z8RR˘[ΗuAVAC2T`,]1ߋx" uj:R$6Fs+sށQ ![ w΄Db" o2]=/"Aewfڑ7|Pi3zVoO'z-c`JN =0Y](w)Te2W\E+014 KH>Z3v!2vao,l*Mu)s`,p]z%GSu"OY:OmN(#%x-egb%8t 6 uŔ >ܧuftS^ls@1Rd6A̤@+|bb9+b"W"&eL +_: R1Musdp[vTpDB"8E6h,Q3wm^`̼!>P'Ċ@IluM4sP00qOT)9*Z|X&97@#gi`9'ݼC#$>fIFJl7mBb y{>Ҝ?7rS9'}&QTC}3U_qB{0+`>/-1BT\sn*fyԏs.H0l*ڏeAxs(%2_^(崮zxۑ(9`9#zI9O[] l6Dgdm3sE vqM,JuRphx&.rjXŋ%ۓgƘȁFlṞkbmTq9iٕ&eK]ul9`<%,X%US\d 6|5 ֙)a 21Bqp;n2y.x1>Oh1.` *Y;zøҜ؎^/w)/oȐ}!P*pt:R)`;֌t,ab^B0 (`1Qm|7}=veH $ztqJ>@ k! Q6D5^\-mI!c7Uj]W1CBm0ɵbL;n)Gϰ+X7>཰a ؏7Bܙ/1!!.:8/Ph8{&h(sC(sve?1hP,-m$uy06*Ps~!$[o:n^_ima2 [25--w"DLy{g}㘓O9'X3+;:VCɶZRw,R-5ư=/^x‹UݤǣumcWZg".+Eęka֨1.5 oOM lˌsԞQ !~$g9ϸJjb^QJSBt.6!m{vx1hoɖ"1AdضcV_b2tT5.Z8 1fv4"nuMLĘs3J99fJ>0 F1F ~ ς~Y]E{3iq Z N]X.f|T"r ۄi}ߑ\uRUm½RN6FHcZÂg ~ d/Ýl378,MPBDt̘S@iܜb; 1H9-Ü9O%wֺ 6hW<&ON F|KSekLdR8uTPi"ЃK^Cr'|.4HqU)m|D 1x RK]oo-h͜V@9 A)%\=鳓$:y̅1:l6 |L 0{'4NHܶ/UgZUKex jtP;03ѱW9}0Oi|:[> a^pQ[v4`1k>H};xB.(B`4&dRUhC&X#A:'&y^$OgJ 8[<68PۆӜ}LzB\RlQ8Ř;EN-v'x H^]SZEOl)7\Ұo/nw7:bNsSr,l,ǂ1'K0#z9#m2Fgf0m/^(=:yz1S$2x׸5rLd<~__8gSf y0ǔ# }4r?s&) sx>mC5lc^{9HsN"] c{q_L$0OJ˙Y0k]nv\J xK4LrL̶+eC1F8okA,>&UGѤ؁xK+iP8GhDZ9??;#®haV5+_%!Q Ɗև"SƼ FYZþh8zfrH-v4^@:'Z啀riH?d\Hv "Ĝk9r=#j78zw Iضmpo{ Cn7BT{*X cDN 1f܄CLi9J7WM1 񟡫=G؎bJ)D9&"z3Sfhkv^t-F 0e}0j*StNM ˩문˅1"<5J qi\`a 5R3Q6Ci|hKʜp# " ջ2qW |H6[k-c&܎}o"=#YD,N<(3Ƽ.ii4Rwê7f3 eIt7B Ny;HAcKh0t=V}{@HTp҃,ќ\ jHEk3m:1Zo}xyاHu!'J& {ML}r)5vTQh+3:)%Ot/-=bz.jRnhc>!;fȡ 2"L皋z!qYnWiǰQwMHYn nTuءq_7}C ΗBqMe.aϘՆ}P]ո )@ :¶,ɿI,n%%A:|vQw#cvEV4l'vuYE mC+=1<:`3X`g-ċcmw̧4uѧgeW2 '{1Cܞ3̇eδ< w(,cnSF g)&vyC>C=x\wIAs6"[K<{U?7򖬸e//Qjk{;N9O^Db 胁X8=HqK;F֘Իňy?Ls~NwNJռ!k)ߗ &,>?2`Z}twA #*OWPYprW!,?H"ß:u?<ց6V hqFkk|[9M?l|Ď#{fk{N7GpMm'{.< ER9q/|DA ]^mD^2ҩȉ5ӆ7#QÇ`ɁK+1;C-WwTi ko1IIX/NZW :LU1yxM@=cZz-A2{>+v~֊c +\$&9`iK|M館{{"W36p=qB00cE/!EQlGC4N7*ȉ]K ;>Gpp#v@ap8FH`-3!dɑ{nwQJH'aZfb.|<χ9L6QʅyH8C .\1T;xPvKT(Te&V#Dֻr~!xEC /sB|Z%:E1jn*g=nlbۈFRQedRn9s 7kt%f:3ɚ ؘGEVNaʦ1'?F584X﷈vWǎ _ԀE _p(בQ|RV~u#[^#V"t ~1N=G 䡰zN5W*/&bdc2تdehǁ\K1PyPXx3Ʌ@P7fzt`ZXτ!Lfg6 ]s=a; }N@/n*`^q?r{3٭-u4!IIݝ:͌X]]0>9;Eh G:~ Ri@W8S\ף^bh2]ANs L8_kEU^.8묨c;6j|~NAv:mIY?0bl+!a!8(u~o;Jm!AG \>>Og Ŕ<>yNضD0ϚyO%j*k c[N7F:$iveOl\SFWR@)"CG`6"nƖEd}+,U @u 徰egFޱ%xZXS%5e~n3m~͛_OsS|3U /W9w9^.ֹP $]$&W rBm1;G+äb T oVTkF[+CǷw_=D _?Bv!γ0L-KvֶHU.Cί>;@B [>0,sAu]-Ar2y̹%"[UNc*:aoؽwK{ "mgʄB"<)Ckp j[[C?CΖ9D*=^ą0>0:ʼnC͔rp)k59BKpà6?VN^`vvȂI8Bb{G ~sfgiV$o}@0O|! ^VM'cg'JϢF0m6+qw:.l268kD'*PϹp1ָdN>sTe=2g! 8p6mqEf=o/XB^oF-SS 0re~7۾*"j{ 6kD]D'@w#*96XCE9)9~bgi]n}fX/p'Paѹ4L9ԢUVypgۘ}{2c0Քvr:Q ԥ\z7cR+A0ڀxÁ-GobfAVHLSi;"y˨c@k,\+,:2XƝQi䥵^ޡpAPs8ΤP H(w˖! ܖ|12=o3Nz 8yQB:ZFoXp]cb*Vu ^104Es%6\w۹MR0>2bhvjuそW<"]9W7Z1'#l'7׮J ީs3ypJt 3RҴV+^lQ, J;֯%>YDxGuH` OxGAk('Or" R3:sPfER1C¡.!Ep@)e>_0NH[9z±!``O99"Jgs4&cAa =~}Q3D)>)V ^ ÜgX<8Uc `;r Ot*aP >FxG#) *(霭6LLEdĔ(mLx݅c`uz?/UP[R!@i7edB>tت(^ 9@yavٱGMxM>x{C-mCL5FΦ::Sffbd9#995yo*mp^p':cB Xx!:\K%KJ!Qǻ)&ѱm4֞f<#ʢe⏕qH}ͼIObBYˍWs1xc>Q>e9ù`hՉc[IK#IǾ΁cD"|&y1؅AT\2E#?)nV1)ǖ3Zog1d=Pnyՠsg˟` Y rحL,ŖH ghH;4sfRnL2_ r"{l|;1I~tp1C]\ >rmX]J#k+\֢kaJËuuJ_صs:DJ)fV(M; M|^bL&ӥ2bb%)mHctHa;w^W(2.}.9-CĠ /V}`ϛE22FZZB <@w'fPN/aJk.n@{5Mr|tKp $${Ić(@_H譓2ǕX_qs\A\L"(Я2wC n3_hJ-qy_{UAF!KaWE\*!"DWtq, ǶazZ+J}0xtfRL!f.HxT|ސTάRLb_p:vΉEi)a\u.-R nkˆf,d-ctbefъľ/E̙#VM#p  .BuhYߋhƦ}#p\q7t'1];jЙCͿ1,r96Z-^|jg/%&rsp2a ?!pnԚG1pz8q`wl@X=˃CbBS48.a.LI 1&7KAe||3:q^3t""iLhr+ )22il=86#-z|::^/_rJ`T/᠘20"`/>f%g UZdeZɨݘl:e ݢ|Ð'ygVȊ~ 6h#Zhľ)"l?4" iX'qhmU #t?Y ?1/Jʈ*|cKcYqz0!.2l(\_`^oܿ?y4!燕[ԜIm ^7~~n9E(]k#zO|@>IrJI(vH[28')R!c>1@m[mvC^1 t._X/j-nňQҾj9Tx U@jr[Lϰ#݆tL^hgA\{ Pi ȷx^ՉBIey1ggÌ#01l Rή1~myug1o>A=}tʫo\ /uu~L CnJC6;^ 1»O 4=[{,ؔ[xS> Y9i|/Epv\ L]rk$}L t`cP1U4>,dize -aҪBc_(S|pLX8M1=N4#Cw$>SM0wj)tdJVmD)3Т(-_Cv #x2h [InT\P st};p%m'Jm/SמQ?3/c} ARkW;ss\w03>#ۉЯ:)UʆkgU>M}^h"4<0Gz㶐e.Ɵw|&ă1qVYip!o̐f.y|!m 4*krN:o@kZw#~X߲S/ >Dr~X{G=ƴ9lE\*Ujs /XdC_>sYf L~ؼhWFv<<1gu<906^A@>OVsgY3=:R<\Ē(e<eA;w: z2tl2oh __<2nyV.2юH~`?]\|0kG@72"Tb^ gqg]F8>燝v}4>RBn#۲jp|xZ\`k;Yu8Zw&0p,az݆-ϊ6PS|] Dh] U SD4M,Gf;$28|JeEAlVĔR"&ε],p03e+͏(Lj[]l)y{y]BXK0'/Ou9a>5 29e@g~%MNu3oŞYh(Se~Ȕ= sA-+# k"zS }G2͹I'_bm1;B:q]N4 *&0a ~uԨrcൿ)ҎfU<_ u_ڬYw_/+<b{'wƢA)m˺ z#H(W$vAW`P[xȄ!͆^*OO?xS죘6:\χ~ı9\jrj}ۅ H@HL Ror7S@JUHXsLHרU VN)UV89su Yu_^9C3 yZ+c8Gh>r2D\yۍlyOcCm-g՛@$E֌ !+()e#8^|lCݻ'ܧe1I$C^=71Cz.縤:oĬVAg+&u0吂)Eҡ?; u |Nh`:xdeh*=Aw~_/ǽ^;>_|pc#;E ʜX> @E=(shOϳ|,|e2" uu_ 6(᠎s }mw@hJ.D=:y;~>ndOARFdMΔNO**3|v?jykѶ%@@:G&a:ԼS\G..R sInF$Ѣ(q_vL" _]6&'f'nǾoO!u_xAVHV|f u$u8se0RsUa.4I"G`^=Zpn>mO::7" x*/[`Duf_lط )TYZ99&'"DZ3χZcU1x8!,@̀kmu1%<#Q#c! }P(΂U7L̾e:-|C)^rߔ t.Yt`qtL)T'(7Bnj2zVZ#mߔAQ}V:x{yXO7O׶^FoNJb|*Fp"Kr`bu: fa&Bnp5-jwZ K3`[nsw~}iS[[_'ds0/ZV m`cݍ]%|i'se㢽mttͤsNS1hnj0|:L&jT>h&~(%ObQ zBT`}@9-t7(}'lF4Tm;ϋ9~7|9g*^Z",{∈Oh#$o%T1[خ zoC7Paq ~3\u~!qƍo> Xy~HNaT2:Pkldm@3jܐg;C̠#C4k;SFpTV,1'5(1RR] Lc4=D!9{EL`Mů8B̸['2Ak;2YXKwRFt_^ _(wjGL q`=F3dNuSly^T:\r?lsI 1ňx&$ݜՃat8 8_pN-_N ؅ʋdռN6xbuC/Tm1"Rm{6!`'r/8Cq!<1(;MBۍUӒ(h~4iRYG_vybr*}'Hmw*R Yn!ߣ54=<pxF-;@a ^v[z$aoqj`]0@GG"GBpǏRڠCIi]>0>@GxBl$<;ȨȪJظf![Th<{8(0x&l$"r ̚6DR)GY8E91|vW9&Ä,g+th; u%4rlmBP@ bѩ§>\?>'7K"{ČMfNRR,l^c":q11ɯΒw G?KPfFwh-?M<J. Ɲw::W_!"F|0,#V C*b>tV;Zv|H} y/[PBuîG9CNzRgZ7W޹8?IJpHE}6L/F%>X!n6v,ɝ'ax!)_:h6B8G`\V 8zL`>'R:~r/Bar$#+:m,G>*!}]c'bF Oi/x*Ės\`KsP9pdtRMj;MiS.-fY('CD @ZRu(_ q"{4dIukgL\gŶpk9| x ݏb` y-&4\HOPPlR{iI!iCm1qFĘmaZomcqߤGrĜ8\Oz.! 1=u" Zr/X|anc4c1^{E*cK9'^)FrW::}0%6BJ'OY\ޞOjǀOQGY+}k~…j6}r"5NyѾ[xªI /VO C_YidhH[bXNT3z+`sRmO_HL(5zJgK쟢FƑJ#ogś+thkm0N VYTŶ%4Sa|* Fs$ izR0sݝRt$ZÖ3Grw8킘;ߔzY{:V ڬT|tJ+J| HCi Ρ|}0:v̉L`Vft2Kjș&ERnrjȒ pmEqGS5YlѣM"#%=DP0J].l2BЈrp)ҝÞ3ePx'`)&*@#!:3Wer6 `e-sxCw7s(CiG i>Za lo)z |}cXd9mPRH&t­:?0 DoJ,fm(V%`\ل βsOg<8;-'ys~um%[c|5xZ|XNJdL7Āo?ZNJ8C3˧ Kf1&x)!1qQ(P6ǝOPx$O2nؐi>i@M1mSc@OSΉ!7*;q)*dbL!f@ %v۟ob|.7X0}/O"-fTtrgL39k*„O}jN݅zzmIVw!4;GwhoN{^Tލ%W@<_3f`Zae@N'W^*tQZ&cVrIn63# :fL#sc(#>yCMJ2f니j( l 0$ez G7ת8^uErG'o@ra>#rٸERNjsM^ $:ȊI.=[ !8 Ӥ/Βwj\ՖB`)eK*a2;Kl͵wNBeoӘ%2:(%#9f& m1{ -ϟ;#IjBebFy_mꪠ6<'"QÑ/A:/]ݘS"‘ҎmgLG>__w6LR_7IID)@jgtf~Bf(!0 C_}ך4^Du~p@.hy1,Q qSӃ}"m.('~:B ـ9)+ F?#]\$y\ v$9e Sl}1^p7u;2D8pZ <#Y?;~n^H *RKG2=D:X^Yf`! -@ת !E +R_Y4։Lu (c;Zvt-?}HQ"zoj%vZ/$ 0]91c!K gc6>S꽍$,'u` /uO&z׺`:F__uضfd:={8OVb(F}=iW`0:38Ht>aq>v$!:AI]NĘx‘w܅)X#Jk$-YtQ΂dU.NU*c?o2ZB3[ÞJu#I ߈y@:IsSnhf״oTPh.=X9PKEG>pw,췜'.x@ 7f qT"w=cqXhWu%΄X ^DG\F;0Б^D#'6-201I4'i~^rء-݇NTMY%5MX6P}Zp!`>o6"z{iju/PaO@Q" nL YTK2h;-O33BO Q6Q:LńKx:Qs4t)kc6 4SE1o9;)<ߙ1d-Blk:K<{~5MA𘍹Ⅳ;D0"g̼T=N)a*;H&N1X_6w?q.`I<3ۿ%]Ys~nxNReL( ciMxm sJ>'|ps*P [ɀ,0k!y;rͼ`όzM9bBQ /VwÞ,@-MTv|u)̙vŊ\#;<Ҍ: k'^}4CN|XiKz>aSZcFnmè7=N{xb"S>烐S*}͟W Ҷӛ"Z)\PQ ^m(\B/3lfpN6bD 99]ī-j'L9c07BDQTqrߨ@CH](oc09ݚ<(Hm>֘=瀊B chGFDxЏI7t Dr# 5t~n^O(z"z2,)7DE J&<`bnUl?Ֆ05G1uu<[s eU99Sm^ZrC#3LAiU̓11,y%B [Bt3@1Ȟ%D7DZ4HM`%FiY:Wc\{¥r/Y$:l[qV`c1.э-)X1xLLS{CŊv11#1T<,tqAx`vLZJ…f2X(>$ }:T(1 :)W6>$~%(,ٷ׎שT*S1D8VRRwDU'DLb2@7Dg*At``,cژӐYR_2 ^/ksS8I){[(?ꘊ[lɶeac}s3S]IHF A(RlLF%u'Oμqr1)P,8Z|c)r8 jg n0L;\6*>SI99![{9bz6,Q@H!B7{U,$07'$Xʆdc/牆ʎ6+V%."JgD,֜.dc 0ةĜT,rNMRH Ii 8 H1Đ#8㜑Av S F2B;RGե&"]1 8NHg]*TѮ#jKT >)/804p'b΋u9U*;~]i(\IayuʖK92F7ZZgDɖwmc;2.xE+??eZ&zVhl.IJjeS4M~aA~ԣ ˾"1 .n= .zC-=^KLB2-`@N apngvYy5[ڨ 1y\b6g4-`d$%p$Rj)qrF7您\4fA!fKQLp{.}t'-]'!BHh6w#lRMh SEw.l%sfm9SV]h7v. *bG{mfb0\1xl=M]4F'3{v*X!jC6арH fE֛KkETc(R5ь~kMĸ L%uzo1Q!E | 1P3ܲWmZ9l1§ 9D`{Ρ䍑#;B>DJ۶=o S(O!ѬQ簿^s~P/JD 4 !]$g[l\T;zOnŸeq[ B.v99upP2Zs̀[PWJeaCof13s`O/00 Gv%p!gА@rq^p"ś]U 6Y+1ؙ*p tHq@XFj[wr |I1P罇Sb*xo*TIK1{Q)L5B15 6NI7{蟘?-SP8fú-=@psgFZ|NyÉX3'|IVq{|NK+ՄJèU\p.?ad{|k{!S9'Tټ^<)F*E9TNV[ ]/W1}qd>/.[ޤ|xЛo mIJS%6=1 )= qY60)׿R!C )`uJȤ"dqf$9pzzZc/%^]@;eElҠWr[}̅ŽG1̩[\DbXطyDة1ְ)Gʶ|-ȿQ8sFVjDme[4D5%o୵12y@Y^9/P5U@%ۿ7c4q2,u^ "B8*[&,ЛbXHp-\[e`X sc+Wх[es4Cba Bi,W{1"q:o6]` >&E,Cü_TI 9 LƋ!{{.VL9{"N3/Vݾ(^Ԁ4;6y(7x/ןv*TLygB|PˑQ qmNӢsG;a}EޠPDϋQTqVeB9v0UavKO$m@KqB0ź+&p{x''Wy Rw5X_ čч g kL9TƂ7DƜqŷwG&y>YFLe2 [tR¯_3a+kM-9s& k-r0'tK!CD UƖR.ۅ)\Cw~>90/%&mS 3.L7.Srm_킋dq UԉpCmZ 1 bPB<}y!8Pu*<~[ްb{ )$x/xm67&P:wM/t!qbV'8(hrXiZ[ΘJVvF1!LjrDnڲhςbOnvviT ![;}g0{o{VB~M8+cbHUK\(ȗg*sI%[j)"y8CYp\w@úc\JKCJaw?-;PbHt>Xށ*bJJj( !:%_V< T.JVT3"U^0byysl}p s)/8i3R E)D]eBߙ?e/T.:yDY%hDLX)QF~}(L> Qb-}ɖ=e̠Y04 V'*އŅm/sQtK4049JL) cpZ?<lU\Z9 JHp" ( /CcyląVfwSB 1Gi{QHҹscPdabd_2G?KNItԳ9SϊkPWl!IӤY} yp~>BU|4*X~z LїR|^<#1[cVC)f>xRp|xuPQD>B@%.s 5K)DVX>:";^eۅpr'#=s}Xu0;hīM(yNb{gYPKRT^q9jM-Ci\=&>tFWr/QX>z Uzm.F'/%h\~iʀib 0J}p%D|X(Ȥ0V'm :|i;V9ejZhXj@9217;FÊ<K)w>.2TY^3kA"&RtOg/|\N!"a m@=>&mqbt-ە.`{iBmX|ck]Si,Auϡ G,{F ]O>A-8f |6B"r)AsLxo0ϵ:NCX0#w~aMbzo%#5@]Q*γ;rNobAM F^k ԫ5rB TXy$& y/v3j<[g**\/YrX-ro;U/!o9ۅ`MK-*T- TOٯ1:r)Xs'O ɩ>9>e9dqgk@Gl㤾ݳK @MLTZ ЮU0:E:]ɿ.?8ac ëPrm(p˅1,fx?6Wqm%Y^>< ۶[F7I[7fۅP+QB!%>9^Uܹp1&@%7qB=\oc${sP31k 7__vovh"ڞ]*6;I.D!2y.yߓSjQaH'Af0v0ݮw<§_5 T'U7185xl*ۛlf: ʆ` pdkn\ " 9x@IZ1 FDR'P\n)Br۪7& h Rb <&g뽡\vR%.y١!K9j\x] J9BT3ڇcuuXAu7UV(t0R]\jhy[-\ ׀^>|˖ҷlaB)l赡n:w88F<&gz K@&󼛶52"Lo1hX=SFH}Z }Uν@P͗"QֽViKy]ԋ/qr0[emgCMu/a9w^~}'l=? Pyġ]P]Exw^ͦһRyR(|%(&7 瀔wnPf 3< Wp]' F1ˡn{w˜]6?Tcs_RB-" %s%4Nc=gN0jE҂CSlˏxFcޢtouZ΅K=#!ƚꁜaY 8B,6rcNv. i;+B5I )a|oR) 1_a"1gCڲ!h8IݍA 17,(쟿El+233z')(c!€<0,GpS5u<9?G! >t, gu|0{GB*!9]m A֤~YR1DkxpH1W;O v:Ԝ UXuPfUIO2{@c*&ʻ×t0hj׶ tjńSgr\~}{隟Cp6 1;!nl9&iqb/_8?^M*9^G`4f&djvqr}YZ^W5bMe vG_XޱpT<hWD &$ "aT*|`u0}w] &wp %|>'S8W]Í?^\>VW 91FV 6|~z. _vk.V|q^6C8GsRZ[*%:,}3bu|([`E;Hpقx<^PeJea]W}"|69Xp̉-8+/@X Dv]\"~< q}fx <v`=^w4T4w8NXe0M7A\ %ܵv1^ۋ@Ci@VÉĜMr!ZE|1Res.mfVC|)kXJ?C/xzכ`q>LJsmϧ"{$Zs4Ȱ%3,Rb0Lc7$"B۶ QLv$)ň7y̾Cy^d1 !fp_K,)d^PD}~8tvuKrNQyŜb32{qAq|c1"A8*6ZJW$]38<0P- oE1{^jk)=_/Qo &Aw1ޛZ%?Կ*"W07 XӺi A9v #`B*nhN w!ŗZybn15kSsى2TcX^;RJVq3g5Q:sqУq+D+0U̽iI,[uC6iu-He 7q^EVEZkr )osu~y1k5YjBݪR)"JızCԱ:<J1FDt1e˦nxY 2L)s3A ƀZ/EDJ6m!BL{!جc۲WFRA(ըHC.uL&P5YuH*Vo!pd@$~9g֟7դr@Vh,rhGf'lr?D%CXup)TE]^״4 t̵i'hBޒ$Y}9[n щ0.ί9(/U(j=e ^j0Fy%&= ++lT|q籡A#Ö‰TZ?6Glq*vHiM,nu*2,vRo/̡[j鐀C0Üi_B$B; 08k(vs6Ζu6m2,ELD8N{₻Z?{!`!bƱ1Y\8($e) A,.pd:q̙n?:_n"3$I$pW1(h6zGL Nsޛ8.wOy`>|0G \I0U/Xn'$":<0E[u@S<^Χ`r[zoqXNv)XB̈46)PVQ0CaS!콽pڈi,Gc _'j6usy] u K9yIU'kQ^\D8G}׾!]xh^2*"ʎB$<@@w}#f#AlN*t2W"Zpsz#!h~gޘ7D] uo5Vvfy H9Nl?S8 PNL:<O)]U#E^)/s 닾g^!"\Xug*hBHGyAmOS$ky ,~ΤbgNr?K(CΪ#(y[`SYq 8,J* UE)&Q+ٔV ѷI1n=9sjxgzcVxG}1$,knU20D&KȈp hp~{A}RU6-XCnȤ:Law3ڼdsԑsu?݄rjc 28HSVx#f\HƘC?N9CB zD}͊Mvk٤"V"eޥR H3ަ Kkzh}"DH#KN8#νlc)*@GsR2=k y{DoH:TL,5m?K Xi(h/9˃olRΪSFv-sZf^^3K9Q>(ˎ2B7daw .ڐSy<Nl`Y$|Rninqq\ n_&qk?T'r6HfhoL[TĘ0'V6} U*|`AE{並=9w(FP ȱ;fp$.]̸_(Fi KV@M9v7tN8+xx_T|c,E >Gv~>:/Ē9=U[ޠk?k {c1R,җm;w~SX2npN̨ܶixF%-GQ=SP-r VqYK~'m+,aܜ*UY.(ņ>~11A "(N[ 2)9kVò'>eUƌP:X.Se霏:®&Bl?J8>5a޼f2|y~-b0'C@U!'kިoM١}9awme?ubvm-ܩͫ?쁿{250(h $ڝ>:NmG|}aDh4NޠahĶp2+L]g-P9n!CJdaIy8բY(x\6YF=cH}8*;Lx vVlAnL'EjL/-ʕ&rE@=sg$Lepz7K2LjȆl_Odx'x;뽈W(^r) ptd?>l.(&t,Bȉ)}P?s9m;|p[a+S #ʦ 8/ XFߒZ5x(bzoWC [.DD,% k0ESjx`U* ;&{k3Mf8,stpGoc˟b\ 1r}-a)Rpf*ɓChZXwesI¥̥r)8o쯷I9J\b ӶPp'w([2(1w0O5 T` U^:R2 nyj9q،F[j @R26V$!SC=Qp> ^|1ˡd G˛RiF]ԥ3U![xMliC۶! 巨ـyٓUn[LN>mnR]kzc*r1+]׉1vehiv;BL*zmc4RL"^7 43yP3Vqf/Gkհ2LyFX➛acTbEVxCǛyq'VdIԲZYQJ9Q|El ;%))&q5PƢB(5;Mt.봜͌шOaAGSJB8V".u2IRy .xJB;QBV<P0uZ/"HM])`7߈3c4Fegbs}s/u+p~{4|"mC#兾xρ+B}*&+gʪlA'? !?{Ep) әU,:U11JJ&y&abp ]*m4uo[ـEܾ滜"Ik,\ʍ65MO r"L$01%T9{ٿ] s<`7OA/ϞЧDIkط)][?'¶aXpy\p?۾S+zMB=.L­ ieZ0AakG'R*䱼$2#1~ a6&wZBטQ-}tKW qr72}G=M0Pb﹌6,]M<3%ZmD=Di3]c#DE=.&j&A$aݘGE`'X59W[]'QLqX} |Qngu^g ug(ze&"EXg:ǧ1/^ff: Ox?+=81fN)ǽt"nj1帅92gĈ.PwgLRġmXh=JLgp;l99sJxuAO0#B|&:==;@x`z~Vj["bWrFtmN:fv$Y$UBœH6Ry^($ wʁeJ?q9}?D ωW)V_5;^ *Ny2W)!j r~Ȟ}PfKEw.ƨRFQRE7 Y9SА>o/CNWRV J-ۏ!P,\]8 @2e`˯GQbzcP>0eΉ1izG71 up o,tൿW {C*^ 2H':Ւox[݁-!Z ]MeĬ$m\L FR 7KEI\d8D;'} yE "J؇<mNbQR1xGI Q)+:nѼ)@oD$E,F,ƕ k0H)\`ϐGPp EH X/~%=Hqv\FuKA_4GF"F67_ܫ)e|PEJϢ /8#~R sHsLdқRsƘ $=!sǴSWRqk#/DXĀw]v #us(op,8x.Rtn*sAm#p?6\s ejT"YD΄L_$Y SLH9[G"_>St΢MQX'Ԥ ֤~ZVq g} Peu*/q ED/U>S 18o\%] >#H| 3޷퉛$D4WoXDJ-O)&sʣu7vCW0UXH<"A`u)qXe?AgI'zg&I;FuJH|^eτz|Z3g4_vVIM;_U+rۆ.N.m EIP 4\v§_߈!,TmbDop9H֔C1D 0pi_/E^mϮLiJeU ϮW fOVjcz2 |1vşQP qeF%mv1 H"Ԋ<#)̰&FopT"z]f@96f_Mؼ:`yhk/J\v,XBtQT)Dx'sX ɲ2d|}s ';cp*̹(շ_4rR2NXw05p'&P3"䀜(힓y=1Z@.mXx=F ¨8.V}6Kw,Q8fLyC+F~|)$Nzy`Lg.Y{PcfGo|X߭Xk`6RIDԣꐷa-jX1a™QA1L;ܒ|}y1:i֛!V-Q mUz02Զ@1Ue6[˖`1b+\ێ1'<8EF\_7zmԒǶe\\h_ޣڢщb۾ӒBD!˱U{O"v;:뛔 ѻ39x tu4*[FJcN!"Iq SECd] #)L"+Fn9}2 ϶X} ^[gi&bgըPЙlgyOkt*㚵23;lgwǎ.^dAzByU^\_8-ضqybj(~RaCL(TA,7<[p0m~ĈzUp~m_8ʾQ"<)xQBSzHbո Y,j %n]0mMEo9]9,, )aNu-w@VN bRd}yetx=>o  G:NG.~oӿѠsM6A%q<=ݐ !1#%!D]Eʌd yy+__/B)D6- *d*9f`Zz/>*].֘ .zWq]`YeBQߺM\"K@ LfKnQ7IKh2cu틋 Y.tB6P;Q}v05\2$fef,&31VᏯ7D{a$zB-_<^l9ݑKA 1Eh!`A}RvЙؙjQ'|݅ vK e~Mf:ĭAlD l]IL:.tp-Gӳ".9gv3K*zW~nX 1A'=Tեlf|XBϞLJTB1렬a;)qt1w`+g2枈K#)}J&86r@~EUʶnVe#k N,{ c >PJ@ k}r1/.f@`i8N/aN2F%v}&ДQnR{11NX fHqOSWLpb1Mvx"Pz ۺZ/`9[YbRZ:\l~"]~0 {{~㨧-YH޻q,@hkp@yЁ-S"#Bp1DV;s`{l{Kq|~0n8삇E@O1[3G/brD7^3K7O(Bk 0롪ޓ烘ɖl B dD _ :h1][J [kb6;ˎ?CB^j盦#eqs :XnFB|h# s7އ3tv[Z(B F}gXx9# ss ,,z》 eo2[8󈕔RUOi ‘v]@0_W`\ȂB)Gv @)$vyR?jg-넔2[]>Q?Hv2&HEiWE FnYtDFm)c:AX$?7ȿT$DN}<9r?G)Sv& bq~|Fa9'oy:K\C L >"?Ė^ ^I]烔v`R5Fe VbD(tp&5ŐX5Ƥ/]&!5IXS2,I~N 5 mӉ99[&[!0i-kސ8.C$*@#+_-bΉl_gmG_Fw` ]3l§_'@@bJՙ~~-1˻$$Ri` 7J"1"ˆ% )3l}{v*5zxy݁X4? sH#2iĘ BDTB9XhC⳸&zlxԔvz<{AZlL ![8QS-$ˎ1FK*/}p| YvyXGaj!d!x0*rɖ'Cأ U̵3EȩpZ"pqzl(WEV`]vY>K*/8>蜏dY@yoc:\p][pA&ټgb 0\D<9׭}nݔYT3E\u2:/E6 j;ߣŠFrD1ڮ)wB;\`4/xX/nzmwزiɕ~Uf>fVqtm1;?>3_b *%[i=^x;\ 68 ƺn&R*SSj4\lcƜ 5y*9c!f308ެ>;?pnu@|6LLI]m,.PE؅}8ॽzuUm{|`F5iALqϓg ;<ֶmq-Kf yEym8IlݐdʊJZ G0O*@C'9ԺZO#gPB;I!_dLj_BB9G<lo* n)$Y Z\6jR V_Jh㳻㾚'}̵LV,^!/i i!E8=:v50 7l N 7j7hDzE)wp|3UʾEbޓvR"Vfݙ`^|75ӕ-IOȮs?D6FOEBm\FUI {/fJ'F٨s::Ոwpn)!lbbGlR`t@ K  !1?KmI2z=g3a  9IR4ҊK_}Tv KecZ/?U]!!a^YIP1G8c@*҆J~ẾQ e>A}`|sU}9>"];a}.QSJ&|$Pj?7"s1^'ԩ~}Z)‹tyb ,d,#B*qQT&`Ō=#}1R~# LLT栢k T3Ȋ@Q~}T˱6c_2E41|BJyЮ8fixvRH%[e; qŽޔƎR)*]PeaS2w}^uTVR/[g\6qq>fYbE$w??w FЫB^yQ.޳ó9n9^^d&sa~Q S2E$iHY@ZH2kY*30 9#̗7 7Ǿ=1ڱ&0810B15^1fr[8-|9X14{:E3xj=FID@ ONxPkE.r, }419LB,6Pv"0"mCdY n-٭6N1ޯ7x݈gvVADspqb;oH;O Y^er]ue1xpѱi btl9/N*V8[S'6fx͆ϟ\͠*ba.pW -\0;Jt#z9ى7x,&Ϻ'vIMD>*q}v8k ,"s3x P7d}90]K;OHE+a"߻:/Ü>fQ"v'wԹU OIPc<#FU-`Z&lxcڋò@ZpV6mYJ^1qy<, OJjE8Hkj:ËY/k C p}a1IеR$GtIUﮓ~qѴ<:AYF嘚Eba߷eU6g TmO𫠨qؽcDya&:DAt.Le"oN..`B%<{0@Nʮkb|12U 6<#͆u8RIsuĐDz[xyî0#\+'0K ]a*=aDՌ_Q6!w̖PUpAV0L0$6g4+&dԜLTSè1vI^"/#67oW˃4*p^:LL$1.{Ty9s Z?s%Ztdxmjo y>9MA8B,i}k)S>=Y>e؞7.xۛ8~fL&|FA̩H["Y_u#잟@;K&YQٷbL]0!?e=%QQ1U._ XTSxǮ!ev9e*1E?l.R] [sEQFoE@"+YI`^}{zFp5ap=XhR}WRthuDj :'L/EpۛM$Gs&0 Fi~98S>ufA~jsC!n>`B1읦.jR \phENԙ\R[cGm>\Dl 4βC;O=N_(|XS11AA<ܽlMvlaqoxCLZ% ؚNG)Ak7ziGtNla`UmxLij1a`N;fl1nuSwo"_18ܽ 7tq4n %A T=T|>`GЛNϡzӲI } b{s.tXn(D]{7v\#7*oĩޛT>~ߙô3^hkѳr4"^1sQt1#6,~ :8Oe2^__(Z[kI\?6 <¯͂y}C~s 1jõ {{}WKP.}69[GBo8u;'EU/me{Xt1D)$:  (\SθHm٦)4jL!8s|_WiH9Rqx1c2zaQݜTua{cyLtr澽vPŌiYb#%1Z}&^ǛM_KDjY9mWaDy}h6%;I<IN0^% f/x4(i 0t&҃Soy+ܴQyCo9 X]GW:Md|4-=*ɹ0t{a  p1cYfpF|\ g̣ ?]ȴ׋c6$e#6µWY,(9=7?HneYB7:}CtR `A992jr _돗]@D. ?Ą>&,Jv5%,Ja\y i߹d$9 nٴGuk1*1i%{K/Mo'` =|%0!,VQsL*w8_&;6Q{pX0;e4# ȹZ ::ߛlZ^7>>g-BCB[wyzljULu{|%5#YIcuzbs+)50? {"@6Ek۶be1 `K88qD"JN8 vأS,-ɽ͏LO=~1-l2qK0FG uaVV. =ii(y]z74%yF-b. 9!8yRrxoN{,G-f3c\h;rC4(Nܓ lgqRDbrq2F772m>DT !;8`߾RUO-#/e},iuR`+\*[^@7\]`Q#bT L-\|\@ŞEveiþc-2Gsss6^bp <儜/ӠuLro" Yk#ƍp] C]S_9왒Gm/ZJF!%˺&T:'jkd;i &dh Zh(Y k=L0Vvvy4hk:Į{tLS,S-!k,+^`kX߲&L^DT |z"zV>Jʔ+4͒u~˕[F$^m%?^c춈!b 8GOSaq]@ga٘psá\vf9-Y$_wטpPt=}T Z#0`RFf-ޞw _/>)X@.bxLDzœ{U(92v,/+@De_cP|]-YUy ?3~g={Qb,.]LPo"d8ӞC,>;i ɖg3`,iFm$ꑡUxANw5"q(!ޕ"G^ufwy/ט Td6Yc5*jrd>Z3-Fq?g]GPGL*uw~7nQx^8jsRhLF 9GJԅizSz\ ҆s6蜘h&NطGX'p $C:51hKxzoL5\m9QE qǴp bN cduw> p qWy0ҵcd1nB UÖ%B[,Wp5y0&P&J̀ICXlr"O>cJ߈72$CM:=Ҿkv_Tw^LK.7Z-pkb $}@M1 \b.B_fVl9'=~}#;ǁ\6[]Vg^"jݮSaw\ e$Qm&8gG ;bD`tE)ep}٭3#u;-de6\( Nd80 L P ༝Y}6o_0g 4D9G[)`!n7,>N !ʾ'i碂~<ӌ~@Hluoꡖ:e̪sOP`v5ʤjm2QKq 20= >.*両E ( syD-ׅ;N!0Vle#?ϔݐ'7g(UģWH6Zc:cʨ@g͇Vב{0̏Q. (]B\b >񶬅L`~׎먬bH^؇slǟa@o#úX@wMY9|]Q5!hF\m顤j8j>pk&ohٹH}DPcG^P果p8me-h )ϓr  K-{6<ҧ`a+;hP$Vbzm. chy,HijzsFtupk>%3: nQ¶Cp:YM|A)tA#7.քc?3=InNĽt:.@s0g](mZ؅ʎQSƲ9-SPG55P3kN=/Fct TlhD^͍ބFo^k(Y~,0r`cg|,sa {q  ܩM%D~8 $i"f)IwhG&Q՟s)*๘v!<`ʜq{ 鸄f 21ް^~5䲣lTv y5s~)[YwDH%` cpчSk}ƕ.lKq9-bL#Ie'?9J<-&Ykd%&x%Iޱ^hWE,ޭAIgE"@ 1OE 7`KrHx2BJ<< շ^ ƬG.ԃ8$z_[>m ILRf'4u>8̹"_c< jP1:Љ^7)j״ʝQ}^kZQ U۬6>KMf;]Pft,Dr0Ŧ'¢ (q,{w'w/ȡ,`,* UUQ ڭVLyğpjE051;ꏟkvґaSkVIER cEN[*zk:vA3:z,Dmh$ǶicV p"CMFA9 SQe.J00j@UǮi-l oF6 qX턨X[ʌ/;&62@Ta}[fq a)L8tq4%ȿzKpaz&jmW@Qnw6 =x~Fs4K !0#8:7sF`r.WEދf2yj~kGfj;5hX,?-Zؾ^d[K!aPx=XpfK!´|.kʤ2y.ʣ5;/%bKg;q~,,:MFN0saD;M=krjZN"tuyˎP~6V;u=gYq)yyC'EVY9gO̸fmպ$k/oQI'PJp2>{ピ3Yz<y>L%Sf%ޢ{xgLӅU],S!8q- >tUYGs6 Zs"R`m1lk4p|M.TECiMjB0cp7v!jI]4x>< u©[=* 1)[`oܭIlʈaz&H*g,<3O(M好dC->bc+U)EkMᠼ~W]/dr\"Pzk.1ɣ("7|zM8Àz7:}AZ\}.9b;mzYs6# bf/;$vca@ $AZ˿7:״_'݌y)-~I+oB]A-8/(}|BՆ> RvbL-NsNgq:D3[ j!EiLSmLbUD*H"Uϯ6  ,/qXo\c5݋@"u1;݌?&aU9\S:VC7FmN,Dby߰V7!!IT3Y8 qrI8v!8Toʭ;Pxp|1gRAG0D @ZHq!8븉 \cu#~t+h1Z Ζn<\XsiFKHō^2[u1 -_kwb5'o;FPVMy0'+~5ndBt cGo hDJ K_|Rjg},Րq"h>S ıxHfs$X,eP˜{%HtU: wPU~!x^1Vl 8caKE1~v[kNQ]p?ʤ5eOX'ǻ'SÈN_I$ӜeRt5;Ԛ Q ~c3TI^ 1\H[ o|&$q7mq~\tA"5r /|F'|KU7kR: ps 6o|/']{x1KV*I69r+G"`[Rj C! {ଓ%~}ટfB`{J 1 ?oռ}Q҆:4*)!6{9sP? MΓjʶ>fʻR]Rƍk ;B \y3h2-mt}+X=' !e@}\ʋnC:G%`AT2#*ʖp ۾wˌh<jx`J_wH^U(8;mv/C@ku p>85,,ԅkֆΜy}zLq!ߒ ==ep LB3V9mgIWo(97DP6: ɭp Өixm/^&BYܹB8?}|)>I ~fk [$Nv?K>sL>_}gA#yrbN2p E8R3ndM XX=T3ژ3pϟ_L]qvV 2KTĜqzN?d-W0BʋGΧ=><j{U/mc 7 zhs>ݩ,ܘߞ0??gm1'>sqв[&boN*=&=[D5c5owaPITkO49$ 5%(/be)f/xB7y,8'p1kpvdv` pxyK}kRi-LpwIy]΁iX [7w:HcjdAkEx\ yuLxL*8DqőI4'Z/`0p5Ml\С(9 :q0 !"SI=>Bk Z[͑ 9dmjIkrvMjkMpX {Dm2e{j'D@@xk[pTv+Ps~s~z|/)Lz7\ nߙ>2Ⱦmw#nHyXʽa^?,v=3k+oD{O|H!ʛ"BPl AGv}FnJ4HJ WR2ITz0n{cؚ\pXR'ep7No_x=~~ mBd |Rje1@T 0w9dt4C>W^8oe7UQya3$K@w+zQ<`pGD po=l'n 'k;/ W3S@)JA>NB%Wae8xԸW{y-b/J)2<Ļ@^hqAq7*}!$jad^-J#O Gh9Wu淃}1D7敯ߊ%@ g;*j4 sQ%#*Ƣ0\{ĢhfK)sv?l,yk0ňqV*?Ly.'lq6f0ɺ~{Imc󑢡/bܺ7SfR=Lט}xHrYO> LX2~3-Clnkl-3M5dӉ}sAj#=~$_ܱt~m1Jp|p \/[ˤ_]Mɼ`d<Տ|=:j B|Jrh8 FJu¹E,bwAD e{-!]3(9'0Ŕ(-.mcB s↽go cԐ\(0c`Dg0Y4;#V;s: }!cX`\9} Drg41ʘޠmby<1yvT`rU'f5\|lacX_eJJ %pn%)N1'ZlspN묜-)KyDׇC\"aiA̙ G8C]_e5٘l簽-.Ut76OY0PeR3I5yx-P[jA0~8&&˩2|s|$[E &gPlf%2̸+k|9\{#G믊3!, yWزB8=)R_kVxm7Xy31n; 2%"R*8\r{ʋsX?aC Yig#,ʦ[ hywfg6fL?x}VR^7s,)\p(ZM  X ,3{תDyOE:KOzٶ,?lӚ{4ѨT,BEPl$hDY$@!EhFب'LRef}㦤xȼ]#g~Y7JQZP]>q<'B\Ƅ<)m)z#h6S9mk,DdxULN0.96x]' H 39>Ȃ $tI$:\A 1Hv.pB7=Pcq3 >hw86 l r^!Bw8+sKiJ;HòYg%GDy6y1Pg$;!`U-d ~R+73Uƻ1ȦZybOBDVǢG[d[  qoN' ĈjрTUư!}aښp(~>2BX=Q )'n|>. QJ1ļ+{qݏmp]kXrY2Jc":w<۽QQ؟x]/8'$n"Y^!캄sRLx_oہraL `?(W +Ζ-#0O7k h`{(7'j+v-jȕ%,pTS>c.Ezֶ89BzyPyYk.B.3JLl氫3}:#8Z7 60t}(fȏ@!zPہn27zY e%M1X=Ԇ cGkDr]&{'O)!.7lSCzx`]f/1|Qj΁)K)2^po@v2ՃKSjm<&~|fZ+rSIʼnxߜվF7LoBB"iò‡VyF|2[BBAU 2cpIt4+)r1IYucv L[sx nǖ-&m8ߧ=!;T@ciܛ~<[<Mgwf6Kr靌5xmyٍZ؟O@߁)8OƽzQdRnMO_/xyP[AJE!yt*fOض >x!tM">'ՏwBmO)"M<8#1M-^3߈ }vᬡ=at[܀u3ωW,.BJ9[Yf"tiww(WvL鮴i[ɇip^{AW=ȅZ'S D^Dޣif+T7LxǠ-6}_RNĸݧ'y7TzcPp3Zls%_6D5Bh 2^Wj|!<GC}Tb@??j u6 [nT Jit\<&_X "$jO8 >:νx {5fGe ns:/ȞЊ@)xO;{`-&ό CUԉx7rrQS $B$Jś_%}Z.ҋ㸸kb}ĢX{P90u!\ Bxu[؊=^QSaIŝٔy/<̓aqϲ 싁>Ra_ R0ӆ+͋XOG\3ӶZϤʍLjQ+3^NN{4'̉ BLh gJI R![>P녔2De ЉZ;Q1l <_7 Hzb:VHrłk8J)2Cm;ХZg8ĸ /kx\D>EQVS,r-FJɩrvaR.ǁB䪀fՋsbhǶC"!'`w$n]DW6%x "R$ X磑g))1*fetc ~Q»LM`ުG Skӎޭ]9B9SN1Bْrc{O%jv:Ðs%{ZFF:YYS0lޖM~*<]Z+cp_=Dy۰[=8)eDcľTG[ԇg1>FG ƨ[8eH}n\ $z*]`ҦSY[3o$18 Mq$k'RC68#^T0:^8cLgN[z`-sC1>6 sNbk?2י0b'R'%-}QJ[.yЛ݈:1=]w;r ƘoLE90IpZb"TbO׺In᪜M:[QBF޳z^~[/V `)(rE u0^y3εsLgWZ2zsV A7hztV9&8/xNSo+1:c?mjC;TK F2 &25mX5twIALmObubq|A1Űۇ/!߯uji^Kze6;i7i" L51\ dD5 44r]m+]sU+1Cy~im+ _ NF.|N`v61ѹSx잎<-ʀ7h>:ˡ "ň"iYyZ z}\al7s .C&CmƧ7'D֛Ly~g49%xrpZvT6mf9c񦾻!:BgCS򎾾DF=06T>5k_fth?|H)آ<6 6#Z+E(wl p-h14 Bp˙.(.Yܷ} Omz`/bIµ0UEb}0lX>,?d|*.A8؎iEUٲ Р?}fշAw0S)Z74a"k@L8ߧVvrDL>G"I|g/PK!iۻvW'c`I/ 7'<'RY ȝ"p'@pRt{<m§~C"լkަB~y+s<` e+s]Ah )ܛ0@!Eb:y^wy۝A`^׉c{FO%_a?P<ҝPKPTA(WEq1ʏ}eA:10|;(7 Llvc\9} zUGt=V(s`RW녘6u\(RSJ wwSJ 3 ~P*)V#i6i1#B +]Q !Y[ ֧6?^C:!X)`ve?{xX e> KaN8 hҐ&mx>ԞEhlޯ";RbdI~&]\F^F(Rt/?s,o,cFxb@}j1(gX~,179C(? gu!MΨ'xX#GF=}*-UIraxG N2H j}4 +2#ϳ zNqOyUk»vz}Nȫ]*88߂G2f9WdW;3"z~v4ޅI_[;NI 1rfY +Do㦕b9yx>;>l4r,7?4jtwo"X}kbnj1DDO; r(ōDjgEarvƙ61>-YurXi=rdz\m@Jٷ:\g1+eIN(Uc&%tzόʁ7&?LTI[PE$<'D-Le9Ԃ!}L J3oZx*.@-'>##?".9l䒅am4UbX񰍄-Ul3Jv?Qo;BH2b~L%P^V4BApstբ*}p<(Sy|}N*{dr!o;zo8Nm*bȼyM +6qEx/(Bk\)"Q%jiضiR4 >SKbLx҅)oT$W;Q4F=u;lOf:pL<|@M;X5zY8ϴ0}W3)Ǧ7@0zrsx2/eot'vrpA0rt7Qm=mh`bRW>?Dg8Bn T)=(}-+KNrrm!C2*}YbDLGb&ajGq 6T}fb k+S kuHp]Z30gD ~Rѣ/ %P3i{B;=Eg<~xlwC 10/~ 6vb롗IRkĘzC>#De\32煏)\)'i'C#riz@bG99&wT)e0 g-=֦+٪!JJԏ,ת՟Ik Dzpt:Y+a>2PA?p^o@嵇U>9D"E׏1.U2YwpVqNS ]\1ڏ . m:ϊga! s)6|zg-jvP503]b?}j#o;eG1DO{8)pp1ebDC#Mw/bq9sΛzZ"x"8Ab Qlێ6@$_x/EM.-YB0&@Ln{yKeDoͻj߶ ނrްRhQ;)7MڭP7z2sİ\آ2pvV LG1Zk|ӎRwx~PuYᥔB Uۀb2ʉ٪QvҶ: .8 ˧Bl<=Mꖭ˻=!x~*kDz /X-܌\RƤ)lF❪}칌vG $T?"疅;6p]ܥX7Un#j[@yGkoxh+zrp&yQyrf[B.38~cE%Jeێ jnSlH28׉Pnϯ_p<.sKzO_ۓ:d&g9)=ff,*Go&e >"A0 m!%~}HMqC/?gx8^uY x~m` F1MmƺV* Xޅ[%p+wA.FЩɮ(jreE!烢Յg,M[L0: Ey=v8xDpl5T{cQ~d/]b3Y׉}< $? 8F 0\y˖#M=;<\ssmO0Rz 蓹!ml%i:Ŷ?0h1ǵfXө W_FQ<X]I 3i!ygfEW_~-BZgSEג3oZKa; 3M@w{lȨR<erl$$SU.VO$cAol#)7bK9긡؈)!8\N<~Ӳ5bEg|s{ZLRN<N {h#fd=QLsI߽Gfٷ݊7o c{{YNSy}ԝ W<bhq…ɰdTrY! gMz)6$F*)۞ *(kP 5IVTK2'u3?ۀn(c`f'iJG˒I3<91/V NFA::gx}Uq9\Tk,*{N \rvڋDΓEC o@ Y(ޱZ7֩h>BOdtNZmw)*iGmoԐ?//:D޳]*r:P|QYSK`cʔ-Nٽ9Eܾx#`):3z7=[SI%Θ@iV>ikt;bu~(?}|P۝}4 ;eӎ6c3jdXw5"DAj r\ @?ZV}tldž]x5 V,Ǣ W*sT;lK~)Eӻ5FS7i겵ʈ%jצ9?U~s;/O%x9̩'s֩a(3Ԉ oaR%hS OF6Qk @.{ub܆ڮqL2# ȏ2Z9Q?V0W[ t"~0=o}#Nbh/[C(uJ{7#!xhsTDPG*/wx1f'ߜ=Xݙ&a\('EŴӎ12Go;rS2^1I[O,S:j9Ą"J=Ze˾CO0__ a S)8 -M{jCPs(&&X;gmO!Bs& 7c%or/߉_LDqD>و88Ox<C 6z0`76>eyVĬ9<>AS"ez +NZsq Ō=۵⭰e ˠD O>yA )4lǎ9LLISplSTb|V/Rlb1zlہi9'Ms{/:!%q8}BCI=0uȓHPr4op|ΐ@_Q;YD/*SOj2\DD9m)!5'j:þQzBy縹8R׼k+zNOO3 R _OD8 fsLO_h梳THd8)DZVbL'q1Ise4{.QKq}ϒFYϒ7e4E@}rPʁ9Ig~~"4ʮ9z։?3Ԕ-"m;tr|4 kq?'HGfAB*s0-!U o*^Hp3i zbd[OCu"LXdު9iTMe[AΛ͵ǁ9֧!I94Cu:k'0G'!И ـ%m^'ڰvo{Ջm+Gaam>ک~-'ĭ($O*HPZohV&<C G'tr[H4~h@3WȌa\m!Y{<ĸ_r:3CNR<9|bnZݔ1Q$t}>O"S !$Ct35"e^͛9;Q'=(c!b07f0ɥ uUmdxSa!LJ&Q a㢬BbFz>j7a[Gr*7Ăz&:AjC LKQ.]'^ <30qo]-ft^C)D`J"hn֎k>?wcX`' /A;1,7b=x[\\x1g9> q>@'t: N!ASQ('zeĔY3) ᩁҥzH!Qn{DQAG=IH1ʂ缫5J Ԥs( kH~ցbu>19H31y}܄%ʹj~A?H>D;h}qgG$R=fǖ6\ݑbrܡÔYN3}5??C 90@uex=]:|oEh"Z:vV%tv@{QڅR*bxhzarbԂfY:&Ѱo;j0IIFPZm)dZ#z(D1Gݻ4CٽXr U2M&-a1U\UyLհS-4U-7AsaFϰESHAuÜ j+Dd8g>sFy`Lol!XSJEm1g-I&>9zlTd̘6x`tű\l #"trń7׉#(!Dﯓ&4w *ĖQ7T?ɮFC 3/˛HFC.bAIA- OV#=LN(T*1{'Pw hbw'){X*OI66>pޘ']Tyg1sLzp_RI1$R07=C;F‹!PcLB*78(s[!DZZAh _r{ 1Р蓿Rq M([";#,wm`UMT!@`&nj`O\/07 -XWcDC-acs݈p0a o$Ӛvq-zs|*bv8`I@Cjt@?VQ5Ud0uEs%n l/'2Sċ+) 䖂Ycc&[ ndj`@|h}wU?r8צ i2&4+8[<{;.bv1tZ'ixSd;%Csgt 02GS6Q+BX]n̉=mQԉ [ʸzE綣 "ć0kC#XtcL|4)#6Y1q|2xB5˅^xwǶ#x g=S#݂ MTMXzAl LKZw0: YSF8ab||bL6.3 O􌏉謖/1x|ajE3IμvS,S:J#(L<ĒbDB.ZH<9&(?7D3EtSPˉVG Bux<ٓ $*N qGo}rzGTNSU;zmЁS2@dޕ=.\&>!@J)g:C7f81x=ݘB D,|Gy w-6t fZG’HjLsCP]̫oш>}!eC6'f<yf_ N2G kœ S{N,7A#-bL%Uۊd*#xw@޾0F%jC( Mg?sPJTّcfZ&[V9m q{>q<qn *?,ɣ 2^|)R"b{4cwD"$!o!HӞpac` ~ C >xND6GɈ iJS4)mpQ0k^4"AJ90WMi:эo&Z*!k^:zjS~! O? ұaxa |Ax _zC1H:m-q!U[ 3J `UX΂h)! ј$ é]@pS>'GǏM˅ iTQx z#2hXv[jqG6oT}<etaieR`}r8biGO)rQ?W8_d%Ջ8߆^biKSR,TtsCMmkH0,uװ~d~ywTO{#g5ʶF% A=힍LUd~XyˌW0։[(FZ8oBtqhr1āxyIX u{#L۸%xOw9~}a~,MCm!f&~ux/FLP(ۨ:ѐbU \T1ZNpl._j' fIsb/|__x^HdžXj،vݓKGpg\A=go\JsKjܫQb7?sNr)|naDl@5g+[a@Ӱ6ª0B) \DZ={)kgb̉Y |JѧjU"tLr2'#VM(!SeBZZ_3vz,v| w4 r";"NPK䉵n B&6w߿KmFF 'gcP{ '!}ĪJ6fHܽ+YX5&p<8_ѓs.7tTla>?r)B4ch0l Ukd.@0*X}g'3ӍQF뛢;IsLqQ[_n:Y0OU^Dyڶ$^6O- bdBĖ=)3"#x>Pާ]=b,-_[ [Fi -)s}ŃA}9mB>sX\=ud u} *p] ȏ`7\md \  Jr񠀆2Y`ہV_Fs'38ٞAؿL3\L}6ѧzo8z;nW Xhr tCaǫ9XJvX"OĪln&O|!{ĺdmp-8=V:!!np'hfҭGH ^p^LT1jIsZK$) nzgkeH-2SS-(YT n{55%e+)`o\J/[I6o|x\uzqٚ3 P+X$d+siCf>{cC3f9įւǠ"9oJb>ٟʅV@mϡN(`rp,ɉmy *| G 2yVLm -P62椬{t{B3J(.`TN@D/g2Ly**ցZ,mTC z9&VP 'j-+7}Cm)sX@LobN3[Z;91PWiɨY) gzYfUXjڅ'l2Z&^ gi9k!sPVv8 VRP1.8e"q[CS>B g<ͻo b@yh'_"b551%k C԰f+Dhbn9|7n.s ƤH+.l1ǔ[ m{b7uˍo گǶU.YGF7/Zo"oO7'œ~d1Ja3z<o (9 _(eP1.:HCX3>?/ZG؂9l@pDN|\|}+^QxuJT6P*:̤ sOJRD0 Aڶe Qi u&B0Zǯ_9Qoh yA\7٧ذoe['m0@ 5tBx~bFxx0cX3̹Ú9U~뷌A}ii" )1)<@BkE?`gsen% Y'mFi`GLNkÆB n 3͋):g _8ufVbA|hd0&~\X,e=K8xlv NCtX v#Fcwz*G^&c ,* kpAWCrxJ.Ft@XjeQ6Z2dq ۈX{CJjRy ԝ&F`X)`,mzQg<íbBzBAo !;^Xܷ> iUPKi_~Dj;1g(ӐD9 ߠya\+0(|xB/;ufh4Qp 8|$\7Ҿ+&&wr޻~r-7!4FvZx:0d}~!& h3䉪 o19,!A ŀyA8Pvxduq1psvWyYe4JV~kPa͌ڕ#MlMmǎ'Df!-*ƊNiC^OJl mg"Yyg6J4(!zoޠ&y:0']T_wOsO\oy@Qʅ6x'2q?Cib*c/~l2_:2P0fʪͻO1D+׍'F}d׋ilf^%%` 8XKFӂoGمr]p#$ɊNo5{C6K1ƚ*ol (7~Z^{Z۟6~0 m$_יaR L"ޯ7:  tgq/F>yls4rIzJd!@cB-d6a1v<poiGkuH .'ֈVaY~q??3::Z)75/M9W{MSaĶgaxZc⪅ 3-JC}G7/=rO ݔ{77׽;a,&'d(,AkyV0zn)yd9S>0&CN朄y~0¿\@-li9:_I)5PBFoP9rVbIL^ !D+[&]˛7g,PēF,V8>5Ɲ1,#a`4ByRJ {Y9ǜ>@?Ęu11Gvld>Pɂ;BD_'\;ONd;ŀ? J:2"Rʘa?# OK(E|>gd@ןR n~u[b_Z#9O>)W\͑S"׸|pPM6PYtx`ja~_&Bon?͘T1S;t ^d lo(1 9Zkge>^K3o2q}XZYi [Zvf(P{ xLL9$oTӡ_lK9o:s'̍QV s[#"}h`':v\Fpjٻ)(UQ5yWqHCc~R kGW %7;W R^jx?SL9l )uW}*gs`h'q}ȓLݎ*Lp>Y\']k7R!DNXw#c3Qk)-e%L=~]r1D NQ:&5s굢jÁVEDWW"& ۤ5& \xW:(d+{  5aɁAIyS"btp+@Dw=a6rF}FEmҭs4&-d&9ANhsc3V4Jr󶣗ˆ͋L^m~[nU%앢齁sL K3w>Fﭟr })pN qTً%?2)6pj!i{S}êNypL4;~8YC-fXy% e8/@fa@`ݼ߽MB@"ɂ!YDK&u9v؜sa@܍?RaKΗb۞2LWB$q=4bsPڻIYLtǓFa+)ȁ=h̓L[J +-oc"l q9cB <Y"RN@x}!Ρ?n–77pYx:Xxy`jC w q# ݻD#Ƭ\`M䔱:Ϯ'nf8؇p!?ˑ(en댴혓S/ģ sN:`5)" ^'10$y2R?5O Oc? k`a=sB#d% @ h'E.<~*b:{7oQfTyu2MA9cFa\l"@}wEN-_πz]p13ry߹ ZNFoaq'?|`$O&?h ֔ޢ)7Ki*~PČZJXQz>!k2-}r֋\mSF 9čv +/&<h_r d}D|[~dD H3EnF)%uY< ;̈́>9Q"-iec&UDpgL3V0$[wR@G΄R1=:Z& p]UOļ\'󢵠8&D8 lHX [ч堔&>f͵Y =JW9IUj DjT oY$yG4ֺRJx a ꖣ:n!{|;xmX<щ# DGd?r"z-M&"ZĴPak]֢c}BO<,qQwSPZ1O)> :\xia5'_Ynh0A2PbLml5r99ù >)`>۾c2C1 \J`fnyÒt 3h$ ֙Q[1AT̀yhi|.bEٰ0y! k1+m,t Ķ3cm"}~?.8֓{)Dx-0')>ol qŘ89 w0?a)x~=TLjw+@dbg 2%V+!l4n<( .Dy5H_<by.8CJP!p] Ol9%ld#V.xq<ؙ"XTxXQPr3$(mg L+p,LuKovu5&z\PڙC( Yj@鼃Asfks*|"fc5xOĔI:L!oUR"<lَ0&f+HEZws\Um}9vB]r T(iM.̡׬`u43s!*YXCǽ8nRNl٥t`6-asx;y\J/EK"_o_ G<;-+cq{ta[J^Hv;jNY8[K v/Az/ ۃ⟍G͛V0|4̡2!Sj1N.j’5еyO %֣Zd= c\WAN)$^/#g7,sg2 S 6s"Zgvf6;ٌv΁F3k5<"a~,ܺ g3u+JDXXhākԙ@ VMcւ}{CTQʉQ+԰+)me9u;\zQ;zW䍩1x<X lq_7DSLvu|t"uڽG1DQBߏ/-eVİ3KD]hb1;rJJ1n#DPQ0fG 3Qkh H .І'43e,S裚rP f\z#䔸ӎe<Ѩ_KA'5۳cFv/vSVWJIHfaOt[@Q6 W? zZ@h epqN8~Y}7*8(ynCivl,݆cBtb<>Oq:F61 L2\RKpid"ro*T3̞X_6 {Zl8h&*1E:$aClb-j [okKt,pEY&ny$ ŖQ1ec2I> E>-g}9 3017*bR P(T >zgndCVIXPʕD_@mjbEa:~[NrSb["G^V3ffq&&(b ugoYѐ9'֮0~Ϳӹ>UT-[7OEQ-IO`ᘊٚi⹣ 2$o갓GGU/ÖiZ.N0" pŜaʹnǁZ8P[%Q;}/6(ޟM+G["Zru ՎXA큫]!~8_-Ʈ;Ͱ# _nq1: O5|xLDZbFy_x,lh&zh&Q? q F-#`\au^徿<-=AG} Ueq8kFG|I2}Y20~}ͩCM8LI®NNfv@4Es\0 w؏T;1SVp R by7h ɾ|81gcPTܝqObw$Ng۩y|4Z6~<KHGoYļCL tӛ%Zm;|-#wSA)dDQvF}r&7;׀ .a4̆ ,N:vI|M##CAf<c˝c߱0 ^9KBLSD4;c|7!PUa7R0g9c Y*B'Bmo u~6v+~ VƲLRFCy&g5R q%]i2m$wk}-/'#J\4q`QBs 3>宥q}fbF >I9I`7|#N.o;z7|#驛Z)L:Yɖr!3|SEz»<ѭU\ C3=8PGu;@6)`K}1Ĥ>8; ?ת wN}HR39SjSA6U|'Qv`T!y5/!z6@)pZ/s'2uҝnLŇRzk* Fcv(<[ʖRpıl'>alXQ/v<{ӂ{`iW.FsxҡP:šT3P "sqQkw@b 393F^(sφrRDn,Mffw.wU-M( DutyӮVTϢ|̃^gtr#TdC3Pj(Oν(@Gp: a'W`Xz~g?["amZD2(]vvIDAT@U FgK*ZO ,|mlx>-49sn2QO^6xv8RnMNn;g,gp߈9w)b|^od^z#1x{BTAᓱuz:'*FVom? kCnBq䃾-u$m:E$=pq a:! č[l+>OWPё6|D̢gGZ+TJw7RCo*\\>eK=F9\כAQkƙ|bzH©b;8oIv#~,Ę7GW!&jCLP9D8@3ؗlwJGF>3:q! )*c~$({ۍ |+q2s|ÖbL5d(+ tmT]0jmD׏ٺ7Mxb5% e@ =tw0^*~wXi^D@JsX0r@Ҷ:C Uo8>R{C-F+8Ъtx[a`5lyQ?[ׯ? (Zu͐졻OF]e.2<9Y*Okl {- 70CD S: )$zџdI} 9=x_\`'rwz"f Z.1"jPҚ{yE`Kt];ۖZ~< Ucߙz/>"wԇH)sm\Ė6 BBK΄l;yc'҄<)[w>}ɉvJD__x;*IRSFJ6d+)d8pVn_-LTߐo—blI7=EOVJ^dg1ۍX=lCJ ZQ[Sb>\*>R}@r` ru6h\X jeP_'GpO| p[EѮj mpp^oW vߋͪW_GrjULK^X؟M{?JŪS [\ 8ú;;f@3O0.J@ xJDX>c;}2+Z mtfa\2uTS[ݱ9}f???]-֬Ǘ b;Nx>pvAȏtT?yAP\L@B ne"٪UԜ<5z.Q|<{G:Q8l}oļFm#C'g4/yOî0|RBnxVga&^v8X`-7\ dZΧr(Rb9ΊG.^w-f6ѯnѓƔ80ec}dO} hI4ųw!{GKt-Z7QA1զ9Rt5L;\%{x.ap++|]&912~.O,%x9'hӤ9;auӢh yoo K$+BpwUIIsRB3㬅& JLxO#oBr \iRjVSm >8bLJ>_˄N@$y>KzÝSt4W ;mƫ4<:Q {R Rθe>-n* 7=RHx_x<J7@'+{;ymCrm&Fw7vdl xocVN1A"~W1֓1dLW#߭1o( 0"rP{E> 茵 ,ý>9ǖL40Z}۠cΓ iO9s<9&Ŷ*rȀg8~2=myz]^adF;pjq>~=9P9/>ScLΑ_ሃ. :1g3^i"H LDŽ%ÎgvDq]oǃnHu=>숪ި=^K.qFݓv=Qk1eb@ )]HܺE2& mK~lϰHlsYLӢX'9.GE ˽Jq<^h_/ZL!{$67R+ꉁV+zi@|Lq}|)55h`]p2jl+MTp=g([LpIЮ>Ŗz֙lj-=ULϏ\hћd֦ jIu/V?@7 ?=x6gZIsUq޵6rZcy~R?i S246_GUo識CwV.|'[L`U*b r!^\Rh&mbHҡCm,!Gq5'v_>nBSӘgpx,SEkp%L7d.=T;q+7..2`k_g}^8>1D6;MSwW@Dp?a#mCD}bGl)gC_ry!];) RPQ}䠟gsX:~1^zmsZ6.Vj[1ѨN?w}j[Ygc>Xe Rz5[v8LV8[Az{H}ИZ!p'@p>n"a,XduC@N1LlgKeNb@Ap_ʉhoNx DNa Tnl-)'b 9oV:,NpkJJw;_/: {I6{⌠ F9Φ~m s~ j-S>6笂Ҹ"o[F)s8"Ā)Ji_޴AIZ/٩Sx!ZM ٭N1ZS:&!dƌ-ol 1o[7r9)e@y'`<.*hD> :fRV@FY*q֊q}"N@'u 13$C`jɽK_jǾ34 ့0ՁY_x %D!97V7兔v#(g@.P5ǎ";[BhLDAv*yռO+h}e>DZKV\ώ#n#yṪ#FLBc!Ղvrx1P{8@P3j٥5B gU'[}U~?I}N0?s$ĜߧE]6M0 řRO(11|KMDlc aYO&>g+?R{8/C8>{n \?'℅O*Z3 ؘ|bc!bBr ^,1~`h|_b81$E&z~ XX[z y 8b6vĸӘ87 թ AEik.V;8NP qHZ5] }%4l1⬍Q@A s_tukTZЯѺ ]ϓJcLU$mG5U~2]f;bј]R+D&D|~ 2) L%QݟSJ Pf {+L!eO$L$heFCPTMCYǾÞW(Ѵj"g)ќɧőp`Z[P[:uaciUw'MU0Ssj:kMÒc%kx}P<<'-Ä1ќ(#>;f "#}A.cL?KVLab61SVONg9 )qpo-kG &:rwlp,u?9?߃U*;Y]D|Dl#M?xy'7ws|V;bx'('SU7}qv|"@ 0|avu ^olxǤv?P 4X10qdV!ulPni\H`7 D lÆ- %GM`37cP<)#_g6 ,;4qOjC2wĸ'rޣuNϳm۠CMa-9Olq*;ΜgۆzgHrDp <7@)f灙1F` x'jt'i¡Tx' &St;7|P)e~eGNl v(bRژ bϳfO,e;٨$d8L!A5x+ݼ BBD-bEՐ64)zڑROՀw\S\[*qBJVo(VmvD)$P\'g)^ 17ψXtoޟBjc{B8ץ9&ijAIo[j`gFS6HW>E1?w7r#?/Ϻr-MF%9AJU0G7Ѱ ?lC! NzafCH)QOI ;[QQEmrGGl*HGe .1Gabj"wbp {ØTBk`^TƐj_ǓC:XbT,sd-kzO_'䧔y}ֆU,febFgB$23ZXH&Bl`/@XDZ9k8m' Yz~}?w?j[v9wn\ )N3v!ouݍ!!'f[ZW.Ў3C1N{ֱޯ[O?ћb_bV `kA'ydgVx]x[yB}0(4==)X[b>nL%pgΜ;93'm4IENDB`Carla-2.1/resources/bitmaps/background_nekobi.png000066400000000000000000000003251364475620200222340ustar00rootroot00000000000000PNG  IHDRlYQ>'PLTEjjj))))((*))***+++((('''(''&&&%%%###U*F pHYs  TIDATc``@   @ Q$0u T$ P0Kn~`\  9 ,dn`8 a0IENDB`Carla-2.1/resources/bitmaps/background_nekobi_left.png000066400000000000000000000233121364475620200232470ustar00rootroot00000000000000PNG  IHDR9l& 53PLTE\\\hhhiiijjjkjjkkklllmmmnnnooonmnomnononmm;;;((()))'''***+++,,,---.../..///0001110/00./1001/00//101&&&/.//-.(''-,-,+,-,,)((,*+.,--+,*)).--+**,++1./0..0-.<;;<<<.///0/.0/:::%%%999'&&:99&%%%$$$$$888###988877777$##655#""666"""!!!f  pHYs  %}IDATxڭ]v$q-ɒbG@!Kڤ%vbM8#95* 99==n׻ In??S(6=ڶOt'}ɧ?|h}s}jT}|*u?3}租}g?V^j?O>tdQ}1 8 Оy۶6s6XҲiY8??/ykuWvd|ݵ݊!Z=s^\.._]^~uyzF{qaʁ~{X\ȿtmeٓNScQ6y 4@~CP6jHd;%6!YӺhgڵ:vPUz-rnmk==Y +뗕"zu+o>M.B: e APkalG!7fckJsìdNqm{]RwyնJ{n ikXyCmGP|כ]Y}Z_ov֣Uq[1r#}R6Zh) \/64(7=V,Jw,j0# *i + 8(4nu9EGD7ow rٓU*ڟBL@/qɈ,RIFncE*[w AAKe/AG2._6~U:DA mW v9򯁽*<۷o..( kVv(*h"%W,Ug_kmx7 F"GmAf=<R^ʦ5r˦=lSft!Wov4]]x{ [U֢M/n 0a.j&=no0+"do2AMVG2*STlzu ZmYW˯jeӝ :HicT4r Jiw]mmn6r~u-9K3[ b5XE*W#UEzحoވ`#qQw/W_ꦑ<]OPkVkE/&D*j7|}ƖȤK7*x (9g(E%vwmH+AHҨpQTFQ@z{/|+7k]U.JK;B.PʚK **%\Rm0L}hmyxhV,KPETBlrHhQacBV+IkAڊkysU]ko!AoEkJ vE,2yQ<8mح{nZU^̈́Q8XiۄVʹRuXmLbahXEpR +klq ^hWwCaT > _D#Ju@9 ܠlh8SU['O!DgAw4t]Sjj^c5"H'~ؑ~U}>a G/n&n$Fr;*E͛@ADHf3@ֺ{Q QJ /uwZ鵹^}2m+KLW. Ȩ I"mZpdlQ?IcD 𙏟M%._;J @0xvkpꑅQCvq*h \ܓ@"B"f=LS\}0\4XI34={|J{9--$@I'(h:qbV{A+&k$a; q.rBlkPH,69{%fOwٍZwN +FK2o-4FuW]n rs7tЙ 0*#:w7|C^oY? /?7ҖH !ңL$oqo~&ۘۦӡ=JiN:XOLO;+=7"$&#fi1.n9l+oZa9V<;*g =1Y01-j [DNYJG Hs28/Ĭ*XjZP;ii-my N{!J t4]+ m_YS<`[ҡZA;Ur{7"#A:K]/6Bg ~;_Fxs󿳐:I}X8nD4$H88>}PAξm!Vs۪q$4}<"պqpΚaGr $,r#tKA$#n+qҫB8T˾PxAօBƤY ENsҤiDN23_ۨ1E3Lc1cd%ŎwM 0bY"FL2s&xOP#GJn^ ~3Z p:M :K_4R$."+jd* $xD"Iβ(dRl{J6lGE`B T #5k`!'n%\n5j^TCh6 |9Tmo H03!93p:JlΫ-LX-$GlkGOjHFdSm{xk T0ON8Ep {!|K@Ni(+}5>\w\*:u]ks^Yrs"WAAT䘹7%}:Cq(`fDeok4q\=D !U{nl3Iԓᗺq^=bMlhZ?_h@wV^B[7X+f <`DxP -Q !7X.o v=}y8b:3U<)lHΜBNu\1bT&/yCw BF(VT;(P.0R!n*cj]@ս24_z!t2['q~Hiz5@3Ii8EXWzPqE\5.amETWT6n D8ô",ԉAu „=.G@I!: Bxh)an;Ep$J ֎fmFq3re:Mj'̑d"ML|֑.~CðE6 P~q,fcY/V % Jz*:ENۑ`,bМU8sšrr[nͱ^@CIț"GR$<+1XDar)Ķ@v`2vD6ͬ H |aa{dz5>wKMN v79zkli%[̖0v[RNɉKoyeND>F|/ N>Ich2A[9[+[#sL̉[i|3kF?̢}}􁣎u{0둨<TE Z=A~NMӠkWEi`%sp# w]% G%bG0;RVqAq&]uaCyC!5Ql6q{qN)SNlfa00pB 8 OOO<=&L2 ifs I}" )w Fs>cCTѡ84O'8Fx-PAxj2iH~7ri90%Dy g6 h RFqJrQ ƭ}afK\OmdY ؜af)M# Tuc 7QR/2Ejm4#>f1Z;%pр5SgNꩳ}=C$~AgWsP^B"[\FۣdX*hGe+ 1xe=de Rǜ48 /2xY]OuFhg$mT݂(ګb!* b/&~vOf7rvoQc~+Ia+ \^Lj'{17" S餎tQ Z{Lʱ:7Yl[DK5z4Ĩ$O[/[D. P1`@@!F(qYm0;Lz'@s0LYj:nIOC~ {>c<|57\5*d /p]vRN>um\+ \ÄӳP%%rڄ:Q;aD `۬ +M7hjnfjGS50b>JCtrF F!wkA7(;Fh=yBd Sr!7x3l1$렦9 ԛ,lQ;wP7oγDy|aipe=ay0G ]^kB?%G-88Ek<gb~R|#mgoE>ۺV\ @BCQѶ+6)&7f4TtC)82T3{dA9mTLP*&z 2&1r x?6OCؙ{|? & 'D9%=c]ς1wwUyGS&C-Z'\ uX]QN=67PP@4,9g raݙJ#!7 F ?E ?I *aGsC(0 G{/H Y{;ܣyj'flGfB7XՁ3syb?`5ogojKi8]m-XWDw wȳd{|Cy$ñYTd&0z k6RMOv:}o7^Ґ?66݊lOOqrM0y駧[d'*xO$yH4Y.y^IysO^JɳځV`7>{P% X83}_6}m?|=Xx_Xۑ}~DBhirIENDB`Carla-2.1/resources/bitmaps/background_nekobi_right.png000066400000000000000000000203001364475620200234240ustar00rootroot00000000000000PNG  IHDRl`PLTEjjjiiihhhgggfffeeedddccccbbbbbaaa```___^^^]]]\\\[[[ZZZZYYYYYXXX)))(((***'''&&&%%%$$$####"""""!!! 777$##999%$$:::&%%'&&('')((;::*));;;+++ +**! "!!<<<<;;:99666  pHYs  RIDATxڍ]uَcGV%7v7F3!-y ERb#UwUn|w='|I O~Ÿ_/'___?8>&~VοO?wǞg|p>l>3.g_缪*ԥӄ6 ڮ{]߻w/0 ?,\j4Mkll'¹@Ht<2:?: P n З5Ͼ aa=Y3 hLl":,?6$:541ͥ"s;//6S/&a ul00 N<с3^͠٠PAX&N茈MދV<<_\hN. 'c<cz^h:Јj1Jԉ4 xV'UGП?yq9/LOL5?lv|&,x xy22lvѧ4Ft{&~0cgsz|mzL<ov6Ts8gKل%o&~rr(vcA04֩(BORzq!8+,_-^"עrAhÃ~Uv:E!OzN^~6yN,Nl.SY'N,ra /fߎ/TZ$4<9ˣ#QK+:ɖZ[TqC|:Z邛LZdEUag#Us9d|^n)^"hVS)B3>)vGs<<; { sl'IWO;şc0gje UlvZ'FCsĨFC`fG*6U;mXt">=!|i]z*$s|pӶh~kH((1q'f*'.B!sIԓ6-4·p8%57*![R}V;1,oy']hF* z0*0"НkQV=QK²PNa FG򪀌Փ5\ѲҖ_AGTNlA923A%؈f1ܐg+a. 1.юk Dk'wن9K (W+Q/:3c r!⻖V 7sV&L>зІB7[ ]l'2f5pxQ79 ‘{Q.b`ܳ#=K^qpnsF8B.\xB^nLG2λwq^DliTu1&+Qf"PӡP0}ёrrWΎ)H!l,:3nDr1 ooo㇟P{-c>9մ(:;3t޿y<tN7W3E2*V[nEWhDu/zL+G4c31HTǢ]QhH!(*@t* < *ihlEa(P*t Fʣ z֜bVԵWRnd|^yw5ql(DB#­4Jt*ɠFYwV8KN͌x=r^"8k3_t:J<y50ϵX4O GqjH =6{m'YbNR{te!"uꍉ2u3.!E {uEg*e!2hpy-1O0#dBQ46(:Уׅ;I~d; (z#U9+1v$P zXruv/ ֽ&'ZK`BG TyzX`]7WVHB2wJ]QRB'~[˹WV JG ;SDۋ07D͌$\aabJWn|qE2h"-vN"Ē?J껲_2˧׷%Q`2րiV\jMT(- 7iUh˴4&$iAI5Fr$fĽS,w8W c<,(S칹?dVk*ea'ƓU!LC?Vy,Hc5l2Թ4xrB .oM4]P7Kb?V&|,:KӹTuSpH\#kJr#AcL z3 3Fp`= GScY+q,un,Nԕu'rL_0[pPԀ6"zJ&eF <70BǺPe8@]kJ"TbJ i\+O߁L'eC f-°ImYM5ҧ:BE}bHⵤߓ a{Nlplc Bu z-rI!{S4Et j xt[faXxtD"cldz)[S딋dk?qEc-[JPm"ږ\`CS!"=M(md!EAs:Zen I<[17X2vr/6\(@W96cxU d dwGkgTIahر,σ,B$Zҕڍd-lV B1lsXR>9:8J:,&:Tm4 :i.=:5Q'[.dM''+-:],n2JATE̔)٩;1#:+Z (oG]i2*YznzlAinM:d,rԔ_̈e2Mp-Q7ᦇh/3tMF"PEIDXocaӈT#xwu[ NkK_ _l=YFRAkdZ.=, %Վ? :0tFb>.p/c<$9@B^*g9K*]UUv!kqv/uc*sDjd 輏9V_љGzc@c* EBnLSt+N~ƥT(3:(-e&ŗau)^U+1vm3RAv[tTKDng+sCRx_rN]qj b& awCǑQ:O; s Vp62:өV>,ȃ P㑩gŖSխ0^b6uĕC(48aY.L{Y Vp"0఼+d;!t$A`3EΔ5p:Oإ(m&% v^X..l}ALʚ ת":PܙrUml^cFwhV3AٶF <c hnćA_YO& :Z+'#AcA۹khe;+3HRq iMiBߘtRFg931YYVSE!GիW#KvX:N{qN:;*:1UdATUl f SIa)oKyJv"Se7 rwp%L2:dAxW^C t}e+\Ʀ-.|ʽ62>nd§3%+\rf97vdɠ45'(v|Zˡ5MّE; ڵ#BS O?uVN+Z$ݬJIu[eMSf;h9״ov` ZYqgîEW&fIXȘv ه_6ay|TcF|NJ*Ų',Ƚ,X.EL]mqiaE[69\\6"3qh1nkF),& lDAl>7}B6 鍣gng-Et|c-7y^k:߁p[rJ&E} gl1?:Id;:F08}\E\#:JQ\/.vmmByY;^jv\Qљ"7_6Zb/|$얩u[Y7Mb %E=[X P+|va5գ ]!LuHYUnx݄V]:Q?oiZ3ƌdGh g4g2SFCc%(aSUp/gsF*F7iIU@nj嶈bƥp+.f>eKANj]F f^s;.`=ot[86S~pKn&2@1c=Y +x#|pj2dt 3`"EO* ЕJ:yLaBnҎVBtPXה1_KI=uRUM8{\cSf@)?I:ru9K ,G9qcDp\9ffeNoaf]`2Ed0dc[NwemiW6X>iTΗ'.Jg*ҢqC)_bʓy& 睍$qQ軆l!̓ČKNBoy{Ӣ9:N:?舂4m:{m7i|?H6^<[A'?1&A_}jيh]@;v3Ńlkt*LpRWn:ғX@S"+j%dBrl$Vl>UoM)uJB ䷟%dUXt* 'kQ^c8[|epL#n<S8k^+`45&z%Gx[M;Sљv59xWNw噟NRrU} WۡHHRDF,8, K@^(Iai,8UX|h#nȒqf4".$p)\j/swb=^i~;3%D+%&+:]{sڜH]z;q ~ ĔW9.9{t_J[ŕkSt03~ү c Hb_.ꥀ4l}3m]keI gdɆG^\ K o3R\0,"~kd o~1>;??'<ǟ7}{-~:?Q<~{85)LjvIENDB`Carla-2.1/resources/bitmaps/background_noise1.png000066400000000000000000004560401364475620200221740ustar00rootroot00000000000000PNG  IHDR^qq pHYs  IDATxl$In)Gּ\Lt7p)/ӝnf:3SʈwE DMҦS^kӭC]Z%In]j55jV?mZ%ݺjխMC.Mu5 IK]MN_;54kԮ[ChաKNI6$]j}vMI&ijjzSӥEM]nMM5s?v-%5 ]jZtI:MuiQ}v:4uzV+]~n%uZ4KM]jZtuw]%Z4tk[_]ut$uISg}VϕNtuS7h)iXoWiԥϜ]} M]t./uIu [MSnjhꭡESM][5}{56\񛛦n-EMMݫ.MMC\;NMSSWȝ1ES4.n. _44uiѢ{9ĦյkcyDX5|SoxK"?XЭ%ԡ53lRe&z\YWץKo4é᫔O}MlKӛia+jqPn[NmZ4t?fOv6)|҈P545Lsa?ysj嫌o3nME?+j.-|d4oBZti׼IßDŽ|rVo6Nftiѡuj7[gȝ\S1մԪMo㫦UWp5mBxx^޻u j<8Cyk]Lo쮩]w6#/M)pxQINm^^UnZo7l'#~vkjեEVjjա3?}i Pp~7DBA-wgͳhtX/s;LM4tDtzۏ\2O)N2!gnҡ~om^CҭU9卿n7KȿѼ k^ޒKV0s(#NۛH>}Xu{^Sgz7M&7O@y_Afꙻ[3S/(B3#~+嫿%ti73XO!x{©.i66'"&#UVoPӽN`-_|\[#BEz2)9Jb;_^,o^{!Cqfr:f{nx 3CԢ#gjW=s4-Z -&~r24p!mjJq{l- ͒I>t8D[3~\KWPu)Œ].vn?W}!BբyYl8""/>:L&Z5C`8tq޴hQGlu~ Ww29%Fl!3C%ǚ[*gn*g&6jשUM3\\ioO_)5Tǥ3}jI -t9Z=76/km:*j])5֞uy9(s ɕxhI{CF{:NǢ64:y7ÙFG yu2pmIОrȺ$79"k#(7i<&2+#Xƻg_~N-м2 Z6}]b,+:7,8wp)^z}ܒZ̪Dyҽb ^(UK7WxrË2bּUOˊE]ZYeG_N]_AnqxFݝZ𺡯GgoyQ6?@jj/g'nK*:]ҡ'FϽjZ\LC\By~ztBtzӮzˀd7v鐺SiNM]|ቼRע]G)c8@0/j̦/Ytf@gym_.xݙHȹj6C{8Q 3;wq/,J10*2/b:Q T]_P\ Oo?9ot:@9xF!]2oS_pX}]^Z4|sh\Wv?(sUm@IΣZjqx't֯`v`]d[-'jZ.E/_ǥoavuѥ3f5l IH^M"Yd g ^Pe{nu9!5`3E_}^$ҥW0\E=Tu%Zu4Zuqg[si ~$,Vg)WgVF[sKv~6S4hO- zHPS7Q"meUdtUKG*-xvzfH"olpF Z&6bxRn=s)`ux`47.W}3/}W_U+a^P꼜jR_C:p`#ͼ qӫϽ%O"r|."d$IדjY2ӢJ/w Du"֩L߈uzu-rlG31I m!4='siuvJ[M@Л(`@ n=/-z=jo:ȁ[`dE7/p3-)@&08WU&g3'Apx4z؂p@ 6Vwצ=Ouu~ׁ-8Y#pNO1'} MQ6YoPK870QVCݓ[ߨЮ)`E"E>B@N8|5{V]Io'S{[h@˧/8LIV6n@Ph\%Lmvzv߽u;mFFAj;RnES}#|Ju5oK3-telAv7斿7iTEݑk "DGaYEuu8eHSC/h3x?A@F{Tdph#dȦ6(tgeO }~5 qlg2VQmLK~xfgZ;lM[7K nE'ָ#%W)r*JEIK7ZN= Mm` jzkfOu?gu` 2LW4!Xm9AH\7],yCأW7Av[H( 0$7!PdVA {3 [Lˑu7!{_V(` r5%Wަ sV~?o|dxyv,K[ŵ~գ4"`9ʍS^H*6O0xƷ;!SWp"`|FnD><ȗ#ɕ% U %kVhd[2@L}G4z^ߪEB,rgIB;vUTuiGFBw{ g+N_nvNB=W^~ẗڮv}4ut\-DGKAr_˕W26^D'i(&0v7?<Rv$:K0?K2{Fs ^S! 4r VSM9x9]* !%߷~w.Y\W 2RZZs}Ӓt7[-ŵl"@EN[( qXZ;"[>]8Om:Ĉ5gi~5ۿ"dtitU7y8 o;:6/WCGUa& n[gOs֕s76׽I6]:ݍ8\}ݥ(5.pXR\9ϓUGa0c60 .7` @rv<8W!ġE#vķޙ6A̚u@tp6$dtBS*6 enz4VK5NGD@=Cі~5Ћ踜MΦ9oFΖ=b۩WsX#>H q@-H-H|epO/D{3bO:kө6<|<B6g:Th!.W\Ԧa5}gڀ]Ro^y:T_\B,GG>j&R 3!$Eo~\`)ΙGߋѪFF5-D)?zSD$`o*[N`0Au=EE%oE6"q,<7^6I9HBrz[86u.מh ziŷ||bX$ku xh3S:?:d? }1fatǵyv!]I`䟢1 ~%%r^ }Vi7(nОyLp_. xE^ Ly@yhSパLmd9zEMY<+-.`]ζ~f`ùDbl^Ge,zUL5Jm1|HY8 UޖHg/կvD>}X||H.M\ؼkTߺha2jc4UQj5nV`͊i`c.2ͼ"@XX -Y,|K- *A(6A "-Z z τ8OA\:5qȰJ-ӹ[dά]`T%i-mjzc2&ZWO#O'HYC?FjoSgdOh/~~r/;YEq(/oK ά[Ԍf,zUx0dx_MtpTsh~TC50r60ip$ox~Ni"GUа).-)gV ,|`.*yen}3wڽ!O]Я:gp|ڜ g. ^<487\[CM*'KE#ф;M;oؘ-|0[8> 'E!=!Q֦OhOjXA gu'oڶt#V; 9*[0B% g+?MW)VNcCd[Zmx؜D,"ƽ}.:4zTXBl=T |ȓz%WV]t>&$OWd&[ftzzn>:7ok};£oVq  5KMajW癫B*qRw _Va(K8\[$Ũ>0Tp>-A%L? as0:Wѐb 'G*©j6"5Dq$J]l8vѽrT*O:؅ /(S ro {JWl+d0eXEg9؜LQʪaof<\v6B߅1j {Wcq.Znv]2ā_ڬKXnCg6r{!(s#,*G6}؈xSad ‰ ʟ[pTg oXi[&e-?K=KbjNqoz:"EٍRQ̷|vLPJ񗘹.n?-3PG֝Jm4:+J] ϶[>;]_5EhlJ:0b1DW4Ng2T£І) DҸFHfӦ{D{kxsM4NWPqlyWMnK>ټUhd[>qr%~7a/0U AkXQC v)SǑE |h/~#_/y'WҚ!x&įV/hn#2(z RTfUvEuGϨ+}q끠{gD~g>2t?tPg)#V)LOWCׅK}[QZJ",pqh.Ԥ#'6!ۅ: 8?2L|7˒Y l(˨0f|M{'=m|: G݄'& ^P5`u @'zڱLi֭, @X!#,Pc+,o@1I1׽/H| \/uuJ'x~3Hr=h"``A7!ݥ2DDbxr8O!f:86pȻK6saxG@G$<î\ ;u\ޠ݅A%E^doO Ը?4 Fȱ*~Lj R=9a WkS2w B%ΝWJGT$,Uq2>nϭ~ԤV-p,ԣs UBQH.15':pD:r7=64}WXit1|cϺ< [cִfX䨹53B+YG 4AOyE\R, 眪"+v;5<@;a\d\eRnmBLHxu";VƓ7![i': Z̢\3iF {n\&TZPIFPdmۆvsC\̦x 52)6ex#/D$A)$Qq$cQ$|iq'GjPb j~qzEw]L,.dԒ~wԽga$nEuUH9z.Wᗠ х}d6gL^Z Qq X$=M3#٧Ǿ>UdQ9!39 TH.FP}葉#]A:z—aXYJA}zt%hus?XnG rbpBJ<RCpUk3_$V,lzc#/ %NcOSCD qǹ ,-=fK1N5O%cE V+DN#gr/+ GnW2u`ȑF)LY1EG;?B:tWIxJM|H 5z(W nӒk2$UL>Tӿ"P#j⨋iIo qq)l,0bN bu^NH%p#O!Uwa Ņi!j&ؒ˿C L%^, krOL԰B׽"-=J(5Ut*{/0:=<7xPy /Ƈѡ83G#paT#YS5ecJ~`1,[ؖLĘwF1:71҈U3v=0O9-8 B1T*!ɤ!DW@[hDWFBvlE[>߄qA4Ju:z]`:CUx/"~<2L-oU19]O}/݉q#1?9*߾fTyg~f!" WS`{vHdj e)kpf[]`Wgp4NY &YP=:h9KeXIZܜu7Q(啚/Ba00 ~aˆ@l:H G~DeD6ETv!.Lv'i?2R仗[>6xp()Sݐ$w#tpA' {Je=ٻW">Gh[uM5Pt1H OF`v@By:UYQKnsdj/! 'O1(/`hjVzwRM%T7 (GbĂl "SI~.S zZZ:PuA,zp1|ǧ ͩM;Ԅ9q+R='43ܖ HeWY]WPxqZ݄R &+/d-wmDXe j-5;YKi9, )VN^t%DЈv'|dbPظ`͹>A؏Q\)l7e}qaM2w\ތ6r)2ň&|qLq?+'8g# e8wļMLS@_yM0ٕU.1a>Rɓ4 [`\53bO!-ZuT6wW:ԒeWNj،Cn8`ƕ[2"2.<BqU 35*ta*⴨H{eo,럃 {JQ? T f*\TP/.K۱㌠G'KO$SO W#oK_˱WޝO^*\xL$_*w մϺ?H" yTʺtQ5.BaЖ>I.}Tlr^I+Xd_zى4A*,ffQy8+L< B,SpuޖIIJ@,QSH}Z{-cYӥ̍R7ɲcoɐ.Ś&yP#۽>&57LBjZ5XNŋ hȨx @ȋ#D U/5=5 3Fnjӝ z- [i#\q_q w)ZMCDS@-Nձ6Qx*BetÇNt\f6+' ]&% Ve!ӉcВrX*+|}}"cwBIZ.E!LWY[?BI.9)bfa)r`1|Ɏ)9p XZĉ9iy]d< a?Z)hEnpdz˞)8"SVIGn7qs#@>N\`NdHTH6"v8q:}A d7  ` fޘ p~ \@H I 8u-mq\U 3D@q,r{brR\A *}Șs`&" !g1*zo73iIr-N7ɑ3[kFN Ex?jj[΅0mBIżezX|[SM?]_ 㓚yxs??c]Q60Zwt ZQd]aOe@-PH-D2[\yp+R$nGQuU:6Qi$P/h 1֩ IdU eI#bnb4 5UdKJRp>g#!R'"e|&"0.7U:u磊Sdub-&BR=q-ʩp  'n/_YFU OsR~ڱZ"D=4;+,Tn*% &Aڸ%gU z[XGPAç'C=53v/}*xAC`P14Tbڞa]&lDb)Tqu/n١ ДA3-P!WCLo&G&mKb44 tzR&4ޒL}Dǿ8EIJ5zm\2'/N #4>ŝIiL\.gL{e:^Uf$e|;+T M/VDZb( Ֆw\;rRgIvy#hBK#t+Aϱ]~ .(V%#L|m‹IW%n Y~6!e' >ot&8"AJJuZ~ph3iI A`@#0GxrEfRM_>6YiJ)WM&(UHi,kvw14ៗzGL?`|pQ}UtKO]q63Y&SաEo^b8I ˁiס;W Z?yVsi wң ~qeK=a, 7jag̝!"]姵3n?(P&O*AХ?g (%m[pY(Oˊ#acԋ07Ljȝ(G%G2qoB2 1 3DY9Kݖ轼|GWclG=\F F "P]^hhC۸X2iz3άgn5d4blrkU12<Ѐyh ]2a}zgchUN3 'omapJ<<ދ!ג88Uq0/jK8dKRjZ~ODf78×6ΩՍ 8R 1%^JX>c8ܯKtR UDr|WoB|f R'隭; *P,@xiqN}L[harBj+V&8Dʙ&͙K]wj:'sPP\@_.d rHPVāA\R3cz#|J7MTH uAwNwg\|)^%[*EFUWT|jq!2\옮ũZf)T2`q_M=X0*Qt,GXzH+A=yRZf CBrH$leu7|Xtğg:'MG:SlvB \ĜƐ>gv!b@Ky -.?۳+#7!wAp .5Ta q 5LeC\?l\cջ:Ѓ)C!+1BЮa`VfrU{fWw< A%5eS&qX,i% wЀ1|+@2ĤG]9M^}<3 +G}BTzW.93vύӲWskX_#ak/~m?GNLuzx]:jux"R^*_w0%V@LY&'q)"Oۭ!:T83߉zV" a`[]_5nyf~EXg{6.g ۿo=ڌqL|цi4 VOilAE_[VWcL \kpE%{*d0ۋRlF[ٖ߁߶L|p[!RlB)Z6㙱:ŞϠɒѵ/*bSV{1|YB2dy³4l[l!||v0oƪ `J n|Ox3 noᢎC½h6iGa"'k h]j"Kjo`PxAw cГMU_G·-qp:M @C6sKY;:dP:iw1맠Gж+j"R'c4/i+V5>O!S( {r=ygU5N@Eany?68Mܜ{/#!%?ZBM*tex@u" m SkQ^97m3onM a% %peSZJ8tߋz.1:${'F?(t <W۽@ ʦ %W 3f5qژp ~Q)=ŬȆ<8\YQPA /Wj BӅx u Ý51 I4G!9)KА%e#x߬OўS*29k&lD-x 'E_dGV?)SQ<dxd^}H{ֵdC 5\ +C1-o`4i0* ]ؠSBt֥O̧ͦZyF,)v0%>\M}A trovCxKw̑`D@i(U4WЙ$Ks/rDmh-i=-ƍ*nԙQוPrki$"K[+ eDgjzC@cG4?uEaiO[``t{e@}NAP dRKVьq,SL}Ye85tY dkD؃3,99MyKɏy͜OL[Fg0$S՝k.(5_T;TazA `+<'1/b %&t̠Ut Uuw*F؎|x> n1Qw`1|1\. N秾1,e(!a!Dp#(t#Đ-hE}՚ukH!O nr}"-\ ȃ~޻UX/phߪnx< ί3D/.ocHps`K0#6?:Ŭ2;+U!5]J/ozI\ػPBBQp[,ȘۡŬ Ā^jښh5#LQ}c-zo=BbN6n3g 5/:tvc˭IX/ɵWWΗt@N 9SЄ#*dv=6/.EeV & UеEMlbniZ9\"}>E˯&$TCjF>5dñ )i˱_UN1CME|+3(֓o>A,INbn FIX h3C^V7;4fu ?9=Ys=m~M:HÌK +_<][f޴r5tBI[lhE s0T(k,C/3;uRQC Q@?w=_l$!  Aad !n^-t5{)Vm%  `YZ$<$(>n1yOj.Uڽ Ĩ(hf#"ѕ-d_c}/m!C !ħ_*c?yw1?bMn)\UU lZ<㧷+'08J3CwWEo HAdzz6<(9Ng =l˧r"D'MPHL,chl*o/Orjbe7=D4]>YƭQ`|jC!ZֶK|ˑA-> Ұ?Q*ɘrCϢTˇS!XU^\|$1Ů:$ _~U«3Us+ "C_Ɩ+p%c"lŠ ۠BaRi7md9^jGhĔP2g 6_ œeFQ*E mG]U ghX*fYvӤ9?䀕ɁFoNoz ]$eLAФ;bcD2$Íhd71c^cbKM4@"j%HSr>X;%cX QdʰU>oӅadsjPQ]yKB(62$D#oa hċyyֿ:;唋^s '~KM |< G; <1d"R |c'obq.c˄.W6.="e@mZU ӍiĦa~kWw;r %E&?+2-díҩ]2;*쭏qw@MPJՐ/v7,"$oyIWB֍ J $ΰ! 3TzŚ_oM,ޔ%湠E"v eX8cxX:`73^.۵ #F ucah#%Av%,PWtl}~CAbF'&3 =S:B")̮JqɿǷ$rMI>#937t[#QxXv/!|8G54(뒆]I%|b^QLa# '/~,([ LXeʇW STW֑cӾe1;!5(N ȕ.jOt+Z蓣 -c|_o/՟yPDԡEp(j Z2CK؈QیxiW~~syqܧrZHRjd٧v/T k&ڈO!Ny0mY^ ͭWh=p6l]W>h<$!R~L/#hmY;Xznp<dm=00n # ndf9RU> .UOCu򍮚$.Lb^/PA[|?{i)j`#vp'Dih7׻/ u=! "l4Q2 a&}x{ u|d F.zX>K%=ЅU.(n1/&%=*1R0ܺߠTIC5Tfw=V'%4iCY/=g-yg4cn$R;C׀0E Hf{>;ȋ0q5u5faK셋 "?w.n[w2 L5 +|T6[^zIՃNYvyʔiAy' Twk,Zq>ǵgp>g /]XB'CɂV,m#9s2/[^',i.Ze =8M {$8uF9W%2^g1ڹ ċ`[\U@YcOⷐ51_*=<5&3YVƺp~oڽ涄`)3* f7u-M'*cIBrx鄇yHG yaS3*1zlXTnkxHBp9v> 2%iU4A-dB#@L"NϜSst9MN/j9~bw1"<)+%xڰ*f`uI|C:=8ۦ1K.$*vr%)`!i-:!_@/CVN:b,_1cܦn[%av&>%icRG F SMLyXX* !W /^"Y.NkxS @8!CZQ:bARGJIJ)'*(C 8Pf->Q3#@#YdLg%x\d.]Py?I ‹Vb t*-T>RbB?3&YCk@y5'Ƣ/X/1:YKSLF) 8j4[+EL!Uf0)rS#GXI+BS#-y>XMc__ ]~"")8s73SG;|p*ռ j=?9zz(H)b,4o,&oeZ #c5uza]p7@$ǀ@jUM`@rڗO l 5eJ5(e@-S`XP&~g9OGSp'dMHKj*9 /2HA?XSC5h{rļ>9Yk< |~%c:@qC+Y3X4z@RB2%cf m-X0."RU)*8 G /ZM( J(T " [=k|z#M .a7M5x0ά%U.]4J |Wq#U6c2sqkj RnrZ :hDJT}ؓD)LVmr sABpfBEPP#_.OTWgL\~ Oq`6Z[2/%t$[8! &"y\<.5fآݢgE.%&(F  =V[H4}7ЎS5Wt[u SlCcC6O1Odeqn{ 4!^kLĥ"1jEK,/D;:0?~pk1]|ːđsXB;Fh<6ij~0M i4:NĂE o텼cA&GuE =E5kQ*W۴fMyß^|gB|-k[ZϬ:r}hwDF'u|˅Tͮޝa"N"a9lL|51ٴmVote">.\:FSK(-C{niŮ6Nߜw 2cZpd˴<72tK%PLcGS)gWu`紆p ^n Biڡ9S?gIJ;ڽt 'yY9!WVc RÝ y9̶:` _ͩUoA).NҰi uvl0~tznҙU#期,zq3LCfMIEm$FO[D94./?K+5ъĭ演i e&,iSc:bF9*]0N'GZ(`-]ܡp??;ڼ60V㌦y w# V2cs;>ZU˦&LQcL#:>(v iՑQW=ۦZj*qslS@1tblB1Bo"@* &k^'9?TK6'hu;[bgLRNjM:6 C ȩYY v XX6TƢ‰9--kʲn)iD 4ŧZPqHZgnW--ƹm~Vԣ(Nlބ-Gg% W|a9c5Di.9*4ҥzwR2L0s^UK~<򌼝nauN2iYOÝeRGG#Td`C$olͼ71SNJ03avVEׄ$hx $d~ML,/E8NBg+,^D_֓ouw=**_ PVth&8uRf~$8-":[W_~;ױ(̲"BTLACe1@7KL|زA/V<pl[HUG.7*nbhGչl$^G]O$`;Y{fe֤Q{l(+%T@[]OkQF\; Ep8lbjmNZL86 #scL`ƥڅ-+bx.GPa mЪ>*߅֍@4./Yo|3j"\b~0Oقƣ_H:9<8qYe_y MUT7Ik!F.2OCtt ˨0` X0<B fv΂ug~S5jYfGLOLZ(tT*-y52M(\\ICFxtģNPD7͙MZyM4HlihbԮHbNw .!`Tz?OTKL)JvA8Xbad Q> K2$ys/IEj˟IsjO\6O1,:Ktaʶʟ J7auH&;f]GVQiVeSh96'rU|L͐^y'?%MS4 t Nn_%EhHP qQy%lIwL&MQΠ?EDt4JfU1!@Tٵ)1X)SX%AAM945,K I8QNva D.L `]sv 3tSR¥ Ԙ$p{ ZQc<2+ .ATO`M2%ZtʘҒ]ӣF֦]aLCvi]4J=2t0"Kb2\<~#(&74w=vKb6MhS$T<.g]Ym-bF ьJ ԓ͆ [C=֢`T1;8髱 uQi8D<ՙCRI6{e3S"Cxu,QwFW@.Qxš5xstg4lˢe:0-o Ft(RH|h cq]1f\D9zTe~.M8,ר]TI5q<V~P¶4YE<(}ngYcؚr@GKٍ'_"5nan] 3 k.81,ck&tX_A*mvN c4Kr(3qTBG >{fBWЈCB? ݙ4Ti,~9?ǩU2~ m)H6]l~4`Ė 2E78ت~]/]P~,ɐ켽y)SєGNJ5lJ05W:9A*F6NГxN^ 5:U暔a}ʡKXR̎[gZbבA:T0N/ޥ'cr-3KY5xrl ڲBZR1))hsR8#Ź Ը Nx>%XЅM5`&L iS\P(Ff2`Nz!xr$IC  .OGԢq|fKT!NQ,4;#1naKN#)8DXsS`֟p Y5XYsS=ddi͠Eֈ а]ܞÑ9F5>u|+ :Do> KFh @0ȣ6BO8Dl ߑ!w:mMfWYe2^#;(&d}Rt~[%Fkw1Qi$W!6᳢W>Aӵ -5+NSܴ[*_^Or 3JM!Cj`43̣!˽ TE>&,@CԴ߸]7{y,ȌeS}Z˻8,(ݺp\aNy#_b,2NKQ,qp }PRDvDB&ʆ'{?2d{U>Wq&]<.=DBLuVf Ag9B y @kcKH 戜Ooi*SVƁ 6\lF#='0:UK9 =2SO?AF9GqJhy՛p`L K="|rK?蹐"^?t6P^W7OBb"铛6Ֆ M\KU(j!LE/aљrQu>8XEÛq3!Պ4;n EO-p Ȉ627QId0[x" EtB^܀ cka:JxD0ڵ eyϓMy9|ܔHDwyɳO;$7`ԛYuxI1?A-@q,=s I=}PGCo:+0 SM؆WU,*2v]kᬂNŕoE&aUj2~_ iGj.K|i>Gz3|'T{ȌՓRƕ Y8*\WQiZԚ zt[]SV,`I/^SƙPՊ#zjRpĸH~sx *ɚ9-+Fyq9 kYz֜ yMw_HBhQN19% ,@.#1Z̆e~zu JxbsܝA-i̎7<+60 l1)FM}Bʽ0rLem:5d. (`J?4ő 3.nwsKklqPb:Ӝ.7V{eV\$|xxgQ؏ܺ=s-~&j]MGV:5_yMVplKu$k"W HSa].06_'e"3_} Ur J͹#Ezd+aw R^EQXAuHۦeFr t&a Ny3n[k+V#Oe#LX;VWYCH %*r4D/'A2ٌwD'9b)zOppQ! exQ vbT3Hns/9*Qe2FuҔ)nZ.Ijůsc. =z(NӂqA:]NKQՂ g%j,~ݚPN?cӂ|Ig}Xp"P]" s ѩ?tyQ<-3j衃4L'M] daTV͟bdI(0^*7,~!`AoNIDATCc&S`-gf[i` [BN丸|U^Sȇ4l"ZQdpB<9XRrnDaOtH h?HtN/`lv6 cZμ%!-pm]:*##\V#j:Ig.XTұ<*:UO˝cuq`"#]89aL&SV.Kw;ha CļhP?}uwm7W( Y9$ް)9a2^ y'bUD/,nG :8D/7PT<[gKQdn| XHB.y?GL &Rnl w8q6*yv1͈}.;6RBl]*źzxCJVћpJ=fRIB}^nVf^ 8xg5j8}pf mC+7~y)R`ĴsU$2ǨP#,3AmQAv'!3eZ<&^N7< 2K( 'e˃["B⧌ NCx؅'"H$]~x P3z4 3Enϸz[4cV6K9. 9R^pEN 3hWgclh(Hog^{f^!QZ+ r\ECɤFĢ/+ʍe?_pOY\b@XZ}`o":bN rL.?b)MtC5Ih33d+m*@T|/qikԙĕ%U&ScE<$RDoSЋB`=ė8zOsoAoE F;2+H-ܰbyPU6QU0JV)li!ee92dOYQ iRjXJLl-XMiT\c ɉvnq.U.=/% I0>|ڡ>7у0(,-EA .%N1d3MLf tKx+kpAx řު}A#ciq7"[!7G~՚˽.z^&v͕YK 0BZK@,1L&:(Lһ|W#pn>631N0a@L sbl%"N5^DaPTUKvpT]bv >2E~םKv1#J9{"x‘VDD_ g$X'aiUJ̛Bf#,@:q kR6ĿY4kh}Ypzgw gf_iFj/@ȥeP ݤ( /Mu;/\ .n-,:7\YC啯ȄW q$D K?onmj" +WJE_s_Bs2mY9QS}+3'39HO(Z`6]-xm˪4La"0 <1C.aqx t<Z:SwG} '-g# ORShKk"'.#{TFb`LH90kBb\~ӠX _imyB0(/M%h0Nc#[,XM1we%b [1`* "b$\U0цWOYjOcOaP2ik3ƌz uq(GV6fs/]P*i%D)5ASeȵfbOZp22P4u%MS΍S-?*unTqÙn7 ЄjS syf$`6v=wW9Mi@?U&Tq)E*XE.N-DSga,̪biP2:Ҋ^Oe\ԻQ|<Ƥ`W+S| @ Jf4i&Qc g{fgO:/(Hc T,BLbΤ+$3uǿK=Ӟ鰉 @`Q\63)_x.N3a}e\~lˮ i:4XO]*uQhk;v$l,Czq0ȉM(a/+=h+ 3:,-fNnZH,E]K.%dIq?#ϐv=/:h(8ڠ<39yFiQTͲ&^!Cf6Ti8'/px+\(=cK/ʴ|}ȿC@(ݧh I> TKn4e S:/ٵCƯGtxb@Lw^oy_^lC?,N$Sbi#8iDc㹞dBخRR+OߑEe G$]L$c'V1+ ?2jZCk \dS6 ?BLUHf8UpI+~ŚIDł2UtAD'ɴ)Un0 ¦TkJ~4!zx4lqsIO^x)2_{?@V15Ϳ=] :KjSeE '\laMdd%%B=nN_\XlXoqi±Uv~l@v81͈l+ݡ%xV 13}zwk$p)}k E 3V&^Oԛ"<w 3q;10>dVW}+e;g`A<qNa.v[HBXIDΞ3Nu5_W8Pbý q灬J c # 1^ss!bdt@m,|JөsGC z".9ݘrsMC;,RSx43Ә-?}Ph0 P|-rVc]] Pyv?oLkBTV*/&'UЩ) LT!ceh=z\AïaX`鿪yzեR  qnRx՞| %傺L-L?iȦ,!fw#e$p}Q.F{䩚r;4:<6`$kA5Y(vn-Ç&N+HX$Wہ "u"7hOƊʦn3iAEp i2F&UvO\ltM)!0a ֚hr!,5CI7s /6J Ha3@L"`85<>)˻*{DB+)6$#os%2'@F3 cO& 9oZ3)sxu)_! at&} ^PñՅ3.d0^: ?AaAhR:M) 4<%,}bgj˫;X#BRDJ6}:#Xq͑C`.E͜ Sn;5kE)~Od]@uF ܈`E8( 0c;2˛;S{@f>dVev!AE\0-յ|] |B?[z Opl#S <\mŢ0tb(M6HQ&% e;|qér_?8isu#9N4PT?-e)h С|r < -'Ci7|e#mXp2lb`XelN1Du^N<+57PB܊@ʑg)⬁Sۂ 4eUvWl:g_A D+9Nr`* PAnTL"\~3 OFvV#]+&*F&Ɵ6jp8Id"UJϣ6 qӄ# 씉&T` dgbMg-f +Ҽ y,En p (\Yy9WQVo ʮT=7mozeTKm'P*,< գUQD N@ FXY)pNUWi*"xkp+G)jHن3:%~1 ?#CW O d?G"a03LY&f#jJG ;%CJcЦ8--S.]1إ]Yc96\E]7ߊ ]V\HXp`.ʓ]_yPѷӱ`)(&5wMW4@v ^4a|dyq]b̠s -pїar؝6l^$w8ڬR32/^z"bApj*ɥc  ,$Ek0[lS[sը%O16atm u{ p{XX>@mLX4Xrw܌-J<Q?.("6yN S/RQcRL['OM|Xbqn&4SDf3MFYte]E`6'y/ȗ(@,6'g<^A}riө!o^ADFTбk:L낰f ; ;QCbDp:%3XT0X,UQIEC(1RucdE-t Iau683 ;KɍXO5HPU#L5`x,rܥ=D aGH?*u:JSm8DxP#I*[UU*aWg{9O&$Ln;'K1xX(ϫiSqV2?<P@d,ɝ279.`TCEz<R=ל1X8 -*y1n/<Pc*bm*|=W1Agrש)'UeYW$5)W4%[BU6W肥]TX3`|ydg UlH@~ X.6^yF!PKU&^̘PYsd0!=nƂضUO. j焎Ƹwb5hg52wO0OOFkgS+{nz}6zTM zeN^9Wz~+]TrHg2^TZS+وo9)GeZ5r5١]TӍg %GҥokL奎O0鄞GlE-[v ^Ru#=)T`2W^3?iFy Gw>D/wdX׌\?NⰾZ923Jo3 }Nؑe7qMx+@.^XGL)`&8[y,#Ĥ4T|cGv6[n8L1R014:0!d^ZGָ]Xsa;&v,j|ΔK+p. LzR5 GIT4[H|+<[^Q<폢 #z](F|"MquK9Ok9. \}zw0KUT1I ɘ^7\苆_,N.M ?T)H^39UvƳ;k$R{JͮDK|q^8\Ż\[3}r w Ѣ^b@Jb l\% C *6)w1|eb/Us ` E$KUٚMׯ~6iO4.6\SQO=C/!wyuM"(|TH.h0粋l5D(>N97blL YMϩ>w&lczog)pÛ`|"l0P҄Xrfqsf:3xZ@:FuF]v *t3Vw* Iin1-MDxCyzz.jVD3D6]ρx r1n^-#{kֲwR-\ ۈ*yUȪPOZ/8v+,Jc1C!@ROkm;bl^l-7)Vz+Y}e}3曋1nJ.bӥS#ǝ!n>Y;zj2p-jxS t#pwk1~csy|XPkw56>2Y/bl3i )zڸ)H [){4nk2IA㰤; 3 7˫ _:Mq=͜ ~*&^k-n#yt|"#E.z#$pC-F$/}W41`B " im<ΑF`u(8rdyp;;@AH,HEO?',QݩQ<%@ˁ)5Ϛ JTK4)fR`e)?\3)hbnhcX$60󍰌a}%`t #8 |&s-o.pKPk@.\B ˆ* x.CsD8NM.V"k:FnKy12a|HzJ}> FBw;b" /7O4U\# w}qhl;Ne}a'+\Dޢ<-vA6$EJ7 .,&%Ǚ>|.`"XCCRߝy3A7ByV02!+I&CL\ Sr!۰.ﰂG3xIprAifIO +CF ,GOP'&w@_l(DsU(/[QF()7dKW_6K4h22bO] R0ES8Ej6xFڪa¦-mΧ25*9 XN8 Cե2`xBVϤ"+HRem|D̻ZWaƼRA4Lj X1Vq&yn F/sIeBXF2r3H.': ʜʟAn@%(1:)q) WRp Eoos_6OuMq|}*Fս8MLIp]ux<BUϗdnhI/}7AތZE' ;#o\x\ca!:eU)e$X/ 2˭$h/,g PC! oEQ+ޅIo,OA7?evh1e ]-z,n4r[ECS?2ad}?g)'r@ f@0D RFQqyu|Fv¿NNC\yGNW;&0˅+8Z?<( oy2j;zyաJIEu!?DQK5F$B8p$H4$HX -Ŋ2g40dػp*s8x7 UKzOK8P#Tu_5y$@M 2$[(qN7AbBќFmQypЯF ʡݯzP3&@0'jl@SV"T*vHg{dMuA9MEK8ti SSDsnWg6l0Ra7D4~xThQ܂K_$ bqw: [ I"~0 0p]":S֡oT|{NJF=8"1}{C\>?bn S8 مs) lOgsqMB6-p|Hq]Az[Gn&APS>"Bk:D]qB])k^$66.#iN%PZ3> IU?v s 2Y<ΘQ-NO\S~6yURB1X fo1Ť!vI8 l]q|zd*Ɲ6:ϋww$l嚂P~7͢DY;ς9 a1/I*.-;z%୧KeZIxqA؍]<Ol/K5pf.F.;5x̼[k *1/kRwŚ@pde z7SGbUVqesytjZSӑ)$I9]C L|f,i:3>=`,立{9kk<sF!'vmb̳ lZl[Oa}9g!.e7<6In!vifpIAeP2~.X*ݮL5K)J˶*Kƴ0U̿p@jMӔXkح|\A.bC}t"Kw@;d TCT)@g/BZ<]{ uC-t-Rx>,:e@(YZE(>- snZ?߼`+"F]L'ҕs[@iGo}Xl#ɖzyAiB;U84ݙtӏ.tzs7 ʧY)3Q^A3 \hskTA*[$?:ub|̭[ 솱覑F4CR9|Ě+d-K"VMÌ `IO'Ph}hcc0=pT'*B`ly5KLZu2ud:? n* f"9f-)eC2J!&.;bKdy:\P3/k5RoF@<0+`|Nz<'. d6ɤKe׽WA=]c:l}"%—ƃvblYJÊ-Z8tV~s /(6ޔ'W)M Y3s= }+ҹ5+P5p-@9#56 倃ܷtH0^5D!RU`ਸ਼Ғ 2pM$ eQyP8-Fh3rzV=8.HhYǖZBsL6(ֈ滃-,1jpIszʘ eC$ײv`_QUPW-T 8o+S$4wKd* c~V1 4f ߚI|321=I829N08+iC#-x iwXm1hje'@S m}Rވ`PʡfPI6Cn+Y4jQWdl(oypKLr&zʻ\gf5HYH|S_ڻKn.]/y2ny75_)ehL֭Q$vpjvJ ^70i?֦}"L1Xa'Ț)4%lb|mb}3݄m{զxĤʣxfɎzx oǩ-7X9].!>C,)[-0u]ҥL٨CcI;l7t?H4B& ]7s F0^YSqN,baTN>1JɊܵ[ࡥ삇b#f2o}l388E\,C Ʋ@S=#k$f%hV +KgN$I:yIhhcC/2QQDyGzH/+1r-|bQUtKIxF\vК *`;|6ng/'*խCYm|flՁ]QA\Y1xnLh;I#JVLZ Hvnщ\#9_ 4$}/5YF2pЬjV[k7 _N"#6WhѸAF׶ I/Z1vs3Yy dЖ6Ozqg$$ؤTָ'Vr4] Œ1mA7-_ d\f$Co5 scx,6رJ^StL ,'~Li۩vY|H*>uQ+@~tnj^uQ ۡrW܋3..`;bjL)el@Fn*ة D-91y|r L>$LQhiꖋV D+8>N׶\%1[5]=L %-#iYS u%˒TcY *q⢾{w+w2]ߛn_rŒ@\[dpj KGq?dgugHXuPb;K)Jn= 1(~B󪦲)Jiyl[L#, w͒ݒ7J􀫠 0=g>UwQY4u5D.4WhIl.#\1n{" : =Ȧ>fL`~kR6tzWW\1pWIwPOo1n9@aklԡjMd[}=unt_6@s**/ZHtzD~N**z,X ^U"ؙR Rdڏ&3jm<If -U" 3 O4%71LX*ħ[XiG=KNɔ36vdOrcuHenvA|. \\icZMLFJXo~^V8iҽu3 a覩5ZO !K2 hQ0g1 #J8[ gQ~+tSg)n̐^ b UF0x 3E_/]O9F5v|OiڍxKOEYh 3"d|C N = p<$ ,c\ԌS/Dz5=OBaf>? "q̀ iPY`>bJ'NI(ضt c/n|@ 㬠ԳHdZF5ŖՕh6\]5eխ@f,iF=hYux|@ E}OM[mS)&Ldu$yGns|czp1*{?tWAc[,n<1 Mo8T-3.EjE|U9[.-8S* o1%q(d=ۛC( nad+U/+2@zN#M!BX)I̸_*4ce7 HRF41@&/ n1 ٕY:c6`kxV龦sO{l;K/<96*x]/yh0 a~yjy!yw쒁bbY&>Ĺ)pl?X %vW1C6 *V-1`D7#gN"E*b@2AG'Տ%~jX ȇETU *&ǯ|[Ve9+y\7@d6 f$`JIZo-? ')hC]~xi\m|Xb-IB-y֕m"NSSjcBq$G?/Ɵ˥UR:lJT;<"^+O.Ǥ;kHGˉ]Z>_YfL.,[+J&bُϷJ Zw(cHPg)5$ D@1a@y D޽d`B $87N8 DHGgN==+ݤ2(STR;laﮟb( wp΁Z0ױPYb]F7@-?: zzOC0eRCX(êSo^r-C>J+"U9WK? V Z8R@'N0o+i9Fɱ$ka3[#0J'\`p͏ ~d||RGcS b*uojlnr;+{%ȥ݈#."ts3Qvcq-s/:!$OtBn"_13[lMBNΌ2 W GE| ȷSL-$(_ƨwU]JP\cMkHr"_& ?GNM@q '~q^3z xihooCbq\9B սݙԆ~Xxs]?\So~#0ZYί2+LUh ``4v` G1M&$$AԸԢ?5u}3c>M۠]`uZw y~{l Ȅ\]@nW^<iKA d18-GՅ43j4|*2!֣X-_>3-!:Yi>Oo R.~q'~zΏJN'u Kaqz*̽G` `+!0W)hxDռ ]{҇1`^D$ZyOWWc^VlA@FJ0gF;a7(fxu4 >z,@n! }j>a4Hq Nuy'Pl1Ժ`cx5Gtuĥ;gty<Et..fiî2 @Y)qJ:tc҂r̬ 9Qz]l֠͆V`1+42{,B6*:p?[: %U18\$6do `Bƫ?Y)}G&(' %!:{ɣ˺]3 Yi~S.!@$Rw b |Q@ȚoΛMoo tHni'6D1hJ'NT.7osPirtP,`kƛ RJ%R@MGmGRE(-\ WqM*Bky?_| xi= Wuo lsWQqlҍ %Dnnv- Ѓ/@I)rp6@]Wп= +`;x^ϪĞ bu2v>o ٠/Ոpn:R+==6Ha&[ U^a]pe6O:_ KKUt"Д{$g u[w칗(.h4jz5. T,t5#ސZ C(tk$,xk7 q-@2I!/?U9u>Ԭ/;\ΏOdx\TӴuXcK]h=cīZj&',ưCVzG/¾Ca $ R1h[?3P\PYzTʠLM0w<|7N u[Y@;u (o!A(/O(S0K)"cЕZ`/]Y7O"г8Pޗ0?m?9⢨-L>warߝB8K<\`GOq3Rw(lL>T*ȒNx>rV{ :3DTzeIM`w-GE:өI? 3䰢o+#DuǐpIUVl3, 0%Үo1k:U^\_`*`SO!ru9PA}ϳ"+TP_ЧcdzQhȓ?z(0Lʍ`̷j55#f8HM ^=M[~2=Ҟ]8*>\EO+OY*WjOd3\(Fn0/@I73Y@Y> ȸQe`Rc(Mb8tjG }jA1S98rP ޶kj*^.;w Ec C^6-\J,J:,H0TGg ~Ѫ*@ on}sO MW;iX߶cBQY۠K/JwgA>sS?N u l>J]OؕOiWfCpsmT"JT9,mD`^}6aw;B~vsy.azD*<$1=:5W-o}-.8x/[%4`':[ђW_"b=zM@ep^ߊ PUNl1 .Ww)N;Ey {*M1w8Lo= 04dԆl67uǸX%Negu1,oNSLPc60Vz )l(mOgEnꇌ;zf\Ǹj 8 ,qW;9>}&ȒEGNe]Oa3u%9zBaw ⪃n7#cvCR  su&/aL^0fp~)FhQS/a,cXjEdcLc RXԔ):F5*?'bqbˑ{8],qխBz|5*,azYS*Y\ƿBmBh  |]$7`G#Pa|=,P8?Yl.*F/ z>n>ćr[}Z4-4.ög \ `-pZ۝X4&n_螸8o<ѵ?RI!pKsbq.Yy)dPY.D9zkp٢\|إG{~,B5v߻w;hnW; N|8OzbÐ⊉:`>%`fO#d͔ɗ־:'7C_*y%ɸ[5]bڂHyoR** Nx^ {?zIشP"~pls(!Tpi Bs-V*K-ԕHŃd{qwC{<coyatTMFGF/x`%K{`lnÈz.?rO<`02 q P"EtYW,ͰF. {=cE+  pAX6ʠ"/ xq] =dCCDWuD?zYWM$W0!+=3Ik9zcE )4e+i'WVx< \ n,dVLOc ;uA6^e~,¶~4"fFz4b*`f}kcp)8/3t>$"b0m`VPծ}d~|'#v`;oCUwSI==f<9% i?ǡ8$jt7P"kE1̹ rِg&趀O Fagͮ?V1XMI4Cĝ,bL-~bG‘2^O嘙TKEN!$5<[:RFTԱa˗՛KqSEY=4kVPYe\=}k )8Ao c& L]f?`4؀=]a uro-?rBn?d Z%n:SaңHWfk.kCW(&vBaV6LxUSwXGRṱo#ϟR \mi^"&>pZjk*_쀇ptupKcB3<3%n16?kE~4 zzJsN5oU1WÁhp U˄[ift-Z|)nΠ GtܓQTaIQQޅd\yȉEJtu=zgǑFT*,'~<>MyaEɯa3t)l~].OZk==xg>#P K w!d^ߗ2+ &UXD:>B\>ܺ?!%,NY2*a9pn -|Vm|v>"ao蘼 <꟔2XɟSdd&7 kr k?>!ʋv=;zIrvԲv2>LLŀ+Í- Чpd$[("pC΄lD짪&``xXukto?,K.b[uBH冚˵&.WJa09|pA] 8t!&k#Vu7|toǁ 47!(\wYF;h^ ?<%= '<\0۲՛=:D.0&7./` [oo75uz).|q >^U,/02ךExZTt/"E]}+,mygMBnQ :n`*>(T T)Vs"t"BO@:Npï ܈X,ZC I=G5ƥ1iAG5x@9Z.5#'T[m({pHTEvBx"m-:3Te,ts=^p#@qһmy+Ip_M*Oit#ÁJ5 8 wٖ*Xwj" +^쒬`aCҪRS")sd"ٹ_DV?hK%Mmҏt'F/^EuW* xi_Df[bQB Kwh&!h;-BƆeyr4u ٢|z9R"]>}zfxsyS(0W-EoRɋLbW~zwh)~.|<$UK D(,X튱"\f|?Ș;ˋ:%Oq.f5*R7!`Ź51ŝ4*)/uv5|CV(|s[=~Bɬ9F8=HRݼ\_He;xD@ N|ozg݇;d-zWd$JX7-}ZuX"'0ߪs ?2\.M!W1)p1`=RŔ_K`D# %#u3tIhJ<]|4p"],">+THټˈ Z Q(j}*CBiЯ2wo NgT:>nj7h>&6 WN$ofv9,KfoK@0XHGk/P"6tGg4pEj)^8Sk(1t-NwF-$e+5(owUb>ݗWja.%\0N2$b`.3I3Tk1SY/bRB-_,UسQ hu?uLjp#Ìo w~#X2mŃUr(h zYl0솁ȇ>^`K߰{Q9(0p<x-^3n}PrŇoK0*hش}QWu~eeg gz$˘taqـ !@1x +ǭUDdc]H{\%|.^ dSط0n]+ Ϋ.FX"]]#EYֳkLxsVۅ޶ a@Z!X>uZu>%R/6.桡iѦοJ5ݾ7~0Ac.V]sgm`BE<>^.'W-|mxm{,K,;{숇-MrKl2{Χdٞ}rPWc%yF$zA108\>%L_ oIRs,2<)J!i0=hF F3r :Cex%՛?i^ _T̵H~FJ̷@*2;W)o} QGu&:Xq2?գ0xp#tV?Ttgw92a`(SVPZG>ucGt_[5^Fյƭ"@m6(]eUڣΫgT6CѤ (cy0z# kMVxv5{V"|.Uo>wwW^c='0SK]bA"2/:Cf5\~Kܾx?`@w9D.o]ngC\XC%<  #[݆F ^9oqL @d{zm?Q Y,7:HIv?ZR3-p[IzaՁGNh֓3'cVXwL}F.a>o=mQ01Pϡ X1H0PQiVI_jַ7WGc pQA20jeW;M]P\Zr7C^"#J F.ȗŊd,;\rH Q~() G\ >/̆0cW.s|vq.Ro dtpo!H ǰn 4B: ~>NW\ G#hQHTcaVl(Ő˱(2@1hP&rJehwv.TDLCPҾP[7Je輸 )|O?*Uk7QݰyZ f=1\0'T/߅shèK ēM8q 'ۯX(XB=}_GAB,mKWU4YGwiQ"\\7'-a'Gӣ(>ԊĭQbV! dDNBFw;nkP R2ڽVWs5[ .k7*s;I^TR?X3I>uNzqMg>;|;ͩ`u~I&R$ y|@<&I4BJ5"ӿa'{^! W\ucA"pհ :lq< !ܫ6ZNliP1cP wSxEc9ʔ<?yUW77(꡻{W*)/MM+<> 3DNU @>'mtc#W940?`5 s6!&A1u2`bklb^6QKLJ\@KԈY4>IJT?O<<=i/t.Ύ";dUݘ}ˢVjbCi<8}7Qqs2!ZuklY#ɻ$zF^\*X} ~T+E/ѲH([p FM`~yJ3P7d}\3L* c$ d4ezb\BJfDC' ZYD<T6\l~1Z<6 ,w Ѿ L)P ,ܼ(V7 }l?x (]];MnE}!,@h< ߻BGjnCHHi{`ST3iު>z 8[mzPoLM0$.?-!cypz}!^,5|:~jLf^ 4k?m1#_<+FoRp  C6B9 v*QZgk)e X,Cpϑ7 mA-#QwS~wbǘL:әo/&^.ReWjR* àfFl>`03(|# ڷg/5Fc&jJ^stM* >hډc4[9 ~PjpV?Đ[wQh3yv`QUlmγp=IɌa{qLjVRYb;aLa%lCS.CtO]RrP7(NŀTB) wIf rΟ}SqE !ҦS^*Pg/Y[L}wyMZ`'֪PX> ߽ͮj"hRlVY¤6ξ.|-Ց~|} Pݑ!-,g6qo#1)^P`&Rlٖ8W$Xm6I#+"[qPK=`aVMFgLoLL+k)9I<{?n`kD`x0h.+C a$bLoԛqNrdJs/Z>6Z 'ӬK'?gcBo D&O|QVL!NG> B 4*>8' A8@..ae& Qd'b#uVW&ajgтv+>PzKI'm9?Sbw3Nu<'1tqOǵwgAJYzVXͩ`0~"AΣ'i9Y߮e7/:t%6r]9>}0OD^Ѕ?WЫuTvPI!Xu I9.oP 6Jr:uc dzeJ褧pY^"|E} $N1=M D8Esp,F`k?I=u}z0& ʠ(O\N 38i~W^mɟ–l4τqkRFlq<4 O˛w|-ٵfFALAknW N:ZnS2k^1—[=z^*f8yL3J[4g;Lٟ5>q9O LUHtܞ50I?gTаrM?6K4 I!H0f;}V $Zӯ"FJKw5?g(6$6eL 7>e.0V kc~,1yi-t+8IJSz%$wu*g^?LLF[91& HbH=\ * XwBE5ܞj5jR. RjB( $mJ"!SxD#x>_/P .B[ Qw5 C B5@z'#:]Rfa6KC |[ 79NAx6Z2EKc_" ꙥ9/08u\T?xss[o+qM?XDUdItkH]tZЀEoƿuЭ`Hӻ_ L ["=ZChh Ni-C~6ՇKkKnϑ0mX@qbh {5Mk1h_޾})Ep"+ KXuHx,MC*Q~W4 ɘaB qcDU+0%QFW5;k.^S3Cέ̿A2@R,Rfz-zjS'|>Rc!!6[ޮ{_~;u$^o6%!ئP&yn`uDC*/U`Z먂ɹs>ڴ[]Qo|iUuQ*Ś|?g[}!`]=D;1T:WWIDAT1pf]Q s1A $'*K!Bt[5WP&N1R(zi! Ip\|"H+,p sn:Qja/8(3ٯPɚ }>m]"Yt5ONm|q4c(ͫ# ~cLbPcN&g!W:XNw +}~FXDy^2 1c wN>&!Eo ՘r.: N(fb} MGYҰ1{~V48!9"r}uy Q.X|#M>_WӦOiQ1`< y 2[ }+gM8.8'7fDKN|ktLfu%܏ւŏ4\/rP N4pVuOf*4zyTG$RqMJvx4ҵjZgZ7 ]x,a %^<̽ hॹG l2+xp *jB8;?*_š.}륚O~9]:Ҫ/<KĝV[e|-_:4e?.@4dZ8D  Z+ bb+/ ǃʼE_%{,x ycNT!B^X{P/]ia)c2uwxM992')U'_:V+R5/ZjQDפ"$%,nlpCujշc GħJC"[;*qGE ;6ndBO#}Z:+m4Jj:ȑ=4vD8GOd۽ahI ǁўxS_now~W;}GEDUÒD`ehUR)m -qmfPo$ !-0[fc=nӶ1F8ڦwҦZOASvzxQP~z;]u=58xػaDtX#? $>Mrs,BZWU x=@{dbHJIRw/>o1<5˓X51.K??)pUҮӥЧUs\Ρ?:8AZ}f%?ŔxT\z覠-."ٌ3qʶi0jJ?"ip~l[ogJlNdM1d,I,&-+a3Q%G̮ ŶEGL&GRhvͣ7FH5{4>#-@~ز4m[1yEZHǑpSeYtB 1teSMִd:0N<{ V~1Pˣ7O W_Ʋ)H=3i Ԥ129鱪wǜYS@ (nŜ-_h uB3nćM^1*/n+u/0Jٕ \<\7]Zx>|4ρ : ϴhbE@|#;şS@_^lr䝕O Ra8T{oCeE*ٻFeVP˜zۣ˰!)6iUb/M4oCJ<Ց<ƿ}lԑX#d3K*D3 im"ܠ wE߀1VzC$LƇCwccC`XEC7fmS.ðd=5ԶFXnqjjOfq<&t/ ꈀHfG"4}VkbM>SrPϨ'9 ۽eٻlL6> aU$H%#/#7zqO6ꋎTm): !Vпb﯃q@tL13nA1b>6%y:y(s?ZVTa>tP8 6]2L~ FVܖØ7 qh+C@:9߮/bz-,_8,SnE@mHXSL@]|15,S^+(X@+ []F Cg䝾qkr 8twlw6w4Jֵq%,Fu7BaB^d4O9cO.1;ݠD1s:zk7\lIkS`y%JHqf#=ND!3_ Ih< *8^9̗e?Aث@dZװDk8EWmraUQ-Hr G`+*σ:I]1x]Uѩ/ r ̧>5-ŀwһ)߮U!DQhGרBڰxF-"_.7+a$c!ܴ&l_^ Ruhm{0X"%JE?#b."ZM'1DbZ|v}Ůɥv-/W &ЛxA4#{d%y}ŲKwrtxb}MXl{m>h^U0*#wE%V#9<G.@Q l dOfN2X/>T)+σFerQnhZL c.>eH&HP "cndJRKW~O!oU}7PO- #ٺ:]Ug-+$1 v1V1 ]XhPD% M9ɞE0?~_RH0릨u RԋLYPFoZY˭2`\/CH;[oo^ [+@i rs9w 3i3ķp9}E ;dcvU$#5F SXX=yZ<ր$U 2^|9Ef! YC\e<&OygeZ(Mo uO9cZ$CK}U=n3Wzmr{-782\f^:HI Jꇉ9:Y(ǷkrK*C\!99] .fE{Pu Ty6/OdXЉ8pI[l-(l qx|X4A骋rUH^ CYە#pYܐbpT8E3Ҽi9+T& hfNn˲bټoI_Z z&~/3&`Nm/?WRy'=kVfAGGsBs3-Ҍ#KWI87q\81? 8l:0zwUso6arqİ*./=-:싛)KO#m;a| O@YUbӷ`ctSF~B/W/XEn()B}w ZܼBw/|٫~BL Z5A* ل=+ ..x쥳<7ۃXp,*<]1RECk0 @eGӆW݆yIqcNB=_bU~#M}8x~g9h E vaq|&MUCFx/a`|DVʯ~Eg`p78o8@cE|XaMuzJk`/{m#&?.U>dzKmx{OnIg g#JĶ*[3Vef14A(0O4s/Fxc0',aH!3 ߘW؏e*^e݋GS??p\D}c/Qݖ0CHEy5SsBN%LF.I1%s;\zK^:#Pq5ПE<$I+Z*aC0dWLF́AR&$^("^=T􍅲 eUp-b {{K^{i u?UL~BMS:. &w"HSR&\ Eo0/c,GKƉ,h|(rYJֺ(;,:oD,@В}#{ୡ "atf0D5S3>G|ZJIZ]B#[a0k6S2\\Qk㭻]«GOE:v/3SX|{N#wҷ;\ڻяB#`jU f*! 쵑\0T{߆`raPM.3]gCڦantaIȡUe$39sUW#Z,^(3xq/-*YFO?7h8$c]k`H lC'c`!O[@\IWË&P7 p@QcVDC=#(c8^MzI@&oAo?kC 0k=cLϏFR*XCh|ZG b|K#$^g[V@ \mˌ8p4bwU:RfrLh&KǙ1@pW|XR2Tt.xˀtHBeP<Зs-$\Z`"ƇP tvP_vg 4c|nYw$p[]>F~οkzl+ hM7q@;Jk o-@XHVKb~*Y<2#ۅltя`- :'e%l,a W q)A!dMD~>tvo;w @.y=-)G0|pDW1.3(6a}y6#@4׎'MNG7=XwW!\N(LI$,r.p1jކD1vfE|d" C SخoͤB9~>bĽu]R`U}0e)qU` "U`>Ƥ*V0p%>}#ʽz zxBxOmO_qH;N1]0&7=f#oƳ_ D&ojbLJ7w 6Iޥ!Jt̩H@jY~ wЧ%!6B1&M>gELY/Ɂ{:KQ]`0M$|q\po0 5Pu Ƴ~VZ䨢V/)$;1_ťH'bqZ,l`c*s6Ѐ8Mˍ9:Wv?$s`D.X*ŐXɖ9|8"T0ځ4 VIb-| =ۧ$\${*)`M#,Cj|6w4Ō{Aat/ann0BEGsm:ҥːԧpZ^6Tsk0'u+X;$R2Ii%lcב'ϑ.&.sb㣐 e-gzb#MW9RJn6k溜9j#Zk7hü zާH{Q" !$7h|4NBYCx/юV-UDx8\HW3C  P2Y.ci%% Lj*~hRzIõFz c'SG>2 "y1_F6ܤ^Xs/O,HM3S8G/q_}2ab uaý3=tLSA'}.qAd3Dq̗7ajFExUCEF7B3=pmHr\ ֞4Qqa%_S=ü:|EӃ;'4((a]ԅ8 GwasW7IƉ e祣;+hVR?];}mXi*1H%%Hߢ{xdVE>sw~NayQ% !;&(iϟI?S(ELD*t_5t*vG+2[;ˢU=0 Z{ڢZE쬠o71 r!6~kѢoke*4+F qX=3)7Uvj* vFr}Q]e~~O?h؂l{Uyu݋ޫBNI(.СS/;-܄w6 pC-dq3 w8t{J%؉$@z.'=0@\>"z=)zS1*eTzvgYM[`ώO."Jۏ~y&0aUVoU/0we{T03_'Cҁh ye2bC!CA96pkga N+Ʒk].fƶ@ T5ybH\\"U}]WKw,>?>鿵6=|ڲ~z=zT?jM:[lG1'@k%<Ec{)"Cw^~xKSI|b1=-lNax|3RrA?C~_f_^-珮M܁uln^X !'?jʻ{7ݽގK| TFD_婂pu|5GOAN.7ѸBdRrPl3k7y4$A{;cy]aG0KP*p%Dnh=.zLokNz̀x[:2 H~ 0"CѓS2;)v Ro-#D /D׷^^l#63ƩϜYF;6+hϪD}82Xe+ :|BZnCw,X5ϲU޽bh*1,8M={~Au (}U+ylfxSQ/nT  _y4C'/O8݇zl9Q|+bס-r0݁hv(UX W{I$0G_åh="#ğ$M!#oQS_er]19W7aхӕ.ZD$0)1P`t$ v`H 3xgA4'  1bkq./S-XTWo#OV*[:FPQ@&^#~O F{./8&vE6dkbf³% 1/L $ĄOj.Z}PjGZ757"nIv&dQK"=!e4^>qC;NrIj=ĔudH_p RRK?@SI&i|CIXmD,sWw>Ocn-HHNl!a08H7Kn} Vf-`9@+tE8:i_j y> pCbbi] R!]R"n|PIʀ ke~ ݣ䃣.?>>ԟ̡yO"oY9bhFA)CGʀ|h* nzo%XՙwA]G&~bt1KD?螒zjBUSapON_…ޒO(4V`hHFл"~X ZCPV\)vfL]K\D-q]Tu| IC*=*zڙ/:~Y0FLB-X!h~7̼ T#Y^ ګ"^̓`K(עwfnp]h5?& 9EyPx30,ݪV{W@̿C|@}z% y&Rh.%byXDWKbׯyf0rW\CCL<||QO] p6??~Dvi{poaV)=WHۨ3um![0\< gEBj=GijQ%:| ^K/mU$lD;/L:ti6+PfY+Җ֖XutzF>3?,B>^떕IM)g[[ 9x' Юv}C2~"ivi76$8,a,6yq/B _/OZna{- 0jzҭd>ߌ!\ٵ1cL02x!C]u,gnYomK"rȪFcqq m .ʋ&sAcY.c'j:j>J)KVn̨xlTytg<2cr7"bOS'qΘAnZ%wZIpqTqڹ\b_NI\G̉=Q۠(1]Z!T=PtZd"̼X^{7`="MPqah0`ڟb>-%kc.&,Y@6Y Y-L?f3.GCvYEƦ{R]ͬКfZt8 >·x$˗ܗXԯb:u! zDg0540#ᥠ.uHlYYUrAy} Ed[0ɄM tP\W+T lŪNcIrvŮi(T,@2XY 7.mB#fD2M.rxpQH7@h%rYދMB YpKU(r~T%@|9.n nhk퍙t<>ڧ> __z.?#(C LLMR cAd͍&̽՞lE?d& ?Vedq!*YT1؋Y@{2oIп I*aֽyOw`5*Qrk9cB@s  r{RM$gMd`ۿF.]ċQ'1Sh8 Tϖ4wTqaN0'څ[Ϛҩ"iMD 0Mkb{R58L^ȒaL3}=Dlf.sOB6슈jMш]mK?u vb]a(!P{ESpCF @I4:*Y{#o@}_Rz`]"FQFJb9.|huo-k?~@`qu CX7o,q8{ bdpͥ7)hr Hjrj1-y,(JNqwMzç $_ѮџXWѤoz>ylb`훔|'c3#ڪ nXuH~ޖ{kWmS@6;P;jWxsŵw_c~DV lj/$$-skiѦ Z5=18CiQ&2k9vga! va ݽ [ӥCtR Ik'$L[`MZ"Цa9Q.QAbN:!q s \4Fgv%o! v_PNWQ/1mm`SA=Am#AվR(:ŜG$Apهۤ'Lh焃xFP3( De!2fbTLZA KRB<ܶ= ~~6RBǝ Nmb$* sI7<(!5>CD.*>6𨢸`WwnsB ^J> !׆_f/T#UWB`-Y|CTσ]tPNS6@KqrP(w5e}+!| ɖq0񰄅UpJKRN.P]zٳnBNO؅6Ua%Z#&=ӣ p^])g< ܱmD| Tk(>YԷXV`x|&=ڑ@IO-HgYB"jm&5 JE*$^/O3Ů> =8-8{ wgV^hi]\i]DZbeq*斵ćYiX2tzcbpE:}65OCwyصpU~$0mx(jQ8ɩbh}Eŭ3> !H^ K&yC\Lq(LۜjM/M7^TǼ { #~,."!50F!t6˽GD,# aFbP* ܽ`OcsbZRoAf9>BV-9.È7r\Df);v/g0-U [,!ʠ SObxJU'a"ߺI8́IN*,HI~ ^Wϩ{}fD_>YbǷ0pxDlt:3( 1v<\ZIF[D7Ϛ+HAxR!?¡x},iICK^.A 7W  ۆp?/X[y13n@v`M{?vJP*SG q2 ƿ!E~ۿZbw@L !HQ+S,3>E8d#K$Fo$jQ%+#DzM!E%3v իsUbZG=Ɂ5,fK%kob48 r V8]H—C=ς[i HFC,fAڬ0y -X;091.Ӛ; ,$4GoUE=C#zd ]{6 $wӹh``PklA*b$EV8 g ϵYm,FbB5t'ѕI Ivb.AnJSe^<+\ /E=K~БIqnpO}nxG v/Z|h`OK _/1ܼ E*$ԽB.o#ciW>*>?°.h/ g2%1l1GԪVΡ~m!$)Fy t7VpɐfD%_@vB$F8/s:%B.ݞ @K{Է˯ dZ[9 d6ߍ{c:HRYR} x-%`S @6FÄ=GvI;@&bqgzO+M<۫g^aL|YmR'B#Aj % #oEJicD0H a\vs=<czIf%K&72<V'1ߝqs*Z5g}j._~GE-2_^Jv&e򍃓0jp Y@ FyEp za g_2 [u%,ǭ|;vpfgOvMH3( &`෷k1bIM*Ai%|nкQ˟CY TC;=GP\.U)Gቆa~N
x)Af_2o Ou]= a|ϑK2\qQb Sx~g^ñ%AqdZ8 6KP$~q, Xx lQ5qZmuxW.,=.g`d^1*%} %‰:;5|j&&,ķ[< ']n5pPAt~bqjlESlp\Hn}g Yު Ogf&֗-ë"W{52ovTW(|l.?BZ5>-f`9w{zd ff.)qt.LpZ~IN O6ajT:۴ zxﷃj,}I:m:j*!dx(^(X7~67c_z0<*pP@N% B~h*BɁPƟ,8tmjvY(=I/"m ,c7ؐ&<559Um_~5m:VWA5rnzn, K5PoE%?>X_Pov${vUqWh(?"0,>Jr bU0@&N"L^ Ǽ}|>/,!z^<#2ߚ".07+SỡN$gsX *_ R(ஶ.\#KD>GK._!ͫ[tړ ]@U@~ӷf#]H>;կf6䪊c?}ֱac|ܿ'U\* Y{8J|칹"؉`5N|˽V:/+ukaSbϮ.5'ri>~Sɒ&\s 7mvjzOo_Pk/~h (9!r2ŏ39l87c ~k襰y̵!w@I(XaPS>j YȡA 1㎎;(đ 42vSw}m02oy=0FwQEu~S`Qj2FP![$s* O5nͣpH@e+-)gH4wR 0|c($\X"tWI/G_U yi#k~ w1nWK5 Y"I(.0Yxir7˥M5d|1p7l;L+۠˺!lB"OI~Hh1gWI m7dЕjֲ79 e%r$EMJ hUӮ7ϼ=iUMB\(Ĉo ݞ"GbߝfEꧬ"JIvS߮.l}nJC쳦椥;!s¥NƩ d3`>Zo%B=2NJ|g_pq.\)M8rܿnv_"5""K c_?ngO'KtlW*ǃ 'COzQ}$\g82 ,a0 f𠤹`:eW^Bj ES+vÍ22)⣼xKVEШzWCEk|OqC.30ޙ')4*L&Cy-LtS/݋QhfP /ۃ$6ɰPQ<0|q`X[},0!b-TGTKoz`!I{^[WSa>D4<+cmSs]cO}6@ O&@ 7"R:B ȝ>! PI^$gҧy%B]>|hR;E.!*<q/4࿴VKtW ?=9(>KvmZuEV1秦+)`615lS:bKd*.&hRo]7ڷ2 /p<`\tM{?C(dT&kWmfl5*eOS[bC|rq5U㯎ka$`[$iΚ#nHAQf*#Էުi6GE>B穈z텹'#ى-]>1Zc;膩6fVx awDA\ICQ":Ti44pY s L yaG=P&eȍ ܫ[Nv[Uۋm `8sY7 4bɯ*ًK=Pnxzg5u0|HYdsB*;d4ql8vUhWTthe\FJ"ܶ悜5~`4PYPڐ?0)$h  2wx=la۽p-kFI_i0/j~NF`l/\"#: Qx5)d;5Aʊ'XϣyH.G2+ aqC)G>Rhze 08*iՊ⣚ (U:.& 7]|MtoMCKvB6o fL>-nl "X8ڭ/+P5l ㅎTJK{` Qh$r) }\⒳!M 4L'PRXuBMח]mʔ$DJN'h f]޻>Cpz+Dž>)fj}GBC0鲝&$DTCrxޤ, _Y\YYo3 Q@\4ɓ!!]9m@IgβeЬo>LJ$m4J;dvihpnx@ѴQ|c)bRgaHbpO=mhr{\F ,BXR pC'8ў8Ɓ(v=f8QT1; vW,!VngN}&=>2P R@hZrXHg37( :bϾ ,%M$䨣3,~Mw0~^]v; DNC@V,/q: KΘCqi# n&Aw ԠTu*]45F݌o0kg76 CUZ▆b`w2>DՠH&%|tD1$L2|TQoǙR2nd~8R!5#~mܽ$0ֺ" 3:0ϦI-ByyxH8w!#Gd "RI/'Siu-E+-"jơujM2 7n~lFI?1`EbOi6o8 *.ӀŴ5CahN"hm<WE1Z p(AEY8_U5F*4l۫wW[x>T$꽨IVAx-?ap$YnWg'[L6e8mž? S67x(%vBv<0 ;>Jr.4jr{o=U{B\@G&TCӞN ? Mi)0$V$(uQQtV~a#Ϯ'yMEnxm0AFCj 6\q8mKՇc8HXMƴv~Xz`QYD-ϊ'ϊNN2 *9JWqkΡ?2z,PE.UL* @blTշy@HP@,1.SL~#_,02ABk2+Bg%ę>} },꾎-榷+0$̴V;ηď/;&7eP&Đ(&$Ui? btY>6٪X $Vl O5\k?ۣOD3q3+/.*$Sb J7WOLݍpKߚ/B(_8-QorV+{bz,屠x/ߏ^{ĥSbi.:L6Ӆϔ(HZpm=-*PN*P>@ri[#ݐeҮj(Qh.֚oB3@ TC DXA/#gp Tw*gnr 삑-"2dZAU1n)^_Aj` cLW/ؾ%ր~0/02r-@ <_kQ.O]KVm=# EM@!S6MZ/a, :PYU̗n25N?f/[ed$69>zrƂM|ٽNuTIHRZ%GJ(pP\(kpLC,XĊ'޽3gۣOWaAM8U6XR[z;kc>a*rg|pom6oƥ3×ÞT$T1@*PX8z~~8M\"%X@vzuiV&š{ZGc]t$%*gpl.Ю\ɟOW(Y+D͖"x|楨jV;&/TKh©x~| PA1{YaO.w:u~~Ņ, PCG/$U+qc=ǺaQ~D,qfmCL}`;'0Ӆ~CO _?g} +-MݿL, DYq̅֬t0b#BcS/,,n}#C8.C)6QDGs0JB'!.|E輅MCo~V/ QQY [k @9ۣ]ʟG?˔k(Ok=0܊NE2<]NA=#9dt>y/[/h~lۥe&oM( Y滍ϩPX w͠V؛¡1OM &Rj+q6iN>r2c}xdiIAǿ!r ] 7ZG@K+J”՗ kXMODoH~q3`OziѕIupycNH^IeI9 7jI4 i1M?t5؜`~2w86~1_뤸S/av@8Ql|Hϐ.2BÑVGsvܙUpGMXLs_  Q]HncR;44'.2oE|pWQ=wOIxY?>6(O%A 藘K̦AڱJĐKMGq ]$`B9{} =9;fܫˤ }0ԛ|Bu /]~{ҭLhr DEb*ED` x 0#ID\R]X^Bf4HCW=4b݊3[ 髹`lJ+e5VMNJ!LLg׼%lB(P D9ti3\9A&nDy\ƶ%0suҠL| w>lXET Zl&?> < FzxTuܠ1<.9:dDߜ!$ qxFkm&mq"n˂,&ҽ`; Wo+7;爛$ò?}M`Zb$t+[prp 4u?\anZnBO|K㫎sh(9FO6j S1/Zt)뻏z#z B&` - hx֭0o00ΰvPC@%%ӳ׍wمe(] !UD`ۛ$tpibqc9 ]QRg /c-hשoa6 8&@$s%VcWoX4s`ٺ֌oii՜O[(7b-K3*Zh7NQTuWIDyP-Ln aY6)v2eXFVm1yC/s#j=]ΌFV\h$X$ u#f7򺣱 %,4z !͚tW:0g1t{^^T۳>zK9x^[0=2“#2 .!UQۧ.hGH dh =z)cXgv4V%-l@zog򑜴t#aaH :F&K[=ERu<œ5\tϱ+aTHx s J =u bb/Oٿ|*ދ5c=fX jI6N#56k:J#.{>Vb; AV۷HRRnE_}$jΔU&&k)֡8`)Dd8ነ&TS¯,fV[,Y>L=8vkIJ#[t'rf8nwt5yP4o =*l2sHKwiww \~GXo |g SZ\/DzUɞ" =mBB /blAwJuV[#?o#;`̰S v~wOac'/ 6_|h'1Mǿ Mhv !҅U-P'j } $țϬLԄur|^^#8yL?(:_R/)ʹ>\ܧz{N⡊D|(N^g84TseS4sen+(+ע`m,@};LI!#DXN~TA/ 9I6 o] TF6 KK/lh#K["xͦ=(|d[o?ƋX R-T}|/3(("U~"1N&[!@TÃ&$ 0`v)EBĤa͚-N"(ubO^t~%=] Oe ?$=.[әmbf%qNC/Z3 # e,0_ 6E۾0 e8-nR"RkB)c T`32<«4< ݄$CA5 CLO^ Q& Cٍ 4,Tݾ«B F.4~*/#g$F}(g&5|P7l~eHA6խ0Ϳa9 F̮]bnS #eK?vbsҁZw8 O;JaCPcKc8>T/9!0+churKɸ*k~$aCԍ tuTEo*ԗ7ܩMf[_^`&}̱bI^.p2|h,< (!7ucM'*j2[!X%UBΌqdtaw58f r`>p}<ł/Y$,,NIat$ ("Jo$@}@W/B$.o2μ :|GVqm-¿K8B8%& JwpiTP}UHQygUX&LR g@UrQAԛeA/(X9$SU-`+2?ju%` bAZhb'1yFFBYnK gs3%f-p-[*GUg⅝>pEQ_Ը$CgPtSV(/ +8q(<3JL*1!bb,1'8'U/mt "#y[DnGɑKGͣu4FRPXƥ/[K|@Nnz> *t'Bܾpv T8զ]}gSCSo[aA/&0L8,Ԁ%)G(6^$E'Sx*G܇!)Oʖo5(wIHzVzu6Z3}8Q◅i|)'{i aaݳo0 4"] bLq!$>nNڡ#`\nL%Au {),5>>C9( -g1A)A6{~|@} ]z`H̅NWr>Z$&O"<w' nbRJpm*k`1~)qE)n{ Lzѷ ZlSXt#z )3rGخ (.CY'-óޘzbY0Hwd,G쾄3W BG9zHN*,ԁ5F ߧ?Ӫ..ZUHؿCU2kMqrөlD3@ ȇx! # H3+/>2T.wզnQ  /7u=j`A$<X>4_}P, rN`'K2 Os>@8gLyHYf$tAaOZ-L^s' R1KNȘxr FF iQ`•AxqF/*Qk隩.M$-Ȱq 0O}$eatw+} Z5/ qn^W;zJy ;8w u wRO¨Niwu5ASUU8]AHXh Nգ)s)&3 u r؉!LZ&%:5XݼCX0EY U]cj+J8^V WWof("{ؚ68|\Yb>E'n't6V'7f1y+ӣJB'p]%1rR5fPSV1O()~] c0s pѽU OmdR̵ 'JITRf>:UQrт3|o`uG"r",wѶp3 y˅Ϋ BIdM5*埚[<[iD ғG^7G#pַǽz~&MB$S^ Mr JlF}Qm]/A}Q~ gnd?F*U~Sv/!*WU  0ջmxmRF)+~ ;fm;wmRY!( h 1)Vݵ>bN:XE5*b^^ѫ@b6'&ڽu|7smJw#\,4D>!*6[dT%dN`؄U{gܛm߅*H9ģ7i ` }ۉA&T#)Fd)v6\џZj:u\K LZ M&lb"L= m4"޷]gg*niT}<@z H7O.%l'T]) Ɩ^]0=Eh +4 Yk6|a꺰 w+" kXП5f /3@uIL7D.P*l .&⣂T/oӻD!' SRt^/1f]5lz)^9&&.;N?&kAfT}-nakf\Vz+Ќ~{$' ߾$^OLuآFd 7ZơۃH*6ߌ|hRf4" ]P.KIyrBӃ5^mV kh5v!\p"#€.KmDp|[Kf6ny!:#A̖ڬxMCV>?[麿KpW`BO* H 7l-1;MiEJiZ!]:0URsU4̞BQL NK0kԉo0LO P僚dž;Z~?=s|{K8/ U0P'W:hXwMz ї!I!Pbr A0y#pXdX5 E-d; D 7_ i`/B%ATV8&(VCbz<&{?J$xԱ|$8ƣ_ђ8X@k}>Xg/*ۣO ҃ٺSWL&?풇&Շ\=u=g:u,pX/+.7hl\l&כpҕ$`į7JpI»2!" e9o|x#i{YE '|q2u@JE54eb[ïG;rDy*?o.+ `vt-gɫ;,IFJ|  bk;KAX]كz'ZJ8|ԍ6C&C(.e~&H_/'\B˲Rer={V1~Y:wAFP> ~8 C[B3LZB^bDu2 !"SG@7/!^g$P?Ց|ڵWۏ&k=d0~b*: ƃ4\[ v' }:z FzljetAv#Ldy_)Xj4y#n,Dg)!p;<-o%-HB.S}Wbx0] Q dc4ƍsuD\RH(θHqn/"܏U~#`vC[ɩJU|I̦@p &t*p?fU@4#՘tU˔ap'U VGf>=pf촾! UCyƴed ;/PJq6Ts(+X3eÉ- FT1T# d[ViFofɷav eaL1`SuS FV6B|+LFNsNCÇԓ;\~oE$$<>Z0Cs?9„4ZEڬ1ӿ}3Ef>ꬫɇ {yݺbJ#"&^i t N;JFI] qy3elF*VNa—yx*HdΒпiA0Gy- "1gs PWie <9$e(ܵ^K%/td(aD.g*&W5}HmK_!P1vN` ȃ3~,ˢ.4 d:иT w2V+%(2|n-_Z!gLwG{PY{ߦ߾})9J|u:^kHjDj#;D^mq`{Xuw;]\ XLjO5ډ0|;4;S@5r2 .%:"bsWiD̊rF.ENaBCǃѭM1Nz+ID`@~= D^ˌGv*,N/xKK"R<k0il6cr&$%cjfԅ[ LOYNr."$(!صjs{-,F3GngJkl./*B.Z\C.}sXzmS+څuD9"׾TŜIDATp5K-+އD`WAUpwr'RlPvR(TWe o{bZm8MW~z9Kt@Tp5P9&AE6Q J>Iu~sYt_z~s@ܺ"ޘ&l }?>P/ʏMz ZDM]]z2cVʸ Ibp<`{ '4rgc/u@Fusz2? :5髛 zF0TOŠ ڟM#<ÔwiX¶7$LqZITL59};!$nK1B‰~{< ~7°%XqD+Hp:k"1 ^2r_Ze-ƙ$~03Jr1߆EǍɇLϮo])F_.tva$ENIr~Hl&TtV2:<^"<\pEs g0o~@8Y#[[\ؼH8`j ܞOp֪MB %I%yv]DԮg[ĉ.BK>_o «PIP!ÁAG [NEṪ;:aFYkuvvT0j:; E^], R2R`B rSSILh]s D,Ҏɷ69Nطrr1.77Z.IհVZ _Gg z\=\|-f%R4r_BjV⬂ h!=Ǡ4Q4sBnC؛I'TW/w;=d }K*`Q=3 (tyR@r<7XvS/UՠD~jVkYc-Ժ4|xa&ԻO.\  /] F^eZn1heB|Z}0ʟh|ݾܴl7TOcl^):`[U^1MN[ oKRYU$Q'M6v.d0}Za$%^N1OfVcj G\*[eF{PL%Ra)qNW2C^eŨ(pc ƒw<Ԟ-I_F̔ʿHrw'< ,0*p>ZE޿UX+Ûηή?.sܱa9}BoP#qmŢ@gRYRVyհhYVHQ0zadg[/ pcLH2 v$Rsn"yh"Y:.9g!#TgmQoCSo1\L_KaƆX[Q5JC*]`Gvßڃ F%)cON3Z$DѮb/}C=84t 'ǣC. Z>:#!⠱bWa~oxc zGEdRv tR~!Y1=z\p̽oss? O݊?8J`itx IbP#=WWc9_VƥH;ʯ ,f?>uo/z/^?<13淾Pm0"6ϰi1'-ڏј鹐V,S?TB(-C툁^EiIqj@&8!wk8} Qw&nži72w(oXAق~}f!Wo\O76Eu7v?Toj!¾z ^Go?4A_=$pn|mZ-dԙф&VkJ$/[?-oDC צH|I}cֆSuIAVS&]=8[]4mE%O.6X]$e ,D!6˓x-v&d̬ U00K W ?e  x {^ʓ&q\okRj=Vmӄ. ;k Փ<P<4bIa]USpWY)dX j;XR0K ]8H Jw|󤻿T1/=zGe xmXAՄykկ u8T[?5|q^˥tQ:b֟}ѵM^4`H4HPUV(H̩o[K05-!GT$אNa] ԭIzg&g$4u{R&$*)HGH?q z2ak[Ԋxw >DF _*cX-*ޢmEImR$jarij4s)T^~pP- Ν2 Ac]xŐ 0TBIH\#%Oõ~5ބ56ZwЁG~ٖp3'dwzy3a2 ?z&p{I {i7܏TW]lX^~H7M %&*/?K8 "}ؔI/ u(}`~9hg7x[۹n ˕ӮDg_OF>|a=[j]C TjkS>Jk1 CKK%Yn3zbve082>旋|@+>Ex{dCi 'G$ lVWNb_4h9ٜh9|R^|xWxjbt79c}OA(/acqO9:+ RՁBVToo}IE:5s01bCHɉꑁk})H2ULXϳ6t`c_3d:c n\r}b]=7UП!Tn֘..HZSL++㽾/)qŻzSE("Jn*%-`=AxaNp9ç!'RD]\>.݅ ƀA>]"'Úm)acAwߟ"96 )^@39 d#u}3A~^c9^֣14BŇzJ%`g 넹P]2֨ N썣"HqdN[oͮ09ZEy*ԖTF>6hC@NhB]1%ǀ{t6?LͰ œ?B.煠[M>8k&"<,bSԛFG!<ܚUqyx\Bcxk +ʒGV=&4%--PYOg5 5YIJȺ/빕& U+^D`S±!Bh&TrfNB_R1̼9̶p<@=zdY!W]֋ަ4tJq1[GⰑ'nޚOR$$E?G۬]y J4q0Ch§l?D r^*IcoobxZUmܶŒPB 26#>`1x o}̽PIHq55QYi(ߓLR C%xnj;̧O XcճhrUpw=}%YS%tnVg4 Sr*TqU2in*MΩѧ"lD6\Ԁ^"--:c@+M[+H9KG}(=j\Wz䀙kA#I9~)uG}[fB|{> 7jݳ^=N嫟p :[hQsH$(*22o8 jQZ2.J\E^X[y~ѳ]\Cxrz-No՗0ۧΥ `*6-7v^v lM__YWvx VG0lC.z$ɵ*2~O %)vUB_OO[ "4$+1~mJ'|ki&5dFZtqX.CN&N.! =#ݝ].~lb~ 06hKvU dW }O(\6H -}`_[hn_K|ccZER%Rur~OB[BkF^慼dtkq`Mvv|[m֪Nf}R?–MK2/xМק| c]8l!EDώec]6th?}>֭/w uZDCoQv_$}WopL±e*ܭINA#Wvq:[P~Y.xA;Jn/ڇCdV, su?{c=s{o<0NHه]ւ(5H@tp1sNu  K )G , 5ߖC-#*l4SpX "G!oe1P/ȼ~!Se#^<9(6%WcE C[\kHeJ뾂 M0-R*ѳH܌v. @ }x,,coa z-$dgx8VX쳈n P^`'n)!^Kz>P[߲Na;\7a>'<wnҕ*#E>F%2:t8"6 6~=#/k+&A[= {{ \0CD'-A_ 8C|ࡐk-L:F P);; I4?uvIі"t ZFLdNՕBALWS!{r=?oڛW աAx(LBFh{A8C1JyYJ6.ϓH: @;3Yq(QErCאu=r?ws=f[_'AO nHB a4ޅm<{((+jqL+Gpb@],ȗʗ껕Ed/.%/&r|vwӎ7ۖdM)wp;64bUE7tSu3Y}]e^\`wA"O4,xGe1F 7_ĭ+VgQWZdj/ðO RT BIba5}ة&  FC,MsS}9r&^Hooˉr/n;&&K!H_yl7F>,$"FW㦸҄4c;扬C{`Qm 1\E䢍4hh]qAFCX_S/+9ln!E8L0$ f 8 cK `4a4U~̾քo% =4mPI@068KR캺^¨&BhP~ .LK~ UP3pWZ<@ov;H_q.Y? i` p 2|wb8_!4@>)F`Eho2׆9iA޽ gDX|a-p׳8Y*BxCW9|L`\.U8ZNjeq|źEoO s 3?(X20~%E08jmbbW AA>ߣD^ldlt@jbܹ &xɬaá{Ob\=4GJ"D*" !X)w.K\&ٗ@f*CS no߅J/_†3ɀ7 [)߮ԳIG&Cw᢫$1ir Ofpb~Ú X@u97pHEJMYU×(0h? #X1uԼ&.8va STiVYz"c>ٴصk0C102#ջίET+P,# '|r8w@KZ`P]r/U%> D~?[~542?넸&TJZ9T5P=;=5b1:}7eTO/4DXZ⨷֖;slyS5C'{C2Do%^ j]:V$uQzy:_e "N"a /ԱM{O 튂P=/(<+97,Pj*oC(Y VaؑJa.[r)P*= +f.^C1F ~3I_v2W{joK7?_7M |A*M"!lKiRh`Ԇj>[ԫG'n# m"ӽ ;1dڻb]^ )ė:E;nl G g!A1UC,~t7e0;# FTPOTAgIC9]B8_ 5'k8[VL4Nc WsH Kk:'}zE!s kyM* 2><R)E [:#9:G~2jKY&mYS?{>s>,u--opts AEϛuܬR [5,1ZW0i4!p4xji廟<$;1a'jΨ[+3WSB-oi:^6ad9L6+X ~Ytmt9#7z7z")7ڧ(q 4 JϯXOmKa+o՟Hp*C‡ZM¢HTfo06RbW*!/:6lÒW9K:ӝ%!S` >?ka> WBp/8% K_aYxiAY+J$PȰ*(tvcCz;'#!$ !i m;/\DcX%S.Q!O Xb2o H?Hnb2Ab-D]R/T|B! "EwPZ[Ey瞅 { Jb? N EUa"}ĩE/]N`<_5eCl"i0yҬu-csƞ9! .k4Jh!T +cܗZo/xx A[2[w.=l^omrϋZXzr5\ ys]W; j.i0^HŶ\ U{-l/ d[h&Cl~() >QS+Dz~8IeS]ԗ'(jkN"½C&a-Y} ^B) (NGԓ_ +27[\x| . X?}#Y7RV2c()mD;.)!xkM9?8Ֆȿ~ôp,"  [ 뽫7*^BKFȽvIC%"T"bnܓ)r-U9Uܶ]DB6axMLZSw A(}tW_D^2S,{88e=Vs|$p,u@W 1BNvs-QzoϤ9;ɷ~gs$d=oBBL0`SwWE,{npƣ .}=Tή n#3Cb'~ͽ&AΩcVvwh*7?:N3j>nM@S(s9 屉Fh(Aie8@CtB<W@YB~T;_>^ A{9 Fjv" `O<>eŠbMp/pCq{9{,|rqY]V&sĨ" S\\ȂO}b͘5Z|7͍lZNcY t6Tha5[i9xB0V͡1%\'s00l|,?(Wi蟄Y"@dBŹ "NvyRfCrXq?{bzF[{N9%fs. 2l?NCQ]9ox ga!Pt@ 32|u jvLB/| 6/z2B\ 2o1gٕ{}ܻg^ʰu%UGgD}{U.k .OG<΂Ft_'>zok,#Uam.rdeS,޳ Ƒ]eGNUqC:Ta6foAu$"LR;9,?ErBdhEy'*Z~ ƽ6ssx3;Lq~?ߟ_v 8SaW˝QfCN.0P^cHG]D_ykfs|*S-k)w] MAhB*r 1pjfUWNNG+׍[.2s7j&B4۠zB(d*3pS׀}n"lf W MC5`ļY!9؞4\f}e~? ;JVA{&{ok@SjY0K$?nNX`aj8a%J|CnCeK3'(˂ 6)vՈ x,pֽKL%hÙ%g%}c rÍ ^X댎oOx30u .a" hQ$CN !)~\sê>;n.H̲^z|p/uJaVjs7k[8ޭFlӂO=݂/FCDvFBS$ @ƈ' KfלPI $k ȵoq Ҹ,܅o̖/ 1 07}0~ 0|lqUE$?N-0^+˯wohzh8R?["wFs7\<$FI@t;Uۊces ?ⵘ0@dR)X 8x^"fuz\ ?Uo}iDPf<0V;LۖbO}ƣ})dU >ePFzC58jx lS;bHY<~*P9dH*A׋`(G41|GSbG= òJF#X}P4︚,~Xh")=EK*yRW»Rsh4u=RbWBmS1V@.ނH ׳HnjE·IRbTH:,8S&\!>^]Q7*wo&3[ ^TqPnoiCF.T K%r[MDqN9eK t6Ȫa;.BJh>9B~@# HiWXmV1rVA~\]0 ltwKR[DN6N3?P?y?"ڨ&N_<`|/m70H=n'T`q16# tѪV/奔+:֭p+~[>zMOo=0 M>LQlQZ25!6-7w (%ꊂousd_%ATO'4J>Je'^/ vSv,Sq K z/lj|p)Xevb{wTnYrIM.]",wh0Yk7^/}!>\*|ja}+2&%&72{b \zM03fbM>%xv}ia9@?V o,%BwC FXᩮ*ڡu%k^"ht&A'T/JmLy9M?9PBZQBM>{.9BSwo"@k[% !1-#N}.1a! #Xb|jKUe|#݇X{1ّg>J P9|Lpu0oaP+EB2y]M=}hnr׀[hGlEުx.j+m"2; [I1 E}(>gרϮnP»ǵD`?*™(>v8q~03}¬$h.BpZC/GC?u6@p<\YDݛmt Ђjj 4 X0jS/!4 u^gFSK&tף凟|Wt,1lt"/wT7؀(oZ"k20V[¨G 5}yH-@F;|lBYOv` ړr \&(.xjV VeZzDV[-Q0BxzT;iYFO 1-c:p[?| #:l2fSȇsa # 8iSB亞4 H[9`U͏x +R/pࡏ03$ n(8VѾy s򲀨*G/Cx"H;s%DuFkG@R?J넀345J)m.DX0\[mM%3{CիpFڪ>T+1sLGR|.ҙ$^=u`,H]X3.TGK5ԬSsLJaC4֦ w"F#5^MB_D;z|>O9s} @)u&Xi&RLҰ*d+z =Ĩj sUnP>ErJԁoPgќxbBh?ή N1̖?|PBN1V~842dgF}UפsatF+fa:z]ֲ]?F(03f/ U @wAFN$v><MsU ce56gW$oXj쫜ȃ%Yʢ+COW2>ROEDݾ +Uէ)~öfr%ԧ>Gl Q5B]>Ƚa!Jy /Yn8a{EHz/]NyS`p˥ﳥ1I iYM>`)3'~ j / fv_f_>|wɾ;,_iAK)Ye$/} !pģȫ-. KS@e^Ԁߵ)ae@Vq˷"ys|nR@,W7'M/'mӘ]2a_Tu|p1DT907_jJ;9bH9Z۟¼҅;"RC۝"JD_LX܂Q仏zǙ:W/EJL 4ڌ1{8v21@ט KϸDf|q_˷@h'OGACJGQSd\xa|D2!H -'(ч#YV*UeЄ[*q3Nԯ7)m@sa%3QdFNס7 ftA$p\Yj)[7ȥS7!_e[97xkc 59bҗ0N㌥{7 TƘInud21'0Nl&89+)qTSnL`ctrĦJTLR GnyxD%D W4G@LK~u̅-ap܏ħXٗfbvvGIaov~ש/׮+}@I">?:ztK=蛓q.J^G]Ǟ" [z"G-[bk_%kc`EVn7و." Y¡Ӑ7 >AQk׮r "hXOGCécss :w-ɒN)2D3|0JHz&_"A̽M0BE! γA&oaZJD=fYPb y-6z͎Ƿ%( "_&Mvbz?Ts , QT3@7tO17ĥ+E_>(z}W8UMg)KUAsH6펖럂SXe9JCA %j+2jD|z&w0pWq ޿[eʨc_C1%B繁0c%3;&1zj"DZf@_ψa`*TRQCPqR2%7 dBVØ^UmV:؈oVr[ 2 !eTX9h@S.E,b =t?I&D6oCDV5/ӱ* ) U]ݫGCaeٖ`@pDr\rr^]<(#QLqtp 1(?-gt /!!.Cy{q^gW(`iʧOԓ'4nWsLlEEbfz9o[_ ½HON;VAe- Xa(H=q2rbD0 O>Qq\O@/uB[GÛ 癪3oGA/r]s n.:0pr?TH?Gޒb2 Ra]bevCQ7z!ג߻ x,``W*ko:Jr:EN%|j^U^bb^W")V>/<0q&J涮۪ij;Kq `WKaԔbҧ]0BTԁrkϪw4Lpc_;EL1] v;47z1dH#xM] gF{t6Loc n5Y$zTw)57ߏB)33>!aOrB}zɭAjȖh͵7:W 2PkŒ-lZB/18cTdOEUpno>ݡ:z)&F&ًJ6Ϝ6'APx:~up3%wUtpHY%{=ňmnݓt̪P`K+?nWqƣww `f4{DEM=a6'䰧? !/k!"XP6!U]^b?K,uY2)}՟.A>*|-oK$ ,(vxBݿ|GD21Y|p|UyDlCBo{y>~ :NH>G ^.=Ʌh!?qŖkNy)5~&UDP3^t[%d]0ac{Ož2qUПp OC(ԐzoCGkRNTwQ lbs H$|,.]1墂QPhsH@@XFZ=,͕,QƳe^.% ȀR5xwТ ]PC{$#a+AO`E;G%5,=Nº %yz`jeL 'D٢kS9X 07tݍ-ro}sAz[J5 t0cƽuV#%qw=֖d苆p/k 7 ~6p ; *fJ}wqP@Ƃ})N ,ȄArxeέ 4Fkk!BV׬7g~Bڊ}eYm_=jAp:uF[YzȴUinߡi^DDŎ8*Fl &YgQwA & 0S.CO"'hA÷Mqvo¡"'YJŗ=:q*h~tw2/mn߂0p`)֋}8-`UU-fH6%"+< Ls)[Ur\hXYAc p!.,@G(zƗZW"^9cr@KcI 1~7ї5.<}L>:KqrR8}Y!EQrԐX byD 1i8y<>ŀX:AO qyy /}Yr]SVBg߶o5^ܗN/¨qGDž97fY BRl%c*#), (a/=$x6ʘ7=ǀ2P!@Aó~Ʒ.{#0?MqmȆY1 ߰b(x k}~[ {'7@ݤQBZXO}WFMm/iLI_7n5RMK&f!ݫ2|ʂ)Ԯ/}4 ƥ'48y~l&…&#V&4Mo,puf"okXrBp OfԷÜ9S(/mF(]Xan\ k[p sd{W1o+| U?"b Y&dKۿ:Sy!'Tx&#!ǎMxᙽǃF Pg6'S#XTO`Ur`=tn|Sqi'ǷR 1؜1wǥ-0eP$ݵAHC4:Ы9p@ٙǫ-df.SH[66 p ^sLn[߼^ܷH ,Jn7(u=k`4.&2(kHZөY~51G:"~b꥾b~TUhx;V1zw}O`{Fy|!U_j+DR#*QrOIcTΚ-LmxO16  !ln_z|[g!Ǎp2\n Tx8C8V[ʰ\*`&,Œ"ׇ+BzelĠ@B]0uvRfl4(߳PV(4 DhM0, r~L]&_ËXE*mc#~)]!y):Xp Gq Ǜqg[P g "w𷚺X:qne8" ݇_h* ;YXs 'CUdLFWKFErsVBņ.:룊 =NT1+ !e*š]OMdӓ.}8M"1tcfѬNeM-[f7n_9T"(J[߱v{6Fw DbI*AÆ[! 1vx?"ZM"ϮNse x7n5x̵@ ]N{Z8!a6z* CWib"RokCRUH42,:ת[:pƭqA\*\?f[Ԑdhl/p`^ISR%1. IOm lE=C`iH_ CZhBm-,/M拾`:dW%hD6PqD\s2]饲ۮ_+2ѻVy% D27  |w,E:(x$Ǵ>qᓑKhV wDbBfR aER[/xS w'p4Ļ'o7`RP'XawJWœH<>~qƃv31'TlOe%֦5ūSK9Q~SI_:]V>3 טEFG-ߎ$Pnvv3]סZa#Z8*i;?'q+g|C|:"e/SW^Σ`ҍ1gD {yQtea OR4]N%S6/$Ԙo#`e 9)݁&Bd3z2߂@XvMo^7Dy`bI_kVX,$r hҼ¦( f7UpXh7[X|vHgX/(-,_'TTB@䆛=*EHiG.rQĆ*2|mO+\9}n >"6ʐ{2 B-Г!w]魋4Jo1<$` Uy=?&a+i[sckL'֛Gq3dBē?IԵА228X:Qqo7 Kਫ=P'GztFcB^4;mix As'^T umoU VWBCF0!o.QW|ZlmԪR8_|C*_44cUv JCFa7!{a#yqv~I&& 75[_pi6_؉5 g:L5Pv,ex5&W3rWO1 "F=3nWGe~C .VlA"Tfz2r:(a]`(Bz~pa!2Ư.o[TU5PQ;^F.=`2F( SpoayDq]eAutS0#n!*x1.1 O} ]Lu1rH7ŏ3۩KFO9&ośy8)BLwa3)^Җ+Xl˛=t(nGe~j!y4HxM)g rlK6J[0+/?ϫ.B%.7@Vy1Eq*DJ-%XBNjq GT$2Xne;K1(͈U{ d0REpCi'g_[Ym.$Y[x«EQ\yž́_!bD AA^bKWXkS<+ kA~ՐsTDS k 줰r"GRI )6tgg#fn&db?ݽV- Her C^_VQ6.V"&OXv^Tp fnL*n8[`Ph(Xc 5U&(j3("3}ǎ :w@;~R$ٞo'Fט5U*{7"RU0Ji(ߡ]r-^z޽E/tX`o4@Qcz ΍yւL(]aսb)5h L'УIBb"ț9EkY:?Fqs"cA8"H.L.FkkAϸ%!44*Ic,CWn@&Ov7xSz0c~DAFxx >MGhb䫙Čr(v臡E4@/şhs $l G|,LA]xt[.f Uqk݅4iY;KSDXyB7oՃ*z?j6KL!IkӮ]~յ6-jٳdQS A)?56ӂZj,.ܻ0anh:XdN@s"ˏD;v~w^ nʨf8ݽ=>B G|GKp]I'OK3Gi3 Ф+qHn{rKd;e4>ᮄBs;NC!l@*!}'Nvlg71j%^W%W>w% =T9CᐃTKh~~m[0 KqqW2-OQWDQpfGaG Q, .*4|C4!,]hL`HK1zcXgW2[3+G#uB /C@y1;i:%}uPu*\%S˵ EgD[bմNp@sLh:3LtGcZȏr 40r!jd("}? c D̸DJ/'ۨ) ΠB ĸɡ F'tF*wG\a_f1*?=N:ݡrx}'mFEo`HS]lJҳO?΢a/:޾./3P{RpzjE*H2X2axw mUy6R8q=Z.Hɺpڪ}Ԧ huH*fG4Wwh( 0<\ILWDf!~ߩ~>R[6Yg$.?fX @h^>jf>?Xsַ0Kl[dE')T'𜉐Y Q!Faҫnd:Sϥ0X6?)=gn+DDUpeG%lc %c"\}H8[pΧEO0ùk}7m銂YW`OUBZؽJVtpϛf Yh[x?!޵EY# /K%|+pժUk&q^3=K#x_SS.uqDMx?1,zpRo I$ +u^=m7Tڇ-2 )/˶ )`nMyC̳:n+hP?o5dr--'&Էky( CAavF]}$ھgxC AHd ^ -iRQ7=&W(_Oulm# } $p` :)]c_m b6S$>:* GhP/8@ x.a7TQj~$} pWz7;`=Z1ߨ%9zq~^sT[p;;S^_՟~C%\ W;W3v/G bX{Na}8å]jUkB&>jzNi)6#hdxuU *s4^֢F%8 ۇ9 hf8&B`z>uĸBah* faO&h¼Dg) 'I8`,p `=|ŵxBR5bc>OgI IPc2 %h%N?E8ݮ"`#\hF}z~醛Yp8|2oơK5J"-[/1^6/H'Qrp ~*Hmyhy=NEBЬ:% 7 XE uw-p3f*`;IB_#F0Ⱦ_!B&aXg&ՋgWo n}؅[DUCppH8h%N$wo׭7dLjzSp"\6ʏƈ7DbPiߘ=R;}wx1~*TPowWlnq gHL ra,7}%?÷]˳!Dݸu[06&p&KCHqAc%lhy;&σ1LzҬi?$oV_B84~0dsOH[ 4Hp/EihO]C\^zK*e&}5[񡗾4-% 79xlD8!PԾVy#.Ky_MTw/ơ](ZU PwnnťdO3/nd,neJTLy׺=MٗkYp$x `XU!~f:E5D6З ^‹8R:wvɆ KXQ]pAɹ`\]aZ{kX${* pL^;Dp ady[zxD]}} fBf0)+lmb<3#/9Y~kkn ! q)خ++`3gѐR’>u,BfdRIA?C4+kϥ58ˣIp~nxfዳ>u)VA+'F^I#M&ۥ JF8>^byn"9)䚍3Jz_//'g2h#n.*9 x Mz~W}]@E7-8,0 Yd=] EL&dY32 r9Tp:n)ѣ ۤ(m@+4H(Plw8#9% ,rzol2g gMe_L]eK=.A ŠWWMZڽYEE'梌`7mC#lX"5H;mc \p[I3͇^&Bxz{+TPcDVarkbYw5JL<׷-k:7eZo( Z"8 hjH9֥S-)T=]'.csT(L"+Z&!a{f0ѷ~S|EP.` f[I~kfKB#l?ySA.|0F Vj?|CtB ][E2m" ꜡s?HYG}>9Z63* JCJP%͇{Vs8ڋgؽ@q6_FڋSLN? /9LDw?* gDkL5TEx` S-%3C52KwRZgae1%3Ȣ7"GHhP2*& YXKoyi{xALqbqfaO2=-uL 6,?&] eRGCЈ~o|IlfS3%5D^WpL2n G*`uS3:!8Lmٵ>:/UV֦}M3 9YS'71g5Np(L{rvW<<ʠ'0 rG֭oj@Ey?j!?KOg{]:OQPAL>GnbYuΗkFЪp1Na܆lhM n~"Y%d#,YP JoW|uk3̾I\mV7|]cT A_tC[l ?W"$2ֈTe˷ukDnZ^7Q;TzЃ"kv<!]ꠚ.8!-3í3:@ގwò`rߣR(?`߅KТQk3bG%8!֟X94H$ g3TC=Cܭ/#━q] 4Ԕ_1)4o>=Fgcc[MNnĴ-eGך-?nҐw-=[Mso ?l!(B.ni& :݋BvX{=]HtYϒĔ 6]qq&Ȏ^˚$aO6E#r \e-M4ayգiɀanKiojЪ푀P9܂D#}#q,Ga=rWx;2.MĽ߈Z'cPoqL,G$.1(|já"o}Mm_^Z]1Z.'\>#Q2)gu(ɺ`s }h.N jE]J?UZK %-ww8[ݡ"զ b(ReKʾz@A7l |EˍIG(3+&Y!oc28<7+.[ɜ 0 9uVaF|r/JV& 2aKrrlYHNTb7yu?NG.8ΞXmXt 7n7cduUPӪz;͑8[;w(>ucG;xt^<ȒpUƪS˟s=t[?*39,(g9m+Sƽ^P]` #sp-]O"lUSwFA&4'hqD6'S-)7E NTDPbQ/7(g]Ea{tO`LEpO è]m~e!1 d{D+xF'&53o[8<㪄SuDģ1h@ج0@!7BT Oɨ|ABZ?gT (ךuW- Y&G?&v4qGM>RO:g@Ի9J x'D[\:>t&SO3 쁱7/'/|'.RvVa~d/myTJTE!L&)n<-?A \.˂wVeH3 '&89 T̔{RIڢ@@FӢ:cIUW;8O~/C6DdS2$=aN[84~T{Ӻ I/2bKBtEτԛRV-B_؅IJpz TfY]!<&]CqB#8Z=0X6qFM0/&aooŒ̕Ӯ)paFM/Zʲ_=M>‘'o T e,}FI%S?bspEx5`E.ˁ;w5yR10}q.256KĎ-Z{WBD#O6 R%HjɄЃjq~YO>]E]Ok<|7N? X(^p}'?9D2xFO;0Yqr&oW7~Ce"p0]G*Hq/G;#}Gv>V#^S9P~GZh`rEع69>c3,'y[1+ 嗹驷8 }y.Ef{joVl~LvWkG"ٯn?$2Ee` (LpG/џ!|Ce$N-1uk8yJA6NyJЗGH! U"N'5e꿌@"sڏɃ h,ܖp]Qtx4,CK9AQa̧c"Hqz` "6*̆ x vm\"Uy1})UHN& e!ʊ[tl𓻌eqxOA<ǪGHI6 b8*6hV@AX!D֪W>u UK񐾍Sűj BB|9 gS~(ɿ>$"aVetJH,g~9jopsSg?EktLv(# =S?[p!N/"j[NFR6bi&wB(V?Cv n,n~@LȱA&`ŐH6%oMy!Tؑͨ;8 \u\9Y8PӀ>6mxxnpQ1FR]. ,hIj62㢍f \12! h_n.‚<]S"zQ׮2Lϡ<6o%u-DXL[Zsu_.pkU;aCw-)2|8<:_Ww@Pl=!rsaoeVԃTƭT^%'.bw~% jw/a1(TbOlJ$}yfCB@ _|Y~ =SeAe* d_1D;|Wo댶m~޻DQYRD ̚5V:G)duõ{pP]z%H|k<巐xªbۄӢ,F''Hi*}A8]zZW'tp?}{a 3@Of^pgFR-<.;i> zaw'`5j,b XI\NVA:XtJv"$oa'3Q #~9u$R" [qOIJXf귐`udn"}4A c_P pw#VٸPk{<'4NƵ-qcV<-A.x.(K#HaT-d ^R1JmE,G+ W=r[ruqq 試 qmP.ዯ8K\A8*(%ǻ>뛗9fQgHq ݐnb|fx:-cQ?L|d/Z ui>x~fr5{a?_DbԿX%$Nr!80+\dq58(NC&JQJC>e Yu^aܛK۵$| Os7H`p@Fp|ugrˮS`|7M)gBb(bMV/corM^oSasn3„ƱG?2R %1̐#j>ckGJ<<>z0ftP$Cjզ$;^S`QPAd'\xH%3Mnh}96!J ( ۵s&>D =ۋ j "l)Pԋ ъpQ#{c(Tt,Cx.v1(֮^t-2r<)H$P)nx3uxxv)u8 ьF?nğ?? ՞N&#BUsoPO};oS>Y-L$jX̱)=| V_xZUi=?xL߈{h>PNVX6g;Av|bYIz@̭iވl/w=,KASĹ̠8@ok^>v /B]H.tSk&RLa>K.(}k׃zo!68b>zQe,Oͳ] \,:xcsq Yc[T$A#)<l붠#61ȌC"!#}HeHwC1,dA'̧&H[ÕdzLC^졅B)=| ?U'ǐ-u!Ѐ~~ƧK-:Ӈ"&#ag0߆gG6&nr3ǨK :Dv@I't*«M6ǴdCKb~[Z@}'[@A#Rrh)l *z`l S7q/ӣa% (z["v s.1KurmHVϿR̮b*.Ӊ85$BcoªӖPzN wMzsfqFf *zp->$IrKU@ .+u` Qx7GA!:ӟBSsI8$wMp2:W]&xx1|?Xa]d0gȧ&!1 T/XќlaD}-IϽ~AfY^Du`]/*$zĢF]8VKO5KYhձ<܆LcF),EXdLԼ"F09>aИ0v!H!+)H6DEEK{[ƷRnXKVh\ u1@g6v8MMAw;fS^ '݇*Q!bre 7XmE%^=ɴlw҂ה9l~Px ^$Ӟ;;` 6)/6+on2;CHXDBf}PL}|xW q[xvtO 3FXښ!1iˢ!b:=Kq7T["І]VUB߶ձJѿ=#Q38by 1B5 #Jw\mYh4It 5\]yl F-1.T9|:JYo$34d~X?:5Kпwo^#:}D c < Ќ57 ǬoTjr C1 Zz4"`sLH@æK}{R\]?D0gJ?$7 Ѧ3,/BguTCطm—?3a9V"Kdo``6V ^~08 #ͨZ Xw]<R}+s0xCX̛<w=JJSBva5Te]3n*aԁջ{EY7kqriUR?/.BBWpCk0Rʂ4[%iSxփlMMX|Xn̓+ E{y fO< 'qqB'U`l*ܾU>?}|H'BӅ^NNs'q 2_"E!.OrF^5(=+u@@?`?1[9!QambCȋ$D n_!_xWCzHml~6UԱS} FBSpQ}{ &#guH ]6L 8U-v̨++}L0ާf8 I6]Y*Es~ ^T2NUB)j'tU *kBRMްL%N$5hPFwO# Ez՜DB7yjȗq1>wsq* 4p|_".,(+HZInm.?B%} Gq3oBOw@8DxDSan:&&kv#O4>U" +uEZQ5e{vK_WRH'n\}& s=e5$us:A ˸pƪXUOiD`B!0T[ooXfaH"XV/_z\=ԋh&U9amP[)!r+0uT\7ol4.'!Xp(J_ni]:cJKQMi~OQ^Eew >O1LrcgvXK0VEWsZ =TڛsK~s" Ud}4'aH![inҺcEѡbuȤw yeL=ơD;pQ\rKM&/yfM , */7v.F,!OÂGQ=DLEpCu?Ox9RO ?/h/MzK$^B^t[M!IC\$wu;f0;_orr{ fTXx0xښbV'+;ixA(i)䝃}O͋B{yY!lB"uAeX;<8\ѠU.*ѝ0I=(HC~8W^rAgFHY1 c<ɣ .2Da5)ҥ;idjzD%(-=yPҌW}i!XiYSqC7&hJʒ}9N1-B ݺ>fi&V`\^ ~ʡAx{EqK| V1 ܬ8'aLVJYBkmf\ zEP y׏URR9[E/wC_ mA6DuV5X։PGN; Xtqw1ckFbFH;%*}6Lf") Jg:rt\Mp|7m~ TC PɨŸi2J*FM={bHB ڍEَ.iOD@,M(j`v?5e `a VoSU9":oK_.cBࠊ,C5gY@tk;c>bv^_ aQ?{'hVBԋq=1]Aakϣt~ Y6Z~kҷ."XPxՙ/7[(8F5QK9n{'fR$!}їnCOlMOE%`?i4*PApPṴ޶lX=Pa6^ /ɞ!c$X'ɐFkikL d $3bk>Xv/`CU(w]OO[m"2P^]@ߦblXd~a.C[D6 X[I~iDϨ1qR f{:19s4 ;h@C}0;D!2W'l"܃^+v(Lϧk+gW=3 Bq4`7/iQMxpTO~{V@2gTMwTZb>H1c*a#z'Lo [t<+&#̤==0-vrüpQ5)<eJV5G}%Ѕٍ׮Pb&69chP*AYH`p }?.m SK\bV?2B'&YNͥ?GozeDI\ 4E< "B^F?[|?Gԕ 8 b`"%,{HĻ(5$|\1L--|ХsTA8R"{k6%le+,PC('{2v5.g_:{̪bfTDzS<(I 41@oW5D1=H*q&t['5!Kd`XF\JKȼ|=Q t!RPBE~+6Ey,@, ʈHUݹ N1 9lXpq{cl-]t@DPKԟ/=D"ol݇ujse&r\f|u;Ô6z"!OfJaHwO3t:z|)4&nʒDd=T[j͠4K3 oxFSCkgd Z>Ɲ Ü`HL\ܛ Hk1g<:X k1=23/ p^j tjї V=@f>woKbM]ԫp[XXLpЍo~@r-=A܈ JSÇ?0g 1(lTJ~`B9"6`.J2*NÇph.^:ཡmR-,Dq3'HpXEH$MX[}3 ^ .ThW/[tg4#y6@8UUHhmK/."O(p/KTv O4SrQ7z6#ϩw=~0/g!'a-83"le,ƛ+0˺xWߗ0 ~*Ѝpa&=GFLBiHwz~XԱ:FdwK ™.f4w79۬խDU8 ŌͱǸӞߕ `֟V )7~`Y(X7k!R4I,n`<,4>^ vE+ &2b1V+TR2ǭۏ-me1B#J_uWo7&UЅGÜe{7) B)b(xcϭ~S1ǹ\K "=6(}D\Y,;J7(d-) LiӄQ^৊ψ$w3?\3 zTG1 oΌTSϒ̃kCZG4NO{%l!#&xpzxRn~|Z|'l4p&U_~]6)D}Ia}wVw: ֤όzP4 n86w`*y؇k%F|Kn!kCO]χ>зpzP.JĻG0p]GHu2&cVY*YOpYbRVjK_-.]V^񖢊[Ň3j !qfIښ#\d I]{qT J[Oڲ lȿ]O襄$D_z}|jF%08?YMƽN$mZL< ɜ]@ a]rr}:{3 $ A‚Hx dn(Q`B8ʁ]_zNEY^Y`l~%Op,[eujU J10<;TG/o$q@~$U Q8ZEJVqcvz=N܉(2S2澠>5|t2&)[ڥwEx1~ iٯo2k״Oi+B9UM_ `/E%u|'@CGLP@9"E:^O'V4E0vT Gu&{9́]*&𞯾q$Jbpn&Hbe-9dI  ą,z-ef,7;~(c4mJ.c}XQf'>X._.W߸{~*؇d6Ue}z GtugPNbL򔦄GJr9yOǬV e({]݄ƻo؂T)zf}7 Rx)}(_ 8$:aZV¨5,rz`L3*fW0hﰮ)!o4駵M PǸ'#C/N_tKx|inLaHCKl_ BvÇ&jNa跈:x.Ys_xY5 /Mه!Jݪ*>^*R;G-^">{].Фp0Yŷ5qg]"qe9̫DS +&O!$Gå_NA=:܎`m<)OYoAfx_ #H# 8ĠQٴPvVuVMC4fG?78uw}]9|HaG a2wӷZ X,OF?:yS`,HC^ŷnT ™[=\&&m)ט<}>M\RǷ;{ʔʠnyW 0:]S\]4k]p\cݯ<߅_!50*]ݎE:9UXCjqC:/7 O̽Px*tx{|C!&uZ RXh{Rq9]dnNe!|x^i zҎ3 9Jlə;&$H Dg7Th0'ԼSpBCIzd$@I1^/!CrA[rB paG`7+:vzD/p1Y #(0ߩ.4saguݤVbPB`,*VCXWni@4?^fH͆GL(=8\9~f%.!J$(]ܽcqϲK[A' #SGa _.s.r8/̀q @NOjջuHcƸ F9?u#8IW ^`L:tWׄ@JS _ַ]f,z\PLCUx˝Qsx$NPVЕ?FT6zT{^8֭STvkyʋO:)BZMzb17)FL aO,oO>2 $5sC" VM|7/bV\M7=س:MJ$ asD_SQzSpA2ԝ E;G?ěBU2Uɨ*LH INa{jꑨ*v ⻙'>sl}3~f ğ9U3Ky3z܅ʕ KvŬKLbwA,P)jm.z CXHt2ƴڂV})]఑220妝["\7Nm'gPG/w=n˘,&.oM(b9_ڞ7#7Gaϲ*yV`1nbL' nD-98qZ>HR ٨b(U~0pQ"3Bs e&z>dPv #g>uNޮnNf[5"OnǨEcLa"bD8J}y󳱺+k=bnXr3[r -ɫة'$lR,8Iңˡ6uGZm9tޖ䬽9&a{nDXfՑ|u5\,3vb'޶4KxBS]Ws1Ąޚ9b`-܆P &Mx-Ej8{uRڄq%"ۋoIF؋S F%t]vs3b.$n, B} Ia7SLQ&F<{gk, >4]x:zu:kf@́P돏LK'6\ەCTI\vlGXI8UăK1ȂJ5)5|s"6ǻ{ԵoGV\XLCxR`#c܃3yI-Z8 ee0vC" ZxE`SRJ".;sw/Ews!޽0#ׁK$5㢏Юŗ?v [P,8I=DVA8osMf tv'YLv7%挪jZC^! PH]$+~fh jK:*& =TC8 t׷H%ÇAqukox/qL{vâF|?/X.YʍFWe8pSx+ V̭WSGX-w3aPN>Pþ6GQr0n,HQ0=u#M.Xxt5ۢ#]tOW)5bĖ ED[ӓShGG̤nEAt$but߬]rpLHux$ !x-#9ų" }]OE2ŻT#)xX3IY<z:Cg}Τg"Yl!?y3דl©nsIЙp"ǿgxF$bLjw-?;a$Trą#:7%5\6>-\DÆOm}xՇj|gwbG~gAp(SE8>R&9TC.X⤵KM/U4oFA}(ҘjfLFqtL-aTר g&/ofI0NUXrCG +#rI$$X0~Q[rb)ɄtJA-GS[qM~C(VQq tGCdכl"Gv1`!Y%ܛ7OZD>ެ vF]LapxwPXQ&7ICdn͇RQ &F4D [x>7-h  ԭ:H0`(cS/I'_-wI>$r9&7[_km9,U0O qm#nKF\ aJcBD8ylt+ 1Ȕ̠!"CALI'pm-ĔܘCq0@֢psrɟu$g`^ëb{1'h:e#E*CrDl̶;Jz$90zkVܻqx)1I05R}A;AnsS2=4ZХ..  sO&м:4;d _<-rz;UbeD%RPҦ_vx o"e7pKĒV{,@VT9*+:RҡՉF2q,OC59ɥxs)&D͇&O}߮ާY! 1vaݍd?KhOի!¡k׸,e- 䈪nEYϫRU84%>sgLbY OaA&|~~ͮ;]spr:2N[k諈g`qYz){1g l).}"{̶/A$zX̲OФoH0x 톔Z#q"Y#U)m?D1%v[>깷вM glWyАѳ{4uiKRpsQp}@>bQvh'KЗVz®S=!o=k+y T#zR}]b &0!Eh죳h͏ŷ 2\(ZLلBFo@|!qo>3b9[ky5 kM!+5mWmcCe& FP(#6!סXD!U+]sa4):NV|2&ՐaTцnt}s.1+O󽒄RQ\QII;y9L~I\ !@z1Y5Ng-'|xG d]3}ݫ@hXOV%zƋ~rzN23l<4I!hr2=a,IJ4뤏%r:P#o$i3j n%T .@U 1? 5Qi Q2`;zWaU3ڔY¼?㥈gC G#q$M:7q/i0ŽzQPݎ^tR "PءyD5u`cPەEl@q34u% LaywQߧ7.(rړ`U, SS|}= $>W'\hmWǼt[W  H3!-2wN>H[ jBR l}m[33JјLHY:-^ Itp0 t>Nb"7{ZڋVjCA]hSlD02DR(H#,]-M)H>w6}5OCУ>cr>pp4]YCt3q uqKW?gK+߂Tw_]߽j:v oO~W֍ _{Vd,G+|JG)QD/}~LvӒ` ,AEL _։ Gs{Tr2y+Ou/[䃧|pg D] g=,5 0Rч̩! DvvL*JcyߘY- >fr. ]1V3 9NB)ij~/)x^WG cYV0&of3"9!dsF"a9C}$3%"4؈ GYh 2)3{j6d= `1 EFMiazO:($q'8PE0~dy55̦['&7*kSۣRzW6_G58Y/٢/HzR2T!l>.B,B:/' J5:w[0&Qv/6^euN~mxbfgHi5.Ps1Y:3/acюwDX*R0FѪGY6b5)`MU{Ua)Xd/^c\aקB}4BEˡgEX>aIvq'#ΙIP SڥZ+)_q冑0hޚA7 nXuiNtf J"n x:[ {*S/ڣRoַLB:ԄvgqpDq. <]Ba\[p#_OnK$2d63ְ1HIfR߹ I^U78yS8l}Zx*AȟTPV!@BFfu 3 exAٺmrLoVD!`c T Kๆ)r+2&"B7 }9k" ,<]zb{ yB4'$_T]Hq @"1 81tb ֮MjAe'jfD^/BE$aT$2j{Bո&smv+C2o ?# b[x-^UCz܅*ZqdDȤ~VY$6|DPE 9"LH."нW;<{4d&p{4kk \4M/f<CLBJR+]5_x˗xHU)O5 7@яB$/1nc}*Eğ@UW)y|ي8a Tg? Eߩl&+.jpľe{kOz4n`סU:ܐ vC ]b:T?<ᄆgz:\A`$pNn0Q~ >nffQ'ji՘@݉hCYr8m .;0aC-0i3{J֔+\MLOCKϜBpp#~k_[?y y.i*>n(m/el G0"7v-/B {C;&Df'{g-S;Cآfb4)SiW&D6ȮEBlQ*"| b&6L2t@mw( R]"Iq3|T-#b:z-+S6AӊBB"]Cq]=x*/ƛC<{jx MϬ x)=+ʐ2*ۅPzS-o.IENDB`Carla-2.1/resources/bitmaps/background_noise2.png000066400000000000000000001702741364475620200221770ustar00rootroot00000000000000PNG  IHDRPLTE9@IUU@3*fF3tLUU f `qIINDw3jUPIbtj@Cy:@*q*==mNI$]U*3Y&f@s(k B@tRNS          / pHYs  IDATxk-GRU$9 p+P׳>"snlMZ93##gK}|~ϗ/~~ǿ/0~~s?p-?g|ᇹN5M];>ܻkgF|ߗk[ ]_g]9fv2k[~gaF5} 7~ F3x{-pp\Kj h㟾~3Ә '[_~3р>Wg,<K:\LD0ؙ6>lhh&],O> ͋|s;l/_$`3Yur\ćC6И03l `3kU/!3/~t))$#{yf' ~@κɪeW&y~] @#˓ _^1_Q6 4wQrL5ܜrφߡ*Pf;f_ߠd= 9WS턆fS;r@{ll}^c63w؀:؄1FVdhq1suL9zFh~i6F}B##1 aE@,kc%qVc{74XK2GhP}ƅƅ+4eBW/mP-XR1%Rә6* &9,,,4?ِ?8yCc=&@~vn}έl<^-~4HjPmh|33n\qsf$vaYͥ~x"=~qqq@cכIζ -A;W,&jhΛfC+{.}S(iL~Ɲ|gNrcFIe`Źv 4297.I06`Snh4Ղo2-5gqP1g9ɣcIn=qE? GN0sr[@s g3Ν^!˜pHE1p6n˖n!׌[ռ4oΙ12Ip>Gea&dNCLHB3*.y戭?*\+3iFcio &x;nxV929s~~rvncÀlP n/9ZBHҖCyb!lκz7fZ АDa0_6↲)yVHp4  : XLI0l&|q=TǜsR\[ &jŶd`{3@l%xˆ]ٙ{``P!EfS劮NÛu21W6gJ-2!l9WoPUFօ3JuNS`%6 !5@Cc50sqq !i8@t:$)} *(Rxe纒CxLjϫ;}ş$`C6 XH)ͦ- *Ÿ;t&IpLKhM,9:#6jB%hX9IO Μ6s~ 4YK64~_F!؀bM]/yxJY'mRPsE2% Is] LjJ >|enxf䄈zq5f{_h\h\hBSP-Oj.vgw)āSAz:2W(+yoaR-iMXϐ#|ْB" -~"ԅ=NOv:QYKWOI " 09G؞K9%'F&<'-.`~}J? +3~j/yFLfxT)3+IzL1J5Lk[^r$l7O1I6ʼnkq!A>K^H< SHoL!kWpئ`M0 0eF^ɔohh#!?g| 1QnS4;@xTJ 3KAՈ}2$ z 0`9/Ј[%FC9Iʔ(A~\ J` v|SV%I": J whhP74$g1cp(r&dXQ6`a#3Ƥz2%pF4 s'~ȃ @.S4z꒳]h6*U脆'4rnBrhIW f=4}lh% 6%f;H.4.4.4>A×/[^Ӑ(< g^l%@rT 75IВ@40qߠV=7t9&.XػP8I`\!jo)gzmK=@{iBA_Jo  9-GVJE;/4.4.4^f gC *܈E36\:' HI-kRI9߳&ED FgvIwgsl<9oNw>u}MIO9(f6k]h\h\hi9q(y4nhO3><>bR@YN##H=F W3tp,G_ -Y4$B99Wβ1i0! W CiT B8chBnf̑}g&@DA|oB`BsDC4r\rƥi7.iL:Ԝp6PM^_h\h\h|FKepc;C9PodK֐\w Ä @ uR1 ) H8mTpwmCPa-x *>Ǟ̀:eRВ (5o.<6*)VhJcBH rc6H/eR |7F|)AuI=p\h\h\h|i79NQ^(|Bѡ6HVF>[[(u4ZE %Ne$[ =ZV1<@z6Acz󓏥@#۹[/pOLbFnB2wRƁv+*#@neay~2UvS)QC)}"֖puQ`]h\h\h|(ɖeS֔aC C$F. 4 Y")I`#ocĦHssm$N؀-OsRO'h`Jhh8>-cBZc!37j'=!nEH؃q,%jT Si I1MTH vv13>K-uqq UЈ1F:I;x;nxB~|le "ŔtAo^U.s6%n:˗MH v+.Y6@HhpoDo ݾ@#?p[zC%jo74r4o6-κù`=\cR1q ]kPAkEITr/4.4.4^Lfyqu&Vz<pMb8@FhɖcPEhuyD='0hvF =8RAZ\Po`N٫ (\M֤[~>s畛($uMz]'̏41;)Skvqqvv>1|+|BNW.}lMidk*Nx|^Y*"bᦡ4|MmKhJ. UT¬1$wGl"4O *dqsn~s]4!OB 3#<aqcjTh)>'G z<;9c~q&*!G%9)ue/4.4.4^Ѯw;E0VhԶن0#{lh=ejXg^f"D;Ή HF]NO($hiTMA'+4v-#DlsYFoĈ(fNS\%#Dòeq >.4]v)|vJV8iY@[  *\Ө)ζiPU޾əJ#|ʖGʠ*NjI"dU čCoZۆnf zlhduؽ}!mBpDS@o lb6,V 1H}yȵD6RC}&|z|p=WGBBB48n ,{.$ 2CS0@Z%\C J!wIMmhx ЅU^oh:iNySnKEApG8-W$#,4"ߏ6m6R <,bΛ돠Rp}h $`B `gG4Adl K]W3B9H).gbő"3FV\lCʳhh2MӳI1n2d*B>NiVJI3BcWfbl`Y5ᕌ*\ߤa>>Bc4aMf8i$EmYq]h\h\hCy峵!2 &noną7,}CX1fj v[lG&ٚ'8ޙDx9KM92l>vv2]$w!jB 4G1lg9XYzҙYUB'esnH-3?Y<61]0r;2Ct Hr.1v Ni&4܏֒a=]Ji,cd$}u/\GWy߄M&6!EZMƄ#DݔNc3ko 9/9βS/7WIchF%4>m/a&wqλAD5AP$#ڌO9\~O`=>8 h\+('"4lATR3iAâi2OTη^C$ǴR'EA SK42&*BbP-|AKę:S0ZE jiɾp EcRp#Mَ6[ qJcl[~xs piW1B]>9&+HJ *Rk_=@si?Y(ииx%;)xpN>% !$kَ)H߇$w&l:ƕ tY=B8Ϧ/BpkS= Ew6\1*[d!Y AS6={=>L7+I =hi ʞτx8Ԓ!\ 74/4.4.4ޡх8):5"'57ܢ!lQJaIC?=N")G)""> ,ꝰbYp v׸vmWgK-OjFH0q_f«r⸦ 8s,㚹Ms@Ph wQ R->Nxv$Qms9o;92jc؟2Gd:sGGa`)TkV>Bии _!lH;1P%b˦Ÿ;h5vRcEv+*NڀνwEUr' ;j8A̸-a<<ڤ!|Щ.~ jR s'ޡ9U ;l4oz'h@H[tNdc\CcJdB{w$C*x'4v*Ua<7*z-:A73/5"gi4Sc@FC#"nQ{I'4bR<5;i'4<| ^h\h\h| :iڅaN ql ƵԹ 9m/tN!!hhdt[Ix5ݐаi 󳡁pƍMmrs j*c~Ki8f.E6]\\LCIB:{m[54$7fm@߁Fe$M$[݆M)FMi)[Z*3LR iV> 4hț[BJQ6>?BG7BРRM{g5٥ؾf.6n&߾V=}?{L71Wג߼i("B89q:gsI: ){QMΝ|qq6xV FLFѶM/vWqIh1re~n+/iD!Op~UL_MR&c`*Jb&*Ҧ$=1f3Mp4sRV,ͅ*>Y(lq@k +ͬ221`(o16|;pH\=W̕ee<;#qp߿]h\h\h|f*._Uj2niG,(MfxaV0H Z]]CKl+\ >H n3 *dԶqs&$ip͹yE,٤#`6)}%XӤl,x_S9VopeߴqqrsaTVi"/n4P`lꄆH0]fC,M&<.j_$sZh)!njf2. Gc_rpؼfP@ hVR |ItvL)D)gZ47<0]3 Z Re;op̹qm֛"C*$?s+u$8:g!{P({Lu8?-b|n8Ҥ1-F9!4dwCP{c)_h\h\h0Vqki5b˚M0ԋ4NS4Nb›S*ǟ0 T,w8MH7[x'7y8V"oXΙ<ο*-9i{xgl'[$-i,^ޟbW׿]h\h\hBh}^8ʔ/JjÄ M!fQ3< j^ u9Z'^<"AJHus} rs !yLa:Hc7gsp1vT̊KIZR|8 [~ZϰL Jd^1-r,b9!|WfOSp{BBB-CR'!FגTĻNXuaC62J>ȖқD&Ʉq%C:NZsVo+>;i74 cޖg^N4jMН5W~xpHʧ! F"D66uIptCNYE(\aȧw=}qq ^-bp+7 ɳT 7J3`l%/4Z8-4+v|-ƟΞZ+g9M&n!:ÐQO.}'\L+h&$+BՔ߆iM6{ $4Ae:' ,Fp. pm4wB\md9sN,UGQRPnۅƅƅ+4lgCB+OڎƕOPa4r-s[%\2(G!1!RLaaZQj׍r,V!xRasFBKdK@X{hH濈Z*u;$hQ|w5Ibm %-zBj0#0^R#iǯPǰm]|[/4.4.4>AC^4?Ӡ ŖAvÑ֥to4^SAGg{EequPEp R]zIE6=G=##Fᣌu-tlq4nD,0O{O7giԖa$@vDXаX]):]h\h\h|o7:mӅ$Hd+uf,B?EʒMvDR]gC>BJtJ;Zc_[N%P@@FJP& ~n K*fc3#8>b8v"VB!w0D{I{"cYo^h\h\hAC":XKxBeqxQK+Tg[k;9+߶i7"(gKiߌetSZ:y 4չP%F#Hk/eƧ3ObX ل y̦͂M!daA#ؙ ?ɚC)pR zTU*f0`b!X)Tx H ʼииx$S4M uDd1. 4!t 8c7Al Ng¤l 6qB {XoTW!r=*?)r̛H1c/4.4.4>ArM"-  ;d ⠘xҹЀF<(;iz;8TI i?&\uPSShrW6Z˦iV;mJЍ:()4<<)T~ *Fh0N{[\gB/CglKn|,!\wi XVcT< 874aDЁ邺b|Mͯ1)-ȜN 4bbHhĴo#5CȬLfHˣ {Bò"m03H'm)` !6EVqGt"pS.&T6x`̹iQ22MCisC h m^Rn/-@n-2h.loCgWHY1- UK,{FJT8sih9ʝ 6ڦ6(JO&lYy`e.)̥֤>Z,[Hug[ԧt ![2YD@E+$A5ݑqsDM}lR7l4ΦWBBBR4M8wV(F5 omB>o=?(i>L GlȞmVrݝ#9e׀#Z9sʰ$FZH'ؠ Փ$ɟ},Y&D曢dw à´"J,w !ؤv)|"0rqq8/|'d |:ATK( ."0ِ8c,c$ځe$'Ӑy[&4 `;ōn:%AhM]|3YN{I۴9{Cn2}G^0)م3v$ڥ[PN7 ! 9nnk wh$|i")Clw;zi%!vht e/k9x7eC tE^-{oLumR2K씟х4 s2tzNcS$y&!9gh`p `KV4kAqgn)d10,nA^Ӱ#݀1]h\h\hCI?4-F /r(/4zAofꠘ @CL$@I4<.,uNڴB~jhPim"{E]cOϒP6&R;;!yhCٔMH0=/I#y_&\29L98%q`0E} D4ӈ:WAC|\.Bq(XM%HVX@# ~Ͻ!'ؙl/_YfTl5 `(n97sM64LM-Izf,AtCSpі6M˼H#!w PK`6Ǎ EKYy7륹~%X^Y>I4 I!6U#nxL1nO[QܙT( A"674:wᦉ!6()h2~nxơlS0ƅƅ'ht ՙu׶m)ac 9l^gqVL!Y8=IΜUUj@9$BÚ,e^m;`'M/&"sJTD)vJSڔڗs7:̆npAp`iO 4"CFJjNvV!Vf3Jj ކd$vPfNO7f`*2`/HjB)PB2r+82 @W67I?ۛAKP̞#3 :X΂=-N ^Lw]nb,ȑ$%MǷ[plO ?>lof Y|7fn_3EH>a\Os0M|eFииxF^y.iZ6FJEs Ex>` :։:wkYDwK1AV|@9#ɿq~9IYg!Jqg⛤; P ;WM&߉ylvT]ruE?[dumF"p X׷ͫNA [hل h(ѿOhH6. sNwD$T:q)t~SwOhwϻD+|=[^߹{RB@w8"p0~CsRHh(Q( q? %GNAJYS֡T[Gohx{`NNB whpm^44ZۭO;@A]nsEnPةJMTMZk -&4nk3E!lgsC!IOy<~۠)xC:N$R&ikR 60L =tRBC*xBo7s8>C#{447l@m ;ΊBBB4|(}[sM* 74&4,khrn|Q)-!+ܯwh6/!LUrAk4qoCg>RL3#xw f+P |FhIbA6bS[4ܩ-q6ؾ.WOkv+Wz Wh(Nxu]\S~h#FjA2~'c>SBH_׻u":qBfYާG7g4$|Z9/@`yϣMȕy0LuF ^A[2~{q{)fo?i%-|Ϝ;ei欚hhcKX&eHGViJииx6tM'K9~l/EYTgۂZ^uưhސ^YMmd@Є׀"=Ę}>Јrox& [Mh@, jTqϕ wN m74LXj 1)vb *3W_gBBBI =Eztꌛ5&+~>[6SL sJIߎoR]l$L[ӛSَ⋗l26GCMS黄~HP\Dm?RpD*40bJ<~JxOW)fNI4#r3LvfgI]s7 vOh`df)H3ժa ߂F6 .nC#!SD2B_3`"ĊlqMhHl]|ùh|Z]f =%֠J۟Ӡs M]Q,-n"mEuiBmH|P\;Ӂϊ{NL&Lli`X"/$4O#8{谴ׁ fGt-z^3ᲯNY B#EbS~NOjD"e% q(fڳj 춹4! <*h*qb 4#s+2Aåhz-ewڀ"}Z@_ \9CZ$?g]#"ց-M|ÒLE.4.4.4[S,&GֺeOozzQg㔔so~Ts-mBj/w9}[ق`-b`]H4It1Xm5ɾ55flgD@mzT$FVܲG)A幕:MLCg sqq6]xiP$6l[oS"U^`-GiI&tAޥQF.9Q2Ff"А roYJMi~vlBs)#MYbBiBx2#ڍ}XlsYpwXN w$whH&43O[ق;41$?.-! 4Oi{N%\6&=|rϏ?,[d9wIxRWvs/_..v+z}>.4.4.4^KӡB)χռqh9pkihQ3?߄b XSdT$H!;7c`"ÖHO.FF .$峻yO*$:?{RC6hٍ hI;4 -H"P"?T/φqCr$aa~ b{p@ש7%ա~OՅƅƅ hpz]gg;TEP-It;lx$VSwgaT[6\|6@avm%4Y2⸰6qFicФKvEavm)gHhS@DQp#4Tx&I|6:.tp.!]eRyF@R.u whbP:H 3KI/lY(r _i.)ZCmL C'F[ƺ`rA8 mE*)hC; 4̀@#;V?b4"%#~JE"I!>:8S pܙn?HUÄ1} "cѾ ?lt1 ]=A4 TnxWFٞ H`n Wh3Da_BBBE9iUfXF=m]-=!r8~w9BlH .ejㆻ[.R%(nTIMUb,x3۲N6![%suurYBNSC:MC'FqZ`P:(jGcGp+vAииxIV`XBMl;FNт,I ˲ŕGzƅ`B'gAnYBA`;,Eg#s~:$),ՄD잦b lӮM@cРȌmN)3 `oY.+ :KpX&ntts;HO߃n10]77r]߃80- Nsst$XlX2 0@]5̉-hD`m}.؍|iJ ,L}ڮ nAlƹCBpeέ4f7 #|C#%LԘ!:>@cK@R!M]veNBI/Hb.%&pD 1uЀACBPu1>-k2=yBuaʔ ix~ LtÙdNqn8M؄ٞeYM4ϟqGf&4zy{+xkϾOwyu6mo5s\ݞP oW7_ Yelw18m)%M,K_{2`9p77"6 =tEsw>t$a5( EBƅע64 ő;kW y2F BDd!2a[.'פ9Nmй}?Hhroۀe`|:`Ŝkíg[5ܧ?%]7sH\ph?v߃9qʕKLQnp-EL}5NS4){@ ~5MitԐە` d ihDA tv-R+0g$@Nܦ, A1A *fh0k)ϜBCL%G)8n1wÄ;ZIvHyд7sߤC] 8(eJ@Jd`fH'|1`ƅƅ;4LJZ%hHD,Awec:!qilXy4b)M_ٙ8RZ}D>` LmdfuH6 Ț)0n ne=[tw6gf-ͷ~"IhHȔdͷTBTAh>l0@ʛov9f/.4.4.4~ oWYpd{37{;aOq0L6ن8imPeRp[G͟ ާ4j>sj~H@LzT7,f͹rl.*)MO BHS XvPFCJCd:k&Qnx"OGηpzFs-Rڛ+ɜ̉wT]6ERMژdииxF :qA9EZ:)#; ;.}L$r|y~-nd$ *>'esKy$עvž1Hy缜GI}$zܼ~ u^иx@[i.6W)b >pw :-B0M$cTI`q-喤Z%8/^^&7]7i5s]~058M42 ^l%.%Χ";i2g3?AyWXq34€YٔC(cf)2T {{ܘ3_h\h\hB#Egs6"#پ6 d!96 r  PVY$KuBA7l=>-f&5Ԍ;K9y7оKs~ϚH4 [DsV$GxP'v2Jćv}ua ^KwXC 4/4.4.4^!!EGА` UÓL6rAeQ06ijug xBC]o`9_~-NOs-75hZϴ76FrRI7Te4 ~BP̧fpCB# If{|]RFB!rRf`a#4p1/Nh=!57ב@BS$C42--[͆B nCZN7mgv'4"\焆2'42H Ҡ齅BVzJ9(=R}R3` W}T=o M+ vňNaOez$Ȼ^h\h\h|FA K74xZY a] m%#RSEqQ4Le]b 9m $&ihWweK(Ȓu: {xnMV 1feNix(Aa1%lG6J q64w6FyL)&Hp,av~\|T"@!ии8q'/d>+`tnۻۄ p ҥQH-@M3V)+rAB}l\AF̦5CGOW&<-n&o/9Fκ]4x11`9$lF:{ "0c[08R f'<Öԭx4}v=l 0\h\h\hR)3ܯvx;5ԗ˙`el%P BHSd{ .C}JǿM$_Inb!) 4bH`9QC:I4]؆!ʹzaQ'ٍDvA*ݲ{[dt˭sS J,f64AH/4.4.4>CC̄Ydkz~m7b;0TҼy[jr6S %;*)$$(d1Bx͸ʱbÀl [:*+ -֐Xn48[! :4( =#\uڙ&4460'l~˅ƅƅ+4`ynhAEeFJ~滻,TW`N[ '!VDt a`+YIZ`j(ݠڎbme~$7(,ᆷ|3H[xnmBnbuB 8P䣃F UXFe+Vޛ=`Db&XT$1e/4.4.4ޡJHlNXBKqTg/]RPnK5@ڋQ1oJR@ }ir'Br$9R [y d=4[3Ih)AYh 枻F&c4.yLsl^οٺ:3hj)H\xqq %ӐP /̀ + v)Pt~m#ڄudb~V]*BN2-Q` P{5i:%d9A/\9-ipD3LY8|J1-˨ H̘m1!lZ cb󋩚]1ٙ6`c ӊ3M6P]h\h\h@#S$)g'B:qpM#54SG Yi .[|S᝔ϟ tYDdy3~qq&z򲝡}HC.bw@3xpti< BPT֝pl:\ c8} 6 6%V1PpAM$l@@ʦsTEUI'6s_# )diH TH|hdN Sw ֝b\:ML_0鵅yChx\bMݴݾ@)tچѲ:l'XfY|[֡|d%v~4re]L"Sg$@&":7H0LH4ɸou$*FT9S`gS?w̄ !1~Գ)^MpҨBBB4h@i1d&ct9?e74^;L}F T9T$nqs oƷCHpr n)U0Gn0A/`; <3?Ϩ`j Y>%с?6]FB*PwCixs@dX\KhAՆ9HAmT wh4u@MNARe а tHOIw}wmjd6;+4*p>^c7戳}N!F/=o>>.ؤx^B4ZL&D:2td KɈZ^\iZl4G"N)6fҗ=h'c`)ՙ+2,R&lvIz RD#\"̌"ƌ"ݾcK{iSI ʊFF畀ΨY m8c @#Lof.'g r b H5~ٽ̽+510IąƅƅhZS&]cI߄ -"b:Ltaep6€@5R5s;E nңwpMԶd>=6SJں;oC'P6ĸ/4.4.4>A#>d,Bc ,`F8uoyY 糬T3Eײ״2䪝s"OTJIKi&VaV rYtNؒ-V@h` )ǼȺ1) i5Z6SLtְ< 9CzT'氂rO1Ɔm.4.4.4>A3o QgiN OeeӜ妰oi3ug]U ͸ L.?c$(w]f+kPٞEKyU h<)yKxUg7|C" ̦ҬeP!HX{6Umxo򍊴'lȉk=$Hh*#)/tIQon 3l!M"IdHmq(9hJ!ipnM ͜l|h . ΆF t[APmά yN7c 799Amap?:->A j#w477R&s_h"Dڛq[q7dA$5>-}}To '%ICQݏs˞ swR"6mH-OO49e="]~&N[glonB\hOmY[A ߍ9I)gv)7}8-Y?,.)6L@ф. ͵0} RJeJr>d9RΊ2Li3s(&wN~H07'"`K+̳2I-[UFF2durt-GPS<;i*?BBB4-tN2oǺnTiB^A࠭囁BLzƞ@3D\/odPBzgݚ-&4bU0VfQyCtqϢ|LsA1#6Bwrm5ۘyǬHflۆ44!UZfGa}<x ʻ6BBB4 iPIuRag-ɫ,4M}#YÒeKa>j\0RX@%zsFI4(.M674?oh2PdE֟64X rt4<_ 泫Ϧ%u[BqN%ASޯ#Q(xɅƅƅxi䷠10T6 7Bե-iQqg]$nfe,O[l6?D *ua:jC |f G:wKkq7GuጻeI\h\h\hCq,B)tzS 4-}yRUƍi&^o[cC1YMdĤ b.rةr=Pײ>\T|{z_S8ݠB5 d*4t P@$da&hҴ@cL@S$O %CI¦%)4LUe'+R:mܢ]w=   g!'DzkCke[@#i7#qָr,U1cpēģJwf~@#3̑ƕ,fl[jnbnT1zd$aF9p78@B< :fm VM _WBBBjM<3m qyٮlW&@iOl=pL1j_? RXX0ie1zNBa~@&?'UkYee1F;O' $6sLFXXKsZXˌұn,]BKryÊgs/ P c̺59cf`ڢаAT-lL @&#0Ųp"KyFnz-rb-9K;qZ"KE1M;AOR&R !eW  ~`!9bflCwm9jGC i.͇(ГNOۺU҉]B =ใ׻}NQGL*=`=|Ss>3:V: !kH.B#pmc4:n{}mmL(q 4 6mM"&eϫqqqٔz(n< hY;f 2_T 6" J Y$=#dc7HJHk'dž@xs@˧~ɔS 6%[Ƃ찘lPXv1ƚHƈBY}o~ y?Pκ3#-Q}9G: >ls>?q+Ѧ<~y9H>ииx)gaaɾ#t3[޷Ms0$ qV| 3phy!w:Dh1Gz$L8waW:s}\AE9)ag1B`^0/o (c\vǭ'5`rw̽&X9;ؠK:@<"w-5p!Dv[׹ииxFqMgBrrrÞ[ n072=xؗ2gH$uVKh-}tț1Ѕ'4Z`;u]2nooϖ9>|2^Y!&ބt'[v -8zoz}n Y Wh-/ݚlNIj0poxNh د^em~Y᝘C'/ 0`7sihhPe..נ:}|ɾLHc(jPees"s3AJ1#`'i9mM 4>IiL5؛M(oi֛Uииxӭ'h ut.N)ޡѥ(mD!fTm_*i'g92e&5 * S&@q7iqi-4ʤ2vނPms ԤO@ms4Z‚[A6iPED.|qq J\dAk(Fڼdԡ5-eo-(aR JCn͆B@d!93A5n4eNIPM&NLqo j PؓJU ۣ圛GG ^<C䱉 JqjCzru5oh s^sMI-G4.dpBBBeK<[lmDiJo7y=$41+{?knNaxϣY}V)}ϔYs(W#w,yygđ=?'~ииx &R6}nƦ6v#T(̘lE1k•E@K%aaF<=1R0<ڀYD)DwwȒ-=12>BWg5$ ݒ< X~GsdE.SҵVG[LI9? %n$mQCȎZ3˞d&\h\h\h4f!&57PFfL<Q;;?R~nˀ&hҶ xH!4vݲ 0@ch#$``B4dN,϶59#3'H ;r90HG@#ί0ۡ c25|Nvh%4}> apqqZlݚ 4H帙FT37gP,[בBHE0JAd/fHp vL 3Vpp\P5s£(?P?Fz bH%a@c$ți#s6{V퇁i#L7Lj i*cD>&91{BBB )R;YjPT Лx;4be\v Ni!qi;~6TR& 4'hX\pӠw5 ,1{LND 3n8[7N