From f65ec845a09e23560fab365e1cb7c5ca4bf66aab Mon Sep 17 00:00:00 2001 From: essej Date: Sat, 25 Feb 2023 21:45:09 -0500 Subject: [PATCH 01/16] fixed server reconnect bugs. added move of old misplaced files in dummy dir (soundboard, etc) on some platforms. updated version to 1.6.2. --- CMakeLists.txt | 4 +-- Source/SonobusPluginEditor.cpp | 51 ++++++++++++++++++------------- Source/SonobusPluginProcessor.cpp | 39 ++++++++++++++++++++++- Source/SonobusPluginProcessor.h | 2 ++ 4 files changed, 72 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cbe8e8e7..b3feb8a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,9 +36,9 @@ endif() # `project()` command. `project()` sets up some helpful variables that describe source/binary # directories, and the current project version. This is a standard CMake command. -project(SonoBus VERSION 1.6.1) +project(SonoBus VERSION 1.6.2) -set(BUILDVERSION 76) +set(BUILDVERSION 77) # If you've installed JUCE somehow (via a package manager, or directly using the CMake install diff --git a/Source/SonobusPluginEditor.cpp b/Source/SonobusPluginEditor.cpp index d5837afd..5557652f 100644 --- a/Source/SonobusPluginEditor.cpp +++ b/Source/SonobusPluginEditor.cpp @@ -3799,32 +3799,41 @@ void SonobusAudioProcessorEditor::handleAsyncUpdate() } - // now attempt to join group - if (ev.success) { - - if (currConnectionInfo.groupName.isNotEmpty()) { - - currConnectionInfo.timestamp = Time::getCurrentTime().toMilliseconds(); - processor.addRecentServerConnectionInfo(currConnectionInfo); - - processor.setWatchPublicGroups(false); - - processor.joinServerGroup(currConnectionInfo.groupName, currConnectionInfo.groupPassword, currConnectionInfo.groupIsPublic); + // we might already have autojoined a group, only attempt if we haven't + if (processor.getCurrentJoinedGroup().isEmpty()) { + + // now attempt to join group + if (ev.success) { + + if (currConnectionInfo.groupName.isNotEmpty()) { + + currConnectionInfo.timestamp = Time::getCurrentTime().toMilliseconds(); + processor.addRecentServerConnectionInfo(currConnectionInfo); + + processor.setWatchPublicGroups(false); + + processor.joinServerGroup(currConnectionInfo.groupName, currConnectionInfo.groupPassword, currConnectionInfo.groupIsPublic); + } + else { + // we've connected but have not specified group, assume we want to see public groups + processor.setWatchPublicGroups(true); + mConnectView->updatePublicGroups(); + } + + mConnectView->updateServerFieldsFromConnectionInfo(); + + //mChatView->addNewChatMessage(SBChatEvent(SBChatEvent::SystemType, "", "", "", "", statstr)); + } else { - // we've connected but have not specified group, assume we want to see public groups - processor.setWatchPublicGroups(true); - mConnectView->updatePublicGroups(); + // switch to group page + mConnectView->showActiveGroupTab(); } - - mConnectView->updateServerFieldsFromConnectionInfo(); - - //mChatView->addNewChatMessage(SBChatEvent(SBChatEvent::SystemType, "", "", "", "", statstr)); - } else { - // switch to group page - mConnectView->showActiveGroupTab(); + DBG("Already joined a group, update currConnectionInfo"); + currConnectionInfo.groupName = processor.getCurrentJoinedGroup(); + currConnectionInfo.userName = processor.getCurrentUsername(); } updateServerStatusLabel(statstr, false); diff --git a/Source/SonobusPluginProcessor.cpp b/Source/SonobusPluginProcessor.cpp index 5b08249a..7b7cf471 100644 --- a/Source/SonobusPluginProcessor.cpp +++ b/Source/SonobusPluginProcessor.cpp @@ -733,6 +733,8 @@ mState (*this, &mUndoManager, "SonoBusAoO", } } + + // use this to match our main app support dir PropertiesFile::Options options; options.applicationName = "SonoBus"; @@ -746,6 +748,8 @@ mState (*this, &mUndoManager, "SonoBusAoO", mSupportDir = options.getDefaultFile().getParentDirectory(); + + #if (JUCE_IOS) mDefaultRecordDir = URL(File::getSpecialLocation (File::userDocumentsDirectory)); if (mDefaultRecordDir.isLocalFile()) { @@ -835,6 +839,8 @@ mState (*this, &mUndoManager, "SonoBusAoO", } loadGlobalState(); + + moveOldMisplacedFiles(); } @@ -847,6 +853,37 @@ SonobusAudioProcessor::~SonobusAudioProcessor() cleanupAoo(); } +void SonobusAudioProcessor::moveOldMisplacedFiles() +{ + // old dummy mistake location + PropertiesFile::Options dummyoptions; + dummyoptions.applicationName = "dummy"; + dummyoptions.filenameSuffix = ".xml"; + dummyoptions.osxLibrarySubFolder = "Application Support/SonoBus"; + #if JUCE_LINUX + dummyoptions.folderName = "~/.config/sonobus"; + #else + dummyoptions.folderName = ""; + #endif + auto dummyloc = dummyoptions.getDefaultFile().getParentDirectory(); + + if (dummyloc.getFullPathName().contains("dummy") && dummyloc.exists()) { + // move any files from here into our real one... (and outside the iterator loop in case it gets mad) + std::vector tomove; + for (auto entry : RangedDirectoryIterator(dummyloc, false)) { + tomove.push_back(entry.getFile()); + } + for (auto & file : tomove) { + auto targfile = mSupportDir.getNonexistentChildFile(file.getFileNameWithoutExtension(), file.getFileExtension()); + if (file.moveFileTo(targfile)) { + DBG("Moving old misplaced file: " << file.getFullPathName() << " to: " << targfile.getFullPathName()); + } + } + } + +} + + void SonobusAudioProcessor::setUseSpecificUdpPort(int port) { mUseSpecificUdpPort = port; @@ -4073,7 +4110,7 @@ int32_t SonobusAudioProcessor::handleClientEvents(const aoo_event ** events, int if (e->result == 0){ DBG("Disconnected from server - " << String::fromUTF8(e->errormsg)); - if (mReconnectAfterServerLoss.get() && !mReconnectTimer.isTimerRunning()) { + if (mCurrentJoinedGroup.isNotEmpty() && mReconnectAfterServerLoss.get() && !mReconnectTimer.isTimerRunning()) { DBG("Starting reconnect timer"); mRecoveringFromServerLoss = true; mReconnectTimer.startTimer(1000); diff --git a/Source/SonobusPluginProcessor.h b/Source/SonobusPluginProcessor.h index dfa4e0dc..7cd646db 100644 --- a/Source/SonobusPluginProcessor.h +++ b/Source/SonobusPluginProcessor.h @@ -916,6 +916,8 @@ class SonobusAudioProcessor : public AudioProcessor, public AudioProcessorValue juce::var getAllLatInfo(); void sendReqLatInfoToAll(); + void moveOldMisplacedFiles(); + bool reconnectToMostRecent(); From 090fc8f82b9f4eec7d79463bea83f212906b6afc Mon Sep 17 00:00:00 2001 From: essej Date: Sat, 25 Feb 2023 22:03:45 -0500 Subject: [PATCH 02/16] updated snap version --- snap/snapcraft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 6eb44707..b9f59ccd 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -57,7 +57,7 @@ parts: plugin: cmake source: https://github.com/sonosaurus/sonobus.git #source: . - source-tag: '1.6.1' + source-tag: '1.6.2' # source-subdir: "Builds/LinuxMakefile" build-packages: - libjack-dev From 5801be25e0301c93520e8c09da26cb8f0d0d6106 Mon Sep 17 00:00:00 2001 From: essej Date: Sat, 25 Feb 2023 22:35:38 -0500 Subject: [PATCH 03/16] update mobile version numbers --- mobile/Builds/Android/app/CMakeLists.txt | 6 ++-- .../Android/app/src/main/AndroidManifest.xml | 4 +-- .../Builds/iOS/Info-AUv3_AppExtension.plist | 6 ++-- .../Builds/iOS/Info-Standalone_Plugin.plist | 6 ++-- .../iOS/SonoBus.xcodeproj/project.pbxproj | 32 +++++++++---------- mobile/JuceLibraryCode/JuceHeader.h | 4 +-- mobile/JuceLibraryCode/JucePluginDefines.h | 8 ++--- mobile/SonoBusMobile.jucer | 6 ++-- 8 files changed, 36 insertions(+), 36 deletions(-) diff --git a/mobile/Builds/Android/app/CMakeLists.txt b/mobile/Builds/Android/app/CMakeLists.txt index 01c3e573..644b4001 100644 --- a/mobile/Builds/Android/app/CMakeLists.txt +++ b/mobile/Builds/Android/app/CMakeLists.txt @@ -14,7 +14,7 @@ add_subdirectory (${OBOE_DIR} ./oboe) add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c") set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression") -add_definitions([[-DJUCE_ANDROID=1]] [[-DJUCE_ANDROID_API_VERSION=24]] [[-DJUCE_PUSH_NOTIFICATIONS=1]] [[-DJUCE_PUSH_NOTIFICATIONS_ACTIVITY="com/sonosaurus/sonobus/SonoBusActivity"]] [[-DJUCE_CONTENT_SHARING=1]] [[-DJUCE_ANDROID_GL_ES_VERSION_3_0=1]] [[-DJUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1]] [[-DSONOBUS_BUILD_VERSION="1.4.9-74"]] [[-DUSE_CODEC_OPUS=1]] [[-DAOO_TIMEFILTER_CHECK=0]] [[-DAOO_STATIC]] [[-DJUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE=0]] [[-DJUCE_ANDROID_ACTIVITY_OVERRIDE_CLASSNAME="com_sonosaurus_sonobus_SonoBusActivity"]] [[-DJUCE_ANDROID_ACTIVITY_OVERRIDE_CLASSPATH="com/sonosaurus/sonobus/SonoBusActivity"]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.6.1]] [[-DJUCE_APP_VERSION_HEX=0x10601]]) +add_definitions([[-DJUCE_ANDROID=1]] [[-DJUCE_ANDROID_API_VERSION=24]] [[-DJUCE_PUSH_NOTIFICATIONS=1]] [[-DJUCE_PUSH_NOTIFICATIONS_ACTIVITY="com/sonosaurus/sonobus/SonoBusActivity"]] [[-DJUCE_CONTENT_SHARING=1]] [[-DJUCE_ANDROID_GL_ES_VERSION_3_0=1]] [[-DJUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1]] [[-DSONOBUS_BUILD_VERSION="1.4.9-74"]] [[-DUSE_CODEC_OPUS=1]] [[-DAOO_TIMEFILTER_CHECK=0]] [[-DAOO_STATIC]] [[-DJUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE=0]] [[-DJUCE_ANDROID_ACTIVITY_OVERRIDE_CLASSNAME="com_sonosaurus_sonobus_SonoBusActivity"]] [[-DJUCE_ANDROID_ACTIVITY_OVERRIDE_CLASSPATH="com/sonosaurus/sonobus/SonoBusActivity"]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.6.2]] [[-DJUCE_APP_VERSION_HEX=0x10602]]) include_directories( AFTER "../../../JuceLibraryCode" @@ -30,7 +30,7 @@ if(JUCE_BUILD_CONFIGURATION MATCHES "DEBUG") "../../../../deps/android/${ANDROID_ABI}" ) - add_definitions([[-DJUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1]] [[-DSONOBUS_BUILD_VERSION="1.4.9-74"]] [[-DLOGLEVEL=2]] [[-DUSE_CODEC_OPUS=1]] [[-DAOO_TIMEFILTER_CHECK=0]] [[-DAOO_STATIC]] [[-DJUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE=0]] [[-DJUCE_ANDROID_ACTIVITY_OVERRIDE_CLASSNAME="com_sonosaurus_sonobus_SonoBusActivity"]] [[-DJUCE_ANDROID_ACTIVITY_OVERRIDE_CLASSPATH="com/sonosaurus/sonobus/SonoBusActivity"]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.6.1]] [[-DJUCE_APP_VERSION_HEX=0x10601]] [[-DDEBUG=1]] [[-D_DEBUG=1]]) + add_definitions([[-DJUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1]] [[-DSONOBUS_BUILD_VERSION="1.4.9-74"]] [[-DLOGLEVEL=2]] [[-DUSE_CODEC_OPUS=1]] [[-DAOO_TIMEFILTER_CHECK=0]] [[-DAOO_STATIC]] [[-DJUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE=0]] [[-DJUCE_ANDROID_ACTIVITY_OVERRIDE_CLASSNAME="com_sonosaurus_sonobus_SonoBusActivity"]] [[-DJUCE_ANDROID_ACTIVITY_OVERRIDE_CLASSPATH="com/sonosaurus/sonobus/SonoBusActivity"]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.6.2]] [[-DJUCE_APP_VERSION_HEX=0x10602]] [[-DDEBUG=1]] [[-D_DEBUG=1]]) include_directories( AFTER "../../../../deps/aoo/lib" "../../../../deps/aoo/deps" @@ -47,7 +47,7 @@ elseif(JUCE_BUILD_CONFIGURATION MATCHES "RELEASE") "../../../../deps/android/${ANDROID_ABI}" ) - add_definitions([[-DJUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1]] [[-DSONOBUS_BUILD_VERSION="1.4.9-74"]] [[-DUSE_CODEC_OPUS=1]] [[-DAOO_TIMEFILTER_CHECK=0]] [[-DAOO_STATIC]] [[-DJUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE=0]] [[-DJUCE_ANDROID_ACTIVITY_OVERRIDE_CLASSNAME="com_sonosaurus_sonobus_SonoBusActivity"]] [[-DJUCE_ANDROID_ACTIVITY_OVERRIDE_CLASSPATH="com/sonosaurus/sonobus/SonoBusActivity"]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.6.1]] [[-DJUCE_APP_VERSION_HEX=0x10601]] [[-DNDEBUG=1]]) + add_definitions([[-DJUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1]] [[-DSONOBUS_BUILD_VERSION="1.4.9-74"]] [[-DUSE_CODEC_OPUS=1]] [[-DAOO_TIMEFILTER_CHECK=0]] [[-DAOO_STATIC]] [[-DJUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE=0]] [[-DJUCE_ANDROID_ACTIVITY_OVERRIDE_CLASSNAME="com_sonosaurus_sonobus_SonoBusActivity"]] [[-DJUCE_ANDROID_ACTIVITY_OVERRIDE_CLASSPATH="com/sonosaurus/sonobus/SonoBusActivity"]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.6.2]] [[-DJUCE_APP_VERSION_HEX=0x10602]] [[-DNDEBUG=1]]) include_directories( AFTER "../../../../deps/aoo/lib" "../../../../deps/aoo/deps" diff --git a/mobile/Builds/Android/app/src/main/AndroidManifest.xml b/mobile/Builds/Android/app/src/main/AndroidManifest.xml index eced244e..128b7a26 100644 --- a/mobile/Builds/Android/app/src/main/AndroidManifest.xml +++ b/mobile/Builds/Android/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ - + diff --git a/mobile/Builds/iOS/Info-AUv3_AppExtension.plist b/mobile/Builds/iOS/Info-AUv3_AppExtension.plist index 45bbfbe4..bd5d7e5e 100644 --- a/mobile/Builds/iOS/Info-AUv3_AppExtension.plist +++ b/mobile/Builds/iOS/Info-AUv3_AppExtension.plist @@ -43,9 +43,9 @@ CFBundleSignature ???? CFBundleShortVersionString - 1.6.1 + 1.6.2 CFBundleVersion - 79 + 80 NSHumanReadableCopyright 2023 Sonosaurus LLC NSHighResolutionCapable @@ -76,7 +76,7 @@ subtype NBus version - 67073 + 67074 sandboxSafe tags diff --git a/mobile/Builds/iOS/Info-Standalone_Plugin.plist b/mobile/Builds/iOS/Info-Standalone_Plugin.plist index 6a2101d0..f95cec28 100644 --- a/mobile/Builds/iOS/Info-Standalone_Plugin.plist +++ b/mobile/Builds/iOS/Info-Standalone_Plugin.plist @@ -43,9 +43,9 @@ CFBundleSignature ???? CFBundleShortVersionString - 1.6.1 + 1.6.2 CFBundleVersion - 79 + 80 NSHumanReadableCopyright 2023 Sonosaurus LLC NSHighResolutionCapable @@ -79,7 +79,7 @@ subtype NBus version - 67073 + 67074 diff --git a/mobile/Builds/iOS/SonoBus.xcodeproj/project.pbxproj b/mobile/Builds/iOS/SonoBus.xcodeproj/project.pbxproj index 0b208f00..639c8454 100644 --- a/mobile/Builds/iOS/SonoBus.xcodeproj/project.pbxproj +++ b/mobile/Builds/iOS/SonoBus.xcodeproj/project.pbxproj @@ -1286,8 +1286,8 @@ "AOO_STATIC", "NOTUSED_JUCE_IOS_AUDIO_EXPLICIT_SAMPLERATES=8000,16000,22050,44100,48000,88200,96000", "JUCER_XCODE_IPHONE_5BC26AE3=1", - "JUCE_APP_VERSION=1.6.1", - "JUCE_APP_VERSION_HEX=0x10601", + "JUCE_APP_VERSION=1.6.2", + "JUCE_APP_VERSION_HEX=0x10602", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", @@ -1350,8 +1350,8 @@ "AOO_STATIC", "NOTUSED_JUCE_IOS_AUDIO_EXPLICIT_SAMPLERATES=8000,16000,22050,44100,48000,88200,96000", "JUCER_XCODE_IPHONE_5BC26AE3=1", - "JUCE_APP_VERSION=1.6.1", - "JUCE_APP_VERSION_HEX=0x10601", + "JUCE_APP_VERSION=1.6.2", + "JUCE_APP_VERSION_HEX=0x10602", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", @@ -1415,8 +1415,8 @@ "AOO_STATIC", "NOTUSED_JUCE_IOS_AUDIO_EXPLICIT_SAMPLERATES=8000,16000,22050,44100,48000,88200,96000", "JUCER_XCODE_IPHONE_5BC26AE3=1", - "JUCE_APP_VERSION=1.6.1", - "JUCE_APP_VERSION_HEX=0x10601", + "JUCE_APP_VERSION=1.6.2", + "JUCE_APP_VERSION_HEX=0x10602", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", @@ -1477,8 +1477,8 @@ "AOO_STATIC", "NOTUSED_JUCE_IOS_AUDIO_EXPLICIT_SAMPLERATES=8000,16000,22050,44100,48000,88200,96000", "JUCER_XCODE_IPHONE_5BC26AE3=1", - "JUCE_APP_VERSION=1.6.1", - "JUCE_APP_VERSION_HEX=0x10601", + "JUCE_APP_VERSION=1.6.2", + "JUCE_APP_VERSION_HEX=0x10602", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", @@ -1544,8 +1544,8 @@ "AOO_STATIC", "NOTUSED_JUCE_IOS_AUDIO_EXPLICIT_SAMPLERATES=8000,16000,22050,44100,48000,88200,96000", "JUCER_XCODE_IPHONE_5BC26AE3=1", - "JUCE_APP_VERSION=1.6.1", - "JUCE_APP_VERSION_HEX=0x10601", + "JUCE_APP_VERSION=1.6.2", + "JUCE_APP_VERSION_HEX=0x10602", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", @@ -1659,8 +1659,8 @@ "AOO_STATIC", "NOTUSED_JUCE_IOS_AUDIO_EXPLICIT_SAMPLERATES=8000,16000,22050,44100,48000,88200,96000", "JUCER_XCODE_IPHONE_5BC26AE3=1", - "JUCE_APP_VERSION=1.6.1", - "JUCE_APP_VERSION_HEX=0x10601", + "JUCE_APP_VERSION=1.6.2", + "JUCE_APP_VERSION_HEX=0x10602", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", @@ -1775,8 +1775,8 @@ "AOO_STATIC", "NOTUSED_JUCE_IOS_AUDIO_EXPLICIT_SAMPLERATES=8000,16000,22050,44100,48000,88200,96000", "JUCER_XCODE_IPHONE_5BC26AE3=1", - "JUCE_APP_VERSION=1.6.1", - "JUCE_APP_VERSION_HEX=0x10601", + "JUCE_APP_VERSION=1.6.2", + "JUCE_APP_VERSION_HEX=0x10602", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", @@ -1841,8 +1841,8 @@ "AOO_STATIC", "NOTUSED_JUCE_IOS_AUDIO_EXPLICIT_SAMPLERATES=8000,16000,22050,44100,48000,88200,96000", "JUCER_XCODE_IPHONE_5BC26AE3=1", - "JUCE_APP_VERSION=1.6.1", - "JUCE_APP_VERSION_HEX=0x10601", + "JUCE_APP_VERSION=1.6.2", + "JUCE_APP_VERSION_HEX=0x10602", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", diff --git a/mobile/JuceLibraryCode/JuceHeader.h b/mobile/JuceLibraryCode/JuceHeader.h index 51ff7d69..eb3e50b0 100644 --- a/mobile/JuceLibraryCode/JuceHeader.h +++ b/mobile/JuceLibraryCode/JuceHeader.h @@ -53,7 +53,7 @@ namespace ProjectInfo { const char* const projectName = "SonoBus"; const char* const companyName = "Sonosaurus"; - const char* const versionString = "1.6.1"; - const int versionNumber = 0x10601; + const char* const versionString = "1.6.2"; + const int versionNumber = 0x10602; } #endif diff --git a/mobile/JuceLibraryCode/JucePluginDefines.h b/mobile/JuceLibraryCode/JucePluginDefines.h index 8ac76740..39bc7ed1 100644 --- a/mobile/JuceLibraryCode/JucePluginDefines.h +++ b/mobile/JuceLibraryCode/JucePluginDefines.h @@ -77,13 +77,13 @@ #define JucePlugin_EditorRequiresKeyboardFocus 0 #endif #ifndef JucePlugin_Version - #define JucePlugin_Version 1.6.1 + #define JucePlugin_Version 1.6.2 #endif #ifndef JucePlugin_VersionCode - #define JucePlugin_VersionCode 0x10601 + #define JucePlugin_VersionCode 0x10602 #endif #ifndef JucePlugin_VersionString - #define JucePlugin_VersionString "1.6.1" + #define JucePlugin_VersionString "1.6.2" #endif #ifndef JucePlugin_VSTUniqueID #define JucePlugin_VSTUniqueID JucePlugin_PluginCode @@ -155,7 +155,7 @@ #define JucePlugin_ARAFactoryID "com.Sonosaurus.SonoBus.factory" #endif #ifndef JucePlugin_ARADocumentArchiveID - #define JucePlugin_ARADocumentArchiveID "com.Sonosaurus.SonoBus.aradocumentarchive.1.6.0" + #define JucePlugin_ARADocumentArchiveID "com.Sonosaurus.SonoBus.aradocumentarchive.1.6.1" #endif #ifndef JucePlugin_ARACompatibleArchiveIDs #define JucePlugin_ARACompatibleArchiveIDs "" diff --git a/mobile/SonoBusMobile.jucer b/mobile/SonoBusMobile.jucer index 5d5650ed..ccb8c510 100644 --- a/mobile/SonoBusMobile.jucer +++ b/mobile/SonoBusMobile.jucer @@ -4,7 +4,7 @@ companyCopyright="2023 Sonosaurus LLC" companyEmail="support@sonosaurus.com" pluginFormats="buildAUv3,buildStandalone,enableIAA" pluginManufacturerCode="Sono" pluginCode="NBus" defines="JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1 SONOBUS_BUILD_VERSION="1.4.9-74" " - pluginDesc="SonoBus - Network Audio" version="1.6.1" cppLanguageStandard="17" + pluginDesc="SonoBus - Network Audio" version="1.6.2" cppLanguageStandard="17" projectLineFeed=" " jucerFormatVersion="1" pluginAUMainType="'aufx'" pluginAUIsSandboxSafe="1"> @@ -397,7 +397,7 @@ UISupportsDocumentBrowser="1" UIFileSharingEnabled="1" customLaunchStoryboard="../images/LaunchScreen.storyboard" iosScreenOrientation="UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationLandscapeRight,UIInterfaceOrientationPortrait,UIInterfaceOrientationPortraitUpsideDown" iPadScreenOrientation="UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationLandscapeRight,UIInterfaceOrientationPortrait,UIInterfaceOrientationPortraitUpsideDown" - UIRequiresFullScreen="0" buildNumber="79"> + UIRequiresFullScreen="0" buildNumber="80"> + androidVersionCode="80"> From c9d9fd878249d34d0e367182afcce976403c76f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E7=9C=BC=E4=BB=94=E6=97=AD?= <86864914+wcxu21@users.noreply.github.com> Date: Mon, 20 Mar 2023 06:17:14 +0800 Subject: [PATCH 04/16] Add Simplified Chinese language (#125) Add Simplified Chinese language --- localization/localized_zh-CN.txt | 585 +++++++++++++++++++++++++++++++ 1 file changed, 585 insertions(+) create mode 100644 localization/localized_zh-CN.txt diff --git a/localization/localized_zh-CN.txt b/localization/localized_zh-CN.txt new file mode 100644 index 00000000..3c974e98 --- /dev/null +++ b/localization/localized_zh-CN.txt @@ -0,0 +1,585 @@ +language: Simplified Chinese (CN) +countries: zh + +"Noise Floor" = "本底噪声" +"Ratio" = "比率" +"Attack" = "打击" +"Release" = "释放" +"Noise Gate" = "噪声门" +"In Gain" = "在增益" +"In Pan" = "在声像" +"C" = "C" +"In Pan 1" = "在声像 1" +"In Pan 2" = "在声像 2" +"Dry Level" = "干音电平" +"Output Level" = "输出电平" +"Default Jitter Buffer Time" = "默认抖动缓冲时间" +"Send Channels" = "发送声道" +"Metronome Enabled" = "节拍器已启用" +"Send Metronome Audio" = "发送节拍器音频" +"Metronome Gain" = "节拍器增益" +"Metronome Tempo" = "节拍器速度" +"Send Playback Audio" = "发送播放音频" +"Hear Latency Test" = "听到延迟测试" +"Record Metronome to File" = "录制节拍器到文件" +"Main Reverb Enabled" = "主混响已启用" +"Main Reverb Level" = "主混响电平" +"Main Reverb Size" = "主混响大小" +"Main Reverb Damping" = "主混响阻尼" +"Pre-Delay Time" = "预延迟时间" +"Main Reverb Model" = "主混响模型" +"Main Send Mute" = "主发送静音" +"Main Receive Mute" = "主接收静音" +"Main In Mute" = "主输入静音" +"Main Monitor Solo" = "主监视器独奏" +"Def Auto Net Buffer Mode" = "默认自动网络缓冲模式" +"Def Send Format" = "默认发送格式" +"Dynamic Resampling" = "动态重采样" +"Reconnect Last" = "最后重新连接" +"Default User Level" = "默认用户电平" +"Sync to Host" = "同步到主机" +"Metronome" = "节拍器" +"File Playback" = "文件播放" +"Could not find format for filename" = "找不到文件名的格式" +"Error creating writer for " = "创建作家时出错" +"Error creating output file: " = "创建输出文件时出错:" +"Error creating directory for recording: " = "创建录制目录时出错:" +"RECENTS" = "最近" +"PRIVATE GROUP" = "私人群组" +"PUBLIC GROUPS" = "公共群组" +"DIRECT" = "直接" +"Local Address:" = "本地地址:" +"Host: " = "主机:" +"Connect directly to other instances of SonoBus on your local network with the local address that they advertise. This is experimental, using a private group is recommended instead, and works fine on local networks." = "使用它们宣传的本地地址直接连接到本地网络上的其他 SonoBus 实例。 这是实验性的,建议使用私有组,并且可以在本地网络上正常工作。" +"IPaddress:port" = "IP 地址:端口" +"Connect" = "连接" +"Direct Connect" = "直接连接" +"Connect to Group" = "连接到群组" +"optional" = "可选" +"Your Displayed Name:" = "您的显示名称:" +"Password:" = "密码:" +"Group Name:" = "群组名称:" +"Connection Server:" = "连接服务器:" +"Generate a random group name" = "生成随机组名" +"Copy connection information to the clipboard to share" = "复制连接信息到剪贴板以共享" +"Paste connection information from the clipboard" = "从剪贴板粘贴连接信息" +"The connection server is only used to help users find each other, no audio passes through it. All audio is sent directly between users (peer to peer)." = "连接服务器仅用于帮助用户找到对方,没有音频通过。 所有音频都直接在用户之间发送(点对点)。" +"Clear All" = "清除全部" +"Active Public Groups" = "活跃公共群组" +"Select existing group below OR " = "选择下面的现有群组或" +"Create Group..." = "创建群组..." +"enter group name" = "输入群组名称" +"Choose a descriptive group name that includes geographic information and genre" = "选择一个包含地理信息和流派的描述性组名" +"Share this link with others to connect with SonoBus:" = "与其他人分享此链接以连接 SonoBus:" +"Or share this link:" = "或分享此链接:" +"Total: " = "总计:" +"Filled in Group information from clipboard! Press \'Connect to Group\' to join..." = "从剪贴板填写组信息! 按“连接到群组”加入..." +"Copied connection info to clipboard for you to share with others" = "将连接信息复制到剪贴板,供您与他人分享" +"Connect to Raw Address..." = "连接到原始地址..." +"You need to specify a group name!" = "您需要指定一个组名!" +"You need to specify a user name!" = "您需要指定用户名!" +"Server address is invalid!" = "服务器地址无效!" +"All who join the same Group will be able to connect with each other." = "所有加入同一组的人都可以相互联系。" +"PUBLIC" = "公共" +"password protected," = "密码保护" +"on" = "在" +"to" = "到" +" active users" = " 活跃用户" +" active user" = " 活跃用户" +"SonoBus" = "SonoBus" +"Shows full information for connected users" = "显示已连接用户的完整信息" +"Shows minimal information for connected users" = "显示连接用户的最少信息" +"INPUT MIXER" = "输入混音器" +"MUTE" = "静音" +"Mutes your input preventing everyone from hearing you, without any indicator" = "静音您的输入,防止所有人听到您的声音,没有任何指示" +"SOLO" = "独奏" +"Listen to only yourself, and other soloed users. Alt-click to exclusively solo yourself." = "只听你自己和其他独奏用户。Alt 键单击以独奏你自己。" +"MON DELAY" = "MON 延迟" +"Control additional self-monitoring delay, which can help mitigate synchronization with others" = "控制额外的自我监控延迟,这有助于减少与他人的同步" +"Silences your Input, none of your audio (including file playback) will be sent to users and they will see a muted indicator" = "使您的输入静音,您的任何音频(包括文件播放)都不会发送给用户,他们将看到静音指示器" +"Mutes/Unmutes all users, no audio data will be received when users are muted" = "静音/取消静音所有用户,静音时不会收到音频数据" +"按下时,将其他人静音并暂时取消您的静音(即按即说)。" = "押すと、他の人をミュートし、一時的にミュートを解除します(プッシュして話します)。" +" Use the \'T\' key as a shortcut." = " 使用 T 键作为快捷方式。" +"Metronome On/Off" = "节拍器开/关" +"Metronome Options" = "节拍器选项" +"Level" = "电平" +"Tempo" = "节奏" +"Send Metronome to All" = "发送节拍器给所有人" +"Synchronize metronome tempo with plugin host" = "与插件主机同步节拍器速度" +"In Level" = "输入电平" +"This reduces or boosts the level of your own audio input, and it will affect the level of your audio being sent to others and your own monitoring" = "这会降低或提高您自己的音频输入电平,并且会影响您发送给他人的音频电平和您自己的监听" +"Monitor" = "监视器" +"This adjusts the level of the monitoring of your input, that only you hear" = "这会调整您输入的监听电平,只有您能听到" +"Out Level" = "输出电平" +"This is the main volume control which affects everything you hear" = "这是影响您听到的一切的主要音量控制" +"Connect..." = "连接..." +"Show the connections page, while staying connected to current group" = "显示连接页面,同时保持与当前组的连接" +"Patchbay" = "配线架" +"Setup Audio" = "设置音频" +"Press to copy/share link to group" = "按复制/分享链接到群组" +"Show/Hide Chat" = "显示/隐藏聊天" +"Manual" = "手动" +"Auto Up" = "自动上升" +"Auto" = "自动" +"Initial Auto" = "初始自动" +"Default Jitter Buffer" = "默认抖动缓冲区" +"Default Send Quality:" = "默认发送质量:" +"Make Latency Test Audible" = "使延迟测试可听" +"Metronome output recorded in full mix" = "全混音录制的节拍器输出" +"Record feature creates the following files:" = "录制功能会创建以下文件:" +"Full Mix" = "完全混音" +"Full Mix without yourself" = "没有你自己的完整混音" +"Yourself" = "你自己" +"Each Connected User" = "每个连接的用户" +"FLAC" = "FLAC" +"WAV" = "WAV" +"OGG" = "OGG" +"16 bit" = "16 位" +"24 bit" = "24 位" +"Audio File Format:" = "音频文件格式:" +"Record Location:" = "录制位置:" +"Use Specific UDP Port" = "使用特定 UDP 端口" +"Use Drift Correction (NOT RECOMMENDED)" = "使用漂移校正(不推荐)" +"Auto-Reconnect to Last Group" = "自动重新连接到最后一个组" +"Override Device Sample Rate" = "覆盖设备采样率" +"Automatically check for updates" = "自动检查更新" +"Sliders Snap to Clicked Position" = "滑块捕捉到单击位置" +"Use Input FX Limiter" = "使用输入效果限制器" +"Change all connected" = "更改所有连接" +"Version: " = "版本:" +"FX" = "FX" +"Send Mono" = "发送单声道" +"Send Stereo" = "发送立体声" +"Send Multichannel" = "发送多声道" +"# Send Channels" = "# 发送声道" +"Size" = "大小" +"Damping" = "阻尼" +"Pre-Delay" = "预延迟" +"Reverb" = "混响" +"Freeverb" = "Freeverb" +"MVerb" = "MVerb" +"Zita" = "Zita" +"Start/Stop recording audio to file" = "开始/停止将音频录制到文件" +"Load audio file for playback" = "加载音频文件进行播放" +"Send File Playback to All" = "发送文件给所有人播放" +"Quit Confirmation" = "退出确认" +"You are connected, are you sure you want to quit?" = "您已连接,您确定要退出吗?" +"Quit" = "退出" +"Last Session: " = "上次会话:" +"Not sending your audio anywhere" = "不在任何地方发送您的音频" +"Sending your audio to others" = "发送音频给其他人" +"Muted everyone" = "已将所有人静音" +"Unmuted all who were not muted previously" = "取消静音所有之前未静音的人" +"Sending your metronome to all users" = "发送您的节拍器给所有用户" +"Now only you will hear your metronome" = "现在只有你会听到你的节拍器" +"Sending file playback to all users" = "向所有用户发送文件播放" +"Now only you will hear the file playback" = "现在只有你会听到文件播放" +"Copied group connection info to clipboard for you to share with others" = "将群组连接信息复制到剪贴板供您与他人分享" +"Finished recording to " = "完成录制到 " +"Last recorded file: " = "上次录制的文件:" +"Started recording output" = "开始录音输出" +"Recording audio to: " = "音频录制到:" +"Recording multi-track audio to: " = "录制多轨音频到:" +"Choose an audio file to open..." = "选择要打开的音频文件..." +"Choose the folder for new recordings" = "选择新录音的文件夹" +"Choose a location and name to store the setup" = "选择一个位置和名称来存储设置" +"Choose a setup file to load" = "选择要加载的安装文件" +"Error while loading" = "加载时出错" +"Couldn\'t read from the specified file!" = "无法从指定的文件中读取!" +"Invalid setup!" = "设置无效!" +"Error while saving" = "保存时出错" +"Couldn\'t write to the specified file!" = "无法写入指定文件!" +"Filled in Group from link! Press \'Connect to Group\' to join..." = "从链接填写群组! 按“连接到群组”加入..." +"AUDIO" = "音频" +"OPTIONS" = "选项" +"HELP" = "帮助" +"RECORDING" = "正在录音" +"Using an ASIO audio device type is strongly recommended. If your audio interface did not come with one, please install ASIO4ALL (asio4all.org) and configure it first." = "强烈建议使用 ASIO 音频设备类型。 如果您的音频接口没有自带,请先安装 ASIO4ALL (asio4all.org) 并进行配置。" +"Disconnect" = "断开连接" +"[P] " = "[P]" +"Waiting for other users to join group" = "等待其他用户加入群组" +"Press Connect button to start." = "按连接按钮开始。" +"Please use headphones if you are using a microphone!" = "如果您使用麦克风,请使用耳机!" +"Connected to server" = "连接到服务器" +"Already connected with this user name" = "已与此用户名连接" +"Connect failed: " = "连接失败:" +"Disconnected from server" = "与服务器断开连接" +"Disconnect failed: " = "断开连接失败:" +"Joined Group: " = "加入群组:" +"Failed to join group: " = "加入群组失败:" +"Left Group: " = "退出群组:" +"Failed to leave group: " = "退出群组失败:" +" - joined group" = " - 加入群组" +" - left group" = " - 退出群组" +"Trim to New" = "修剪为新的" +"Share File" = "共享文件" +"Reveal File" = "显示文件" +"Mute All Input" = "静音所有输入" +"Toggle Mute all input" = "切换静音所有输入" +"Popup" = "弹出" +"Mute All Users" = "静音所有用户" +"Toggle Mute all users" = "切换静音所有用户" +"Play/Pause" = "播放/暂停" +"Toggle file playback" = "切换文件播放" +"Loop" = "循环" +"Toggle file looping" = "切换文件循环" +"Trim file from selection to new file" = "将文件从选择修剪到新文件" +"Close Audio File" = "关闭音频文件" +"Close audio file" = "关闭音频文件" +"Open Audio File..." = "打开音频文件..." +"Open Audio file" = "打开音频文件" +"Share Audio File" = "分享音频文件" +"Share audio file" = "分享音频文件" +"Reveal Audio File" = "显示音频文件" +"Reveal audio file" = "显示音频文件" +"Load Setup..." = "加载设置..." +"Load Setup file" = "加载设置文件" +"Save Setup..." = "保存设置..." +"Save Setup file" = "保存设置文件" +"Show or hide chat area" = "显示或隐藏聊天区" +"Show Options" = "显示选项" +"Record" = "录制" +"Toggle Record" = "切换录制" +"Check For New Version" = "检查新版本" +"Check for New Version" = "检查新版本" +"File" = "文件" +"Transport" = "传输" +"View" = "查看" +"Help" = "帮助" +"Load Recent Setup" = "加载最近设置" +"Save current state" = "保存当前状态" +"Load a saved state" = "加载保存的状态" +"Audio/MIDI Settings" = "音频/MIDI 设置" +"Audio Settings" = "音频设置" +"Audio/MIDI Settings..." = "音频/MIDI 设置..." +"Save current state..." = "保存当前状态..." +"Load a saved state..." = "加载保存的状态..." +"Reset to default state" = "重置为默认状态" +"Send Level: " = "发送级别:" +"Reverb Send" = "混响发送" +"Enable the main reverb at the bottom of the window to hear the effect" = "启用窗口底部的主混响以听到效果" +"Main Reverb Send" = "主混响发送" +"Crashed Last Time" = "上次崩溃" +"Looks like you crashed on launch last time, restoring default settings!" = "看起来您上次启动时崩溃了,正在恢复默认设置!" +"Threshold" = "阈值" +"Makeup Gain" = "补偿增益" +"Compressor" = "压缩器" +"Autoset Makeup" = "自动设置补偿" +"Gain" = "增益" +"High Shelf" = "高架子" +"Low Shelf" = "低架子" +"Freq 1" = "频率 1" +"Q" = "Q" +"Freq 2" = "频率 2" +"Parametric EQ" = "参数均衡器" +"Chat" = "聊天" +"Enter message here..." = "在此输入消息..." +"Send" = "发送" +"Save Chat" = "保存聊天" +"Clear Chat" = "清除聊天" +"Add New Input Group" = "添加新的输入组" +"CLEAR" = "清除" +"Remove all input groups" = "删除所有输入组" +"Level: " = "电平:" +"Monitor: " = "监视器::" +"Pre Level: " = "预设电平::" +"Set name for this group that others will see" = "为该组设置其他人将看到的名称" +"Click to toggle extra information visibility" = "单击以切换额外信息的可见性" +"Toggles receive muting, preventing audio from being heard for this user" = "切换接收静音,防止听到此用户的音频" +"Mute this channel for both sending and monitoring" = "将此声道静音以进行发送和监视" +"Solo - Listen to only this user, and other soloed users. Alt-click to exclusively solo this user." = "独奏 - 只听这个用户和其他独奏用户。 Alt-单击以独占此用户。" +"Solo - Listen to only this channel for this user" = "独奏 - 只听这个用户的这个声道" +"Solo - Listen to only this channel, does not affect sending" = "Solo - 只听这个声道,不影响发送" +"Monitor output level" = "监控输出电平" +"Pan" = "声像" +"Pan: Center" = "声像:中心" +"Pan: " = "声像:" +"Change channel layout" = "更改声道布局" +"Select Input channel source (or drag to rearrange)" = "选择输入声道源(或拖动以重新排列)" +"mono" = "单声道" +"Choose destination output channels" = "选择目标输出声道" +"Choose destination monitoring channels" = "选择目标监控声道" +"Edit input effects (applied before sending)" = "编辑输入效果(发送前应用)" +"Edit effects" = "编辑效果" +"M.FX" = "M.FX" +"Edit input monitoring effects (applied to local monitoring only)" = "编辑输入监听效果(仅适用于本地监听)" +"Edit monitoring effects" = "编辑监听效果" +"ch" = "ch" +"Confirm Remove of All Inputs" = "确认删除所有输入" +"ADD INPUT GROUP:" = "添加输入组:" +"Mono" = "单声道" +"Stereo" = "立体声" +"channel" = "声道" +"CHANGE CHANNEL LAYOUT:" = "更改声道布局:" +"<恢复原始布局>" = "<元のレイアウトに戻す>" +"SELECT INPUTS:" = "选择输入:" +"SELECT INPUT:" = "选择输入:" +"CHANGE LAYOUT..." = "更改布局..." +"REMOVE" = "移除" +"SELECT MONITOR OUT:" = "选择显示器输出:" +"Remote address:" = "远程地址:" +"Disable Sending" = "禁用发送" +"Listen to only this user, and other soloed users. Alt-click to exclusively solo this user." = "只听这个用户和其他独奏用户。 Alt-单击以独占此用户。" +"Resets jitter buffer to the minimum. Hold Alt key to reset for all (with auto)." = "将抖动缓冲区重置为最小值。 按住 Alt 键重置所有(自动)。" +"Jitter Buffer" = "抖动缓冲器" +"Change for all" = "为所有人更改" +"Send Quality" = "发送质量" +"No Preference" = "无偏好" +"Preferred Recv Quality" = "首选接收质量" +"Change all" = "更改全部" +"Latency (ms)" = "延迟(毫秒)" +"Ping" = "Ping" +"PRESS" = "按" +"Send Quality:" = "发送质量:" +"Recv Jitter Buffer:" = "接收抖动缓冲器:" +"Reset Dropped" = "重置已删除" +"Remove" = "移除" +"Removes user from your own connections, does not affect the whole group" = "从您自己的连接中删除用户,不影响整个组" +"Removes pending user from list" = "从列表中删除待处理用户" +"Other end muted us" = "另一端使我们静音" +"SEND DISABLED" = "发送已禁用" +"Other side is muted" = "另一边静音" +"You muted them" = "你静音了他们" +"****" = "****" +"Could not connect with user, one or both of you may need to configure your internal firewall or network router to allow SonoBus to work between you. See the help documentation to enable port forwarding on your router." = "无法与用户连接,你们中的一个或两个可能需要配置您的内部防火墙或网络路由器以允许 SonoBus 在你们之间工作。 请参阅帮助文档以在您的路由器上启用端口转发。" +"Connecting..." = "正在连接..." +"Estimated Round-trip Latency:" = "预计往返延迟:" +"Round-trip Network Ping:" = "往返网络 Ping:" +"Est. Outgoing:" = "传出预估时间:" +"Est. Incoming:" = "传入预估时间:" +"Est. Jitter:" = "抖动预估时间:" +"Legacy-mode, ask them \r\n to install latest version" = "传统模式\r\n要求他们安装最新版本" +"Measuring actual round-trip latency" = "测量实际的往返延迟" +"Mute All" = "全部静音" +"Unmute All" = "取消全部静音" +"Delay Time" = "延迟时间" +"One-way" = "单向" +"Round-trip" = "往返" +"Set From Peers" = "从对等点设置" +"Pressing this will calculate an average latency for all connected peers and set the monitoring delay time accordingly, based on one-way or round-trip choice selection" = "按下此按钮将计算所有已连接对等方的平均延迟,并根据单向或往返选择选择相应地设置监控延迟时间" +"Link Delay Time with other inputs" = "与其他输入的链接延迟时间" +"Additional Monitoring Delay" = "额外监测延迟" +"none" = "无" +"Show advanced settings..." = "显示高级设置..." +"Error when trying to open audio device!" = "尝试打开音频设备时出错!" +"(no audio output channels found)" = "(未找到音频输出声道)" +"Active Output Channels:" = "有源输出声道:" +"(no audio input channels found)" = "(未找到音频输入声道)" +"Active Input Channels:" = "有源输入声道:" +"Control Panel" = "控制面板" +"Opens the device\'s own control panel" = "打开设备自己的控制面板" +"Reset Device" = "重置设备" +"Resets the audio interface - sometimes needed after changing a device\'s properties in its custom control panel" = "重置音频接口 - 有时需要在其自定义控制面板中更改设备的属性后" +"Output:" = "输出:" +"Device:" = "设备:" +"Test" = "测试" +"Plays a test tone" = "播放测试音" +"Input:" = "输入:" +"Sample rate:" = "采样率:" +"Audio Buffer Size:" = "音频缓冲区大小:" +"Audio device type:" = "音频设备类型:" +"No MIDI inputs available" = "没有可用的 MIDI 输入" +"Active MIDI inputs:" = "活动 MIDI 输入:" +"Bluetooth MIDI" = "蓝牙 MIDI" +"Scan for bluetooth MIDI devices" = "扫描蓝牙 MIDI 设备" +"MIDI Output:" = "MIDI 输出:" +"This button shows/hides the Input Mixer where you can organize your audio input levels, panning, and effects before your signal is sent out. You can also control how you monitor yourself." = "此按钮显示/隐藏输入混音器,您可以在其中组织音频输入电平、声像和效果,然后再发送信号。 您还可以控制如何监控自己。" +"Press for group action menu" = "按组操作菜单" +"This controls how many channels of audio you send out to other connected users. Mono and Stereo send 1 or 2 channels respectively mixed from all of your inputs that you set up in the Input Mixer. If you choose Send Multichannel, it will send all of the inputs you specify in the Input Mixer separately to everyone connected, where they can mix all the channels themselves." = "这控制了您发送给其他连接用户的音频通道数。 单声道和立体声分别从您在输入混音器中设置的所有输入发送 1 或 2 个通道。 如果您选择发送多通道,它会将您在输入混音器中指定的所有输入分别发送给连接的每个人,他们可以自己混合所有通道。" +"Share Group Link" = "分享群组链接" +"Copy Group Link" = "复制群组链接" +"Group Latency Match..." = "群组延迟匹配....." +"Match Latency" = "匹配延迟" +"requests to use a matched group latency of:" = "请求使用匹配的组延迟:" +"Prints the list of commands" = "打印命令列表" +"Prints the current version number only" = "仅打印当前版本号" +"Specify the group name to immediately connect to upon launch" = "指定启动时立即连接的组名" +"Specify the displayed username for yourself when connecting to a group" = "连接到组时为自己指定显示的用户名" +"Specify the password to use for the group name to connect to (optional)" = "指定用于连接组名的密码(可选)" +"Specify connection server to use when connecting to a group (optional)" = "指定连接到组时要使用的连接服务器(可选)" +"Specify the filename of a setup file to load." = "指定要加载的安装文件的文件名。" +"The setup file can be created using the Save Setup feature from the full application, and includes any device selection, input mixer setup, and all other options. If you don\'t specify a full or relative pathname it will look for a preset file by that name in the last used setup folder." = "可以使用完整应用程序中的保存设置功能创建设置文件,包括任何设备选择、输入混音器设置和所有其他选项。 如果您未指定完整或相对路径名,它将在上次使用的安装文件夹中查找该名称的预设文件。" +"If specified, no GUI will be used and the application will be run headless." = "如果指定,将不使用 GUI,应用程序将无头运行。" +"You\'ll need to use other command-line options to connect to a group... eventually there will be an OSC remote control interface." = "您需要使用其他命令行选项来连接到一个组... 最终会有一个 OSC 远程控制界面。" +" version " = " 版本" +"Usage: " = "使用方法:" +"Error: you need to specify a group to connect to for headless operation right now... eventually there will be an OSC interface." = "错误:您现在需要指定要连接的组以进行无头操作... 最终将有一个 OSC 接口。" +"System Default Language" = "系统默认语言" +"English" = "英語" +"Spanish" = "西班牙语" +"French" = "法语" +"Italian" = "意大利语" +"German" = "德语" +"Portuguese (Portugal)" = "葡萄牙语(葡萄牙)" +"Portuguese (Brazil)" = "葡萄牙语(巴西)" +"Dutch" = "荷兰语" +"Japanese" = "日语" +"Chinese (Simplified)" = "中文(简体)" +"Chinese (Traditional)" = "中文(繁体)" +"This controls controls the default jitter buffer size to start with. When using the Auto modes, it is recommended to keep the value at the minimum so it starts from the lowest possible value. Generally you will only want to set this higher if you are using a Manual mode default which is not recommended." = "此控件控制开始时的默认抖动缓冲区大小。 使用自动模式时,建议将值保持在最小值,以便从可能的最低值开始。 通常,如果您使用不推荐的手动模式默认值,您只会希望将其设置得更高。" +"This controls how the jitter buffers are automatically adjusted based on network conditions. The Auto mode is the recommended choice as it will adjust the jitter buffers up or down based on current conditions. The Auto-Up will only make the buffers larger. The Initial Auto will do an initial adjustment from the smallest value and once it stabilizes will no longer change, even if network conditions worsen. Manual will let you set the jitter buffer manually, leaving it up to you to deal with if network conditions change, but can be useful with known users." = "这控制如何根据网络条件自动调整抖动缓冲区。 推荐选择自动模式,因为它会根据当前条件向上或向下调整抖动缓冲区。 Auto-Up 只会使缓冲区变大。 Initial Auto 将从最小值开始进行初始调整,一旦稳定,即使网络状况恶化,也不会再改变。 Manual 将允许您手动设置抖动缓冲区,如果网络条件发生变化,则由您自行处理,但对已知用户很有用。" +"The default send quality will be used when you first connect with someone. The values specified with a kbps/ch are Opus compressed audio and use less network bandwidth at the expense of a little latency. It is not recommended to use less than 96 kpbs/ch, as that will increase latency more. The PCM 16bit (and above) use uncompressed audio data and will use the most network bandwidth, but have the least latency and CPU load. If you are connecting with a known small group who all have network service that can support it, using PCM 16 bit is recommended for the lowest latency. Otherwise 96 kbps/ch is a good default." = "当您第一次与某人联系时,将使用默认发送质量。 用 kbps/ch 指定的值是 Opus 压缩音频,使用较少的网络带宽,但会产生一点延迟。 不建议使用低于 96 kpbs/ch,因为这会增加更多延迟。 PCM 16 位(及以上)使用未压缩的音频数据,将使用最多的网络带宽,但延迟和 CPU 负载最少。 如果您要与一个已知的小组连接,他们都有可以支持它的网络服务,建议使用 PCM 16 位以获得最低延迟。 否则 96 kbps/ch 是一个很好的默认值。" +"Language:" = "语言:" +"Allow Bluetooth Input" = "允许蓝牙输入" +"sec" = "秒" +"This controls how sensitive the auto-jitter buffer adjustment is when there are audio dropouts. The jitter buffer size will be increased if there are any dropouts within the number of seconds specified here. When this value is smaller it will be less likely to increase the jitter buffer size automatically." = "这控制了音频丢失时自动抖动缓冲调整的敏感程度。 如果在此处指定的秒数内有任何丢失,则抖动缓冲区大小将增加。 当此值较小时,自动增加抖动缓冲区大小的可能性较小。" +"Auto Adjust Drop Threshold" = "自动调整下降阈值" +"In order to change the language, the application must be closed and restarted by you." = "要更改语言,您必须关闭并重新启动应用程序。" +"App restart required" = "需要重新启动应用程序" +"In order to change the language, the plugin host must close the plugin view and reopen it." = "为了更改语言,插件宿主必须关闭插件视图并重新打开它。" +"Host session reload required" = "需要重新加载主机会话" +"Change and Close" = "更改并关闭" +"Cancel" = "取消" +"Download Installer" = "下载安装程序" +"Save Chat..." = "保存聊天..." +"Use Variable Width Font" = "使用可变宽度字体" +"Use Fixed Width Font" = "使用固定宽度字体" +"Font Size..." = "字体大小..." +"Confirm Clear Chat" = "确认清除聊天" +"Tiny" = "微小" +"Small" = "小" +"Normal" = "正常" +"Large" = "大" +"Huge" = "超大" +"Group Latency Match" = "组延迟匹配" +"Target Latency" = "目标延迟" +"Request Group Match" = "请求组匹配" +"Polarity Invert" = "极性反转" +"Input Reverb Level" = "输入混响电平" +"Input Reverb Size" = "输入混响大小" +"Input Reverb Damping" = "输入混响阻尼" +"Input Reverb Pre-Delay Time" = "输入混响预延迟时间" +"Default Net Buffer Time" = "默认净缓冲时间" +"Local Address:Port" = "本地地址:端口" +"Remote Host:Port" = "远程主机:端口" +"Close" = "关闭" +"Menu" = "菜单" +"Connection Server" = "连接服务器" +"Optional Group Password" = "可选群组密码" +"Randomize Group Name" = "随机群组名称" +"Copy Share Link" = "复制分享链接" +"Paste Share Link" = "粘贴分享链接" +"Recents List" = "最近列表" +"Public Groups List" = "公共群组列表" +"Public Group Name" = "公共群组名称" +"Group Name" = "群组名称" +"Your Name" = "你的名称" +"User Count" = "用户数量" +"Detailed View" = "详细视图" +"Minimal View" = "最小视图" +"Send Mute" = "发送静音" +"Mute All Others" = "静音所有其他人" +"Push To Talk" = "即按即说" +"Metronome Level" = "节拍器电平" +"Connect to Other" = "连接到其他" +"Settings" = "设置" +"Group Action Menu" = "群组操作菜单" +"Main Effects" = "主效果" +"Reverb Enabled" = "启用混响" +"Reverb Style" = "混响风格" +"Load File" = "加载文件" +"Play" = "播放" +"Return to start of file" = "返回文件开头" +"Toggle loop range" = "切换循环范围" +"Loop Toggle" = "循环切换" +"Dismiss File Playback" = "关闭文件播放" +"Playback Level" = "播放级别" +"Additional file commands" = "附加文件命令" +"Recording finished" = "录制完成" +"Disconnected" = "断开连接" +"Return To Start" = "返回开始" +"Toggle Full Info View" = "切换完整信息视图" +"Show File Menu" = "显示文件菜单" +"Show Connect Menu" = "显示连接菜单" +"Show View Menu" = "显示查看菜单" +"Show Transport Menu" = "显示传输菜单" +"The input reverb settings can be edited at the top of the input mixer" = "输入混响设置可以在输入混音器的顶部进行编辑" +"Input Reverb Send" = "输入混响发送" +"Korean" = "韩语" +"Language" = "语言" +"Open finished recording for playback" = "打开完成的录音进行播放" +"Record yourself including input FX" = "录制自己,包括输入 FX" +"Disable keyboard shortcuts" = "禁用键盘快捷键" +"High Shelf Gain" = "高货架增益" +"Low Shelf Gain" = "低货架增益" +"Gain 1" = "增益 1" +"Q 1" = "Q 1" +"Gain 2" = "增益 2" +"Q 2" = "Q 2" +"Chat Text" = "聊天文本" +"Message Text" = "消息文本" +"Close Chat" = "关闭聊天" +"Chat Menu" = "聊天菜单" +"Input Reverb" = "输入混响" +"Add Input Group" = "添加输入组" +"In Reverb" = "在混响中" +"Configure input reverb parameters" = "配置输入混响参数" +"Channel Layout" = "声道布局" +"Input Source" = "输入源" +"Output Destination" = "输出位置" +"Monitor Destination" = "监控目标" +"Input Effects" = "输入效果" +"Effects" = "効果" +"Input Monitoring Effects" = "输入监控效果" +"Monitoring Effects" = "监控效果" +"Send Metronome" = "发送节拍器" +"Send File Playback" = "发送文件播放" +"Latency" = "延迟" +"Reset Jitter Buffer" = "重置抖动缓冲器" +"Receive Options" = "接收选项" +"Send Options" = "发送选项" +"Preferred Receive Quality" = "首选接收质量" +"Russian" = "俄语" +"Send Soundboard Audio" = "发送 Soundboard 音频" +"Sync Met to File Playback" = "同步 Met 到文件播放" +"Sync with File" = "同步文件" +"Synchronize metronome start with file playback" = "同步节拍器开始与文件播放" +"Show/Hide Soundboard" = "显示/隐藏 Soundboard" +"Show or hide soundboard panel" = "显示或隐藏 Soundboard 面板" +"Stop All Soundboard Playback" = "停止所有 Soundboard 播放" +"not recommended" = "不推荐" +"Delete" = "删除" +"Name" = "名称" +"Browse" = "浏览" +"Button colour" = "按钮颜色" +"Playback options" = "播放选项" +"Playback gain level" = "播放增益电平" +"Loop Off" = "循环关闭" +"Loop On" = "循环开启" +"Replay" = "重新播放" +"Continue" = "继续" +"Simultaneous" = "同时" +"Back to Back" = "返回到返回" +"Background" = "背景" +"Toggle" = "切换" +"Hold" = "保留" +"1-shot" = "单次" +"Hotkey" = "热键" +"Click to change..." = "点击更改..." +"Press a key..." = "按一个键..." +"Remove hotkey" = "删除热键" +"Select an audio file..." = "选择一个音频文件..." +"Name of the soundboard:" = "Soundboard 名称:" +"Rename Soundboard" = "重命名 Soundboard" +"Create Soundboard" = "创建 Soundboard" +"Soundboard" = "Soundboard" +"Send Soundboard" = "发送 Soundboard" +"Send Soundboard to All" = "向所有人发送 Soundboard" +"Custom Button Colour" = "自定义按钮颜色" +"Close Soundboard" = "关闭 Soundboard" +"Soundboard Menu" = "Soundboard 菜单" +"Select Soundboard" = "选择 Soundboard" +"Toggle hotkeys" = "切换热键" +"Toggles whether sound samples can be played using hotkeys." = "切换是否可以使用热键播放声音示例。" +"Stop all playback" = "停止所有播放" +"Stops all playing samples." = "停止所有播放示例。" +"Add Sample" = "所有示例" +"Cannot play file" = "无法播放文件" +"The selected audio file failed to load. The file cannot be played." = "所选音频文件加载失败。 无法播放文件。" +"New soundboard..." = "新建 Soundboard..." +"Rename soundboard..." = "重命名 Soundboard..." +"Duplicate soundboard..." = "复制 Soundboard..." +"Delete soundboard" = "删除 Soundboard" +"Delete soundboard?" = "要删除 Soundboard 吗?" +"No, keep soundboard" = "不,保留 Soundboard" +"Yes, delete soundboard" = "是,删除 Soundboard" From 20b25ec9c2e5a632f9041d8f78c8b04f4da7e1cf Mon Sep 17 00:00:00 2001 From: Dennis Lysenko Date: Fri, 11 Aug 2023 10:27:13 -0700 Subject: [PATCH 05/16] updates --- .gitignore | 1 + .vscode/settings.json | 5 + CMakeLists.txt | 12 +- Source/AutoUpdater.cpp | 4 +- Source/BeatToggleGrid.cpp | 2 +- Source/BricolageGrotesque-Regular.ttf | Bin 0 -> 91276 bytes Source/ChatView.cpp | 2 +- Source/ConnectView.cpp | 12 +- Source/SonoLookAndFeel.cpp | 19 +- Source/SonobusPluginEditor.cpp | 20 +- Source/SonobusPluginProcessor.cpp | 8 +- images/AmunsonAudio172x96.jpg | Bin 0 -> 1896 bytes images/AmunsonAudioTransparent.png | Bin 0 -> 241689 bytes images/AmunsonAudioWide.png | Bin 0 -> 237267 bytes images/LaunchScreen.storyboard | 2 +- images/sonobus_icon_ios_1024.png | Bin 118185 -> 206925 bytes images/sonobus_icon_ios_256.png | Bin 23473 -> 32883 bytes images/sonobus_icon_mac_1024.png | Bin 151768 -> 206925 bytes images/sonobus_icon_mac_256.png | Bin 30366 -> 32883 bytes images/sonobus_logo@2x.png | Bin 70141 -> 206925 bytes images/sonobus_logo_96.png | Bin 5099 -> 9021 bytes images/sonobus_title.png | Bin 28439 -> 58554 bytes images/sonobus_title_small.png | Bin 16322 -> 40699 bytes mobile/Builds/Android/app/CMakeLists.txt | 4 +- mobile/Builds/Android/app/build.gradle | 2 + .../Android/app/src/main/AndroidManifest.xml | 1 + mobile/Builds/Android/local.properties | 2 +- .../Builds/iOS/Info-AUv3_AppExtension.plist | 173 +- .../Builds/iOS/Info-Standalone_Plugin.plist | 163 +- .../iOS/SonoBus.xcodeproj/project.pbxproj | 2040 +++++++++-------- mobile/JuceLibraryCode/AppConfig.h | 2 +- mobile/JuceLibraryCode/BinaryData.cpp | 234 +- mobile/JuceLibraryCode/JucePluginDefines.h | 2 +- .../include_juce_audio_plugin_client_ARA.cpp | 9 + .../include_juce_audio_plugin_client_LV2.cpp | 9 + .../include_juce_audio_plugin_client_LV2.mm | 9 + .../include_juce_audio_processors_ara.cpp | 9 + ...include_juce_audio_processors_lv2_libs.cpp | 9 + 38 files changed, 1358 insertions(+), 1397 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 Source/BricolageGrotesque-Regular.ttf create mode 100644 images/AmunsonAudio172x96.jpg create mode 100644 images/AmunsonAudioTransparent.png create mode 100644 images/AmunsonAudioWide.png create mode 100644 mobile/JuceLibraryCode/include_juce_audio_plugin_client_ARA.cpp create mode 100644 mobile/JuceLibraryCode/include_juce_audio_plugin_client_LV2.cpp create mode 100644 mobile/JuceLibraryCode/include_juce_audio_plugin_client_LV2.mm create mode 100644 mobile/JuceLibraryCode/include_juce_audio_processors_ara.cpp create mode 100644 mobile/JuceLibraryCode/include_juce_audio_processors_lv2_libs.cpp diff --git a/.gitignore b/.gitignore index d0c9e65c..970b9f53 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ build32 buildXcode release/1.* mobile/Builds +.DS_Store diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..1b572c6d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "*.mm": "cpp" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index b3feb8a4..242f202f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,8 +150,8 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr NEEDS_MIDI_INPUT TRUE NEEDS_MIDI_OUTPUT TRUE EDITOR_WANTS_KEYBOARD_FOCUS TRUE - COMPANY_NAME "Sonosaurus" - BUNDLE_ID "com.Sonosaurus.SonoBus" + COMPANY_NAME "AmunsonAudio" + BUNDLE_ID "com.AmunsonAudio.app" MICROPHONE_PERMISSION_ENABLED TRUE ICON_BIG "images/sonobus_icon_mac_1024.png" @@ -173,7 +173,7 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr PLUGIN_MANUFACTURER_CODE Sono PLUGIN_CODE ${plugincode} FORMATS ${formats} - DESCRIPTION "SonoBus - Network Audio" + DESCRIPTION "Amunson Audio" PRODUCT_NAME "${product_name}") juce_generate_juce_header("${target_name}") @@ -450,6 +450,7 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr juce_add_binary_data("${target_name}_SBData" SOURCES Source/wordmaker.g Source/DejaVuSans.ttf + Source/BricolageGrotesque-Regular.ttf localization/localized_de.txt localization/localized_es.txt localization/localized_fr.txt @@ -545,6 +546,9 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr images/triangle_disclosure_right.svg images/urei_main.wav images/x_icon.svg + images/AmunsonAudio172x96.jpg + images/AmunsonAudioTransparent.png + images/AmunsonAudioWide.png ) set_target_properties(${target_name}_SBData PROPERTIES FOLDER "Targets") @@ -605,7 +609,7 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr endfunction() # most of the targets -sono_add_custom_plugin_target(SonoBus SonoBus "${FormatsToBuild}" FALSE "NBus") +sono_add_custom_plugin_target(SonoBus AmunsonAudio "${FormatsToBuild}" FALSE "NBus") # Mobile targets #sono_add_custom_plugin_target(SonoBusMobile "AUv3 Standalone" FALSE "NBus") diff --git a/Source/AutoUpdater.cpp b/Source/AutoUpdater.cpp index 680d93fb..5aaabfbd 100644 --- a/Source/AutoUpdater.cpp +++ b/Source/AutoUpdater.cpp @@ -557,9 +557,9 @@ void restartProcess (const File& targetFolder) #if JUCE_MAC || JUCE_LINUX #if JUCE_MAC - auto newProcess = targetFolder.getChildFile ("SonoBus.app").getChildFile ("Contents").getChildFile ("MacOS").getChildFile ("SonoBus"); + auto newProcess = targetFolder.getChildFile ("AmunsonAudio.app").getChildFile ("Contents").getChildFile ("MacOS").getChildFile ("AmunsonAudio"); #elif JUCE_LINUX - auto newProcess = targetFolder.getChildFile ("SonoBus"); + auto newProcess = targetFolder.getChildFile ("AmunsonAudio"); #endif StringArray command ("/bin/sh", "-c", "while killall -0 SonoBus; do sleep 5; done; " + newProcess.getFullPathName().quoted()); diff --git a/Source/BeatToggleGrid.cpp b/Source/BeatToggleGrid.cpp index 84872978..191873a0 100644 --- a/Source/BeatToggleGrid.cpp +++ b/Source/BeatToggleGrid.cpp @@ -47,7 +47,7 @@ void BeatToggleGrid::setupStuff() activeColor = Colour::fromFloatRGBA(0.1, 0.7, 0.5, 1.0); - accentedColor = Colour::fromFloatRGBA(0.5, 0.4, 0.6, 0.9); + accentedColor = Colour(0xFF002CFF); //self.backgroundColor = [UIColor colorWithRed:0.4 green:0.5 blue:0.6 alpha:1.0 ]; diff --git a/Source/BricolageGrotesque-Regular.ttf b/Source/BricolageGrotesque-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..970fa8fed18b91e2a563422e3c4b26a6bd67eb63 GIT binary patch literal 91276 zcmcG12YejG_5aLXQ}3s)(-qyFba%SmbkeEcNmjQdOSU9~WmzuRmTb!ng9*hZ^lFmO zJ4pxuLVy4vBoH78Nq~eDAP@{8KmvsBUjq2_|IX~*so2Jb+Y?+kr1I3(6`$9di(dkFZjZKmo|q@?-vtNb^{@) zPxtma+!L3dwvrI~I`XgVA7~m_)4b#&+e)x+>W|rHV|;frm?$O-L2+$a-Y+)``vQlo#wn{xsxQJwRvn-7UWmw}j5jkW5^Ou#~JNDzb?v+1;E! zIm?BXZ;E|Lh@x($J9fW9vmg&E%}U{TIHUe+CuY`tLS(YHSS^1^@4T5^58S04LfJbM z8u=RBDv7|L_+zyv5gAf>9A+cJ)aL2kth$}6x2>ZBp*z>E+eRs#=ArjwxC&H3F9FWz zEnZ%rnPfH6a{6_^6?k%u3e7?b^2vmtP$Ps;ZvpN$;g}*n$N34GO(@N!QJiA^$#$}jTtR+AULx<%ELuu!w2n^D?P&8-dM*74 z{T2NqeU-jT{{vb#3bzVB5I&X>S(+>$+bG*6`?l;Cvgc%nSITJ@aj71i6S&yrG;mL#o8+M0A)(s@b0 zO8R56CfSngPd+>OvgGTMZ%@8I`Cy8Wa$?E_DG#P*r*@|3j(Tc5T) z?PqDvrG1cgD7_-xnO>LPo<5MiGX0|TtI}^vzd!xS3{^%!hB?EN(U7q>9M7D}JSFp+nKx(NmHCUz=Q2OZqFKwcCbG6Vx?$`AhQ0@;B!1%HNy+%ltp&A1J6RXe-!R@Q;E|3Ta__ zVSVAw!ZQmmD!j7rmcqLVA1eG+;Y)>Y7JgVnic*U-MO8(uMO%vY6rEdiMbV8#cN9HZ ztSojFhl{rspH_Tc@vn+!N>WP-O3WpJl2c1AD7mKO+a*6NdB5cI(w5TR(vi~dmflzT zXz6cDUnnamGn8FW_N=B@vr==G<|56HHBXjjmY0-ImhUbYShqsAUbkI$hVBC0^}0uNPwD=odrhCDH|W>ur}d}l z&(&X{KcIg{|9^%|Lx~}5SY)`~@U-F0in0nv#dyV46%ST?WQ-VB8h>TdnEFj?O;?(p zG5yP2Wj@9H%}P?awDN+=+bUnI%BgZyZLIon)t@X4mi?ArSzfmmSi7wot>3mDwB^`N zu{~p(sm`fxs-CL8p!!jJioL>qw*7bZ7wvzuzhnQz9&@N1S&kxy-eGmrI6537j*X5z zj*A@EJMMNo>iE6mFOJt8?>Y`TW}HdRY-h34;Iuh?&U$B?v(LHQxyrf0xy`x9dG;}W z-*kS*`LOd@=S$AFod0&^xty*|uJ5_-bv@;J&-IyGh%LzsCPm zzz|pz*bz7@aB<+8z+Hjg22+EL!Lx%;*H~({)I1Q%2%QvqxK>`W@9NZbx7GbQ ztOy6fr-ttfKU%M-KfnIg`d>DXhRTN8hW3V)4Hq;0|Iwf-lfk2oR&k@b-?Bj-o1jXWNCGxAY1KdO(~qoHVDbTqmydSUe1=;P66qt8bV zMBj~m5ak()!wPS2NM5~_NTgB zUA|7QGwJNQ0o@6@%k_d@sn68s=!^9ly;a|?U#Xuk{{u5H!R+EBA#ww`mE1{FXg<|Y z6SY%6t)We{gZ9xA=xVwSdi*Z>TcHp*J}Ep8O{Y3a_=YDh}A+P?0L0`S?)%#xkp7{LL%W?msS8sl``Be*kS+5Sfy8PAn z9LuvD_zQkd95{I3u>-yXu(1wkab)69zVg{C@4xcfSMDO@g z2$h(1>x8J#E-VpN3TuQ@g)@b{!rj6>!o9-%tZLx_;W6PUmWuzeJK^`Tz2d!Wuk0Mz z1rRP+dJF$#r^!y2osH+`Eqp3F8zs&Yk9aBBnJh(bp%2l&(#PmQ!9ZW5uh6IIGxTRd z3ca8Hg5F1ePJcun5VC~~A&WjtUj;=)q?nWw1Mw0cWVn{Jk#^ESdPyG{gsm_|Hj`~+ zH`zljA(xVGkZ+Rf>F?>|^f{rBJ|%QO;(tsYCXbRQU@88Y{Dr(s{z={;{~{lekIAPr z8)G4l7DCc=)JuIdL~CgaeU`pWe<$SATj`JK$FO{o={xjwp`HGnw$T@b0{VuqguW%@ z(QD|nLZ_gkf1{5G{q$;#q`$xh`8qwH{sfkhKvH1OWWgpXBxM+X6~shrq?v?CJ!!y* z93U&n5LrexkQ0P7auPWU#50Hn*Ps#7dljN7=Y4SRG zg&ZKSlE=xvshoU9KBt*f5YlM|HB&vUphj3HIkX<*|9&iu*Bh};?;wFC}M)C{dC(n~0d65Lj3mAhhktlf!_Rkw6Lf#~eEBP&{Bu|kR@^{ii{zguuGBQRLWH~uRM#u~qrG%`2r9MnzWSpwV z1WhJuXbM?NQ^{(YM9!opvX@qpv#EugLv7?-T20QQcJg&CM41SqyMI#!Fr|iKlD@jk)RahG)89x zfqqUu#OOB)Cc!Ke3uQvNkSgQ~%wpHjNyrA3CnNp1JYPyvVv@Ztr3I29dreBqNQdlO zQd&;@vQ<)AK|-=hDXk=4;bSSCM2dwMrF1gVKaq zl+r~QF~1kn;AkO60mm7fWj!XQ*%-S;O3NVgmq=+j;Acx|#Vjq5qBQ6Vv8)PX^CT&q zgkG2ELT}|jw}^RC0B@JlsYo|U=`^H+QaT;^O;S1ox++adXCg%~MyAMC=&3QX5#wY6 zsr8VYDKd$*+62ziIIlhe#EbfwW^+UDv8xNR$gUBx3+JtT3`iYJrE zs|C-d$Qq<}0*kGvSu5q(i0e4+;~dnYU6H3-k%!U3^7cb#b>YfrVR`4)%;=x3!G>pp z$g`E>##+~c=XQQ*=U_I!-8eR5WC!qLG>t)yHuAQ2;-2B51&p=Z1YOC}+rSg;SL6`u z!MS|h3BK$EmQ21_TkFyCcBB}u$H>We!un|wIDE8{jHhGh{T(R5dWBKWdMIA5dtS|q z6Y;v6(9Q&CWo_6t$6NH&dU ze>%$XIB@u19={~@tUlRusCOOO+=Sy7NbkdS?y-Y-goVd7q)#X%g^A-a(kuM0j=iK* zc0186JcKQzTxcTcUwBj!y)gHvB6i{b(;?f9x`#=ZU?A?pj$!bO9ep@Dh)Zz&_XljV z5}^h3%{_Y1e)r6$u(fNka_Pd+PClCX9LFJ~YdQR5tT;Zx3gaVKu^(a8@zKmd`T?FD znt6d8f(CWqz%zEVN!MDslvrdZ;~8sX;n54&AZYqB$6Dk+(y^cp*+a<3_$nSAdLHSL z4i~OrA%j#OcASqqn@L{$z*uVi!ebK8k8~WVTrSCx8A;*7LlB4>eG&Mg13MyydB?@1 zkY0gtb2dNfVBu?p8sZc>acx2W_K+H352>SngMGXQ`fDfb;gd-%wUH_zmH32q^#2&C z5C$-IS-!V%e+u%QOd5qD*xEzHio=Pc0!JQ>FpfCf&+prD-%e_!qXJhojxY`e58`mM zdwL&a<~?Gf7ZNkQl;qRffcrOyi{4FabO|Y?-zAmw`$!*ezSNluWg}QiY$7Ik7BS1Z zkp3IVmu89LrC9^<8&O& zIM^THSc&D~FyUDN!R`Up8l_kTQsHXce~Ps)4(xK}gGX6B&-3!ER_|zJrkgGzTKYNq`fVJ&sDI8qHIgRmh$Yc6QbyZm4q+YKPqkRDuw4r~ju27f z$RyWe?S4JUq!$n!jw-Cdby$Js(+aHR_Y;k9I_9PuAP?^nBjmy)=!g#<7ME}u(a5gE zoHT@dH(@@q;rf4kjov}G0N2+*>lox5`bwS-{810)**dP<*mVQsVlnjD3(&(CL+0h&fUFTTH;;O+l@1}WC0mi(up%6d{+~~hj~E;4~K#z!GDqh|3@199~qFatRv)6 z9Y-GJVR_`ho3)pL%WQiKTgx6B+qjLqH9j^yL0%gl-?W*$xO#GG6ZylMtz+Zlo{f{+ zH<3HA&%2S_#?LqK^Hl(ECHtq?(~G9IuAU@kZ)WM!r`J!eA-kuyubL*?rnhgNCX?G3 zd>zMu`MxQm5N8o9cuSFHG9kbZq~>=;{LK1}f-~%#%FoO*LNSLDaH#~|yK;;@1N>xW zj6*B@W)7?iJ@7{ccs|zO*hU1GSt;fr7I>;A`Jtpn)oZF8<>$%+*tKKF-PprBLD{El zR$A~YRc0uO;xWYyiqjNp6g>*RqEP;b@EzeQVYf0v7{KAjk+004ALDoy$L%=I#IX#A zO_@PrIG)CFi;|EtVZSp8VtdIH9>!DxAisk*LvbfkkT8r5mM4farMJw@0hy!WnN#&?nhblE#NF>fuc8AnoEh0KlAfMZUO$pf7AErzq$NoVIF!6-uiRsM!JLs zsTRJ=56MgLLf?yd^#dPXlXzuqvOg9r!1A&&5>L%O z6C*9er?ctV=L%jnUViS~Y#wDIk66$A``LV|Ir+q#3n8<4*@&9^W7r=Ko6V1Cf(1WT z;z-chGE5p5{#dCa!)ME-9#)Fg!b%?PiCC7>pYxJzq<7GMNXE|rVZ9|j5oJVxPqq-x zJF%zKO?zlBcH$O8BKnUAdy@W|{)YY*waDoJU4bgr!Rkn%PtYeY&;5e_3YwR-F6t;H zXp6T_u)nvK(>nWwcnt6xAPe9G{;RiXKw~KKVuZPX6tgqx)56Q6Wb05+a zUXwT;@OI-_8}@H-uzWZMv2*k(9~lD1WD1wmjes*<&&shn1>|DmlVbcXd_qw^UO$Cr zr*h7n9^-lTS>7B>C|Zn4H22S=t%6e!rzjs9Dn7fhrH`O&KAuqQkTDwBnP9f3 z*zscb>`XBK&$cd(4T0~?%!P_0>t)mzZs*!@n>vyiIY=H+2ARfpFj%0j#zIr7MP ztPjPmkso$`KnM~+2yvS547-Fcqs71BCj+&N-hbjJjwvP|FXPFZfXvER5AxU`Cvxb% zeApc+LIY~_2=zGogfPxlp$=!;oE$AYM>EgS#B((A9B2o4xzKi;hs#J6_Pz%pp&`T{ zX)xOf*uQ)OJAp4^|L$q%{5;{fMwz$aR>1E+ZFUSLAef@wdUtyABw$agQ-X zAA#gl;_eChB+mU9Zvsa6D9(%d+NO^VBi#$XmH-W~4CijFFRhrntYz_}mw zv9g5aG>1~+yg_Ujw;2HY*D<8&uIgI+DlTnoTnPjb zZ(J+vqHW|g@V^w%2WQi`mZN-Z4Z;V1Gi2gZ#8un^9r^_H+%KW&L^}|dnQJiOkMJif z1+aqriV9Rl<%s7~B03|9{DLMU{vnm7VJ~$R%^=^$9&Z-ShX3_W%)3UcQx9REaW&1s ziXHpc*qN=wE~A?K5-}46*v&4&9_v%UrIh@dmO)y|sTOvt1v|z%swY-zz-qn%JDIEm(h9A!XI%HRvrDA}}1(i5*NAXn2)q#{)|SjqZ{BH4U#`#UHnJv z7I%<89btAEK>rNF&mTe`E<+y=!7_zYfy>%kI7c0pdSk1O#-+2|JU^S#< z4Wwut*+AFB+S~x!WfS(IC&@{4if)E%PGUFY2JE6mNen7wif)B>cbZa+<#w`}!siWX z*#T+VMNh`w^={a|TObpAATwXXUQ!474<7t)KMEBeS{dNCyHQtVz|hS}m|?15hn3B3Xm{7vj;e~avf)L(@d z0>l&`Uh#TFx!g!@Bzv$w-4CrjK$g;*5W9E_8Kk#j-}!TRY0f1>*ctu~A_z`{kLGl8 z2E84->EEMw(C^bbA*FZIAJBW~59z&#s< ziv8-JkvHk1G29ZfcVJQ5GCBuKj=RZWAP65vj2tM?Dr9g z`62xX8th~GG5rMI%!BkG-`Qq++Mi)3`w-vLhN2Jz?0U-)lcB_(cao4Sq+nM&O-M)7 zW`>X{WFc}SN5~cO1htSa6d+2d2z%cpLa9)O6?!ICavDSs$T3>=uwj2rz79XL2D45M zX~6!t7JB<0LVqmRgFEqajF$s2P_W7}}n0t8i>pr0tkvd_- zuw=j=_de!FEx8!$&T?`E{5_Y$moNrDKohwPbILU=dKNJfSCU(WCTR8~@}$r#vU6cViuX&IPPa=!s3xKun9b#OH7S?Q zk(G#qX2h>pI*V3BDjSuEi^S2C(2GRUm(D|Lsl?f(B4-s#x2~UDt6a+Ys~qB3r4Eg+ z-#Wg1)0&MFyOM`iubWDiF6ru#u0D2!@Jk$S;`b2#_+XIAHPwjuo0_GoR8NyfH6{@|CJF!e zEGDZtrRi7KXM1+G=XGZHT)d`wABsH}^(jxDEB_MvqBY9h zytvxEGrq}OcfaGb+ z8_;hLcz?Pw|>rK3+G=C)Li9QvEEW*aA!OHkj+0x4{#v4VIAF zU`eqJF~!>8`B)n~pV$UZif!Z7|n2Z-XaT8!REU!IEMdVv4oF^RYH~KCum+ z6x-k#c^fRn#K7(H@d1IWHyIq``PQXzPKoL1RK|NLoyMz_Zg_cTkZW+aGsqUB!>Iwd@ve8zGEF_8~$u1MSgac09+ z%IEUuZ=Tq?erh$dT`(oB=K2#GIVDF1+u8m|>bjFRufw3>>50kJW7F%T^rl3bHS3Ic zqRLI{Cz*zto*18+TrGC0%ac4Yy$uR^+e929kt0qPZfCPEeSB);)Z`{~`nIvHC(Bn) zO|F$kwr`yh$r0I(d=gv4*$ej(`Ns8I$D~XW51RR`?RGZB8S@D_jG~T*Hk|ZCaJgl^RR2Ch)8|RlK&?u`MORL|OAVIX%e3(ZIDSnJd~krM>Cv zrlvNGt(w{aw#VyqN#$M5Y0#akCN@s(oP8+Lgv^Ru)kLnJV0pX8j9Zr##tR)VDY&%M$ud=qlgKl5v>PksPjlnU!7DyW^-k;JkL;3 zWGTp_(Fhh1OiEv6+}3 z1v?7D7GXcIzz*GXt|!-k*HQvLox1d`eQ&LLEbXyWx=+}DXrs_}=)wKbDE1y%Z-8UXhH|u-m78f3w#ee;%z}md-{=3tb1@(D z`vF6_onu&nRogr)sYjXbar@1le5KN$H<rYtS zHisPH7e$rkVpE{JJh<{(-(owhVrxx@Ve2EWi`a5( z1p&3nJQurL_g{9|{<-M9KR({OYE=Rc*_jD$IuNrk%gz2o`y9@>i5-CiH{<1Ixhdw0 zbF*K<54*MVF!Tiq)QI<=$HH6oUw(P%2@}z|c!q&x@A%ih^{oWQ)*OZr;~2+?bIg6% za}Of%6VGJ>2}-N5?&g#-xe)dz;G$f_IlP-wfW7Cr_{-+^{@)gKcF!!nvWpV+0?%2_ z%32d}FWzSm@o1fgM=gDv@5zhfU{4~y8!P-o56PA%;2zd<@P#11Y#BzH0)CBjcumys z0l^jKQ5h&3Zv{AX*`90}u9S^G8oEAQ5qqbEwxrO_u@gtFv?=yeIwkDyIrI=l;{M)V z)+4mCvy+zfA{Yj-l;HFLTF8ZW!;ZSMJ#LMl&VvF`Gv$F1V)nS}1)tY0GZ=hQQZN|$ zKM0OA>NU;2(E;D4!Mh*S`771AdUu2I%q`Vz?vg@l*m$9^KhM%sZ4MceQp(VQ% z<73q-j$Ibx2c$v7E(Fgk8{Z<z~N#@;>q=gtoIT+%w1 zfHZnWd+ZlSZk)}gXjKQUvDq{g^C^@4Y=bnC*l6k>t)|z<#xRgBq1Q2{^!8F)M+Ys! z$U$%L@?3_%9VSEY(Ory@D#G_B>Sg+JLCvC8pI3iuTU@Wtwn7`YYEQJqG_=^3gM5wa z4c?ZVNd$wN1rF!99N>DgANo+oX9V%Nh5U)nlVU!lh^xGR4z5hUEWp+n*YNWZo}Q!Q zXK}t@j+Pg(V_JSbc0TgBh#l(zIn(m?d_J2-< zGitf^7xRnM#(RXlYb5q`?h$CjEHIzEcch76mb7cd*`mBpk@wMY%UPtUU+Vq zZttII#rt7wP7>j@ERH8Z9n<+D+{5}5II{Xn6LQIWBd*{3M+0>PRv*W$%Mt!nY& zxCY$@4O-2#mdO;?pam*uZLUBy(5O(L(BNvdAz;W5=)mHywO4j;?(i>fsgy61X`D6X zmd=1ySJQ6xb~zOL-|NiHO!qHK@BHSL#itKDOTFE$!m5xVtE_&ay>p_rxN>p*qSXiP zYZ|nI7N(iDaeK_id&-5k7#Zz#GX?>8fkqKtgEzY3nrs{IK@n~NJWl)SS=z@SiShYO zNE$u#-l(14!D#37SFssPj_7G3yqPG2am@4uol~++xZ%)BK{0aZ{gG-Ew?$$_^Xs6D z=j3i)2j_SH3YLNQ-9hYW?3bIc-^F&o+1m#U|32J(#>YN~W9-*)dhwLZ$aa8U5gwU& zkHZy!e=b{+fVa+kz~Rk+|BUlN%x}RQ%=i|aX(LZ?nTf;Q7`Fnf07CASiIOZz29w(r z9V;XY^)+s-c#!K=Zmo!=eXxL8tt|HL6B)BpMR*&c*cn_i(@O45w5AklQ$XWP41y(> z^(AsgXWm91QId>U_9XBMmg-_7L82W~S{L9Z{&OwCdG0(m19BYmpOAv$S!33k+{Put)&3>*j$F&y z5_Qdr?pk4g?1|jQfiX{L%|Js=da19=wQX5#zcuzAXy}Kep=My)4k}fMO8ppDJ~z_W zBr+{;&aF$F+vnD3ljf;JwX(g5Sqgms ze83m6_8N-F&qS+C(}{2o)0nK)nHH8GJANAIEwgCk`JkfmG6XEljB{wBm*k}6s5}An zh}zLtt4xnQG>6ECmr`2h(N#K35pOwtcrMLoh3Teqpc`|rTQAvkY-!A_+zi3YZQHn+ zsS)U^_D!9pu6=_o8@nu~&dIj&XxJ1O_LoKLD-E^Lbm#D%?&&Lg?90zs(z9o|vo}Am zrtie<0d;WQK=(v#A)}VJ$9X&`@wkkSG7-+^a1rjn+wg4kaX6pD8Jx}Gfb+g7<+ETN zX0>zp94^qG69oqbxq3AA{H_^fX(<9gAq;;yH7^NDZ6w=TqY& zGZHoE4L;}3f9}B!IGgiDE)68ORE3>hkxSqLpGjCb%=w%PvN*Rn^;O5FJs0}&7-T0y znI4nm8$??`#Fp6tB33@cF|c`z!-W~dAeA9*gEX0a(30HYAma<1qYI#r+*xf>$lH@L zEWi9hQ52?C+2vlHyQ%EZ-Y+GUs}@KlBNuN-i!i0JBSN^=iwEG+Q)iv!C%nZ3P@WuB%EQ&L$p8md^dyQ6D+ z^IKRjF;{~)$23FR7c*_Yldb3AtCYM7qRYXc!fd(s$~>>nURrAN*fPF%Z)mKovSr`I zW23+Bk!9#Yc3V)JF6%C-84N92#vkp>lBP1XUJ}Z@WnaYCt6`+QePBypMSEMMS<^H*SgSR6ZE73dx5&Emj3HNV=MqosfU&*S zP;B)Ei)%)Frn$Fk#k}D?{pR%kzKUIMbq^0aG zs9D?BFkEZM@b5UWXCjy{Sv!a-*^l=mEPNh!Yh-MeW9Y>VEHyklanAR@;at*WFH~1G zSPcHE49mDar8;apXEM+0uSO5JtFulM_Gf7vVY5DDD^;W^N`uZT_E|jzpVEjdwbW%Y zyGqhz7)8vkSjy+T&7yW8%vKcFGD~4sFnpi~VObmlBhjV8@v1I55?;145wC2lKH&yU zASX{hGIF$Tu5|+5U_^;H*5HdR%qI1~K4?K7Vi*95>F_Z4zHU zMpTd>!S@1ZSn^*MYsqc(rEq_nS$$uU0NJJE<9(uM+B1{Icnsc)bc7JGCDLb@2d_b_ z7VDEf^vOo_3FaNPo;3$FGQQ407hrY4%{7@i+mP+82OL9CrS^;7N_w@sqgvH2FDTb% zmiqL%+CImPvaZ^ynuljZbgN*W@G>drcK?O`5Rij4GSj zV704bOX;oJXp_IZswa4^idOe}{6k)F9oDQM$LL~y1iqGFI`qJ3>?QgR(-%T3mJ>2D z7i6C0N}tUq`h3LPv7K>e4=Y0(6CV6RSkPzzeA>c%B*dSz^buixn$@X{+{YnxWJ=pj|SHZE0r zM5&@Be2x_1Y*$5uyYP-9n>$4~vs^{E1K&cLg)>`CgjXSAPlRJe=TwMr3(e-MSE*f4 z0l)T<>0sXY!)Y01R_Iaa5#Hl#Ua@XwiHU9c@Wr1vjxWm;33vbzfwOS7BgOKY5p~X1 zLTp78=S3U7x)v`t`&^_&#(DBG?4v@&3|AhFnp|@LcAtqGe#RqG_6j^!hIA_HN=mPa zUH?U7?n}zc(^cl#n{|_-?a3&9nXmHaQ!t-$W(%(DN%w;f-dzq9<=4OJ8;R~omqrx9BA6YbS&i6Pp<+kjAu_~vyG`V@9q&^^% zrIeMHnTwQJaz(CFotlcs(sf7aZl*Ov4EH23bmJY)c%M%5T@(>>PANtY+jUuo(SuPt zCc_Fl*CV6k_0>N~`RS@RFmQh&w7`r&KKPnt=OQ0li;MYqUbegWr2xp^5gjZ2B=d)A~ zu*f|e4`x~~#AUPSsho$808bDo!plq-?Wy$iY*U)uB?#dkNobYSD1if<$4 zza#c9niKm`>^`cFy^WI4T=+ihe&%tS_DLnxAH8wXcjUKi`1_yeBeARLM6CHwpquC9 zbbnK%8$WI0W&9-0L;e`@D*ez0DQvQT4{^+ zS5`Ul3hhQsolVuBWUT3`uJ5sA$rQ2yK~B>%++9TlcDp&VB+J*>=+imVwT(`1y&+4f zOjWB(EQNVaONl9DQ5(V?rYY^B4y~?PZ*H#Y$kcg_E96<($!U3Jow*8qAmaNr=(t(p z(eL0{jKhDEfVKK>hsoVH z{`D)boaM!z7x03~h{y{jBR4O2>cM+CFT^EGi1Se?RIL+hWcuGCjvnV>b6pb8wCqo?kb;7Y-}N8~{(eSZ!QYVjUbg4@EoiCWzF zYUnKdsYERvNTdK+`%tzRU)Jcsdo4$iGcgRpBkFXO!e+ zc{$YlleUQ28eL*G*>co2Lusu|*`E>|4pxON`KfY)w_fAu4VB4bC({wDLK`+)nvKSY zOJgfnD;6hL_@kEK@|v`?w5niBdcNIi&de{2b~aYI(zQ(vZ@oSn^FThE2h`505?8w^ zud?1^Z#3o@+BUSy!g4dVWL(3I;lb*xGWhh3p{jgyXTTV)F6zkCx(qu?va-_hDoy4p z@BrUw!CN^G!9T$L){Kw>16DUY0L8&?|?8vS3w3z@#>` zc`YHGqF;##HQm~|(i>XcWi7PTn+i2vU8%R-UN>mhV4ZJmsV;!bi7m3Z@nLC>dl6Sb zf*(9Q2IWY&NNf4y!00#3);JbgG8td8bL_GhKN8r5*tdBSSU-_~Ti{=1STj#W#@wDv z_)SEQq^y8%JM;aPxvoemYdXQ@SkWA4v!rCplNF}V0OVO9mh64t~HHdZ)P z#%53kg(b2>v_$^Q=T{fjJ4xIUVNaPQ@(0+myeyXra2%EhqYv*Z9}k6zZN1|o@>ynR zu)VHh(kb-DH~40$dVT>_KI~60t3jlh*%WhW_K@wfPX(quL_SqW zImC1j%gx}7Lqc38z?%h8dPnPf=6X3krVKGt;@AukZEz89ws$7t$9Rz7kZ@lD?j?JH zKf`+oA4O`mdc$r)!h=#EPB7eqax6inZ>#-oeO761cT%RQG`GAw^{2-*+HO_K(zKdf zT}g`Dl2Kr@=I3O~X*F2D8iaDFmmC#%8F-&8>sldm^AlF+3D!v-! zYfyx$X73m|v&4{Xj5tkUb!wi!L~qF|O5cN5v^TaVWv3YIB~=X->YSxH`BrO@u}IY! z+s~pY^fUd4=1PJOIKozPVq6paO?u{c3iw3kc|2-!JWy3{GE0_`xVx`Zie>{;ra^p= z>tMxv@6v9*bsbib}O**4$lr;jpD~_fX4#skpK- zb9=~Yj`-^vn;Ys|%WJ=1W~T%0vj>aG)H3Y9D?!`|lfHdkcJM^$Q@ z3AUROUlKUydbPvlDhe;IG}T8M^JDK)xvn{22%cDvFT5a9h(LDP>}e#Vg+*k3Q9DYy zHg@IW6@o$~&*qIa8M9@hN~tk6Ki>JpErJKw*&q)IPayW{uaxOjin*#66=u!7AB4b(?nLTi3F7SKE5oN*b!h}sqT?>Xc2~&(9hTE&{E_DzQ-=s z?Bj7F@J5n<32X%~LfbxK?d2mDYZeQ!Jw#*)4DW*|aY%SHQ6l=fh+!wae*uPO?7w}2 z+`yDpFr75>!b~ULfM+`PZNR}z7~GUYe*kVGG7KwSvpHW3<;oDs(lyyhO|_#r#=w0_ z`9Nk_y^wY2Q(J2_`>#+;+LDDIFO1^y&)H<`8Zj@buTDEDx2Ce643M6Or2I;u1~MhEy;5r9vW-4r zQCqp#RIyMY7F#k*cPw4BH1?c;_C(5MUf4mHk*BlqvYt4`1oe@|8n)mQ!)|eMR=Ta( zV)7euGE?jkXaIedd_~Az( zT^BNYSA;)^7H7$J1L%}%)kbo4v?hrAk!8Z?PG5b{lGY{D-Vm33#^26JVUc?;1WtfGKDV4_A z9-7Y=dR9(lfhtlzs;P@zb3|-!S1J4R%j(MVgI%WEkA^k)!YqIaw4TXgc%>OidhLqM zKFl%8WPnZYShLzXwlubEj<#)SZrajPf-UwkN2s*ek6;H!D7|s_vf-U|4JR)j-c{F` zYwHLEyX@**>!Lug+o5J05ZhuJ4!W3owEmv3HY&IsDZ(Ah+KA`p)+d9rxH4viFkkB5 z6ZYq9IWu(HU%4+;%qJJyg9XZHV_%~=CVdIN*B27H`*O+b{6c~SdEDeoP{J(E`IPwZ zt);llS;75S^PhY06~@GKuKUSAAvX+o~pOiPssd79-)7)nXctm&;P^4UsC?SYa)kFB`G=1*(j%1_%C^0gU_i`KWw!m?F&zBYF{sV3&&XvgkS#5ocRs zY%gANBC-uKjjU^lA~V(2>WrS~bgpRjw_8%P6iJFJZQ*ilofYmUby}g(eFHutM$f5k zF-A}6?cE))8$;z;*MI=vSmtz>?%v0Zq}t)a}~Zy^}r29wc#>brz3I-^JiAIRp(f2 zmb|n6;us8Z$EL@{9GgJ{aPojR8FAi3*aD431u{ftolItrDi@O#j}c6`m*_o;WO-Jq zwJp%J!r?eE;)z&NvQ+()eq8RZC`?tGYm62+=IU-ZuQ*g&YU!+wp3>8MO4QV1`}(2S z^4CP~sS}o#*!><11tYlMTb!u_8B2$xr7SgEt{RhL# zTyn)qrP4bT{19V}*>=0Q{>kIo+;$q5Y7RY!y0I=jV(oG3q~q^L0_U-N>-xCzKt!dQy2kg;@se~qS_Rz#e2O%;t6 zME_N|M;jYPys}=ZtE=>djSZFNMIpU^WqN@%Y|1sbiYpDJ_hm57t>R9Ji;>?3oiswj;w(Xo3{pcq-4l$qv?rsGB44l5kT|1QTyNqJ4L^PjOl zzx2JvB_?1Y*2^Rgeg`gbqOC5%u}d$(UHBRs!%l?5OUmK!bncpkVr42p@h_rz-ZqAF zq7Dl=z*pQ-o1g`4f~QBOhS?2Ap$Km@v>lx)LG?w zLVD>zF|4e*g@u)geFRKq4x?l~2cBB+Tq$^V&h{njBZ+U-_*NdXk3@dLK9b;G{2ymA ze=9vSrT3U{*}n@W}`k)4{RDqR?sTpU;D+^2<1E~Qwml3^@9@^re8SzpdgPe zqCYzHIdVZO%F;0kGBH0ai0-=Syc5=B;wwBEYge5AwGF8o1O+R_OMXW0i*=%9u{4u) zpV+gsmt!QtnM{jt2lGTE@-wLx;Z@`fl;bg^z=EwVjuPFq5SL}>zlHcPzY-|IJWAgM zMTn4^Ms!z!C*YCg8q5Y&!CgPtusiMKlkWQAhEvmau`ilF^GxheEcWcPC>59)p#MfG z#AAz^lLeAObBcBW1{7O8vv^w;HN=8T@iElO-llwe!GO!rSe2WSo$8EKdzy^!V9?Y8 zi%#d#=g3Bq)D`}YJ93Sh7JY@bZqPrmXqmaHK3bRk%9GhHpS{e`IOw@1w$I!Z4OzMW zOT>e5lzHCRx)gpea886Xjxsp31mANPp^Tp*v}!xg8@q$ilBmN%Uih57YarDP8okF& zC0}bCH>GxT%kfex%!und5i6!uM2da*Qt&LrOsYlNJf||LhDU)uihg2m_sxkSGti3I zEA*<^AE~XME>G+3iQSym!)g)pGk&&6{JfJ(oCrTCz1ugZCNUmuPJOW(ur|MZw$@o2 zNUVc#U##0gZs2tn;v2kMgzK;m1I+umQ3<4e3Lx$Q;jYI6ovXS#xJt$~&nRO^k^g{g9RQdUM* zQC4PoQC_LFEK}$5soM&?-u!G&fjv;4ZPGLd>1nF8;-bP5HuCWG-95lHoy~*5RkDAX zH82}qAnp_Vx^LXR*wZuN=yMfVO3SJX^RZm1rkYhJHVs%-jx{c|G~@>yu25mV&*=)` zm3cAhdlJ1RzGDsx)Wd%)Lj3fRXGdZ=!XP~uOX0_lde|4L>tMljAjUmg^c^L3PuM4W z=De54FoN%>rEV-@Y~9(jWLrZ;WUS6uZ!flXdF{QpH<=LI?^A$dv*G+X z;pMgEU|p#_SnTMux9nc>R_xpKzUN0byF=3%C7yO`p~YXGUKF&|G!_YU52$F**qthh z#aVcSuQ^IUl|i@y?+4W zUB%U*Qd6tlU@uN#@>Gn|FTfWzm*Q(JVy|V$)aR81mes{>r{DK1uF}a;M+19VKw%eL_b{Ey+t;lYxrQ4EHg+P%-T!+M^SyX^#LwZgmuRqt+Znk}^$MTGL_jj|NJELv_neYYFX~tZFctYBW_fhAd+^v(VAzD6n`+ zQp{~D{H1w|Dn$tv9ruP*+h`T~yWKuI_SJyHZV&)#0Jtjm^6U>c^v| z?gD$er+&z88jRpm5KK0(JSML}6DG%X4O2E>KcUQ_RkqQMi_^->4t>V*!7ieI0Y=bG z)6h3;&S0MM!_|%NnIdmRz*ADK&qe@`{lvDqW%kl)U*R>he&m82t5;KD&CodYnRsWa zqSaXucAK--Cgl#WHuN(C`2Muwi*=2(A}kCKhqX-AIBLq6B%R#+R$Y!5UR)7qaT$$M7(P(@uswe@2Gv{eC5OB33HrkP%#X)0Vp9iiNthLg*e ztZ>txu63;4aFXZHh;SkljXk-KVOo#afD)9Bdz`;m)8K_4Q`@?lL0Mb0t2-Tl$~7y|&aG zb;Nazer6?o8k~Wy8JeqWE-MalU2_LKj+z^KZoU@EM&38%*|Yz9C$jH?Fm1zV`yXqY za5vXB>!59{O*^}bLtNWb^*EWfF>q~DsB5-aT8!(=VQ8CZT-$`4acxu8<_?M4rrf+h z+n9?|u}x?4N!rF%J6GE@A|ir~;r~M0xIF`5qkK?aR^=}CM5~y#NmZ8BEP}T2mjs7u zm+xt**)dhwSYfQuRtEK16?NY)Mxe~UZG+wCqiY*!U(8xF(xh+LvZ#Bq79XPu>T4{8<~B!p zO?6R$wFbt`XM_6^fH{0$D_YmPd- za#8Fz_^<4rEl$;z@sECp){Ys{!S*wcVeS08*kdU|thzQ>l`jm-yqo&l)`ztIhVrNA zr5k>jXLSb3VeMpBwz_jfYp1%q$)9(bXzf&h6DHs$@!=@ej--N0>qo=P+R-?JrOqBl zWY56A@b1aa{@S)WTvof|=;n^b8?{LGP9AvSII_Ky=UmoVr@nDCS+{hBi~jVIwT?9# zPV&yPcf!2i_8&tF&CX`DvhAeMpsXX>*`KEIm~>8ko^oA2y(xBQc3Ot7)zms{ZQhbF zc*+7y3yB7g*_EHLc)S>?#as*V_(#byKQ4=hc~)uY)bnb$_FLNn2F#-s0j;f}GAAi1 zS+4Q5R=9_J#r~y@MxQp*5YX0jR0Iw;ck~@cGI#nT4o@yLb6mO>+B%PDTh=X#Ef?^W zt`P^j-@$t%*%KFJg1wN;yy3K5gR+l;a1=_mG;z|eh zt*gvo-8e>YXrei?+TU0QTj#j64{V*IYo9PEGJvB0Li^|)J&1A`P?S{K)UIZ8wmeCZ zswnlhR(J-z#r`EV1G^f6Ti2LEdcCjA=+$NFgQBfd_a(J|sqhn@6ZEV4w~XQFf8RJCaPgkk$IEA6;#AANLfa8MSB zbabVaxhk~PSY@rr!K=;>!1fslHVs-TnwA~Y_F-Bl<-gE6?pNy)NOZ&QV%-&5#Y+*si*&(QkHYufa_xYn69e6(G<`elI<`$%it@F|AjGbm}D zAUK+J1gq!%vih;s*qQYC&`6{9hOV2gy(l=(>T!cA_5WV)RJ3mjo0_Utja4?8>o&C) zcqztRyf@!G&QYoHLljF8H)RGP6(D56s?uCG?G^qn`F7nGtc9{FHLhC600iskl@6TJ_ahl zhZ9hnugTICm<*-*jBeW7V{63=1C{wF9jNSI|Nm%v4>+r;Yw`c=bEo&YQ|^>I<<6bn zm|kF*Mj2q}gMc&-n^ z$lUw?u652G#*&x(KL1b7z5DFm)?RDvwaeK%v9L5VFW{^6r}WOwZ!6EQEf1tjjZT~- zsb^Ei6_i0&lH5f%U22n=n^X%WLP1MNZ0%8uU~a2kUcUqT}qcPJeK0 zX?p4S#=_F{+M-~6cA)W;RTGbEN-3!JrxgU~?lXgFwJkn>YgNve3SW0-z*|yM70k(( zy950|tpli~P#*mpUs{2gm?eS!#utshprJIga_o6$)J8>3oR~j#!SZHCMwQg!5^CW^ z`fcLAt_ZgBE&tJJ7%jMdR4g*q(fta}3@OtvvV%Y+L7jzpsd;8?Ywh6lf|}f#na$ps zLVtC3R&{?JP~NE$c>s7ofk;+SLP+t44$$MfAjS8(s9+}=G9cs?JlXw zEY8R;^VT<}_^a~MbMq1y0~KV}WYxCj^o)~sXkI?4fAN@CYf5Mc!Ujs2gXb3O)6n_6}V--pXtu1f{?xvj7t!{uz(g?q$tkucwMU2+I>j=IQJdr7B}Fl+3; z5k{80#HH2*&1IU-d9I6}SRESceAlItFqdc;SqP5Ax>#MlB`)j%{sB72{K($gm7H>Q zmbrFmNDtVQ(uX&D8tnU`DxA`D$K5(^p<=bhoNb=bwTtrbCQtX*hWMs=Lqk*$VvGG4 zX=r^V4Rf)k@lE?XZW^0C{;y5r9PU<=wT*1bafgOb2x%ImMmf&0$Gd4f>zV$wXqofLB&4r~Ha=E}hSwr{Xnk# zhReBiPFfcX2+vm-)^jTOMqI!Eb*Tu~n-$g*xKIam$tKnc4MY9ZC5JHQs0$dNE{%j) zW8LpyfV$L%%gkk(4j7;=eqwcKEXt=Ym4vxO!+-%Ju`X5@Fu-x)uEX!yzj4ZJ+N8{e zn-1;uPMOuE!lZzsw>o83muzCK&@j>_5-W!==ctQdt++H2W{v&dPMOuEmYWqX({u!D zC5)d~9U4nuDlV0TxkSSV){2Y7x>#KVYq=$q9T1lo&cx)rWow8NEi#(d{@3E`e!Q5& zpx1Jv(Njpjwx z#_x=-04MIWqRpweOZ@*-_q&YX%AMgu>Q4UlW!A|O9vrIREj#@2Hy@(Q3ekSPJ@^Tf z33or&)9i^oTFT}5r{@(G1p@pxm|dZ)yCTKacoz^a--$QG^$Z!@4H3hhFRHkFY~JbZ z{Th!0JhJRxjx8)GC@f@y3U{@J_rnQ($rnA<| zhFX7bV@^|}FCn{iTw%pPdr@IM(o9sKI1m7g8#<;nmIi8zx&NXtXO6ERHM_RAwx+$Z zw5GRVq{z0F7Um97JKf2-FI$%e<-jMtZ)QW9ERA*ZA*8g9Qw@_BomFu(>#Q~>>w+HG7p4*l592>Gv`cl8>Ez8psN$h2u3Ak10+H&2}^ z<+Q`UH^=hL23%gwGPI4gfGj;JNA}?x{siAa$9GZ?@4*&*-qV8{wcK_RmyZzKCcl&payA{6H zo)z99=^R5k_N+A|Lm7%qG3lSp_PNKbUbRLm1M-Py~y>D3e&gMyI@nz^bykjEvec`?l6oR<9Z}`2CAIC#<_-LjRTD>lb*% zg|D=pcTyN?cBbcIgR)3bZ^xflRwFS_ENRG1%B{3->;K-B{S&TOH=*;Q?+=bywfYo^ zUl6{?OtWv1eeCs6gAq z%Fg!0m;q0;cg*}rT|IfU>oBFLc1p2|MNd5}prSP!Ft8NbTJIs}*j5o&nQY^4s*<7gUyp8ES=@G7V{e3yL#=&GJ_p_Hu#UmhC{NE$nk{;2c9OlZZm_SYdCquWL>F94 z<^I%C`(C7kyQ~!Z6ixqDboS$z9o7#ueQPL^`VYU7mYark6=_J>NP|=Z)?9APmO!KJqyj#CWe}qo42)|Z*z;Xq=vh74tx~KAA*6_Bri-cPk;20+@}z} z%%1AuR#|W-A9%FM7X;0*Eam$+AzHg7${YCz^y_acF^L(+XUxnPmk~PrQQNUSC53%0 zi{`eRI`sQH83=H1Nkez(#b?w^YGMbzA#d{)(JLICO9LXP)KuRbW++@6V7WofVIfPBStL95tGPBe*+Y zeE;XJ890x7ij>?bF-x1IEpWy`KTslENAYnPpL&9rIPoV5CyDO0ZLVal-}(PSkz zk83L}_Y`*o1Fbzw52mG;=4aOxN6m^ZYUn9#=`Bey#xuaCn#9DK@h3Gd`@xbWKRB+j z@i@_!HO}a}eATMU`}^hHcN1qX7D_VOd2a8H8 z2itbsb;1exwauZcnrBuQbqvNnO@H_mCUoLE)T-?tmaBACXXH+vN$Jj(dfMD!ZNjmHy_sdjOTXP+Heqq=HH|;%n0d#oKR0K#uAJOC z)RBMWxd{_IV~#v$e>j2L=dIT80<#;aO|*`2G3cxNwBgy>i^)`uFV@*)rM+9BZZ41P zZgw^qxLeQJJe1vbOlQG#Q#yG}cWuS44aOxUmA9}6Q(~rPl=}+Ux{@|Hy z%l+0t?*IPh6r(udV3G5|fUF%lM_}r;KpU6-SYZL%dTDu9gLaY zciE~{m-Y9{yKiB~ah>B=j0=pb^p!SemA97E_m!|IEWM&KtJaN&8~-RCV_c>efFwZ~4Jcx=sz z6Hi>(ZYpc*3aUJDc1fVKC8yxzpT=c*GqV-)@n(vr+Ww*P(@eOnB5EKjgI#kn=hhk< ztjM}>@IKSfc*dFEIBnp9zVpl!GbMDlVFoF5#7x<_Gj#W-JVNP(=KGA@Ze-4m0Yqf~ zpCG4ObBEBW_Xa-k&#q`Ltm+Mx_m&lxR|JYHD$Vyxx~l`tL2sbDhC^O@s{+ir6$ezV zE;PTVFV$Izq4wt3!n}p8=J(sTYY*~!!v!AnzaPlHaw`U1dJyDi>t-j0$QMI%uJ_a* zd0t964WIvYC1`7io%hr=ecGy3@pH_X&xRh-V9Y;K&13DIvd>^Bw$&BmvnpaaxaOx9 zU+VF#%89!4qS(yiGVQMHrG-(KToP5d)ED*fUdcN%ypNkj*2}o*%d6e7>;*Z>?-)nH z%#c*ZcP|Yp?8Wncv2h zSG7?MNsW`|*0oM(K516p+M)Wyq{+!Fcgw!U*=DMiyXZ?LrzKK?M)yBl0eQuO*bx!no_9;0FilP@Ujw)P`6V=!Elj!cA=-dT` zQA?IY70#EO8pEG^0`>-QzESEa6M!y71~^hdwkb;Oni;Zr8Uyh4$UZr|%&luTEMLB1 z?diWhE_!%FY+Omtg4TiWR8Fp4c=Eto=HA5Unt`Fp=J~y>4qkuqNk5-I=f*RmlW$3` zs?6`HXJ4UN85{rW%)0U%e^q7TpW>mrA(+S>FwaAK6(ikQeY7jLzKq<0VccHi>#)(@ zws-IFX`^nCu>Vxq8w5WKs(VVy`&|62G7EY_I~YWbTy^me5jGa=`w>z~oKltCCKUum z-LwaiO0!5S&7cwLUzS+zjGq~QIcm5oe&&;?(6)a?a5?XXJj3hPty}lae@S+cn+h(o zSGv+w{ZYw^qg-Xs?F{?BdJh{rR86xNk;>cUEttG^dS%u0Qzx|0e8-sTfof&}id&a< zkDFR*&nX;#d_MJ& z$n`(Y{0@KnAyc`+G*fR#h-f!Ju2@BeQ56i;1_`DSkD zBA;2AQ}<7AEi@;0bX?iqzWbkCUMR9t2{b#)ZR^(2Z5>&X(XBI{$hiYbC5)W2oFmvw zo_D!d2)A|Cg_Fytubsk0iWSidJOyJq3ah8Gm#JfNdGqwTm>=yl)4VCkZSy0od-k+z zPoH(sf(C!{U_(w7o5TF$S4^3@a%^tJtnpJ;yz$50d31l$qMz8804=$9HK->YIXwj( zgY5V}O0?3@sDREh>e$GcXjJJT)+}6b&bV^_L#cIRDswAmw71TxiyE@aCL9;~Z+qtO z?e@&j_SEvq;;izCwY3AaG4tXloYFUS&A1$I@|by@_2V;RQ@nZQc|}e6{?6Kr`pFGB zCa$^p+s(}}Dc+pI%s@kaZgaV>V_G@i%m!OBfU1u!j%)sOhC*i9JgphcCd-W6KUR5Q z|M{WUP1*2UOCGR~G4NqBWvlOo*+;<_U_1&GB zg+-a!^%G4|)6~Y4WN%`ix-lLXe}~jExyFY#Ny)Y^08cQT$tj? zZO<*6)LLw+$C#?6sFgKw4ae8Sjggk3ZR~H-+G$oMGptCjtE5uS6{maxWsrnDoCL$y z4$<~EgMCZK{qmg1y`A&g^QL=JiaTqw%rC%$pDyiPGO)CF zDbffU+Hp=V5e#f0YkhN0Hb^MY*jOyyQAGW<2lkwn^H*xd(#N6RSM)uTtrLiTrmbL7Z| z4I9j#elvXX`DQ3KX5s0fn`5KR`ThMrj{M)YuNdBArw^ZR7YuI&he{~_8?MwWdC1*# z))1)&P-U)e{^30?CBHFe{&IM-zCZX`W-E8P6mX+R^6$9QWlH6Qb=J) zJZx73lQPOg_ce+6)1$ZIdN>44zhaQjOJKo1`S?dToVg-DvAnPC7nkKv?5@nK9#fO@ zzr~fAnbi{-8hdL}OF~_?XL#85c#f^;DW4Xd+tpsxR*-BLno0)O1;yjW6nK(7Rg)T5 znH$HC|2-3=+{ipa-`z^zU!d)*f0ed9t(5T}(zi>~Fn10vaX+)JS!_U z&{PEQTb97EKMZA>54kaC_<*@*_Us?QsAWwhmamJC(vP0{B(&~xV|TEd>?Bb)FABZO zgzr>ndNS%lK@ht`Zk~(=3t~M_k4lB{*H@_UOJACL%5FKb5K6S?-!feGtK%>s#PpLLWDnxO?Va!P-{c{DWk_h;N1 z+O}o&&CxfVyyc1rk?ne(uUT(0%R+-XF7C2UHyh1onx4X~0%U!8_D*xz>E?>i`8N&@ z%GkEc#1iUQLP7n3tS&ad#Lk^-!Qr~BGw|8x#;-6wk7+k&cbMrN9icnW&gd}HIzo5p zOIoVSI>v0Y6EP{rlGG|jt*?1TnaSlre*qJZEW+kHy5xF8eqK&~eojt7==S`ay!`y! zT=}xEi+Sjc<_@PElB)Erq!7B0vK~J)^k<4Ixet)LPeTcw1T&f?oTz)Iy)-TK2PeXS z*>sl^Me434Zb2r1=alh_Cf%0MQ|7W`j{9EH_g37+lKvM$ts)S;Mzq-|nTP&vT93Kw zth-haR?B%jC0L>o#z=aCt8SVSW$*IAq@fiTpA|Y7f$^v~kp1W% zn=iKwr!s$x>lt$E_$s7b_Azm(fFmd%59nv;=EC9$<6FEbiT0$#xQgP!zMi&>v?R~O zgxIpr5|b0X*`;ko2`Pyg*@4btg~0{1)xx7~6$|dtRzpK3Vdl&qKJ*Z|dd)b#=l)ND z`Vcp8$o(7Mzg%$d%Bxd;V8)sGd|wtHIsiR1S>rt4GcW3ByIIbH>(e4eCXL(LV}o?* zj`S&F4|}s%<%$S0vKKG5y;;V%qfd%4zfG;_s;TPq7j#zDbX6al6`$ER)HrTQYwOZ+ zjr01v@eOG;q^Zgw)m0dN9)xTlKxeR|BTzgxSlU_8Q9Gfu zb!iv7^Mn2MV*?!}rJcpR107}K>idJui^q2@Z7rQp3p{$l@7WvJiIVZvb4^7waXyTb z3d({ef*Q-T=B$A;=TtY$mt)0->TBknHMw|jLUnNbj4I!_u?>ZleS;yhV|FMfrGDP& zeG;^8?l&g(5p;HD!-BrC3&$2F6*SN4=v~l~v&_C|_)=h>5}s>*#k>mAF!G`Zdu{C* zIues<*O*vOOw3ssO>B*-D~cM7Ypcs{$WP0w@kbBFxBVf-J2^Qar`+!D?@3J?NKVWx zAAYdEM<|3o+kP2&6w!pd+;o)Trh4;dN0ds)s|&i^Ujp)6?4ki~f>Rz1909(cgK zAG+jke>2}%ztHrUzGLSkgdPYzlrWpJ$qGNxhC{6*H`H*vpouzf>B5BjkJ}ph(PJL7 zI`o0uRHOHglh;J@ve_X_ud_go8WPNAS&3CrXPhU9&vEKm6PH9~)Kyosm1IUOw&%vB z##QyzW!IO+r)I6Ue|><9O)COpr&sUhSdU+~&8|%^_1`&$)SHnog7yupXIZP{66wfN zOt;-y9~Il)rlSMgN3BORn&FEvyMuw=y1EH9S;kvE^&4}{va65l%=6Xu%x!8q zrZ?ERw5?*W+ne=7>BP3;$|+6tgEch+^J|I+r*)Oub3HXPR<3DoT0En@sHkgk*NoLI zg_Fk7*A|9%c)n}jio9OT%vzttcGRz#Z`QS>NMXNb2Jj31(NNHfO+$@^E&ai!p@!C> zYF~Xpabr%7yzOM13Y#I(xs9zuH92*Kfrgyix`Lv{P@eh8QqHt)teH2yaiBiCdR|Ze z+={{M#)?`PNn=G-b53YY^)dL>`D%uG`iIH~vl}XFnzMZk6;&<1W)+8$?O0DPC`bh)NmzC*JXJK%?Tw0`7azs^T5-idS9V)==j0mD(O(xBe#9PEQlB5UEGECMxTw}o zr()o-^>)8`Pf}hbG!xB_lqEIxWU$9F)?Z&7sxdD)G5vML_3a7u#RJ_OQ9my(D!Xf9 zkz~^vSl&x&&@W#oYWdD3g=ThY(XF&+QN|#t<`hqMi|6Zditoxi?!d7w4B zYoMZNVpn!l9I#059)P!G+Q+jGC(e4l?@T!n z*EzLhv=4LQD`pOyfRFHKd`z4Ds&ZUwNaxGjn->q%EL}LMW{EwtZrwU51vgq*ClQLp ztT}KacH_my#oP0;((R#OOIbqE6d0o9-*3j+pTIegTHAeD6`34BYWM4@l8*mG{6AHH zy~jrUueCpQuHr)mv1hZ&^c1oMD@HLgO`_6{FxAXHlV4e$XZq}dakaJM{Pt6NHxCS} z!>Pp->jC>C2jZjQ1SO8Fhn-s1)KrQJrh7R^IWyCqQe9P5Ra042Rh^xlnU$I0Rfx-} z5k2;kB7Y721Nmz>qqep*DVeX;u0GEQR*`)Xdauc9Z*4Gt%V+v|B+k(~Ux&DMZIrOchFux){Ha#Y-DJvx<%9b;}6~pB0Vs5!& z#}DV<%;sh$JK_%Ju}kU8xX0!~-1-fd!ZcnZ;rUj zDav;UT!mibv{=rGbxLzQC+`YPsylQdttpf=#-<1mi(C!v64VvW`8G~iZX0sbXk{;h zoWGh*8r_~>jkq`C=A^xXU3w3Fl~P9YrdNIW`M#XIyjyb_?lJhYSNL-CvweBFzMR}V z)fMB$n>2g-C~CjxqKoYDa~Ce0yHHxpYtMw59}pfW{VNiJJC4!mXr=7e@@q=ck`wHv z_}IeSyqeOq)Ob>ugyIGbh)VT3GMT$;nR3Zz$B;UA}@H`A+?nD`0PN><+zPXGUB69gN35j{Kzr7Q3b^*#TxxoIHJ=m9pmev)8gq zIZ8YU57#FQJO55yb>>>D^t9v8Jk=^Z?bOpw6`H|U_5?~;_Ezhg*%V)nx!%lW&rlMS zm4pue0yw{Tus7`hJV|mG&9Dr!gaCtaDNbUp8eYps0CP z2z3y(55;cptZlCS9rV{wFQUXfq9m-N1e>dvg{-yf_|m(pyTk6J{hf9q zM%KJcS~&AME6FU+IAU2DpJnXL*y-x;x%yk9?3?kAgnQm~f6CP#b@h#|e(xyz=y-Ry z?tgIgTU=ez9Ubl_*Zqc3{!+f{TsylAwY*oMUxvB}bsp+W)Ed-@uD;yW#eETKo@9rqEA6F!#|>TVQ$N4$biySFLm`oSI-$`_Yy7=KFM{Dadpely@y@9gc}v!yWjQS zJ<6Yay*pg@cP-2N2I^(hCe)LzF7}5}_qq1F(Qiln4)s5%^{DH;*OEPt_ge2Yj@^5u zt6%Es7rOd-^m7O&I`O>BldFEpD1UK3!L={5tW3)2U5J|N>eJEJdnbE)(XVm!h+Xut zxVL!gy_M)CC_joG+?$3j?60Xg4 zZ*cW$^iouztLM17*VU8IW74eD!>$f}s(trSd+LrfD=iZ4UDy2$SAW^nH@W(gN9|vT z_ps}JpR3>P=#uUi!rkur|L&;2mIoSF-Hn$D-KJiTg5p!JL0yTu6m_AipX2J{eg^6k z*M36kvebo`zpT#{|J3QJlU*H}R{L02Zy9B;CtM_arR!ee>V8+xc6A9iI((Yzo-oQ^ z@{MxrDIv>BIf&Ya`Vh6v)!%XT*IfNY^k-0yqaH;46?GTtHq-{x&8~iC z{%X`Zl*GFjCGjqB^+>q0UHe+})uKXmo0T>UavzlbuQhdL9r26ZB8IcgF8$Zqs`u0GS% zaZjFt>PK~<+FZTC)y2IUB|7w+T!_j+d6ScpW4@$YmX&lkX@Ao0q#a4`y80Wg{<5oY za&-y!B;g|AA0BbP&yDZshm-De!#Vbcu}k`QyZY^Jyx)z)ck=%q*M7IFucvI+qpn3= zgSyhyFLm_`T|MG|4)!xpr=U(iEpzpSu0Ge*#eX^~5^l2V-s|dP(OXdUu3qWtC9duV zXgo>Ts5Ddp3Yts|Iqr!EG4De`lZo3<@3`)-x%!K){tSMPqaH;46?K>EejDZuDCjcr zM$}JH&{#wsNW2>RI@HCe3s7gH){e5T#=HU^;qtA-CD`YqW}~K|CZf7g9jGQ$Evg(< zjLJi0qEb+CD4Q}FlaGYWoAp>@moocc%n{atjfq!tyqaZB-exvTc zQTHxJt;Tf8Xu|wN!(6Lj+GWgRTJ0-&mvUx|F#)@m_jHXrsBu@Td9`bn@~oEfaD&u( z-cOnWT#QM^yjQ|lPwS}U9&4lchR2I-tUBd9THtM(uY{eY1 z|IGVd^<}w>Fg@yWNWz$O8E2U&frE+FG{GTtk#yE-Iu9$99v5HhVNL%b4HK_v4yk#L znzyKVi<)Z{hUIFm(K=RW9c$FRQEOML^{SO|u4#~QuBq4hj*-!>snPn5k$mk8#ie>l z-=3<_tI?DzHOERd*GZe2BCS`gjCoCi{U5xUrQls_GeS2HtNCRK&n%g^XY*w#V{L(| zwMOgvZO=r^+tmGhg?5Uj$;UN>AFye6>${r5_rjDDvy7uJkb3c!G5Ezg9{-kx`IgiO zcP9+(i20YiFH(5I4b(--^DQ-hOKZ`qdG$(Orccd%YA#TS71*!iULYkjtzoHkfekHN zn>2+@_8MG@6wZYT`BH^;p#vXHp-^ESRG614%mWJZLWOyu;zNm)(45Zgdd3tggk>(! z*n@ltXH27DkqKy;^@>FSja8d2Rw5W+Cm0Ub$;!^e3u)voTq)?_k)Any|1 zIUeSk4Lnoc%FRmHq-{*OXNY$|(=72YzhjC$r|~Y+@Bs}U(D3kK+&k3#iiUhiL%yaV zrB^ZLW%Zq)<_T&(-jk2}@vJ)-v(zK}bA{wG0>6kC!yL&7_vla*EcDen8CXJ6GTJ>N{E6XsjoIZ?}h;Ler%o$7-wfX_zKW zp;hymrM^v?!U<}Y^=4yOu$H%)_o{iX6GrQDF7u_voXC8Qv43m-mzeb}_XikroYs1! zLVLB=ccs>JrROz#S4Y+IUa1f`(IYTfp%6Gp$^+Ii%VSnbj`l5@<4SpB#|4#z?`fLy zQmxAxt;-o&mo*ZGvmT`Ue^>JpYNpS{^n5p zrIMF*snpB5Lh52&DkaBV%5#b1>yg#!by5cFkCFm+e(76NzD?7-P0gpN`7|{zQCyv= z`7YJgU#h-K)z`0PznUwxz7-1FT7_qY#;sJSRwz_!6{_V5)oO)mxk9x<;Zviqb#NPr zg8Eiy%D-0gC2BrZ&2u#6C5lCJH1079+qsUfhFq)WwQ7Dy%@3)0ik5Rg@qa)|J3~u5 zMawy$<(#hNoTeq5tR)=KTn0RMQmPqIB0mghEe1W$i&-HvsO3LJ^J1Y$+{uyCB7n8P z^mOYX^hcO`ebCxz(yeWrurXOq0^!$h&f_=1e2d>ib1}b3=2Cu>&E@ielyH^elyLl_{}o!@SANuHiyg{+p=x5$Yx8QS!zjde>duO)bCLL zgIbTe9(6718q|8!l_Q9VDX0^mqh+{D*oaz>*-^~wVm8*d^*vADv-Leg z_$#x#@?NR$>-Eju5xA%%!mO~EZ_)SFoDX9xZUyB%Pv8H`+qR-*F4vOtOY5lC7`w}g zVh*>LIbNB=&0^JsZ;IyZjSq=5NO%jo9e<_F%EsS3xDMA<%((C6v-hq1-VVPP{#fq` zwZdC*|1|s@_g?M@zkz8tr#yti?{hLi7*`&`9uggsaC6?_kHW%l36t9g*O3(`0#t&3pC6sK}q;e;k(1Xp=SF?G30Vd+^cPFj>$Vu-ygm& z{Fm_i;XTBCA^cK!C;DGecZJ!JD3!HEc^^97XX&9D$Mmi3BPJf{L!>0Z@Lw=E?YGm_|H$Y}eBJPpGPZE|k?=v@ zVa$@(L2*;}1FpZ^4xAs}PN+kiLa~STku=~k;PL_D6aeW|ewpMh*h{IvP%WXh{yyLo zAAVd@+rV2}i!i?x7q?8nPGZS>Te_B)`NomMiGv70(nSV>BIY4~m-W^wpg+&`s#fhR5>kcQW4W>>#rGOjP+ z5|oqud8$wyRs%JDTwx^rsI1#r+!%a^7=_LxC3!P$&_`jNEVK>&H-(?Tu~_QE6Ogh) zkukz4zD zCr(`GT3Q5d3q9|Ji+(_fxUE?zKsYOQCBlzyn8Vm2< zM-7NY*w2I)lcco&n{J+xM;s~%9F#}=K2?*p3^v7e;rl$w16*IX6y%vrDYUGLyKn<2 z-F+msLT3kh7?|w_qQjKr2)finIEM5n`=zC{1;XGMJr6aJ8XlxY1Vgrgi=P0`Sn^AN zhC*5{%HyO!A_Dz*;2Q-l3&e?qujEfY`bdb8zQ%FVca*vxBrLM1(`IlVmy$FsfsgY< zu<{AvdOXnrElMxt7tT*c=E;vXjv!rd{IZqQp9!ZIl zgj_yJ>jPPbGYU0<>$HrRK9N$YI!x^o!5sE&z!RWAT&2u!fKN)Xz&u^k6G#gGI!swZ z@GHJ@CG8`WECbh&?8s60gy3G;^HpcQ^iIf#VuD4xh2>;fU7>I0nRDLvqJ z=|#}@X>T$N*Ho+or*XkHhA}%U;Vot?^6CsT$ILSe%wqF5^N@MbyaXH)@oTZ-@gHj?5N5g+ zN4OcBS1`xSu{?yIN00pFr5X3Q5w%!fEJ?nQRA+vX+GkkOA&0uo>E!y=_j^7mcK zo{LpdGJ4yOp*7?Mp)ky16Vo4+i#(?0S2^QuA8Di_b3B9p4tln?3HhGFk{&kvAQFWY zeu%co0-n-iMTa*diQK2ykShH__!)emYt-Y~Rxc>u;a)dV;=z3rDZ+Q~7g_Ufiji3VoDtwI?F|hPdM5_QkGEQkA|sByrUju^)p$68S(~2tl8)Pq;e% zJAuSbbTEN1J1LRSgmB|+VA&yf4Db^U7inDGPVx3ox5hbHLw&gn+-& zX4_mol?=5AA3Xvs2jNEPgbP!WWF(vMNNBoWoZ2POQj)gNm+$~2XdqflDtsM?%NFYW zI^Kp-12O2PSbGkUx?RErKY$G>;;yGfTXnNi%?`TvG&kD?*P#hrFwXaTaUwv5iw9!EWE^4 z8yreGrlj{d)P96kw#f}#&^CFURHRLIxHL|GL(o{@>h_Jw&!rBLn#q0klG+vtsrVu` z!5jDlSoDd)-==JFU=MJmCU7jCM1hXtUZj5$E~hcoU*Rn#Xjt(2U5vIu zOWNT8@*({mCK+F4kh8SAj93^WqDv2Wn7V9&zM>Vf+ZjLYB0LiizqM@3Y7==iJT`CD3XN8bd(d1 zC~a$63Y)+yMB4N`q%S)r9XRckcs$a#3KoQ+qECP#6ioO%=tcBY;^Xj%Eh9Mz$FQl1 zjlW%dl#B`OLVuyKph)+<3dvcy3ZGDLMRviBL28YdFT)1A+NBE4IP`KQ*)6^ zWOuHF_z1m_`65SVmKKX(wCdQUk4hIzV7DJ}E~*#15xlDQlS zCF${CVtm5;2=Sf%M9YZF9@6vGv_JVwF;#lgtx(=G=x<0`=uUrfn6RX%E`JO^ z6n+P)cn=zXo8RjwfqNyKW5g+#6#7ZP$CaS1gv&AgkY2A9SL5IGk1L9m3V68i}nB zs|XPzdW4E2extmU5=2UnFfMjG-kJ+(%L9%J?{pu^@AQmz_-)6@fvS$t9El6e8vQu_ z(qb;%(AGT2pQOFlg_IM=i7y^LFd;-6`v{}`G;Rtv<}gM-0oO7H{fjjfkMXEhRD{zs z$QcnM&t%e;{v-$Kk9>HXx0K?mX^Fq~w}gsjkFCI@L>yhnHMm$&p>Fi4M<1t!6fc~* z<8>6Xz*lvJY81Pjc*@h2Z;4&$;{ZD9s}C`cDE1G7;|`rTDT)l?v?3`vxj3=i9Azfp zbL~|$l-pAKoi=e|f}w{TS`v9uFq1dEtF)!!>4yRBK0(qJ$a;aMGwLTc@g0g4la@f-+$UG{H1IMYH9=CA$HAmzM_zDkK6svkXHIz? zid7oYIE+R_av*Ow5;>_<38ZXz3*&M)4YD2F;&U18@GxsFZ4V6h0gVH^KSnD1RN`T$ zPmnf-dJemA{Y=Kn)Q_1f9XGM-8+!;EVAPC>5e=!xDEo7*ukb_qS>=x(xj6K(jMasA zx$R2s*a<05L|5~Nlsv(0=deHkJcDn_JgEB1oV1RE(1l}3ZX%mVn2*536m%J@A0$+) zmf>S+%0oEn$@^1E>47Gson$mA7_nb4lseP%Lh%A;2g)*<3#s1+Qeu4es2uFVMqM7E z=h#EfxEDEo7Z~<|%N_jKn878^2h=(hd1ni06w>p3tau`IMC8D?qP78SqkFqWHc5{?AKkM#~p=~DUP0~K3 ztC!JT2@(z~ttIli+ow1+iIh%s{1w}d@-LiRZb=I}eSGv6dd7(F7y2pSD-vX?^lp+1 z^-#Q!{56*lI4C`%KtuW9NY5ytomspHUl$B^dPcXeaLTPIx_pRIixkQj1Ze7aEToGG zDG+)<0+aK>b!<%jc6g)8WHRa!8U3KbR^<1OgvV&zCAC*+lMFERW8Ak>cdyn&=f1TL zpKANZkYXGdBlF$@-y?*Vc0uY_ldK?pqI18}I$Kzwc>#U1q#&X7eE>>~z-P0z4s)fV zZ&U0hLZ9oJx}5)>g$_q#N>-83~nGXdj(x;Qcy$Vjr}zS?VbgBYa^OJn%gd zvGH~AYV?!hK18pjG|2px@`>&4Omd>8CG@LllD=Xey8B2icnl=~ z;$VrGnOj#^kK&QTBXoY+#cvsTIJnLCb;5-S9S<*+KKgU$IbP%sbXheKC^1S9J2^zr zo2Fn>dZ6W<*?ng3;nBiThjo5V(%wT!g)eVcx)SV?p23~1(b553VC~imbA+Pyf=#w! zz649r5YRa^AS);yaQQ=ePx>*^ll}&}RoqBmUJy#A$ZtsNlGhRV4}4MZR_Fnf%m{!P zT9Z^->>~$KLW9bu1jD6=1wS0Q5&Ho~CPKM8BhZsLn!oZ-(#sIsC&#@CL00i7q0CU^ zK*L6R36aJN@DBsqobaz1dF>^Qt#IV$l}lUTYN5`L909)7%yVWU{h9DBP*V$Eoz;Vb z1;mh+)wvxY2Y08{rC$@gddzB)@-cs^GZ#Qb*YIdXzg0{b{iqly(TC3bGH-zzw5rst zd=D3AW>a{V!_DN4Vm4LAPFt~gfRDfv2(aSpj*_r?fss(HjDEK&JXOBH{sNpPnsV-@ zw6B5JwqiOf^ORh|A5usQ?nX1t_b9gzY!kkvJdl`&!6O6j6X^viqlZk;wN06ElP5;G zhDbFc)5#N~y^vt9gXtn~h=~+=!{Nw18LXFeCok=_U0npv4+=+4}1gNplA+Mhs~v{{H!$apYI`*osGiaMo}9nL-n z$|!Uq^S7>K4~`(^NLdtavdRbVBaF1X(-#dRqwK}qS%Z2`Q$=oIHl5W#VhVQYIdv)* zK8X)2GmP?|2iECA_q6K$gz|)MrfgE8As!jq&Npe!G^zK z7rEh6Bp7M0Puvx3*>xiID{#04p*$k9YAZm6n58DtCd>ly7L$BI9#1{^YLiyqtS*_< z;(gjgDV}^26kmkHiTovy5Q=A(6fPw5{vY_gfm+S%?>phEfa2O(>o`9vR_o z_p(0&m@p4|4;=OlsC6r;gqRO{4csXthmCN?3~2q&HA%>!4Z ztv?U{mYo7GBSEJl72g1~#&FVIA+t#j;~NV9MoT0Ry%+U1?fwK(a#i?t_R`3V?M<}v zUj@9t;ch5+8*3jMu}N8-tSN^ zd@w1`V#e!wxU}r6f$njA-%agaRwMqdD<87sz+!If*XsWQ=08)9z0_-qxX2@%7H;up zHM_Eddblrz{3|M@>?VKcM0ghOPg#|G9Q|2-_n|+jGN7zNx^*Fte8GJ5i5H{N1EW93 zS@&Fs>s?TdL$!`ax@gq)6(kX7R`7YXKdA14*KbnmXxbI?(MM=dpV9fcPD-CzHt1=$ zvn!W}rx#@xn3niGkYRCr4RDKTO$#mZ=xLF{>TqWT?YlaD6A~$AYEz z(6jG=PTnNkX17;LhD!-|hf5OT1!4(pKSKB*loEi~O3gn*S4oc8((ArRxur*uo=?uX zHmt9{tMiPq{{E6+F?G+DG_|D8nBU#YK<$Kg9RjnImsx`vMqZ?diX}JcY387umTwV` zh)sI_NbMtON9M*Zu)e|FXCr&VH1yFI-%0=l%bH5LXX>7+S?cMO?`XK-h;gc#B-FRn zv`pW^zb#Imb>yriY8!ORhDD&mTXIsKE;e~oI+XP{=b={8S3>JDvegHh?5h*5FJmZK z@e<4sJpI@SqgWv_NIdu^ZFU4DIZ2DF{Nt9&O;0t)JnXbKR4(`pcF98y!j0Htq5Y9F zZWT&!`mc{^d8fCMv}ME;C%M2MMULHxN!Gb`BB_L_#qFBp(Hg?j3Gwsr)%riGma2pQa``7g8R@Flj473U$gOvdJNNQ;JW~C4KSBqlb3zM%vh+ z2g;&2S8j@A#s#oht( z&a9iz^4re1PG#6vRA%@@@>7h7)wo4R@sBb&E$iT&!$bGsDl5^oIKud26Y)_r>gRP?0>fyrK*CxtJCWWSMJna1{v% znN3qy4iLe{5q@w#n8Ek}oZm@nyw7aH0eG~H+=W!k=z@Fo=q;k~k#zFtPj&$->6Lzt z{PimQzJOITnT7OfOUZ0wMA9zAT#fYkIWmjzt+m)4?0LwQR^Uar{6gPaK1>41RPAv- zCGKyjZK?PJ0cTzHK4J)+#3;_C(EhK9H*26T3jTs)uTsW$kRdz8>dkdKYa~fkl-pc@w=lRFpaTq8F+q|^0gE2cO;14hp*Dy zowmA0%@H~g>Q26-9%=E#e^d=!??oINPnmk7vMA42fLmTfP z0kc;Nj~Z-_tRPsN1P;GKIz`a@CTb$|do_LhGlcZfLl+A^E3G_@9&l(_M|TZK89S+o z@O-I>Lyz~lyJ96L*=;`RQEc%l|JRz3dxgrSdzg2lmNIHnieVm^Xv}cA@|euPJ3M|= zYJ_FK1@#j;Q8*Hc84+aYT@k#*T~@M%Mr4*qcG3wQOJ2;BYdql@pMkUVnp$_^$_@^t zIJ{zXmLqsC^cm?HWsIa!A#O5Tya$~7pYnVOIRsvyV^z<2Jj+Jz%k;(#?_A1{wKpV?^R|0u3 zUqZ}}fRxl$X3Cte24rQzp)BxF{g{!FGJ#)FyrrdG`T|$jYfKx79Kw!DvB?MmikCH) zLfVD>WAyOs#AY_J489a1Cusq8l}SoGdCpD<%5tCX@|Tg;R@x<3M_R>%f0R)1;bm}P zp$6GSB#_xpZKePDoZZ>N#o;CJ5E*486FZjD<_p)?Q6f8f6kF56PvXKTTU!Fo;NT57 zD5KvG`R!MFmC^5qN=48pp`N33l6R@b_UgFjB{l081;Cz%G0$_d#{fBAM!#<|4${8c z4Hp^x{+;^56A1T+@)#+z&Q-~NO$V~>*y#}sb+`0#I&M}R*L`XhI}Abib&K>!qbwBhwTy65?%o3YoKK{KI<-Hpvai*`a7? zXD6lE3gl$f?0%?fa^)^BS2E$1^Gf4oTyzsy&IcWKP@$~S(}lJ8QdE$AV76R*k}!tZHaxI8?WNBYO3g;0@+U?o|BSi+2$Dtfa zO}Lw^$;ji>SdAko;N$RrbfMfxOkEMupef3)vXnb>PN70iJ^tTb@QB?KgH<>uCz<=z zFDYf-dh`>%2V1jz2}(%mqx4bi`c%J7)NufQn|;k@hEy8cqoub7pR0cB4bNw_K@-c zWKNl1`OIl0ZQYOcy8;>4e=PI>w~{vhh&3L4l%G4sFTGXDc+FWs`;ync$*TNJddAI4 zX;2kyBBMu@Rme1;R7I}_RY%KyBJlLiY=Q7c=opl-= zZ3|BFttGBJ3Tv0|IO(`=z6iiqc&hXf!iAjKAf!Z0Lcb!LC(&k~(yFr0jvY7nkuDf1 zxa9OLvLi)Czhb9PcFQU~jXcPWJW6%0kDG$JOG>hS;H2j6hXCi4x*Q%tZ?Z?i3MNvD z-Oz;O;>=OwgXu*uE=2G08E>RmTx5pj1)Y(Vy$2$d%Rcx|RAOU)myRiwXEHydaMCq^cIZSTB*6&52Zg=hxXKh#Vwnf$r+`|ucBz&QnexBwS)p;+eK$Yogj zSjqXIazOZkK0>)J-8;3%Mmdo2^wGQ+yNZR})s?h_|3&bHZ=}@59yo<9-=|2ev}Had zREWNOA8q@*mVc*&qK1i#pJe>7Q+O8bxE0Kjvlias_b#%6Py;ya$}lqXDftgWXQh&x z@|s<0ir|&bK_Ual^93HR`-ViaDFk+kKf06gT{oPAl~~|g@v>8kP@CXf2jO9|t4!$7 zp`4F&w?4C?xC-7qs2uDK_^Uo{+K%N5Z<)Iy%?)30{I^>PyVDhkgQUKlux({v!UT@`0di307;4#dQROpW0qO#1Hzk~hc*@( z^6HKl#YJrJ6Uj&3=)(1#^^-W#bk+o26D3$*YlzkTo@nOB30Qc~fi`<1K7UhjR%A=o*Fm+VV)9;Y91Eu%FJ z%{JU7<&5a4YUY zneGGiB`Qq{c9J^24jzfzrIMVc^ttd!hkv4XOvo%AD*a!Q9I3;)^2 zPr~yxl7vuf-=&!NDYA@%{j#q`W;y@jq~YWhNpG~St4*(~^gr79-)@FZ#DaQ7!utRs-;Z-sl=B~*R`ysaA0BIDxHDCNp1d3roK$e4fW`Tj`&+%jn2)qb%=Im-mnsxAB%yBOHsi zG*Eg9sqsxY^uL8P<@@zVHI!h&R>sBeK|90nyA*u&iz&q%841WEWgE*`93QiW0p%zb zeWDQB?ogcO6d6HH)i}AYKrU= zhZBPP`Z#0D?NTPiP$U5GQ6#TnYO$Me&NwBOnj(2hC{mNYT_{ds?R5G&r8!m|a1qWs z`q8r)aBw(>rsD8oClIA{C`!Ja&@TgUPhzAceVcq|AU(6QXXNO9^aAL7H@`!X*428; zUK>{DWL$`B@;+-ZhmcSMj0R-xi&a(hXHf@bE{}C5e&}}+dJOsl&S*~U!WDeDxpi?R zj>B%R?@&A`@wog@x!-Q5Cj%>spj53DW1OAZ3sy1SAw}7HMY=E3M#@pyJt$uU!g;6> z@EpmLuLww6=3PUwDhAwTUzvmxtjs}w4@E2R6tZeihMtLwl!{eLah8!4BXwCrcuMW^ zN*ytYK`BJI1TksVFFuqfUgxFq)IH1bb!TECLGv|5n>jJVmld+(WITE=zb>oanuKkD zJuQ9K3~Qb>nR^;eW47mX>pXUiTwuM;NnP(+?^!Qf+xfj}ePHdhUb8+le(McW$OT@> zrqy(sAol`JHkF(rHjPskW^z(ktC?$tOov%$7I6Z@60_8dH-F;SW9~G6HofK^eiO`J z`Asw%`Ass9nI}l&?`D&kYM$pe%e-vfCZ#Q0|GCIcuv5$uJIzk#bir&pn^W>^>pJQq z->K*Dt77aU-xJGizllJ#7;}Ic7cx?p-8ij$iwUgwu=y}@sS z^(H^B^%iXzXT8I35-qwFm-qNh)^_#Mt{>pCliz^#q4hCw_wk!*ePSIV)?se%@mNO; zC(0O);d}&>$f>pooHECmBqr6c58R}gG|cIoKo@7c#%m>W4qb+oZ8A+3F4-m<7oYKA z&H;NeOo1uDTxg1|0uwOJoXa8Sb*vD4vNHA5j+J0lzm*D}Otx~simBF+V3_6SoVr14 zhMwthoSx~i1e}{`jR$9DS>wQ&*@Tf(J{E$7bFDToamX6f6F*Kc$CzWRnP$G3Z!Oo; zKbC@{3$1SObP=)SB#>jxh2}!5LQcx#eZ9Hfsx&`0KeuL?8_W&X@#Yui7uGU4BhTtF z|84%88(PJ&<_<_RTO4SEjAV)HO3xi&%-k69DVedZ1G2Ie=- zn^wPh%e-xsLSgS(_2vV!(<*_|60JNt$xh;Qy<|HXbBdj66+?SzRp`~FHX5p zoYG_rG&vQHIStNK40X=nE%ez8ea<7~eCv4VaD{aen7Vp|N^Pk0G;%virFlxFUZv6i zRC*aXUT$3lO@1GWjZuniRf^3}ifvPhO;C!>hhp!6&V@cbN}qn{b0a+b0e)GWxA-8^ z{6qYDtcUseq0*NKDRkJcbXWitz5!(l1tvj(Z$am8^Gi|+Oi~KWQVL8`&YA@6eFP8M zZS5ibz5L3d#g8!yH4Z8@##@ICJHkwi;Z|^y1notS(4H3z7OIPd>U>tAQd+jsSSd7C ziF=i)x6;fQ=q*+$&8IY$s5Dlj)K#mrG)ZY`g3?lhQc;CcQLR$TWOFPx5>Hf`X@I*g zflij1rO+fi-kPcyKU*=rTQPpT;(D)Q`5eXaPQ~mgirJNl*+IqZnTpx7=mj=G$@BwI zm*8~0;`A8B>3YTKF^bbwiqqAK(^ZPo)r!+~^c!2Ov5ML4iqj>E)6*5FOTg(At50!y zKyiAS;&cbCZPP=t;$-{5FU!O?6*i?c9&X&rZ>Rn?H$KnruZ?##{;u(w#)XY@8(SK7 zHoVvHR>S6oM;m$@%E#O>#ycjeeqa6F_5V}f5V-SKVEeQMUa9yw~*cL1frUc_k?kl;aWKqeylDxp)z|O$Nz+Hh`0yhSh2mZgl?mfDz z>P{5+Ie`EM2=5ReM)1+GRa>RdR%oqbYoRDl8N>>m-md#chdaHx9P89ntQMu6xp%ri zDX1t2XvbRHjz~g;pa=<|SOS6xAOylQFCwq-5;*hO=l8?K+_mnktexNQch275?{|OS z`*HS}H0T?H@&>gZcyZv#flULq4SapzHwF$KSTwL;V3(_AUiG8mbHyi%n~Dz<*A;K~ z_fc_q@vn;ivG}&)>x-{0E-KEy^5m8Odga8TrlQKC-xl3iR4|}r!0Q7Z8*s;f>-#V5 ze{H{W{a)!;((gz8zSr;iemRAk3rh;`F6`g8p>J8=r}|FlTU5|m&`_|iU{^s+!RCSw z3Mva$6f7(FbHPsv2KPDIXK|lz_O9#wo8E(a_wMyhuUWkw>NT;~7kahtS=Y0&=i;7s z_Z-}_ch3$zPWD*P<0n17)cuTio&2VIN%w#3UeN8uZUy<}`E&Ch%l|?C#QZT`|7X`> zT?abz|EVrN?s9$SKX?8~=bXGJ@_w8*GVhMOYp;0yite3SJC%3(ZKnr2{jgKiaYe`5 zI}Ypce>?m*_hjxnxv%9e$h|xF%kAg1&u`}}6e~j+Jqf!9yfMz-6}&>oNm~(%-H8*le+XZuC5#I^W;zJlH}|7x}w`AA3a} z@P@xTWgkmL{bl|}M9ck+##zTU?XOjcb#a;_XRUyu(?agW?yG9r666 zE`BjN6Tg%kjTa=l;)Thf_~m40yvX;(Nn^YuIrurW<#L$vB#Bof7qgJx6UlqT8)5j4qDrlE1`ztoMH*a>`#+Yt&_TQ#=H{L$x06 zb5wFRz6*7CCpGctWLrE2^s&jYc%19wlQ-iD$>I2(q$U2lRd>=UX zCtKqw$$_{uSs9ll@1VF5#hdYBSG?A}P00zA?u@tkUX%PgO8!M zlPG9K!D$p+fOU&j4O*OJ86%90<|g&%JgHW5wpO6=6dK#o+7q?@JKygGX)>JCarbfk zn}Lp}aXdrE0d&+kpKZLJRU3upMkUDxFpq+H?h;lxfwPow=?Lx|jYpI2c$n@@p|-}q z#F-h%UJ#FGWzd$>LoWtsbxf;9ygiDyCsN+tmFxk#POoav`zc6o;b#+m20m7!wE_=6 zi66t?>H7F9SOfH@VaZ?!ybHXl#jEW(-II@CJH=PT#)spKTj!ZAT#1%Z$!A&a98G&N zIoXZAdLE!gPixI!gdPpS;h}mz9Q^O&*C-l!7f#;||7hRG(7Lgpjq`nc@&Q`g(0VeS zs6T?FzQK zpPKZkDJL&EnA15ql#_2n9n+@0#$C1UjRNN`{Ja~C(df?TWuWaumbQ~rniIl(rLD+IG=}=J-i{{FSyd@cn7OH~C$SCR&EBQ|LLt<2KReA<9sYhAZDs zK1RVhP!FPQPdpXm>7?;Xke<-{Ct;nDY>%Hp!PCCiCNJ~POG&2&&uh(FWFQ^_vE_4! zquEFXVjYM_QivI74OwW-DYO;Ieh^pV*$44%H14rd(H>WVwjSp@8uh?)&iMTXewVYk zcjEP^t(H^m#Q$CPy5yyt9Fx3fOjAUXJ8J=z<6EvnZpyyf|j7}p?r9S7+gy=kv> z$CvxiIR)maewXTd86WgEpSudbDx>e{+46XU^1iZLy?sd)U0avaB{{){w&xUh@~4;` ztw7nrl(NgI3KRuu0ww=11!Iy`c=+3tf`EM`kGYB^ui?7_=8Y^WV6^g@V$EQz&2eT( zPM@S1<_cb~kUyBN#thtgntsn`Tie*jZqYv`+XF@z|DQTq4>AWdhWw}VHZ$m*`teHV zj~7@`7>M7M+KN4(+-5Fg8a-TQ-fRnRVRlu|Zo=pDdiO1Sz7e1M>*Y20{8c>OipN{= zcx&7rZP$_g9VB}no=@eA7NE5>S&G+hroG;P_wOs#tMqs;3RcTa3av&BvJ2`qJPg<~ zSg(U|7);l)<~4X&2I9w`LtDwFR^ja$+P6M=oAfe}KZeP9$)F#=&ov~t50Qr)qyv0%zL(#e5EjX_H)|DSOW@B zGy3p3{XrvPIf^TL(>`QqFH32!jLbzPf4z+6_h{aqc)1r++I!H%g5-JQ$U<>rkkx`a zWqD()K}|Co_yB)>*m@d$mjUHCQFI`?`v-RSW~#e=!Ys5FMOtjrBGKZa76a6d)&3hg zc9=W|Sqa_ogC5=NeK!~Ns*znCA?JF%IT~-~`F8Ve z^*nbyMbXPQs-<~HbEaMAH$ZTkLg5%Rm{-R|UzzbA(nV~u2*X!(FTkMcp4R$*(=ko2;#03Y8{ zZhs{A|{nkFq?i&T;xYFHwiLJ4tZ|{(eZNtDG(n{#TNF zAuArHx6^q2yLgbh*~K!FStUYj3#Z-i2uILy)Rnz-rkt-X=Y^N^(^HK}FTcCN@5^iS z1^pnNUNpw&lI3R|-X*Yg#=Fk^Mh;&Q$=G}A_eHZ_9WR4=3?*CPttasTsM!Mg+wi}g z;vZzsN+U@%k$xkcSr*CC=*=6^Y(1N2&b~qfeoxL<<+DZ(R%`Ur6y3uk9jDvf<6>MM zB6<(SxluGSWC!D18!w9Aqt0rPsXF?i8Lcm8qg5pes!&ix@7_Vh8rEKDRbUV*u2#ay z4r6HVG`X9Zdi}eF9^6h3zOJ8x=)ui&;2Zk7pNvnC@lG1LB%Ym=($c@g&+=Atk_9yN zKWOSJ@jMhfm;8~ozDee1$b14mREBtC1Q*W2EKo+kSc1z-M7j#xeOIw--^@>bTpaa@ zhv4pABt9C4$M_siqwXQu$@*Q2l8{-gWee3Z*mmTSi#riL3s0xA0urbaMf#Fqe^|n9 z>!HddrG$KE(f`@{I*$~pP|$>94&~cQmUSLx$t&@**0%o`t;cUbS*0RzLe$hNRk}IYVX76Dez2H z=4+XOvK*8*Kq&*I43siZ%J3ymFP5TbDL(fGwH&l%yk98_%k-q0uO%7Zdhi5qSs@Ce zoVD>xe9mNEZ@U0AURGw6_FA0<*m*L!) zr6`=)74s-F;mJ_60^AR^JxWVr{%9_$!x(lZJ1oV+kV~#LnyTi(^4M;`u;DW3E6iH= zR3l`Y?bK-HO=20~5b3oj$KXGTg>){InThqzp8oW^O|e@u8umT z*uvd4?ixd55W|kH65x?N$NPyd z{bi#vVXZ_KpTm`r$|z;5GESMK&QEY%7Ib0d3@O5xD!5MsK9h^;YHi7s%ICq2k5~yK5 z%=uj)@#aWtHgT6DY1BC2_o)7Uk zl)t*w=Wu1DGD;b%j8i7L_fww_DkaG*kn2HS400LY_G`ZFh{(|r_r~ioK5o6381lbO zG`ANF`+3GsVb~8+plv<~`#^XZgq0xt7KGzsPJKLxjSOW)8Cnm5vI>;eV4pd8;#hak z8bE3QsR5+9AO%1B`@p|6nuQ&O=VUMeTA3A<3_rvCNGk|yjl41%x(kF$8u|$c84WFs z`fC+r8?>}ct7ffUHxu-bZ0liG_%k{BBO=_-`QH*b)i3lJFT|<0#HlyLsdwqzuf?gQ z;?xpxYMnUsx;XVmes3n6;eR80dqT^Z{8{+zToV7CnCAc9^#A_!zf)CQ@vN=?+ns}7 zVZ2j~S2ZGGtthyI9cSj9-i{mDVN>!hdK=}x-f<$b6lrlpi_==Xs>L6)SgFM_o^*v4 zo3z-dMXMGeKWY^N9zj*2NcWOkDFe2T-(_}`YA836{>!Vs!@P(OiYryeZ z7RS;ojt|v(AC8tl6&x*Ti{@;LKWp)x79np~qs2OK_i9n6MRS&_437O;97D+~TD+mf zDlJxM@s1Xowb-P^PAzu8VFwAS#BJ78ll)1G3N0$Ncu$K;Ep}?LLyIsYa!`wgEO#@r ze6MHwuw3nxY6m{0K3VP7w058PA@Tp8l!uj{DUT@sto&SgR4Gw@p;YKkjSQw1rT>+N z-JpJw33$niqXv==vhi7RyqWu(ir$7pQwd4PzmvVu5-B)YG7z1@#pCCqdev z)fP1mWouR&UzD)>Su(-d{MS5Q^f|?|rh1)YmZr_T)&=X#k$J6))|jIdV(9bzpiTjG zs?4I44=7_(%jrpZ)R&A}c!~2y&gW%MArCn%zMLbkHu7pCuVdtOEGwr*6gB5uBa^xk zHNoE;Ldjl~>_x#@6r44)b_NBf<(?N(PW=GX`$3%IGvrF8GM_T}U%9@oMd^C$_#2d9 zd0X(p`zByL1M3-BgAX_iYfFlig!LuJa*7&LVW~8-54M<(o`!gojP5RY?^edqmKmhA z$n{b!%E)=Wo^POQ8{uY!S{}!T5hxppl5u!8gTD0=A3JBSb$U^ox&F&Iwc(dQV*=?OVWfcli$3qTGK z7N@)moC%b+Y1M|SBS>~6evTvM8SvI8C&6t|Yk%mETD3;nVbr}>JhhvPydvY4NIoB# zH;;^6qIj$_UYVfWqu7l_VXUaFjw}HmO&Frl`=dCV`6WY zqqqB5O$)1OVKre^_#E9mNq5Z*vnp?5kxiesuF^>^+5xQ}qxEB$KFi6+uO1?02T(&6 z{5FW!fcPPZ=Dy{g?cB-aw$;X0u{;TG;hj zHLGL@>tzVhTf19fb9I#^gsI4C^K5` zXQx9)*>W8jW^AHMOPbd4m8HR9{;a50;xbvrMY8onbET|dUgi%45#cCHg|Hu=zWPRD{;6= zsc|K&e(eq;UaiBkaN!)9lXRlD;>;M?St8fFke$yyZJHh8U(FI>}@X|QW{jg)a3fI=THd?Re@U&~fSSi(% zB2qi6Z*9>k&LP*n(*a#U#`eW15NC+6FG!4f~r!f zMx+`AUW*F$zQ%*da!;B$h77PS-ac2}95S8|cN?|3a z9*lY#Qk!Z^FFM#2B?YMHfr?zU!-=3lp21SgQurTsfrfp$;aQBJfdP8pM@EttQ5FSn z3r+-MM>{$q^J~ruvx*$S-I(IKr0>1JKV^=oKS|}KUabmDCuf=iip&9ZOnDw)&IumG z=X%$JHGispCA+OsQaW7ujQ?-1tU-IQRCrlycmg#*t<|nxE9V7(+(j?)Q|j{p46;aL zDoZRUo3(gV9keH{)yv9$Pc{~2E<2D!S8#3u(woTC;mM*`ZKq zf5R=&Tz+F7xdz_VkbH)JA^v|a+85USK+f_nVzne`KcdoGDN5<@77rwoA$-=+4H5j*ti4(bT(CFE8?in88Sy|W|+8fhlZ~n@9*%Rrnb*^kt!t6aQkMp$&{29%{ z>h&g%?+UT(Gqo?mTts{N!Cr(**NfX%i(D7@scO(m%x?r+k5dSxs0cZ1Mh_yk9-dVz z;Sy#j$%k4k-myqc$_qjqL$KV6vFpK`a zvPs#l?9eVmLvvCvho=~V!~@j8x6w3qE8mm%`PG0czz)8PPvys(^>HJ=-NI)(-zckx z;rUPXSV8a~O}t~U!;Gg4KD#ep(T#?9!)Jvc9$bP#!6)8nw z?%36oziV(Wj2SMqk4dq=c>9336y)g?;dDJP&E`Zs@9gE<&WC(3^x0}qXc6Y2r}6Xl z#>+GQDiY@Ws!Zto#;{7%^Tv!GP}*oj6A}6OqJRBO-6THtibINn*yBk##rrT zDP7Gy1!!aG&;;4sJ!qV0tPMJz)zhozj3Yiaj%YECSc8Yp(CBB=OupX8ua|LFH@$Aq zlc3M_BwGwaSmC*bOk|VvIkVg07|6B8IQu{gE1HM3uICp+rhA(a!%|S{?NB{r?XH1W zIS2oBG;K6J&SYq3K-ht{{b*}K+q-D1N7pVEwhm1p_8zuFE6>_`jPv|an z`u{SRy5ZEp=v7v_6j#jov#@Pwua*f^r<`(rDQ<0vwz?NMR?q7lGL~zIzGTH}SKQxd z;;T54;o1pYJBP9lP*#hwuv_94lRpxRgn~Q5F-@1r9jp}`3pIErxS?Qv5Rr)%&A@FsW zk=r!-@F?i7;6i}$d*$Di*OWgRYb>QV%RI$V>a3zNTq*ax0;k}@k!8_(^}IVWs`iA( z7P`IF?>bn+v)}ci!9nZY8SdPOJKN~h^7sm+3w`Oz-nv=a?n7n;dS>=FzLx9)<$vS* zjmk~dD8E80Zce${7=Mec-fkx9Z*lrgo@z8-JXYHYGQWHLo@hR35*^j^zzdw-N~@Yv zt(s~U&rC6{y^Pyo?Q=65T7~0FX_d2h%}rW`Qyyl0#=_Bb)Xy?cIa>xk52qIL!%NuQ z3+brvU^>bTs{sp9{IY9{P`sGzm*_<%TM1+2Fh|$M4~8*$3l9+@d&ok<(+xoiR!Dhq zPr>3?$MjB^ff_9@njkm7m%QiD!Op3?Zd2E9#>|WJDkUQo>QuDY@M=I@s1L{G}o9bH}$)NjCHS8 zhA6|){Y|BmTSCBKm^Ia`ce z2JrOG;!&qa@s1Ii820Vt*!B5!8C8y5o;fnn9PcyDi6((KS$WX+hk2n#loC?5GbMUl znZ>4Mqp7wIqJdW{L-=#?fc9=S!rB|ZD5k%}wicLAT*x+Gc7GAgUCgI1;jKz#T4lUi z(25GNYQ6oH8m@HP_ zZxzhJ=Ciq&V$~x0dI$*a-v`=YLyvZeUD!Flf z16kD>>o*u79*pfo!__8S4Qm%C^dY7}VWug_VuWJumG_N2{gF8pdA3h>n&yR<>?UM% z!Dfdkv(5KB!y`PKddX(ic!V{Yn|AL~&bZch-qo(+@LX|5>a8T*fo*o7I~|M|t)i!Q zrkSmH)l5s+rPCc3!**+16n?Q%7h1Al@9Nc}?QYF}X(* zkMSHD|D5$s@9+d+J!m-^pXZ&{^BS-68n1~*A*1(R6q3Knvu9W7!PjWa4LI~|SA%Ye zQKS;i-p%ykDBB48kj{wU7jUdlM%RYwtJ2spR@R)chme0Xrc?!=HIHqsL3urI(UBH3 z^Kh~-eavJP2hqA8Kf|~)jKaHmmae@h(jooTz|ulCJyv9zU>0u@8wtB~XW{uA{$p-{ zPNzF&X*{Bp*+YDuK!fjPuXEBfz`fsrKWbw^BV-x5WIvFdT&>q%*Xys)^}cCuolMGt zd+6n-cF*VVYfD|9m#p?Z%;kq~x$YiIe?8{PESXHW8g>GFifjFF<)pdNp`@DO+m6qn qg*)~5ga*Fq19Y~F!w%;Oa<+R&Fi3Z@Ufyp7eM*`^p5UkG!+!#-gsetOutline(0); mConnectTab->setTabBarDepth(36); mConnectTab->getTabbedButtonBar().setMinimumTabScaleFactor(0.1f); - mConnectTab->getTabbedButtonBar().setColour(TabbedButtonBar::frontTextColourId, Colour::fromFloatRGBA(0.4, 0.8, 1.0, 1.0)); - mConnectTab->getTabbedButtonBar().setColour(TabbedButtonBar::frontOutlineColourId, Colour::fromFloatRGBA(0.4, 0.8, 1.0, 0.5)); + mConnectTab->getTabbedButtonBar().setColour(TabbedButtonBar::frontTextColourId, Colour(0xFFFFFFFF)); + mConnectTab->getTabbedButtonBar().setColour(TabbedButtonBar::frontOutlineColourId, Colour(0xFFFF2E61)); mDirectConnectContainer = std::make_unique(); mServerConnectContainer = std::make_unique(); @@ -86,7 +86,7 @@ publicGroupsListModel(this) mRemoteAddressStaticLabel = std::make_unique