From 91c6c0db29a64fa270eca3fa5aa8811ef148771f Mon Sep 17 00:00:00 2001 From: matt Date: Mon, 24 Aug 2026 07:28:17 -0400 Subject: [PATCH 01/35] XM4 first-class support: protocol impl, bug fixes, conformance + golden tests In-progress work from the Codex session: XM4 (WH-1000XM4 v1) protocol support, 14 verified bug fixes (connection-thread crashes, command/notification races), 18 exact Bluetooth wire-format golden tests, and protocol-conformance harness. Co-Authored-By: Claude Opus 4.8 --- .gitignore | 1 + Client/BluetoothWrapper.cpp | 31 +- Client/ByteMagic.cpp | 2 +- Client/CommandSerializer.cpp | 31 +- Client/CommandSerializer.h | 5 +- Client/Constants.h | 33 +- Client/Headphones.cpp | 298 +++++++++++++----- Client/Headphones.h | 24 +- Client/fuzz/FuzzCommandSerializer.cpp | 89 ++++++ Client/fuzz/README.md | 28 ++ Client/fuzz/dictionaries/sony_protocol.dict | 23 ++ Client/fuzz/run-macos.sh | 41 +++ Client/fuzz/seeds/ack.hex | 1 + Client/fuzz/seeds/ambient_level1.hex | 1 + Client/fuzz/seeds/dangling_escape.hex | 1 + Client/fuzz/seeds/declared_size_overflow.hex | 1 + Client/fuzz/seeds/escape_triplet.hex | 1 + Client/fuzz/seeds/init.hex | 1 + Client/macos/ContentView.swift | 2 + Client/macos/HeadphonesBridge.h | 5 +- Client/macos/HeadphonesBridge.mm | 117 ++++--- Client/macos/HeadphonesModel.swift | 10 + Client/macos/MacOSBluetoothConnector.h | 8 +- Client/macos/MacOSBluetoothConnector.mm | 80 +++-- Client/tests/HeadphonesProtocolTests.cpp | 180 +++++++++++ Client/tests/ProtocolConformanceTests.cpp | 151 +++++++++ Client/tests/conformance/COVERAGE.md | 14 + Client/tests/conformance/DISCREPANCIES.md | 5 + Client/tests/conformance/PROVENANCE.md | 10 + .../conformance/fixtures/xm4_v1_frames.golden | 19 ++ .../conformance/generate_reference_goldens.rb | 29 ++ Client/tests/run-macos.sh | 24 ++ docs/QUALITY_AUDIT.md | 35 ++ docs/XM4_ROADMAP.md | 44 +++ 34 files changed, 1137 insertions(+), 208 deletions(-) create mode 100644 Client/fuzz/FuzzCommandSerializer.cpp create mode 100644 Client/fuzz/README.md create mode 100644 Client/fuzz/dictionaries/sony_protocol.dict create mode 100644 Client/fuzz/run-macos.sh create mode 100644 Client/fuzz/seeds/ack.hex create mode 100644 Client/fuzz/seeds/ambient_level1.hex create mode 100644 Client/fuzz/seeds/dangling_escape.hex create mode 100644 Client/fuzz/seeds/declared_size_overflow.hex create mode 100644 Client/fuzz/seeds/escape_triplet.hex create mode 100644 Client/fuzz/seeds/init.hex create mode 100644 Client/tests/HeadphonesProtocolTests.cpp create mode 100644 Client/tests/ProtocolConformanceTests.cpp create mode 100644 Client/tests/conformance/COVERAGE.md create mode 100644 Client/tests/conformance/DISCREPANCIES.md create mode 100644 Client/tests/conformance/PROVENANCE.md create mode 100644 Client/tests/conformance/fixtures/xm4_v1_frames.golden create mode 100644 Client/tests/conformance/generate_reference_goldens.rb create mode 100755 Client/tests/run-macos.sh create mode 100644 docs/QUALITY_AUDIT.md create mode 100644 docs/XM4_ROADMAP.md diff --git a/.gitignore b/.gitignore index 32ccd080..67f143f9 100644 --- a/.gitignore +++ b/.gitignore @@ -89,6 +89,7 @@ coverage.xml .hypothesis/ .pytest_cache/ pytestdebug.log +*.actual # Translations *.mo diff --git a/Client/BluetoothWrapper.cpp b/Client/BluetoothWrapper.cpp index cd3cb744..c4b9231c 100644 --- a/Client/BluetoothWrapper.cpp +++ b/Client/BluetoothWrapper.cpp @@ -92,8 +92,18 @@ Buffer BluetoothWrapper::sendCommandAndReadResponse(const std::vector& byt void BluetoothWrapper::_waitForAck() { - auto msg = this->_readMessage(); - this->_seqNumber = msg.seqNumber; + // Notifications can arrive between a SET and its ACK. _readMessage() acknowledges DATA_MDR frames; + // keep consuming until the device's actual ACK arrives so it cannot poison the next command. + for (int i = 0; i < 16; i++) + { + auto msg = this->_readMessage(); + if (msg.dataType == DATA_TYPE::ACK) + { + this->_seqNumber = msg.seqNumber; + return; + } + } + throw RecoverableException("No acknowledgment received from device", true); } CommandSerializer::Message BluetoothWrapper::_readMessage() @@ -118,11 +128,17 @@ CommandSerializer::Message BluetoothWrapper::_readMessage() { numRecvd = this->_connector->recv(buf, sizeof(buf)); } + if (numRecvd <= 0) + { + throw RecoverableException("Bluetooth connection closed while reading a frame", true); + } - size_t messageStart = 0; - size_t messageEnd = numRecvd; + // Bytes outside START/END markers are transport noise, not message data. When a frame spans recv() + // calls, the next chunk starts inside the frame and therefore begins at byte zero. + size_t messageStart = ongoingMessage ? 0 : static_cast(numRecvd); + size_t messageEnd = static_cast(numRecvd); - for (size_t i = 0; i < numRecvd; i++) + for (int i = 0; i < numRecvd; i++) { if (buf[i] == START_MARKER) { @@ -146,6 +162,10 @@ CommandSerializer::Message BluetoothWrapper::_readMessage() } msgBytes.insert(msgBytes.end(), buf + messageStart, buf + messageEnd); + if (msgBytes.size() > MAX_BLUETOOTH_MESSAGE_SIZE) + { + throw RecoverableException("Bluetooth frame exceeds the maximum message size", true); + } } while (!messageFinished); auto msg = CommandSerializer::unpackBtMessage(msgBytes); @@ -160,4 +180,3 @@ CommandSerializer::Message BluetoothWrapper::_readMessage() return msg; } - diff --git a/Client/ByteMagic.cpp b/Client/ByteMagic.cpp index 773666a3..910871ff 100644 --- a/Client/ByteMagic.cpp +++ b/Client/ByteMagic.cpp @@ -48,7 +48,7 @@ std::string MACBytesToString(unsigned char addr[]) { // Create hex string from the bytes. std::stringstream mac_addr_str; - for (int i = 0; i < MAC_ADDR_BYTES_LEN; i++) + for (size_t i = 0; i < MAC_ADDR_BYTES_LEN; i++) { mac_addr_str << std::hex << (((addr[MAC_ADDR_BYTES_LEN - 1 - i] & 0xF0) >> 4) & 0xF); mac_addr_str << std::hex << (addr[MAC_ADDR_BYTES_LEN - 1 - i] & 0x0F); diff --git a/Client/CommandSerializer.cpp b/Client/CommandSerializer.cpp index c0e4d551..ac9b8eb7 100644 --- a/Client/CommandSerializer.cpp +++ b/Client/CommandSerializer.cpp @@ -4,7 +4,7 @@ constexpr unsigned char ESCAPED_BYTE_SENTRY = 61; constexpr unsigned char ESCAPED_60 = 44; constexpr unsigned char ESCAPED_61 = 45; constexpr unsigned char ESCAPED_62 = 46; -constexpr int MAX_STEPS_WH_1000_XM3 = 19; +constexpr int MAX_AMBIENT_SOUND_LEVEL_V1 = 20; namespace CommandSerializer { @@ -150,10 +150,14 @@ namespace CommandSerializer ((unsigned int)(unsigned char)unescaped[4] << 8) | ((unsigned int)(unsigned char)unescaped[5]); - if (unescaped.size() < (size_t)6 + dataSize + 1) + if (dataSize > unescaped.size() - 7) { throw RecoverableException("Invalid message: declared size exceeds received data", true); } + if (dataSize != unescaped.size() - 7) + { + throw RecoverableException("Invalid message: trailing data after checksum", true); + } //Checksum covers everything from DATA_TYPE up to (not including) the checksum byte, over the unescaped bytes. if ((unsigned char)unescaped[6 + dataSize] != _sumChecksum(unescaped.data(), 6 + dataSize)) @@ -168,32 +172,18 @@ namespace CommandSerializer return ret; } - NC_DUAL_SINGLE_VALUE getDualSingleForAsmLevel(char asmLevel) + Buffer serializeNcAndAsmSetting(NC_ASM_EFFECT ncAsmEffect, NC_ASM_SETTING_TYPE ncAsmSettingType, NC_DUAL_SINGLE_VALUE ncValue, ASM_SETTING_TYPE asmSettingType, ASM_ID asmId, char asmLevel) { - NC_DUAL_SINGLE_VALUE val = NC_DUAL_SINGLE_VALUE::OFF; - if (asmLevel > MAX_STEPS_WH_1000_XM3) - { - throw std::runtime_error("Exceeded max steps"); - } - else if (asmLevel == 1) - { - val = NC_DUAL_SINGLE_VALUE::SINGLE; - } - else if (asmLevel == 0) + if (asmLevel < 0 || asmLevel > MAX_AMBIENT_SOUND_LEVEL_V1) { - val = NC_DUAL_SINGLE_VALUE::DUAL; + throw std::runtime_error("Ambient sound level must be between 0 and 20"); } - return val; - } - - Buffer serializeNcAndAsmSetting(NC_ASM_EFFECT ncAsmEffect, NC_ASM_SETTING_TYPE ncAsmSettingType, ASM_SETTING_TYPE asmSettingType, ASM_ID asmId, char asmLevel) - { Buffer ret; ret.push_back(static_cast(COMMAND_TYPE::NCASM_SET_PARAM)); ret.push_back(static_cast(NC_ASM_INQUIRED_TYPE::NOISE_CANCELLING_AND_AMBIENT_SOUND_MODE)); ret.push_back(static_cast(ncAsmEffect)); ret.push_back(static_cast(ncAsmSettingType)); - ret.push_back(static_cast(getDualSingleForAsmLevel(asmLevel))); + ret.push_back(static_cast(ncValue)); ret.push_back(static_cast(asmSettingType)); ret.push_back(static_cast(asmId)); ret.push_back(asmLevel); @@ -226,4 +216,3 @@ namespace CommandSerializer } } - diff --git a/Client/CommandSerializer.h b/Client/CommandSerializer.h index 80eb2a30..36418c43 100644 --- a/Client/CommandSerializer.h +++ b/Client/CommandSerializer.h @@ -7,7 +7,6 @@ #include "Exceptions.h" constexpr int MINIMUM_VOICE_FOCUS_STEP = 2; -constexpr unsigned int ASM_LEVEL_DISABLED = -1; namespace CommandSerializer { @@ -37,10 +36,8 @@ namespace CommandSerializer Message unpackBtMessage(const Buffer& src); - NC_DUAL_SINGLE_VALUE getDualSingleForAsmLevel(char asmLevel); - Buffer serializeNcAndAsmSetting(NC_ASM_EFFECT ncAsmEffect, NC_ASM_SETTING_TYPE ncAsmSettingType, ASM_SETTING_TYPE asmSettingType, ASM_ID asmId, char asmLevel); + Buffer serializeNcAndAsmSetting(NC_ASM_EFFECT ncAsmEffect, NC_ASM_SETTING_TYPE ncAsmSettingType, NC_DUAL_SINGLE_VALUE ncValue, ASM_SETTING_TYPE asmSettingType, ASM_ID asmId, char asmLevel); //v2 protocol variant (WH-CH720N, XM5, newer XM4, etc) - different NCASM_SET_PARAM byte layout than v1. Buffer serializeNcAndAsmSettingV2(NC_ASM_EFFECT ncAsmEffect, NC_ASM_SETTING_TYPE_V2 ncAsmSettingType, ASM_ID voicePassthrough, char asmLevel); Buffer serializeVPTSetting(VPT_INQUIRED_TYPE type, unsigned char preset); } - diff --git a/Client/Constants.h b/Client/Constants.h index 91613ca9..ceae60ed 100644 --- a/Client/Constants.h +++ b/Client/Constants.h @@ -14,7 +14,7 @@ inline unsigned char SERVICE_UUID_IN_BYTES[] = { // this is the SERVICE_UUID but 0xb3, 0x2d, 0xe3, 0x16, 0xf5, 0xe0, 0x69, 0xba }; -// Second-generation Sony protocol (WH-CH720N, WF/WH-1000XM5, newer XM4/WF-C700N units, etc). +// Second-generation Sony protocol (WH-CH720N, WF/WH-1000XM5, WF-C700N, etc). inline constexpr auto SERVICE_UUID_V2 = "956C7B26-D49A-4BA8-B03F-B17D393CB6E2"; inline unsigned char SERVICE_UUID_V2_IN_BYTES[] = { // this is the SERVICE_UUID_V2 but in bytes 0x95, 0x6c, 0x7b, 0x26, 0xd4, 0x9a, 0x4b, 0xa8, @@ -27,6 +27,37 @@ enum class SonyProtocolVersion : signed char V2 = 1 }; +// First-generation MDR protocol used by the WH-1000XM4 and earlier models. Several values overlap +// with v2 but mean something entirely different, so call sites must select a namespace only after +// the SDP service UUID has established the protocol version. +namespace V1Command +{ + inline constexpr unsigned char INIT_REQUEST = 0x00; + inline constexpr unsigned char INIT_REPLY = 0x01; + inline constexpr unsigned char FW_GET = 0x04; + inline constexpr unsigned char FW_RET = 0x05; + inline constexpr unsigned char BATTERY_GET = 0x10; + inline constexpr unsigned char BATTERY_RET = 0x11; + inline constexpr unsigned char CODEC_GET = 0x18; + inline constexpr unsigned char CODEC_RET = 0x19; + inline constexpr unsigned char POWER_OFF = 0x22; + inline constexpr unsigned char EQ_GET = 0x56; + inline constexpr unsigned char EQ_RET = 0x57; + inline constexpr unsigned char EQ_SET = 0x58; + inline constexpr unsigned char AMBIENT_GET = 0x66; + inline constexpr unsigned char AMBIENT_RET = 0x67; + inline constexpr unsigned char AMBIENT_SET = 0x68; + inline constexpr unsigned char DSEE_GET = 0xe6; + inline constexpr unsigned char DSEE_RET = 0xe7; + inline constexpr unsigned char DSEE_SET = 0xe8; + inline constexpr unsigned char BTNMODE_GET = 0xf6; + inline constexpr unsigned char BTNMODE_RET = 0xf7; + inline constexpr unsigned char BTNMODE_SET = 0xf8; + inline constexpr unsigned char SUB_AUTO_POWER_OFF = 0x04; + inline constexpr unsigned char SUB_SPEAK_TO_CHAT = 0x05; + inline constexpr unsigned char MANUAL_EQ = 0xff; +} + // Second-generation (v2) inquiry/response command opcodes (the first payload byte). // Byte layouts reverse-engineered by GadgetBridge (SonyProtocolImplV2); verified against WH-CH720N. namespace V2Command diff --git a/Client/Headphones.cpp b/Client/Headphones.cpp index 54d010f2..94cf1bde 100644 --- a/Client/Headphones.cpp +++ b/Client/Headphones.cpp @@ -18,11 +18,13 @@ void Headphones::setAmbientSoundControl(bool val) bool Headphones::getAmbientSoundControl() { + std::lock_guard guard(this->_propertyMtx); return this->_ambientSoundControl.current; } bool Headphones::isFocusOnVoiceAvailable() { + std::lock_guard guard(this->_propertyMtx); return this->_ambientSoundControl.current && this->_asmLevel.current > MINIMUM_VOICE_FOCUS_STEP; } @@ -34,22 +36,25 @@ void Headphones::setFocusOnVoice(bool val) bool Headphones::getFocusOnVoice() { + std::lock_guard guard(this->_propertyMtx); return this->_focusOnVoice.current; } bool Headphones::isSetAsmLevelAvailable() { + std::lock_guard guard(this->_propertyMtx); return this->_ambientSoundControl.current; } void Headphones::setAsmLevel(int val) { std::lock_guard guard(this->_propertyMtx); - this->_asmLevel.desired = val; + this->_asmLevel.desired = std::clamp(val, 0, 20); } int Headphones::getAsmLevel() { + std::lock_guard guard(this->_propertyMtx); return this->_asmLevel.current; } @@ -61,6 +66,7 @@ void Headphones::setSurroundPosition(SOUND_POSITION_PRESET val) SOUND_POSITION_PRESET Headphones::getSurroundPosition() { + std::lock_guard guard(this->_propertyMtx); return this->_surroundPosition.current; } @@ -72,21 +78,40 @@ void Headphones::setVptType(int val) int Headphones::getVptType() { + std::lock_guard guard(this->_propertyMtx); return this->_vptType.current; } void Headphones::initDevice() { - // v2 devices expect an init handshake before they answer GET inquiries. Best-effort: the reply - // (INIT_REPLY, 8 bytes on v2) is ignored here - we only need the device to enter the ready state. + // Both protocol generations expect an init exchange before they answer state inquiries. + auto isV1 = this->_conn.getProtocolVersion() == SonyProtocolVersion::V1; this->_conn.sendCommandAndReadResponse( - { (char)V2Command::INIT_REQUEST, 0x00 }, - V2Command::INIT_REPLY + { (char)(isV1 ? V1Command::INIT_REQUEST : V2Command::INIT_REQUEST), 0x00 }, + isV1 ? V1Command::INIT_REPLY : V2Command::INIT_REPLY ); } void Headphones::requestBattery() { + if (this->_conn.getProtocolVersion() == SonyProtocolVersion::V1) + { + // v1 (including WH-1000XM4): 10 00 is the single-battery inquiry. Never substitute the + // v2 22 00 command here: 0x22 is POWER_OFF on this protocol generation. + auto resp = this->_conn.sendCommandAndReadResponse( + { (char)V1Command::BATTERY_GET, 0x00 }, + V1Command::BATTERY_RET, + 0x00 + ); + if (resp.size() < 4) throw std::runtime_error("Invalid v1 battery response"); + + std::lock_guard guard(this->_propertyMtx); + this->_batteryLevel = (unsigned char)resp[2]; + this->_batteryCharging = resp[3] == 1; + this->_hasBattery = true; + return; + } + // Single battery (over-ear and most models): GET 22 00 -> RET 23 00 try { auto resp = this->_conn.sendCommandAndReadResponse({ (char)V2Command::BATTERY_GET, 0x00 }, V2Command::BATTERY_RET, 0x00); @@ -94,6 +119,7 @@ void Headphones::requestBattery() std::lock_guard guard(this->_propertyMtx); this->_batteryLevel = (unsigned char)resp[2]; this->_batteryCharging = resp[3] == 1; + this->_hasBattery = true; return; // found a single battery; don't waste time probing the TWS types } } catch (...) {} @@ -107,6 +133,7 @@ void Headphones::requestBattery() this->_batteryLeft = (unsigned char)resp[2]; this->_batteryRight = (unsigned char)resp[4]; this->_batteryLevel = std::min(this->_batteryLeft, this->_batteryRight); + this->_hasBattery = true; } } catch (...) {} @@ -119,32 +146,42 @@ void Headphones::requestBattery() } catch (...) {} } +bool Headphones::hasBattery() { std::lock_guard guard(this->_propertyMtx); return this->_hasBattery; } int Headphones::getBatteryLevel() { + std::lock_guard guard(this->_propertyMtx); return this->_batteryLevel; } bool Headphones::isBatteryCharging() { + std::lock_guard guard(this->_propertyMtx); return this->_batteryCharging; } -bool Headphones::hasDualBattery() { return this->_hasDualBattery; } -int Headphones::getBatteryLeft() { return this->_batteryLeft; } -int Headphones::getBatteryRight() { return this->_batteryRight; } -int Headphones::getBatteryCase() { return this->_batteryCase; } +bool Headphones::hasDualBattery() { std::lock_guard guard(this->_propertyMtx); return this->_hasDualBattery; } +int Headphones::getBatteryLeft() { std::lock_guard guard(this->_propertyMtx); return this->_batteryLeft; } +int Headphones::getBatteryRight() { std::lock_guard guard(this->_propertyMtx); return this->_batteryRight; } +int Headphones::getBatteryCase() { std::lock_guard guard(this->_propertyMtx); return this->_batteryCase; } void Headphones::requestEqualizer() { - // GET: 56 00 -> RET: 57 00 06 + auto isV1 = this->_conn.getProtocolVersion() == SonyProtocolVersion::V1; + auto subtype = isV1 ? 0x01 : 0x00; + // v1 uses subtype 01; v2 uses subtype 00. Both return the same six-band value layout. auto resp = this->_conn.sendCommandAndReadResponse( - { (char)V2Command::EQ_GET, 0x00 }, - V2Command::EQ_RET + { (char)(isV1 ? V1Command::EQ_GET : V2Command::EQ_GET), (char)subtype }, + isV1 ? V1Command::EQ_RET : V2Command::EQ_RET, + subtype ); if (resp.size() >= 3) { std::lock_guard guard(this->_propertyMtx); - this->_eqPreset = static_cast((unsigned char)resp[2]); + auto rawPreset = (unsigned char)resp[2]; + this->_eqPreset = (isV1 && rawPreset == V1Command::MANUAL_EQ) + ? EQ_PRESET::MANUAL + : static_cast(rawPreset); + this->_hasEqualizer = true; // When band data is present (57 00 06 ), decode the -10..10 values. if (resp.size() >= 10) { @@ -157,18 +194,24 @@ void Headphones::requestEqualizer() } } +bool Headphones::hasEqualizer() { std::lock_guard guard(this->_propertyMtx); return this->_hasEqualizer; } EQ_PRESET Headphones::getEqualizerPreset() { + std::lock_guard guard(this->_propertyMtx); return this->_eqPreset; } void Headphones::setEqualizerPreset(EQ_PRESET preset) { - // SET preset: 58 00 00 + if (!this->hasEqualizer()) throw std::logic_error("Equalizer capability has not been confirmed"); + auto isV1 = this->_conn.getProtocolVersion() == SonyProtocolVersion::V1; + auto rawPreset = (unsigned char)preset; + if (isV1 && preset == EQ_PRESET::MANUAL) rawPreset = V1Command::MANUAL_EQ; + // SET preset: v1 58 01 00; v2 58 00 00. this->_conn.sendCommand({ - (char)V2Command::EQ_SET, - 0x00, - (char)static_cast(preset), + (char)(isV1 ? V1Command::EQ_SET : V2Command::EQ_SET), + (char)(isV1 ? 0x01 : 0x00), + (char)rawPreset, 0x00 }); std::lock_guard guard(this->_propertyMtx); @@ -177,12 +220,14 @@ void Headphones::setEqualizerPreset(EQ_PRESET preset) void Headphones::setEqualizerCustom(int clearBass, const std::vector& bands) { - // SET custom: 58 00 A0 06 (0xA0 = MANUAL preset; values clamped to [-10,10]) + if (!this->hasEqualizer()) throw std::logic_error("Equalizer capability has not been confirmed"); + auto isV1 = this->_conn.getProtocolVersion() == SonyProtocolVersion::V1; + // v1 selects custom EQ with 0xff/subtype 01; v2 uses 0xa0/subtype 00. auto clamp = [](int v) { return (char)(unsigned char)(std::max(-10, std::min(10, v)) + 10); }; Buffer cmd = { - (char)V2Command::EQ_SET, - 0x00, - (char)static_cast(EQ_PRESET::MANUAL), + (char)(isV1 ? V1Command::EQ_SET : V2Command::EQ_SET), + (char)(isV1 ? 0x01 : 0x00), + (char)(isV1 ? V1Command::MANUAL_EQ : static_cast(EQ_PRESET::MANUAL)), 0x06, clamp(clearBass) }; @@ -194,50 +239,62 @@ void Headphones::setEqualizerCustom(int clearBass, const std::vector& bands std::lock_guard guard(this->_propertyMtx); this->_eqPreset = EQ_PRESET::MANUAL; - this->_eqClearBass = clearBass; + this->_eqClearBass = std::clamp(clearBass, -10, 10); for (int i = 0; i < 5; i++) { - this->_eqBands[i] = i < (int)bands.size() ? bands[i] : 0; + this->_eqBands[i] = std::clamp(i < (int)bands.size() ? bands[i] : 0, -10, 10); } } int Headphones::getClearBass() { + std::lock_guard guard(this->_propertyMtx); return this->_eqClearBass; } int Headphones::getEqualizerBand(int index) { + std::lock_guard guard(this->_propertyMtx); return (index >= 0 && index < (int)this->_eqBands.size()) ? this->_eqBands[index] : 0; } void Headphones::requestDsee() { - // GET: e6 01 -> RET: e7 01 + auto isV1 = this->_conn.getProtocolVersion() == SonyProtocolVersion::V1; + auto subtype = isV1 ? 0x02 : 0x01; auto resp = this->_conn.sendCommandAndReadResponse( - { (char)V2Command::DSEE_GET, 0x01 }, - V2Command::DSEE_RET + { (char)(isV1 ? V1Command::DSEE_GET : V2Command::DSEE_GET), (char)subtype }, + isV1 ? V1Command::DSEE_RET : V2Command::DSEE_RET, + subtype ); - if (resp.size() >= 3) + if ((!isV1 && resp.size() >= 3) || (isV1 && resp.size() >= 4)) { std::lock_guard guard(this->_propertyMtx); - this->_dsee = resp[2] != 0; + this->_dsee = resp[isV1 ? 3 : 2] != 0; + this->_hasDsee = true; } } +bool Headphones::hasDsee() { std::lock_guard guard(this->_propertyMtx); return this->_hasDsee; } bool Headphones::getDsee() { + std::lock_guard guard(this->_propertyMtx); return this->_dsee; } void Headphones::setDsee(bool enabled) { - // SET: e8 01 - this->_conn.sendCommand({ - (char)V2Command::DSEE_SET, - 0x01, - (char)(enabled ? 0x01 : 0x00) - }); + if (!this->hasDsee()) throw std::logic_error("DSEE capability has not been confirmed"); + if (this->_conn.getProtocolVersion() == SonyProtocolVersion::V1) + { + // v1: e8 02 00 + this->_conn.sendCommand({ (char)V1Command::DSEE_SET, 0x02, 0x00, (char)(enabled ? 0x01 : 0x00) }); + } + else + { + // v2: e8 01 + this->_conn.sendCommand({ (char)V2Command::DSEE_SET, 0x01, (char)(enabled ? 0x01 : 0x00) }); + } std::lock_guard guard(this->_propertyMtx); this->_dsee = enabled; } @@ -266,13 +323,27 @@ void Headphones::requestAmbientState() } else { - // v1 (e.g. WH-1000XM4): upstream drove these settings fire-and-forget, with no read-back at all. - // We still issue the GET because v1 devices need valid protocol traffic after connect to stay - // powered on, and we read the reply to drain it from the socket - but we deliberately do NOT parse - // it back into the NC/Ambient/level state. The v1 reply layout is unverified, and letting a - // mis-parsed 2s poll overwrite the user's choice is exactly what made Ambient snap back to Noise - // Cancelling and the level slider jump while being dragged. Trust the user's selection instead. - this->_conn.sendCommandAndReadResponse({ 0x66, 0x02 }, 0x67); + // v1: 67 02 . + auto resp = this->_conn.sendCommandAndReadResponse( + { (char)V1Command::AMBIENT_GET, 0x02 }, V1Command::AMBIENT_RET, 0x02); + if (resp.size() == 8) + { + bool enabled = resp[2] != 0; + auto settingType = (unsigned char)resp[3]; + auto settingValue = (unsigned char)resp[4]; + int level = (unsigned char)resp[7]; + bool ambient = enabled && settingValue == 0x00 && level > 0; + bool voice = resp[6] != 0; + + std::lock_guard guard(this->_propertyMtx); + if (settingType <= static_cast(NC_ASM_SETTING_TYPE::DUAL_SINGLE_OFF)) + this->_ncAsmSettingType = static_cast(settingType); + if ((unsigned char)resp[5] <= static_cast(ASM_SETTING_TYPE::LEVEL_ADJUSTMENT)) + this->_asmSettingType = static_cast((unsigned char)resp[5]); + this->_ambientSoundControl.current = this->_ambientSoundControl.desired = enabled; + this->_asmLevel.current = this->_asmLevel.desired = ambient ? level : 0; + this->_focusOnVoice.current = this->_focusOnVoice.desired = ambient && voice; + } } } @@ -312,6 +383,30 @@ void Headphones::probeCapabilities() { // Each GET is best-effort: an unsupported feature times out (recv timeout -> throw) and stays unsupported, // so we never expose or send a command the device can't handle. + if (this->_conn.getProtocolVersion() == SonyProtocolVersion::V1) + { + try { + auto r = this->_conn.sendCommandAndReadResponse({ (char)V1Command::FW_GET, 0x02 }, V1Command::FW_RET, 0x02); + if (r.size() > 3) { std::lock_guard g(this->_propertyMtx); this->_firmware = std::string(r.begin() + 3, r.end()); this->_hasFirmware = true; } + } catch (...) {} + + try { + auto r = this->_conn.sendCommandAndReadResponse({ (char)V1Command::CODEC_GET, 0x00 }, V1Command::CODEC_RET, 0x00); + if (r.size() >= 3) { auto n = codecName((unsigned char)r[2]); if (!n.empty()) { std::lock_guard g(this->_propertyMtx); this->_codec = n; this->_hasCodec = true; } } + } catch (...) {} + + try { + auto r = this->_conn.sendCommandAndReadResponse({ (char)V1Command::BTNMODE_GET, (char)V1Command::SUB_AUTO_POWER_OFF }, V1Command::BTNMODE_RET, V1Command::SUB_AUTO_POWER_OFF); + if (r.size() >= 5) { std::lock_guard g(this->_propertyMtx); this->_autoPowerOff = apoIndexFromCode((unsigned char)r[3], (unsigned char)r[4]); this->_hasAutoPowerOff = true; } + } catch (...) {} + + try { + auto r = this->_conn.sendCommandAndReadResponse({ (char)V1Command::BTNMODE_GET, (char)V1Command::SUB_SPEAK_TO_CHAT }, V1Command::BTNMODE_RET, V1Command::SUB_SPEAK_TO_CHAT); + if (r.size() >= 4 && r[2] == 0x01) { std::lock_guard g(this->_propertyMtx); this->_speakToChat = r[3] != 0; this->_hasSpeakToChat = true; } + } catch (...) {} + return; + } + try { auto r = this->_conn.sendCommandAndReadResponse({ (char)V2Command::FW_GET, 0x02 }, V2Command::FW_RET); if (r.size() > 3) { std::lock_guard g(this->_propertyMtx); this->_firmware = std::string(r.begin() + 3, r.end()); this->_hasFirmware = true; } @@ -338,35 +433,53 @@ void Headphones::probeCapabilities() } catch (...) {} } -bool Headphones::hasAutoPowerOff() { return this->_hasAutoPowerOff; } -int Headphones::getAutoPowerOff() { return this->_autoPowerOff; } +bool Headphones::hasAutoPowerOff() { std::lock_guard guard(this->_propertyMtx); return this->_hasAutoPowerOff; } +int Headphones::getAutoPowerOff() { std::lock_guard guard(this->_propertyMtx); return this->_autoPowerOff; } void Headphones::setAutoPowerOff(int index) { - if (index < 0 || index > 5) return; - this->_conn.sendCommand({ (char)V2Command::APO_SET, 0x05, (char)APO_CODES[index].first, (char)APO_CODES[index].second }); + if (index < 0 || index > 5) throw std::invalid_argument("Invalid auto power-off option"); + if (!this->hasAutoPowerOff()) throw std::logic_error("Auto power-off capability has not been confirmed"); + if (this->_conn.getProtocolVersion() == SonyProtocolVersion::V1) + { + this->_conn.sendCommand({ (char)V1Command::BTNMODE_SET, (char)V1Command::SUB_AUTO_POWER_OFF, 0x01, (char)APO_CODES[index].first, (char)APO_CODES[index].second }); + } + else + { + this->_conn.sendCommand({ (char)V2Command::APO_SET, 0x05, (char)APO_CODES[index].first, (char)APO_CODES[index].second }); + } std::lock_guard guard(this->_propertyMtx); this->_autoPowerOff = index; } -bool Headphones::hasFirmware() { return this->_hasFirmware; } -std::string Headphones::getFirmware() { return this->_firmware; } -bool Headphones::hasCodec() { return this->_hasCodec; } -std::string Headphones::getCodec() { return this->_codec; } +bool Headphones::hasFirmware() { std::lock_guard guard(this->_propertyMtx); return this->_hasFirmware; } +std::string Headphones::getFirmware() { std::lock_guard guard(this->_propertyMtx); return this->_firmware; } +bool Headphones::hasCodec() { std::lock_guard guard(this->_propertyMtx); return this->_hasCodec; } +std::string Headphones::getCodec() { std::lock_guard guard(this->_propertyMtx); return this->_codec; } -bool Headphones::hasSpeakToChat() { return this->_hasSpeakToChat; } -bool Headphones::getSpeakToChat() { return this->_speakToChat; } +bool Headphones::hasSpeakToChat() { std::lock_guard guard(this->_propertyMtx); return this->_hasSpeakToChat; } +bool Headphones::getSpeakToChat() { std::lock_guard guard(this->_propertyMtx); return this->_speakToChat; } void Headphones::setSpeakToChat(bool enabled) { - // SET: f8 0c 01 (enable bit is inverted on v2) - this->_conn.sendCommand({ (char)V2Command::BTNMODE_SET, (char)V2Command::SUB_SPEAK_TO_CHAT, (char)(enabled ? 0x00 : 0x01), 0x01 }); + if (!this->hasSpeakToChat()) throw std::logic_error("Speak-to-Chat capability has not been confirmed"); + if (this->_conn.getProtocolVersion() == SonyProtocolVersion::V1) + { + this->_conn.sendCommand({ (char)V1Command::BTNMODE_SET, (char)V1Command::SUB_SPEAK_TO_CHAT, 0x01, (char)(enabled ? 0x01 : 0x00) }); + } + else + { + // v2 enable bit is inverted. + this->_conn.sendCommand({ (char)V2Command::BTNMODE_SET, (char)V2Command::SUB_SPEAK_TO_CHAT, (char)(enabled ? 0x00 : 0x01), 0x01 }); + } std::lock_guard guard(this->_propertyMtx); this->_speakToChat = enabled; } -bool Headphones::hasAdaptiveVolume() { return this->_hasAdaptiveVolume; } -bool Headphones::getAdaptiveVolume() { return this->_adaptiveVolume; } +bool Headphones::hasAdaptiveVolume() { std::lock_guard guard(this->_propertyMtx); return this->_hasAdaptiveVolume; } +bool Headphones::getAdaptiveVolume() { std::lock_guard guard(this->_propertyMtx); return this->_adaptiveVolume; } void Headphones::setAdaptiveVolume(bool enabled) { + if (this->_conn.getProtocolVersion() != SonyProtocolVersion::V2 || !this->hasAdaptiveVolume()) + throw std::logic_error("Adaptive volume capability has not been confirmed"); // SET: f8 0a (inverted) this->_conn.sendCommand({ (char)V2Command::BTNMODE_SET, (char)V2Command::SUB_ADAPTIVE_VOLUME, (char)(enabled ? 0x00 : 0x01) }); std::lock_guard guard(this->_propertyMtx); @@ -375,68 +488,97 @@ void Headphones::setAdaptiveVolume(bool enabled) bool Headphones::isChanged() { - return !(this->_ambientSoundControl.isFulfilled() && this->_asmLevel.isFulfilled() && this->_focusOnVoice.isFulfilled() && this->_surroundPosition.isFulfilled() && this->_vptType.isFulfilled()); + std::lock_guard guard(this->_propertyMtx); + auto ambientChanged = !(this->_ambientSoundControl.isFulfilled() && this->_asmLevel.isFulfilled() && this->_focusOnVoice.isFulfilled()); + auto vptChanged = this->_conn.getProtocolVersion() == SonyProtocolVersion::V1 && + !(this->_surroundPosition.isFulfilled() && this->_vptType.isFulfilled()); + return ambientChanged || vptChanged; } void Headphones::setChanges() { auto protocolVersion = this->_conn.getProtocolVersion(); + Property ambientSoundControl; + Property focusOnVoice; + Property asmLevelProperty; + NC_ASM_SETTING_TYPE ncAsmSettingType; + ASM_SETTING_TYPE asmSettingType; + { + std::lock_guard guard(this->_propertyMtx); + ambientSoundControl = this->_ambientSoundControl; + focusOnVoice = this->_focusOnVoice; + asmLevelProperty = this->_asmLevel; + ncAsmSettingType = this->_ncAsmSettingType; + asmSettingType = this->_asmSettingType; + } - if (!(this->_ambientSoundControl.isFulfilled() && this->_focusOnVoice.isFulfilled() && this->_asmLevel.isFulfilled())) + if (!(ambientSoundControl.isFulfilled() && focusOnVoice.isFulfilled() && asmLevelProperty.isFulfilled())) { if (protocolVersion == SonyProtocolVersion::V2) { // v2 has no separate "disabled" level - NC vs Ambient Sound is its own field, and level is 1-based. - char asmLevel = static_cast(this->_asmLevel.desired > 0 ? this->_asmLevel.desired : 1); + char asmLevel = static_cast(asmLevelProperty.desired > 0 ? asmLevelProperty.desired : 1); this->_conn.sendCommand(CommandSerializer::serializeNcAndAsmSettingV2( - this->_ambientSoundControl.desired ? NC_ASM_EFFECT::ON : NC_ASM_EFFECT::OFF, - this->_asmLevel.desired > 0 ? NC_ASM_SETTING_TYPE_V2::AMBIENT_SOUND : NC_ASM_SETTING_TYPE_V2::NOISE_CANCELLING, - this->_focusOnVoice.desired ? ASM_ID::VOICE : ASM_ID::NORMAL, + ambientSoundControl.desired ? NC_ASM_EFFECT::ON : NC_ASM_EFFECT::OFF, + asmLevelProperty.desired > 0 ? NC_ASM_SETTING_TYPE_V2::AMBIENT_SOUND : NC_ASM_SETTING_TYPE_V2::NOISE_CANCELLING, + focusOnVoice.desired ? ASM_ID::VOICE : ASM_ID::NORMAL, asmLevel )); } else { - auto ncAsmEffect = this->_ambientSoundControl.desired ? NC_ASM_EFFECT::ADJUSTMENT_COMPLETION : NC_ASM_EFFECT::OFF; - auto asmId = this->_focusOnVoice.desired ? ASM_ID::VOICE : ASM_ID::NORMAL; - auto asmLevel = this->_ambientSoundControl.desired ? this->_asmLevel.desired : ASM_LEVEL_DISABLED; + auto ncAsmEffect = ambientSoundControl.desired ? NC_ASM_EFFECT::ADJUSTMENT_COMPLETION : NC_ASM_EFFECT::OFF; + auto asmId = focusOnVoice.desired ? ASM_ID::VOICE : ASM_ID::NORMAL; + auto asmLevel = ambientSoundControl.desired ? asmLevelProperty.desired : 0; + auto noiseCancelling = ambientSoundControl.desired && asmLevelProperty.desired == 0; + auto ncValue = noiseCancelling + ? (ncAsmSettingType == NC_ASM_SETTING_TYPE::DUAL_SINGLE_OFF ? NC_DUAL_SINGLE_VALUE::DUAL : NC_DUAL_SINGLE_VALUE::SINGLE) + : NC_DUAL_SINGLE_VALUE::OFF; this->_conn.sendCommand(CommandSerializer::serializeNcAndAsmSetting( ncAsmEffect, - NC_ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, - ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, + ncAsmSettingType, + ncValue, + asmSettingType, asmId, asmLevel )); } std::lock_guard guard(this->_propertyMtx); - this->_ambientSoundControl.fulfill(); - this->_asmLevel.fulfill(); - this->_focusOnVoice.fulfill(); + if (this->_ambientSoundControl.desired == ambientSoundControl.desired) this->_ambientSoundControl.fulfill(); + if (this->_asmLevel.desired == asmLevelProperty.desired) this->_asmLevel.fulfill(); + if (this->_focusOnVoice.desired == focusOnVoice.desired) this->_focusOnVoice.fulfill(); } // VPT/Surround has no known v2 command and no hardware on v2-only devices like the CH720N - v1 only. - if (protocolVersion == SonyProtocolVersion::V1 && !(this->_vptType.isFulfilled() && this->_surroundPosition.isFulfilled())) { + Property vptType; + Property surroundPosition; + { + std::lock_guard guard(this->_propertyMtx); + vptType = this->_vptType; + surroundPosition = this->_surroundPosition; + } + if (protocolVersion == SonyProtocolVersion::V1 && !(vptType.isFulfilled() && surroundPosition.isFulfilled())) { VPT_INQUIRED_TYPE command; unsigned char preset; - if (this->_vptType.desired != 0) { + if (vptType.desired != 0) { command = VPT_INQUIRED_TYPE::VPT; - preset = static_cast(this->_vptType.desired); + preset = static_cast(vptType.desired); } - else if (this->_surroundPosition.desired != SOUND_POSITION_PRESET::OFF) { + else if (surroundPosition.desired != SOUND_POSITION_PRESET::OFF) { command = VPT_INQUIRED_TYPE::SOUND_POSITION; - preset = static_cast(this->_surroundPosition.desired); + preset = static_cast(surroundPosition.desired); } else { // Just used that one because it seems like it disables both - if (this->_surroundPosition.current != SOUND_POSITION_PRESET::OFF) { + if (surroundPosition.current != SOUND_POSITION_PRESET::OFF) { command = VPT_INQUIRED_TYPE::SOUND_POSITION; preset = static_cast(SOUND_POSITION_PRESET::OFF); } - else if (this->_vptType.current != 0) { + else if (vptType.current != 0) { command = VPT_INQUIRED_TYPE::VPT; preset = 0; } @@ -448,7 +590,7 @@ void Headphones::setChanges() this->_conn.sendCommand(CommandSerializer::serializeVPTSetting(command, preset)); std::lock_guard guard(this->_propertyMtx); - this->_vptType.fulfill(); - this->_surroundPosition.fulfill(); + if (this->_vptType.desired == vptType.desired) this->_vptType.fulfill(); + if (this->_surroundPosition.desired == surroundPosition.desired) this->_surroundPosition.fulfill(); } } diff --git a/Client/Headphones.h b/Client/Headphones.h index 6197d569..a051985c 100644 --- a/Client/Headphones.h +++ b/Client/Headphones.h @@ -34,12 +34,13 @@ class Headphones { void setVptType(int val); int getVptType(); - // Handshake the device expects before it answers inquiry (GET) commands on the v2 protocol. + // Handshake the device expects before it answers inquiry (GET) commands. void initDevice(); - // Battery (v2 inquiry). getBatteryLevel() returns -1 until requestBattery() succeeds. + // Battery. getBatteryLevel() returns -1 until requestBattery() succeeds. // For TWS earbuds requestBattery() also fills the per-earbud + case levels (hasDualBattery()). void requestBattery(); + bool hasBattery(); int getBatteryLevel(); bool isBatteryCharging(); bool hasDualBattery(); @@ -47,8 +48,9 @@ class Headphones { int getBatteryRight(); int getBatteryCase(); - // Equalizer (v2). requestEqualizer() reads current state; setEqualizerPreset() pushes a preset immediately. + // Equalizer. Wire subtypes and the custom-preset byte differ between protocol generations. void requestEqualizer(); + bool hasEqualizer(); EQ_PRESET getEqualizerPreset(); void setEqualizerPreset(EQ_PRESET preset); // Custom (manual) EQ: 5 band values + clear bass, each in [-10, 10]. Selects the MANUAL preset. @@ -56,8 +58,9 @@ class Headphones { int getClearBass(); int getEqualizerBand(int index); // 0..4 - // DSEE / audio upsampling (v2). + // DSEE / audio upsampling. void requestDsee(); + bool hasDsee(); bool getDsee(); void setDsee(bool enabled); @@ -89,22 +92,27 @@ class Headphones { bool isChanged(); void setChanges(); private: - Property _ambientSoundControl = { 0 }; - Property _focusOnVoice = { 0 }; - Property _asmLevel = { 0 }; + Property _ambientSoundControl = { false, false }; + Property _focusOnVoice = { false, false }; + Property _asmLevel = { 0, 0 }; + NC_ASM_SETTING_TYPE _ncAsmSettingType = NC_ASM_SETTING_TYPE::DUAL_SINGLE_OFF; + ASM_SETTING_TYPE _asmSettingType = ASM_SETTING_TYPE::LEVEL_ADJUSTMENT; Property _surroundPosition = { SOUND_POSITION_PRESET::OUT_OF_RANGE, SOUND_POSITION_PRESET::OFF }; - Property _vptType = { 0 }; + Property _vptType = { 0, 0 }; int _batteryLevel = -1; + bool _hasBattery = false; bool _batteryCharging = false; bool _hasDualBattery = false; int _batteryLeft = -1; int _batteryRight = -1; int _batteryCase = -1; EQ_PRESET _eqPreset = EQ_PRESET::OFF; + bool _hasEqualizer = false; std::vector _eqBands = { 0, 0, 0, 0, 0 }; int _eqClearBass = 0; bool _dsee = false; + bool _hasDsee = false; bool _hasAutoPowerOff = false; int _autoPowerOff = 0; bool _hasFirmware = false; std::string _firmware; diff --git a/Client/fuzz/FuzzCommandSerializer.cpp b/Client/fuzz/FuzzCommandSerializer.cpp new file mode 100644 index 00000000..1718af12 --- /dev/null +++ b/Client/fuzz/FuzzCommandSerializer.cpp @@ -0,0 +1,89 @@ +#include "CommandSerializer.h" + +#include +#include +#include +#include + +namespace +{ + [[noreturn]] void failInvariant() + { + std::abort(); + } + + void requireEqual(const Message& expected, const Message& actual) + { + if (expected.dataType != actual.dataType || + expected.seqNumber != actual.seqNumber || + expected.payload != actual.payload) + { + failInvariant(); + } + } +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + if (size > MAX_BLUETOOTH_MESSAGE_SIZE) + { + return 0; + } + + Buffer input; + if (size != 0) + { + input.assign(reinterpret_cast(data), + reinterpret_cast(data) + size); + } + + // Exercise the untrusted inbound parser directly. Malformed frames are expected + // to throw; sanitizer findings and invariant failures are not. + try + { + auto decoded = CommandSerializer::unpackBtMessage(input); + try + { + auto packaged = CommandSerializer::packageDataForBt( + decoded.payload, decoded.dataType, static_cast(decoded.seqNumber)); + Buffer body(packaged.begin() + 1, packaged.end() - 1); + requireEqual(decoded, CommandSerializer::unpackBtMessage(body)); + } + catch (const std::exception&) + { + // An accepted inbound frame can be larger than the outbound framing limit + // after canonical escaping. That size rejection is expected behavior. + } + } + catch (const std::exception&) + { + } + + // Turn arbitrary bytes into structured payloads to reach the packager and its + // escaping logic quickly, then verify every package that fits can be decoded. + if (size >= 2) + { + Buffer payload; + if (size > 2) + { + payload.assign(reinterpret_cast(data) + 2, + reinterpret_cast(data) + size); + } + const auto dataType = static_cast(static_cast(data[0])); + const auto sequence = data[1]; + + try + { + auto packaged = CommandSerializer::packageDataForBt(payload, dataType, sequence); + Buffer body(packaged.begin() + 1, packaged.end() - 1); + Message expected{ dataType, static_cast(sequence), payload }; + requireEqual(expected, CommandSerializer::unpackBtMessage(body)); + } + catch (const std::exception&) + { + // Oversized escaped output is an expected packager rejection. + } + } + + return 0; +} diff --git a/Client/fuzz/README.md b/Client/fuzz/README.md new file mode 100644 index 00000000..774f4e67 --- /dev/null +++ b/Client/fuzz/README.md @@ -0,0 +1,28 @@ +# Protocol fuzzing + +`FuzzCommandSerializer.cpp` targets the raw frame body accepted by +`CommandSerializer::unpackBtMessage`. It checks two properties: + +- malformed input is rejected without memory errors or undefined behavior; +- valid packets retain their type, sequence, and payload after a package/decode + round trip. + +The corpus is generated in a temporary directory from reviewed hexadecimal seeds. +It includes empty, minimal valid, typical XM4, escaped-byte, truncated escape, and +oversized-length inputs. `sony_protocol.dict` supplies framing bytes and safe XM4 +v1 inquiry opcodes. + +Run the sanitizer campaign on macOS: + +```sh +Client/fuzz/run-macos.sh +``` + +Override the default 60-second smoke duration with `FUZZ_SECONDS`. Crash artifacts +are intentionally kept outside the repository; minimize and reproduce any finding, +then add the smallest input to the permanent protocol regression tests. + +MemorySanitizer is not included because it requires a fully instrumented C++ +standard library. ThreadSanitizer is not applicable to this single-threaded parser +target; connection concurrency is covered by the protocol integration tests and +Xcode static analysis. diff --git a/Client/fuzz/dictionaries/sony_protocol.dict b/Client/fuzz/dictionaries/sony_protocol.dict new file mode 100644 index 00000000..30b64f21 --- /dev/null +++ b/Client/fuzz/dictionaries/sony_protocol.dict @@ -0,0 +1,23 @@ +# Sony RFCOMM framing, escape, data-type, and XM4 v1 command tokens. +start="\x3e" +end="\x3c" +escape="\x3d" +escaped_start="\x3d\x2e" +escaped_end="\x3d\x2c" +escaped_escape="\x3d\x2d" +ack="\x01" +data_mdr="\x0c" +zero_size="\x00\x00\x00\x00" +size_two="\x00\x00\x00\x02" +size_eight="\x00\x00\x00\x08" +size_max="\x00\x00\x07\xf9" +size_overflow="\xff\xff\xff\xff" +init="\x00\x00" +firmware="\x04\x02" +battery="\x10\x00" +codec="\x18\x00" +equalizer="\x56\x01" +ambient="\x66\x02" +dsee="\xe6\x02" +auto_power_off="\xf6\x04" +speak_to_chat="\xf6\x05" diff --git a/Client/fuzz/run-macos.sh b/Client/fuzz/run-macos.sh new file mode 100644 index 00000000..d5cd67a0 --- /dev/null +++ b/Client/fuzz/run-macos.sh @@ -0,0 +1,41 @@ +#!/bin/sh +set -eu + +client_dir=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd) +fuzz_dir="$client_dir/fuzz" +work_dir=$(mktemp -d "${TMPDIR:-/tmp}/sonybridge-fuzz.XXXXXX") +trap 'rm -rf "$work_dir"' EXIT INT TERM + +binary="$work_dir/fuzz-command-serializer" +corpus="$work_dir/corpus" +artifacts="$work_dir/artifacts" +mkdir -p "$corpus" "$artifacts" + +# Empty input is a required parser boundary seed. +: > "$corpus/empty" +for seed in "$fuzz_dir"/seeds/*.hex; do + name=$(basename "$seed" .hex) + xxd -r -p "$seed" "$corpus/$name" +done + +clang++ -std=c++20 -g -O1 \ + -fsanitize=fuzzer,address,undefined \ + -fno-sanitize-recover=all -fno-omit-frame-pointer \ + -I"$client_dir" \ + "$fuzz_dir/FuzzCommandSerializer.cpp" \ + "$client_dir/ByteMagic.cpp" \ + "$client_dir/CommandSerializer.cpp" \ + -o "$binary" + +export ASAN_OPTIONS="abort_on_error=1:detect_leaks=1:symbolize=1" +export UBSAN_OPTIONS="halt_on_error=1:print_stacktrace=1" + +"$binary" \ + -max_total_time="${FUZZ_SECONDS:-60}" \ + -max_len="$MAX_BLUETOOTH_MESSAGE_SIZE" \ + -timeout=5 \ + -use_value_profile=1 \ + -print_final_stats=1 \ + -dict="$fuzz_dir/dictionaries/sony_protocol.dict" \ + -artifact_prefix="$artifacts/" \ + "$corpus" diff --git a/Client/fuzz/seeds/ack.hex b/Client/fuzz/seeds/ack.hex new file mode 100644 index 00000000..db9ee083 --- /dev/null +++ b/Client/fuzz/seeds/ack.hex @@ -0,0 +1 @@ +01010000000002 diff --git a/Client/fuzz/seeds/ambient_level1.hex b/Client/fuzz/seeds/ambient_level1.hex new file mode 100644 index 00000000..2149fc46 --- /dev/null +++ b/Client/fuzz/seeds/ambient_level1.hex @@ -0,0 +1 @@ +0c0000000008680211020001000193 diff --git a/Client/fuzz/seeds/dangling_escape.hex b/Client/fuzz/seeds/dangling_escape.hex new file mode 100644 index 00000000..8a06c661 --- /dev/null +++ b/Client/fuzz/seeds/dangling_escape.hex @@ -0,0 +1 @@ +3d diff --git a/Client/fuzz/seeds/declared_size_overflow.hex b/Client/fuzz/seeds/declared_size_overflow.hex new file mode 100644 index 00000000..9978e831 --- /dev/null +++ b/Client/fuzz/seeds/declared_size_overflow.hex @@ -0,0 +1 @@ +0c00ffffffff00 diff --git a/Client/fuzz/seeds/escape_triplet.hex b/Client/fuzz/seeds/escape_triplet.hex new file mode 100644 index 00000000..35c9202a --- /dev/null +++ b/Client/fuzz/seeds/escape_triplet.hex @@ -0,0 +1 @@ +0c00000000033d2c3d2d3d2ec6 diff --git a/Client/fuzz/seeds/init.hex b/Client/fuzz/seeds/init.hex new file mode 100644 index 00000000..b095c536 --- /dev/null +++ b/Client/fuzz/seeds/init.hex @@ -0,0 +1 @@ +0c000000000200000e diff --git a/Client/macos/ContentView.swift b/Client/macos/ContentView.swift index 45b0388a..87956c13 100644 --- a/Client/macos/ContentView.swift +++ b/Client/macos/ContentView.swift @@ -77,6 +77,8 @@ struct ContentView: View { } if model.supportsEqualizer { equalizerCard + } + if model.supportsDsee { dseeCard } if model.hasAdaptiveVolume || model.hasSpeakToChat || model.hasAutoPowerOff { diff --git a/Client/macos/HeadphonesBridge.h b/Client/macos/HeadphonesBridge.h index dfbdd039..d02c820b 100644 --- a/Client/macos/HeadphonesBridge.h +++ b/Client/macos/HeadphonesBridge.h @@ -23,7 +23,7 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { // Only meaningful while connected. @property (nonatomic, readonly) BOOL supportsVpt; // v1 protocol devices only -@property (nonatomic, readonly) NSInteger maxAmbientLevel; // 19 (v1) or 20 (v2) +@property (nonatomic, readonly) NSInteger maxAmbientLevel; // 1...20 on supported devices // Current on-device state, mirrored from the last successful command. @property (nonatomic, readonly) SHCAmbientMode mode; @@ -38,8 +38,9 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { @property (nonatomic, readonly) NSInteger batteryRight; @property (nonatomic, readonly) NSInteger batteryCase; @property (nonatomic, readonly) NSInteger eqPreset; // raw preset byte (EQ_PRESET) -@property (nonatomic, readonly) BOOL supportsEqualizer; // v2 devices only +@property (nonatomic, readonly) BOOL supportsEqualizer; // true after a successful read-only probe @property (nonatomic, readonly) NSInteger clearBass; // -10..10 +@property (nonatomic, readonly) BOOL supportsDsee; // true after a successful read-only probe @property (nonatomic, readonly) BOOL dsee; // DSEE / audio upsampling // Optional features (present only if the device answered the capability probe on connect). diff --git a/Client/macos/HeadphonesBridge.mm b/Client/macos/HeadphonesBridge.mm index 4f1b58d3..4f2bbc74 100644 --- a/Client/macos/HeadphonesBridge.mm +++ b/Client/macos/HeadphonesBridge.mm @@ -7,6 +7,7 @@ #import #import +#include #include #include "MacOSBluetoothConnector.h" #include "BluetoothWrapper.h" @@ -16,18 +17,21 @@ @implementation HeadphonesBridge { std::unique_ptr _bt; - std::unique_ptr _hp; + // Queued operations retain the current device state so disconnecting cannot invalidate a raw pointer + // while a Bluetooth read or write is still completing. + std::shared_ptr _hp; NSString *_deviceName; NSString *_deviceMac; - BOOL _initialized; - // All user-initiated commands run on this SERIAL queue so quick successive taps reach the device in - // order (a concurrent queue let them race and land out of order). + std::atomic_bool _initialized; + // All device I/O runs on this serial queue. Bluetooth commands are stateful, and serializing reads with + // writes also prevents a slow capability probe from racing a user action or dynamic refresh. dispatch_queue_t _cmdQueue; } - (instancetype)init { if ((self = [super init])) { _bt = std::make_unique(std::make_unique()); + _initialized = false; _cmdQueue = dispatch_queue_create("com.sonybridge.commands", DISPATCH_QUEUE_SERIAL); } return self; @@ -56,8 +60,7 @@ - (BOOL)supportsVpt { } - (NSInteger)maxAmbientLevel { - if (self.connected && _bt->getProtocolVersion() == SonyProtocolVersion::V2) return 20; - return 19; + return 20; } - (SHCAmbientMode)mode { @@ -96,7 +99,7 @@ - (NSInteger)eqPreset { } - (BOOL)supportsEqualizer { - return self.connected && _bt->getProtocolVersion() == SonyProtocolVersion::V2; + return _hp && _hp->hasEqualizer(); } - (NSInteger)clearBass { @@ -107,6 +110,10 @@ - (BOOL)dsee { return _hp ? _hp->getDsee() : NO; } +- (BOOL)supportsDsee { + return _hp && _hp->hasDsee(); +} + - (NSInteger)equalizerBandAtIndex:(NSInteger)index { return _hp ? _hp->getEqualizerBand((int)index) : 0; } @@ -180,7 +187,7 @@ - (void)scanAndConnectWithCompletion:(void (^)(BOOL, NSString * _Nullable))compl _deviceName = [device nameOrAddress]; _deviceMac = [device addressString]; - _hp = std::make_unique(*_bt); + _hp = std::make_shared(*_bt); completion(YES, nil); } @@ -189,36 +196,22 @@ - (void)disconnect { _hp.reset(); _deviceName = nil; _deviceMac = nil; - _initialized = NO; + _initialized = false; } - (void)refreshStatusWithCompletion:(void (^)(void))completion { if (!_hp || !self.connected) { completion(); return; } - Headphones *hp = _hp.get(); - // CRITICAL: the init/battery/EQ inquiries below use v2 opcodes. Opcode 0x22 is BATTERY_LEVEL_REQUEST - // on v2 but POWER_OFF on v1 - sending it to a v1 device (e.g. WH-1000XM4) powers the headphones off. - // A v1 device still needs *some* valid handshake traffic right after connect or it drops/powers off on - // its own, so read its ambient state (read-only 66 02) instead of sending nothing. - if (_bt->getProtocolVersion() != SonyProtocolVersion::V2) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - try { hp->requestAmbientState(); } catch (std::exception &exc) {} - dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); - }); - return; - } - // Reads run on the global queue (not the serial command queue) so they don't block quick user taps; - // per-call the connector mutex still serializes actual I/O. - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - // Fast, always-supported reads first, then update the UI immediately... - try { - if (!self->_initialized) { - hp->initDevice(); - self->_initialized = YES; - } - hp->requestBattery(); - hp->requestEqualizer(); - hp->requestDsee(); - } catch (std::exception &exc) {} + auto hp = _hp; + dispatch_async(_cmdQueue, ^{ + // Every method chooses its command family from the SDP-confirmed protocol version. This is + // essential for v1: 0x22 powers off an XM4 but requests battery state on v2. + if (!self->_initialized.load()) { + try { hp->initDevice(); self->_initialized = true; } catch (std::exception &exc) {} + } + try { hp->requestAmbientState(); } catch (std::exception &exc) {} + try { hp->requestBattery(); } catch (std::exception &exc) {} + try { hp->requestEqualizer(); } catch (std::exception &exc) {} + try { hp->requestDsee(); } catch (std::exception &exc) {} dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); // ...then the optional-feature probes, which can each take a couple seconds to time out on a @@ -230,8 +223,8 @@ - (void)refreshStatusWithCompletion:(void (^)(void))completion { - (void)refreshDynamicWithCompletion:(void (^)(void))completion { if (!_hp || !self.connected) { completion(); return; } - Headphones *hp = _hp.get(); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + auto hp = _hp; + dispatch_async(_cmdQueue, ^{ // The headphone's physical button only changes ambient/NC, so that's all we poll (keeps traffic low). // requestAmbientState() is protocol-aware (v2 uses 66 17, v1 uses 66 02), so this is safe on both. try { hp->requestAmbientState(); } catch (std::exception &exc) {} @@ -244,12 +237,11 @@ - (void)setEqualizerPreset:(NSInteger)preset completion:(void (^)(BOOL, NSString completion(NO, @"Not connected."); return; } - // The v2 EQ SET opcode differs from v1; only issue it on confirmed v2 devices. - if (_bt->getProtocolVersion() != SonyProtocolVersion::V2) { + if (!_hp->hasEqualizer()) { completion(NO, @"Equalizer control isn't supported on this device yet."); return; } - Headphones *hp = _hp.get(); + auto hp = _hp; dispatch_async(_cmdQueue, ^{ NSString *error = nil; BOOL ok = YES; @@ -266,14 +258,14 @@ - (void)setEqualizerPreset:(NSInteger)preset completion:(void (^)(BOOL, NSString } - (void)setCustomEqualizerBass:(NSInteger)bass bands:(NSArray *)bands completion:(void (^)(BOOL, NSString * _Nullable))completion { - if (!_hp || !self.connected || _bt->getProtocolVersion() != SonyProtocolVersion::V2) { + if (!_hp || !self.connected || !_hp->hasEqualizer()) { completion(NO, @"Equalizer control isn't supported on this device yet."); return; } std::vector cbands; for (NSNumber *n in bands) cbands.push_back((int)n.integerValue); int cbass = (int)bass; - Headphones *hp = _hp.get(); + auto hp = _hp; dispatch_async(_cmdQueue, ^{ NSString *error = nil; BOOL ok = YES; try { @@ -284,11 +276,11 @@ - (void)setCustomEqualizerBass:(NSInteger)bass bands:(NSArray *)band } - (void)setDsee:(BOOL)enabled completion:(void (^)(BOOL, NSString * _Nullable))completion { - if (!_hp || !self.connected || _bt->getProtocolVersion() != SonyProtocolVersion::V2) { + if (!_hp || !self.connected || !_hp->hasDsee()) { completion(NO, @"Not supported on this device."); return; } - Headphones *hp = _hp.get(); + auto hp = _hp; dispatch_async(_cmdQueue, ^{ NSString *error = nil; BOOL ok = YES; try { @@ -307,27 +299,26 @@ - (void)applyMode:(SHCAmbientMode)mode return; } - switch (mode) { - case SHCAmbientModeOff: - _hp->setAmbientSoundControl(false); - break; - case SHCAmbientModeNoiseCanceling: - _hp->setAmbientSoundControl(true); - _hp->setAsmLevel(0); - _hp->setFocusOnVoice(false); - break; - case SHCAmbientModeAmbientSound: - _hp->setAmbientSoundControl(true); - _hp->setAsmLevel((int)MAX(level, 1)); - _hp->setFocusOnVoice(focusVoice); - break; - } - - Headphones *hp = _hp.get(); + auto hp = _hp; dispatch_async(_cmdQueue, ^{ NSString *error = nil; BOOL ok = YES; try { + switch (mode) { + case SHCAmbientModeOff: + hp->setAmbientSoundControl(false); + break; + case SHCAmbientModeNoiseCanceling: + hp->setAmbientSoundControl(true); + hp->setAsmLevel(0); + hp->setFocusOnVoice(false); + break; + case SHCAmbientModeAmbientSound: + hp->setAmbientSoundControl(true); + hp->setAsmLevel((int)MAX(level, 1)); + hp->setFocusOnVoice(focusVoice); + break; + } if (hp->isChanged()) hp->setChanges(); } catch (RecoverableException &exc) { ok = NO; @@ -344,7 +335,7 @@ - (void)applyMode:(SHCAmbientMode)mode - (void)setAutoPowerOff:(NSInteger)index completion:(void (^)(BOOL, NSString * _Nullable))completion { if (!_hp || !self.connected) { completion(NO, @"Not connected."); return; } - Headphones *hp = _hp.get(); + auto hp = _hp; dispatch_async(_cmdQueue, ^{ NSString *error = nil; BOOL ok = YES; try { hp->setAutoPowerOff((int)index); } catch (std::exception &exc) { ok = NO; error = @(exc.what()); } @@ -354,7 +345,7 @@ - (void)setAutoPowerOff:(NSInteger)index completion:(void (^)(BOOL, NSString * _ - (void)setSpeakToChat:(BOOL)enabled completion:(void (^)(BOOL, NSString * _Nullable))completion { if (!_hp || !self.connected) { completion(NO, @"Not connected."); return; } - Headphones *hp = _hp.get(); + auto hp = _hp; dispatch_async(_cmdQueue, ^{ NSString *error = nil; BOOL ok = YES; try { hp->setSpeakToChat(enabled); } catch (std::exception &exc) { ok = NO; error = @(exc.what()); } @@ -364,7 +355,7 @@ - (void)setSpeakToChat:(BOOL)enabled completion:(void (^)(BOOL, NSString * _Null - (void)setAdaptiveVolume:(BOOL)enabled completion:(void (^)(BOOL, NSString * _Nullable))completion { if (!_hp || !self.connected) { completion(NO, @"Not connected."); return; } - Headphones *hp = _hp.get(); + auto hp = _hp; dispatch_async(_cmdQueue, ^{ NSString *error = nil; BOOL ok = YES; try { hp->setAdaptiveVolume(enabled); } catch (std::exception &exc) { ok = NO; error = @(exc.what()); } diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index cda475ad..414053bb 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -30,6 +30,7 @@ final class HeadphonesModel: ObservableObject { @Published var supportsEqualizer = false @Published var eqBands = [0, 0, 0, 0, 0] @Published var clearBass = 0 + @Published var supportsDsee = false @Published var dsee = false @Published var hasAutoPowerOff = false @@ -76,7 +77,9 @@ final class HeadphonesModel: ObservableObject { self.batteryRight = self.bridge.batteryRight self.batteryCase = self.bridge.batteryCase self.eqPreset = self.bridge.eqPreset + self.supportsEqualizer = self.bridge.supportsEqualizer self.clearBass = self.bridge.clearBass + self.supportsDsee = self.bridge.supportsDsee self.dsee = self.bridge.dsee self.eqBands = (0..<5).map { self.bridge.equalizerBand(at: $0) } self.hasAutoPowerOff = self.bridge.hasAutoPowerOff @@ -118,7 +121,9 @@ final class HeadphonesModel: ObservableObject { let level = self.bridge.ambientLevel if level > 0 { self.ambientLevel = level } self.eqPreset = self.bridge.eqPreset + self.supportsEqualizer = self.bridge.supportsEqualizer self.clearBass = self.bridge.clearBass + self.supportsDsee = self.bridge.supportsDsee self.dsee = self.bridge.dsee self.eqBands = (0..<5).map { self.bridge.equalizerBand(at: $0) } } @@ -131,6 +136,10 @@ final class HeadphonesModel: ObservableObject { } func setEqualizer(_ preset: Int) { + if preset == 0xA0 { + applyCustomEq() + return + } eqPreset = preset errorMessage = nil bridge.setEqualizerPreset(preset) { ok, error in @@ -217,6 +226,7 @@ final class HeadphonesModel: ObservableObject { protocolVersion = bridge.protocolVersionString ?? "" supportsVpt = bridge.supportsVpt supportsEqualizer = bridge.supportsEqualizer + supportsDsee = bridge.supportsDsee maxAmbientLevel = bridge.maxAmbientLevel mode = bridge.mode let level = bridge.ambientLevel diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h index 186b06a4..3e3f42ad 100644 --- a/Client/macos/MacOSBluetoothConnector.h +++ b/Client/macos/MacOSBluetoothConnector.h @@ -24,6 +24,10 @@ class MacOSBluetoothConnector final : public IBluetoothConnector virtual void closeConnection(); virtual SonyProtocolVersion getProtocolVersion() noexcept; + // Called by the Objective-C RFCOMM delegate when the peer closes the channel. This callback runs + // on the connector thread, so it must only signal shutdown; joining that same thread would abort. + void handleChannelClosed() noexcept; + virtual std::vector getConnectedDevices() noexcept(false); std::deque> receivedBytes; std::mutex receiveDataMutex; @@ -36,7 +40,7 @@ class MacOSBluetoothConnector final : public IBluetoothConnector SonyProtocolVersion protocolVersion = SonyProtocolVersion::V1; private: - void *rfcommDevice; - void *rfcommchannel; + void *rfcommDevice = nullptr; + std::atomic rfcommchannel{nullptr}; std::thread uthread; }; diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index bd2db624..4327f978 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -6,10 +6,9 @@ } MacOSBluetoothConnector::~MacOSBluetoothConnector() { - // onclose event - if (isConnected()){ - disconnect(); - } + // A failed or remotely closed connection can leave a finished-but-joinable std::thread even when + // isConnected() is false. Always perform the idempotent cleanup before the thread is destroyed. + disconnect(); } @interface AsyncCommDelegate : NSObject { @@ -24,7 +23,7 @@ - (void)rfcommChannelClosed:(IOBluetoothRFCOMMChannel *)rfcommChannel{ #ifdef SHC_DEBUG_PROTOCOL fprintf(stderr, "[connect] rfcommChannelClosed\n"); #endif - delegateCPP->disconnect(); + delegateCPP->handleChannelClosed(); } #ifdef SHC_DEBUG_PROTOCOL @@ -64,7 +63,9 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) #ifdef SHC_DEBUG_PROTOCOL _debugHexDump("send", buf, length); #endif - [(__bridge IOBluetoothRFCOMMChannel*)rfcommchannel writeSync:(void*)buf length:length]; + IOBluetoothRFCOMMChannel *channel = (__bridge IOBluetoothRFCOMMChannel*)rfcommchannel.load(); + if (channel == nil) throw RecoverableException("Bluetooth connection is closed", false); + [channel writeSync:(void*)buf length:length]; return (int)length; } @@ -116,22 +117,22 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) AsyncCommDelegate* asyncCommDelegate = [[AsyncCommDelegate alloc] init]; asyncCommDelegate->delegateCPP = macOSBluetoothConnector; // try to open channel + macOSBluetoothConnector->running = true; IOReturn openResult = [device openRFCOMMChannelAsync:&channel withChannelID:rfcommChannelID delegate:asyncCommDelegate]; #ifdef SHC_DEBUG_PROTOCOL fprintf(stderr, "[connect] openRFCOMMChannelAsync -> 0x%x\n", openResult); #endif if ( openResult != kIOReturnSuccess ) { + macOSBluetoothConnector->running = false; RecoverableException exc = RecoverableException("Could not open the rfcomm.", false); std::exception_ptr excPtr = std::make_exception_ptr(exc); connectPromise.set_exception(excPtr); return; } // store the channel - macOSBluetoothConnector->rfcommchannel = (__bridge void*) channel; + macOSBluetoothConnector->rfcommchannel.store((__bridge void*) channel); macOSBluetoothConnector->protocolVersion = protocolVersion; - macOSBluetoothConnector->running = true; - // tell the other tread that we are done connecting connectPromise.set_value(); @@ -148,6 +149,10 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) lk.unlock(); } void MacOSBluetoothConnector::connect(const std::string& addrStr){ + // Reconnects must reap the previous worker first. Assigning over a joinable std::thread terminates. + if (uthread.joinable()) { + disconnect(); + } // convert mac address to nsstring NSString *addressNSString = [NSString stringWithCString:addrStr.c_str() encoding:[NSString defaultCStringEncoding]]; // get device based on mac address @@ -163,8 +168,17 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) rfcommDevice = (__bridge void*) device; uthread = std::thread(MacOSBluetoothConnector::connectToMac, this, std::move(connectPromise)); - // wait till the device is connected - connectFuture.get(); + // Wait until SDP lookup and the asynchronous open request have started. If setup fails, reap the + // worker before propagating the exception so destruction cannot encounter a joinable thread. + try { + connectFuture.get(); + } catch (...) { + running = false; + disconnectionConditionVariable.notify_all(); + receiveDataConditionVariable.notify_all(); + if (uthread.joinable()) uthread.join(); + throw; + } } int MacOSBluetoothConnector::recv(char* buf, size_t length) @@ -173,8 +187,11 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) // feature) or a dropped link doesn't block the caller forever. std::unique_lock g(receiveDataMutex); bool gotData = receiveDataConditionVariable.wait_for(g, std::chrono::milliseconds(2500), - [this]{ return !receivedBytes.empty(); }); - if (!gotData) { + [this]{ return !receivedBytes.empty() || !running; }); + if (!running && receivedBytes.empty()) { + throw RecoverableException("Bluetooth connection closed", false); + } + if (!gotData || receivedBytes.empty()) { throw RecoverableException("recv timed out", false); } @@ -225,27 +242,46 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) void MacOSBluetoothConnector::disconnect() noexcept { - // close connection - closeConnection(); running = false; - // notify the other thread that we are done disconnecting disconnectionConditionVariable.notify_all(); - // wait for the thread to finish - uthread.join(); + receiveDataConditionVariable.notify_all(); + closeConnection(); + + if (uthread.joinable()) { + // The delegate only calls handleChannelClosed(), but retain this guard so future callbacks cannot + // accidentally reintroduce a self-join termination. + if (uthread.get_id() == std::this_thread::get_id()) { + uthread.detach(); + } else { + uthread.join(); + } + } + + std::lock_guard g(receiveDataMutex); + receivedBytes.clear(); } void MacOSBluetoothConnector::closeConnection() { - // get the channel - IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; + // Only one close path owns the channel pointer. A remote-close callback clears it first. + IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*)rfcommchannel.exchange(nullptr); + if (chan == nil) return; [chan setDelegate: nil]; // close the channel [chan closeChannel]; } +void MacOSBluetoothConnector::handleChannelClosed() noexcept +{ + rfcommchannel.store(nullptr); + running = false; + disconnectionConditionVariable.notify_all(); + receiveDataConditionVariable.notify_all(); +} + bool MacOSBluetoothConnector::isConnected() noexcept { if (!running) return false; - IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; - return chan.isOpen; + IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*)rfcommchannel.load(); + return chan != nil && chan.isOpen; } diff --git a/Client/tests/HeadphonesProtocolTests.cpp b/Client/tests/HeadphonesProtocolTests.cpp new file mode 100644 index 00000000..671e089a --- /dev/null +++ b/Client/tests/HeadphonesProtocolTests.cpp @@ -0,0 +1,180 @@ +#include "BluetoothWrapper.h" +#include "CommandSerializer.h" +#include "Headphones.h" + +#include +#include +#include +#include +#include +#include + +namespace +{ +class FakeV1Connector final : public IBluetoothConnector +{ +public: + int send(char* buf, size_t length) override + { + Buffer frame(buf, buf + length); + if (frame.size() < 2 || frame.front() != START_MARKER || frame.back() != END_MARKER) + throw std::runtime_error("invalid outbound frame"); + + Buffer body(frame.begin() + 1, frame.end() - 1); + auto message = CommandSerializer::unpackBtMessage(body); + if (message.dataType != DATA_TYPE::DATA_MDR) return static_cast(length); + + sentPayloads.push_back(message.payload); + if (notificationBeforeNextAck) { + queue({ (char)V1Command::AMBIENT_RET, 0x02, 0x11, 0x02, 0x02, 0x01, 0x00, 0x00 }, DATA_TYPE::DATA_MDR, 0); + notificationBeforeNextAck = false; + } + queue({}, DATA_TYPE::ACK, 1 - message.seqNumber); + queueResponse(message.payload); + return static_cast(length); + } + + int recv(char* buf, size_t length) override + { + if (incoming.empty()) throw std::runtime_error("fake connector has no queued response"); + auto frame = std::move(incoming.front()); + incoming.pop_front(); + if (!recvPrefix.empty()) { + frame.insert(frame.begin(), recvPrefix.begin(), recvPrefix.end()); + recvPrefix.clear(); + } + if (frame.size() > length) throw std::runtime_error("fake response exceeds receive buffer"); + std::memcpy(buf, frame.data(), frame.size()); + return static_cast(frame.size()); + } + + void connect(const std::string&) override { connected = true; } + void disconnect() noexcept override { connected = false; } + bool isConnected() noexcept override { return connected; } + std::vector getConnectedDevices() override { return {}; } + SonyProtocolVersion getProtocolVersion() noexcept override { return SonyProtocolVersion::V1; } + + std::vector sentPayloads; + Buffer recvPrefix; + bool notificationBeforeNextAck = false; + +private: + void queue(const Buffer& payload, DATA_TYPE type, unsigned char sequence) + { + incoming.push_back(CommandSerializer::packageDataForBt(payload, type, sequence)); + } + + void queueResponse(const Buffer& request) + { + if (request.empty()) return; + Buffer response; + switch ((unsigned char)request[0]) + { + case V1Command::INIT_REQUEST: response = { (char)V1Command::INIT_REPLY, 0x00, 0x40, 0x10 }; break; + case V1Command::FW_GET: response = { (char)V1Command::FW_RET, 0x02, 0x05, '3', '.', '0', '.', '1' }; break; + case V1Command::BATTERY_GET: response = { (char)V1Command::BATTERY_RET, 0x00, 87, 0x00 }; break; + case V1Command::CODEC_GET: response = { (char)V1Command::CODEC_RET, 0x00, 0x10 }; break; + case V1Command::EQ_GET: response = { (char)V1Command::EQ_RET, 0x01, 0x10, 0x06, 10, 10, 10, 10, 10, 10 }; break; + case V1Command::DSEE_GET: response = { (char)V1Command::DSEE_RET, 0x02, 0x00, 0x01 }; break; + case V1Command::AMBIENT_GET: response = { (char)V1Command::AMBIENT_RET, 0x02, 0x11, 0x02, 0x02, 0x01, 0x00, 0x00 }; break; + case V1Command::BTNMODE_GET: + if (request.size() >= 2 && (unsigned char)request[1] == V1Command::SUB_AUTO_POWER_OFF) + response = { (char)V1Command::BTNMODE_RET, (char)V1Command::SUB_AUTO_POWER_OFF, 0x01, 0x01, 0x01 }; + else if (request.size() >= 2 && (unsigned char)request[1] == V1Command::SUB_SPEAK_TO_CHAT) + response = { (char)V1Command::BTNMODE_RET, (char)V1Command::SUB_SPEAK_TO_CHAT, 0x01, 0x01 }; + break; + default: return; // SET commands only need the ACK already queued above. + } + if (!response.empty()) queue(response, DATA_TYPE::DATA_MDR, 0); + } + + bool connected = true; + std::deque incoming; +}; + +void require(bool condition, const char* message) +{ + if (!condition) throw std::runtime_error(message); +} +} + +int main() +{ + auto fake = std::make_unique(); + auto* observed = fake.get(); + BluetoothWrapper bluetooth(std::move(fake)); + Headphones headphones(bluetooth); + + // RFCOMM stacks may deliver harmless transport noise before a start marker. It must not become part + // of the checksum-protected Sony frame. + observed->recvPrefix = { 0x00, 0x7f }; + headphones.initDevice(); + headphones.requestAmbientState(); + headphones.requestBattery(); + headphones.requestEqualizer(); + headphones.requestDsee(); + headphones.probeCapabilities(); + + require(headphones.hasBattery(), "v1 battery capability was not recorded"); + require(headphones.getBatteryLevel() == 87, "v1 battery response was not parsed"); + require(headphones.hasEqualizer(), "v1 equalizer capability was not recorded"); + require(headphones.getEqualizerPreset() == EQ_PRESET::BRIGHT, "v1 equalizer response was not parsed"); + require(headphones.hasDsee() && headphones.getDsee(), "v1 DSEE response was not parsed"); + require(headphones.getAmbientSoundControl(), "v1 ANC response was not parsed"); + require(headphones.getAsmLevel() == 0, "v1 ANC response was mistaken for ambient sound"); + require(headphones.hasFirmware() && headphones.getFirmware() == "3.0.1", "v1 firmware response was not parsed"); + require(headphones.hasCodec() && headphones.getCodec() == "LDAC", "v1 codec response was not parsed"); + require(headphones.hasAutoPowerOff() && headphones.getAutoPowerOff() == 2, "v1 auto-power-off response was not parsed"); + require(headphones.hasSpeakToChat() && headphones.getSpeakToChat(), "v1 Speak-to-Chat response was not parsed"); + + const auto hasV1BatteryRequest = std::any_of(observed->sentPayloads.begin(), observed->sentPayloads.end(), [](const Buffer& payload) { + return payload.size() >= 2 && (unsigned char)payload[0] == V1Command::BATTERY_GET && payload[1] == 0x00; + }); + const auto hasDangerousV2BatteryRequest = std::any_of(observed->sentPayloads.begin(), observed->sentPayloads.end(), [](const Buffer& payload) { + return !payload.empty() && (unsigned char)payload[0] == V2Command::BATTERY_GET; + }); + require(hasV1BatteryRequest, "XM4 path did not issue the v1 battery inquiry"); + require(!hasDangerousV2BatteryRequest, "XM4 path emitted v2 battery / v1 power-off opcode 0x22"); + + headphones.setAmbientSoundControl(true); + headphones.setAsmLevel(20); + headphones.setFocusOnVoice(false); + headphones.setChanges(); + const auto hasLevel20 = std::any_of(observed->sentPayloads.begin(), observed->sentPayloads.end(), [](const Buffer& payload) { + return payload.size() == 8 && (unsigned char)payload[0] == V1Command::AMBIENT_SET && + (unsigned char)payload[7] == 20; + }); + require(hasLevel20, + "XM4 ambient level 20 was not serialized correctly"); + + headphones.setAsmLevel(1); + headphones.setChanges(); + const auto& ambientLevelOne = observed->sentPayloads.back(); + require(ambientLevelOne.size() == 8 && (unsigned char)ambientLevelOne[4] == 0x00 && + (unsigned char)ambientLevelOne[7] == 0x01, + "XM4 ambient level 1 was mistaken for wind/noise cancellation"); + + headphones.setEqualizerCustom(3, { -2, -1, 0, 1, 2 }); + require(!observed->sentPayloads.empty(), "custom EQ command was not sent"); + const auto& customEq = observed->sentPayloads.back(); + require(customEq.size() == 10 && (unsigned char)customEq[0] == V1Command::EQ_SET, + "custom EQ did not use the v1 command"); + require((unsigned char)customEq[1] == 0x01 && (unsigned char)customEq[2] == V1Command::MANUAL_EQ, + "custom EQ did not use the v1 subtype and manual preset byte"); + + observed->notificationBeforeNextAck = true; + headphones.setDsee(false); + const auto& dsee = observed->sentPayloads.back(); + require(dsee.size() == 4 && (unsigned char)dsee[0] == V1Command::DSEE_SET && + (unsigned char)dsee[1] == 0x02 && (unsigned char)dsee[3] == 0x00, + "DSEE did not use the v1 command layout"); + + headphones.setSpeakToChat(false); + const auto& speakToChat = observed->sentPayloads.back(); + require(speakToChat.size() == 4 && (unsigned char)speakToChat[0] == V1Command::BTNMODE_SET && + (unsigned char)speakToChat[1] == V1Command::SUB_SPEAK_TO_CHAT && (unsigned char)speakToChat[3] == 0x00, + "Speak-to-Chat did not use the v1 command layout"); + + std::cout << "WH-1000XM4 protocol safety tests passed\n"; + return 0; +} diff --git a/Client/tests/ProtocolConformanceTests.cpp b/Client/tests/ProtocolConformanceTests.cpp new file mode 100644 index 00000000..fe1c82dc --- /dev/null +++ b/Client/tests/ProtocolConformanceTests.cpp @@ -0,0 +1,151 @@ +#include "CommandSerializer.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ +struct Fixture +{ + std::string name; + unsigned int dataType; + unsigned int sequence; + Buffer payload; + Buffer frame; +}; + +Buffer parseHex(const std::string& text) +{ + Buffer bytes; + std::istringstream input(text); + unsigned int value; + while (input >> std::hex >> value) + { + if (value > 0xff) throw std::runtime_error("fixture contains a non-byte value"); + bytes.push_back(static_cast(value)); + } + if (!input.eof()) throw std::runtime_error("fixture contains invalid hex"); + return bytes; +} + +std::string toHex(const Buffer& bytes) +{ + std::ostringstream output; + for (size_t i = 0; i < bytes.size(); i++) + { + if (i != 0) output << ' '; + output << std::hex << std::setw(2) << std::setfill('0') + << static_cast(static_cast(bytes[i])); + } + return output.str(); +} + +std::vector loadFixtures(const std::string& path) +{ + std::ifstream input(path); + if (!input) throw std::runtime_error("could not open golden fixture: " + path); + + std::vector fixtures; + std::string line; + while (std::getline(input, line)) + { + if (line.empty() || line[0] == '#') continue; + std::istringstream row(line); + std::string name, type, sequence, payload, frame; + if (!std::getline(row, name, '|') || !std::getline(row, type, '|') || + !std::getline(row, sequence, '|') || !std::getline(row, payload, '|') || + !std::getline(row, frame)) + throw std::runtime_error("invalid fixture row: " + line); + fixtures.push_back({ name, static_cast(std::stoul(type, nullptr, 16)), + static_cast(std::stoul(sequence)), parseHex(payload), parseHex(frame) }); + } + return fixtures; +} + +std::string renderFixtures(const std::vector& fixtures, const std::vector& frames) +{ + std::ostringstream output; + output << "# id|data_type|sequence|payload|complete_frame\n"; + for (size_t i = 0; i < fixtures.size(); i++) + { + output << fixtures[i].name << '|' << std::hex << std::setw(2) << std::setfill('0') + << fixtures[i].dataType << '|' << std::dec << fixtures[i].sequence << '|' + << toHex(fixtures[i].payload) << '|' << toHex(frames[i]) << '\n'; + } + return output.str(); +} + +void require(bool condition, const std::string& message) +{ + if (!condition) throw std::runtime_error(message); +} + +template +void requireReject(Func operation, const char* name) +{ + try { operation(); } + catch (const std::exception&) { return; } + throw std::runtime_error(std::string("malformed frame was accepted: ") + name); +} +} + +int main(int argc, char** argv) +{ + if (argc != 2) throw std::runtime_error("usage: protocol-conformance-tests "); + const std::string fixturePath = argv[1]; + auto fixtures = loadFixtures(fixturePath); + require(!fixtures.empty(), "golden fixture has no cases"); + + std::vector actualFrames; + bool mismatch = false; + for (const auto& fixture : fixtures) + { + auto actual = CommandSerializer::packageDataForBt(fixture.payload, + static_cast(fixture.dataType), fixture.sequence); + actualFrames.push_back(actual); + if (actual != fixture.frame) + { + mismatch = true; + std::cerr << fixture.name << " golden mismatch\nexpected: " << toHex(fixture.frame) + << "\nactual: " << toHex(actual) << '\n'; + } + + require(actual.front() == START_MARKER && actual.back() == END_MARKER, + fixture.name + " is not framed"); + Buffer body(actual.begin() + 1, actual.end() - 1); + auto decoded = CommandSerializer::unpackBtMessage(body); + require(static_cast(decoded.dataType) == fixture.dataType, + fixture.name + " data type did not round-trip"); + require(decoded.seqNumber == fixture.sequence, fixture.name + " sequence did not round-trip"); + require(decoded.payload == fixture.payload, fixture.name + " payload did not round-trip"); + } + + if (const char* update = std::getenv("UPDATE_GOLDENS"); update && std::string(update) == "1") + { + std::ofstream output(fixturePath, std::ios::trunc); + output << renderFixtures(fixtures, actualFrames); + std::cout << "Updated golden fixture; review the diff before accepting it.\n"; + mismatch = false; + } + else if (mismatch) + { + std::ofstream actual(fixturePath + ".actual", std::ios::trunc); + actual << renderFixtures(fixtures, actualFrames); + throw std::runtime_error("golden mismatch; inspect the .actual file"); + } + + requireReject([] { CommandSerializer::unpackBtMessage({}); }, "empty"); + requireReject([] { CommandSerializer::unpackBtMessage({ 0x3d }); }, "dangling escape"); + requireReject([] { CommandSerializer::unpackBtMessage({ 0x0c, 0, 0, 0, 0, 2, 0, 0 }); }, "missing checksum"); + requireReject([] { CommandSerializer::unpackBtMessage({ 0x0c, 0, 0, 0, 0, 0, 0x0c, 0 }); }, "trailing data"); + requireReject([] { CommandSerializer::unpackBtMessage({ 0x0c, 0, 0, 0, 0, 0, 0x00 }); }, "bad checksum"); + + std::cout << fixtures.size() << " Sony protocol golden cases passed\n"; + return 0; +} diff --git a/Client/tests/conformance/COVERAGE.md b/Client/tests/conformance/COVERAGE.md new file mode 100644 index 00000000..fec93d68 --- /dev/null +++ b/Client/tests/conformance/COVERAGE.md @@ -0,0 +1,14 @@ +# XM4 v1 conformance coverage + +The target contract is the Sony MDR v1 community specification at the revisions pinned in `PROVENANCE.md`. “MUST” here means required for SonyBridge's supported XM4 feature set, not a claim about Sony's unpublished full protocol. + +| Section | MUST | SHOULD | Tested | Passing | Divergent | Score | +|---|---:|---:|---:|---:|---:|---:| +| Framing, escaping, length, checksum, round-trip | 8 | 0 | 8 | 8 | 0 | 100% | +| Safe protocol routing and inquiry payloads | 9 | 0 | 9 | 9 | 0 | 100% | +| Ambient/NC mode and levels 1/20 | 4 | 0 | 4 | 4 | 0 | 100% | +| EQ preset and persistent custom EQ | 3 | 0 | 3 | 3 | 0 | 100% | +| DSEE and Speak-to-Chat mutations | 2 | 0 | 2 | 2 | 0 | 100% | +| Malformed-frame rejection | 5 | 0 | 5 | 5 | 0 | 100% | + +Hardware behavior is deliberately excluded from this file's score. It has a separate live-device verification gate because the public specification is reverse-engineered and Sony firmware can differ. diff --git a/Client/tests/conformance/DISCREPANCIES.md b/Client/tests/conformance/DISCREPANCIES.md new file mode 100644 index 00000000..9ea6ca18 --- /dev/null +++ b/Client/tests/conformance/DISCREPANCIES.md @@ -0,0 +1,5 @@ +# Known conformance divergences + +There are currently no intentional divergences from the pinned XM4 v1 reference for the supported command set. + +Unknown or unimplemented Sony features are out of scope rather than silently skipped. Any future intentional difference must receive a `DISC-NNN` entry with its status, impact, affected tests, and review date. diff --git a/Client/tests/conformance/PROVENANCE.md b/Client/tests/conformance/PROVENANCE.md new file mode 100644 index 00000000..041f242b --- /dev/null +++ b/Client/tests/conformance/PROVENANCE.md @@ -0,0 +1,10 @@ +# Fixture provenance + +The XM4 v1 payloads are cross-checked against two independently maintained community references: + +- Gadgetbridge `27ed00aa4232eaa360172b78b35d2fb168c190f0`: `PayloadTypeV1.java` and `SonyProtocolImplV1.java`. This is the primary source for command IDs, subtypes, and payload layouts, including DSEE, auto power-off, EQ, ambient sound, battery, firmware, codec, and Speak-to-Chat. +- `tanat/sony-connect-osx` `1a68e3bee54778c2db92db6379fa24662537b1db`: `SonyPacket.swift` and `HeadphonesController.swift`. This is an XM4-specific independent source for frame escaping, checksum rules, strict frame length, and the core XM4 commands. + +The exact frames were generated on 2026-08-24 with Ruby 3.4 from `generate_reference_goldens.rb`. That script is a clean-room transcription of the documented wire rules and pinned payload facts. Regenerate to a temporary file, diff every byte against `fixtures/xm4_v1_frames.golden`, and update this file when either reference revision changes. + +The fixture is deterministic and platform-independent. It uses exact byte comparison; no scrubbing or tolerance is appropriate. diff --git a/Client/tests/conformance/fixtures/xm4_v1_frames.golden b/Client/tests/conformance/fixtures/xm4_v1_frames.golden new file mode 100644 index 00000000..5791e1a1 --- /dev/null +++ b/Client/tests/conformance/fixtures/xm4_v1_frames.golden @@ -0,0 +1,19 @@ +# id|data_type|sequence|payload|complete_frame +ack_seq1|01|1||3e 01 01 00 00 00 00 02 3c +escape_triplet|0c|0|3c 3d 3e|3e 0c 00 00 00 00 03 3d 2c 3d 2d 3d 2e c6 3c +init|0c|0|00 00|3e 0c 00 00 00 00 02 00 00 0e 3c +firmware_get|0c|0|04 02|3e 0c 00 00 00 00 02 04 02 14 3c +battery_get|0c|0|10 00|3e 0c 00 00 00 00 02 10 00 1e 3c +codec_get|0c|0|18 00|3e 0c 00 00 00 00 02 18 00 26 3c +eq_get|0c|0|56 01|3e 0c 00 00 00 00 02 56 01 65 3c +eq_preset_bright|0c|0|58 01 10 00|3e 0c 00 00 00 00 04 58 01 10 00 79 3c +eq_custom|0c|0|58 01 ff 06 0d 08 09 0a 0b 0c|3e 0c 00 00 00 00 0a 58 01 ff 06 0d 08 09 0a 0b 0c b3 3c +ambient_get|0c|0|66 02|3e 0c 00 00 00 00 02 66 02 76 3c +ambient_level1|0c|0|68 02 11 02 00 01 00 01|3e 0c 00 00 00 00 08 68 02 11 02 00 01 00 01 93 3c +ambient_level20|0c|0|68 02 11 02 00 01 00 14|3e 0c 00 00 00 00 08 68 02 11 02 00 01 00 14 a6 3c +noise_cancel|0c|0|68 02 11 02 02 01 00 00|3e 0c 00 00 00 00 08 68 02 11 02 02 01 00 00 94 3c +dsee_get|0c|0|e6 02|3e 0c 00 00 00 00 02 e6 02 f6 3c +dsee_off|0c|0|e8 02 00 00|3e 0c 00 00 00 00 04 e8 02 00 00 fa 3c +auto_power_get|0c|0|f6 04|3e 0c 00 00 00 00 02 f6 04 08 3c +speak_get|0c|0|f6 05|3e 0c 00 00 00 00 02 f6 05 09 3c +speak_off|0c|0|f8 05 01 00|3e 0c 00 00 00 00 04 f8 05 01 00 0e 3c diff --git a/Client/tests/conformance/generate_reference_goldens.rb b/Client/tests/conformance/generate_reference_goldens.rb new file mode 100644 index 00000000..169ffd57 --- /dev/null +++ b/Client/tests/conformance/generate_reference_goldens.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +# Clean-room generator for the deterministic frame facts documented in PROVENANCE.md. +def frame(data_type, sequence, payload) + body = [data_type, sequence, 0, 0, 0, payload.length] + payload + body << body.sum.modulo(256) + escaped = body.flat_map { |byte| [0x3c, 0x3d, 0x3e].include?(byte) ? [0x3d, byte & 0xef] : [byte] } + [0x3e] + escaped + [0x3c] +end + +cases = { + ack_seq1: [0x01, 1, []], escape_triplet: [0x0c, 0, [0x3c, 0x3d, 0x3e]], + init: [0x0c, 0, [0x00, 0x00]], firmware_get: [0x0c, 0, [0x04, 0x02]], + battery_get: [0x0c, 0, [0x10, 0x00]], codec_get: [0x0c, 0, [0x18, 0x00]], + eq_get: [0x0c, 0, [0x56, 0x01]], eq_preset_bright: [0x0c, 0, [0x58, 0x01, 0x10, 0x00]], + eq_custom: [0x0c, 0, [0x58, 0x01, 0xff, 0x06, 13, 8, 9, 10, 11, 12]], + ambient_get: [0x0c, 0, [0x66, 0x02]], ambient_level1: [0x0c, 0, [0x68, 0x02, 0x11, 0x02, 0, 1, 0, 1]], + ambient_level20: [0x0c, 0, [0x68, 0x02, 0x11, 0x02, 0, 1, 0, 20]], + noise_cancel: [0x0c, 0, [0x68, 0x02, 0x11, 0x02, 2, 1, 0, 0]], + dsee_get: [0x0c, 0, [0xe6, 0x02]], dsee_off: [0x0c, 0, [0xe8, 0x02, 0, 0]], + auto_power_get: [0x0c, 0, [0xf6, 0x04]], speak_get: [0x0c, 0, [0xf6, 0x05]], + speak_off: [0x0c, 0, [0xf8, 0x05, 1, 0]] +} + +puts '# id|data_type|sequence|payload|complete_frame' +cases.each do |name, (data_type, sequence, payload)| + hex = ->(bytes) { bytes.map { |byte| format('%02x', byte) }.join(' ') } + puts [name, format('%02x', data_type), sequence, hex.call(payload), hex.call(frame(data_type, sequence, payload))].join('|') +end diff --git a/Client/tests/run-macos.sh b/Client/tests/run-macos.sh new file mode 100755 index 00000000..70705689 --- /dev/null +++ b/Client/tests/run-macos.sh @@ -0,0 +1,24 @@ +#!/bin/sh +set -eu + +client_dir=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd) +test_binary="${TMPDIR:-/tmp}/sonybridge-xm4-protocol-tests" +conformance_binary="${TMPDIR:-/tmp}/sonybridge-protocol-conformance-tests" + +clang++ -std=c++20 -pthread -I"$client_dir" \ + "$client_dir/tests/HeadphonesProtocolTests.cpp" \ + "$client_dir/BluetoothWrapper.cpp" \ + "$client_dir/ByteMagic.cpp" \ + "$client_dir/CommandSerializer.cpp" \ + "$client_dir/Headphones.cpp" \ + -o "$test_binary" + +"$test_binary" + +clang++ -std=c++20 -Wall -Wextra -Werror -I"$client_dir" \ + "$client_dir/tests/ProtocolConformanceTests.cpp" \ + "$client_dir/ByteMagic.cpp" \ + "$client_dir/CommandSerializer.cpp" \ + -o "$conformance_binary" + +"$conformance_binary" "$client_dir/tests/conformance/fixtures/xm4_v1_frames.golden" diff --git a/docs/QUALITY_AUDIT.md b/docs/QUALITY_AUDIT.md new file mode 100644 index 00000000..7db63456 --- /dev/null +++ b/docs/QUALITY_AUDIT.md @@ -0,0 +1,35 @@ +# Quality audit + +This log records the four-pass hardening work performed for first-class WH-1000XM4 support. + +## Pass 1: surface scan + +- Baseline protocol tests and a strict C++20 build passed. +- Xcode's static analyzer completed without findings. UBS was not available on this machine. +- Fixed RFCOMM shutdown calling `disconnect()` from the connector thread, which could join itself. +- Fixed failed and remotely closed connections leaving a joinable thread that could terminate the app. +- Made connector shutdown idempotent and wake blocked readers immediately. +- Fixed frame parsing so transport noise before a start marker is ignored and oversized frames are rejected. + +## Pass 2: fresh-eyes review + +- Replaced queued raw `Headphones*` captures with retained `shared_ptr` values to prevent use-after-free on disconnect. +- Serialized status reads, dynamic polling, and writes on one device-I/O queue. +- Locked headphone property reads and bounded ambient/EQ values stored in the model. +- Fixed v2 devices remaining permanently “changed” because v1-only VPT state was included. +- Capability-gated optional setters in the C++ core, not only in the UI. +- Fixed interleaved headset notifications being mistaken for command acknowledgments. +- Tightened frame decoding to reject trailing bytes after the checksum. + +## Pass 3: integration + +- Added regression coverage for preamble noise and notification-before-ACK ordering. +- Protocol tests pass with `-Wall -Wextra -Werror`. +- The macOS Debug app builds successfully after the lifecycle and concurrency changes. +- `git diff --check` passes. + +## Pass 4: verification + +- Xcode static analysis passes after all fixes. +- The strict protocol suite passes after the final rescan. +- No deferred bug-hunt findings remain. Protocol conformance, fuzzing, security, hardware, UX, and release checks are tracked as separate ordered passes. diff --git a/docs/XM4_ROADMAP.md b/docs/XM4_ROADMAP.md new file mode 100644 index 00000000..03427d60 --- /dev/null +++ b/docs/XM4_ROADMAP.md @@ -0,0 +1,44 @@ +# WH-1000XM4 macOS Roadmap + +## Product direction + +Turn SonyBridge into a dependable, native macOS companion for the WH-1000XM4. The first milestone favors safe device control and honest capability detection over broad model claims. Firmware installation is intentionally out of scope. + +## Safety boundary + +Sony's first- and second-generation control protocols reuse some opcode values for different operations. In particular, `0x22` requests battery state on v2 devices but powers off a v1 device such as the WH-1000XM4. Every request and mutation must therefore be selected from the connected transport's confirmed protocol version. Unsupported features stay hidden until their read-only inquiry succeeds. + +## Milestones + +### 1. First-class XM4 protocol support + +- Initialize v1 devices before capability inquiries. +- Read battery, firmware, codec, equalizer, DSEE, Speak-to-Chat, and auto-power-off state with v1-specific commands. +- Normalize v1 and v2 equalizer values into one internal model. +- Parse v1 ANC and ambient responses so physical-button changes update the interface. +- Gate mutations behind successful read-only capability probes. +- Add regression coverage proving the XM4 path never emits the v2 battery opcode. + +### 2. Headset verification + +- Verify connection and initial state against a WH-1000XM4 on firmware 3.0.1. +- Exercise one control at a time and capture sanitized protocol diagnostics. +- Confirm state persists and remains synchronized after physical-button changes, reconnects, and idle link drops. + +### 3. Native Mac experience + +- Add a menu-bar surface for battery, ANC, Ambient Sound, and Speak-to-Chat. +- Keep the existing window for EQ and less-frequent settings. +- Add launch-at-login, automatic reconnect, clear loading states, and recoverable errors. +- Improve keyboard access, VoiceOver labels, contrast, and reduced-motion behavior. + +### 4. Distribution quality + +- Add unit tests for framing, protocol routing, parsing, and capability gating. +- Add CI for Apple Silicon and Intel builds. +- Rename the bundle identifier for the fork and document upstream attribution. +- Produce signed/notarized releases only when a dedicated identity is available. + +## Definition of done for the first milestone + +The app builds cleanly, connects to the paired XM4 without powering it off, displays the settings returned by the headset, exposes only verified controls, and safely handles disconnects and unanswered inquiries. From 9247fd4017b2b91b04f3dd792ea5ce04c4c08b3e Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Aug 2026 07:21:04 -0400 Subject: [PATCH 02/35] docs(fuzz): preserve prior agent's static audit notes on the inbound parser Found uncommitted in the working tree (authored by the earlier audit pass, not this session); committed verbatim so the tree is clean and the analysis is not lost. Co-Authored-By: Claude Opus 4.8 --- Client/fuzz/AUDIT_FINDINGS.md | 138 ++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 Client/fuzz/AUDIT_FINDINGS.md diff --git a/Client/fuzz/AUDIT_FINDINGS.md b/Client/fuzz/AUDIT_FINDINGS.md new file mode 100644 index 00000000..767072af --- /dev/null +++ b/Client/fuzz/AUDIT_FINDINGS.md @@ -0,0 +1,138 @@ +# Adversarial static audit — inbound Bluetooth frame parser + +Scope traced: `CommandSerializer.cpp/.h`, `ByteMagic.cpp/.h`, `Headphones.cpp/.h`, +`BluetoothWrapper.cpp/.h` (framing layer feeding the parser), `Constants.h`, `Exceptions.h`. +Trust boundary: raw bytes an attacker-controlled/spoofed headset writes on the RFCOMM channel. + +## Bottom line + +I could not find a memory-safety bug, integer-overflow bug, escape-handling bug, or +round-trip divergence on the inbound path. The frame (de)serializer and the framing layer +are unusually careful. Below are (a) the specific defenses I verified by tracing concrete +byte sequences, and (b) three low/informational observations that are NOT exploitable as +written but are worth knowing. Nothing here is CONFIRMED-exploitable. + +The fuzz harness (`FuzzCommandSerializer.cpp`) only drives `unpackBtMessage` / +`packageDataForBt`. It never reaches `BluetoothWrapper::_readMessage` (the marker/leftover +framing) or the `Headphones::request*` consumers — so I put most reading effort there. +Those paths are also clean; details below. + +--- + +## Verified defenses (traced with concrete inputs) + +### D1 — `unpackBtMessage` length math cannot underflow or over-read +`CommandSerializer.cpp:136-173`. +- `unescaped.size() < 7` is rejected first (line 142), so indices `[0..6]` used to read + `dataType`, `seq`, the 4 size bytes, and the checksum byte always exist. +- `dataSize` is assembled as `unsigned int` from 4 bytes (max `0xFFFFFFFF`). Line 153 + `dataSize > unescaped.size() - 7`: `size` is `size_t >= 7`, so `size - 7` never wraps; + the comparison promotes `dataSize` to `size_t`, so a huge declared size is rejected, not + truncated. +- Line 157 forces `dataSize == size - 7` exactly (rejects trailing bytes). Consequently the + checksum index `unescaped[6 + dataSize]` (line 163) is exactly `size - 1` — always the + last valid byte — and the payload slice `[begin+6, begin+6+dataSize)` (line 171) ends + exactly at `size - 1`. No off-by-one. +- Trigger bytes I checked: minimal empty-payload frame body (unescaped) + `00 00 00 00 00 00 00` → dataSize 0, checksum at [6], payload empty: accepted, no OOB. + Body `3E 3E 3E` (len 3 < 7) → clean throw. Declared-size overflow body + `00 00 FF FF FF FF CK` → rejected at line 153. + +### D2 — escape/unescape is symmetric and bounded +`_escapeSpecials` / `_unescapeSpecials` (`CommandSerializer.cpp:11-85`). +- A trailing lone sentry `0x3D` at end of buffer is explicitly rejected + (`i == src.size() - 1` → throw, line 54) — no read past the end for the escaped byte. +- Sentry followed by any byte other than `44/45/46` throws ("Unexpected escaped byte") — + an escape can never synthesize an out-of-range value; it only ever emits `60/61/62`. +- The three escapable values (`60/61/62`) and the sentry (`61`) are all `< 128`, so the + `char`-vs-int `switch`/`==` comparisons are sign-safe (no negative-`char` mismatch). +- Delimiters `START=62` / `END=60` are themselves escaped inside the body, so a well-formed + body never contains a raw delimiter; the framing layer strips markers before unescape. +- Trigger checked: `3D` (single byte) → throw, no over-read; `3D 44` → `60`; `3D 99` → throw. + +### D3 — checksum is computed over identical bytes on both sides +`_sumChecksum` (`CommandSerializer.cpp:87-100`) accumulates into `unsigned char`. Pack sums +`[dataType..payload]` (pre-escape) and appends it; unpack sums `unescaped[0 .. 6+dataSize)` += the same logical bytes. The signed-`char` element promotion is identical on both sides, so +`unpack(pack(x))` reproduces the same checksum. No signedness bypass, no round-trip drift. + +### D4 — `_readMessage` framing cannot overrun `buf[2048]` +`BluetoothWrapper.cpp:109-182`. +- `recv(buf, sizeof(buf))` and the leftover replay both cap at `sizeof(buf)` via + `std::min(_leftoverBytes.size(), sizeof(buf))` (line 123); `numRecvd <= 2048` always. +- `messageStart`/`messageEnd` stay within `[0, numRecvd]`; the only way `messageStart` is set + is `i+1` on a START at index `i < numRecvd` (so `<= numRecvd`), and an END that sets + `messageEnd = i` is only reached *after* a START in the same scan (`i` strictly greater), + so the `insert(buf+messageStart, buf+messageEnd)` range is never inverted. +- `_leftoverBytes.assign(buf+i+1, buf+numRecvd)` uses `i+1 <= numRecvd` — valid, possibly + empty. +- Total accumulation is bounded: `msgBytes.size() > MAX_BLUETOOTH_MESSAGE_SIZE` throws, so an + attacker who never sends END cannot grow memory without bound (DoS-bounded). +- A second START while a message is ongoing → clean `RecoverableException(shouldDisconnect)`. + +### D5 — no attacker-controlled value is ever used as an array index +Every payload-derived array access in `Headphones.cpp` uses a *fixed* loop bound, not a +payload value: `_eqBands[i]` and `resp[5+i]` (i in 0..4, guarded by `resp.size() >= 10`, +lines 186-192); `APO_CODES[index]` is only reached via `setAutoPowerOff`, which validates +`index` in 0..5 (line 440), and `apoIndexFromCode` returns a value found by a fixed 0..5 scan +(lines 359-366). Enum values decoded from the wire (`DATA_TYPE`, `EQ_PRESET`) are only ever +compared or displayed, never used to index a table → no enum-driven OOB. + +### D6 — every consumer bounds-checks before indexing, and every call site catches +`std::exception` +Traced all `request*`/`probeCapabilities` readers: each guards with `resp.size()` before the +highest index it reads (`requestBattery` `<4`/`>=4`/`>=6`; `requestEqualizer` `>=3`/`>=10`; +`requestAmbientState` v2 `>=7`, v1 `==8`; `requestDsee` `>=3`/`>=4`; `probeCapabilities` +`>3`/`>=3`/`>=4`/`>=5`). `sendCommandAndReadResponse` only returns a payload after checking +`!payload.empty()` (so `payload[0]` is safe) and, for subtype matches, `payload.size() >= 2`. +Every invocation in `CrossPlatformGUI.cpp` and `macos/HeadphonesBridge.mm` is wrapped in +`catch (const std::exception&)` / `catch (const RecoverableException&)`, so the mix of thrown +types (see O1) cannot escape to terminate the process. + +--- + +## Observations (low / informational — not exploitable as written) + +### O1 — INFO — inconsistent exception type in the parser (not a vuln, verified caught) +`CommandSerializer.cpp:56, 74, 144` throw plain `std::runtime_error`, while the size/checksum +rejections at 155/159/165 throw `RecoverableException`. If any call site ever caught *only* +`RecoverableException`, a malformed frame (e.g. body `3D` → "No data left for escaped byte +data", or a `< 7`-byte body) would become an uncaught exception → `std::terminate` → remote +DoS. I checked every reachable call site (`CrossPlatformGUI.cpp:126/157/189-244/566-586`, +`HeadphonesBridge.mm:169-361`, `windows/main.cpp:18`, `linux/main.cpp:17`): all catch +`std::exception`, so today this is **safe**. Flagged only because the invariant is implicit — +a future call site that narrows to `RecoverableException` would silently turn any bad frame +into a crash. Recommend making the parser throw `RecoverableException` uniformly. +Status: SUSPECTED-DoS in theory, CONFIRMED-not-reachable in this tree. + +### O2 — LOW — unvalidated device-reported scalar values (cosmetic, no memory impact) +Battery level (`Headphones.cpp:109/120/133/144`), EQ band values, DSEE/adaptive flags, etc. +are stored straight from the wire with no range validation (e.g. a spoofed headset can report +battery `0xFF` → "255%"). Purely a UI-correctness issue; no bounds or state-corruption +consequence. Worth a `clamp`/range check for polish, not a security fix. + +### O3 — LOW — attacker-controlled firmware/codec strings rendered in UI +`probeCapabilities` builds `_firmware = std::string(r.begin()+3, r.end())` +(`Headphones.cpp:390/412`) from up to ~2041 attacker-chosen bytes, including NULs and control +bytes, and displays it. ImGui renders text literally (no escape-sequence interpretation), so +this is not a terminal-injection vector in the shipped GUI; it would only matter if the string +were ever echoed to a raw terminal/log. Informational. + +--- + +## Out-of-scope-but-checked + +`ByteMagic::MACBytesToString` reads a fixed 6 bytes and `MACStringToLong` parses a config +string; both are Windows-only and fed by OS device-enumeration / user config, not by inbound +frame bytes — outside this trust boundary and outside the macOS target. No issue on the +inbound path. + +## Round-trip + +`unpack(pack(x)) == x` holds for `(dataType, seqNumber, payload)`: pack writes +`static_cast(dataType)`, the low byte of `seqNumber`, a 4-byte BE size, the +payload, and a checksum, then canonically escapes; unpack reverses each step and the exact +`dataSize == size-7` check rejects any non-canonical framing. I could not construct an +accepted frame that fails to re-pack-and-re-decode identically (oversized-after-escape frames +are rejected by `packageDataForBt`'s `MAX_BLUETOOTH_MESSAGE_SIZE` guard, which the harness +already treats as expected). No divergence found. From 45b994dfb97da04442e522cfc174806708939e6b Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Aug 2026 07:21:04 -0400 Subject: [PATCH 03/35] fix(fuzz): make the harness compile Message lives in the CommandSerializer namespace, and its seqNumber field is unsigned char; the harness used the unqualified name and narrowed through a signed char cast, so the libFuzzer target never built. Co-Authored-By: Claude Opus 4.8 --- Client/fuzz/FuzzCommandSerializer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Client/fuzz/FuzzCommandSerializer.cpp b/Client/fuzz/FuzzCommandSerializer.cpp index 1718af12..fb4e929b 100644 --- a/Client/fuzz/FuzzCommandSerializer.cpp +++ b/Client/fuzz/FuzzCommandSerializer.cpp @@ -7,6 +7,8 @@ namespace { + using CommandSerializer::Message; + [[noreturn]] void failInvariant() { std::abort(); @@ -76,7 +78,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { auto packaged = CommandSerializer::packageDataForBt(payload, dataType, sequence); Buffer body(packaged.begin() + 1, packaged.end() - 1); - Message expected{ dataType, static_cast(sequence), payload }; + Message expected{ dataType, sequence, payload }; requireEqual(expected, CommandSerializer::unpackBtMessage(body)); } catch (const std::exception&) From efcc096bc0a917cd8c6ec8f0f504089a6f71c05f Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Aug 2026 07:21:04 -0400 Subject: [PATCH 04/35] fix(fuzz): make run-macos.sh runnable and add a no-libFuzzer fallback - -max_len referenced MAX_BLUETOOTH_MESSAGE_SIZE as a shell variable, which is never set, so 'set -u' killed the script before fuzzing; derive it from Constants.h instead. - Apple's clang++ has no libFuzzer runtime and the failure only appears at link time; probe with a real link and fall back to a Homebrew LLVM clang++. - When no libFuzzer-capable compiler exists at all, build driver_main.cpp: a deterministic seed-replay + structured-mutation driver (bit/byte flips, truncation, length-field tampering, escape/marker injection, splicing) over the same LLVMFuzzerTestOneInput entry point under ASan/UBSan. - Suppress libFuzzer's own never-joined RSS-monitor thread (lsan.supp) so leak detection stays on for the parser; skip detect_leaks on Apple ASan, which does not support it. Co-Authored-By: Claude Opus 4.8 --- Client/fuzz/README.md | 8 ++ Client/fuzz/driver_main.cpp | 187 ++++++++++++++++++++++++++++++++++++ Client/fuzz/lsan.supp | 4 + Client/fuzz/run-macos.sh | 78 +++++++++++---- 4 files changed, 258 insertions(+), 19 deletions(-) create mode 100644 Client/fuzz/driver_main.cpp create mode 100644 Client/fuzz/lsan.supp diff --git a/Client/fuzz/README.md b/Client/fuzz/README.md index 774f4e67..c45caffe 100644 --- a/Client/fuzz/README.md +++ b/Client/fuzz/README.md @@ -22,6 +22,14 @@ Override the default 60-second smoke duration with `FUZZ_SECONDS`. Crash artifac are intentionally kept outside the repository; minimize and reproduce any finding, then add the smallest input to the permanent protocol regression tests. +The script prefers a libFuzzer-capable clang (`CXX`, else a Homebrew LLVM). Apple's +`/usr/bin/clang++` ships without the libFuzzer runtime; when no capable compiler is +found, the script builds `driver_main.cpp` instead — a deterministic seed-replay and +structured-mutation driver over the same `LLVMFuzzerTestOneInput` entry point, still +under ASan/UBSan. Override its default 1.5M iterations with `FUZZ_ITERATIONS`. +`lsan.supp` suppresses libFuzzer's own never-joined RSS-monitor thread so leak +detection stays enabled for the parser under test. + MemorySanitizer is not included because it requires a fully instrumented C++ standard library. ThreadSanitizer is not applicable to this single-threaded parser target; connection concurrency is covered by the protocol integration tests and diff --git a/Client/fuzz/driver_main.cpp b/Client/fuzz/driver_main.cpp new file mode 100644 index 00000000..815d8f4e --- /dev/null +++ b/Client/fuzz/driver_main.cpp @@ -0,0 +1,187 @@ +// Standalone deterministic driver for toolchains without libFuzzer. +// Replays every corpus seed plus the empty input, then runs bounded +// structured mutation (bit/byte flips, truncation, length-field tampering, +// escape/marker injection, seed splicing) through LLVMFuzzerTestOneInput. +// Build with -fsanitize=address,undefined -fno-sanitize-recover=all. +// Not compiled into the libFuzzer target; see run-macos.sh fallback path. + +#include +#include +#include +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); + +namespace +{ + constexpr size_t kMaxInput = 2048; // mirrors MAX_BLUETOOTH_MESSAGE_SIZE + + uint64_t rngState = 0x9e3779b97f4a7c15ull; + + uint64_t nextRand() + { + // xorshift64* — deterministic across runs and platforms. + rngState ^= rngState >> 12; + rngState ^= rngState << 25; + rngState ^= rngState >> 27; + return rngState * 0x2545f4914f6cdd1dull; + } + + void runOne(const std::vector& input) + { + LLVMFuzzerTestOneInput(input.data(), input.size()); + } + + void mutate(std::vector& buf) + { + // Bytes the protocol treats specially: markers, escape sentry, escape codes. + static const uint8_t special[] = { 0x3c, 0x3d, 0x3e, 0x2c, 0x2d, 0x2e, 0x00, 0xff }; + + switch (nextRand() % 8) + { + case 0: // bit flip + if (!buf.empty()) + { + buf[nextRand() % buf.size()] ^= static_cast(1u << (nextRand() % 8)); + } + break; + + case 1: // byte overwrite with random value + if (!buf.empty()) + { + buf[nextRand() % buf.size()] = static_cast(nextRand()); + } + break; + + case 2: // truncate + if (!buf.empty()) + { + buf.resize(nextRand() % buf.size()); + } + break; + + case 3: // length-field tampering (bytes 2..5 of the unescaped header) + if (buf.size() >= 6) + { + buf[2 + nextRand() % 4] = static_cast(nextRand()); + } + break; + + case 4: // escape/marker injection at a random position + { + size_t pos = buf.empty() ? 0 : nextRand() % buf.size(); + buf.insert(buf.begin() + pos, special[nextRand() % sizeof(special)]); + } + break; + + case 5: // overwrite with a special byte + if (!buf.empty()) + { + buf[nextRand() % buf.size()] = special[nextRand() % sizeof(special)]; + } + break; + + case 6: // append random tail + { + size_t extra = nextRand() % 16 + 1; + for (size_t i = 0; i < extra && buf.size() < kMaxInput; i++) + { + buf.push_back(static_cast(nextRand())); + } + } + break; + + case 7: // duplicate a random chunk (grows structure, keeps checksummed prefixes) + if (!buf.empty()) + { + size_t start = nextRand() % buf.size(); + size_t len = nextRand() % (buf.size() - start) + 1; + if (buf.size() + len <= kMaxInput) + { + std::vector chunk(buf.begin() + start, buf.begin() + start + len); + buf.insert(buf.begin() + start, chunk.begin(), chunk.end()); + } + } + break; + } + + if (buf.size() > kMaxInput) + { + buf.resize(kMaxInput); + } + } +} + +int main(int argc, char** argv) +{ + std::vector> seeds; + seeds.push_back({}); // empty input is a required boundary case + + for (int i = 1; i < argc; i++) + { + if (std::strncmp(argv[i], "-iterations=", 12) == 0) + { + continue; // handled below + } + std::ifstream f(argv[i], std::ios::binary); + if (!f) + { + std::fprintf(stderr, "cannot read seed %s\n", argv[i]); + return 2; + } + std::vector data((std::istreambuf_iterator(f)), + std::istreambuf_iterator()); + seeds.push_back(std::move(data)); + } + + unsigned long long iterations = 1500000; + for (int i = 1; i < argc; i++) + { + if (std::strncmp(argv[i], "-iterations=", 12) == 0) + { + iterations = std::strtoull(argv[i] + 12, nullptr, 10); + } + } + + // Replay every seed unmodified first. + for (const auto& s : seeds) + { + runOne(s); + } + + // Structured mutation: pick a seed (or a splice of two), apply 1-4 mutations. + std::vector buf; + for (unsigned long long i = 0; i < iterations; i++) + { + const auto& base = seeds[nextRand() % seeds.size()]; + buf = base; + if (nextRand() % 4 == 0 && seeds.size() > 1) + { + const auto& other = seeds[nextRand() % seeds.size()]; + size_t cut = buf.empty() ? 0 : nextRand() % (buf.size() + 1); + buf.resize(cut); + if (!other.empty()) + { + size_t take = nextRand() % (other.size() + 1); + buf.insert(buf.end(), other.begin(), other.begin() + take); + } + } + size_t rounds = nextRand() % 4 + 1; + for (size_t r = 0; r < rounds; r++) + { + mutate(buf); + } + runOne(buf); + + if ((i + 1) % 250000 == 0) + { + std::fprintf(stderr, "iter %llu\n", i + 1); + } + } + + std::fprintf(stderr, "done: %llu mutation iterations + %zu seed replays\n", + iterations, seeds.size()); + return 0; +} diff --git a/Client/fuzz/lsan.supp b/Client/fuzz/lsan.supp new file mode 100644 index 00000000..b246cb8f --- /dev/null +++ b/Client/fuzz/lsan.supp @@ -0,0 +1,4 @@ +# libFuzzer's RSS-monitor std::thread is heap-allocated and never joined at +# exit (fuzzer::StartRssThread, FuzzerDriver.cpp). It is runtime-internal and +# reports as a 56-byte leak; keep detect_leaks=1 for the code under test. +leak:fuzzer::StartRssThread diff --git a/Client/fuzz/run-macos.sh b/Client/fuzz/run-macos.sh index d5cd67a0..2cefcb08 100644 --- a/Client/fuzz/run-macos.sh +++ b/Client/fuzz/run-macos.sh @@ -18,24 +18,64 @@ for seed in "$fuzz_dir"/seeds/*.hex; do xxd -r -p "$seed" "$corpus/$name" done -clang++ -std=c++20 -g -O1 \ - -fsanitize=fuzzer,address,undefined \ - -fno-sanitize-recover=all -fno-omit-frame-pointer \ - -I"$client_dir" \ - "$fuzz_dir/FuzzCommandSerializer.cpp" \ - "$client_dir/ByteMagic.cpp" \ - "$client_dir/CommandSerializer.cpp" \ - -o "$binary" - -export ASAN_OPTIONS="abort_on_error=1:detect_leaks=1:symbolize=1" +# Apple's clang++ ships without the libFuzzer runtime; the failure only shows at +# link time, so probe with a real link. Fall back to a Homebrew LLVM clang++, and +# if none exists run the deterministic mutation driver instead of libFuzzer. +probe="$work_dir/fuzzer-probe" +printf 'extern "C" int LLVMFuzzerTestOneInput(const unsigned char*, unsigned long) { return 0; }\n' > "$probe.cpp" +cxx="${CXX:-clang++}" +have_libfuzzer=1 +if ! "$cxx" -fsanitize=fuzzer "$probe.cpp" -o "$probe" 2>/dev/null; then + have_libfuzzer=0 + for candidate in /opt/homebrew/opt/llvm*/bin/clang++ /usr/local/opt/llvm*/bin/clang++; do + if [ -x "$candidate" ] && "$candidate" -fsanitize=fuzzer "$probe.cpp" -o "$probe" 2>/dev/null; then + cxx="$candidate" + have_libfuzzer=1 + break + fi + done +fi + +# Keep -max_len in lockstep with MAX_BLUETOOTH_MESSAGE_SIZE in Constants.h. +max_len=$(sed -n 's/.*MAX_BLUETOOTH_MESSAGE_SIZE = \([0-9]*\).*/\1/p' "$client_dir/Constants.h") + export UBSAN_OPTIONS="halt_on_error=1:print_stacktrace=1" -"$binary" \ - -max_total_time="${FUZZ_SECONDS:-60}" \ - -max_len="$MAX_BLUETOOTH_MESSAGE_SIZE" \ - -timeout=5 \ - -use_value_profile=1 \ - -print_final_stats=1 \ - -dict="$fuzz_dir/dictionaries/sony_protocol.dict" \ - -artifact_prefix="$artifacts/" \ - "$corpus" +if [ "$have_libfuzzer" -eq 1 ]; then + # Apple's ASan lacks leak detection; only enable it for LLVM clang builds. + export ASAN_OPTIONS="abort_on_error=1:detect_leaks=1:symbolize=1" + export LSAN_OPTIONS="suppressions=$fuzz_dir/lsan.supp" + + "$cxx" -std=c++20 -g -O1 \ + -fsanitize=fuzzer,address,undefined \ + -fno-sanitize-recover=all -fno-omit-frame-pointer \ + -I"$client_dir" \ + "$fuzz_dir/FuzzCommandSerializer.cpp" \ + "$client_dir/ByteMagic.cpp" \ + "$client_dir/CommandSerializer.cpp" \ + -o "$binary" + + "$binary" \ + -max_total_time="${FUZZ_SECONDS:-60}" \ + -max_len="$max_len" \ + -timeout=5 \ + -use_value_profile=1 \ + -print_final_stats=1 \ + -dict="$fuzz_dir/dictionaries/sony_protocol.dict" \ + -artifact_prefix="$artifacts/" \ + "$corpus" +else + echo "libFuzzer unavailable; running deterministic mutation driver" >&2 + export ASAN_OPTIONS="abort_on_error=1:symbolize=1" + "$cxx" -std=c++20 -g -O1 \ + -fsanitize=address,undefined \ + -fno-sanitize-recover=all -fno-omit-frame-pointer \ + -I"$client_dir" \ + "$fuzz_dir/driver_main.cpp" \ + "$fuzz_dir/FuzzCommandSerializer.cpp" \ + "$client_dir/ByteMagic.cpp" \ + "$client_dir/CommandSerializer.cpp" \ + -o "$binary" + + "$binary" -iterations="${FUZZ_ITERATIONS:-1500000}" "$corpus"/* +fi From a5d3d349f218866e99caec72c1c08cce7651959f Mon Sep 17 00:00:00 2001 From: claude Date: Mon, 24 Aug 2026 07:27:17 -0400 Subject: [PATCH 05/35] harden(parser): uniform RecoverableException on malformed inbound frames Both the fuzz campaign (8.2M execs, zero parser bugs) and the static audit flagged the same latent issue: three malformed-frame paths in unpackBtMessage threw bare std::runtime_error instead of the RecoverableException used by the sibling checks. Safe only because every current call site catches std::exception; a future site narrowing its catch would turn attacker- controlled input into std::terminate (remote DoS). Made all three throw RecoverableException(msg, true), matching the existing malformed-frame throws, and added regression assertions. Also broadened the LSan suppression from fuzzer::StartRssThread to fuzzer:: to cover an intermittent symbolizer leak in libFuzzer's PC printer (parser never on the stack). Co-Authored-By: Claude Opus 4.8 --- Client/CommandSerializer.cpp | 6 +++--- Client/fuzz/lsan.supp | 11 +++++++---- Client/tests/HeadphonesProtocolTests.cpp | 25 ++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/Client/CommandSerializer.cpp b/Client/CommandSerializer.cpp index ac9b8eb7..105f1ca4 100644 --- a/Client/CommandSerializer.cpp +++ b/Client/CommandSerializer.cpp @@ -53,7 +53,7 @@ namespace CommandSerializer { if (i == src.size() - 1) { - throw std::runtime_error("No data left for escaped byte data"); + throw RecoverableException("No data left for escaped byte data", true); } i = i + 1; switch (src[i]) @@ -71,7 +71,7 @@ namespace CommandSerializer break; default: - throw std::runtime_error("Unexpected escaped byte"); + throw RecoverableException("Unexpected escaped byte", true); break; } } @@ -141,7 +141,7 @@ namespace CommandSerializer //1 (type) + 1 (seq) + 4 (size) + 1 (checksum) = 7 bytes minimum, before any payload. if (unescaped.size() < 7) { - throw std::runtime_error("Invalid message: Smaller than the minimum message size"); + throw RecoverableException("Invalid message: Smaller than the minimum message size", true); } unsigned int dataSize = diff --git a/Client/fuzz/lsan.supp b/Client/fuzz/lsan.supp index b246cb8f..952d4547 100644 --- a/Client/fuzz/lsan.supp +++ b/Client/fuzz/lsan.supp @@ -1,4 +1,7 @@ -# libFuzzer's RSS-monitor std::thread is heap-allocated and never joined at -# exit (fuzzer::StartRssThread, FuzzerDriver.cpp). It is runtime-internal and -# reports as a 56-byte leak; keep detect_leaks=1 for the code under test. -leak:fuzzer::StartRssThread +# libFuzzer's own runtime allocates at exit in ways LSan flags but that are not +# under-test code: the RSS-monitor std::thread is heap-allocated and never joined +# (fuzzer::StartRssThread), and the coverage/PC printer allocates in the symbolizer +# when new PCs are observed. Both stacks are entirely inside fuzzer:: internals with +# the parser nowhere on them. Suppress the whole libFuzzer runtime so detect_leaks=1 +# stays live for CommandSerializer/ByteMagic (their frames never contain "fuzzer::"). +leak:fuzzer:: diff --git a/Client/tests/HeadphonesProtocolTests.cpp b/Client/tests/HeadphonesProtocolTests.cpp index 671e089a..0c9a6e91 100644 --- a/Client/tests/HeadphonesProtocolTests.cpp +++ b/Client/tests/HeadphonesProtocolTests.cpp @@ -1,5 +1,6 @@ #include "BluetoothWrapper.h" #include "CommandSerializer.h" +#include "Exceptions.h" #include "Headphones.h" #include @@ -96,6 +97,19 @@ void require(bool condition, const char* message) { if (!condition) throw std::runtime_error(message); } + +// A malformed inbound frame must surface as a RecoverableException (caught at every call +// site and shown in the UI) rather than a bare std::runtime_error. If a future call site +// narrowed its catch to RecoverableException, a plain runtime_error here would reach +// std::terminate on attacker-controlled input. +template +void expectRecoverable(Fn&& fn, const char* message) +{ + try { fn(); } + catch (const RecoverableException&) { return; } + catch (...) { throw std::runtime_error(message); } + throw std::runtime_error(message); +} } int main() @@ -175,6 +189,17 @@ int main() (unsigned char)speakToChat[1] == V1Command::SUB_SPEAK_TO_CHAT && (unsigned char)speakToChat[3] == 0x00, "Speak-to-Chat did not use the v1 command layout"); + // Malformed inbound frames on the untrusted parser path must throw the recoverable type. + // 61 (0x3D) is the escape sentry; a lone one at buffer end and one followed by a + // non-escapable byte are the two unescape rejection paths. + constexpr char ESCAPE_SENTRY = 61; + expectRecoverable([&] { CommandSerializer::unpackBtMessage(Buffer{ ESCAPE_SENTRY }); }, + "dangling escape byte did not throw RecoverableException"); + expectRecoverable([&] { CommandSerializer::unpackBtMessage(Buffer{ ESCAPE_SENTRY, 0x00 }); }, + "unexpected escaped byte did not throw RecoverableException"); + expectRecoverable([] { CommandSerializer::unpackBtMessage(Buffer{ 0x00, 0x00, 0x00 }); }, + "under-minimum-size frame did not throw RecoverableException"); + std::cout << "WH-1000XM4 protocol safety tests passed\n"; return 0; } From 18e17e7757e19bb93088a3faf9506137b4a4bb45 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Aug 2026 07:40:21 -0400 Subject: [PATCH 06/35] test: add metamorphic protocol suite (round-trip, escaping, framing, corruption) Covers the gap between the exact golden fixtures and the crash-only fuzzer with relational properties over programmatically generated inputs (fixed-seed splitmix64, fully deterministic): - P1 round-trip: unpack(strip_markers(pack(p, dt, seq))) recovers (p, dt, seq & 0xFF); pack output is also structurally verified against an independent re-implementation of the documented layout (declared BE size, mod-256 checksum, header bytes). - P2 escaping transparency: every escapable byte (60/61/62) at every payload position round-trips; the frame interior never contains a raw marker byte. - P3 seq domain: 0..255 round-trips exactly; wider values pack byte-identically to seq & 0xFF. - P4 framing: +/-1-byte damage at either end and marker-attached frames are all rejected with RecoverableException. - P5 determinism and inverse consistency: pack is byte-identical across calls; repacking an unpacked message reproduces the frame. - P6 corruption: exhaustive single-byte replacement (all 255 values, every position, four frames incl. escape-dense ones) plus per-bit flips on a 512-byte-payload frame - 31270 corrupted bodies, all rejected recoverably, none silently parsed. - P7 size boundary: 2039 plain payload bytes fill the 2048 frame exactly; 2040 overflows; escape-heavy payloads halve the budget (1016 x 0x3C fits, 1020 does not). Wired into Client/tests/run-macos.sh after the conformance suite, same clang++ -Wall -Wextra -Werror invocation. Co-Authored-By: Claude Opus 4.8 --- Client/tests/MetamorphicProtocolTests.cpp | 428 ++++++++++++++++++++++ Client/tests/run-macos.sh | 9 + 2 files changed, 437 insertions(+) create mode 100644 Client/tests/MetamorphicProtocolTests.cpp diff --git a/Client/tests/MetamorphicProtocolTests.cpp b/Client/tests/MetamorphicProtocolTests.cpp new file mode 100644 index 00000000..670052d8 --- /dev/null +++ b/Client/tests/MetamorphicProtocolTests.cpp @@ -0,0 +1,428 @@ +#include "CommandSerializer.h" +#include "Constants.h" +#include "Exceptions.h" + +#include +#include +#include +#include +#include +#include +#include + +// Metamorphic (relational) tests for the Sony v1 wire protocol layer. +// +// The conformance suite pins 18 exact golden frames and the fuzzer proves the +// inbound parser is crash-free; this suite covers the gap between them: +// properties that must hold across *transformations* of programmatically +// generated inputs, not just for pinned examples. +// +// P1 Round-trip: unpack(strip_markers(pack(p, dt, seq))) == (p, dt, seq & 0xFF), +// and pack's output matches an independent re-implementation of the +// documented frame layout (structure, declared size, checksum). +// P2 Escaping transparency: every escapable byte (60/61/62) survives a +// round trip at every payload position, and the packed frame interior +// never contains a raw frame marker (60/62). +// P3 Sequence-number domain: seq 0..255 round-trips exactly; wider values +// are truncated mod 256, byte-identically to packing (seq & 0xFF). +// P4 Framing: dropping or adding a single byte at either end of a valid +// body is rejected, as is unpacking a frame with its markers attached. +// P5 Determinism / inverse consistency: packing is byte-identical across +// calls, and re-packing an unpacked message reproduces the original frame. +// P6 Corruption rejection: for the frames tested here, replacing any single +// body byte with any other value (and, for a large frame, flipping any +// single bit) makes unpack throw RecoverableException. Note: single-byte +// edits of the *unescaped* image are always caught (mod-256 sum changes +// whenever one byte changes); wire-level edits also shift length/framing, +// and this section verifies rejection exhaustively over this corpus. +// P7 Size boundary: pack succeeds iff the escaped frame fits in +// MAX_BLUETOOTH_MESSAGE_SIZE, measured on the escaped size (payload +// bytes that escape count double), and every returned frame fits. +// +// Everything is deterministic: fixed-seed splitmix64, no wall clock, no I/O. + +namespace +{ +size_t g_checks = 0; + +void require(bool condition, const std::string& message) +{ + g_checks++; + if (!condition) throw std::runtime_error(message); +} + +// Fixed-seed splitmix64 so every run sees the exact same corpus. +uint64_t g_rngState = 0x5b7a1e0fd2c3a9e4ULL; + +unsigned char nextByte() +{ + g_rngState += 0x9e3779b97f4a7c15ULL; + uint64_t z = g_rngState; + z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL; + z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL; + return static_cast((z ^ (z >> 31)) & 0xff); +} + +Buffer randomPayload(size_t n) +{ + Buffer ret; + ret.reserve(n); + for (size_t i = 0; i < n; i++) + ret.push_back(static_cast(nextByte())); + return ret; +} + +std::string hexDump(const Buffer& b) +{ + std::ostringstream oss; + oss << std::hex; + for (auto c : b) oss << ((unsigned)(unsigned char)c < 16 ? "0" : "") << (unsigned)(unsigned char)c << " "; + return oss.str(); +} + +constexpr unsigned char SENTRY = 61; + +// Independent re-implementation of the documented unescape (from the format +// comment in CommandSerializer.h), used to structurally verify pack's output +// without calling the production _unescapeSpecials. +std::vector refUnescape(const Buffer& body) +{ + std::vector out; + for (size_t i = 0; i < body.size(); i++) + { + auto b = static_cast(body[i]); + if (b == SENTRY) + { + require(i + 1 < body.size(), "packed frame ends with a dangling escape sentry"); + auto n = static_cast(body[++i]); + if (n == 44) out.push_back(60); + else if (n == 45) out.push_back(61); + else if (n == 46) out.push_back(62); + else require(false, "packed frame contains an invalid escape pair"); + } + else + { + out.push_back(b); + } + } + return out; +} + +Buffer stripMarkers(const Buffer& frame) +{ + require(frame.size() >= 2, "packed frame is too small to carry both markers"); + require(frame.front() == START_MARKER, "packed frame does not start with the start marker"); + require(frame.back() == END_MARKER, "packed frame does not end with the end marker"); + return Buffer(frame.begin() + 1, frame.end() - 1); +} + +enum class Outcome { Parsed, Recoverable, OtherError }; + +Outcome tryUnpack(const Buffer& body, CommandSerializer::Message* out = nullptr) +{ + try + { + auto msg = CommandSerializer::unpackBtMessage(body); + if (out) *out = msg; + return Outcome::Parsed; + } + catch (const RecoverableException&) { return Outcome::Recoverable; } + catch (...) { return Outcome::OtherError; } +} + +struct Case +{ + Buffer payload; + unsigned char dataType; + unsigned int seq; +}; + +// Every declared DATA_TYPE value. +const unsigned char DATA_TYPES[] = { 0, 1, 2, 9, 10, 12, 13, 14, 16, 18, 25, 26, 28, 29, 30, 45 }; +const unsigned int SEQS[] = { 0, 1, 2, 60, 61, 62, 127, 128, 254, 255 }; + +std::vector buildCorpus() +{ + std::vector corpus; + const size_t sizes[] = { 0, 1, 2, 3, 4, 7, 8, 16, 63, 64, 255, 256, 257, 1024 }; + size_t dtIdx = 0, seqIdx = 0; + for (auto n : sizes) + { + corpus.push_back({ randomPayload(n), + DATA_TYPES[dtIdx++ % (sizeof(DATA_TYPES))], + SEQS[seqIdx++ % (sizeof(SEQS) / sizeof(SEQS[0]))] }); + } + // Payloads whose checksum byte lands exactly on 60/61/62 (dt=12, seq=1: + // 14 + b == 60/61/62), so the escaped-checksum path is exercised too. + for (unsigned char b : { 46, 47, 48 }) + corpus.push_back({ Buffer{ static_cast(b) }, 12, 1 }); + // Escape-dense and sentry-adjacent patterns. + corpus.push_back({ Buffer{ 60, 61, 62, 60, 61, 62 }, 12, 0 }); + corpus.push_back({ Buffer{ 61, 44, 61, 45, 61, 46 }, 12, 0 }); + corpus.push_back({ Buffer{ 44, 45, 46 }, 12, 0 }); + return corpus; +} + +// P1 + P5 for one case: structural validation against the independent +// re-implementation, production round trip, determinism, and repack identity. +void checkRoundTrip(const Case& c) +{ + const auto frame = CommandSerializer::packageDataForBt(c.payload, static_cast(c.dataType), c.seq); + const auto frameAgain = CommandSerializer::packageDataForBt(c.payload, static_cast(c.dataType), c.seq); + require(frame == frameAgain, "packing the same input twice was not byte-identical"); + require(frame.size() <= MAX_BLUETOOTH_MESSAGE_SIZE, "pack returned a frame larger than MAX_BLUETOOTH_MESSAGE_SIZE"); + + const auto body = stripMarkers(frame); + // The interior must never contain a raw frame marker, or the transport + // could not find frame boundaries unambiguously. + for (auto ch : body) + require(ch != START_MARKER && ch != END_MARKER, + "packed frame interior contains a raw frame marker: " + hexDump(frame)); + + // Structural check against the documented layout, independently unescaped. + const auto ref = refUnescape(body); + require(ref.size() == 7 + c.payload.size(), "unescaped frame size does not match header + payload + checksum"); + require(ref[0] == c.dataType, "frame does not begin with the data type byte"); + require(ref[1] == (c.seq & 0xFF), "frame seq byte does not match the requested sequence number"); + const uint32_t declared = ((uint32_t)ref[2] << 24) | ((uint32_t)ref[3] << 16) | ((uint32_t)ref[4] << 8) | (uint32_t)ref[5]; + require(declared == c.payload.size(), "declared big-endian size does not match the payload length"); + for (size_t i = 0; i < c.payload.size(); i++) + require(ref[6 + i] == static_cast(c.payload[i]), "payload byte was altered by packing"); + unsigned char sum = 0; + for (size_t i = 0; i < 6 + c.payload.size(); i++) sum = static_cast(sum + ref[i]); + require(sum == ref[6 + c.payload.size()], "checksum byte does not equal the mod-256 sum of the frame"); + + // Production round trip. + CommandSerializer::Message msg; + require(tryUnpack(body, &msg) == Outcome::Parsed, "unpack rejected a freshly packed frame: " + hexDump(frame)); + require(static_cast(msg.dataType) == c.dataType, "round-tripped data type differs"); + require(msg.seqNumber == (c.seq & 0xFF), "round-tripped sequence number differs"); + require(msg.payload == c.payload, "round-tripped payload differs: " + hexDump(frame)); + + // Inverse consistency: packing the unpacked message reproduces the frame. + const auto repacked = CommandSerializer::packageDataForBt(msg.payload, msg.dataType, msg.seqNumber); + require(repacked == frame, "re-packing an unpacked message did not reproduce the original frame"); +} + +size_t testRoundTripCorpus(const std::vector& corpus) +{ + for (const auto& c : corpus) checkRoundTrip(c); + return corpus.size(); +} + +// P2: every escapable byte, at every position, in several payload sizes. +size_t testEscapingTransparency() +{ + size_t cases = 0; + size_t dtIdx = 0, seqIdx = 0; + for (unsigned char special : { 60, 61, 62 }) + { + for (size_t n : { 1, 2, 3, 5, 17 }) + { + for (size_t pos = 0; pos < n; pos++) + { + Buffer payload(n, 0x41); + payload[pos] = static_cast(special); + checkRoundTrip({ payload, + DATA_TYPES[dtIdx++ % sizeof(DATA_TYPES)], + SEQS[seqIdx++ % (sizeof(SEQS) / sizeof(SEQS[0]))] }); + cases++; + } + } + // Payloads made entirely of one escapable byte. + for (size_t n : { 1, 2, 3, 8, 64 }) + { + checkRoundTrip({ Buffer(n, static_cast(special)), 12, 3 }); + cases++; + } + } + return cases; +} + +// P3: seq 0..255 round-trips exactly; wider seqs truncate mod 256. +size_t testSeqDomain() +{ + size_t cases = 0; + const Buffer payload{ 0x01, 0x02 }; + for (unsigned int seq = 0; seq <= 255; seq++) + { + checkRoundTrip({ payload, 12, seq }); + cases++; + } + for (unsigned int wide : { 256u, 300u, 65536u + 5u, 0xDEADBEEFu, 0xFFFFFFFFu }) + { + const auto packedWide = CommandSerializer::packageDataForBt(payload, DATA_TYPE::DATA_MDR, wide); + const auto packedTrunc = CommandSerializer::packageDataForBt(payload, DATA_TYPE::DATA_MDR, wide & 0xFF); + require(packedWide == packedTrunc, "wide sequence number was not truncated mod 256 consistently"); + cases++; + } + return cases; +} + +// P4: one-byte framing damage at either end is rejected, and unpack does not +// accept a frame that still carries its start/end markers. +size_t testFraming(const std::vector& corpus) +{ + size_t cases = 0; + for (const auto& c : corpus) + { + const auto frame = CommandSerializer::packageDataForBt(c.payload, static_cast(c.dataType), c.seq); + const auto body = stripMarkers(frame); + + Buffer truncated(body.begin(), body.end() - 1); + require(tryUnpack(truncated) == Outcome::Recoverable, + "body truncated by one byte was not rejected: " + hexDump(frame)); + + Buffer headless(body.begin() + 1, body.end()); + require(tryUnpack(headless) == Outcome::Recoverable, + "body with first byte dropped was not rejected: " + hexDump(frame)); + + for (char extra : { (char)0x00, (char)SENTRY }) + { + Buffer extended = body; + extended.push_back(extra); + require(tryUnpack(extended) == Outcome::Recoverable, + "body extended by one byte was not rejected: " + hexDump(frame)); + } + + Buffer prefixed{ 0x00 }; + prefixed.insert(prefixed.end(), body.begin(), body.end()); + require(tryUnpack(prefixed) == Outcome::Recoverable, + "body with a prepended byte was not rejected: " + hexDump(frame)); + + require(tryUnpack(frame) == Outcome::Recoverable, + "frame with markers still attached was not rejected: " + hexDump(frame)); + cases += 6; + } + return cases; +} + +// P6: exhaustive single-byte corruption. Every replacement of every body byte +// (and every single-bit flip on a large frame) must be rejected with +// RecoverableException - never parsed, never a non-recoverable escape. +size_t testCorruptionRejection() +{ + size_t cases = 0; + const std::vector targets = { + { Buffer{}, 12, 0 }, + { Buffer{ 0x11, 0x22, 0x33 }, 1, 7 }, + { Buffer{ 60, 61, 62, 44, 45, 46 }, 12, 61 }, + { randomPayload(64), 13, 200 }, + }; + for (const auto& c : targets) + { + const auto frame = CommandSerializer::packageDataForBt(c.payload, static_cast(c.dataType), c.seq); + const auto body = stripMarkers(frame); + for (size_t pos = 0; pos < body.size(); pos++) + { + Buffer corrupted = body; + for (int v = 0; v <= 255; v++) + { + if (static_cast(v) == body[pos]) continue; + corrupted[pos] = static_cast(v); + const auto outcome = tryUnpack(corrupted); + if (outcome != Outcome::Recoverable) + { + std::ostringstream oss; + oss << (outcome == Outcome::Parsed ? "silently accepted" : "threw a non-recoverable error for") + << " a corrupted frame: pos " << pos << " -> " << v << " in body " << hexDump(body); + require(false, oss.str()); + } + g_checks++; + cases++; + } + } + } + + // Single-bit flips across a large frame (payload well past one MTU chunk + // of typical commands, still under the 2048 frame cap). + const auto bigPayload = randomPayload(512); + const auto bigFrame = CommandSerializer::packageDataForBt(bigPayload, DATA_TYPE::DATA_MDR, 1); + const auto bigBody = stripMarkers(bigFrame); + for (size_t pos = 0; pos < bigBody.size(); pos++) + { + Buffer corrupted = bigBody; + for (int bit = 0; bit < 8; bit++) + { + corrupted[pos] = static_cast(bigBody[pos] ^ (1 << bit)); + const auto outcome = tryUnpack(corrupted); + if (outcome != Outcome::Recoverable) + { + std::ostringstream oss; + oss << (outcome == Outcome::Parsed ? "silently accepted" : "threw a non-recoverable error for") + << " a bit-flipped frame: pos " << pos << " bit " << bit; + require(false, oss.str()); + } + g_checks++; + cases++; + } + } + return cases; +} + +// P7: the 2048 cap applies to the escaped frame, so the payload budget depends +// on content: plain bytes cost 1 wire byte, escapable bytes cost 2. +size_t testSizeBoundary() +{ + size_t cases = 0; + + // Plain payload: overhead is 9 bytes (2 markers + 6 header + 1 checksum, + // none of which escape for these inputs), so 2039 fits exactly and 2040 + // overflows. + checkRoundTrip({ Buffer(2039, 0x41), 12, 1 }); + const auto maxFrame = CommandSerializer::packageDataForBt(Buffer(2039, 0x41), DATA_TYPE::DATA_MDR, 1); + require(maxFrame.size() == MAX_BLUETOOTH_MESSAGE_SIZE, "largest plain payload did not produce an exactly full frame"); + cases++; + + for (size_t n : { 2040, 2100, 4096 }) + { + bool threw = false; + try { CommandSerializer::packageDataForBt(Buffer(n, 0x41), DATA_TYPE::DATA_MDR, 1); } + catch (const std::exception&) { threw = true; } + require(threw, "oversized plain payload was not rejected"); + cases++; + } + + // All-escapable payload: each byte costs two wire bytes, so the budget + // halves. 1016 bytes of 60 fits (frame 2041); 1020 does not (frame 2049). + checkRoundTrip({ Buffer(1016, 60), 12, 1 }); + cases++; + { + bool threw = false; + try { CommandSerializer::packageDataForBt(Buffer(1020, 60), DATA_TYPE::DATA_MDR, 1); } + catch (const std::exception&) { threw = true; } + require(threw, "oversized escape-heavy payload was not rejected despite escaping inflation"); + cases++; + } + return cases; +} +} + +int main() +{ + try + { + const auto corpus = buildCorpus(); + const auto roundTrips = testRoundTripCorpus(corpus); + const auto escapes = testEscapingTransparency(); + const auto seqs = testSeqDomain(); + const auto framings = testFraming(corpus); + const auto corruptions = testCorruptionRejection(); + const auto boundaries = testSizeBoundary(); + + std::cout << "Sony protocol metamorphic tests passed: " + << roundTrips << " round-trip, " + << escapes << " escaping, " + << seqs << " seq-domain, " + << framings << " framing, " + << corruptions << " corruption, " + << boundaries << " boundary cases (" + << g_checks << " checks)\n"; + return 0; + } + catch (const std::exception& e) + { + std::cerr << "METAMORPHIC TEST FAILURE: " << e.what() << "\n"; + return 1; + } +} diff --git a/Client/tests/run-macos.sh b/Client/tests/run-macos.sh index 70705689..ab8dff7b 100755 --- a/Client/tests/run-macos.sh +++ b/Client/tests/run-macos.sh @@ -4,6 +4,7 @@ set -eu client_dir=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd) test_binary="${TMPDIR:-/tmp}/sonybridge-xm4-protocol-tests" conformance_binary="${TMPDIR:-/tmp}/sonybridge-protocol-conformance-tests" +metamorphic_binary="${TMPDIR:-/tmp}/sonybridge-metamorphic-protocol-tests" clang++ -std=c++20 -pthread -I"$client_dir" \ "$client_dir/tests/HeadphonesProtocolTests.cpp" \ @@ -22,3 +23,11 @@ clang++ -std=c++20 -Wall -Wextra -Werror -I"$client_dir" \ -o "$conformance_binary" "$conformance_binary" "$client_dir/tests/conformance/fixtures/xm4_v1_frames.golden" + +clang++ -std=c++20 -Wall -Wextra -Werror -I"$client_dir" \ + "$client_dir/tests/MetamorphicProtocolTests.cpp" \ + "$client_dir/ByteMagic.cpp" \ + "$client_dir/CommandSerializer.cpp" \ + -o "$metamorphic_binary" + +"$metamorphic_binary" From 3ae5709fd93512eb96cf7263404ac8c2867e1c5b Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Aug 2026 07:40:59 -0400 Subject: [PATCH 07/35] Bound the macOS connector's receive queue and drop zero-length frames The RFCOMM data delegate buffered every frame unconditionally, but recv() only drains the queue during a command exchange, so a device streaming unsolicited frames grew receivedBytes without bound. Cap the buffered total at RECEIVE_BUFFER_CAP, dropping the oldest chunks; the wrapper's marker scan resynchronizes on what survives. A zero-length frame also made recv() return 0, which BluetoothWrapper reads as a closed connection - drop those at the delegate boundary instead of fabricating a disconnect. Covered by new offline tests that inject frames exactly as the delegate would, with no Bluetooth channel opened. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MnKJraRSytaMh5E2G57ifx --- Client/macos/MacOSBluetoothConnector.h | 12 ++++ Client/macos/MacOSBluetoothConnector.mm | 36 +++++++--- Client/tests/MacConnectorBufferTests.mm | 93 +++++++++++++++++++++++++ Client/tests/run-macos.sh | 10 +++ 4 files changed, 142 insertions(+), 9 deletions(-) create mode 100644 Client/tests/MacConnectorBufferTests.mm diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h index 3e3f42ad..994c76c6 100644 --- a/Client/macos/MacOSBluetoothConnector.h +++ b/Client/macos/MacOSBluetoothConnector.h @@ -28,6 +28,16 @@ class MacOSBluetoothConnector final : public IBluetoothConnector // on the connector thread, so it must only signal shutdown; joining that same thread would abort. void handleChannelClosed() noexcept; + // Called by the Objective-C RFCOMM delegate for every received data frame. Drops zero-length + // frames (recv() returning 0 reads as "connection closed" upstream) and caps the total buffered + // bytes so a device streaming unsolicited frames while nothing is reading can't grow memory + // without bound. Public so the offline buffer tests can drive it without a live channel. + void enqueueReceivedData(const unsigned char* data, size_t length); + + // recv() only runs during a command exchange, so the queue must be bounded. Protocol frames are + // at most MAX_BLUETOOTH_MESSAGE_SIZE; 16 of them is far more than any legitimate burst. + static constexpr size_t RECEIVE_BUFFER_CAP = MAX_BLUETOOTH_MESSAGE_SIZE * 16; + virtual std::vector getConnectedDevices() noexcept(false); std::deque> receivedBytes; std::mutex receiveDataMutex; @@ -43,4 +53,6 @@ class MacOSBluetoothConnector final : public IBluetoothConnector void *rfcommDevice = nullptr; std::atomic rfcommchannel{nullptr}; std::thread uthread; + //Total bytes across receivedBytes; guarded by receiveDataMutex. + size_t receivedBytesTotal = 0; }; diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 4327f978..7cc6c147 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -34,13 +34,7 @@ - (void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel stat -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength { - std::lock_guard g(delegateCPP->receiveDataMutex); - - unsigned char* buffer = (unsigned char*)dataPointer; - std::vector vectorBuffer(buffer, buffer+dataLength); - - delegateCPP->receivedBytes.push_back(vectorBuffer); - delegateCPP->receiveDataConditionVariable.notify_one(); + delegateCPP->enqueueReceivedData((const unsigned char*)dataPointer, dataLength); } @@ -181,6 +175,27 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) } } +void MacOSBluetoothConnector::enqueueReceivedData(const unsigned char* data, size_t length) +{ + // A zero-length RFCOMM frame carries no message bytes; queuing it would make recv() return 0, + // which BluetoothWrapper treats as a closed connection. + if (length == 0) return; + + std::lock_guard g(receiveDataMutex); + receivedBytes.emplace_back(data, data + length); + receivedBytesTotal += length; + + // Nothing drains the queue between command exchanges, so a flooding device would otherwise grow + // it without bound. Drop the oldest chunks past the cap (never the newest one); the wrapper's + // START/END marker scan resynchronizes on whatever survives. + while (receivedBytesTotal > RECEIVE_BUFFER_CAP && receivedBytes.size() > 1) { + receivedBytesTotal -= receivedBytes.front().size(); + receivedBytes.pop_front(); + } + + receiveDataConditionVariable.notify_one(); +} + int MacOSBluetoothConnector::recv(char* buf, size_t length) { // wait for newly received data, but time out so an unanswered inquiry (probing an unsupported @@ -198,16 +213,18 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) // fill the buf with the new data std::vector receivedVector = receivedBytes.front(); receivedBytes.pop_front(); - + receivedBytesTotal -= receivedVector.size(); + size_t lengthCopied = std::min(length, receivedVector.size()); // copy the first amount of bytes std::memcpy(buf, receivedVector.data(), lengthCopied); - + // too much data, save it for next time if (receivedVector.size() > length){ receivedVector.erase(receivedVector.begin(), receivedVector.begin() + lengthCopied); receivedBytes.push_front(receivedVector); + receivedBytesTotal += receivedVector.size(); } #ifdef SHC_DEBUG_PROTOCOL @@ -259,6 +276,7 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) std::lock_guard g(receiveDataMutex); receivedBytes.clear(); + receivedBytesTotal = 0; } void MacOSBluetoothConnector::closeConnection() { // Only one close path owns the channel pointer. A remote-close callback clears it first. diff --git a/Client/tests/MacConnectorBufferTests.mm b/Client/tests/MacConnectorBufferTests.mm new file mode 100644 index 00000000..c7217215 --- /dev/null +++ b/Client/tests/MacConnectorBufferTests.mm @@ -0,0 +1,93 @@ +// Offline tests for MacOSBluetoothConnector's receive buffering (enqueueReceivedData/recv). +// No RFCOMM channel is ever opened; frames are injected exactly as the IOBluetooth data +// delegate would deliver them. + +#include "MacOSBluetoothConnector.h" + +#include +#include +#include +#include +#include + +namespace +{ +void require(bool condition, const char* message) +{ + if (!condition) throw std::runtime_error(message); +} + +size_t bufferedTotal(MacOSBluetoothConnector& connector) +{ + std::lock_guard g(connector.receiveDataMutex); + size_t total = 0; + for (const auto& chunk : connector.receivedBytes) total += chunk.size(); + return total; +} +} + +int main() +{ + // A zero-length frame must be dropped: recv() returning 0 reads as "connection closed" in + // BluetoothWrapper, so buffering it would fabricate a disconnect. + { + MacOSBluetoothConnector connector; + connector.running = true; + connector.enqueueReceivedData(nullptr, 0); + require(connector.receivedBytes.empty(), "zero-length frame was buffered"); + + const unsigned char payload[] = { 0x3e, 0x01, 0x02, 0x3c }; + connector.enqueueReceivedData(payload, sizeof(payload)); + char buf[16] = { 0 }; + int numRecvd = connector.recv(buf, sizeof(buf)); + require(numRecvd == 4 && std::memcmp(buf, payload, 4) == 0, + "frame after a zero-length frame was not delivered intact"); + } + + // A device streaming unsolicited frames while nothing is reading must not grow the buffer + // without bound; the oldest chunks are dropped and the newest survive. + { + MacOSBluetoothConnector connector; + connector.running = true; + std::vector chunk(1000); + for (int i = 0; i < 200; i++) + { + std::fill(chunk.begin(), chunk.end(), (unsigned char)i); + connector.enqueueReceivedData(chunk.data(), chunk.size()); + } + require(bufferedTotal(connector) <= MacOSBluetoothConnector::RECEIVE_BUFFER_CAP, + "receive buffer exceeded RECEIVE_BUFFER_CAP under flood"); + require(!connector.receivedBytes.empty() && connector.receivedBytes.back().front() == 199, + "flood dropped the newest chunk instead of the oldest"); + } + + // Splitting an oversized chunk across recv() calls must keep the byte accounting consistent, + // so the cap still holds after partial reads. + { + MacOSBluetoothConnector connector; + connector.running = true; + std::vector big(3000); + std::iota(big.begin(), big.end(), 0); + connector.enqueueReceivedData(big.data(), big.size()); + + char buf[2048]; + int first = connector.recv(buf, sizeof(buf)); + require(first == 2048 && (unsigned char)buf[2047] == (unsigned char)2047, + "first partial read returned wrong data"); + require(bufferedTotal(connector) == 3000 - 2048, "split remainder was not re-buffered"); + + int second = connector.recv(buf, sizeof(buf)); + require(second == 3000 - 2048 && (unsigned char)buf[0] == (unsigned char)2048, + "second partial read returned wrong data"); + require(bufferedTotal(connector) == 0, "buffer not empty after draining the split chunk"); + + // The cap must still be measured correctly after the split bookkeeping. + std::vector chunk(1000); + for (int i = 0; i < 200; i++) connector.enqueueReceivedData(chunk.data(), chunk.size()); + require(bufferedTotal(connector) <= MacOSBluetoothConnector::RECEIVE_BUFFER_CAP, + "receive buffer exceeded the cap after split reads"); + } + + std::cout << "macOS connector receive-buffer tests passed\n"; + return 0; +} diff --git a/Client/tests/run-macos.sh b/Client/tests/run-macos.sh index 70705689..a9f63c30 100755 --- a/Client/tests/run-macos.sh +++ b/Client/tests/run-macos.sh @@ -4,6 +4,7 @@ set -eu client_dir=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd) test_binary="${TMPDIR:-/tmp}/sonybridge-xm4-protocol-tests" conformance_binary="${TMPDIR:-/tmp}/sonybridge-protocol-conformance-tests" +mac_connector_binary="${TMPDIR:-/tmp}/sonybridge-mac-connector-buffer-tests" clang++ -std=c++20 -pthread -I"$client_dir" \ "$client_dir/tests/HeadphonesProtocolTests.cpp" \ @@ -22,3 +23,12 @@ clang++ -std=c++20 -Wall -Wextra -Werror -I"$client_dir" \ -o "$conformance_binary" "$conformance_binary" "$client_dir/tests/conformance/fixtures/xm4_v1_frames.golden" + +# Offline receive-buffer tests for the macOS connector (no Bluetooth channel is opened). +clang++ -std=c++20 -fobjc-arc -pthread -I"$client_dir" -I"$client_dir/macos" \ + "$client_dir/tests/MacConnectorBufferTests.mm" \ + "$client_dir/macos/MacOSBluetoothConnector.mm" \ + -framework IOBluetooth -framework Foundation \ + -o "$mac_connector_binary" + +"$mac_connector_binary" From 135e1d5f44a42b7abc8cbf0d440d74c63e0b5b2a Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Aug 2026 07:40:59 -0400 Subject: [PATCH 08/35] Guard against a nil addressString before building the connect address [[device addressString] UTF8String] on a nil addressString hands std::string a null char*, which is undefined behaviour. getConnectedDevices() already guards the same call; apply the same check on the scan-and-connect path. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MnKJraRSytaMh5E2G57ifx --- Client/macos/HeadphonesBridge.mm | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Client/macos/HeadphonesBridge.mm b/Client/macos/HeadphonesBridge.mm index 4f2bbc74..d4ace713 100644 --- a/Client/macos/HeadphonesBridge.mm +++ b/Client/macos/HeadphonesBridge.mm @@ -164,8 +164,16 @@ - (void)scanAndConnectWithCompletion:(void (^)(BOOL, NSString * _Nullable))compl return; } + // A device without an address string would hand std::string a null char* below (undefined + // behaviour); getConnectedDevices() applies the same guard. + NSString *address = [device addressString]; + if (!address) { + completion(NO, @"The selected device has no Bluetooth address."); + return; + } + try { - _bt->connect([[device addressString] UTF8String]); + _bt->connect([address UTF8String]); } catch (RecoverableException &exc) { completion(NO, @(exc.what())); return; From 27398a84af750a6a1753e90a4880b8147965d66d Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Aug 2026 08:12:49 -0400 Subject: [PATCH 09/35] perf(macos): coalesce slider drags to latest-value sends Every integer step of an ambient-level or custom-EQ slider drag was enqueuing a full Bluetooth exchange on the serial command queue (~70ms measured per exchange, up to 2500ms worst-case each), so a 20-step drag queued ~1.4s+ of stale intermediate sends that kept hitting the headset after the user released. HeadphonesModel now mirrors the in-flight gate the ImGui client already uses (CrossPlatformGUI _sendFeatureCommand): the first change sends immediately; changes arriving while an exchange is in flight only overwrite a pending snapshot; when the exchange completes, at most one more send fires, and only if the pending snapshot differs from what was last sent. The pending value is an explicit snapshot (not re-read from the model at completion time) so syncFromBridge or the 2s poll overwriting @Published state cannot clobber the user's latest drag value. All gate state is main-thread-confined - bridge completions arrive on the main queue - so no locks are needed. Isomorphism: end-state is unchanged - the user's final value always reaches the device (on failure with a newer pending value, the pending value is still sent; pending is cleared before resending so it is never sent twice), single clicks still send immediately with no added latency, and a drag now costs <=2-3 exchanges instead of one per step. Discrete controls (mode buttons, toggles) are untouched. disconnect() drops pending snapshots so an intentional disconnect does not fire a doomed resend. Verified: 4 macOS test suites green (protocol safety, 18 golden, 56109 metamorphic checks, connector buffer), 12s fuzz smoke exit 0, Release xcodebuild clean with no new warnings. Co-Authored-By: Claude Opus 4.8 --- Client/macos/HeadphonesModel.swift | 49 ++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index 414053bb..bcf9b2ff 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -49,6 +49,15 @@ final class HeadphonesModel: ObservableObject { private var pollTimer: Timer? private var dynamicTimer: Timer? + // Slider-drag coalescing (mirrors the ImGui in-flight gate in CrossPlatformGUI). + // While an exchange is in flight, only the latest value is remembered; when the + // exchange completes, at most one more send fires with that latest value. All + // state is main-thread-confined (bridge completions arrive on the main queue). + private var pushInFlight = false + private var pendingPush: (mode: SHCAmbientMode, level: Int, focusVoice: Bool)? + private var eqInFlight = false + private var pendingEq: (bass: Int, bands: [Int])? + func connect() { connecting = true errorMessage = nil @@ -151,7 +160,24 @@ final class HeadphonesModel: ObservableObject { func applyCustomEq() { eqPreset = 0xA0 errorMessage = nil - bridge.setCustomEqualizerBass(clearBass, bands: eqBands.map { NSNumber(value: $0) }) { ok, error in + if eqInFlight { + pendingEq = (clearBass, eqBands) + return + } + sendCustomEq((clearBass, eqBands)) + } + + private func sendCustomEq(_ sent: (bass: Int, bands: [Int])) { + eqInFlight = true + bridge.setCustomEqualizerBass(sent.bass, bands: sent.bands.map { NSNumber(value: $0) }) { ok, error in + self.eqInFlight = false + if let pending = self.pendingEq { + self.pendingEq = nil + if pending != sent { + self.sendCustomEq(pending) + return + } + } if !ok, let error = error { self.errorMessage = error } } } @@ -167,6 +193,8 @@ final class HeadphonesModel: ObservableObject { func disconnect() { stopWatchingConnection() stopDynamicPolling() + pendingPush = nil + pendingEq = nil bridge.disconnect() connected = false deviceName = "" @@ -210,7 +238,24 @@ final class HeadphonesModel: ObservableObject { private func pushState() { errorMessage = nil - bridge.applyMode(mode, level: ambientLevel, focusVoice: focusOnVoice) { ok, error in + if pushInFlight { + pendingPush = (mode, ambientLevel, focusOnVoice) + return + } + sendPush((mode, ambientLevel, focusOnVoice)) + } + + private func sendPush(_ sent: (mode: SHCAmbientMode, level: Int, focusVoice: Bool)) { + pushInFlight = true + bridge.applyMode(sent.mode, level: sent.level, focusVoice: sent.focusVoice) { ok, error in + self.pushInFlight = false + if let pending = self.pendingPush { + self.pendingPush = nil + if pending != sent { + self.sendPush(pending) + return + } + } if ok { self.syncFromBridge() } else if let error = error { From 1750b7a6701724adc1a4187bddeb7f1f736b2034 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Aug 2026 08:16:43 -0400 Subject: [PATCH 10/35] perf(macos): gate @Published writes to real changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every 2s poll tick and every interaction completion wrote 8-12 @Published properties unconditionally; each setter fires objectWillChange, so the whole ContentView body re-evaluated every tick even when nothing changed. The wire poll only refreshes ambient state, so most per-tick writes (EQ/DSEE re-read from cached bridge values) were provably no-ops that still forced a full re-render — the recurring 0.4-1.2% idle CPU blips in .hotspots/evidence/connected_idle_cpu_series.txt, pure waste on battery. Mechanism: a generic assignIfChanged(keyPath, value) helper writes a @Published property only when the new value differs from the current one, applied to both the refreshDynamic poll completion and syncFromBridge. The eqBands candidate array is still built the same way, then compared before assignment instead of assigned unconditionally. Isomorphism: reads, read order, and poll cadence are untouched — only writes became conditional. Equal value -> no write -> visible state identical; different value -> write fires exactly as before, so every device-side change still lands in the UI on the same tick it did before. The slider-coalescing convergence from the previous commit is preserved: after a successful push, syncFromBridge still overwrites mode/ambientLevel whenever device truth differs from the UI, and skipping the write when they are equal is indistinguishable. First sync after connect still fires every write, since all values transition from their defaults. Verified: 4 test suites green, fuzz smoke exit 0, Release build succeeded. Co-Authored-By: Claude Opus 4.8 --- Client/macos/HeadphonesModel.swift | 49 ++++++++++++++++++------------ 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index bcf9b2ff..4b111e2a 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -120,21 +120,30 @@ final class HeadphonesModel: ObservableObject { bridge.setAdaptiveVolume(on) { ok, error in if !ok, let e = error { self.errorMessage = e } } } + // Every @Published setter fires objectWillChange — and a full ContentView body + // re-evaluation — even when the value is unchanged. The 2s poll mostly re-reads + // cached bridge values, so gate writes to real changes. + private func assignIfChanged(_ keyPath: ReferenceWritableKeyPath, _ newValue: T) { + if self[keyPath: keyPath] != newValue { + self[keyPath: keyPath] = newValue + } + } + // Poll the button-changeable state so the app stays in sync when you use the headphone's own controls. private func startDynamicPolling() { stopDynamicPolling() dynamicTimer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { [weak self] _ in guard let self = self, self.connected else { return } self.bridge.refreshDynamic { - self.mode = self.bridge.mode + self.assignIfChanged(\.mode, self.bridge.mode) let level = self.bridge.ambientLevel - if level > 0 { self.ambientLevel = level } - self.eqPreset = self.bridge.eqPreset - self.supportsEqualizer = self.bridge.supportsEqualizer - self.clearBass = self.bridge.clearBass - self.supportsDsee = self.bridge.supportsDsee - self.dsee = self.bridge.dsee - self.eqBands = (0..<5).map { self.bridge.equalizerBand(at: $0) } + if level > 0 { self.assignIfChanged(\.ambientLevel, level) } + self.assignIfChanged(\.eqPreset, self.bridge.eqPreset) + self.assignIfChanged(\.supportsEqualizer, self.bridge.supportsEqualizer) + self.assignIfChanged(\.clearBass, self.bridge.clearBass) + self.assignIfChanged(\.supportsDsee, self.bridge.supportsDsee) + self.assignIfChanged(\.dsee, self.bridge.dsee) + self.assignIfChanged(\.eqBands, (0..<5).map { self.bridge.equalizerBand(at: $0) }) } } } @@ -265,18 +274,18 @@ final class HeadphonesModel: ObservableObject { } private func syncFromBridge() { - connected = bridge.connected - deviceName = bridge.deviceName ?? "" - deviceMac = bridge.deviceMac ?? "" - protocolVersion = bridge.protocolVersionString ?? "" - supportsVpt = bridge.supportsVpt - supportsEqualizer = bridge.supportsEqualizer - supportsDsee = bridge.supportsDsee - maxAmbientLevel = bridge.maxAmbientLevel - mode = bridge.mode + assignIfChanged(\.connected, bridge.connected) + assignIfChanged(\.deviceName, bridge.deviceName ?? "") + assignIfChanged(\.deviceMac, bridge.deviceMac ?? "") + assignIfChanged(\.protocolVersion, bridge.protocolVersionString ?? "") + assignIfChanged(\.supportsVpt, bridge.supportsVpt) + assignIfChanged(\.supportsEqualizer, bridge.supportsEqualizer) + assignIfChanged(\.supportsDsee, bridge.supportsDsee) + assignIfChanged(\.maxAmbientLevel, bridge.maxAmbientLevel) + assignIfChanged(\.mode, bridge.mode) let level = bridge.ambientLevel - if level > 0 { ambientLevel = level } - focusOnVoice = bridge.focusOnVoice - focusOnVoiceAvailable = bridge.focusOnVoiceAvailable + if level > 0 { assignIfChanged(\.ambientLevel, level) } + assignIfChanged(\.focusOnVoice, bridge.focusOnVoice) + assignIfChanged(\.focusOnVoiceAvailable, bridge.focusOnVoiceAvailable) } } From 6f5aecedc9a553b33192f636de52858d2af2c42a Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Aug 2026 08:20:25 -0400 Subject: [PATCH 11/35] =?UTF-8?q?build(macos):=20pin=20Release=20codegen?= =?UTF-8?q?=20=E2=80=94=20-O2,=20dead-strip,=20wholemodule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Release configuration never chose a C++/ObjC++ optimization level: GCC_OPTIMIZATION_LEVEL was absent (Xcode default -Os), DEAD_CODE_STRIPPING resolved to NO, and SWIFT_COMPILATION_MODE was unpinned. Every C++ profile of the protocol stack was bounded by unchosen codegen (HOTSPOTS rank 3). Changes (Release blocks only, Debug untouched): - project-level Release: GCC_OPTIMIZATION_LEVEL = 2 (explicit -O2 — deliberate speed-over-size for the protocol paths; -O3 skipped, no measured win to justify vectorization bloat) - project-level Release: DEAD_CODE_STRIPPING = YES - target-level Release: SWIFT_COMPILATION_MODE = wholemodule (pins the Xcode-default; SWIFT_OPTIMIZATION_LEVEL already -O) Considered and skipped: LTO (unmeasured benefit vs real build-time and debuggability cost), C++ standard cleanup (gnu++14 vs c++17 hygiene, not this pass's lever). Isomorphism: config-only, zero source changes — -O2 vs -Os is a codegen-level change with identical observable semantics, and dead-code stripping removes only unreferenced symbols. Verification: - Resolved Release (was: GCC_OPTIMIZATION_LEVEL unset, DEAD_CODE_STRIPPING = NO, no SWIFT_COMPILATION_MODE) → now GCC_OPTIMIZATION_LEVEL = 2, DEAD_CODE_STRIPPING = YES, SWIFT_COMPILATION_MODE = wholemodule - Resolved Debug unchanged (0 / NO / -Onone) - Clean Release build: BUILD SUCCEEDED, no new warnings - Binary: 853,392 → 730,304 bytes (-14.4%; dead-strip outweighs -O2 growth) - Tests: all 4 suites green (protocol safety, 18 golden, 56,109 metamorphic checks, connector buffer); fuzz smoke exit 0 Co-Authored-By: Claude Opus 4.8 --- Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj index 2ce1c62e..7079b2ce 100644 --- a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj +++ b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj @@ -302,11 +302,13 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 2; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -378,6 +380,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; SWIFT_VERSION = 5.0; SWIFT_OBJC_BRIDGING_HEADER = "SonyHeadphonesClient-Bridging-Header.h"; + SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; }; name = Release; From e1679a9b0d2a8b03a0d8b9a01be44560d43f3661 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Aug 2026 08:27:23 -0400 Subject: [PATCH 12/35] perf(macos): connector thread waits on disconnect instead of pumping a sourceless run loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live profiling (10s @1ms, connected to a physical XM4) proved the connectToMac pump loop dead weight: all 8537/8537 connector-thread samples sat in __psynch_cvwait at the wait_for, zero in the runUntilDate pump, while inbound RFCOMM data was delivered by -[IOBluetoothRFCOMMChannel stream:handleEvent:] on the MAIN thread's run loop (CFSocket source scheduled there). The connector thread's run loop has no sources; it never delivered anything. Change: replace the 100ms-pump/1000ms-timed-poll alternation with a plain cv wait on running. Removing the timed re-poll unmasks a lost-wakeup race (running is atomic, stored lock-free by notifiers; a notify landing between the waiter's predicate check and its block was previously bounded at 1s, now would sleep forever), so every running=false setter — disconnect(), handleChannelClosed(), connect()'s catch — now stores under disconnectionMutex before notifying. Hazards traced: 1. Channel lifetime: the wait keeps connectToMac's frame (and its strong `channel` ref) alive exactly as the loop did; release ordering at frame exit vs running=false/notify unchanged. closeConnection() retains its own strong ref before closeChannel; disconnect() still joins before the connector object is destroyed (destructor + connect() catch paths). 2. Open-complete: connectPromise.set_value() fires synchronously after openRFCOMMChannelAsync returns success, before the wait — connect() never depended on the delegate callback; rfcommChannelOpenComplete: exists only under SHC_DEBUG_PROTOCOL and only logs. All delegate callbacks arrive on main (profiled), so the pump was load-bearing for nothing. 3. connect() error path kept coherent: catch stores running=false under the mutex like the other setters. 4. recv()'s receiveDataConditionVariable path untouched. Isomorphism: connect, data flow, and disconnect end states unchanged (data never flowed through this thread). Disconnect wakeup is now immediate instead of worst-case ~1s, and the thread does zero spurious wakeups (was ~2/s). Offline test added: both running=false setters wake the exact connectToMac wait, 200 interleavings, lost wakeup = test failure. Verified: 4 test suites green, FUZZ_SECONDS=10 fuzz exit 0, Release xcodebuild BUILD SUCCEEDED. Co-Authored-By: Claude Opus 4.8 --- Client/macos/MacOSBluetoothConnector.h | 5 ++-- Client/macos/MacOSBluetoothConnector.mm | 37 +++++++++++++++++-------- Client/tests/MacConnectorBufferTests.mm | 37 +++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 13 deletions(-) diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h index 994c76c6..bcb5a898 100644 --- a/Client/macos/MacOSBluetoothConnector.h +++ b/Client/macos/MacOSBluetoothConnector.h @@ -24,8 +24,9 @@ class MacOSBluetoothConnector final : public IBluetoothConnector virtual void closeConnection(); virtual SonyProtocolVersion getProtocolVersion() noexcept; - // Called by the Objective-C RFCOMM delegate when the peer closes the channel. This callback runs - // on the connector thread, so it must only signal shutdown; joining that same thread would abort. + // Called by the Objective-C RFCOMM delegate when the peer closes the channel. Delegate callbacks + // are delivered on the main thread's run loop (the connector thread never pumps one), so this + // must only signal shutdown; disconnect()'s close-and-join runs on whichever thread invokes it. void handleChannelClosed() noexcept; // Called by the Objective-C RFCOMM delegate for every received data frame. Drops zero-length diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 7cc6c147..6e863454 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -130,15 +130,15 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) // tell the other tread that we are done connecting connectPromise.set_value(); - // keep thread running, until we are disconnected + // Park until disconnect. Every delegate callback (data and channel-closed) is delivered on + // the main thread's run loop — this thread's run loop has no sources, so there is nothing + // to pump here. This frame's `channel` reference keeps the RFCOMM channel alive for the + // whole connection; the wait returns exactly once, when a running=false setter notifies. + // Setters must store running=false while holding disconnectionMutex (see disconnect()), + // or a notify landing between this predicate check and the block would be lost forever. std::unique_lock lk(macOSBluetoothConnector->disconnectionMutex); - while (macOSBluetoothConnector->running) { - [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:.1]]; - - macOSBluetoothConnector->disconnectionConditionVariable.wait_for( - lk, std::chrono::milliseconds(1000), - [&]() { return !macOSBluetoothConnector->running; }); - } + macOSBluetoothConnector->disconnectionConditionVariable.wait( + lk, [&]() { return !macOSBluetoothConnector->running; }); lk.unlock(); } @@ -167,7 +167,12 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) try { connectFuture.get(); } catch (...) { - running = false; + // running=false must be stored under disconnectionMutex: connectToMac's untimed wait + // would otherwise miss a notify racing its predicate check and never wake. + { + std::lock_guard g(disconnectionMutex); + running = false; + } disconnectionConditionVariable.notify_all(); receiveDataConditionVariable.notify_all(); if (uthread.joinable()) uthread.join(); @@ -259,7 +264,12 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) void MacOSBluetoothConnector::disconnect() noexcept { - running = false; + // running=false must be stored under disconnectionMutex: connectToMac's untimed wait + // would otherwise miss a notify racing its predicate check and never wake. + { + std::lock_guard g(disconnectionMutex); + running = false; + } disconnectionConditionVariable.notify_all(); receiveDataConditionVariable.notify_all(); closeConnection(); @@ -290,7 +300,12 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) void MacOSBluetoothConnector::handleChannelClosed() noexcept { rfcommchannel.store(nullptr); - running = false; + // running=false must be stored under disconnectionMutex: connectToMac's untimed wait + // would otherwise miss a notify racing its predicate check and never wake. + { + std::lock_guard g(disconnectionMutex); + running = false; + } disconnectionConditionVariable.notify_all(); receiveDataConditionVariable.notify_all(); } diff --git a/Client/tests/MacConnectorBufferTests.mm b/Client/tests/MacConnectorBufferTests.mm index c7217215..3c913882 100644 --- a/Client/tests/MacConnectorBufferTests.mm +++ b/Client/tests/MacConnectorBufferTests.mm @@ -4,10 +4,13 @@ #include "MacOSBluetoothConnector.h" +#include #include +#include #include #include #include +#include #include namespace @@ -88,6 +91,40 @@ int main() "receive buffer exceeded the cap after split reads"); } + // The connector thread parks in an untimed wait on disconnectionConditionVariable until + // running goes false (connectToMac). There is no timed re-poll anymore, so every + // running=false setter must store under disconnectionMutex before notifying — a notify + // landing between the waiter's predicate check and its block would otherwise be lost + // forever. Drive both setters against the exact wait connectToMac performs; iterating + // samples the race window at different waiter/setter interleavings. + { + for (int i = 0; i < 200; i++) + { + MacOSBluetoothConnector connector; + connector.running = true; + + std::promise wokePromise; + std::future woke = wokePromise.get_future(); + std::thread waiter([&] { + std::unique_lock lk(connector.disconnectionMutex); + connector.disconnectionConditionVariable.wait(lk, [&] { return !connector.running; }); + wokePromise.set_value(); + }); + + if (i % 2 == 0) + connector.disconnect(); + else + connector.handleChannelClosed(); + + if (woke.wait_for(std::chrono::seconds(2)) != std::future_status::ready) + { + waiter.detach(); + throw std::runtime_error("disconnect wakeup lost: waiter still parked after 2s"); + } + waiter.join(); + } + } + std::cout << "macOS connector receive-buffer tests passed\n"; return 0; } From 9efdd24570fbcb9ee4670ed2a1e30b34a25a0d63 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Aug 2026 08:32:41 -0400 Subject: [PATCH 13/35] feat(macos): keep Speak-to-Chat off by default on connect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Speak-to-Chat pauses audio whenever the mics hear speech, which is hostile to anyone who dictates constantly — every utterance stops the music. This adds a persisted preference (UserDefaults key KeepSpeakToChatOffOnConnect) that forces S2C off once per connect. Mechanism: connect() arms a per-connection flag; the refreshStatus completion — which fires a second time after probeCapabilities confirms optional features — consumes the flag the first time hasSpeakToChat is true, and only then sends a single setSpeakToChat(false) if the pref is on and the device reports S2C enabled. Devices without S2C, or with it already off, never receive a write; the flag also clears on disconnect, so the disable fires at most once per connection. The manual toggle is untouched: turning S2C on mid-session sticks until the next connect. The pref defaults to true per this build's user request; upstream may prefer defaulting to false — it's a one-line change (the `?? true` in HeadphonesModel.swift). The secondary "Keep off on connect" toggle sits under the S2C switch and is hidden with it when the capability is absent, matching the existing gating pattern. Co-Authored-By: Claude Opus 4.8 --- Client/macos/ContentView.swift | 8 ++++++++ Client/macos/HeadphonesModel.swift | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/Client/macos/ContentView.swift b/Client/macos/ContentView.swift index 87956c13..526fefbd 100644 --- a/Client/macos/ContentView.swift +++ b/Client/macos/ContentView.swift @@ -353,6 +353,14 @@ struct ContentView: View { if model.hasSpeakToChat { settingToggle("Speak-to-Chat", "Pause music when you talk", on: model.speakToChat) { model.setSpeakToChat($0) } + Toggle(isOn: $model.keepSpeakToChatOff) { + Text("Keep off on connect") + .font(.system(size: 11)) + .foregroundColor(Theme.secondary) + } + .toggleStyle(SwitchToggleStyle(tint: Theme.accent)) + .controlSize(.small) + .padding(.leading, 12) } if model.hasAutoPowerOff { HStack { diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index 4b111e2a..dee5165c 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -6,6 +6,8 @@ import Foundation import Combine +private let keepSpeakToChatOffKey = "KeepSpeakToChatOffOnConnect" + final class HeadphonesModel: ObservableObject { private let bridge = HeadphonesBridge() @@ -39,6 +41,11 @@ final class HeadphonesModel: ObservableObject { @Published var codec = "" @Published var hasSpeakToChat = false @Published var speakToChat = false + // Force Speak-to-Chat off each time we connect (it pauses audio whenever it hears + // speech, which is hostile to dictation). Flipping this takes effect next connect. + @Published var keepSpeakToChatOff = UserDefaults.standard.object(forKey: keepSpeakToChatOffKey) as? Bool ?? true { + didSet { UserDefaults.standard.set(keepSpeakToChatOff, forKey: keepSpeakToChatOffKey) } + } @Published var hasAdaptiveVolume = false @Published var adaptiveVolume = false @Published var deviceMac = "" @@ -58,6 +65,10 @@ final class HeadphonesModel: ObservableObject { private var eqInFlight = false private var pendingEq: (bass: Int, bands: [Int])? + // Armed on each successful connect; consumed once Speak-to-Chat capability is + // confirmed, so the off-on-connect enforcement fires at most once per connection. + private var s2cAutoDisablePending = false + func connect() { connecting = true errorMessage = nil @@ -66,6 +77,7 @@ final class HeadphonesModel: ObservableObject { self.bridge.scanAndConnect { ok, error in self.connecting = false if ok { + self.s2cAutoDisablePending = true self.syncFromBridge() self.startWatchingConnection() self.refreshStatus() @@ -99,6 +111,15 @@ final class HeadphonesModel: ObservableObject { self.speakToChat = self.bridge.speakToChat self.hasAdaptiveVolume = self.bridge.hasAdaptiveVolume self.adaptiveVolume = self.bridge.adaptiveVolume + // Speak-to-Chat capability is only confirmed by the probeCapabilities pass + // (the second completion), so this stays armed until then and fires at most + // once per connect. The device stays untouched unless it reports S2C on. + if self.s2cAutoDisablePending && self.hasSpeakToChat { + self.s2cAutoDisablePending = false + if self.keepSpeakToChatOff && self.speakToChat { + self.setSpeakToChat(false) + } + } } } @@ -204,6 +225,7 @@ final class HeadphonesModel: ObservableObject { stopDynamicPolling() pendingPush = nil pendingEq = nil + s2cAutoDisablePending = false bridge.disconnect() connected = false deviceName = "" From 558d274bfc756e6dec6e8e67d8eb9ae52b319333 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Aug 2026 08:49:56 -0400 Subject: [PATCH 14/35] feat: multipoint (connect to 2 devices) toggle v2 devices only, byte layout proven by Gadgetbridge on the WH-ULT900N (ULT WEAR): commits 8cbc309346 ("WIP add ConnectTwoDevices feature"), e8520865f3 ("fix: setting Connect Two Devices"), 5d7b37d1b7 ("fix read Connect Two Devices"), files SonyProtocolImplV2.java and SonyHeadphonesProtocol.java. State rides touch-sensor subtype d1 with an inverted enable bit (GET d6 d1 -> RET d7 d1 00 <00=on/01=off>); a SET sends d8 d1 00 <00=on/01=off> then the fixed apply commit 98 00 06 01 for both directions. The system-control RET (97 00 06) always reports 01 and is never used as a state source. v1 (WH-1000XM4) gets no multipoint on purpose: Gadgetbridge's SonyProtocolImplV1 explicitly logs "Connect two devices not implemented for V1" and returns null, so no proven v1 frames exist. The v1 test now asserts the XM4 path never emits any multipoint opcode and that setMultipoint throws. The probe (d6 d1) is appended to the v2 probeCapabilities sequence; the toggle is capability-gated and mirrors the device-persistent state with no app-enforced default. Full research trail with the negative findings in docs/MULTIPOINT_RESEARCH.md; exact framing pinned in conformance/fixtures/ult900n_v2_multipoint.golden. Co-Authored-By: Claude Opus 4.8 --- Client/Constants.h | 14 +++ Client/Headphones.cpp | 26 +++++ Client/Headphones.h | 7 ++ Client/macos/ContentView.swift | 6 +- Client/macos/HeadphonesBridge.h | 3 + Client/macos/HeadphonesBridge.mm | 12 +++ Client/macos/HeadphonesModel.swift | 12 +++ Client/tests/HeadphonesProtocolTests.cpp | 100 ++++++++++++++++++ Client/tests/conformance/COVERAGE.md | 1 + Client/tests/conformance/PROVENANCE.md | 4 +- .../fixtures/ult900n_v2_multipoint.golden | 7 ++ .../conformance/generate_reference_goldens.rb | 20 +++- Client/tests/run-macos.sh | 1 + docs/MULTIPOINT_RESEARCH.md | 84 +++++++++++++++ 14 files changed, 293 insertions(+), 4 deletions(-) create mode 100644 Client/tests/conformance/fixtures/ult900n_v2_multipoint.golden create mode 100644 docs/MULTIPOINT_RESEARCH.md diff --git a/Client/Constants.h b/Client/Constants.h index ceae60ed..d10882eb 100644 --- a/Client/Constants.h +++ b/Client/Constants.h @@ -86,6 +86,20 @@ namespace V2Command inline constexpr unsigned char BTNMODE_SET = 0xf8; // SET f8 inline constexpr unsigned char SUB_ADAPTIVE_VOLUME = 0x0a; inline constexpr unsigned char SUB_SPEAK_TO_CHAT = 0x0c; + // Touch-sensor family. On the WH-ULT900N (ULT WEAR) subtype 0xd1 carries the multipoint + // ("Connect to 2 devices simultaneously") state; the enable bit is inverted (00=on, 01=off). + // Source: GadgetBridge SonyProtocolImplV2 setWideAreaTap/handleTouchSensor + getConnectTwoDevices + // (commits 8cbc309346, e8520865f3, 5d7b37d1b7 - hardware-verified against the WH-ULT900N). + inline constexpr unsigned char TOUCH_GET = 0xd6; // GET d6 -> RET d7 00 <00=on/01=off> + inline constexpr unsigned char TOUCH_RET = 0xd7; + inline constexpr unsigned char TOUCH_SET = 0xd8; // SET d8 00 <00=on/01=off> + inline constexpr unsigned char SUB_MULTIPOINT = 0xd1; + // System-control family (reboot=0x16, multipoint apply=0x06). Multipoint SETs are committed with + // the fixed frame 98 00 06 01 - identical bytes for both ON and OFF; the touch-sensor frame above + // carries the actual state. The matching RET (97 00 06 xx) always reports 01, so it is never used + // as a state source. + inline constexpr unsigned char SYSCTL_SET = 0x98; + inline constexpr unsigned char SUB_SYSCTL_MULTIPOINT = 0x06; } // v2 equalizer preset ids (byte value sent/received at EQ payload[2]). diff --git a/Client/Headphones.cpp b/Client/Headphones.cpp index 94cf1bde..0f96f35f 100644 --- a/Client/Headphones.cpp +++ b/Client/Headphones.cpp @@ -431,6 +431,16 @@ void Headphones::probeCapabilities() auto r = this->_conn.sendCommandAndReadResponse({ (char)V2Command::BTNMODE_GET, (char)V2Command::SUB_SPEAK_TO_CHAT }, V2Command::BTNMODE_RET, V2Command::SUB_SPEAK_TO_CHAT); if (r.size() >= 3) { std::lock_guard g(this->_propertyMtx); this->_speakToChat = (r[2] == 0); this->_hasSpeakToChat = true; } } catch (...) {} + + // Multipoint state rides the touch-sensor 0xd1 subtype (GET d6 d1 -> RET d7 d1 00 <00=on/01=off>); + // the system-control RET (97 00 06) always reports 01 and cannot be used as the state source. + // Proven on the WH-ULT900N by GadgetBridge (SonyProtocolImplV2 getConnectTwoDevices/handleTouchSensor, + // commits 8cbc309346..5d7b37d1b7). Other v2 models may alias 0xd1 to a real touch gesture instead, + // so exposure stays probe-gated and the label is only shown when the device answers this GET. + try { + auto r = this->_conn.sendCommandAndReadResponse({ (char)V2Command::TOUCH_GET, (char)V2Command::SUB_MULTIPOINT }, V2Command::TOUCH_RET, V2Command::SUB_MULTIPOINT); + if (r.size() >= 4) { std::lock_guard g(this->_propertyMtx); this->_multipoint = (r[3] == 0); this->_hasMultipoint = true; } + } catch (...) {} } bool Headphones::hasAutoPowerOff() { std::lock_guard guard(this->_propertyMtx); return this->_hasAutoPowerOff; } @@ -486,6 +496,22 @@ void Headphones::setAdaptiveVolume(bool enabled) this->_adaptiveVolume = enabled; } +bool Headphones::hasMultipoint() { std::lock_guard guard(this->_propertyMtx); return this->_hasMultipoint; } +bool Headphones::getMultipoint() { std::lock_guard guard(this->_propertyMtx); return this->_multipoint; } +void Headphones::setMultipoint(bool enabled) +{ + if (this->_conn.getProtocolVersion() != SonyProtocolVersion::V2 || !this->hasMultipoint()) + throw std::logic_error("Multipoint capability has not been confirmed"); + // GadgetBridge's proven order (SonyHeadphonesProtocol PREF_SONY_CONNECT_TWO_DEVICES case): the + // state frame goes first (d8 d1 00 <00=on/01=off>, enable bit inverted), then the fixed apply + // commit 98 00 06 01 - identical bytes for both directions. sendCommand waits for the ACK, so + // two sequential sends reproduce GadgetBridge's frame/ack interleaving. + this->_conn.sendCommand({ (char)V2Command::TOUCH_SET, (char)V2Command::SUB_MULTIPOINT, 0x00, (char)(enabled ? 0x00 : 0x01) }); + this->_conn.sendCommand({ (char)V2Command::SYSCTL_SET, 0x00, (char)V2Command::SUB_SYSCTL_MULTIPOINT, 0x01 }); + std::lock_guard guard(this->_propertyMtx); + this->_multipoint = enabled; +} + bool Headphones::isChanged() { std::lock_guard guard(this->_propertyMtx); diff --git a/Client/Headphones.h b/Client/Headphones.h index a051985c..9788295c 100644 --- a/Client/Headphones.h +++ b/Client/Headphones.h @@ -89,6 +89,12 @@ class Headphones { bool getAdaptiveVolume(); void setAdaptiveVolume(bool enabled); + // Multipoint ("Connect to 2 devices simultaneously"). v2 only; the setting is device-persistent, + // so the app never enforces a default - the toggle just reads and writes the on-device state. + bool hasMultipoint(); + bool getMultipoint(); + void setMultipoint(bool enabled); + bool isChanged(); void setChanges(); private: @@ -119,6 +125,7 @@ class Headphones { bool _hasCodec = false; std::string _codec; bool _hasSpeakToChat = false; bool _speakToChat = false; bool _hasAdaptiveVolume = false; bool _adaptiveVolume = false; + bool _hasMultipoint = false; bool _multipoint = false; std::mutex _propertyMtx; diff --git a/Client/macos/ContentView.swift b/Client/macos/ContentView.swift index 526fefbd..d98952c3 100644 --- a/Client/macos/ContentView.swift +++ b/Client/macos/ContentView.swift @@ -81,7 +81,7 @@ struct ContentView: View { if model.supportsDsee { dseeCard } - if model.hasAdaptiveVolume || model.hasSpeakToChat || model.hasAutoPowerOff { + if model.hasAdaptiveVolume || model.hasSpeakToChat || model.hasAutoPowerOff || model.hasMultipoint { settingsCard } if let error = model.errorMessage { @@ -362,6 +362,10 @@ struct ContentView: View { .controlSize(.small) .padding(.leading, 12) } + if model.hasMultipoint { + settingToggle("Connect to 2 devices", "Stay paired to two devices at once", + on: model.multipoint) { model.setMultipoint($0) } + } if model.hasAutoPowerOff { HStack { VStack(alignment: .leading, spacing: 2) { diff --git a/Client/macos/HeadphonesBridge.h b/Client/macos/HeadphonesBridge.h index d02c820b..4a67adf4 100644 --- a/Client/macos/HeadphonesBridge.h +++ b/Client/macos/HeadphonesBridge.h @@ -54,6 +54,8 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { @property (nonatomic, readonly) BOOL speakToChat; @property (nonatomic, readonly) BOOL hasAdaptiveVolume; @property (nonatomic, readonly) BOOL adaptiveVolume; +@property (nonatomic, readonly) BOOL hasMultipoint; // v2 "Connect to 2 devices simultaneously" +@property (nonatomic, readonly) BOOL multipoint; // Runs the native Bluetooth device picker (modal, main thread) and connects to the chosen device. // completion is called on the main thread. @@ -85,6 +87,7 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { - (void)setAutoPowerOff:(NSInteger)index completion:(void (^)(BOOL ok, NSString * _Nullable error))completion; - (void)setSpeakToChat:(BOOL)enabled completion:(void (^)(BOOL ok, NSString * _Nullable error))completion; - (void)setAdaptiveVolume:(BOOL)enabled completion:(void (^)(BOOL ok, NSString * _Nullable error))completion; +- (void)setMultipoint:(BOOL)enabled completion:(void (^)(BOOL ok, NSString * _Nullable error))completion; // Re-reads the fast-changing state (ambient/NC, level, EQ, DSEE) so changes made with the headphone's // own button show up in the app. Called on a timer while connected. diff --git a/Client/macos/HeadphonesBridge.mm b/Client/macos/HeadphonesBridge.mm index d4ace713..77e24c99 100644 --- a/Client/macos/HeadphonesBridge.mm +++ b/Client/macos/HeadphonesBridge.mm @@ -128,6 +128,8 @@ - (BOOL)hasSpeakToChat { return _hp && _hp->hasSpeakToChat(); } - (BOOL)speakToChat { return _hp && _hp->getSpeakToChat(); } - (BOOL)hasAdaptiveVolume { return _hp && _hp->hasAdaptiveVolume(); } - (BOOL)adaptiveVolume { return _hp && _hp->getAdaptiveVolume(); } +- (BOOL)hasMultipoint { return _hp && _hp->hasMultipoint(); } +- (BOOL)multipoint { return _hp && _hp->getMultipoint(); } static BOOL SHCLooksLikeSonyHeadset(NSString *name) { if (name.length == 0) return NO; @@ -371,4 +373,14 @@ - (void)setAdaptiveVolume:(BOOL)enabled completion:(void (^)(BOOL, NSString * _N }); } +- (void)setMultipoint:(BOOL)enabled completion:(void (^)(BOOL, NSString * _Nullable))completion { + if (!_hp || !self.connected) { completion(NO, @"Not connected."); return; } + auto hp = _hp; + dispatch_async(_cmdQueue, ^{ + NSString *error = nil; BOOL ok = YES; + try { hp->setMultipoint(enabled); } catch (std::exception &exc) { ok = NO; error = @(exc.what()); } + dispatch_async(dispatch_get_main_queue(), ^{ completion(ok, error); }); + }); +} + @end diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index dee5165c..280005eb 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -48,6 +48,10 @@ final class HeadphonesModel: ObservableObject { } @Published var hasAdaptiveVolume = false @Published var adaptiveVolume = false + // Multipoint ("Connect to 2 devices"). Device-persistent - no app-enforced default; the + // toggle just mirrors the on-device state read by the capability probe. + @Published var hasMultipoint = false + @Published var multipoint = false @Published var deviceMac = "" @Published var protocolVersion = "" @@ -111,6 +115,8 @@ final class HeadphonesModel: ObservableObject { self.speakToChat = self.bridge.speakToChat self.hasAdaptiveVolume = self.bridge.hasAdaptiveVolume self.adaptiveVolume = self.bridge.adaptiveVolume + self.hasMultipoint = self.bridge.hasMultipoint + self.multipoint = self.bridge.multipoint // Speak-to-Chat capability is only confirmed by the probeCapabilities pass // (the second completion), so this stays armed until then and fires at most // once per connect. The device stays untouched unless it reports S2C on. @@ -141,6 +147,12 @@ final class HeadphonesModel: ObservableObject { bridge.setAdaptiveVolume(on) { ok, error in if !ok, let e = error { self.errorMessage = e } } } + func setMultipoint(_ on: Bool) { + multipoint = on + errorMessage = nil + bridge.setMultipoint(on) { ok, error in if !ok, let e = error { self.errorMessage = e } } + } + // Every @Published setter fires objectWillChange — and a full ContentView body // re-evaluation — even when the value is unchanged. The 2s poll mostly re-reads // cached bridge values, so gate writes to real changes. diff --git a/Client/tests/HeadphonesProtocolTests.cpp b/Client/tests/HeadphonesProtocolTests.cpp index 0c9a6e91..10320969 100644 --- a/Client/tests/HeadphonesProtocolTests.cpp +++ b/Client/tests/HeadphonesProtocolTests.cpp @@ -93,6 +93,60 @@ class FakeV1Connector final : public IBluetoothConnector std::deque incoming; }; +// v2-generation device that supports multipoint the way GadgetBridge proved it on the WH-ULT900N: +// only the touch-sensor 0xd1 GET answers with the multipoint state; every other capability probe +// times out (recv on an empty queue throws), which the probe treats as "unsupported". +class FakeV2Connector final : public IBluetoothConnector +{ +public: + int send(char* buf, size_t length) override + { + Buffer frame(buf, buf + length); + if (frame.size() < 2 || frame.front() != START_MARKER || frame.back() != END_MARKER) + throw std::runtime_error("invalid outbound frame"); + + Buffer body(frame.begin() + 1, frame.end() - 1); + auto message = CommandSerializer::unpackBtMessage(body); + if (message.dataType != DATA_TYPE::DATA_MDR) return static_cast(length); + + sentPayloads.push_back(message.payload); + queue({}, DATA_TYPE::ACK, 1 - message.seqNumber); + // GET d6 d1 -> RET d7 d1 00 <00=on/01=off> (GadgetBridge SonyProtocolImplV2 handleTouchSensor; + // the enable bit is inverted). The fake reports multipoint currently ON. + if (message.payload.size() >= 2 && (unsigned char)message.payload[0] == V2Command::TOUCH_GET + && (unsigned char)message.payload[1] == V2Command::SUB_MULTIPOINT) + queue({ (char)V2Command::TOUCH_RET, (char)V2Command::SUB_MULTIPOINT, 0x00, 0x00 }, DATA_TYPE::DATA_MDR, 0); + return static_cast(length); + } + + int recv(char* buf, size_t length) override + { + if (incoming.empty()) throw std::runtime_error("fake connector has no queued response"); + auto frame = std::move(incoming.front()); + incoming.pop_front(); + if (frame.size() > length) throw std::runtime_error("fake response exceeds receive buffer"); + std::memcpy(buf, frame.data(), frame.size()); + return static_cast(frame.size()); + } + + void connect(const std::string&) override { connected = true; } + void disconnect() noexcept override { connected = false; } + bool isConnected() noexcept override { return connected; } + std::vector getConnectedDevices() override { return {}; } + SonyProtocolVersion getProtocolVersion() noexcept override { return SonyProtocolVersion::V2; } + + std::vector sentPayloads; + +private: + void queue(const Buffer& payload, DATA_TYPE type, unsigned char sequence) + { + incoming.push_back(CommandSerializer::packageDataForBt(payload, type, sequence)); + } + + bool connected = true; + std::deque incoming; +}; + void require(bool condition, const char* message) { if (!condition) throw std::runtime_error(message); @@ -189,6 +243,52 @@ int main() (unsigned char)speakToChat[1] == V1Command::SUB_SPEAK_TO_CHAT && (unsigned char)speakToChat[3] == 0x00, "Speak-to-Chat did not use the v1 command layout"); + // Multipoint has no proven v1 frames (GadgetBridge SonyProtocolImplV1: "Connect two devices not + // implemented for V1"), so the XM4 path must never probe or set it. + require(!headphones.hasMultipoint(), "multipoint capability must stay unconfirmed on v1"); + const auto hasMultipointFrame = std::any_of(observed->sentPayloads.begin(), observed->sentPayloads.end(), [](const Buffer& payload) { + return !payload.empty() && ((unsigned char)payload[0] == V2Command::TOUCH_GET || + (unsigned char)payload[0] == V2Command::TOUCH_SET || + (unsigned char)payload[0] == V2Command::SYSCTL_SET); + }); + require(!hasMultipointFrame, "XM4 path emitted a v2 multipoint frame (d6/d8/98)"); + bool multipointRejected = false; + try { headphones.setMultipoint(true); } + catch (const std::logic_error&) { multipointRejected = true; } + require(multipointRejected, "setMultipoint on v1 must throw instead of sending"); + + // --- v2 multipoint ("Connect to 2 devices"), byte layout proven by GadgetBridge on the WH-ULT900N + // (SonyProtocolImplV2 commits 8cbc309346, e8520865f3, 5d7b37d1b7) --- + auto fakeV2 = std::make_unique(); + auto* observedV2 = fakeV2.get(); + BluetoothWrapper bluetoothV2(std::move(fakeV2)); + Headphones ult900n(bluetoothV2); + ult900n.probeCapabilities(); + + require(ult900n.hasMultipoint(), "v2 multipoint probe (d6 d1) was not recorded"); + require(ult900n.getMultipoint(), "RET d7 d1 00 00 must parse as multipoint ON (enable bit inverted)"); + require(!ult900n.hasSpeakToChat() && !ult900n.hasAdaptiveVolume(), + "unanswered v2 probes must stay unsupported"); + + ult900n.setMultipoint(false); + require(observedV2->sentPayloads.size() >= 2, "multipoint OFF did not send both frames"); + const auto offState = observedV2->sentPayloads[observedV2->sentPayloads.size() - 2]; + const auto offCommit = observedV2->sentPayloads.back(); + require(offState == Buffer({ (char)0xd8, (char)0xd1, 0x00, 0x01 }), + "multipoint OFF state frame must be d8 d1 00 01"); + require(offCommit == Buffer({ (char)0x98, 0x00, 0x06, 0x01 }), + "multipoint apply commit must be the fixed 98 00 06 01"); + require(!ult900n.getMultipoint(), "multipoint OFF was not mirrored locally"); + + ult900n.setMultipoint(true); + const auto onState = observedV2->sentPayloads[observedV2->sentPayloads.size() - 2]; + const auto onCommit = observedV2->sentPayloads.back(); + require(onState == Buffer({ (char)0xd8, (char)0xd1, 0x00, 0x00 }), + "multipoint ON state frame must be d8 d1 00 00"); + require(onCommit == Buffer({ (char)0x98, 0x00, 0x06, 0x01 }), + "multipoint ON must reuse the fixed apply commit 98 00 06 01"); + require(ult900n.getMultipoint(), "multipoint ON was not mirrored locally"); + // Malformed inbound frames on the untrusted parser path must throw the recoverable type. // 61 (0x3D) is the escape sentry; a lone one at buffer end and one followed by a // non-escapable byte are the two unescape rejection paths. diff --git a/Client/tests/conformance/COVERAGE.md b/Client/tests/conformance/COVERAGE.md index fec93d68..d92cee0c 100644 --- a/Client/tests/conformance/COVERAGE.md +++ b/Client/tests/conformance/COVERAGE.md @@ -10,5 +10,6 @@ The target contract is the Sony MDR v1 community specification at the revisions | EQ preset and persistent custom EQ | 3 | 0 | 3 | 3 | 0 | 100% | | DSEE and Speak-to-Chat mutations | 2 | 0 | 2 | 2 | 0 | 100% | | Malformed-frame rejection | 5 | 0 | 5 | 5 | 0 | 100% | +| v2 multipoint (WH-ULT900N) GET/RET/SET/apply framing | 6 | 0 | 6 | 6 | 0 | 100% | Hardware behavior is deliberately excluded from this file's score. It has a separate live-device verification gate because the public specification is reverse-engineered and Sony firmware can differ. diff --git a/Client/tests/conformance/PROVENANCE.md b/Client/tests/conformance/PROVENANCE.md index 041f242b..63014f80 100644 --- a/Client/tests/conformance/PROVENANCE.md +++ b/Client/tests/conformance/PROVENANCE.md @@ -7,4 +7,6 @@ The XM4 v1 payloads are cross-checked against two independently maintained commu The exact frames were generated on 2026-08-24 with Ruby 3.4 from `generate_reference_goldens.rb`. That script is a clean-room transcription of the documented wire rules and pinned payload facts. Regenerate to a temporary file, diff every byte against `fixtures/xm4_v1_frames.golden`, and update this file when either reference revision changes. -The fixture is deterministic and platform-independent. It uses exact byte comparison; no scrubbing or tolerance is appropriate. +The v2 multipoint payloads in `fixtures/ult900n_v2_multipoint.golden` (generated by the same script with the `ult900n_v2_multipoint` argument) are pinned from Gadgetbridge's ConnectTwoDevices feature as hardware-verified on the WH-ULT900N (ULT WEAR): commits `8cbc309346` ("WIP add ConnectTwoDevices feature"), `e8520865f3` ("fix: setting Connect Two Devices"), and `5d7b37d1b7` ("fix read Connect Two Devices"), all 2026-07-08, files `SonyProtocolImplV2.java` and `SonyHeadphonesProtocol.java`. Pinned facts: the state is read and written through touch-sensor subtype `d1` with an inverted enable bit (`d6 d1` / `d7 d1 00 <00=on|01=off>` / `d8 d1 00 <00=on|01=off>`), a SET is followed by the fixed system-control apply commit `98 00 06 01` for both directions, and the system-control RET (`97 00 06 xx`) always reports `01` so it is never a state source. Gadgetbridge implements no v1 (WH-1000XM4) multipoint frames — `SonyProtocolImplV1.setConnectTwoDevices`/`getConnectTwoDevices` log "not implemented for V1" and return null — so no v1 fixture exists on purpose. + +Both fixtures are deterministic and platform-independent. They use exact byte comparison; no scrubbing or tolerance is appropriate. diff --git a/Client/tests/conformance/fixtures/ult900n_v2_multipoint.golden b/Client/tests/conformance/fixtures/ult900n_v2_multipoint.golden new file mode 100644 index 00000000..24612cea --- /dev/null +++ b/Client/tests/conformance/fixtures/ult900n_v2_multipoint.golden @@ -0,0 +1,7 @@ +# id|data_type|sequence|payload|complete_frame +mp_probe_get|0c|0|d6 d1|3e 0c 00 00 00 00 02 d6 d1 b5 3c +mp_ret_on|0c|0|d7 d1 00 00|3e 0c 00 00 00 00 04 d7 d1 00 00 b8 3c +mp_ret_off|0c|0|d7 d1 00 01|3e 0c 00 00 00 00 04 d7 d1 00 01 b9 3c +mp_set_on|0c|0|d8 d1 00 00|3e 0c 00 00 00 00 04 d8 d1 00 00 b9 3c +mp_set_off|0c|0|d8 d1 00 01|3e 0c 00 00 00 00 04 d8 d1 00 01 ba 3c +mp_apply_commit|0c|0|98 00 06 01|3e 0c 00 00 00 00 04 98 00 06 01 af 3c diff --git a/Client/tests/conformance/generate_reference_goldens.rb b/Client/tests/conformance/generate_reference_goldens.rb index 169ffd57..206e881b 100644 --- a/Client/tests/conformance/generate_reference_goldens.rb +++ b/Client/tests/conformance/generate_reference_goldens.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true # Clean-room generator for the deterministic frame facts documented in PROVENANCE.md. +# Usage: ruby generate_reference_goldens.rb [xm4_v1|ult900n_v2_multipoint] def frame(data_type, sequence, payload) body = [data_type, sequence, 0, 0, 0, payload.length] + payload body << body.sum.modulo(256) @@ -8,7 +9,7 @@ def frame(data_type, sequence, payload) [0x3e] + escaped + [0x3c] end -cases = { +XM4_V1_CASES = { ack_seq1: [0x01, 1, []], escape_triplet: [0x0c, 0, [0x3c, 0x3d, 0x3e]], init: [0x0c, 0, [0x00, 0x00]], firmware_get: [0x0c, 0, [0x04, 0x02]], battery_get: [0x0c, 0, [0x10, 0x00]], codec_get: [0x0c, 0, [0x18, 0x00]], @@ -20,7 +21,22 @@ def frame(data_type, sequence, payload) dsee_get: [0x0c, 0, [0xe6, 0x02]], dsee_off: [0x0c, 0, [0xe8, 0x02, 0, 0]], auto_power_get: [0x0c, 0, [0xf6, 0x04]], speak_get: [0x0c, 0, [0xf6, 0x05]], speak_off: [0x0c, 0, [0xf8, 0x05, 1, 0]] -} +}.freeze + +# v2 multipoint ("Connect to 2 devices simultaneously") payload facts, pinned from GadgetBridge +# SonyProtocolImplV2 as hardware-verified on the WH-ULT900N (see PROVENANCE.md): +# state rides touch-sensor subtype d1 with an inverted enable bit; SETs are followed by the fixed +# system-control apply commit 98 00 06 01 regardless of direction. +ULT900N_V2_MULTIPOINT_CASES = { + mp_probe_get: [0x0c, 0, [0xd6, 0xd1]], + mp_ret_on: [0x0c, 0, [0xd7, 0xd1, 0x00, 0x00]], + mp_ret_off: [0x0c, 0, [0xd7, 0xd1, 0x00, 0x01]], + mp_set_on: [0x0c, 0, [0xd8, 0xd1, 0x00, 0x00]], + mp_set_off: [0x0c, 0, [0xd8, 0xd1, 0x00, 0x01]], + mp_apply_commit: [0x0c, 0, [0x98, 0x00, 0x06, 0x01]] +}.freeze + +cases = (ARGV[0] || 'xm4_v1') == 'ult900n_v2_multipoint' ? ULT900N_V2_MULTIPOINT_CASES : XM4_V1_CASES puts '# id|data_type|sequence|payload|complete_frame' cases.each do |name, (data_type, sequence, payload)| diff --git a/Client/tests/run-macos.sh b/Client/tests/run-macos.sh index 22cd9593..6d1a9e0c 100755 --- a/Client/tests/run-macos.sh +++ b/Client/tests/run-macos.sh @@ -24,6 +24,7 @@ clang++ -std=c++20 -Wall -Wextra -Werror -I"$client_dir" \ -o "$conformance_binary" "$conformance_binary" "$client_dir/tests/conformance/fixtures/xm4_v1_frames.golden" +"$conformance_binary" "$client_dir/tests/conformance/fixtures/ult900n_v2_multipoint.golden" clang++ -std=c++20 -Wall -Wextra -Werror -I"$client_dir" \ "$client_dir/tests/MetamorphicProtocolTests.cpp" \ diff --git a/docs/MULTIPOINT_RESEARCH.md b/docs/MULTIPOINT_RESEARCH.md new file mode 100644 index 00000000..c24f8d2e --- /dev/null +++ b/docs/MULTIPOINT_RESEARCH.md @@ -0,0 +1,84 @@ +# Multipoint ("Connect to 2 devices simultaneously") — protocol research + +Research date: 2026-08-24. Question: can SonyBridge toggle Sony's multipoint setting without +the phone app, using only wire bytes proven by an existing implementation? + +## Sources examined + +- **Gadgetbridge** (codeberg.org/Freeyourgadget/Gadgetbridge, `master`), path + `app/src/main/java/nodomain/freeyourgadget/gadgetbridge/{devices,service/devices}/sony/headphones/`. + Files pulled raw and cross-checked against the repository's commit API (the GitHub mirror is the + archived 2022 snapshot and predates this feature). +- **Plutoberth/SonyHeadphonesClient** (upstream of this codebase): issues #113 ("Change pairing + mode sony headphone") and #114 ("Feature request: switch bluetooth source") are open feature + requests with no frames and no implementation. No prior multipoint art exists there. + +## Finding 1 — v1 (WH-1000XM4): NOT implemented anywhere. No proven frames exist. + +`SonyProtocolImplV1.java` (protocol/impl/v1) implements the capability interface with an explicit +negative — both methods log and return null: + +```java +public Request setConnectTwoDevices(final ConnectTwoDevices config) { + LOG.warn("Connect two devices not implemented for V1"); + return null; +} +public Request getConnectTwoDevices() { + LOG.warn("Connect two devices not implemented for V1"); + return null; +} +``` + +`PayloadTypeV1.java` contains no multipoint/pairing-management payload type. No v1 device +coordinator declares `SonyHeadphonesCapabilities.ConnectTwoDevices`. + +**Consequence for SonyBridge: the XM4 gets no multipoint support.** Inventing v1 frames to send +at real hardware is out of scope by policy; this repo only ships wire bytes a proven +implementation has sent at a real device. The v1 test suite instead asserts the XM4 path never +emits any of the v2 multipoint opcodes (`d6`/`d8`/`98`). + +## Finding 2 — v2: proven by Gadgetbridge on the WH-ULT900N (ULT WEAR) + +Added 2026-07-08 by David Giron, three commits (in order): + +1. `8cbc309346` "WIP add ConnectTwoDevices feature" — first cut: GET `96 00 06`, + SET `98 00 06 <01|00>` (SYSTEM_CONTROL family, subcode 0x06). +2. `e8520865f3` "fix: setting Connect Two Devices" — hardware testing showed the SET value byte is + ignored; the state is actually driven through the touch-sensor `d1` subtype, and `98 00 06 01` + is a fixed "apply" commit sent after it for **both** directions. +3. `5d7b37d1b7` "fix read Connect Two Devices" — hardware testing showed `SYSTEM_CONTROL_RET` + (`97 00 06 xx`) always reports `01` regardless of actual state, so the GET was changed to the + touch-sensor read, whose RET carries the real value. + +Final proven wire contract (`SonyProtocolImplV2.java` `setConnectTwoDevices`/`getConnectTwoDevices`/ +`setWideAreaTap`/`handleTouchSensor`, `SonyHeadphonesProtocol.java` `PREF_SONY_CONNECT_TWO_DEVICES` +case; only `SonyWHULT900NCoordinator` declares the capability): + +| Step | Payload | Meaning | +|---|---|---| +| GET | `d6 d1` | read state | +| RET | `d7 d1 00 XX` | `XX == 00` → multipoint ON, `01` → OFF (enable bit inverted) | +| SET (1st frame) | `d8 d1 00 XX` | `00` → ON, `01` → OFF | +| SET (2nd frame) | `98 00 06 01` | fixed apply commit, identical bytes for ON and OFF | + +Frame order for SET: the `d8 d1 ...` state frame is sent first (it is the returned +`configRequest`, encoded immediately); the `98 00 06 01` commit is queued and drained on the next +ACK. SonyBridge reproduces this with two sequential `sendCommand` calls, each of which waits for +its ACK. + +### Caveat carried into the implementation + +On devices with real touch-tap hardware (LinkBuds family), touch-sensor subtype `d1` is Wide Area +Tap, not multipoint; Gadgetbridge distinguishes by per-model capability lists. SonyBridge gates by +capability probe instead (house style): the toggle appears only when the device answers `d6 d1`, +and the byte contract is only hardware-proven for the WH-ULT900N family. This is noted at the +probe site in `Headphones.cpp`. + +## What SonyBridge implements + +- v2 only: probe `d6 d1` appended to `probeCapabilities()` (v2 branch), state parsed per the table + above; `setMultipoint()` sends `d8 d1 00 XX` then `98 00 06 01`. +- v1 (XM4): nothing — `hasMultipoint()` stays false, `setMultipoint()` throws. +- Offline proof: `HeadphonesProtocolTests.cpp` (FakeV2Connector GET/RET exchange + exact SET frame + bytes; v1 negative assertions) and `conformance/fixtures/ult900n_v2_multipoint.golden` + (exact framing for all six payloads). From e93962e9e51808d7618e5f2b2bad09714126a005 Mon Sep 17 00:00:00 2001 From: Suyash Date: Fri, 18 Sep 2026 02:44:35 +0000 Subject: [PATCH 15/35] fix(ui): manual EQ sliders cover the full -10..+10 range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The custom-EQ sliders were limited to 0..10, so every band could only be boosted — cutting a band was impossible from the Windows/Linux UI, and a negative value read back from the headphones (`requestEqualizer()` decodes `byte - 10`) was clamped to 0 by the widget and pushed back on the next edit. Both ends of the protocol already use the signed range: `setEqualizerCustom()` clamps to [-10, 10] and sends `value + 10`. The macOS UI uses -10...10 too, so this also makes the two interfaces agree. Co-Authored-By: Claude Opus 5 --- Client/CrossPlatformGUI.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Client/CrossPlatformGUI.cpp b/Client/CrossPlatformGUI.cpp index 993d9a85..ba90fc0b 100644 --- a/Client/CrossPlatformGUI.cpp +++ b/Client/CrossPlatformGUI.cpp @@ -462,9 +462,11 @@ void CrossPlatformGUI::_drawEqualizer() for (int i = 0; i < 6; ++i) { std::string id = "##eqband" + std::to_string(i); - std::string fmt = std::string(bandNames[i]) + " %d"; + std::string fmt = std::string(bandNames[i]) + " %+d"; ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::SliderInt(id.c_str(), values[i], 0, 10, fmt.c_str())) + // Range is -10..+10 on the wire: Headphones::setEqualizerCustom() clamps to that and sends + // value+10, and requestEqualizer() decodes byte-10. A 0..10 slider could only ever boost. + if (ImGui::SliderInt(id.c_str(), values[i], -10, 10, fmt.c_str())) changed = true; } if (changed) From 991670b79ba9edef5f9955b2228be0639d3493c8 Mon Sep 17 00:00:00 2001 From: Suyash Date: Fri, 18 Sep 2026 02:44:35 +0000 Subject: [PATCH 16/35] fix(ui): upload device hero images so they actually render `_deviceTexture()` pushed the freshly created `ImTextureData` straight into `ImGui::GetPlatformIO().Textures`, but `UpdateTexturesEndFrame()` resizes that list to 0 each frame and refills it from the font atlases plus the registered user textures. The entry was therefore gone before the renderer backend could honour `ImTextureStatus_WantCreate`, and the texture was never uploaded: - Release: the product image area is blank; every device falls back to nothing. - Debug: `IM_ASSERT(tex_id != ImTextureID_Invalid && "ImDrawCmd is referring to ImTextureData that wasn't uploaded to graphics system...")` fires. `ImGui::RegisterUserTexture()` (imgui 1.92+) adds it to `g.UserTextures`, which is what the per-frame rebuild reads from, so the upload request survives. Co-Authored-By: Claude Opus 5 --- Client/CrossPlatformGUI.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Client/CrossPlatformGUI.cpp b/Client/CrossPlatformGUI.cpp index 993d9a85..2c010180 100644 --- a/Client/CrossPlatformGUI.cpp +++ b/Client/CrossPlatformGUI.cpp @@ -1,5 +1,7 @@ #include "CrossPlatformGUI.h" +#include "imgui_internal.h" // ImGui::RegisterUserTexture() + #include #include #include @@ -317,8 +319,12 @@ const CrossPlatformGUI::DeviceTexture& CrossPlatformGUI::_deviceTexture(const st ImTextureData* tex = IM_NEW(ImTextureData)(); tex->Create(ImTextureFormat_RGBA32, w, h); memcpy(tex->GetPixels(), pixels, (size_t)w * h * 4); - tex->SetStatus(ImTextureStatus_WantCreate); - ImGui::GetPlatformIO().Textures.push_back(tex); + // ImGui::UpdateTexturesEndFrame() clears and rebuilds PlatformIO.Textures from the font atlases + // and the registered user textures on every frame, so pushing into it directly was dropped again + // before the renderer backend ever saw the WantCreate request: the hero image stayed blank in + // Release builds and tripped the "ImDrawCmd is referring to ImTextureData that wasn't uploaded" + // assert in Debug. RegisterUserTexture() is the supported way in (imgui >= 1.92). + ImGui::RegisterUserTexture(tex); out.ref = tex->GetTexRef(); out.w = w; From e5fc1ab7ed7e31e471cdc427ca4404f82f21abb1 Mon Sep 17 00:00:00 2001 From: Suyash Date: Fri, 18 Sep 2026 02:44:03 +0000 Subject: [PATCH 17/35] fix(win): stop Disconnect from freezing the UI, and a 100% CPU spin on link loss MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three related problems around teardown on Windows: 1. `BluetoothWrapper::disconnect()` took `_connectorMtx` before closing the socket, but a worker thread holds that same lock while blocked in `recv()`. Closing the socket is what releases that thread, so the UI thread waited on the lock — Disconnect froze the window until the 2.5s recv timeout expired, and closing the app while a read was in flight hung it. On Windows, close first, then take the lock; other platforms keep the old order. 2. `_socket` was written by the UI thread (disconnect) while a worker thread read it inside `send()`/`recv()` — a data race that could hand `recv()` a closed or recycled handle. It is now `std::atomic`, swapped through a single `_closeSocket()`. 3. `recv()` returning 0 (graceful close by the headphones) was treated as a successful read of an empty buffer, so `BluetoothWrapper::_readMessage()` looped forever looking for a start marker — one core pegged until the app was killed. Both the connector and the wrapper now treat it as a disconnect. Also loops `send()` until the whole frame is out: a partial send left the device waiting for the rest of a command that never arrived. Co-Authored-By: Claude Opus 5 --- Client/BluetoothWrapper.cpp | 19 ++++++- Client/windows/WindowsBluetoothConnector.cpp | 60 ++++++++++++++------ Client/windows/WindowsBluetoothConnector.h | 9 ++- 3 files changed, 68 insertions(+), 20 deletions(-) diff --git a/Client/BluetoothWrapper.cpp b/Client/BluetoothWrapper.cpp index cd3cb744..23f6dfce 100644 --- a/Client/BluetoothWrapper.cpp +++ b/Client/BluetoothWrapper.cpp @@ -48,10 +48,21 @@ void BluetoothWrapper::connect(const std::string& addr) void BluetoothWrapper::disconnect() noexcept { +#if defined(_WIN32) + // Close the link BEFORE taking the lock. A worker thread can hold _connectorMtx while blocked in + // recv(), and closing the socket is exactly what wakes it up - taking the lock first deadlocks the + // UI thread until the recv timeout expires, and hangs the app on exit. The Windows connector's + // disconnect() is safe to call concurrently with an in-flight recv(). + this->_connector->disconnect(); + std::lock_guard guard(this->_connectorMtx); + this->_seqNumber = 0; + this->_leftoverBytes.clear(); +#else std::lock_guard guard(this->_connectorMtx); this->_seqNumber = 0; this->_leftoverBytes.clear(); this->_connector->disconnect(); +#endif } @@ -117,12 +128,18 @@ CommandSerializer::Message BluetoothWrapper::_readMessage() else { numRecvd = this->_connector->recv(buf, sizeof(buf)); + if (numRecvd <= 0) + { + // A connector that reports 0 bytes (peer closed) would otherwise spin this loop at + // 100% CPU forever, since no marker can ever be found in an empty buffer. + throw RecoverableException("The headphones closed the connection.", true); + } } size_t messageStart = 0; size_t messageEnd = numRecvd; - for (size_t i = 0; i < numRecvd; i++) + for (size_t i = 0; i < static_cast(numRecvd); i++) { if (buf[i] == START_MARKER) { diff --git a/Client/windows/WindowsBluetoothConnector.cpp b/Client/windows/WindowsBluetoothConnector.cpp index 6967f36f..cfb1c101 100644 --- a/Client/windows/WindowsBluetoothConnector.cpp +++ b/Client/windows/WindowsBluetoothConnector.cpp @@ -1,5 +1,7 @@ #include "WindowsBluetoothConnector.h" +#include + void WSAStartupWrapper() { int iResult; @@ -50,8 +52,7 @@ void WindowsBluetoothConnector::connect(const std::string& addrStr) } // A failed connect() can leave the socket unusable - recreate it before trying the v2 UUID. - ::closesocket(this->_socket); - this->_socket = INVALID_SOCKET; + this->_closeSocket(); this->_initSocket(); if (_tryConnect(SONY_UUID_V2, sab)) @@ -66,25 +67,57 @@ void WindowsBluetoothConnector::connect(const std::string& addrStr) WindowsBluetoothConnector::~WindowsBluetoothConnector() { - if (this->_socket != INVALID_SOCKET) + this->_closeSocket(); +} + +void WindowsBluetoothConnector::_closeSocket() noexcept +{ + SOCKET sock = this->_socket.exchange(INVALID_SOCKET); + if (sock != INVALID_SOCKET) { - ::closesocket(this->_socket); + ::shutdown(sock, SD_BOTH); + ::closesocket(sock); } } int WindowsBluetoothConnector::send(char* buf, size_t length) { - auto bytesSent = ::send(this->_socket, buf, length, 0); - if (bytesSent == SOCKET_ERROR) + SOCKET sock = this->_socket.load(); + if (sock == INVALID_SOCKET) { - throw RecoverableException("Couldn't send (" + std::to_string(WSAGetLastError()) + ")", true); + throw RecoverableException("Not connected", true); + } + + // send() is free to accept only part of the buffer; keep going until the whole frame is out, + // otherwise the device sees a truncated command and never answers. + size_t total = 0; + while (total < length) + { + int chunk = static_cast((std::min)(length - total, static_cast(0x7fffffff))); + int sent = ::send(sock, buf + total, chunk, 0); + if (sent == SOCKET_ERROR) + { + throw RecoverableException("Couldn't send (" + std::to_string(WSAGetLastError()) + ")", true); + } + total += static_cast(sent); } - return bytesSent; + return static_cast(total); } int WindowsBluetoothConnector::recv(char* buf, size_t length) { - auto bytesReceived = ::recv(this->_socket, buf, length, 0); + SOCKET sock = this->_socket.load(); + if (sock == INVALID_SOCKET) + { + throw RecoverableException("Not connected", true); + } + + auto bytesReceived = ::recv(sock, buf, static_cast(length), 0); + if (bytesReceived == 0) + { + // Graceful close by the headphones. Without this the caller loops on an empty buffer forever. + throw RecoverableException("The headphones closed the connection.", true); + } if (bytesReceived == SOCKET_ERROR) { int err = WSAGetLastError(); @@ -142,13 +175,8 @@ std::vector WindowsBluetoothConnector::getConnectedDevices() void WindowsBluetoothConnector::disconnect() noexcept { - if (this->_socket != INVALID_SOCKET) - { - this->_connected = false; - shutdown(this->_socket, SD_BOTH); - closesocket(this->_socket); - this->_socket = INVALID_SOCKET; - } + this->_connected = false; + this->_closeSocket(); } bool WindowsBluetoothConnector::isConnected() noexcept diff --git a/Client/windows/WindowsBluetoothConnector.h b/Client/windows/WindowsBluetoothConnector.h index 824b8e1d..690fd121 100644 --- a/Client/windows/WindowsBluetoothConnector.h +++ b/Client/windows/WindowsBluetoothConnector.h @@ -34,8 +34,11 @@ class WindowsBluetoothConnector final : public IBluetoothConnector std::string _wstringToUtf8(const std::wstring& wstr); bool _tryConnect(const char* uuid, SOCKADDR_BTH& sab); - SOCKET _socket = INVALID_SOCKET; - std::atomic _connected = false; - SonyProtocolVersion _protocolVersion = SonyProtocolVersion::V1; + // disconnect() runs on the UI thread while a worker thread can be inside recv(), so the handle + // itself has to be atomic; closing it is what makes that blocked recv() return. + std::atomic _socket{ INVALID_SOCKET }; + std::atomic _connected{ false }; + std::atomic _protocolVersion{ SonyProtocolVersion::V1 }; void _initSocket(); + void _closeSocket() noexcept; }; \ No newline at end of file From 7810fe2e1fa56564004838dbd2e6928ac916eff6 Mon Sep 17 00:00:00 2001 From: Suyash Date: Fri, 18 Sep 2026 02:43:31 +0000 Subject: [PATCH 18/35] fix(win): build with MinGW-w64 and on case-sensitive filesystems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Windows target only ever built under MSVC: - `#include ` — the MinGW-w64 header is `bluetoothapis.h`, and the case also matters when cross-compiling from a case-sensitive filesystem. - `#pragma comment(lib, ...)` is MSVC-only, so ws2_32/rpcrt4/bthprops were never linked anywhere else: ~25 undefined references to closesocket, WSAStartup, UuidFromStringA, BluetoothFindFirstRadio and friends. - `#include "Windows.h"` in WindowsGUI.h fails the same way. Link the import libraries from CMake instead, keep the pragmas for MSVC only, and move NOMINMAX/WIN32_LEAN_AND_MEAN to the target so every translation unit gets them, not just CrossPlatformGUI.cpp. Verified by cross-compiling the Windows target with x86_64-w64-mingw32-g++ 13. MSVC is unaffected: it keeps both the pragmas and the CMake libraries. Co-Authored-By: Claude Opus 5 --- Client/CMakeLists.txt | 10 +++++++-- Client/windows/WindowsBluetoothConnector.h | 24 ++++++++++++++-------- Client/windows/WindowsGUI.h | 2 +- Client/windows/main.cpp | 1 + 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Client/CMakeLists.txt b/Client/CMakeLists.txt index 9695cef9..7b42c151 100644 --- a/Client/CMakeLists.txt +++ b/Client/CMakeLists.txt @@ -84,7 +84,10 @@ if (LINUX) endif () if (WIN32) - ADD_DEFINITIONS(-DUNICODE) + target_compile_definitions(SonyHeadphonesClient PRIVATE + UNICODE _UNICODE + NOMINMAX + WIN32_LEAN_AND_MEAN) target_sources(SonyHeadphonesClient PRIVATE windows/WindowsGUI.cpp @@ -94,8 +97,11 @@ if (WIN32) imgui/backends/imgui_impl_win32.cpp ) + # Non-MSVC toolchains have no #pragma comment(lib, ...), so name every import library here. target_link_libraries(SonyHeadphonesClient - PRIVATE d3d11 + PRIVATE d3d11 dxgi d3dcompiler + ws2_32 rpcrt4 bthprops + dwmapi # imgui_impl_win32.cpp ) endif () diff --git a/Client/windows/WindowsBluetoothConnector.h b/Client/windows/WindowsBluetoothConnector.h index 824b8e1d..d6f9b855 100644 --- a/Client/windows/WindowsBluetoothConnector.h +++ b/Client/windows/WindowsBluetoothConnector.h @@ -1,17 +1,25 @@ #pragma once -#include -#pragma comment(lib, "ws2_32.lib") -#pragma comment(lib, "rpcrt4.lib") -#pragma comment(lib, "Bthprops.lib") + +// winsock2.h must precede windows.h, which bluetoothapis.h pulls in. #include #include -#include -#include +// Lowercase: the MinGW-w64 headers are named this way, and so is the file on a +// case-sensitive filesystem (cross-compiling from Linux). +#include #include -#include "IBluetoothConnector.h" + +#include #include + +#include "IBluetoothConnector.h" #include "ByteMagic.h" -#include + +// Only MSVC understands these; every other toolchain gets the libraries from CMake. +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "rpcrt4.lib") +#pragma comment(lib, "bthprops.lib") +#endif class WindowsBluetoothConnector final : public IBluetoothConnector { diff --git a/Client/windows/WindowsGUI.h b/Client/windows/WindowsGUI.h index b4be8e49..0a764eb4 100644 --- a/Client/windows/WindowsGUI.h +++ b/Client/windows/WindowsGUI.h @@ -18,7 +18,7 @@ #include -#include "Windows.h" +#include #include "CrossPlatformGUI.h" diff --git a/Client/windows/main.cpp b/Client/windows/main.cpp index fd248713..cd164c5a 100644 --- a/Client/windows/main.cpp +++ b/Client/windows/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "WindowsBluetoothConnector.h" #include "CommandSerializer.h" From 7f1bf9b88948dfeab4143b7d8b74393a5faa69b6 Mon Sep 17 00:00:00 2001 From: Suyash Date: Fri, 18 Sep 2026 03:02:22 +0000 Subject: [PATCH 19/35] fix(ui): refresh the battery level while connected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `requestBattery()` only runs in the post-connect read, so the percentage in the header is a snapshot from the moment you pressed Connect. Leave the app open for a few hours and it still shows that first value while the real headset drains — and on a charging headset it never climbs. Piggyback a battery read on the existing ambient poll worker, once every ~30s (`BATTERY_POLL_FRAMES`), so no extra thread or future is needed. The read is guarded: a device that doesn't answer the inquiry keeps its stale value instead of dropping the poll. Verified against a simulated v2 device whose reported level changes over time: the header follows it instead of freezing at the connect-time value. Co-Authored-By: Claude Opus 5 --- Client/CrossPlatformGUI.cpp | 21 ++++++++++++++++++++- Client/CrossPlatformGUI.h | 4 ++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Client/CrossPlatformGUI.cpp b/Client/CrossPlatformGUI.cpp index 993d9a85..b5b08e4d 100644 --- a/Client/CrossPlatformGUI.cpp +++ b/Client/CrossPlatformGUI.cpp @@ -241,7 +241,26 @@ void CrossPlatformGUI::_pumpConnectionState() if (!this->_pollFuture.valid() && ++this->_pollCounter >= DYNAMIC_POLL_FRAMES) { this->_pollCounter = 0; - this->_pollFuture.setFromAsync([this]() { this->_headphones.requestAmbientState(); }); + + // Battery is otherwise read once, in the post-connect phase, and never again: the header keeps + // showing the level from the moment you connected for as long as the app stays open. Refresh it + // on the same worker, on its own slower schedule. + bool withBattery = false; + this->_batteryPollCounter += DYNAMIC_POLL_FRAMES; + if (this->_isV2() && this->_batteryPollCounter >= BATTERY_POLL_FRAMES) + { + this->_batteryPollCounter = 0; + withBattery = true; + } + + this->_pollFuture.setFromAsync([this, withBattery]() { + this->_headphones.requestAmbientState(); + // Best effort: a device that doesn't answer the battery inquiry must not kill the poll. + if (withBattery) + { + try { this->_headphones.requestBattery(); } catch (const std::exception&) {} + } + }); } } diff --git a/Client/CrossPlatformGUI.h b/Client/CrossPlatformGUI.h index f396939f..f4a3d5b3 100644 --- a/Client/CrossPlatformGUI.h +++ b/Client/CrossPlatformGUI.h @@ -26,6 +26,9 @@ const auto WINDOW_COLOR = ImVec4(0.09f, 0.09f, 0.11f, 1.00f); // Physical-button changes (ASM) are polled roughly every two seconds so the app stays in sync. constexpr auto DYNAMIC_POLL_FRAMES = FPS * 2; +// Battery moves slowly and each read costs a round trip, so it rides along with the ambient poll on a +// much slower schedule instead of getting a request of its own. +constexpr auto BATTERY_POLL_FRAMES = FPS * 30; class CrossPlatformGUI { @@ -81,6 +84,7 @@ class CrossPlatformGUI bool _synced = false; bool _probed = false; int _pollCounter = 0; + int _batteryPollCounter = 0; // UI state, synced from the device once after connect; user edits are pushed back to the headphones. bool _uiAsmOn = false; From 22c367680acd881cb02a88c4eed6759edb10eabb Mon Sep 17 00:00:00 2001 From: "Claude Opus 5.5" Date: Wed, 7 Oct 2026 02:52:24 +0200 Subject: [PATCH 20/35] fix(macos): auto-connect Sony ULT WEAR in the SwiftUI app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v0.3.3 ULT WEAR fix changed MacOSBluetoothConnector::getConnectedDevices, but the macOS app connects through HeadphonesBridge.scanAndConnect, which only auto-selects a paired device that is isConnected AND whose name matches WH-/WF-/WI-/MDR-/XB/LinkBuds. "ULT WEAR" matches neither, so the app fell back to IOBluetoothDeviceSelectorController, which lists only discoverable devices and showed an empty list. - add "ULT" to the Sony name prefixes - if no connected match, fall back to any paired device that looks like a Sony headset (BLE/audio-only links report isConnected == NO) Assisted-by: Nikša Barlović Tested-by: Nikša Barlović --- Client/macos/HeadphonesBridge.mm | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Client/macos/HeadphonesBridge.mm b/Client/macos/HeadphonesBridge.mm index 4f1b58d3..59bb044c 100644 --- a/Client/macos/HeadphonesBridge.mm +++ b/Client/macos/HeadphonesBridge.mm @@ -124,7 +124,7 @@ - (BOOL)adaptiveVolume { return _hp && _hp->getAdaptiveVolume(); } static BOOL SHCLooksLikeSonyHeadset(NSString *name) { if (name.length == 0) return NO; - NSArray *prefixes = @[@"WH-", @"WF-", @"WI-", @"MDR-", @"XB", @"LinkBuds"]; + NSArray *prefixes = @[@"WH-", @"WF-", @"WI-", @"MDR-", @"XB", @"LinkBuds", @"ULT"]; for (NSString *p in prefixes) { if ([name hasPrefix:p] || [name containsString:p]) return YES; } @@ -141,6 +141,15 @@ - (void)scanAndConnectWithCompletion:(void (^)(BOOL, NSString * _Nullable))compl break; } } + // BLE/audio-only headsets (e.g. ULT WEAR) report isConnected == NO; fall back to any paired Sony headset. + if (!device) { + for (IOBluetoothDevice *paired in [IOBluetoothDevice pairedDevices]) { + if (SHCLooksLikeSonyHeadset([paired name])) { + device = paired; + break; + } + } + } if (!device) { // Fall back to the native picker if we can't auto-identify a connected Sony device. From f2ce53668ddcf3342e3113c48c8ab667459a668e Mon Sep 17 00:00:00 2001 From: Fred Date: Thu, 22 Oct 2026 19:08:53 -0300 Subject: [PATCH 21/35] feat(macos): multipoint device list, playback switching and fixing (v2) Adds Sound Connect's "Switch playback device and fix" for v2 headsets, so playback can be pinned to the Mac (e.g. for calls) and the phone can't take it over. Transport: BluetoothWrapper can now send and match on command table 2 (DATA_MDR_NO2, 0x0e) and ACKs table 2 frames. The tables are separate command spaces - in table 1, 0x30-0x3f are the firmware-update commands - so the multipoint opcodes only ever go out on 0x0e. Discovery (GETs only, v2 only, gated on the init reply advertising table 2): support functions (06 00), device list (36 02 / 36 00), fixed state (36 01), and the MULTIPOINT_SETTING general-setting slot found by name (d0 d1..d4), then its value (d6). Raw replies are kept for "Copy diagnostics". Writes (each refused locally unless discovery saw function 0x31): - switch playback: 3c 01
-> 3d 01
- fix / unfix: 38 01 00 / 01 -> 39 01 "Switch and fix" = unfix if fixed, switch, fix; if the switch is refused it re-fixes the old device. A plain switch unfixes afterwards, since the headset carries "fixed" across a switch. State is re-read after every write. UI: Devices card (connected/paired, playback and lock icons, This Mac tag, Fix/Unfix, per-device switch menu) and a menu-bar item with "Pin Playback to This Mac" whose icon shows the playback device (phone, computer or slot number). The device list is re-read every 10 s so the icon follows changes made from the phone. Opcodes and layouts from mos9527/SonyHeadphonesClient (ProtocolV2T2.hpp) and nullpoint. Verified on a WH-1000XM5 fw 2.5.1: list, switch, fix, unfix, and the FAIL_CALLING refusal (39 01 00 02) during a call. --- Client/BluetoothWrapper.cpp | 18 +- Client/BluetoothWrapper.h | 15 +- Client/Constants.h | 49 +++++ Client/Headphones.cpp | 292 +++++++++++++++++++++++++- Client/Headphones.h | 43 ++++ Client/macos/AppDelegate.mm | 2 + Client/macos/ContentView.swift | 323 ++++++++++++++++++++++++++++- Client/macos/HeadphonesBridge.h | 31 +++ Client/macos/HeadphonesBridge.mm | 137 ++++++++++++ Client/macos/HeadphonesModel.swift | 75 +++++++ 10 files changed, 967 insertions(+), 18 deletions(-) diff --git a/Client/BluetoothWrapper.cpp b/Client/BluetoothWrapper.cpp index cd3cb744..21d2b7c6 100644 --- a/Client/BluetoothWrapper.cpp +++ b/Client/BluetoothWrapper.cpp @@ -24,10 +24,10 @@ BluetoothWrapper& BluetoothWrapper::operator=(BluetoothWrapper&& other) noexcept return *this; } -int BluetoothWrapper::sendCommand(const std::vector& bytes) +int BluetoothWrapper::sendCommand(const std::vector& bytes, DATA_TYPE dataType) { std::lock_guard guard(this->_connectorMtx); - auto data = CommandSerializer::packageDataForBt(bytes, DATA_TYPE::DATA_MDR, this->_seqNumber++); + auto data = CommandSerializer::packageDataForBt(bytes, dataType, this->_seqNumber++); auto bytesSent = this->_connector->send(data.data(), data.size()); this->_waitForAck(); @@ -65,10 +65,11 @@ SonyProtocolVersion BluetoothWrapper::getProtocolVersion() noexcept return this->_connector->getProtocolVersion(); } -Buffer BluetoothWrapper::sendCommandAndReadResponse(const std::vector& bytes, unsigned char retCommandId, int retSubType) +Buffer BluetoothWrapper::sendCommandAndReadResponse(const std::vector& bytes, unsigned char retCommandId, int retSubType, + DATA_TYPE dataType) { std::lock_guard guard(this->_connectorMtx); - auto data = CommandSerializer::packageDataForBt(bytes, DATA_TYPE::DATA_MDR, this->_seqNumber++); + auto data = CommandSerializer::packageDataForBt(bytes, dataType, this->_seqNumber++); this->_connector->send(data.data(), data.size()); // The device replies with an ACK and then the RET frame; unrelated notifications may interleave. @@ -80,7 +81,7 @@ Buffer BluetoothWrapper::sendCommandAndReadResponse(const std::vector& byt this->_seqNumber = msg.seqNumber; continue; } - if (msg.dataType == DATA_TYPE::DATA_MDR && !msg.payload.empty() + if (msg.dataType == dataType && !msg.payload.empty() && (unsigned char)msg.payload[0] == retCommandId && (retSubType < 0 || (msg.payload.size() >= 2 && (unsigned char)msg.payload[1] == retSubType))) { @@ -150,9 +151,10 @@ CommandSerializer::Message BluetoothWrapper::_readMessage() auto msg = CommandSerializer::unpackBtMessage(msgBytes); - // The device retransmits any DATA_MDR frame it sends until the host ACKs it. The ack carries the - // toggled 1-bit sequence number (1 - deviceSeq), matching the device's own ack-to-us behaviour. - if (msg.dataType == DATA_TYPE::DATA_MDR) + // The device retransmits any DATA_MDR / DATA_MDR_NO2 frame it sends until the host ACKs it. The ack + // carries the toggled 1-bit sequence number (1 - deviceSeq), matching the device's own ack-to-us behaviour. + // Both tables share the one sequence counter. + if (msg.dataType == DATA_TYPE::DATA_MDR || msg.dataType == DATA_TYPE::DATA_MDR_NO2) { auto ack = CommandSerializer::packageDataForBt({}, DATA_TYPE::ACK, (unsigned char)(1 - msg.seqNumber)); this->_connector->send(ack.data(), ack.size()); diff --git a/Client/BluetoothWrapper.h b/Client/BluetoothWrapper.h index 612790c9..7a335a66 100644 --- a/Client/BluetoothWrapper.h +++ b/Client/BluetoothWrapper.h @@ -21,12 +21,15 @@ class BluetoothWrapper BluetoothWrapper(BluetoothWrapper&& other) noexcept; BluetoothWrapper& operator=(BluetoothWrapper&& other) noexcept; - int sendCommand(const std::vector& bytes); - - // Sends an inquiry command and returns the payload of the first DATA_MDR response whose command id - // (payload[0]) matches retCommandId, skipping the ACK and any unrelated notifications. When retSubType - // is >= 0, payload[1] must also match it (for multiplexed command families that share one opcode). - Buffer sendCommandAndReadResponse(const std::vector& bytes, unsigned char retCommandId, int retSubType = -1); + // dataType selects the command table: DATA_MDR (0x0c, table 1) or DATA_MDR_NO2 (0x0e, table 2). + // The two tables are separate command spaces - the same opcode means different things in each. + int sendCommand(const std::vector& bytes, DATA_TYPE dataType = DATA_TYPE::DATA_MDR); + + // Sends an inquiry command and returns the payload of the first response of the same dataType whose + // command id (payload[0]) matches retCommandId, skipping the ACK and any unrelated notifications. When + // retSubType is >= 0, payload[1] must also match it (for multiplexed command families that share one opcode). + Buffer sendCommandAndReadResponse(const std::vector& bytes, unsigned char retCommandId, int retSubType = -1, + DATA_TYPE dataType = DATA_TYPE::DATA_MDR); bool isConnected() noexcept; //Try to connect to the headphones diff --git a/Client/Constants.h b/Client/Constants.h index 91613ca9..8f3fa7e7 100644 --- a/Client/Constants.h +++ b/Client/Constants.h @@ -1,5 +1,6 @@ #pragma once +#include #include inline constexpr auto MAX_BLUETOOTH_MESSAGE_SIZE = 2048; @@ -55,6 +56,54 @@ namespace V2Command inline constexpr unsigned char BTNMODE_SET = 0xf8; // SET f8 inline constexpr unsigned char SUB_ADAPTIVE_VOLUME = 0x0a; inline constexpr unsigned char SUB_SPEAK_TO_CHAT = 0x0c; + // INIT_REPLY layout: 01 + inline constexpr size_t INIT_REPLY_TABLE2_INDEX = 7; + // General settings: up to four device-defined boolean/list settings in slots D1..D4. Which slot holds + // what is per-model, so the slot is found by name via GS_GET_CAPABILITY. Values: 00=ON, 01=OFF. + inline constexpr unsigned char GS_GET_CAPABILITY = 0xd0; // d0 + inline constexpr unsigned char GS_RET_CAPABILITY = 0xd1; // d1 name summary + inline constexpr unsigned char GS_GET_PARAM = 0xd6; // d6 + inline constexpr unsigned char GS_RET_PARAM = 0xd7; // d7 + inline constexpr unsigned char GS_SLOT_FIRST = 0xd1; + inline constexpr unsigned char GS_SLOT_LAST = 0xd4; + inline constexpr unsigned char GS_DISPLAY_LANGUAGE_ENGLISH = 0x01; +} + +// Second command table (frame DATA_TYPE::DATA_MDR_NO2 = 0x0e) on v2 devices: multipoint / paired-device +// management. Layouts from mos9527/SonyHeadphonesClient (ProtocolV2T2.hpp, generated from Sound Connect) +// and WF-1000XM5 / WH-1000XM6 captures. +// NEVER send these with DATA_MDR (0x0c): in table 1, 0x30-0x3f are the firmware-update (UPDT) commands. +namespace V2Table2Command +{ + inline constexpr unsigned char SUPPORT_FUNCTION_GET = 0x06; // 06 00 + inline constexpr unsigned char SUPPORT_FUNCTION_RET = 0x07; // 07 00 ( ) x n + inline constexpr unsigned char PERI_GET_PARAM = 0x36; // 36 + inline constexpr unsigned char PERI_RET_PARAM = 0x37; + inline constexpr unsigned char PERI_SET_PARAM = 0x38; // 38 01 <00=fix playback, 01=free> + inline constexpr unsigned char PERI_NTFY_PARAM = 0x39; // 39 01 + inline constexpr unsigned char PERI_SET_EXTENDED_PARAM = 0x3c; // 3c 01 + inline constexpr unsigned char PERI_NTFY_EXTENDED_PARAM = 0x3d; // 3d 01 + + // Source-switch results (switch / fix writes). NO_CONFIRMATION is ours: no notify within the timeout. + inline constexpr int RESULT_SUCCESS = 0x00; + inline constexpr int RESULT_FAIL = 0x01; + inline constexpr int RESULT_FAIL_CALLING = 0x02; + inline constexpr int RESULT_FAIL_A2DP_NOT_CONNECTED = 0x03; + inline constexpr int RESULT_FAIL_VOICE_ASSISTANT = 0x04; + inline constexpr int RESULT_NO_CONFIRMATION = -1; + + // Inquired types (payload[1] of the PERI_* commands). + inline constexpr unsigned char PERI_DEVICES_CLASSIC = 0x00; // device list without class of device + inline constexpr unsigned char PERI_SOURCE_SWITCH = 0x01; // 37 01 <1=switching free, 0=playback fixed> + inline constexpr unsigned char PERI_DEVICES_WITH_COD = 0x02; // device list with class of device + + // Function ids in the SUPPORT_FUNCTION_RET list. + inline constexpr unsigned char FN_DEVICES_CLASSIC = 0x30; + inline constexpr unsigned char FN_SOURCE_SWITCH = 0x31; + inline constexpr unsigned char FN_DEVICES_WITH_COD = 0x32; + inline constexpr unsigned char FN_DEVICES_WITH_COD_LE = 0x33; + + inline constexpr size_t BT_ADDRESS_LENGTH = 17; // ASCII "XX:XX:XX:XX:XX:XX", no terminator } // v2 equalizer preset ids (byte value sent/received at EQ payload[2]). diff --git a/Client/Headphones.cpp b/Client/Headphones.cpp index 54d010f2..13a0ce71 100644 --- a/Client/Headphones.cpp +++ b/Client/Headphones.cpp @@ -5,6 +5,7 @@ #include #include #include +#include Headphones::Headphones(BluetoothWrapper& conn) : _conn(conn) { @@ -77,12 +78,16 @@ int Headphones::getVptType() void Headphones::initDevice() { - // v2 devices expect an init handshake before they answer GET inquiries. Best-effort: the reply - // (INIT_REPLY, 8 bytes on v2) is ignored here - we only need the device to enter the ready state. - this->_conn.sendCommandAndReadResponse( + // v2 devices expect an init handshake before they answer GET inquiries. The reply (INIT_REPLY, 8 bytes + // on v2) also says whether the device has command table 2, which gates every multipoint read. + auto resp = this->_conn.sendCommandAndReadResponse( { (char)V2Command::INIT_REQUEST, 0x00 }, V2Command::INIT_REPLY ); + std::lock_guard guard(this->_propertyMtx); + this->_initReply = resp; + this->_table2Supported = resp.size() > V2Command::INIT_REPLY_TABLE2_INDEX + && resp[V2Command::INIT_REPLY_TABLE2_INDEX] == 0x00; } void Headphones::requestBattery() @@ -373,6 +378,287 @@ void Headphones::setAdaptiveVolume(bool enabled) this->_adaptiveVolume = enabled; } +// --- Multipoint (read-only) --- + +namespace +{ + std::string hexString(const Buffer& bytes) + { + static const char digits[] = "0123456789abcdef"; + std::string out; + for (size_t i = 0; i < bytes.size(); i++) + { + auto b = (unsigned char)bytes[i]; + if (i > 0) out += ' '; + out += digits[b >> 4]; + out += digits[b & 0x0f]; + } + return out; + } + + // 37 { [] } x count + // Returns false (and leaves `out` untouched) on any length mismatch, so a misread never reaches the UI. + bool parsePairedDevices(const Buffer& resp, bool withClassOfDevice, std::vector& out) + { + if (resp.size() < 4) return false; + size_t pos = 2; + size_t count = (unsigned char)resp[pos++]; + std::vector devices; + for (size_t i = 0; i < count; i++) + { + size_t fixed = V2Table2Command::BT_ADDRESS_LENGTH + 1 + (withClassOfDevice ? 3 : 0) + 1; + if (pos + fixed > resp.size()) return false; + PairedDevice device; + device.address.assign(resp.begin() + pos, resp.begin() + pos + V2Table2Command::BT_ADDRESS_LENGTH); + pos += V2Table2Command::BT_ADDRESS_LENGTH; + device.slot = (unsigned char)resp[pos++]; + if (withClassOfDevice) + { + device.classOfDevice = ((unsigned char)resp[pos] << 16) | ((unsigned char)resp[pos + 1] << 8) | (unsigned char)resp[pos + 2]; + pos += 3; + } + size_t nameLength = (unsigned char)resp[pos++]; + if (pos + nameLength > resp.size()) return false; + device.name.assign(resp.begin() + pos, resp.begin() + pos + nameLength); + pos += nameLength; + devices.push_back(device); + } + if (pos + 1 != resp.size()) return false; + // The trailing byte is the slot (1/2) that holds playback, not an index into the list. + int playbackSlot = (unsigned char)resp[pos]; + for (auto& device : devices) + { + device.playback = device.slot != 0 && device.slot == playbackSlot; + } + out = devices; + return true; + } +} + +void Headphones::requestMultipoint() +{ + if (this->_conn.getProtocolVersion() != SonyProtocolVersion::V2) return; + + Buffer initReply; + bool table2Supported; + bool functionsRead; + std::vector functions; + bool slotSearched; + int slot; + std::string discoveryLog; + { + std::lock_guard guard(this->_propertyMtx); + initReply = this->_initReply; + table2Supported = this->_table2Supported; + functionsRead = this->_table2FunctionsRead; + functions = this->_table2Functions; + slotSearched = this->_multipointSlotSearched; + slot = this->_multipointSlot; + discoveryLog = this->_multipointDiscoveryLog; + } + + // One-time discovery reads (support functions, slot search) go to discoveryLog so a later refresh + // still shows them; per-refresh reads go to log. + std::string log; + std::string* target = &discoveryLog; + auto read = [&](const Buffer& cmd, unsigned char retCommandId, int retSubType, DATA_TYPE dataType) -> Buffer { + std::string label = dataType == DATA_TYPE::DATA_MDR_NO2 ? "T2 " : "T1 "; + try + { + auto resp = this->_conn.sendCommandAndReadResponse(cmd, retCommandId, retSubType, dataType); + *target += label + hexString(cmd) + " -> " + hexString(resp) + "\n"; + return resp; + } + catch (const std::exception& exc) + { + *target += label + hexString(cmd) + " -> (" + exc.what() + ")\n"; + return {}; + } + }; + + bool hasPairedDevices = false; std::vector pairedDevices; + bool hasPinState = false; bool pinned = false; + if (!table2Supported) + { + log += "table 2 not advertised in the init reply; skipped the device list\n"; + } + else + { + if (!functionsRead) + { + target = &discoveryLog; + // 07 00 ( ) x n + auto resp = read({ (char)V2Table2Command::SUPPORT_FUNCTION_GET, 0x00 }, + V2Table2Command::SUPPORT_FUNCTION_RET, 0x00, DATA_TYPE::DATA_MDR_NO2); + if (resp.size() >= 3) + { + size_t count = (unsigned char)resp[2]; + for (size_t i = 0; i < count && 3 + i * 2 < resp.size(); i++) + { + functions.push_back((unsigned char)resp[3 + i * 2]); + } + functionsRead = true; + } + } + target = &log; + auto supports = [&](unsigned char function) { + return std::find(functions.begin(), functions.end(), function) != functions.end(); + }; + + bool withClassOfDevice = supports(V2Table2Command::FN_DEVICES_WITH_COD) || supports(V2Table2Command::FN_DEVICES_WITH_COD_LE); + if (withClassOfDevice || supports(V2Table2Command::FN_DEVICES_CLASSIC)) + { + unsigned char type = withClassOfDevice ? V2Table2Command::PERI_DEVICES_WITH_COD : V2Table2Command::PERI_DEVICES_CLASSIC; + auto resp = read({ (char)V2Table2Command::PERI_GET_PARAM, (char)type }, + V2Table2Command::PERI_RET_PARAM, type, DATA_TYPE::DATA_MDR_NO2); + hasPairedDevices = parsePairedDevices(resp, withClassOfDevice, pairedDevices); + if (!resp.empty() && !hasPairedDevices) log += "device list: unexpected layout\n"; + } + + if (supports(V2Table2Command::FN_SOURCE_SWITCH)) + { + // 37 01 : 1 = playback switches freely, 0 = playback device fixed. + auto resp = read({ (char)V2Table2Command::PERI_GET_PARAM, (char)V2Table2Command::PERI_SOURCE_SWITCH }, + V2Table2Command::PERI_RET_PARAM, V2Table2Command::PERI_SOURCE_SWITCH, DATA_TYPE::DATA_MDR_NO2); + if (resp.size() >= 3) + { + hasPinState = true; + pinned = resp[2] == 0x00; + } + } + } + + // The multipoint on/off switch is a table 1 general setting whose slot (D1..D4) differs per model: + // find it by name once per connection, then just read its value. + if (!slotSearched) + { + target = &discoveryLog; + for (int candidate = V2Command::GS_SLOT_FIRST; candidate <= V2Command::GS_SLOT_LAST; candidate++) + { + // d1 + auto resp = read({ (char)V2Command::GS_GET_CAPABILITY, (char)candidate, (char)V2Command::GS_DISPLAY_LANGUAGE_ENGLISH }, + V2Command::GS_RET_CAPABILITY, candidate, DATA_TYPE::DATA_MDR); + if (resp.size() < 5 || resp[2] != 0x00) continue; + size_t nameLength = (unsigned char)resp[4]; + if (5 + nameLength > resp.size()) continue; + if (std::string(resp.begin() + 5, resp.begin() + 5 + nameLength) == "MULTIPOINT_SETTING") + { + slot = candidate; + break; + } + } + slotSearched = true; + } + target = &log; + + bool hasMultipointSetting = false; bool multipointEnabled = false; + if (slot > 0) + { + // d7 + auto resp = read({ (char)V2Command::GS_GET_PARAM, (char)slot }, V2Command::GS_RET_PARAM, slot, DATA_TYPE::DATA_MDR); + if (resp.size() >= 4 && resp[2] == 0x00) + { + hasMultipointSetting = true; + multipointEnabled = resp[3] == 0x00; + } + } + + std::lock_guard guard(this->_propertyMtx); + this->_table2FunctionsRead = functionsRead; + this->_table2Functions = functions; + this->_multipointSlotSearched = slotSearched; + this->_multipointSlot = slot; + this->_hasPairedDevices = hasPairedDevices; + this->_pairedDevices = pairedDevices; + this->_hasPlaybackPinState = hasPinState; + this->_playbackPinned = pinned; + this->_hasMultipointSetting = hasMultipointSetting; + this->_multipointEnabled = multipointEnabled; + this->_multipointDiscoveryLog = discoveryLog; + this->_multipointDiagnostics = "init " + (initReply.empty() ? std::string("(no reply)") : hexString(initReply)) + "\n" + + discoveryLog + this->_multipointWriteLog + log; +} + +int Headphones::switchPlaybackDevice(const std::string& address) +{ + std::string target; + { + std::lock_guard guard(this->_propertyMtx); + bool supported = this->_table2Supported && std::find(this->_table2Functions.begin(), this->_table2Functions.end(), + V2Table2Command::FN_SOURCE_SWITCH) != this->_table2Functions.end(); + if (!supported) throw RecoverableException("This headset doesn't support switching the playback device."); + auto sameAddress = [&](const std::string& other) { + return other.size() == address.size() && std::equal(other.begin(), other.end(), address.begin(), + [](char a, char b) { return std::toupper((unsigned char)a) == std::toupper((unsigned char)b); }); + }; + for (const auto& device : this->_pairedDevices) + { + if (device.slot != 0 && sameAddress(device.address)) target = device.address; + } + } + if (target.size() != V2Table2Command::BT_ADDRESS_LENGTH) + { + throw RecoverableException("That device isn't connected to the headset."); + } + + // SET: 3c 01 -> NTFY: 3d 01
+ Buffer cmd = { (char)V2Table2Command::PERI_SET_EXTENDED_PARAM, (char)V2Table2Command::PERI_SOURCE_SWITCH }; + cmd.insert(cmd.end(), target.begin(), target.end()); + int result = V2Table2Command::RESULT_NO_CONFIRMATION; + std::string line = "W T2 " + hexString(cmd) + " -> "; + try + { + auto resp = this->_conn.sendCommandAndReadResponse(cmd, V2Table2Command::PERI_NTFY_EXTENDED_PARAM, + V2Table2Command::PERI_SOURCE_SWITCH, DATA_TYPE::DATA_MDR_NO2); + line += hexString(resp); + if (resp.size() >= 3) result = (unsigned char)resp[2]; + } + catch (const std::exception& exc) + { + line += std::string("(") + exc.what() + ")"; + } + std::lock_guard guard(this->_propertyMtx); + this->_multipointWriteLog += line + "\n"; + return result; +} + +int Headphones::setPlaybackPinned(bool pinned) +{ + { + std::lock_guard guard(this->_propertyMtx); + if (!this->_hasPlaybackPinState) throw RecoverableException("This headset doesn't support fixing the playback device."); + } + + // SET: 38 01 <00=fixed, 01=free> -> NTFY: 39 01 + char value = pinned ? 0x00 : 0x01; + Buffer cmd = { (char)V2Table2Command::PERI_SET_PARAM, (char)V2Table2Command::PERI_SOURCE_SWITCH, value }; + int result = V2Table2Command::RESULT_NO_CONFIRMATION; + std::string line = "W T2 " + hexString(cmd) + " -> "; + try + { + auto resp = this->_conn.sendCommandAndReadResponse(cmd, V2Table2Command::PERI_NTFY_PARAM, + V2Table2Command::PERI_SOURCE_SWITCH, DATA_TYPE::DATA_MDR_NO2); + line += hexString(resp); + if (resp.size() >= 4) result = (unsigned char)resp[3]; + else if (resp.size() == 3) result = resp[2] == value ? V2Table2Command::RESULT_SUCCESS : V2Table2Command::RESULT_FAIL; + } + catch (const std::exception& exc) + { + line += std::string("(") + exc.what() + ")"; + } + std::lock_guard guard(this->_propertyMtx); + this->_multipointWriteLog += line + "\n"; + return result; +} + +bool Headphones::hasPairedDevices() { std::lock_guard g(this->_propertyMtx); return this->_hasPairedDevices; } +std::vector Headphones::getPairedDevices() { std::lock_guard g(this->_propertyMtx); return this->_pairedDevices; } +bool Headphones::hasPlaybackPinState() { std::lock_guard g(this->_propertyMtx); return this->_hasPlaybackPinState; } +bool Headphones::isPlaybackPinned() { std::lock_guard g(this->_propertyMtx); return this->_playbackPinned; } +bool Headphones::hasMultipointSetting() { std::lock_guard g(this->_propertyMtx); return this->_hasMultipointSetting; } +bool Headphones::getMultipointEnabled() { std::lock_guard g(this->_propertyMtx); return this->_multipointEnabled; } +std::string Headphones::getMultipointDiagnostics() { std::lock_guard g(this->_propertyMtx); return this->_multipointDiagnostics; } + bool Headphones::isChanged() { return !(this->_ambientSoundControl.isFulfilled() && this->_asmLevel.isFulfilled() && this->_focusOnVoice.isFulfilled() && this->_surroundPosition.isFulfilled() && this->_vptType.isFulfilled()); diff --git a/Client/Headphones.h b/Client/Headphones.h index 6197d569..19520ce2 100644 --- a/Client/Headphones.h +++ b/Client/Headphones.h @@ -3,6 +3,18 @@ #include "Constants.h" #include +#include +#include + +// One entry of the headset's paired-device list (multipoint, v2 table 2). +struct PairedDevice +{ + std::string address; // "XX:XX:XX:XX:XX:XX", as the headset reports it + std::string name; // may be empty + int slot = 0; // multipoint slot: 0 = paired but not connected, 1/2 = connected + int classOfDevice = -1; // 24-bit Bluetooth class of device; -1 if not reported, 0xFFFFFF for paired-only + bool playback = false; // currently holds the playback (A2DP) right +}; template struct Property { @@ -86,6 +98,26 @@ class Headphones { bool getAdaptiveVolume(); void setAdaptiveVolume(bool enabled); + // Multipoint (v2, read-only). Only GETs are sent, and the table 2 reads only when initDevice()'s reply + // says the device has command table 2. Each piece is exposed only if the device answered it. + void requestMultipoint(); + bool hasPairedDevices(); + std::vector getPairedDevices(); + bool hasPlaybackPinState(); + bool isPlaybackPinned(); + bool hasMultipointSetting(); + bool getMultipointEnabled(); + // Hex log of the init reply and every multipoint request/reply from the last requestMultipoint(), + // for bringing the protocol up on models nobody has captured yet. + std::string getMultipointDiagnostics(); + + // Multipoint writes. Each sends exactly one command and returns a V2Table2Command::RESULT_* code. They + // throw RecoverableException (without sending) unless requestMultipoint() saw the device advertise + // source-switch control. Call requestMultipoint() afterwards to read back the real state. + // switchPlaybackDevice: the address must be a connected device from the last device list. + int switchPlaybackDevice(const std::string& address); + int setPlaybackPinned(bool pinned); + bool isChanged(); void setChanges(); private: @@ -112,6 +144,17 @@ class Headphones { bool _hasSpeakToChat = false; bool _speakToChat = false; bool _hasAdaptiveVolume = false; bool _adaptiveVolume = false; + Buffer _initReply; + bool _table2Supported = false; + bool _table2FunctionsRead = false; std::vector _table2Functions; + bool _hasPairedDevices = false; std::vector _pairedDevices; + bool _hasPlaybackPinState = false; bool _playbackPinned = false; + bool _multipointSlotSearched = false; int _multipointSlot = -1; + bool _hasMultipointSetting = false; bool _multipointEnabled = false; + std::string _multipointDiscoveryLog; + std::string _multipointWriteLog; + std::string _multipointDiagnostics; + std::mutex _propertyMtx; BluetoothWrapper& _conn; diff --git a/Client/macos/AppDelegate.mm b/Client/macos/AppDelegate.mm index 5d09dc3e..7339a465 100644 --- a/Client/macos/AppDelegate.mm +++ b/Client/macos/AppDelegate.mm @@ -6,6 +6,7 @@ // #import "AppDelegate.h" +#import "SonyHeadphonesClient-Swift.h" @interface AppDelegate () @@ -15,6 +16,7 @@ @interface AppDelegate () @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { _window = [[[NSApplication sharedApplication] windows] firstObject]; + [MenuBarController install]; } - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag diff --git a/Client/macos/ContentView.swift b/Client/macos/ContentView.swift index 45b0388a..e7ceb6cb 100644 --- a/Client/macos/ContentView.swift +++ b/Client/macos/ContentView.swift @@ -5,6 +5,7 @@ import SwiftUI import AppKit +import Combine private enum Theme { static let bg = Color(red: 0.07, green: 0.07, blue: 0.086) @@ -16,7 +17,7 @@ private enum Theme { @available(macOS 11.0, *) struct ContentView: View { - @StateObject private var model = HeadphonesModel() + @StateObject private var model = HeadphonesModel.shared @State private var showAbout = false var body: some View { @@ -82,6 +83,9 @@ struct ContentView: View { if model.hasAdaptiveVolume || model.hasSpeakToChat || model.hasAutoPowerOff { settingsCard } + if !model.multipointDiagnostics.isEmpty { + devicesCard + } if let error = model.errorMessage { Text(error) .font(.system(size: 12)) @@ -387,6 +391,156 @@ struct ContentView: View { .toggleStyle(SwitchToggleStyle(tint: Theme.accent)) } + // Multipoint device list. Read-only for now: nothing here sends a command that changes the headset. + private var devicesCard: some View { + VStack(alignment: .leading, spacing: 14) { + HStack { + Text("Devices") + .font(.system(size: 15, weight: .semibold)) + .foregroundColor(.white) + Spacer() + Button(action: model.refreshMultipoint) { + Image(systemName: "arrow.clockwise") + .font(.system(size: 12, weight: .semibold)) + .foregroundColor(Theme.secondary) + } + .buttonStyle(PlainButtonStyle()) + .disabled(model.refreshingMultipoint) + .opacity(model.refreshingMultipoint ? 0.4 : 1) + } + if model.hasMultipointSetting { + devicesInfoRow("Connect to 2 devices", model.multipointEnabled ? "On" : "Off") + } + if model.hasPlaybackPinState { + HStack { + VStack(alignment: .leading, spacing: 2) { + Text("Playback device").font(.system(size: 13, weight: .medium)).foregroundColor(.white) + Text(model.playbackPinned ? "Fixed" : "Switches automatically") + .font(.system(size: 11)).foregroundColor(Theme.secondary) + } + Spacer() + Button(action: { model.setPlaybackPinned(!model.playbackPinned) }) { + Text(model.playbackPinned ? "Unfix" : "Fix") + .font(.system(size: 12, weight: .semibold)) + .foregroundColor(.white) + .padding(.horizontal, 12) + .padding(.vertical, 5) + .background(Theme.cardHi) + .clipShape(Capsule()) + } + .buttonStyle(PlainButtonStyle()) + .disabled(model.multipointBusy) + } + } + if model.hasPairedDevices { + let connected = model.pairedDevices.filter { $0.connected }.sorted { $0.slot < $1.slot } + let paired = model.pairedDevices.filter { !$0.connected } + if !connected.isEmpty { + devicesSectionLabel("Connected") + ForEach(connected) { deviceRow($0) } + } + if !paired.isEmpty { + devicesSectionLabel("Paired") + ForEach(paired) { deviceRow($0) } + } + } else { + Text("This headset didn't return a device list.") + .font(.system(size: 12)) + .foregroundColor(Theme.secondary) + } + Divider().background(Theme.cardHi) + HStack { + Text(model.multipointBusy ? "Sending…" : "Switching and fixing are experimental") + .font(.system(size: 11)) + .foregroundColor(Theme.secondary.opacity(0.7)) + Spacer() + Button(action: copyMultipointDiagnostics) { + Text("Copy diagnostics") + .font(.system(size: 11, weight: .medium)) + .foregroundColor(Theme.accent) + } + .buttonStyle(PlainButtonStyle()) + } + } + .padding(18) + .frame(maxWidth: .infinity, alignment: .leading) + .background(Theme.card) + .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) + } + + private func devicesInfoRow(_ label: String, _ value: String) -> some View { + HStack { + Text(label).font(.system(size: 13, weight: .medium)).foregroundColor(.white) + Spacer() + Text(value).font(.system(size: 12)).foregroundColor(Theme.secondary) + } + } + + private func devicesSectionLabel(_ text: String) -> some View { + Text(text.uppercased()) + .font(.system(size: 10, weight: .semibold)) + .foregroundColor(Theme.secondary.opacity(0.8)) + .padding(.top, 2) + } + + private func deviceRow(_ device: PairedDeviceInfo) -> some View { + HStack(spacing: 12) { + Image(systemName: deviceSymbol(device.classOfDevice)) + .font(.system(size: 15)) + .foregroundColor(device.connected ? .white : Theme.secondary) + .frame(width: 22) + VStack(alignment: .leading, spacing: 2) { + Text(device.name.isEmpty ? device.address : device.name) + .font(.system(size: 13, weight: .medium)) + .foregroundColor(device.connected ? .white : Theme.secondary) + .lineLimit(1) + if device.isThisMac { + Text("This Mac").font(.system(size: 11)).foregroundColor(Theme.accent) + } + } + Spacer() + if device.playback { + if model.playbackPinned { + Image(systemName: "lock.fill") + .font(.system(size: 11)) + .foregroundColor(Theme.accent) + } + Image(systemName: "speaker.wave.2.fill") + .font(.system(size: 12)) + .foregroundColor(Theme.accent) + } + if device.connected && model.hasPlaybackPinState { + Menu { + Button("Switch playback device and fix") { model.switchPlayback(to: device, fix: true) } + if !device.playback { + Button("Switch playback device") { model.switchPlayback(to: device, fix: false) } + } + } label: { + Image(systemName: "ellipsis") + } + .menuStyle(BorderlessButtonMenuStyle()) + .fixedSize() + .disabled(model.multipointBusy) + } + } + } + + // Major device class lives in bits 8-12 of the class of device (1 = computer, 2 = phone). + private func deviceSymbol(_ classOfDevice: Int) -> String { + guard classOfDevice >= 0, classOfDevice != 0xFFFFFF else { return "dot.radiowaves.left.and.right" } + switch (classOfDevice >> 8) & 0x1F { + case 1: return "laptopcomputer" + case 2: return "iphone" + default: return "dot.radiowaves.left.and.right" + } + } + + private func copyMultipointDiagnostics() { + let header = "\(model.deviceName) · fw \(model.firmware) · \(model.protocolVersion)\n" + NSPasteboard.general.clearContents() + NSPasteboard.general.setString(header + model.multipointDiagnostics, forType: .string) + } + // ⋯ About / device info popover. private var aboutView: some View { VStack(alignment: .leading, spacing: 0) { @@ -439,6 +593,173 @@ struct ContentView: View { } } +// MARK: - Menu bar + +// Status-bar item for pinning playback to this Mac without opening the window. Installed once from +// AppDelegate; reads and drives the same HeadphonesModel as the window. The icon shows the playback device +// next to the headphones (phone, computer, or its multipoint slot number), and the headphones fill in +// while playback is fixed to this Mac. +@objc final class MenuBarController: NSObject, NSMenuDelegate { + private static var instance: MenuBarController? + + private let model = HeadphonesModel.shared + private let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) + private var cancellables = Set() + + @objc static func install() { + guard instance == nil else { return } + instance = MenuBarController() + } + + private override init() { + super.init() + let menu = NSMenu() + menu.delegate = self + menu.autoenablesItems = false + statusItem.menu = menu + updateIcon() + // objectWillChange fires before the new values land, so read them on the next main-loop turn. + model.objectWillChange + .sink { [weak self] _ in DispatchQueue.main.async { self?.updateIcon() } } + .store(in: &cancellables) + } + + private var thisMac: PairedDeviceInfo? { + model.pairedDevices.first { $0.isThisMac && $0.connected } + } + + private var pinnedToThisMac: Bool { + model.playbackPinned && thisMac?.playback == true + } + + private var playbackDevice: PairedDeviceInfo? { + model.connected ? model.pairedDevices.first { $0.playback } : nil + } + + // Phone if the name says so, computer for this Mac (or another Mac), otherwise the slot number. + private func playbackSymbol(for device: PairedDeviceInfo) -> String { + let name = device.name.lowercased() + if name.contains("phone") { return "iphone" } + if device.isThisMac || name.contains("mac") { return "laptopcomputer" } + return "\(device.slot).circle" + } + + private func updateIcon() { + let base = pinnedToThisMac ? "headphones.circle.fill" : "headphones" + let device = playbackDevice + statusItem.button?.image = Self.icon(base: base, accessory: device.map(playbackSymbol(for:))) + statusItem.button?.appearsDisabled = !model.connected + if let device = device { + let name = device.name.isEmpty ? device.address : device.name + statusItem.button?.toolTip = "Playing on \(name)" + (model.playbackPinned ? " (fixed)" : "") + } else { + statusItem.button?.toolTip = model.connected ? model.deviceName : "SonyBridge" + } + } + + // Draws the headphones symbol with an optional second symbol beside it, as one template image. + private static func icon(base: String, accessory: String?) -> NSImage? { + let baseConfig = NSImage.SymbolConfiguration(pointSize: 14, weight: .regular) + let accessoryConfig = NSImage.SymbolConfiguration(pointSize: 11, weight: .regular) + guard let baseImage = NSImage(systemSymbolName: base, accessibilityDescription: "SonyBridge")? + .withSymbolConfiguration(baseConfig) else { return nil } + guard let accessory = accessory, + let accessoryImage = NSImage(systemSymbolName: accessory, accessibilityDescription: nil)? + .withSymbolConfiguration(accessoryConfig) else { + baseImage.isTemplate = true + return baseImage + } + let spacing: CGFloat = 2 + let size = NSSize(width: baseImage.size.width + spacing + accessoryImage.size.width, + height: max(baseImage.size.height, accessoryImage.size.height)) + let image = NSImage(size: size, flipped: false) { _ in + baseImage.draw(in: NSRect(x: 0, y: (size.height - baseImage.size.height) / 2, + width: baseImage.size.width, height: baseImage.size.height)) + accessoryImage.draw(in: NSRect(x: baseImage.size.width + spacing, y: (size.height - accessoryImage.size.height) / 2, + width: accessoryImage.size.width, height: accessoryImage.size.height)) + return true + } + image.isTemplate = true + image.accessibilityDescription = "SonyBridge" + return image + } + + func menuNeedsUpdate(_ menu: NSMenu) { + menu.removeAllItems() + if model.connected { + menu.addItem(disabledItem(model.deviceName)) + if model.hasPlaybackPinState { + if thisMac != nil { + let pin = actionItem(pinnedToThisMac ? "Playback Fixed to This Mac" : "Pin Playback to This Mac", + #selector(pinToThisMac)) + pin.state = pinnedToThisMac ? .on : .off + pin.isEnabled = !pinnedToThisMac && !model.multipointBusy + menu.addItem(pin) + } else { + menu.addItem(disabledItem("This Mac isn't a connected device")) + } + if model.playbackPinned { + let unfix = actionItem("Unfix Playback", #selector(unfixPlayback)) + unfix.isEnabled = !model.multipointBusy + menu.addItem(unfix) + } + } + if model.multipointBusy { + menu.addItem(disabledItem("Sending…")) + } else if let error = model.errorMessage { + menu.addItem(disabledItem(error)) + } + // Re-read so the next open reflects changes made from the phone or the headset. + if !model.multipointBusy && !model.refreshingMultipoint { + model.refreshMultipoint() + } + } else { + menu.addItem(disabledItem("No headphones connected")) + let connect = actionItem(model.connecting ? "Connecting…" : "Connect Headphones", #selector(connectHeadphones)) + connect.isEnabled = !model.connecting + menu.addItem(connect) + } + menu.addItem(.separator()) + menu.addItem(actionItem("Open SonyBridge", #selector(openWindow))) + menu.addItem(actionItem("Quit SonyBridge", #selector(quit), key: "q")) + } + + @objc private func pinToThisMac() { + guard let thisMac = thisMac else { return } + model.switchPlayback(to: thisMac, fix: true) + } + + @objc private func unfixPlayback() { + model.setPlaybackPinned(false) + } + + @objc private func connectHeadphones() { + NSApp.activate(ignoringOtherApps: true) + model.connect() + } + + @objc private func openWindow() { + NSApp.activate(ignoringOtherApps: true) + NSApp.windows.first { $0.contentViewController != nil }?.makeKeyAndOrderFront(nil) + } + + @objc private func quit() { + NSApp.terminate(nil) + } + + private func actionItem(_ title: String, _ action: Selector, key: String = "") -> NSMenuItem { + let item = NSMenuItem(title: title, action: action, keyEquivalent: key) + item.target = self + return item + } + + private func disabledItem(_ title: String) -> NSMenuItem { + let item = NSMenuItem(title: title, action: nil, keyEquivalent: "") + item.isEnabled = false + return item + } +} + // Factory so the Obj-C++ ViewController can instantiate the SwiftUI hierarchy. @available(macOS 11.0, *) @objc final class HeadphonesUIFactory: NSObject { diff --git a/Client/macos/HeadphonesBridge.h b/Client/macos/HeadphonesBridge.h index dfbdd039..a049b9d3 100644 --- a/Client/macos/HeadphonesBridge.h +++ b/Client/macos/HeadphonesBridge.h @@ -14,6 +14,16 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { SHCAmbientModeAmbientSound = 2, }; +// One entry of the headset's paired-device list (multipoint). +@interface SHCPairedDevice : NSObject +@property (nonatomic, copy, readonly) NSString *name; +@property (nonatomic, copy, readonly) NSString *address; // "XX:XX:XX:XX:XX:XX" +@property (nonatomic, readonly) NSInteger slot; // 0 = paired only, 1/2 = connected +@property (nonatomic, readonly) NSInteger classOfDevice; // 24-bit Bluetooth CoD, -1 if not reported +@property (nonatomic, readonly) BOOL playback; // holds the playback right +@property (nonatomic, readonly) BOOL isThisMac; +@end + @interface HeadphonesBridge : NSObject @property (nonatomic, readonly) BOOL connected; @@ -54,6 +64,15 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { @property (nonatomic, readonly) BOOL hasAdaptiveVolume; @property (nonatomic, readonly) BOOL adaptiveVolume; +// Multipoint (read-only; v2 devices that answered the reads on connect or on refreshMultipoint). +@property (nonatomic, readonly) BOOL hasPairedDevices; +@property (nonatomic, copy, readonly) NSArray *pairedDevices; +@property (nonatomic, readonly) BOOL hasPlaybackPinState; +@property (nonatomic, readonly) BOOL playbackPinned; +@property (nonatomic, readonly) BOOL hasMultipointSetting; +@property (nonatomic, readonly) BOOL multipointEnabled; +@property (nonatomic, copy, readonly) NSString *multipointDiagnostics; // hex log of the last multipoint reads + // Runs the native Bluetooth device picker (modal, main thread) and connects to the chosen device. // completion is called on the main thread. - (void)scanAndConnectWithCompletion:(void (^)(BOOL ok, NSString * _Nullable error))completion; @@ -89,6 +108,18 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { // own button show up in the app. Called on a timer while connected. - (void)refreshDynamicWithCompletion:(void (^)(void))completion; +// Re-reads the paired-device list, pinned state and multipoint switch (GETs only); completion on main. +- (void)refreshMultipointWithCompletion:(void (^)(void))completion; + +// Moves playback to a connected device (address from pairedDevices). With fix=YES it is Sound Connect's +// "Switch playback device and fix": unfix if fixed, switch (skipped if it already plays), then fix - +// stopping at the first refused step. With fix=NO it switches, then unfixes if playback was fixed, so it +// ends switching freely. State is re-read from the headset afterwards; completion on main. +- (void)switchPlaybackToAddress:(NSString *)address fix:(BOOL)fix completion:(void (^)(BOOL ok, NSString * _Nullable error))completion; + +// Fixes (pins) or frees the current playback device; one write, then a re-read. Completion on main. +- (void)setPlaybackPinned:(BOOL)pinned completion:(void (^)(BOOL ok, NSString * _Nullable error))completion; + @end NS_ASSUME_NONNULL_END diff --git a/Client/macos/HeadphonesBridge.mm b/Client/macos/HeadphonesBridge.mm index 4f1b58d3..12a399a6 100644 --- a/Client/macos/HeadphonesBridge.mm +++ b/Client/macos/HeadphonesBridge.mm @@ -14,6 +14,23 @@ // RecoverableException comes in transitively via BluetoothWrapper.h -> IBluetoothConnector.h -> Exceptions.h. // (Exceptions.h isn't a project file reference, so it can't be #included directly from this directory.) +@interface SHCPairedDevice () +@property (nonatomic, copy, readwrite) NSString *name; +@property (nonatomic, copy, readwrite) NSString *address; +@property (nonatomic, readwrite) NSInteger slot; +@property (nonatomic, readwrite) NSInteger classOfDevice; +@property (nonatomic, readwrite) BOOL playback; +@property (nonatomic, readwrite) BOOL isThisMac; +@end + +@implementation SHCPairedDevice +@end + +// IOBluetooth formats addresses as "aa-bb-cc-dd-ee-ff"; the headset reports "AA:BB:CC:DD:EE:FF". +static NSString *SHCNormalizedAddress(NSString *address) { + return [[address uppercaseString] stringByReplacingOccurrencesOfString:@"-" withString:@":"]; +} + @implementation HeadphonesBridge { std::unique_ptr _bt; std::unique_ptr _hp; @@ -23,12 +40,16 @@ @implementation HeadphonesBridge { // All user-initiated commands run on this SERIAL queue so quick successive taps reach the device in // order (a concurrent queue let them race and land out of order). dispatch_queue_t _cmdQueue; + // Multipoint reads can take several seconds (unanswered slot probes time out), so they get their own + // serial queue instead of holding up user taps on _cmdQueue. + dispatch_queue_t _multipointQueue; } - (instancetype)init { if ((self = [super init])) { _bt = std::make_unique(std::make_unique()); _cmdQueue = dispatch_queue_create("com.sonybridge.commands", DISPATCH_QUEUE_SERIAL); + _multipointQueue = dispatch_queue_create("com.sonybridge.multipoint", DISPATCH_QUEUE_SERIAL); } return self; } @@ -122,6 +143,33 @@ - (BOOL)speakToChat { return _hp && _hp->getSpeakToChat(); } - (BOOL)hasAdaptiveVolume { return _hp && _hp->hasAdaptiveVolume(); } - (BOOL)adaptiveVolume { return _hp && _hp->getAdaptiveVolume(); } +- (BOOL)hasPairedDevices { return _hp && _hp->hasPairedDevices(); } +- (BOOL)hasPlaybackPinState { return _hp && _hp->hasPlaybackPinState(); } +- (BOOL)playbackPinned { return _hp && _hp->isPlaybackPinned(); } +- (BOOL)hasMultipointSetting { return _hp && _hp->hasMultipointSetting(); } +- (BOOL)multipointEnabled { return _hp && _hp->getMultipointEnabled(); } +- (NSString *)multipointDiagnostics { return _hp ? @(_hp->getMultipointDiagnostics().c_str()) : @""; } + +- (NSArray *)pairedDevices { + if (!_hp) return @[]; + NSString *hostAddress = SHCNormalizedAddress([[IOBluetoothHostController defaultController] addressAsString] ?: @""); + NSMutableArray *result = [NSMutableArray array]; + for (const auto &device : _hp->getPairedDevices()) { + SHCPairedDevice *item = [SHCPairedDevice new]; + // Names are UTF-8 as far as we know; fall back to Latin-1 so a bad byte can't drop the row. + NSString *name = [[NSString alloc] initWithBytes:device.name.data() length:device.name.size() encoding:NSUTF8StringEncoding] + ?: [[NSString alloc] initWithBytes:device.name.data() length:device.name.size() encoding:NSISOLatin1StringEncoding]; + item.name = name ?: @""; + item.address = SHCNormalizedAddress(@(device.address.c_str())); + item.slot = device.slot; + item.classOfDevice = device.classOfDevice; + item.playback = device.playback; + item.isThisMac = hostAddress.length > 0 && [item.address isEqualToString:hostAddress]; + [result addObject:item]; + } + return result; +} + static BOOL SHCLooksLikeSonyHeadset(NSString *name) { if (name.length == 0) return NO; NSArray *prefixes = @[@"WH-", @"WF-", @"WI-", @"MDR-", @"XB", @"LinkBuds"]; @@ -225,9 +273,98 @@ - (void)refreshStatusWithCompletion:(void (^)(void))completion { // device that doesn't support them. Update the UI again once they've settled. try { hp->probeCapabilities(); } catch (std::exception &exc) {} dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); + + // Multipoint reads need the init reply (table 2 support), so they run after it, serialized with + // any manual refresh. + dispatch_sync(self->_multipointQueue, ^{ + try { hp->requestMultipoint(); } catch (std::exception &exc) {} + }); + dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); }); } +- (void)refreshMultipointWithCompletion:(void (^)(void))completion { + // GETs only, and v2 only: on v1 these opcodes are unverified (0x22-style collisions are possible). + if (!_hp || !self.connected || _bt->getProtocolVersion() != SonyProtocolVersion::V2 || !_initialized) { + completion(); + return; + } + Headphones *hp = _hp.get(); + dispatch_async(_multipointQueue, ^{ + try { hp->requestMultipoint(); } catch (std::exception &exc) {} + dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); + }); +} + +static NSString *_Nullable SHCSourceSwitchError(int result) { + switch (result) { + case V2Table2Command::RESULT_SUCCESS: return nil; + case V2Table2Command::RESULT_FAIL_CALLING: return @"The headset refused: a call is in progress."; + case V2Table2Command::RESULT_FAIL_A2DP_NOT_CONNECTED: return @"The headset refused: that device isn't connected for audio."; + case V2Table2Command::RESULT_FAIL_VOICE_ASSISTANT: return @"The headset refused: the voice assistant has priority."; + case V2Table2Command::RESULT_NO_CONFIRMATION: return @"The headset didn't confirm the change. Showing the state it reports now."; + default: return [NSString stringWithFormat:@"The headset refused the change (result %d).", result]; + } +} + +- (void)runMultipointWrite:(int (^)(Headphones *hp))write completion:(void (^)(BOOL, NSString * _Nullable))completion { + if (!_hp || !self.connected || _bt->getProtocolVersion() != SonyProtocolVersion::V2 || !_initialized) { + completion(NO, @"Not connected."); + return; + } + Headphones *hp = _hp.get(); + dispatch_async(_multipointQueue, ^{ + NSString *error = nil; + try { + error = SHCSourceSwitchError(write(hp)); + } catch (std::exception &exc) { + error = @(exc.what()); + } + try { hp->requestMultipoint(); } catch (std::exception &exc) {} + dispatch_async(dispatch_get_main_queue(), ^{ completion(error == nil, error); }); + }); +} + +- (void)switchPlaybackToAddress:(NSString *)address fix:(BOOL)fix completion:(void (^)(BOOL, NSString * _Nullable))completion { + std::string target = address.UTF8String ?: ""; + BOOL alreadyPlaying = NO; + for (SHCPairedDevice *device in self.pairedDevices) { + if ([device.address isEqualToString:address] && device.playback) alreadyPlaying = YES; + } + BOOL pinned = self.playbackPinned; + [self runMultipointWrite:^int(Headphones *hp) { + if (!fix) { + // The headset keeps "fixed" on across a switch (the fix moves to the new device), so a plain + // switch frees it afterwards. A refused switch leaves the fix untouched. + int result = hp->switchPlaybackDevice(target); + if (result != V2Table2Command::RESULT_SUCCESS || !pinned) return result; + return hp->setPlaybackPinned(false); + } + // A fixed playback device may refuse a switch, so free it first. + BOOL unfixed = NO; + if (pinned && !alreadyPlaying) { + int result = hp->setPlaybackPinned(false); + if (result != V2Table2Command::RESULT_SUCCESS) return result; + unfixed = YES; + } + if (!alreadyPlaying) { + int result = hp->switchPlaybackDevice(target); + if (result != V2Table2Command::RESULT_SUCCESS) { + // Don't leave the old device unfixed after a refused switch (e.g. mid-call). + if (unfixed) hp->setPlaybackPinned(true); + return result; + } + } + return hp->setPlaybackPinned(true); + } completion:completion]; +} + +- (void)setPlaybackPinned:(BOOL)pinned completion:(void (^)(BOOL, NSString * _Nullable))completion { + [self runMultipointWrite:^int(Headphones *hp) { + return hp->setPlaybackPinned(pinned); + } completion:completion]; +} + - (void)refreshDynamicWithCompletion:(void (^)(void))completion { if (!_hp || !self.connected) { completion(); return; } Headphones *hp = _hp.get(); diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index cda475ad..4e991aaa 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -6,7 +6,22 @@ import Foundation import Combine +struct PairedDeviceInfo: Identifiable, Equatable { + let name: String + let address: String + let slot: Int // 0 = paired only, 1/2 = connected + let classOfDevice: Int // -1 if not reported + let playback: Bool + let isThisMac: Bool + + var id: String { address } + var connected: Bool { slot != 0 } +} + final class HeadphonesModel: ObservableObject { + // One connection per app: the window and the menu-bar item drive the same model. + static let shared = HeadphonesModel() + private let bridge = HeadphonesBridge() @Published var connected = false @@ -43,6 +58,16 @@ final class HeadphonesModel: ObservableObject { @Published var deviceMac = "" @Published var protocolVersion = "" + @Published var hasPairedDevices = false + @Published var pairedDevices: [PairedDeviceInfo] = [] + @Published var hasPlaybackPinState = false + @Published var playbackPinned = false + @Published var hasMultipointSetting = false + @Published var multipointEnabled = false + @Published var multipointDiagnostics = "" + @Published var refreshingMultipoint = false + @Published var multipointBusy = false + @Published var errorMessage: String? private var pollTimer: Timer? @@ -87,9 +112,51 @@ final class HeadphonesModel: ObservableObject { self.speakToChat = self.bridge.speakToChat self.hasAdaptiveVolume = self.bridge.hasAdaptiveVolume self.adaptiveVolume = self.bridge.adaptiveVolume + self.syncMultipointFromBridge() + } + } + + func refreshMultipoint() { + refreshingMultipoint = true + bridge.refreshMultipoint { + self.refreshingMultipoint = false + self.syncMultipointFromBridge() + } + } + + func switchPlayback(to device: PairedDeviceInfo, fix: Bool) { + multipointBusy = true + errorMessage = nil + bridge.switchPlayback(toAddress: device.address, fix: fix) { ok, error in + self.multipointBusy = false + if !ok, let error = error { self.errorMessage = error } + self.syncMultipointFromBridge() } } + func setPlaybackPinned(_ pinned: Bool) { + multipointBusy = true + errorMessage = nil + bridge.setPlaybackPinned(pinned) { ok, error in + self.multipointBusy = false + if !ok, let error = error { self.errorMessage = error } + self.syncMultipointFromBridge() + } + } + + private func syncMultipointFromBridge() { + hasPairedDevices = bridge.hasPairedDevices + pairedDevices = bridge.pairedDevices.map { + PairedDeviceInfo(name: $0.name, address: $0.address, slot: $0.slot, + classOfDevice: $0.classOfDevice, playback: $0.playback, isThisMac: $0.isThisMac) + } + hasPlaybackPinState = bridge.hasPlaybackPinState + playbackPinned = bridge.playbackPinned + hasMultipointSetting = bridge.hasMultipointSetting + multipointEnabled = bridge.multipointEnabled + multipointDiagnostics = bridge.multipointDiagnostics + } + func setAutoPowerOff(_ index: Int) { autoPowerOff = index errorMessage = nil @@ -111,8 +178,15 @@ final class HeadphonesModel: ObservableObject { // Poll the button-changeable state so the app stays in sync when you use the headphone's own controls. private func startDynamicPolling() { stopDynamicPolling() + var tick = 0 dynamicTimer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { [weak self] _ in guard let self = self, self.connected else { return } + // Every 5th tick (10 s), also re-read which device has playback, so the menu-bar icon follows + // changes made from the phone. Skipped while a multipoint write or refresh is in flight. + tick += 1 + if tick % 5 == 0 && self.hasPairedDevices && !self.multipointBusy && !self.refreshingMultipoint { + self.bridge.refreshMultipoint { self.syncMultipointFromBridge() } + } self.bridge.refreshDynamic { self.mode = self.bridge.mode let level = self.bridge.ambientLevel @@ -161,6 +235,7 @@ final class HeadphonesModel: ObservableObject { bridge.disconnect() connected = false deviceName = "" + syncMultipointFromBridge() } // The headset can drop the RFCOMM link on its own (idle power-save). Poll so the UI reflects reality From 9efb44ac6b0e2595c04754c4b0e8c76ab045ab69 Mon Sep 17 00:00:00 2001 From: Fred Date: Thu, 22 Oct 2026 19:22:59 -0300 Subject: [PATCH 22/35] feat(macos): show the playback device sooner, with a loading state - Read the multipoint state (device list, fixed state) right after battery/EQ/DSEE instead of after the capability probes, so the playback device appears with the battery rather than after any probe timeouts. - Devices card shows a "Reading devices from the headset..." placeholder until the first read lands, and a spinner in its header during refreshes, switches and fixes. - Move the Devices card up, right after Ambient Sound Control. --- Client/macos/ContentView.swift | 52 ++++++++++++++++++++++-------- Client/macos/HeadphonesBridge.mm | 13 ++++---- Client/macos/HeadphonesModel.swift | 6 ++++ 3 files changed, 50 insertions(+), 21 deletions(-) diff --git a/Client/macos/ContentView.swift b/Client/macos/ContentView.swift index e7ceb6cb..07109e8b 100644 --- a/Client/macos/ContentView.swift +++ b/Client/macos/ContentView.swift @@ -76,6 +76,9 @@ struct ContentView: View { if model.mode == .ambientSound { ambientLevelCard } + if model.multipointLoading || !model.multipointDiagnostics.isEmpty { + devicesCard + } if model.supportsEqualizer { equalizerCard dseeCard @@ -83,9 +86,6 @@ struct ContentView: View { if model.hasAdaptiveVolume || model.hasSpeakToChat || model.hasAutoPowerOff { settingsCard } - if !model.multipointDiagnostics.isEmpty { - devicesCard - } if let error = model.errorMessage { Text(error) .font(.system(size: 12)) @@ -399,14 +399,30 @@ struct ContentView: View { .font(.system(size: 15, weight: .semibold)) .foregroundColor(.white) Spacer() - Button(action: model.refreshMultipoint) { - Image(systemName: "arrow.clockwise") - .font(.system(size: 12, weight: .semibold)) + if model.multipointLoading || model.refreshingMultipoint || model.multipointBusy { + ProgressView() + .scaleEffect(0.5) + .frame(width: 16, height: 16) + } else { + Button(action: model.refreshMultipoint) { + Image(systemName: "arrow.clockwise") + .font(.system(size: 12, weight: .semibold)) + .foregroundColor(Theme.secondary) + } + .buttonStyle(PlainButtonStyle()) + } + } + if model.multipointLoading { + HStack(spacing: 10) { + ProgressView() + .scaleEffect(0.6) + .frame(width: 18, height: 18) + Text("Reading devices from the headset…") + .font(.system(size: 12)) .foregroundColor(Theme.secondary) } - .buttonStyle(PlainButtonStyle()) - .disabled(model.refreshingMultipoint) - .opacity(model.refreshingMultipoint ? 0.4 : 1) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.vertical, 6) } if model.hasMultipointSetting { devicesInfoRow("Connect to 2 devices", model.multipointEnabled ? "On" : "Off") @@ -443,11 +459,23 @@ struct ContentView: View { devicesSectionLabel("Paired") ForEach(paired) { deviceRow($0) } } - } else { + } else if !model.multipointLoading { Text("This headset didn't return a device list.") .font(.system(size: 12)) .foregroundColor(Theme.secondary) } + if !model.multipointLoading { + devicesFooter + } + } + .padding(18) + .frame(maxWidth: .infinity, alignment: .leading) + .background(Theme.card) + .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) + } + + private var devicesFooter: some View { + VStack(alignment: .leading, spacing: 14) { Divider().background(Theme.cardHi) HStack { Text(model.multipointBusy ? "Sending…" : "Switching and fixing are experimental") @@ -462,10 +490,6 @@ struct ContentView: View { .buttonStyle(PlainButtonStyle()) } } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Theme.card) - .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) } private func devicesInfoRow(_ label: String, _ value: String) -> some View { diff --git a/Client/macos/HeadphonesBridge.mm b/Client/macos/HeadphonesBridge.mm index 12a399a6..a51755c2 100644 --- a/Client/macos/HeadphonesBridge.mm +++ b/Client/macos/HeadphonesBridge.mm @@ -267,19 +267,18 @@ - (void)refreshStatusWithCompletion:(void (^)(void))completion { hp->requestEqualizer(); hp->requestDsee(); } catch (std::exception &exc) {} + // The multipoint reads (device list, fixed state) belong with the fast reads so the playback device + // shows up with the battery instead of after the probe timeouts. They need the init reply (table 2 + // support), so they come after it, serialized with any manual refresh. + dispatch_sync(self->_multipointQueue, ^{ + try { hp->requestMultipoint(); } catch (std::exception &exc) {} + }); dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); // ...then the optional-feature probes, which can each take a couple seconds to time out on a // device that doesn't support them. Update the UI again once they've settled. try { hp->probeCapabilities(); } catch (std::exception &exc) {} dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); - - // Multipoint reads need the init reply (table 2 support), so they run after it, serialized with - // any manual refresh. - dispatch_sync(self->_multipointQueue, ^{ - try { hp->requestMultipoint(); } catch (std::exception &exc) {} - }); - dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); }); } diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index 4e991aaa..14136c46 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -68,6 +68,12 @@ final class HeadphonesModel: ObservableObject { @Published var refreshingMultipoint = false @Published var multipointBusy = false + // True from connect until the first multipoint read has finished. Those reads run after the + // capability probes, so on a v2 headset this can take several seconds. + var multipointLoading: Bool { + connected && protocolVersion == "v2" && multipointDiagnostics.isEmpty + } + @Published var errorMessage: String? private var pollTimer: Timer? From 0c43f147f1a8800239273e4f647932a19cea7e89 Mon Sep 17 00:00:00 2001 From: Amit Rajput Date: Tue, 27 Oct 2026 15:59:12 +0530 Subject: [PATCH 23/35] chore: ignore brainstorm scratch dir Co-Authored-By: Claude Opus 5.5 --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 32ccd080..7e37570d 100644 --- a/.gitignore +++ b/.gitignore @@ -530,3 +530,5 @@ Client/imgui.ini # linux build Client/linux/sonyheadphonesclient.build/ + +.superpowers/ From e06b63ae17bb468a1bbe795a25ab2f6234c60ec5 Mon Sep 17 00:00:00 2001 From: Sergey Ukolov Date: Fri, 14 Aug 2026 20:51:22 +0300 Subject: [PATCH 24/35] fix(macos): read per-earbud battery on TWS models requestBattery() probed the single-battery sub-type first and returned on any reply, so TWS earbuds never reached the dual probe and L/R stayed unset. Probe order now follows the model name (WF-*/LinkBuds try dual first), with a fallback to the other layout either way. - add DUAL2 (0x01) for the WF-C500/C510/C700N line - keep the per-earbud charging flags instead of discarding them - treat a level of 0 as "not reporting" (docked), not a flat battery - read the charging case (0x0a) - re-read battery on the dynamic poll so it stops going stale (v2 only: 0x22 is POWER_OFF on v1) Sub-types and byte offsets verified against a WF-1000XM5 by docking one earbud and watching byte [4] track it; captured frames are in Constants.h. (cherry picked from commit ff1605d69c0d76c80bb7806dccf0e3529b79a844) Conflict resolution on top of #7/#28 (by maintainer): - keep #7's v1 battery branch (10 00); per-earbud probing is v2-only - a 0/0 dual reply is a real answer (both earbuds docked), not "unsupported": rejecting it fell through to DUAL2/single probes that time out, stalling the command queue ~5s on every battery poll - battery re-read runs on the serial command queue (no _dynamicTick race) and model writes are change-gated Co-Authored-By: Claude Opus 5.5 --- Client/Constants.h | 27 +++++- Client/CrossPlatformGUI.cpp | 17 +++- Client/Headphones.cpp | 141 +++++++++++++++++++++++------ Client/Headphones.h | 18 +++- Client/macos/ContentView.swift | 40 ++++++-- Client/macos/HeadphonesBridge.h | 3 + Client/macos/HeadphonesBridge.mm | 17 ++++ Client/macos/HeadphonesModel.swift | 23 +++-- 8 files changed, 238 insertions(+), 48 deletions(-) diff --git a/Client/Constants.h b/Client/Constants.h index 0e10aab6..eb3d9fc1 100644 --- a/Client/Constants.h +++ b/Client/Constants.h @@ -65,9 +65,30 @@ namespace V2Command { inline constexpr unsigned char INIT_REQUEST = 0x00; // payload: 00 00 inline constexpr unsigned char INIT_REPLY = 0x01; // reply: 01 ... (8 bytes total => v2 device) - inline constexpr unsigned char BATTERY_GET = 0x22; // payload: 22 - inline constexpr unsigned char BATTERY_RET = 0x23; // reply: 23 - inline constexpr unsigned char BATTERY_NTFY = 0x25; // notify: 25 + inline constexpr unsigned char BATTERY_GET = 0x22; // payload: 22 + inline constexpr unsigned char BATTERY_RET = 0x23; // reply: 23 + inline constexpr unsigned char BATTERY_NTFY = 0x25; // notify: 25 + // Battery inquiry sub-types (payload byte 1). A device answers only the ones it actually has, so + // these have to be probed. TWS earbuds report DUAL (or DUAL2 on the WF-C5xx/C700N line) plus CASE; + // everything else reports SINGLE. Values and the DUAL byte layout match GadgetBridge's + // SonyProtocolImplV2.encodeBatteryType() / handleBattery(). + inline constexpr unsigned char BATTERY_SUB_SINGLE = 0x00; // RET 23 00 + inline constexpr unsigned char BATTERY_SUB_DUAL2 = 0x01; // WF-C500 / WF-C510 / WF-C700N + inline constexpr unsigned char BATTERY_SUB_DUAL = 0x09; // WF-1000XM4 / WF-1000XM5 / LinkBuds + inline constexpr unsigned char BATTERY_SUB_CASE = 0x0a; // RET 23 0a + // DUAL/DUAL2 reply: 23 . A level of 0 means that earbud isn't + // reporting (docked in the case / powered down) rather than "empty" - treat it as unknown. + // + // The reply can be LONGER than the reference layout, so size checks must be lower bounds, never + // equality. Captured from a WF-1000XM5 (fw 6.1.0), both earbuds out of the case and full: + // send 22 09 -> 23 09 64 00 64 00 64 64 (8 bytes; documented layout is 6) + // send 22 0a -> 23 0a 64 00 1e (5 bytes; documented layout is 4) + // Confirmed on hardware by docking one earbud and watching the frames change: + // right earbud in the case -> 23 09 64 00 00 00 64 64 (byte [4] = R went 0x64 -> 0x00) + // right earbud back out -> 23 09 64 00 64 00 64 64 + // So bytes [2]/[4] really are the L/R levels, as in the reference layout. The trailing bytes stayed + // fixed (0x64 0x64 on 22 09, 0x1e on 22 0a) across that change, which rules them out as per-earbud + // levels but leaves their meaning unknown - don't reuse them without a sample that moves them. inline constexpr unsigned char EQ_GET = 0x56; // payload: 56 00 inline constexpr unsigned char EQ_RET = 0x57; // reply: 57 00 06 inline constexpr unsigned char EQ_SET = 0x58; // preset: 58 00 00 ; custom: 58 00 A0 06 diff --git a/Client/CrossPlatformGUI.cpp b/Client/CrossPlatformGUI.cpp index 8537eb83..15a2de3a 100644 --- a/Client/CrossPlatformGUI.cpp +++ b/Client/CrossPlatformGUI.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #define STB_IMAGE_IMPLEMENTATION #define STBI_ONLY_PNG @@ -194,6 +195,8 @@ void CrossPlatformGUI::_pumpConnectionState() try { this->_headphones.requestAmbientState(); } catch (const std::exception&) {} if (this->_isV2()) { + // Lets requestBattery() probe the per-earbud layout first on TWS models (WF-*/LinkBuds). + this->_headphones.setDeviceName(this->_connectedDevice.name); try { this->_headphones.requestBattery(); } catch (const std::exception&) {} try { this->_headphones.requestEqualizer(); } catch (const std::exception&) {} try { this->_headphones.requestDsee(); } catch (const std::exception&) {} @@ -382,9 +385,19 @@ void CrossPlatformGUI::_drawStatusHeader() if (this->_headphones.hasDualBattery()) { - ImGui::Text("Battery L %d%% R %d%%", this->_headphones.getBatteryLeft(), this->_headphones.getBatteryRight()); + // An earbud that isn't reporting (docked in the case / powered down) reads -1; show a dash. + auto budText = [](int level, bool charging) { + char buf[32]; + if (level < 0) snprintf(buf, sizeof(buf), "--"); + else snprintf(buf, sizeof(buf), "%d%%%s", level, charging ? "+" : ""); + return std::string(buf); + }; + ImGui::Text("Battery L %s R %s", + budText(this->_headphones.getBatteryLeft(), this->_headphones.isBatteryLeftCharging()).c_str(), + budText(this->_headphones.getBatteryRight(), this->_headphones.isBatteryRightCharging()).c_str()); if (this->_headphones.getBatteryCase() >= 0) - ImGui::Text("Case %d%%", this->_headphones.getBatteryCase()); + ImGui::Text("Case %d%%%s", this->_headphones.getBatteryCase(), + this->_headphones.isBatteryCaseCharging() ? " (charging)" : ""); } else { diff --git a/Client/Headphones.cpp b/Client/Headphones.cpp index 2670194a..0c9a5fb0 100644 --- a/Client/Headphones.cpp +++ b/Client/Headphones.cpp @@ -98,6 +98,72 @@ void Headphones::initDevice() && resp[V2Command::INIT_REPLY_TABLE2_INDEX] == 0x00; } +void Headphones::setDeviceName(const std::string& name) +{ + std::lock_guard guard(this->_propertyMtx); + this->_deviceName = name; +} + +// True for Sony's true-wireless earbuds, which report a battery per earbud instead of one for the +// whole device. Only used to pick the probe order - an unrecognised name still finds both layouts, +// just one timed-out inquiry slower. +bool Headphones::_looksLikeEarbuds() const +{ + std::string name; + for (char c : this->_deviceName) name.push_back((char)std::tolower((unsigned char)c)); + return name.find("wf-") != std::string::npos || name.find("linkbuds") != std::string::npos; +} + +// Reads the per-earbud (and case) levels. Returns false if the device didn't answer this sub-type or +// answered with nothing usable, so the caller can fall back to the other layout. +bool Headphones::_requestDualBattery(unsigned char subType) +{ + Buffer resp; + try { + resp = this->_conn.sendCommandAndReadResponse( + { (char)V2Command::BATTERY_GET, (char)subType }, V2Command::BATTERY_RET, subType); + } catch (const std::exception&) { + return false; + } + if (resp.size() < 6) return false; + + const int left = (unsigned char)resp[2]; + const int right = (unsigned char)resp[4]; + + // Both zero is still a real answer: both earbuds are docked (level 0 means "not reporting", not empty). + // Rejecting it would fall through to the DUAL2 and single probes, which time out on these models and + // stall the command queue for ~5s on every battery poll while the buds sit in the case. + std::lock_guard guard(this->_propertyMtx); + this->_hasDualBattery = true; + this->_hasBattery = true; + this->_batteryLeft = left > 0 ? left : -1; + this->_batteryRight = right > 0 ? right : -1; + this->_batteryLeftCharging = resp[3] == 1; + this->_batteryRightCharging = resp[5] == 1; + // Headline level: the emptier of the two earbuds that are actually reporting. + if (this->_batteryLeft >= 0 && this->_batteryRight >= 0) + this->_batteryLevel = std::min(this->_batteryLeft, this->_batteryRight); + else + this->_batteryLevel = std::max(this->_batteryLeft, this->_batteryRight); // -1 when both are docked + this->_batteryCharging = this->_batteryLeftCharging || this->_batteryRightCharging; + return true; +} + +bool Headphones::_requestSingleBattery(unsigned char subType, int& levelOut, bool& chargingOut) +{ + Buffer resp; + try { + resp = this->_conn.sendCommandAndReadResponse( + { (char)V2Command::BATTERY_GET, (char)subType }, V2Command::BATTERY_RET, subType); + } catch (const std::exception&) { + return false; + } + if (resp.size() < 4) return false; + levelOut = (unsigned char)resp[2]; + chargingOut = resp[3] == 1; + return true; +} + void Headphones::requestBattery() { if (this->_conn.getProtocolVersion() == SonyProtocolVersion::V1) @@ -118,38 +184,54 @@ void Headphones::requestBattery() return; } - // Single battery (over-ear and most models): GET 22 00 -> RET 23 00 - try { - auto resp = this->_conn.sendCommandAndReadResponse({ (char)V2Command::BATTERY_GET, 0x00 }, V2Command::BATTERY_RET, 0x00); - if (resp.size() >= 4) { - std::lock_guard guard(this->_propertyMtx); - this->_batteryLevel = (unsigned char)resp[2]; - this->_batteryCharging = resp[3] == 1; - this->_hasBattery = true; - return; // found a single battery; don't waste time probing the TWS types + // A device only answers the battery sub-types it supports, and an unsupported inquiry costs a + // full recv timeout, so probe the layout this model is likely to use first. Crucially the dual + // probe must come before the single one on earbuds: some TWS models *do* answer the single + // inquiry (with a combined or zero level), and taking that answer would hide the per-earbud + // levels entirely. + if (this->_looksLikeEarbuds()) + { + if (this->_requestDualBattery(V2Command::BATTERY_SUB_DUAL) + || this->_requestDualBattery(V2Command::BATTERY_SUB_DUAL2)) + { + int caseLevel = -1; bool caseCharging = false; + if (this->_requestSingleBattery(V2Command::BATTERY_SUB_CASE, caseLevel, caseCharging)) { + std::lock_guard guard(this->_propertyMtx); + // The case reports 0 while it's disconnected from the buds; keep the last known value. + if (caseLevel > 0) { + this->_batteryCase = caseLevel; + this->_batteryCaseCharging = caseCharging; + } + } + return; } - } catch (...) {} + } - // TWS earbuds: dual L/R (22 09 -> 23 09 ) and case (22 0a -> 23 0a ). - try { - auto resp = this->_conn.sendCommandAndReadResponse({ (char)V2Command::BATTERY_GET, 0x09 }, V2Command::BATTERY_RET, 0x09); - if (resp.size() >= 6) { - std::lock_guard guard(this->_propertyMtx); - this->_hasDualBattery = true; - this->_batteryLeft = (unsigned char)resp[2]; - this->_batteryRight = (unsigned char)resp[4]; - this->_batteryLevel = std::min(this->_batteryLeft, this->_batteryRight); - this->_hasBattery = true; - } - } catch (...) {} + // Single battery (over-ear and most other models). + int level = -1; bool charging = false; + if (this->_requestSingleBattery(V2Command::BATTERY_SUB_SINGLE, level, charging)) { + std::lock_guard guard(this->_propertyMtx); + this->_batteryLevel = level; + this->_batteryCharging = charging; + this->_hasBattery = true; + return; + } - try { - auto resp = this->_conn.sendCommandAndReadResponse({ (char)V2Command::BATTERY_GET, 0x0a }, V2Command::BATTERY_RET, 0x0a); - if (resp.size() >= 4) { - std::lock_guard guard(this->_propertyMtx); - this->_batteryCase = (unsigned char)resp[2]; + // Unrecognised name that turned out to be earbuds after all. + if (!this->_looksLikeEarbuds()) { + if (this->_requestDualBattery(V2Command::BATTERY_SUB_DUAL) + || this->_requestDualBattery(V2Command::BATTERY_SUB_DUAL2)) + { + int caseLevel = -1; bool caseCharging = false; + if (this->_requestSingleBattery(V2Command::BATTERY_SUB_CASE, caseLevel, caseCharging)) { + std::lock_guard guard(this->_propertyMtx); + if (caseLevel > 0) { + this->_batteryCase = caseLevel; + this->_batteryCaseCharging = caseCharging; + } + } } - } catch (...) {} + } } bool Headphones::hasBattery() { std::lock_guard guard(this->_propertyMtx); return this->_hasBattery; } @@ -169,6 +251,9 @@ bool Headphones::hasDualBattery() { std::lock_guard guard(this->_propertyMtx); r int Headphones::getBatteryLeft() { std::lock_guard guard(this->_propertyMtx); return this->_batteryLeft; } int Headphones::getBatteryRight() { std::lock_guard guard(this->_propertyMtx); return this->_batteryRight; } int Headphones::getBatteryCase() { std::lock_guard guard(this->_propertyMtx); return this->_batteryCase; } +bool Headphones::isBatteryLeftCharging() { std::lock_guard guard(this->_propertyMtx); return this->_batteryLeftCharging; } +bool Headphones::isBatteryRightCharging() { std::lock_guard guard(this->_propertyMtx); return this->_batteryRightCharging; } +bool Headphones::isBatteryCaseCharging() { std::lock_guard guard(this->_propertyMtx); return this->_batteryCaseCharging; } void Headphones::requestEqualizer() { diff --git a/Client/Headphones.h b/Client/Headphones.h index 9840476e..f04396a1 100644 --- a/Client/Headphones.h +++ b/Client/Headphones.h @@ -49,16 +49,23 @@ class Headphones { // Handshake the device expects before it answers inquiry (GET) commands. void initDevice(); + // Model name of the connected device (e.g. "WF-1000XM5"). Only a hint: it picks which battery + // layout to probe first, so set it before the first requestBattery() to save a timed-out inquiry. + void setDeviceName(const std::string& name); + // Battery. getBatteryLevel() returns -1 until requestBattery() succeeds. // For TWS earbuds requestBattery() also fills the per-earbud + case levels (hasDualBattery()). void requestBattery(); bool hasBattery(); - int getBatteryLevel(); + int getBatteryLevel(); // for earbuds: the emptier of the two bool isBatteryCharging(); bool hasDualBattery(); int getBatteryLeft(); // -1 if n/a int getBatteryRight(); int getBatteryCase(); + bool isBatteryLeftCharging(); + bool isBatteryRightCharging(); + bool isBatteryCaseCharging(); // Equalizer. Wire subtypes and the custom-preset byte differ between protocol generations. void requestEqualizer(); @@ -142,6 +149,15 @@ class Headphones { int _batteryLeft = -1; int _batteryRight = -1; int _batteryCase = -1; + bool _batteryLeftCharging = false; + bool _batteryRightCharging = false; + bool _batteryCaseCharging = false; + std::string _deviceName; + + bool _looksLikeEarbuds() const; + // Both return false if the device didn't answer that battery sub-type. + bool _requestDualBattery(unsigned char subType); + bool _requestSingleBattery(unsigned char subType, int& levelOut, bool& chargingOut); EQ_PRESET _eqPreset = EQ_PRESET::OFF; bool _hasEqualizer = false; std::vector _eqBands = { 0, 0, 0, 0, 0 }; diff --git a/Client/macos/ContentView.swift b/Client/macos/ContentView.swift index 2e8139e3..46af867b 100644 --- a/Client/macos/ContentView.swift +++ b/Client/macos/ContentView.swift @@ -155,12 +155,13 @@ struct ContentView: View { HStack(spacing: 7) { if model.hasDualBattery { - Image(systemName: "battery.100") - .font(.system(size: 13)) - .foregroundColor(Theme.accent) - Text("L \(model.batteryLeft)% R \(model.batteryRight)%") - .font(.system(size: 13, weight: .semibold)) - .foregroundColor(Theme.secondary) + // Earbuds report a battery each, plus the case when it's connected. An earbud that + // isn't reporting (docked / powered down) comes through as -1 and is left out. + budBattery("L", model.batteryLeft, charging: model.batteryLeftCharging) + budBattery("R", model.batteryRight, charging: model.batteryRightCharging) + if model.batteryCase >= 0 { + budBattery("Case", model.batteryCase, charging: model.batteryCaseCharging) + } } else if model.batteryLevel >= 0 { Image(systemName: model.batteryCharging ? "bolt.fill" : batterySymbol(model.batteryLevel)) .font(.system(size: 13)) @@ -577,8 +578,11 @@ struct ContentView: View { .padding(.bottom, 10) aboutRow("Status", model.connected ? "Connected" : "Disconnected") if model.hasDualBattery { - aboutRow("Battery L / R", "\(model.batteryLeft)% / \(model.batteryRight)%") - if model.batteryCase >= 0 { aboutRow("Case", "\(model.batteryCase)%") } + aboutRow("Battery L", batteryText(model.batteryLeft, model.batteryLeftCharging)) + aboutRow("Battery R", batteryText(model.batteryRight, model.batteryRightCharging)) + if model.batteryCase >= 0 { + aboutRow("Case", batteryText(model.batteryCase, model.batteryCaseCharging)) + } } else if model.batteryLevel >= 0 { aboutRow("Battery", "\(model.batteryLevel)%\(model.batteryCharging ? " (charging)" : "")") } @@ -596,6 +600,11 @@ struct ContentView: View { .background(Theme.card) } + private func batteryText(_ level: Int, _ charging: Bool) -> String { + guard level >= 0 else { return "—" } + return "\(level)%\(charging ? " (charging)" : "")" + } + private func aboutRow(_ label: String, _ value: String) -> some View { HStack { Text(label).font(.system(size: 12)).foregroundColor(Theme.secondary) @@ -611,6 +620,21 @@ struct ContentView: View { return NSImage(named: slug) } + // One "L 82%" chip, with a bolt in place of the battery glyph while that unit is charging. + // A docked/powered-down earbud reports no level; show it dimmed as "R --" rather than dropping the + // chip, so it reads as "in the case" instead of looking like the app lost track of it. + private func budBattery(_ label: String, _ level: Int, charging: Bool) -> some View { + HStack(spacing: 3) { + Image(systemName: level < 0 ? "battery.0" : (charging ? "bolt.fill" : batterySymbol(level))) + .font(.system(size: 12)) + .foregroundColor(level < 0 ? Theme.secondary.opacity(0.5) + : (level <= 20 && !charging ? .red.opacity(0.9) : Theme.accent)) + Text(level < 0 ? "\(label) --" : "\(label) \(level)%") + .font(.system(size: 13, weight: .semibold)) + .foregroundColor(Theme.secondary.opacity(level < 0 ? 0.5 : 1.0)) + } + } + private func batterySymbol(_ level: Int) -> String { switch level { case ...15: return "battery.0" diff --git a/Client/macos/HeadphonesBridge.h b/Client/macos/HeadphonesBridge.h index 5e9b5058..c551c3a1 100644 --- a/Client/macos/HeadphonesBridge.h +++ b/Client/macos/HeadphonesBridge.h @@ -47,6 +47,9 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { @property (nonatomic, readonly) NSInteger batteryLeft; // -1 if n/a @property (nonatomic, readonly) NSInteger batteryRight; @property (nonatomic, readonly) NSInteger batteryCase; +@property (nonatomic, readonly) BOOL batteryLeftCharging; +@property (nonatomic, readonly) BOOL batteryRightCharging; +@property (nonatomic, readonly) BOOL batteryCaseCharging; @property (nonatomic, readonly) NSInteger eqPreset; // raw preset byte (EQ_PRESET) @property (nonatomic, readonly) BOOL supportsEqualizer; // true after a successful read-only probe @property (nonatomic, readonly) NSInteger clearBass; // -10..10 diff --git a/Client/macos/HeadphonesBridge.mm b/Client/macos/HeadphonesBridge.mm index 8fcf38a2..86c4e0c2 100644 --- a/Client/macos/HeadphonesBridge.mm +++ b/Client/macos/HeadphonesBridge.mm @@ -15,6 +15,10 @@ // RecoverableException comes in transitively via BluetoothWrapper.h -> IBluetoothConnector.h -> Exceptions.h. // (Exceptions.h isn't a project file reference, so it can't be #included directly from this directory.) +// The dynamic poll fires every 2s; re-read the battery every 15th tick (~30s), which is far more often +// than a headphone battery meaningfully moves but cheap enough not to crowd out the ambient/NC polling. +static const unsigned kBatteryPollEveryNTicks = 15; + @interface SHCPairedDevice () @property (nonatomic, copy, readwrite) NSString *name; @property (nonatomic, copy, readwrite) NSString *address; @@ -40,6 +44,8 @@ @implementation HeadphonesBridge { NSString *_deviceName; NSString *_deviceMac; std::atomic_bool _initialized; + // Only touched inside blocks on _cmdQueue, which is serial. + unsigned _dynamicTick; // All device I/O runs on this serial queue. Bluetooth commands are stateful, and serializing reads with // writes also prevents a slow capability probe from racing a user action or dynamic refresh. dispatch_queue_t _cmdQueue; @@ -110,6 +116,9 @@ - (BOOL)hasDualBattery { return _hp && _hp->hasDualBattery(); } - (NSInteger)batteryLeft { return _hp ? _hp->getBatteryLeft() : -1; } - (NSInteger)batteryRight { return _hp ? _hp->getBatteryRight() : -1; } - (NSInteger)batteryCase { return _hp ? _hp->getBatteryCase() : -1; } +- (BOOL)batteryLeftCharging { return _hp && _hp->isBatteryLeftCharging(); } +- (BOOL)batteryRightCharging { return _hp && _hp->isBatteryRightCharging(); } +- (BOOL)batteryCaseCharging { return _hp && _hp->isBatteryCaseCharging(); } - (NSInteger)eqPreset { return _hp ? (NSInteger)_hp->getEqualizerPreset() : 0; @@ -249,6 +258,8 @@ - (void)scanAndConnectWithCompletion:(void (^)(BOOL, NSString * _Nullable))compl _deviceName = [device nameOrAddress]; _deviceMac = [device addressString]; _hp = std::make_shared(*_bt); + // Lets requestBattery() probe the per-earbud layout first on TWS models (WF-*/LinkBuds). + _hp->setDeviceName(_deviceName ? [_deviceName UTF8String] : ""); // A link the headset dropped on its own never went through -disconnect, so reset here: every new // Headphones needs the init handshake (its reply also gates the multipoint reads). _initialized = false; @@ -374,10 +385,16 @@ - (void)setPlaybackPinned:(BOOL)pinned completion:(void (^)(BOOL, NSString * _Nu - (void)refreshDynamicWithCompletion:(void (^)(void))completion { if (!_hp || !self.connected) { completion(); return; } auto hp = _hp; + BOOL isV2 = _bt->getProtocolVersion() == SonyProtocolVersion::V2; dispatch_async(_cmdQueue, ^{ // The headphone's physical button only changes ambient/NC, so that's all we poll (keeps traffic low). // requestAmbientState() is protocol-aware (v2 uses 66 17, v1 uses 66 02), so this is safe on both. try { hp->requestAmbientState(); } catch (std::exception &exc) {} + // Battery drains, earbuds get docked and the case charges them, so re-read it too - but only + // every Nth poll, since it costs up to three inquiries on TWS. v2 only: 0x22 is POWER_OFF on v1. + if (isV2 && self->_dynamicTick++ % kBatteryPollEveryNTicks == 0) { + try { hp->requestBattery(); } catch (std::exception &exc) {} + } dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); }); } diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index 1ae69c48..490e6de0 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -43,6 +43,9 @@ final class HeadphonesModel: ObservableObject { @Published var batteryLeft = -1 @Published var batteryRight = -1 @Published var batteryCase = -1 + @Published var batteryLeftCharging = false + @Published var batteryRightCharging = false + @Published var batteryCaseCharging = false @Published var eqPreset = 0 @Published var supportsEqualizer = false @Published var eqBands = [0, 0, 0, 0, 0] @@ -124,12 +127,7 @@ final class HeadphonesModel: ObservableObject { func refreshStatus() { bridge.refreshStatus { - self.batteryLevel = self.bridge.batteryLevel - self.batteryCharging = self.bridge.batteryCharging - self.hasDualBattery = self.bridge.hasDualBattery - self.batteryLeft = self.bridge.batteryLeft - self.batteryRight = self.bridge.batteryRight - self.batteryCase = self.bridge.batteryCase + self.syncBatteryFromBridge() self.eqPreset = self.bridge.eqPreset self.supportsEqualizer = self.bridge.supportsEqualizer self.clearBass = self.bridge.clearBass @@ -198,6 +196,18 @@ final class HeadphonesModel: ObservableObject { multipointDiagnostics = bridge.multipointDiagnostics } + private func syncBatteryFromBridge() { + assignIfChanged(\.batteryLevel, bridge.batteryLevel) + assignIfChanged(\.batteryCharging, bridge.batteryCharging) + assignIfChanged(\.hasDualBattery, bridge.hasDualBattery) + assignIfChanged(\.batteryLeft, bridge.batteryLeft) + assignIfChanged(\.batteryRight, bridge.batteryRight) + assignIfChanged(\.batteryCase, bridge.batteryCase) + assignIfChanged(\.batteryLeftCharging, bridge.batteryLeftCharging) + assignIfChanged(\.batteryRightCharging, bridge.batteryRightCharging) + assignIfChanged(\.batteryCaseCharging, bridge.batteryCaseCharging) + } + func setAutoPowerOff(_ index: Int) { autoPowerOff = index errorMessage = nil @@ -253,6 +263,7 @@ final class HeadphonesModel: ObservableObject { self.assignIfChanged(\.supportsDsee, self.bridge.supportsDsee) self.assignIfChanged(\.dsee, self.bridge.dsee) self.assignIfChanged(\.eqBands, (0..<5).map { self.bridge.equalizerBand(at: $0) }) + self.syncBatteryFromBridge() } } } From ac08666210ccac29fccced155468163f26fdf713 Mon Sep 17 00:00:00 2001 From: Sergey Ukolov Date: Fri, 14 Aug 2026 20:51:30 +0300 Subject: [PATCH 25/35] fix(macos): don't write to a freed RFCOMM channel after disconnect rfcommchannel was a non-owning __bridge pointer that was never cleared when the link dropped, so a poll already in flight would writeSync: to a released channel and crash (EXC_BAD_ACCESS / pointer auth failure). Docking an earbud was enough to trigger it. Retain the channel and clear it under a mutex, so a concurrent send sees either a live channel or nil; send() now raises a recoverable error instead. Also fixes a self-join: the RFCOMM delegate runs on uthread's own run loop, so rfcommChannelClosed -> disconnect() was joining that thread from itself. recv() now wakes on disconnect rather than waiting out its full timeout. (cherry picked from commit ac78f13f75a9328ba0803fa521a556345ce47af4) Conflict resolution on top of #7 (by maintainer): #7 already fixed the self-join and the recv wake-up; kept its version of those and applied this commit's core fix to it - the channel pointer is now an owning reference guarded by channelMtx (send/isConnected take a strong ref under the lock), instead of #7's unretained atomic pointer, which a remote close could still free under an in-flight send. Co-Authored-By: Claude Opus 5.5 --- Client/macos/MacOSBluetoothConnector.h | 6 +++++- Client/macos/MacOSBluetoothConnector.mm | 27 ++++++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h index bcb5a898..7e87aa16 100644 --- a/Client/macos/MacOSBluetoothConnector.h +++ b/Client/macos/MacOSBluetoothConnector.h @@ -52,7 +52,11 @@ class MacOSBluetoothConnector final : public IBluetoothConnector private: void *rfcommDevice = nullptr; - std::atomic rfcommchannel{nullptr}; + // Owning (+1, CFBridgingRetain) reference to the open IOBluetoothRFCOMMChannel, or null. Guarded by + // channelMtx: readers take their own strong reference under the lock, so a remote close on the main + // run loop can never free the channel under an in-flight send(). + void *rfcommchannel = nullptr; + std::mutex channelMtx; std::thread uthread; //Total bytes across receivedBytes; guarded by receiveDataMutex. size_t receivedBytesTotal = 0; diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 6e863454..44465736 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -57,7 +57,11 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) #ifdef SHC_DEBUG_PROTOCOL _debugHexDump("send", buf, length); #endif - IOBluetoothRFCOMMChannel *channel = (__bridge IOBluetoothRFCOMMChannel*)rfcommchannel.load(); + IOBluetoothRFCOMMChannel *channel = nil; + { + std::lock_guard g(channelMtx); + channel = (__bridge IOBluetoothRFCOMMChannel*)rfcommchannel; + } if (channel == nil) throw RecoverableException("Bluetooth connection is closed", false); [channel writeSync:(void*)buf length:length]; return (int)length; @@ -124,7 +128,10 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) return; } // store the channel - macOSBluetoothConnector->rfcommchannel.store((__bridge void*) channel); + { + std::lock_guard g(macOSBluetoothConnector->channelMtx); + macOSBluetoothConnector->rfcommchannel = (void*)CFBridgingRetain(channel); + } macOSBluetoothConnector->protocolVersion = protocolVersion; // tell the other tread that we are done connecting @@ -290,7 +297,12 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) } void MacOSBluetoothConnector::closeConnection() { // Only one close path owns the channel pointer. A remote-close callback clears it first. - IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*)rfcommchannel.exchange(nullptr); + IOBluetoothRFCOMMChannel *chan = nil; + { + std::lock_guard g(channelMtx); + chan = (IOBluetoothRFCOMMChannel*)CFBridgingRelease(rfcommchannel); + rfcommchannel = nullptr; + } if (chan == nil) return; [chan setDelegate: nil]; // close the channel @@ -299,7 +311,11 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) void MacOSBluetoothConnector::handleChannelClosed() noexcept { - rfcommchannel.store(nullptr); + { + std::lock_guard g(channelMtx); + if (rfcommchannel) CFRelease(rfcommchannel); + rfcommchannel = nullptr; + } // running=false must be stored under disconnectionMutex: connectToMac's untimed wait // would otherwise miss a notify racing its predicate check and never wake. { @@ -315,6 +331,7 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) { if (!running) return false; - IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*)rfcommchannel.load(); + std::lock_guard g(channelMtx); + IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*)rfcommchannel; return chan != nil && chan.isOpen; } From 8d976527896a51174f87ce7c9fd91114eb52f95c Mon Sep 17 00:00:00 2001 From: Sergey Ukolov Date: Fri, 14 Aug 2026 20:51:38 +0300 Subject: [PATCH 26/35] fix(macos): give the app icon macOS squircle geometry The icon was a full-bleed square, which looks wrong in the Dock. Reshape to Apple's grid: 824x824 body centred in 1024, continuous (not circular) corner curve, subtle drop shadow. Artwork unchanged. (cherry picked from commit ae4e0c74bedceb22e6a82bc549fa5aafd67b51da) --- .../AppIcon.appiconset/icon_1024.png | Bin 97688 -> 86745 bytes .../AppIcon.appiconset/icon_128.png | Bin 5381 -> 5736 bytes .../AppIcon.appiconset/icon_16.png | Bin 649 -> 563 bytes .../AppIcon.appiconset/icon_256.png | Bin 13651 -> 14137 bytes .../AppIcon.appiconset/icon_32.png | Bin 1180 -> 1268 bytes .../AppIcon.appiconset/icon_512.png | Bin 15795 -> 40422 bytes .../AppIcon.appiconset/icon_64.png | Bin 2417 -> 2617 bytes 7 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_1024.png b/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_1024.png index d04c24d295d512cf9823d086a7ed230337a31ccd..1549669ad787d8f00fd603d309008b3953a98e21 100644 GIT binary patch literal 86745 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 X-*Z}G?XUm$51c0FEzeb*agF~!s~WmR literal 97688 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 F{{V{dH)H?+ diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_128.png b/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_128.png index 69b33b6703d3f85c78f6072868c0a30b8e6b4548..0be9d29362e970de7048f3ef2aca91dd506c3732 100644 GIT binary patch literal 5736 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 diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_16.png b/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_16.png index 4a18806e899eed332159ceb853715e62840f009d..45d1691119ff615aacdb82cc9ce5367cd9f4124f 100644 GIT binary patch delta 539 zcmV+$0_6RP1+xT@BYy$-|V zm*Z4Oq=+(rIoQ5#>f@IU66bRtB9Q?}L#^+jV3_jz%)f?c5p-kZn4Vm?rAN=K>)Pl= zEvl-Wvl^TWwNqt+xEPD-l_aXmKw@bgZZkG_o7U-<)W0J zrbM#qxWarYOpJ9d^AtB8eCE~r@5IA(;(b*Q5{e79v`pcvs(JIf8W?7+m`7%8! d`{%##8x+{1y+30nFXR9K002ovPDHLkV1l(Q3)=ty literal 649 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|DpDgn(|mmy zw18|51{Ovs23C*~Ahu(ahO^xmH5iz|;!F$-?U@WLP&Ix)8U#Fm7^DY6GcRC-ss@TJ zV1la_Sip>6gS4^Vay<&9I14-?iy0WWg+Z8+Vb&Z8plPc-T^vI!1m{lL?;RZ|a@_v> z_qa)IM>2x9Cbc?+wsYAlOR;4e5tU@%7`Uo9N z@;Ruu(0Sg<%B#!XAAjk4b%uMsR>gw@d%xH0pI?1`?{x;3r&AX{KXuM{u~@=pGtdu^ygl7_w^_s6~oZ$()a^ijl_b1OMdep^gotO98U%K$Mf%lSD_F&I7cBOglxnCaY)|_%)dSpXxak;|T zw5<#GTqf^A&OnvM#!oC?lgHA_vY;m>pBuA9Qk+9nC~&p(wr`Fl0r z?ythVv2PcKO+T-F*5OA)spRP+k{&m9)ScM<*Lj*5e}U~^&MopQS!FzresF&HyYThR oUGCuy<=$Hs{p}1q`9Hm$fsb*ezewYWhoC6+boFyt=akR{0N^F@P5=M^ diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_256.png b/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_256.png index f4b375c0b5391b4453a01010f7e9ca3071ae273d..35f8a1f7e5d550229551059c26d0e9f30fa3514f 100644 GIT binary patch literal 14137 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 Mp`xQ)sc41#KZpH-y8r+H literal 13651 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 SH#z{}dZePITz%g<{C@ywVw{Ws diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_32.png b/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_32.png index c2ca3816a8630176168458f1ab2850cb28af5e92..ba31dce348b294b981831b43b00dc9cdeb13eb6d 100644 GIT binary patch delta 1249 zcmV<71RndG3G@k&BYy~lZno_p_H?>IT2&Xh2MU}|9! z*-KCw5=0c*L*QFI1rcEqy+uTX^kUFML{twNL2qe(WG0qYl4E9$gJzMXsW^@w-I;sN z*|E>v=Xz%5ei|*swkZcnVkt3lC}d9{a+S&BC`C&1xbl0BJa9n{RzgS)Y3>My!ijg4>V)pPqp@QJSiWv;Zh={CLT_m)S5wME z(Sw4g$Y+CkAoG@QVsPyUeaqg$%?+Y;(CEau3C)oVz)4OtG7;#>2<2XwQ_xZC%?rgu zAbD>N1Iu1wC}t#gr%k@jgi7K%?J};1?Fd@KjhjAR1~Ms)t2907kWxWMj1=<_O2`Ycp9OQt z&w)z<$_LN0HBW7ijaEbnC&w$dwlC~{3x9O7ZVLiKJnZ=DDwoPt`aDID2~m+cZ=L5@ z;-ZBQMlaQ#wZ@)yKRYuf{G?+?gz-tA=a2l3CU%T+r>Cfi>_Iv&>=d~Z^OSFt<00000 LNkvXXu0mjf-??VA delta 1161 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 I$0_Q60MN^5F8}}l literal 15795 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 wwHgF9ftDcz=^BDxRVV-dpZ~Aho*%< zZp}jqf~u4U8iB-X#RIMSRw4DFeFIfcsihJUg;GdSNrF_6Dhh~P$|dE}#w0XA5-yEN z<2dWJ*Bg8HoT+BcoaAKVUGLdT;;Q+i(b&6ZX1@P_zWKgy=6}q>CAlP*n98E-&A zp%Bi6Tn@_Wd`$(G!~}E!L(PG|C`3fM4p|I|32<$FPt5Ea0}RT|E>qb>8!j{vkGu`kiV3m#K z4Xq(z^Z?h(;HZGkCF>bjyOV+Sd*~SWZm6fSp(zlt)|RTfJy6An3}-l2TOejg83IgkbsZAnC?DzjbT0muCE`^& z2X71YY%LL0vB(;Y=GnUGeBN~+ZNRIuB)H%iA|y^^5uaJZz;#ctbYnz>tRNz>Dxw0* z`MOcPVU$xhEuIUR6sQvTO5scJ1A*`B8hoiq0Ds^2@fCC~`UV|~o}xJNcXEgBXX4|h z&Lu)cNod`Ysm7kH(m;Riw3+~I1yMGO%mL_}C05fKrF&M16Jq$MJ|@XIV&^M5GIHorw`p3QYcGDvQFAluFzVNx+yhM`a? zWs06GM}m_Q1WHjVL#Zq%`{4S@)Q)cJL)lSbv@j7vgi%B2XML2OKUW}oufj<$vQ{t$ z2#`8_D=2AX`mnGEKEE8qQh{^?6O(Wvrx+elk${F3R3_s>nBE*1ff)Uy<>$D23wao5c$)_uQ+1%r_@4t;A7 z!0}PV+lK;nza8+=r+O&}JSQZ=^+Ss&2a0l8AwFp@P9|4EA&A+e^J72FD3N%3HtjSHhkUTFR%JMw>L1K z>%Bv%te1vDmI6FCMThHB$d7aMAHUy}x4o)RC3~Zy5nnVm$fa;tbpFTWMmoKNXsBy&{ytA;4D-pS#TE*0p(l z^0VJ^@Ri??J86MS6GmDFynkf`2*OZy-;W0A?RO}jEY}a-tbqVDIN>0R1^ivxS+jc^ z(|evHm(vl##Sa2h&|2UvAwXJ>f7KP8+_q&NL9R~l6~HNu!>;X!7q_84c^|i@o1b65 znk|1mND!3GS>Ti7uzNea@P8y6I}GV8PERjN z1#IlkvZ5!=(XnDUj+%o6_%_~eyt)gf14P`#R|3~2EbVZGJnZ@ty!b~LK4O5=v%q*l z5%{LxRMunNK({3zTxN5M0HM9Ng8AJpE0=mu3d~HMCz>S34QGAg6ztvsFK&b3qvrrO zxvrH6>KA)EXt%hHHh+xrE=@ppr_NI=W=O9M{aT>IfkF;mc>@0WFdY8`GBX1|w{ykf ztW|HW`hfE!dL`l7L#Vuhp>7y@07gzhI$az1MG&{qhS8*q6?`Tp1A6C+FwIYE-~#pu z*l({fq^6;3Ug-Jj0d8E2;Kb>2GiiRC2~eRQIF&DP^wVj2mw#snh84~}8NQMj~p1`rH^xlTw@Wo+r;-pL?89R*{pwl@I}e}a2Y=5WW?H}MN;&2@OXo+`I?x>H zXY_zxr^oJp7x>PzhnTcyi7lA?Gts)*xw)*-_;`|$GzqQ{JbCB@H|+Qqubn93W<8vg zG!~&P#hmXMQo_?=eL(7FT|?M?Zye{_&%DdY;&eMUKgW}VL1pU?lD;4*TT6KTc%EyY zKEUl)_J48Lsy^2AW$8-0X8U|*1V7-zi4xC#oadpT|FC~V$ImdgXd!q}f#tlOMU5*m zYk`*=d3jQ~dmHS|uxde;!LAf3DalQhIh>#3z^O?l^%1bSMH04YL&B%AtONEWxkBp! zy}-dnFG=amq9cTovpi>>5u%-!qz+mvUecGNqkq8f?ca&>IirD6;mstyO%MWCo-Nu+ zMD$F1_WF8gVKIz0a*I3zECJrNc;?dO=-Eo7>$?_1)e91}BxTEHp!h#TLZoBS>K@@} zNV0Z=yA_zMxGa6KfzGt%quZgAR_CQ;)1oiYS=BBEF?W7m51 z?~3X^ei98T6M>GdpGEz&8gw;@W;PI~00000NkvXXu0mjf#Bc%9 delta 2407 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 From af00e2e07620c0d68af31584270891e2a1c091bb Mon Sep 17 00:00:00 2001 From: Sergey Ukolov Date: Fri, 14 Aug 2026 22:31:02 +0300 Subject: [PATCH 27/35] fix(macos): stop settings snapping back after a link glitch A short audio dropout was enough to desync the response stream for the rest of the session: changing NC/Ambient or an EQ preset reverted a second or two later, and DSEE wouldn't toggle at all. _readMessage() left the parser stranded whenever a chunk arrived garbled or truncated - bytes before the first START_MARKER were concatenated into the message, and a second start marker threw. 60/61/62 are escaped inside a frame, so a start marker unambiguously begins one; resync on it in both cases, and cap the buffer so a stream that never delivers an END_MARKER can't grow it forever. _waitForAck() read exactly one frame and assumed it was the ACK. The device pushes unsolicited notifications on the same stream (a state change, a press of the headset's own button), so it could take _seqNumber from the wrong frame - and the device dedupes on that sequence number, silently discarding the next command as a duplicate. Wait for an actual ACK frame instead; skipped notifications are still acked back by _readMessage(). Also: - requestAmbientState() matches sub-type 0x17 rather than any 0x67, so a notification with a different layout is no longer parsed as the reply - the read-back no longer overwrites a change that hasn't been sent yet. It cleared the pending change too (isChanged() went false), so the command was never sent at all. discardAmbientChanges() releases that state when a write genuinely fails, so polling can't stay suppressed - the 2s poll stopped republishing dsee/eqPreset/eqBands, which it never re-read - they came straight back from the C++ cache, which only updates once a write succeeds. Failed writes roll back explicitly with the error instead, and the EQ sliders no longer fight the timer mid-drag (cherry picked from commit 40e65d44dff0390c1617d77b817a7b9eaa3b4aba) Conflict resolution on top of #7/#28 (by maintainer): _waitForAck kept #7's equivalent ACK loop (now on MAX_FRAMES_PER_TRANSACTION); parser keeps this commit's resync-on-START_MARKER plus #7's noise skipping; the poll's change-gated writes and #7's slider coalescing are kept, with this commit's "sync either way" on a failed ambient write. Co-Authored-By: Claude Opus 5.5 --- Client/BluetoothWrapper.cpp | 37 +++++++++++++++++++++--------- Client/Headphones.cpp | 30 ++++++++++++++++++++---- Client/Headphones.h | 4 ++++ Client/macos/HeadphonesBridge.mm | 3 +++ Client/macos/HeadphonesModel.swift | 30 +++++++++++++----------- 5 files changed, 75 insertions(+), 29 deletions(-) diff --git a/Client/BluetoothWrapper.cpp b/Client/BluetoothWrapper.cpp index 9aef51a5..ed4ea784 100644 --- a/Client/BluetoothWrapper.cpp +++ b/Client/BluetoothWrapper.cpp @@ -1,5 +1,10 @@ #include "BluetoothWrapper.h" +// How many frames one transaction will read before giving up. The device interleaves ACKs and +// unsolicited notifications with the reply we're after, so a handful of unrelated frames is normal; +// this only bounds a device that never sends what we asked for. +static constexpr int MAX_FRAMES_PER_TRANSACTION = 16; + BluetoothWrapper::BluetoothWrapper(std::unique_ptr connector) { this->_connector.swap(connector); @@ -84,7 +89,7 @@ Buffer BluetoothWrapper::sendCommandAndReadResponse(const std::vector& byt this->_connector->send(data.data(), data.size()); // The device replies with an ACK and then the RET frame; unrelated notifications may interleave. - for (int i = 0; i < 16; i++) + for (int i = 0; i < MAX_FRAMES_PER_TRANSACTION; i++) { auto msg = this->_readMessage(); if (msg.dataType == DATA_TYPE::ACK) @@ -106,7 +111,7 @@ void BluetoothWrapper::_waitForAck() { // Notifications can arrive between a SET and its ACK. _readMessage() acknowledges DATA_MDR frames; // keep consuming until the device's actual ACK arrives so it cannot poison the next command. - for (int i = 0; i < 16; i++) + for (int i = 0; i < MAX_FRAMES_PER_TRANSACTION; i++) { auto msg = this->_readMessage(); if (msg.dataType == DATA_TYPE::ACK) @@ -145,8 +150,13 @@ CommandSerializer::Message BluetoothWrapper::_readMessage() throw RecoverableException("Bluetooth connection closed while reading a frame", true); } - // Bytes outside START/END markers are transport noise, not message data. When a frame spans recv() - // calls, the next chunk starts inside the frame and therefore begins at byte zero. + // Every 60/61/62 inside a frame is escaped, so a START_MARKER can only ever begin one. That makes + // resyncing unambiguous, which is what matters after a brief link glitch garbles or truncates a + // chunk: bytes before the first START_MARKER are the tail of a frame we can no longer parse, and + // a second START_MARKER means the frame we were collecting never finished. Both cases resync on + // the new marker here. Previously the first silently concatenated garbage into the message and + // the second threw, in either case leaving the parser stranded mid-stream for the rest of the + // session - every command after that failed and the UI kept snapping back to the old value. size_t messageStart = ongoingMessage ? 0 : static_cast(numRecvd); size_t messageEnd = static_cast(numRecvd); @@ -154,11 +164,10 @@ CommandSerializer::Message BluetoothWrapper::_readMessage() { if (buf[i] == START_MARKER) { - if (ongoingMessage) - { - throw RecoverableException("Invalid: Multiple start markers without an end marker", true); - } + // Whatever we had collected was a truncated frame, not the start of this one. + msgBytes.clear(); messageStart = i + 1; + messageEnd = static_cast(numRecvd); ongoingMessage = true; } else if (ongoingMessage && buf[i] == END_MARKER) @@ -167,16 +176,22 @@ CommandSerializer::Message BluetoothWrapper::_readMessage() ongoingMessage = false; messageFinished = true; // A single recv() can return more than one framed message back-to-back; keep whatever's - // past this message's END_MARKER for the next _waitForAck() call instead of dropping it. + // past this message's END_MARKER for the next read instead of dropping it. this->_leftoverBytes.assign(buf + i + 1, buf + numRecvd); break; } } - msgBytes.insert(msgBytes.end(), buf + messageStart, buf + messageEnd); + if (messageStart < messageEnd) + { + msgBytes.insert(msgBytes.end(), buf + messageStart, buf + messageEnd); + } + + // Bail out on a stream that keeps delivering bytes but never an END_MARKER, so the next read can + // resync on the next START_MARKER instead of growing this buffer forever. if (msgBytes.size() > MAX_BLUETOOTH_MESSAGE_SIZE) { - throw RecoverableException("Bluetooth frame exceeds the maximum message size", true); + throw RecoverableException("Invalid: message exceeded the maximum size without an end marker", true); } } while (!messageFinished); diff --git a/Client/Headphones.cpp b/Client/Headphones.cpp index 0c9a5fb0..3bc279e5 100644 --- a/Client/Headphones.cpp +++ b/Client/Headphones.cpp @@ -398,7 +398,9 @@ void Headphones::requestAmbientState() if (protocolVersion == SonyProtocolVersion::V2) { // GET: 66 17 -> RET: 67 17 01 - auto resp = this->_conn.sendCommandAndReadResponse({ 0x66, 0x17 }, 0x67); + // Match the sub-type too: 0x67 also carries unsolicited notifications with a different layout, + // and accepting one of those parsed / out of unrelated bytes. + auto resp = this->_conn.sendCommandAndReadResponse({ 0x66, 0x17 }, 0x67, 0x17); if (resp.size() >= 7) { bool on = resp[3] != 0; @@ -406,10 +408,17 @@ void Headphones::requestAmbientState() bool voice = resp[5] != 0; int level = (unsigned char)resp[6]; std::lock_guard guard(this->_propertyMtx); - // Update both current and desired so the UI reflects reality and isChanged() stays false. - this->_ambientSoundControl.current = this->_ambientSoundControl.desired = on; - this->_asmLevel.current = this->_asmLevel.desired = ambient ? level : 0; - this->_focusOnVoice.current = this->_focusOnVoice.desired = voice; + // A change the user just made may not be on the wire yet - the UI writes the desired values + // and only then queues the send - and this reply was produced before it. Adopting it would + // both revert the user's choice and clear the pending change (isChanged() goes false), so the + // command would never be sent at all. Leave everything alone until setChanges() has flushed it. + if (this->_ambientSoundControl.isFulfilled() && this->_asmLevel.isFulfilled() && this->_focusOnVoice.isFulfilled()) + { + // Update both current and desired so the UI reflects reality and isChanged() stays false. + this->_ambientSoundControl.current = this->_ambientSoundControl.desired = on; + this->_asmLevel.current = this->_asmLevel.desired = ambient ? level : 0; + this->_focusOnVoice.current = this->_focusOnVoice.desired = voice; + } } } else @@ -874,6 +883,17 @@ void Headphones::setMultipoint(bool enabled) this->_multipointEnabled = enabled; } +// requestAmbientState() deliberately refuses to adopt device state while a change is pending, so a write +// that never reached the device would otherwise block the read-back for the rest of the session - the UI +// would freeze on a value the headphones never took. Dropping the pending change lets polling resume. +void Headphones::discardAmbientChanges() +{ + std::lock_guard guard(this->_propertyMtx); + this->_ambientSoundControl.desired = this->_ambientSoundControl.current; + this->_asmLevel.desired = this->_asmLevel.current; + this->_focusOnVoice.desired = this->_focusOnVoice.current; +} + bool Headphones::isChanged() { std::lock_guard guard(this->_propertyMtx); diff --git a/Client/Headphones.h b/Client/Headphones.h index f04396a1..71fc173e 100644 --- a/Client/Headphones.h +++ b/Client/Headphones.h @@ -133,6 +133,10 @@ class Headphones { bool isChanged(); void setChanges(); + + // Rolls a failed ambient/NC write back to the last known device state. Must be called when + // setChanges() throws - see the comment on the definition. + void discardAmbientChanges(); private: Property _ambientSoundControl = { false, false }; Property _focusOnVoice = { false, false }; diff --git a/Client/macos/HeadphonesBridge.mm b/Client/macos/HeadphonesBridge.mm index 86c4e0c2..2ba293e4 100644 --- a/Client/macos/HeadphonesBridge.mm +++ b/Client/macos/HeadphonesBridge.mm @@ -494,6 +494,9 @@ - (void)applyMode:(SHCAmbientMode)mode ok = NO; error = @(exc.what()); } + // The write never landed, so stop it counting as pending - otherwise the ambient read-back stays + // suppressed and the UI freezes on a value the headphones never took. + if (!ok) hp->discardAmbientChanges(); dispatch_async(dispatch_get_main_queue(), ^{ completion(ok, error); }); diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index 490e6de0..59557b5d 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -254,15 +254,12 @@ final class HeadphonesModel: ObservableObject { self.bridge.refreshMultipoint { self.syncMultipointFromBridge() } } self.bridge.refreshDynamic { + // Only publish what refreshDynamic actually re-read: ambient/NC state and the battery. + // EQ and DSEE aren't re-read on this path - they'd come straight back from the C++ cache, + // so a failed write would snap back two seconds later and an EQ drag would fight the timer. self.assignIfChanged(\.mode, self.bridge.mode) let level = self.bridge.ambientLevel if level > 0 { self.assignIfChanged(\.ambientLevel, level) } - self.assignIfChanged(\.eqPreset, self.bridge.eqPreset) - self.assignIfChanged(\.supportsEqualizer, self.bridge.supportsEqualizer) - self.assignIfChanged(\.clearBass, self.bridge.clearBass) - self.assignIfChanged(\.supportsDsee, self.bridge.supportsDsee) - self.assignIfChanged(\.dsee, self.bridge.dsee) - self.assignIfChanged(\.eqBands, (0..<5).map { self.bridge.equalizerBand(at: $0) }) self.syncBatteryFromBridge() } } @@ -273,6 +270,8 @@ final class HeadphonesModel: ObservableObject { dynamicTimer = nil } + // The controls below update optimistically and are corrected here if the write failed, rather than + // being silently overwritten by the next poll tick. func setEqualizer(_ preset: Int) { if preset == 0xA0 { applyCustomEq() @@ -281,7 +280,10 @@ final class HeadphonesModel: ObservableObject { eqPreset = preset errorMessage = nil bridge.setEqualizerPreset(preset) { ok, error in - if !ok, let error = error { self.errorMessage = error } + if !ok { + self.eqPreset = self.bridge.eqPreset + if let error = error { self.errorMessage = error } + } } } @@ -315,7 +317,10 @@ final class HeadphonesModel: ObservableObject { dsee = on errorMessage = nil bridge.setDsee(on) { ok, error in - if !ok, let error = error { self.errorMessage = error } + if !ok { + self.dsee = self.bridge.dsee + if let error = error { self.errorMessage = error } + } } } @@ -391,11 +396,10 @@ final class HeadphonesModel: ObservableObject { return } } - if ok { - self.syncFromBridge() - } else if let error = error { - self.errorMessage = error - } + // Sync either way: on failure the bridge has rolled the pending change back, so this shows + // what the headphones are actually set to instead of leaving the UI lying. + self.syncFromBridge() + if !ok, let error = error { self.errorMessage = error } } } From 3228ad4e59fc5e5eb311a830a44d9b37b9f107b0 Mon Sep 17 00:00:00 2001 From: Sergey Ukolov Date: Wed, 19 Aug 2026 00:07:53 +0300 Subject: [PATCH 28/35] fix: read back the EQ bands after switching preset Selecting Manual showed the previous preset's slider positions, not the custom curve stored on the device. The bands were only ever read once, on connect, where the device reports the curve of whatever preset is active - setEqualizerPreset() then sent 58 00 00 and updated the cached preset byte alone, so the cached bands stayed behind. Touching a slider from there wrote those stale values back, overwriting the stored curve. Re-read with requestEqualizer() after the write, so the cache holds the bands that belong to the preset the device just switched to. The read-back is guarded: it runs after the property lock is released (requestEqualizer() takes the same non-recursive mutex), and a failed read leaves the bands stale rather than reporting the write that already landed as failed. The macOS model publishes eqPreset/clearBass/eqBands on a successful preset write, and the ImGui GUI pulls them into its sliders once the command future completes - neither re-read them on any other path. (cherry picked from commit 43a9221a1873079e07587236589dc057f99ede82) --- Client/CrossPlatformGUI.cpp | 12 ++++++++++++ Client/CrossPlatformGUI.h | 3 +++ Client/Headphones.cpp | 18 ++++++++++++++++-- Client/macos/HeadphonesModel.swift | 7 +++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/Client/CrossPlatformGUI.cpp b/Client/CrossPlatformGUI.cpp index 15a2de3a..7b52bda7 100644 --- a/Client/CrossPlatformGUI.cpp +++ b/Client/CrossPlatformGUI.cpp @@ -485,6 +485,9 @@ void CrossPlatformGUI::_drawEqualizer() { this->_uiEqPreset = presets[i].val; int p = presets[i].val; + // setEqualizerPreset() re-reads the bands that go with the new preset (the device restores the + // stored custom curve for Manual), so pull them into the sliders once the command lands. + this->_eqBandsNeedSync = true; this->_sendFeatureCommand([this, p]() { this->_headphones.setEqualizerPreset((EQ_PRESET)p); }); } if (sel) ImGui::PopStyleColor(); @@ -605,6 +608,15 @@ void CrossPlatformGUI::_sendPendingASMChanges() try { this->_featureCommandFuture.get(); } catch (const RecoverableException& e) { if (e.shouldDisconnect) this->_bt.disconnect(); this->_mq.addMessage(e.what()); } catch (const std::exception& e) { this->_mq.addMessage(e.what()); } + + if (this->_eqBandsNeedSync) + { + this->_eqBandsNeedSync = false; + this->_uiEqPreset = (int)(unsigned char)this->_headphones.getEqualizerPreset(); + for (int i = 0; i < 5; ++i) + this->_uiEqBands[i] = this->_headphones.getEqualizerBand(i); + this->_uiClearBass = this->_headphones.getClearBass(); + } } if (this->_sendCommandFuture.valid() && this->_sendCommandFuture.ready()) diff --git a/Client/CrossPlatformGUI.h b/Client/CrossPlatformGUI.h index f4a3d5b3..aceac4a0 100644 --- a/Client/CrossPlatformGUI.h +++ b/Client/CrossPlatformGUI.h @@ -94,6 +94,9 @@ class CrossPlatformGUI int _uiEqPreset = 0; std::array _uiEqBands = { 0, 0, 0, 0, 0 }; int _uiClearBass = 0; + // Set when a preset write is in flight, so the band sliders take the values the device reports for + // that preset once it completes instead of keeping the previous preset's. + bool _eqBandsNeedSync = false; bool _uiDsee = false; int _uiAutoPowerOff = 0; bool _uiSpeakToChat = false; diff --git a/Client/Headphones.cpp b/Client/Headphones.cpp index 3bc279e5..d51127b4 100644 --- a/Client/Headphones.cpp +++ b/Client/Headphones.cpp @@ -305,8 +305,22 @@ void Headphones::setEqualizerPreset(EQ_PRESET preset) (char)rawPreset, 0x00 }); - std::lock_guard guard(this->_propertyMtx); - this->_eqPreset = preset; + { + std::lock_guard guard(this->_propertyMtx); + this->_eqPreset = preset; + } + // The band values that go with the new preset live on the device, not here: selecting MANUAL restores + // the custom curve the user last stored on the headphones, and every other preset has its own fixed + // curve. Without this read-back the cached bands stay whatever the *previous* preset had, so switching + // to Manual showed the wrong slider positions. A failed read-back mustn't fail the write that already + // went through - the cached preset above is still correct, only the bands would be stale. + try + { + this->requestEqualizer(); + } + catch (const std::exception&) + { + } } void Headphones::setEqualizerCustom(int clearBass, const std::vector& bands) diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index 59557b5d..1de62721 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -283,7 +283,14 @@ final class HeadphonesModel: ObservableObject { if !ok { self.eqPreset = self.bridge.eqPreset if let error = error { self.errorMessage = error } + return } + // The bridge re-reads the EQ after the write, so this picks up the band values that belong to + // the preset just selected - in particular the custom curve the device restores for Manual, + // which is what the sliders below the chips show. + self.eqPreset = self.bridge.eqPreset + self.clearBass = self.bridge.clearBass + self.eqBands = (0..<5).map { self.bridge.equalizerBand(at: $0) } } } From 2312de0fd7d8c57bc4e801c4c78c4fe7f85d221e Mon Sep 17 00:00:00 2001 From: Amit Rajput Date: Tue, 27 Oct 2026 16:20:11 +0530 Subject: [PATCH 29/35] fix(xm6): read noise control via 0x19 and drive the ten-band equalizer (fixes #11) WH-1000XM6 answers the 66 17 noise-control inquiry with all zeros in every mode, which the 2s poll parsed as "Off" - so Noise Cancelling / Ambient switched the headset but the UI snapped straight back. It reports the same layout under inquired type 0x19. Its equalizer uses inquired type 0x04 with 10 raw bands (0..12) and no Clear Bass slot; the 5-band 58 00 frame is ACKed but ignored, which is why presets highlighted without changing the sound. - 66 19 on the XM6; any v2 reply whose byte [2] isn't 01 is ignored, so a zeroed answer can no longer read as "Off" on other models either - 56/58 04 ten-band read/preset/custom on the XM6; band count and the ten-band flag exposed to the UI, which shows 10 raw sliders, no Clear Bass, and only the Off/Custom presets (other XM6 preset codes are unnamed) - tests: XM6 frames, the zeroed-0x17 guard, and #7's multipoint test moved to the name-based general-settings slot lookup Layouts from btsnoop captures and hardware re-tests on a WH-1000XM6 (fw 3.1.5) by marconvcm/sony-device-center contributors (#44, #74). Co-Authored-By: Claude Opus 5.5 --- Client/Constants.h | 5 ++ Client/Headphones.cpp | 65 +++++++++++++- Client/Headphones.h | 10 ++- Client/macos/ContentView.swift | 30 ++++--- Client/macos/HeadphonesBridge.h | 2 + Client/macos/HeadphonesBridge.mm | 8 ++ Client/macos/HeadphonesModel.swift | 10 ++- Client/tests/HeadphonesProtocolTests.cpp | 108 +++++++++++++++++++---- 8 files changed, 201 insertions(+), 37 deletions(-) diff --git a/Client/Constants.h b/Client/Constants.h index eb3d9fc1..7a609e71 100644 --- a/Client/Constants.h +++ b/Client/Constants.h @@ -108,6 +108,11 @@ namespace V2Command inline constexpr unsigned char BTNMODE_SET = 0xf8; // SET f8 inline constexpr unsigned char SUB_ADAPTIVE_VOLUME = 0x0a; inline constexpr unsigned char SUB_SPEAK_TO_CHAT = 0x0c; + // Noise-control inquired types: 66/67/68 . The WH-1000XM6 reads back via 0x19 (0x17 returns zeros). + inline constexpr unsigned char NCASM_TYPE = 0x17; + inline constexpr unsigned char NCASM_TYPE_XM6 = 0x19; + // Ten-band equalizer inquired type (WH-1000XM6): 56/57/58 04, 10 raw bands 0..12, no clear bass. + inline constexpr unsigned char EQ_TEN_BAND = 0x04; // INIT_REPLY layout: 01 inline constexpr size_t INIT_REPLY_TABLE2_INDEX = 7; // General settings: up to four device-defined boolean/list settings in slots D1..D4. Which slot holds diff --git a/Client/Headphones.cpp b/Client/Headphones.cpp index d51127b4..10b20c64 100644 --- a/Client/Headphones.cpp +++ b/Client/Headphones.cpp @@ -114,6 +114,13 @@ bool Headphones::_looksLikeEarbuds() const return name.find("wf-") != std::string::npos || name.find("linkbuds") != std::string::npos; } +bool Headphones::_isWh1000Xm6() const +{ + std::string name; + for (char c : this->_deviceName) name.push_back((char)std::tolower((unsigned char)c)); + return name.find("wh-1000xm6") != std::string::npos || name.find("wh1000xm6") != std::string::npos; +} + // Reads the per-earbud (and case) levels. Returns false if the device didn't answer this sub-type or // answered with nothing usable, so the caller can fall back to the other layout. bool Headphones::_requestDualBattery(unsigned char subType) @@ -258,6 +265,24 @@ bool Headphones::isBatteryCaseCharging() { std::lock_guard guard(this->_property void Headphones::requestEqualizer() { auto isV1 = this->_conn.getProtocolVersion() == SonyProtocolVersion::V1; + if (!isV1 && this->_isWh1000Xm6()) + { + // GET 56 04 -> RET 57 04 , raw device steps 0..12 with no bias and no + // clear-bass slot. Layout from a Sound Connect btsnoop capture, verified on a WH-1000XM6 (fw 3.1.5) + // by sony-device-center (marconvcm/sony-device-center#44). The legacy 56 00 frame is ACKed but ignored. + auto resp = this->_conn.sendCommandAndReadResponse( + { (char)V2Command::EQ_GET, (char)V2Command::EQ_TEN_BAND }, V2Command::EQ_RET, V2Command::EQ_TEN_BAND); + if (resp.size() < 4) return; + size_t count = (unsigned char)resp[3]; + if (resp.size() < 4 + count) return; + std::lock_guard guard(this->_propertyMtx); + this->_eqPreset = static_cast((unsigned char)resp[2]); + this->_hasEqualizer = true; + this->_eqClearBass = 0; + this->_eqBands.assign(resp.begin() + 4, resp.begin() + 4 + count); + for (auto& band : this->_eqBands) band = (unsigned char)band; + return; + } auto subtype = isV1 ? 0x01 : 0x00; // v1 uses subtype 01; v2 uses subtype 00. Both return the same six-band value layout. auto resp = this->_conn.sendCommandAndReadResponse( @@ -298,10 +323,10 @@ void Headphones::setEqualizerPreset(EQ_PRESET preset) auto isV1 = this->_conn.getProtocolVersion() == SonyProtocolVersion::V1; auto rawPreset = (unsigned char)preset; if (isV1 && preset == EQ_PRESET::MANUAL) rawPreset = V1Command::MANUAL_EQ; - // SET preset: v1 58 01 00; v2 58 00 00. + // SET preset: v1 58 01 00; v2 58 00 00; ten-band v2 58 04 00. this->_conn.sendCommand({ (char)(isV1 ? V1Command::EQ_SET : V2Command::EQ_SET), - (char)(isV1 ? 0x01 : 0x00), + (char)(isV1 ? 0x01 : this->_isWh1000Xm6() ? V2Command::EQ_TEN_BAND : 0x00), (char)rawPreset, 0x00 }); @@ -327,6 +352,21 @@ void Headphones::setEqualizerCustom(int clearBass, const std::vector& bands { if (!this->hasEqualizer()) throw std::logic_error("Equalizer capability has not been confirmed"); auto isV1 = this->_conn.getProtocolVersion() == SonyProtocolVersion::V1; + if (!isV1 && this->_isWh1000Xm6()) + { + // SET 58 04 a0 , raw 0..12, no clear-bass slot. + std::vector raw(bands.begin(), bands.end()); + for (auto& band : raw) band = std::clamp(band, 0, 12); + Buffer cmd = { (char)V2Command::EQ_SET, (char)V2Command::EQ_TEN_BAND, + (char)static_cast(EQ_PRESET::MANUAL), (char)raw.size() }; + for (int band : raw) cmd.push_back((char)band); + this->_conn.sendCommand(cmd); + + std::lock_guard guard(this->_propertyMtx); + this->_eqPreset = EQ_PRESET::MANUAL; + this->_eqBands = raw; + return; + } // v1 selects custom EQ with 0xff/subtype 01; v2 uses 0xa0/subtype 00. auto clamp = [](int v) { return (char)(unsigned char)(std::max(-10, std::min(10, v)) + 10); }; Buffer cmd = { @@ -363,6 +403,18 @@ int Headphones::getEqualizerBand(int index) return (index >= 0 && index < (int)this->_eqBands.size()) ? this->_eqBands[index] : 0; } +int Headphones::getEqualizerBandCount() +{ + std::lock_guard guard(this->_propertyMtx); + return (int)this->_eqBands.size(); +} + +bool Headphones::isTenBandEqualizer() +{ + std::lock_guard guard(this->_propertyMtx); + return this->_conn.getProtocolVersion() == SonyProtocolVersion::V2 && this->_isWh1000Xm6(); +} + void Headphones::requestDsee() { auto isV1 = this->_conn.getProtocolVersion() == SonyProtocolVersion::V1; @@ -414,8 +466,13 @@ void Headphones::requestAmbientState() // GET: 66 17 -> RET: 67 17 01 // Match the sub-type too: 0x67 also carries unsolicited notifications with a different layout, // and accepting one of those parsed / out of unrelated bytes. - auto resp = this->_conn.sendCommandAndReadResponse({ 0x66, 0x17 }, 0x67, 0x17); - if (resp.size() >= 7) + // The WH-1000XM6 answers 66 17 with all zeros in every mode - parsing that as "off" is what snapped its + // UI back to Off (issue #11). It reports the same first seven bytes (plus two trailing ones) under + // inquired type 0x19, verified on fw 3.1.5 (marconvcm/sony-device-center#74). + unsigned char inquired = this->_isWh1000Xm6() ? V2Command::NCASM_TYPE_XM6 : V2Command::NCASM_TYPE; + auto resp = this->_conn.sendCommandAndReadResponse({ 0x66, (char)inquired }, 0x67, inquired); + // Byte [2] is always 01 in a real reply; anything else (like the XM6's zeroed 0x17 answer) is not state. + if (resp.size() >= 7 && resp[2] == 0x01) { bool on = resp[3] != 0; bool ambient = resp[4] != 0; diff --git a/Client/Headphones.h b/Client/Headphones.h index 71fc173e..fa69c279 100644 --- a/Client/Headphones.h +++ b/Client/Headphones.h @@ -72,10 +72,13 @@ class Headphones { bool hasEqualizer(); EQ_PRESET getEqualizerPreset(); void setEqualizerPreset(EQ_PRESET preset); - // Custom (manual) EQ: 5 band values + clear bass, each in [-10, 10]. Selects the MANUAL preset. + // Custom (manual) EQ. Selects the MANUAL preset. Standard layout: 5 bands + clear bass, each in [-10, 10]. + // Ten-band layout (WH-1000XM6): 10 raw device steps in [0, 12], no clear bass (ignored). void setEqualizerCustom(int clearBass, const std::vector& bands); int getClearBass(); - int getEqualizerBand(int index); // 0..4 + int getEqualizerBand(int index); + int getEqualizerBandCount(); + bool isTenBandEqualizer(); // DSEE / audio upsampling. void requestDsee(); @@ -159,6 +162,9 @@ class Headphones { std::string _deviceName; bool _looksLikeEarbuds() const; + // The WH-1000XM6 speaks a different layout for two v2 commands: noise-control state is read via inquired + // type 0x19 (0x17 answers all zeros), and the equalizer uses inquired type 0x04 with 10 raw bands. + bool _isWh1000Xm6() const; // Both return false if the device didn't answer that battery sub-type. bool _requestDualBattery(unsigned char subType); bool _requestSingleBattery(unsigned char subType, int& levelOut, bool& chargingOut); diff --git a/Client/macos/ContentView.swift b/Client/macos/ContentView.swift index 46af867b..a2e95bbe 100644 --- a/Client/macos/ContentView.swift +++ b/Client/macos/ContentView.swift @@ -271,6 +271,10 @@ struct ContentView: View { ("Manual", 0xA0) ] private let eqBandLabels = ["400", "1k", "2.5k", "6.3k", "16k"] + // WH-1000XM6: only Off and Custom have confirmed preset codes on the ten-band layout; its other preset + // bytes (0x20, 0x30-0x33, 0xa1-0xa2) are unnamed, and the 5-band codes above don't apply to it. + private let tenBandEqPresets: [(String, Int)] = [("Off", 0x00), ("Custom", 0xA0)] + private let tenBandEqLabels = ["31", "63", "125", "250", "500", "1k", "2k", "4k", "8k", "16k"] private var equalizerCard: some View { VStack(alignment: .leading, spacing: 14) { @@ -278,22 +282,25 @@ struct ContentView: View { .font(.system(size: 15, weight: .semibold)) .foregroundColor(.white) LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())], spacing: 10) { - ForEach(eqPresets, id: \.1) { preset in + ForEach(model.tenBandEqualizer ? tenBandEqPresets : eqPresets, id: \.1) { preset in eqChip(preset.0, preset.1) } } if model.eqPreset == 0xA0 { Divider().background(Theme.cardHi) - ForEach(0..<5, id: \.self) { i in - eqBandRow(eqBandLabels[i], value: Binding( + let labels = model.tenBandEqualizer ? tenBandEqLabels : eqBandLabels + ForEach(0.., display: Int, accent: Bool = false) -> some View { + // raw: the ten-band layout's 0...12 device steps (no dB mapping is known yet), shown unsigned. + private func eqBandRow(_ label: String, value: Binding, display: Int, accent: Bool = false, raw: Bool = false) -> some View { HStack(spacing: 10) { Text(label) .font(.system(size: 11, weight: .medium)) .foregroundColor(accent ? Theme.accent : Theme.secondary) .frame(width: 34, alignment: .leading) - Slider(value: value, in: -10...10, step: 1).accentColor(Theme.accent) - Text("\(display > 0 ? "+" : "")\(display)") + Slider(value: value, in: raw ? 0...12 : -10...10, step: 1).accentColor(Theme.accent) + Text(raw ? "\(display)" : "\(display > 0 ? "+" : "")\(display)") .font(.system(size: 11, weight: .semibold, design: .monospaced)) .foregroundColor(.white) .frame(width: 26, alignment: .trailing) diff --git a/Client/macos/HeadphonesBridge.h b/Client/macos/HeadphonesBridge.h index c551c3a1..76ac43ac 100644 --- a/Client/macos/HeadphonesBridge.h +++ b/Client/macos/HeadphonesBridge.h @@ -53,6 +53,8 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { @property (nonatomic, readonly) NSInteger eqPreset; // raw preset byte (EQ_PRESET) @property (nonatomic, readonly) BOOL supportsEqualizer; // true after a successful read-only probe @property (nonatomic, readonly) NSInteger clearBass; // -10..10 +@property (nonatomic, readonly) NSInteger equalizerBandCount; // 5, or 10 on the ten-band layout +@property (nonatomic, readonly) BOOL tenBandEqualizer; // WH-1000XM6: raw 0..12 bands, no clear bass @property (nonatomic, readonly) BOOL supportsDsee; // true after a successful read-only probe @property (nonatomic, readonly) BOOL dsee; // DSEE / audio upsampling diff --git a/Client/macos/HeadphonesBridge.mm b/Client/macos/HeadphonesBridge.mm index 2ba293e4..90678d39 100644 --- a/Client/macos/HeadphonesBridge.mm +++ b/Client/macos/HeadphonesBridge.mm @@ -140,6 +140,14 @@ - (BOOL)supportsDsee { return _hp && _hp->hasDsee(); } +- (NSInteger)equalizerBandCount { + return _hp ? _hp->getEqualizerBandCount() : 5; +} + +- (BOOL)tenBandEqualizer { + return _hp && _hp->isTenBandEqualizer(); +} + - (NSInteger)equalizerBandAtIndex:(NSInteger)index { return _hp ? _hp->getEqualizerBand((int)index) : 0; } diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index 1de62721..f27d7714 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -49,6 +49,7 @@ final class HeadphonesModel: ObservableObject { @Published var eqPreset = 0 @Published var supportsEqualizer = false @Published var eqBands = [0, 0, 0, 0, 0] + @Published var tenBandEqualizer = false @Published var clearBass = 0 @Published var supportsDsee = false @Published var dsee = false @@ -133,7 +134,8 @@ final class HeadphonesModel: ObservableObject { self.clearBass = self.bridge.clearBass self.supportsDsee = self.bridge.supportsDsee self.dsee = self.bridge.dsee - self.eqBands = (0..<5).map { self.bridge.equalizerBand(at: $0) } + self.tenBandEqualizer = self.bridge.tenBandEqualizer + self.eqBands = self.readEqBands() self.hasAutoPowerOff = self.bridge.hasAutoPowerOff self.autoPowerOff = self.bridge.autoPowerOff self.firmware = self.bridge.firmware ?? "" @@ -196,6 +198,10 @@ final class HeadphonesModel: ObservableObject { multipointDiagnostics = bridge.multipointDiagnostics } + private func readEqBands() -> [Int] { + (0.. #include #include +#include #include #include #include @@ -93,9 +94,8 @@ class FakeV1Connector final : public IBluetoothConnector std::deque incoming; }; -// v2-generation device that supports multipoint the way GadgetBridge proved it on the WH-ULT900N: -// only the touch-sensor 0xd1 GET answers with the multipoint state; every other capability probe -// times out (recv on an empty queue throws), which the probe treats as "unsupported". +// v2-generation device scripted per test through `reply`: a request it returns an empty buffer for gets +// only the ACK, so the read times out (recv on an empty queue throws), which callers treat as "unsupported". class FakeV2Connector final : public IBluetoothConnector { public: @@ -111,11 +111,8 @@ class FakeV2Connector final : public IBluetoothConnector sentPayloads.push_back(message.payload); queue({}, DATA_TYPE::ACK, 1 - message.seqNumber); - // GET d6 d1 -> RET d7 d1 00 <00=on/01=off> (GadgetBridge SonyProtocolImplV2 handleTouchSensor; - // the enable bit is inverted). The fake reports multipoint currently ON. - if (message.payload.size() >= 2 && (unsigned char)message.payload[0] == V2Command::TOUCH_GET - && (unsigned char)message.payload[1] == V2Command::SUB_MULTIPOINT) - queue({ (char)V2Command::TOUCH_RET, (char)V2Command::SUB_MULTIPOINT, 0x00, 0x00 }, DATA_TYPE::DATA_MDR, 0); + auto response = reply ? reply(message.payload) : Buffer{}; + if (!response.empty()) queue(response, DATA_TYPE::DATA_MDR, 0); return static_cast(length); } @@ -136,6 +133,12 @@ class FakeV2Connector final : public IBluetoothConnector SonyProtocolVersion getProtocolVersion() noexcept override { return SonyProtocolVersion::V2; } std::vector sentPayloads; + std::function reply; + + bool sent(const Buffer& payload) const + { + return std::find(sentPayloads.begin(), sentPayloads.end(), payload) != sentPayloads.end(); + } private: void queue(const Buffer& payload, DATA_TYPE type, unsigned char sequence) @@ -147,6 +150,13 @@ class FakeV2Connector final : public IBluetoothConnector std::deque incoming; }; +Buffer bytes(std::initializer_list values) +{ + Buffer out; + for (int v : values) out.push_back((char)v); + return out; +} + void require(bool condition, const char* message) { if (!condition) throw std::runtime_error(message); @@ -245,28 +255,43 @@ int main() // Multipoint has no proven v1 frames (GadgetBridge SonyProtocolImplV1: "Connect two devices not // implemented for V1"), so the XM4 path must never probe or set it. - require(!headphones.hasMultipoint(), "multipoint capability must stay unconfirmed on v1"); + headphones.requestMultipoint(); + require(!headphones.hasMultipointSetting(), "multipoint capability must stay unconfirmed on v1"); const auto hasMultipointFrame = std::any_of(observed->sentPayloads.begin(), observed->sentPayloads.end(), [](const Buffer& payload) { - return !payload.empty() && ((unsigned char)payload[0] == V2Command::TOUCH_GET || - (unsigned char)payload[0] == V2Command::TOUCH_SET || + return !payload.empty() && ((unsigned char)payload[0] == V2Command::GS_GET_CAPABILITY || + (unsigned char)payload[0] == V2Command::GS_GET_PARAM || + (unsigned char)payload[0] == V2Command::GS_SET_PARAM || (unsigned char)payload[0] == V2Command::SYSCTL_SET); }); - require(!hasMultipointFrame, "XM4 path emitted a v2 multipoint frame (d6/d8/98)"); + require(!hasMultipointFrame, "XM4 path emitted a v2 multipoint frame (d0/d6/d8/98)"); bool multipointRejected = false; try { headphones.setMultipoint(true); } - catch (const std::logic_error&) { multipointRejected = true; } + catch (const std::exception&) { multipointRejected = true; } require(multipointRejected, "setMultipoint on v1 must throw instead of sending"); // --- v2 multipoint ("Connect to 2 devices"), byte layout proven by GadgetBridge on the WH-ULT900N // (SonyProtocolImplV2 commits 8cbc309346, e8520865f3, 5d7b37d1b7) --- + // The setting lives in a per-model general-settings slot, found by name; the ULT900N uses D1. auto fakeV2 = std::make_unique(); auto* observedV2 = fakeV2.get(); + observedV2->reply = [](const Buffer& request) -> Buffer { + if (request == bytes({ 0xd0, 0xd1, 0x01 })) { + std::string name = "MULTIPOINT_SETTING"; + Buffer response = bytes({ 0xd1, 0xd1, 0x00, 0x00, (int)name.size() }); + response.insert(response.end(), name.begin(), name.end()); + response.push_back(0x00); + return response; + } + if (request == bytes({ 0xd6, 0xd1 })) return bytes({ 0xd7, 0xd1, 0x00, 0x00 }); // 00 = ON (inverted) + return {}; + }; BluetoothWrapper bluetoothV2(std::move(fakeV2)); Headphones ult900n(bluetoothV2); ult900n.probeCapabilities(); + ult900n.requestMultipoint(); - require(ult900n.hasMultipoint(), "v2 multipoint probe (d6 d1) was not recorded"); - require(ult900n.getMultipoint(), "RET d7 d1 00 00 must parse as multipoint ON (enable bit inverted)"); + require(ult900n.hasMultipointSetting(), "MULTIPOINT_SETTING slot D1 was not found by name"); + require(ult900n.getMultipointEnabled(), "RET d7 d1 00 00 must parse as multipoint ON (enable bit inverted)"); require(!ult900n.hasSpeakToChat() && !ult900n.hasAdaptiveVolume(), "unanswered v2 probes must stay unsupported"); @@ -278,7 +303,7 @@ int main() "multipoint OFF state frame must be d8 d1 00 01"); require(offCommit == Buffer({ (char)0x98, 0x00, 0x06, 0x01 }), "multipoint apply commit must be the fixed 98 00 06 01"); - require(!ult900n.getMultipoint(), "multipoint OFF was not mirrored locally"); + require(!ult900n.getMultipointEnabled(), "multipoint OFF was not mirrored locally"); ult900n.setMultipoint(true); const auto onState = observedV2->sentPayloads[observedV2->sentPayloads.size() - 2]; @@ -287,7 +312,54 @@ int main() "multipoint ON state frame must be d8 d1 00 00"); require(onCommit == Buffer({ (char)0x98, 0x00, 0x06, 0x01 }), "multipoint ON must reuse the fixed apply commit 98 00 06 01"); - require(ult900n.getMultipoint(), "multipoint ON was not mirrored locally"); + require(ult900n.getMultipointEnabled(), "multipoint ON was not mirrored locally"); + + // --- WH-1000XM6 (issue #11): noise control reads via 0x19, the equalizer is the ten-band 0x04 layout. + // Frames captured on fw 3.1.5 by marconvcm/sony-device-center (#44, #74). --- + auto fakeXm6 = std::make_unique(); + auto* observedXm6 = fakeXm6.get(); + observedXm6->reply = [](const Buffer& request) -> Buffer { + if (request == bytes({ 0x66, 0x17 })) return bytes({ 0x67, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00 }); + if (request == bytes({ 0x66, 0x19 })) return bytes({ 0x67, 0x19, 0x01, 0x01, 0x01, 0x00, 0x0a, 0x00, 0x00 }); + if (request == bytes({ 0x56, 0x04 })) return bytes({ 0x57, 0x04, 0xa0, 0x0a, 6, 6, 6, 6, 6, 6, 6, 6, 6, 12 }); + return {}; + }; + BluetoothWrapper bluetoothXm6(std::move(fakeXm6)); + Headphones xm6(bluetoothXm6); + xm6.setDeviceName("WH-1000XM6"); + + xm6.requestAmbientState(); + require(observedXm6->sent(bytes({ 0x66, 0x19 })) && !observedXm6->sent(bytes({ 0x66, 0x17 })), + "XM6 noise control must be read via 66 19"); + require(xm6.getAmbientSoundControl() && xm6.getAsmLevel() == 10, "XM6 67 19 reply (Ambient, level 10) was not parsed"); + + xm6.requestEqualizer(); + require(xm6.hasEqualizer() && xm6.isTenBandEqualizer(), "XM6 ten-band equalizer was not recognised"); + require(xm6.getEqualizerBandCount() == 10 && xm6.getEqualizerBand(0) == 6 && xm6.getEqualizerBand(9) == 12, + "XM6 raw ten-band values were not decoded"); + require(xm6.getEqualizerPreset() == EQ_PRESET::MANUAL, "XM6 custom preset byte was not decoded"); + + xm6.setEqualizerCustom(5, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 13 }); + require(observedXm6->sentPayloads.back() == bytes({ 0x58, 0x04, 0xa0, 0x0a, 0, 1, 2, 3, 4, 5, 6, 7, 8, 12 }), + "XM6 custom EQ must be 58 04 a0 0a <10 raw bands clamped to 0..12>, no clear bass"); + xm6.setEqualizerPreset(EQ_PRESET::OFF); + require(observedXm6->sent(bytes({ 0x58, 0x04, 0x00, 0x00 })), "XM6 preset must use inquired type 04"); + + // Any other v2 headset that answered 66 17 with zeros must not be read as "Off" either. + auto fakeZeros = std::make_unique(); + fakeZeros->reply = [](const Buffer& request) -> Buffer { + if (request == bytes({ 0x66, 0x17 })) return bytes({ 0x67, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00 }); + return {}; + }; + BluetoothWrapper bluetoothZeros(std::move(fakeZeros)); + Headphones zeros(bluetoothZeros); + zeros.setDeviceName("WH-1000XM5"); + zeros.setAmbientSoundControl(true); + zeros.setAsmLevel(7); + zeros.setFocusOnVoice(false); + zeros.setChanges(); + zeros.requestAmbientState(); + require(zeros.getAmbientSoundControl() && zeros.getAsmLevel() == 7, "a zeroed 67 17 reply overwrote the state"); // Malformed inbound frames on the untrusted parser path must throw the recoverable type. // 61 (0x3D) is the escape sentry; a lone one at buffer end and one followed by a @@ -300,6 +372,6 @@ int main() expectRecoverable([] { CommandSerializer::unpackBtMessage(Buffer{ 0x00, 0x00, 0x00 }); }, "under-minimum-size frame did not throw RecoverableException"); - std::cout << "WH-1000XM4 protocol safety tests passed\n"; + std::cout << "XM4 / multipoint / XM6 protocol tests passed\n"; return 0; } From 642bf99d9b6ac1bcb87447905c3c70ffb2c1a15b Mon Sep 17 00:00:00 2001 From: Amit Rajput Date: Tue, 27 Oct 2026 16:25:23 +0530 Subject: [PATCH 30/35] docs: one-line Homebrew install that taps automatically (fixes #9) The landing page told people to run `brew install --cask sonybridge`, which fails: the cask lives in our tap, not homebrew/cask. The fully-qualified name taps on first use. Also bump the stated minimum to macOS 12. Co-Authored-By: Claude Opus 5.5 --- README.md | 4 ++-- docs/index.html | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a67afb1b..87a8de22 100644 --- a/README.md +++ b/README.md @@ -72,12 +72,12 @@ on macOS, and a matching modern UI on Windows/Linux. macOS -`brew tap AmitRajput-Dev/tap && brew install --cask sonybridge` +`brew install --cask amitrajput-dev/tap/sonybridge` or [**Download .app**](https://github.com/AmitRajput-Dev/SonyBridge/releases/latest) -macOS 11+ · Apple Silicon & Intel +macOS 12+ · Apple Silicon & Intel Windows diff --git a/docs/index.html b/docs/index.html index d626c207..7f71cd18 100644 --- a/docs/index.html +++ b/docs/index.html @@ -215,7 +215,7 @@

Your Sony headphones,
finally on your desktop.
- $brew install --cask sonybridge + $brew install --cask amitrajput-dev/tap/sonybridge
MIT licensed · builds on the community SonyHeadphonesClient
@@ -337,8 +337,8 @@

Install in a minute.

macOS
-
$brew install --cask sonybridge
-
macOS 11+ · Apple Silicon & Intel · or download the .app
+
$brew install --cask amitrajput-dev/tap/sonybridge
+
macOS 12+ · Apple Silicon & Intel · or download the .app
From 26f079840d38786d6682ffd627010fc2d0acb625 Mon Sep 17 00:00:00 2001 From: Amit Rajput Date: Tue, 27 Oct 2026 16:36:33 +0530 Subject: [PATCH 31/35] feat(macos): refreshed look with three selectable themes Same single-window layout; every control, condition and binding unchanged. - Refined Dark (default): today's look, polished - segmented mode control, status chips (battery / codec / mode), EQ curve preview, hairline cards - Native Glass: follows system light/dark, material cards, system accent - Sony Signature: near-black with a warm amber accent, rings behind the product, pill controls, EQ bars - Theme picker under Appearance in the device-info popover, remembered across launches; applied through NSApp.appearance because .preferredColorScheme(nil) doesn't return a macOS window to the system appearance once it has been forced dark - Theme tokens and one card modifier replace the hard-coded colours and the six copies of card chrome; macOS 12 is now the minimum (materials; Xcode 27 no longer builds for 11) Co-Authored-By: Claude Opus 5.5 --- Client/macos/ContentView.swift | 411 ++++++++++-------- .../project.pbxproj | 12 +- Client/macos/Theme.swift | 284 ++++++++++++ 3 files changed, 514 insertions(+), 193 deletions(-) create mode 100644 Client/macos/Theme.swift diff --git a/Client/macos/ContentView.swift b/Client/macos/ContentView.swift index a2e95bbe..d90c992b 100644 --- a/Client/macos/ContentView.swift +++ b/Client/macos/ContentView.swift @@ -7,22 +7,16 @@ import SwiftUI import AppKit import Combine -private enum Theme { - static let bg = Color(red: 0.07, green: 0.07, blue: 0.086) - static let card = Color(red: 0.13, green: 0.13, blue: 0.16) - static let cardHi = Color(red: 0.20, green: 0.20, blue: 0.24) - static let accent = Color(red: 0.62, green: 0.62, blue: 0.96) - static let secondary = Color(white: 0.62) -} - -@available(macOS 11.0, *) struct ContentView: View { @StateObject private var model = HeadphonesModel.shared @State private var showAbout = false + @AppStorage("appTheme") private var theme = AppTheme.refinedDark + @Environment(\.colorScheme) private var colorScheme + + private var palette: Palette { theme.palette(colorScheme) } var body: some View { ZStack { - Theme.bg.ignoresSafeArea() if model.connected { connectedView } else { @@ -30,6 +24,16 @@ struct ContentView: View { } } .frame(minWidth: 360, minHeight: 500) + .background(palette.background) + .environment(\.appTheme, theme) + .onAppear { applyAppearance(theme) } + .onChange(of: theme, perform: applyAppearance) + } + + // Not .preferredColorScheme: on macOS, once it has forced a window dark, setting it back to nil + // doesn't return the window to the system appearance, so Native Glass would stay dark until relaunch. + private func applyAppearance(_ theme: AppTheme) { + NSApp.appearance = theme.colorScheme == .dark ? NSAppearance(named: .darkAqua) : nil } // MARK: - Disconnected @@ -39,24 +43,24 @@ struct ContentView: View { Spacer() Image(systemName: "headphones") .font(.system(size: 64, weight: .thin)) - .foregroundColor(Theme.secondary) + .foregroundColor(palette.secondary) Text("No headphones connected") .font(.system(size: 15, weight: .medium)) - .foregroundColor(Theme.secondary) + .foregroundColor(palette.secondary) if let error = model.errorMessage { Text(error) .font(.system(size: 12)) - .foregroundColor(.red.opacity(0.9)) + .foregroundColor(palette.danger) .multilineTextAlignment(.center) .padding(.horizontal, 32) } Button(action: model.connect) { Text(model.connecting ? "Connecting…" : "Connect headphones") .font(.system(size: 14, weight: .semibold)) - .foregroundColor(.white) + .foregroundColor(palette.onAccent) .frame(maxWidth: .infinity) .padding(.vertical, 12) - .background(Theme.accent) + .background(palette.accent) .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) } .buttonStyle(PlainButtonStyle()) @@ -91,7 +95,7 @@ struct ContentView: View { if let error = model.errorMessage { Text(error) .font(.system(size: 12)) - .foregroundColor(.red.opacity(0.9)) + .foregroundColor(palette.danger) } } .padding(20) @@ -103,41 +107,23 @@ struct ContentView: View { HStack(spacing: 10) { Spacer() Button(action: { showAbout = true }) { - Image(systemName: "ellipsis") - .font(.system(size: 15, weight: .semibold)) - .foregroundColor(Theme.secondary) - .frame(width: 32, height: 32) - .background(Theme.card) - .clipShape(Circle()) + roundIcon("ellipsis", size: 15) } .buttonStyle(PlainButtonStyle()) .popover(isPresented: $showAbout, arrowEdge: .bottom) { aboutView } Button(action: model.disconnect) { - Image(systemName: "power") - .font(.system(size: 14, weight: .semibold)) - .foregroundColor(Theme.secondary) - .frame(width: 32, height: 32) - .background(Theme.card) - .clipShape(Circle()) + roundIcon("power", size: 14) } .buttonStyle(PlainButtonStyle()) } // Product-style banner. Generic headphone graphic (device-specific Sony renders are - // copyrighted and can't be bundled) over a soft accent halo, mirroring Sony's app layout. + // copyrighted and can't be bundled) over the theme's backdrop, mirroring Sony's app layout. ZStack { - // Soft accent glow behind the product for depth. - Circle() - .fill( - RadialGradient( - gradient: Gradient(colors: [Theme.accent.opacity(0.22), Theme.accent.opacity(0.0)]), - center: .center, startRadius: 4, endRadius: 104 - ) - ) - .frame(width: 210, height: 210) + HeroBackdrop() if let image = deviceImage() { - // Background-removed product cutout floating on the dark UI. + // Background-removed product cutout floating on the backdrop. Image(nsImage: image) .resizable() .aspectRatio(contentMode: .fit) @@ -145,82 +131,124 @@ struct ContentView: View { } else { Image(systemName: "headphones") .font(.system(size: 92, weight: .thin)) - .foregroundColor(.white) + .foregroundColor(palette.primary) } } Text(model.deviceName) .font(.system(size: 24, weight: .bold)) - .foregroundColor(.white) - - HStack(spacing: 7) { - if model.hasDualBattery { - // Earbuds report a battery each, plus the case when it's connected. An earbud that - // isn't reporting (docked / powered down) comes through as -1 and is left out. - budBattery("L", model.batteryLeft, charging: model.batteryLeftCharging) - budBattery("R", model.batteryRight, charging: model.batteryRightCharging) - if model.batteryCase >= 0 { - budBattery("Case", model.batteryCase, charging: model.batteryCaseCharging) + .foregroundColor(palette.primary) + + HStack(spacing: 6) { + chip { + if model.hasDualBattery { + // Earbuds report a battery each, plus the case when it's connected. An earbud that + // isn't reporting (docked / powered down) comes through as -1 and is left out. + budBattery("L", model.batteryLeft, charging: model.batteryLeftCharging) + Text("·") + budBattery("R", model.batteryRight, charging: model.batteryRightCharging) + if model.batteryCase >= 0 { + Text("·") + budBattery("Case", model.batteryCase, charging: model.batteryCaseCharging) + } + } else if model.batteryLevel >= 0 { + Image(systemName: model.batteryCharging ? "bolt.fill" : batterySymbol(model.batteryLevel)) + .foregroundColor(model.batteryLevel <= 20 ? palette.danger : palette.accent) + chipText("\(model.batteryLevel)%") + } else { + Circle().fill(palette.accent).frame(width: 6, height: 6) + chipText("Connected") } - } else if model.batteryLevel >= 0 { - Image(systemName: model.batteryCharging ? "bolt.fill" : batterySymbol(model.batteryLevel)) - .font(.system(size: 13)) - .foregroundColor(model.batteryLevel <= 20 ? .red.opacity(0.9) : Theme.accent) - Text("\(model.batteryLevel)%") - .font(.system(size: 14, weight: .semibold)) - .foregroundColor(Theme.secondary) - } else { - Circle().fill(Theme.accent).frame(width: 7, height: 7) - Text("Connected") - .font(.system(size: 13, weight: .medium)) - .foregroundColor(Theme.secondary) } if !model.codec.isEmpty { - Text("·").foregroundColor(Theme.secondary) - Text(model.codec) - .font(.system(size: 12, weight: .semibold)) - .foregroundColor(Theme.secondary) + chip { chipText(model.codec) } } + chip { chipText(modeName(model.mode)) } } } .padding(.bottom, 4) } + private func roundIcon(_ symbol: String, size: CGFloat) -> some View { + Image(systemName: symbol) + .font(.system(size: size, weight: .semibold)) + .foregroundColor(palette.secondary) + .frame(width: 32, height: 32) + .background(palette.raised, in: Circle()) + .overlay(Circle().strokeBorder(palette.cardStroke, lineWidth: 1)) + } + + private func chip(@ViewBuilder _ content: () -> Content) -> some View { + HStack(spacing: 4, content: content) + .font(.system(size: theme.isSignature ? 10 : 11, weight: .semibold)) + .foregroundColor(palette.secondary) + .lineLimit(1) + .padding(.horizontal, 9) + .padding(.vertical, 4) + .background(palette.raised, in: Capsule()) + .overlay(Capsule().strokeBorder(palette.cardStroke, lineWidth: 1)) + } + + private func chipText(_ text: String) -> Text { + Text(theme.isSignature ? text.uppercased() : text).tracking(theme.isSignature ? 0.8 : 0) + } + + private func cardTitle(_ title: String) -> some View { + Text(theme.isSignature ? title.uppercased() : title) + .font(.system(size: theme.isSignature ? 11 : 15, weight: .semibold)) + .tracking(theme.isSignature ? 1.2 : 0) + .foregroundColor(theme.isSignature ? palette.secondary : palette.primary) + } + + private func modeName(_ mode: SHCAmbientMode) -> String { + switch mode { + case .noiseCanceling: return "Noise Canceling" + case .ambientSound: return "Ambient" + default: return "Off" + } + } + + // Selected/idle look shared by the mode control and the EQ presets: pills in Sony Signature, + // rounded segments otherwise. The content shape keeps clear (idle) segments clickable. + private func selectable(_ label: Label, selected: Bool, idleFill: Color) -> some View { + let shape = RoundedRectangle(cornerRadius: theme.isSignature ? 15 : 8, style: .continuous) + return label + .foregroundColor(selected ? palette.selectedText : palette.secondary) + .background(selected ? palette.selectedFill : idleFill, in: shape) + .overlay(shape.strokeBorder(selected ? palette.selectedStroke + : (theme.isSignature ? palette.cardStroke : .clear), lineWidth: 1)) + .contentShape(shape) + } + private var ambientCard: some View { - VStack(alignment: .leading, spacing: 16) { - Text("Ambient Sound Control") - .font(.system(size: 15, weight: .semibold)) - .foregroundColor(.white) - HStack(spacing: 0) { - modeButton(.noiseCanceling, "speaker.slash.fill", "Noise\nCanceling") - modeButton(.ambientSound, "wind", "Ambient\nSound") - modeButton(.off, "circle", "Off") - } + let track = RoundedRectangle(cornerRadius: 11, style: .continuous) + return VStack(alignment: .leading, spacing: 16) { + cardTitle("Ambient Sound Control") + HStack(spacing: theme.isSignature ? 6 : 0) { + modeButton(.noiseCanceling) + modeButton(.ambientSound) + modeButton(.off) + } + .padding(theme.isSignature ? 0 : 3) + .background(palette.track, in: track) + .overlay(track.strokeBorder(theme.isSignature ? .clear : palette.cardStroke, lineWidth: 1)) } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Theme.card) - .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) + .themedCard() } - private func modeButton(_ mode: SHCAmbientMode, _ symbol: String, _ label: String) -> some View { + private func modeButton(_ mode: SHCAmbientMode) -> some View { let selected = model.mode == mode return Button(action: { model.setMode(mode) }) { - VStack(spacing: 8) { - ZStack { - Circle() - .fill(selected ? Theme.accent : Theme.cardHi) - .frame(width: 58, height: 58) - Image(systemName: symbol) - .font(.system(size: 22, weight: .medium)) - .foregroundColor(selected ? .white : Theme.secondary) - } - Text(label) - .font(.system(size: 11, weight: .medium)) - .multilineTextAlignment(.center) - .foregroundColor(selected ? .white : Theme.secondary) - } - .frame(maxWidth: .infinity) + selectable( + Text(modeName(mode)) + .font(.system(size: 12, weight: .semibold)) + .lineLimit(1) + .minimumScaleFactor(0.8) + .frame(maxWidth: .infinity) + .padding(.vertical, 8), + selected: selected, idleFill: .clear + ) + .shadow(color: selected ? palette.selectedShadow : .clear, radius: 8) } .buttonStyle(.plain) } @@ -230,11 +258,11 @@ struct ContentView: View { HStack { Text("Ambient Sound Level") .font(.system(size: 13, weight: .medium)) - .foregroundColor(Theme.secondary) + .foregroundColor(palette.secondary) Spacer() Text("\(model.ambientLevel)") - .font(.system(size: 20, weight: .bold, design: .rounded)) - .foregroundColor(Theme.accent) + .font(.system(size: 20, weight: .bold, design: theme.isSignature ? .monospaced : .rounded)) + .foregroundColor(palette.accentText) } Slider( value: Binding( @@ -244,7 +272,7 @@ struct ContentView: View { in: 1...Double(model.maxAmbientLevel), step: 1 ) - .accentColor(Theme.accent) + .accentColor(palette.accent) if model.focusOnVoiceAvailable { Toggle(isOn: Binding( @@ -253,15 +281,12 @@ struct ContentView: View { )) { Text("Focus on Voice") .font(.system(size: 13, weight: .medium)) - .foregroundColor(.white) + .foregroundColor(palette.primary) } - .toggleStyle(SwitchToggleStyle(tint: Theme.accent)) + .toggleStyle(SwitchToggleStyle(tint: palette.accent)) } } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Theme.card) - .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) + .themedCard() } private let eqPresets: [(String, Int)] = [ @@ -278,16 +303,15 @@ struct ContentView: View { private var equalizerCard: some View { VStack(alignment: .leading, spacing: 14) { - Text("Equalizer") - .font(.system(size: 15, weight: .semibold)) - .foregroundColor(.white) + cardTitle("Equalizer") + EQPreview(bands: model.eqBands, range: model.tenBandEqualizer ? 0...12 : -10...10) LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())], spacing: 10) { ForEach(model.tenBandEqualizer ? tenBandEqPresets : eqPresets, id: \.1) { preset in eqChip(preset.0, preset.1) } } if model.eqPreset == 0xA0 { - Divider().background(Theme.cardHi) + Divider().background(palette.cardStroke) let labels = model.tenBandEqualizer ? tenBandEqLabels : eqBandLabels ForEach(0.. 0 ? "+" : "")\(display)") .font(.system(size: 11, weight: .semibold, design: .monospaced)) - .foregroundColor(.white) + .foregroundColor(palette.primary) .frame(width: 26, alignment: .trailing) } } @@ -327,27 +348,24 @@ struct ContentView: View { private var dseeCard: some View { Toggle(isOn: Binding(get: { model.dsee }, set: { model.setDsee($0) })) { VStack(alignment: .leading, spacing: 2) { - Text("DSEE").font(.system(size: 14, weight: .semibold)).foregroundColor(.white) - Text("Upscale compressed audio").font(.system(size: 11)).foregroundColor(Theme.secondary) + Text("DSEE").font(.system(size: 14, weight: .semibold)).foregroundColor(palette.primary) + Text("Upscale compressed audio").font(.system(size: 11)).foregroundColor(palette.secondary) } } - .toggleStyle(SwitchToggleStyle(tint: Theme.accent)) - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Theme.card) - .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) + .toggleStyle(SwitchToggleStyle(tint: palette.accent)) + .themedCard() } private func eqChip(_ name: String, _ code: Int) -> some View { let selected = model.eqPreset == code return Button(action: { model.setEqualizer(code) }) { - Text(name) - .font(.system(size: 12, weight: .medium)) - .foregroundColor(selected ? .white : Theme.secondary) - .frame(maxWidth: .infinity) - .padding(.vertical, 8) - .background(selected ? Theme.accent : Theme.cardHi) - .clipShape(RoundedRectangle(cornerRadius: 9, style: .continuous)) + selectable( + Text(name) + .font(.system(size: 12, weight: .medium)) + .frame(maxWidth: .infinity) + .padding(.vertical, 8), + selected: selected, idleFill: palette.track + ) } .buttonStyle(PlainButtonStyle()) } @@ -356,9 +374,7 @@ struct ContentView: View { private var settingsCard: some View { VStack(alignment: .leading, spacing: 14) { - Text("Settings") - .font(.system(size: 15, weight: .semibold)) - .foregroundColor(.white) + cardTitle("Settings") if model.hasAdaptiveVolume { settingToggle("Adaptive Volume", "Auto-adjust volume by surroundings", on: model.adaptiveVolume) { model.setAdaptiveVolume($0) } @@ -369,9 +385,9 @@ struct ContentView: View { Toggle(isOn: $model.keepSpeakToChatOff) { Text("Keep off on connect") .font(.system(size: 11)) - .foregroundColor(Theme.secondary) + .foregroundColor(palette.secondary) } - .toggleStyle(SwitchToggleStyle(tint: Theme.accent)) + .toggleStyle(SwitchToggleStyle(tint: palette.accent)) .controlSize(.small) .padding(.leading, 12) } @@ -382,8 +398,8 @@ struct ContentView: View { if model.hasAutoPowerOff { HStack { VStack(alignment: .leading, spacing: 2) { - Text("Auto Power-Off").font(.system(size: 14, weight: .semibold)).foregroundColor(.white) - Text("Turn off when idle").font(.system(size: 11)).foregroundColor(Theme.secondary) + Text("Auto Power-Off").font(.system(size: 14, weight: .semibold)).foregroundColor(palette.primary) + Text("Turn off when idle").font(.system(size: 11)).foregroundColor(palette.secondary) } Spacer() Picker("", selection: Binding( @@ -394,33 +410,28 @@ struct ContentView: View { } .pickerStyle(MenuPickerStyle()) .frame(width: 130) - .accentColor(Theme.accent) + .accentColor(palette.accent) } } } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Theme.card) - .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) + .themedCard() } private func settingToggle(_ title: String, _ subtitle: String, on: Bool, action: @escaping (Bool) -> Void) -> some View { Toggle(isOn: Binding(get: { on }, set: { action($0) })) { VStack(alignment: .leading, spacing: 2) { - Text(title).font(.system(size: 14, weight: .semibold)).foregroundColor(.white) - Text(subtitle).font(.system(size: 11)).foregroundColor(Theme.secondary) + Text(title).font(.system(size: 14, weight: .semibold)).foregroundColor(palette.primary) + Text(subtitle).font(.system(size: 11)).foregroundColor(palette.secondary) } } - .toggleStyle(SwitchToggleStyle(tint: Theme.accent)) + .toggleStyle(SwitchToggleStyle(tint: palette.accent)) } // Multipoint device list. Read-only for now: nothing here sends a command that changes the headset. private var devicesCard: some View { VStack(alignment: .leading, spacing: 14) { HStack { - Text("Devices") - .font(.system(size: 15, weight: .semibold)) - .foregroundColor(.white) + cardTitle("Devices") Spacer() if model.multipointLoading || model.refreshingMultipoint || model.multipointBusy { ProgressView() @@ -430,7 +441,7 @@ struct ContentView: View { Button(action: model.refreshMultipoint) { Image(systemName: "arrow.clockwise") .font(.system(size: 12, weight: .semibold)) - .foregroundColor(Theme.secondary) + .foregroundColor(palette.secondary) } .buttonStyle(PlainButtonStyle()) } @@ -442,7 +453,7 @@ struct ContentView: View { .frame(width: 18, height: 18) Text("Reading devices from the headset…") .font(.system(size: 12)) - .foregroundColor(Theme.secondary) + .foregroundColor(palette.secondary) } .frame(maxWidth: .infinity, alignment: .leading) .padding(.vertical, 6) @@ -450,19 +461,19 @@ struct ContentView: View { if model.hasPlaybackPinState { HStack { VStack(alignment: .leading, spacing: 2) { - Text("Playback device").font(.system(size: 13, weight: .medium)).foregroundColor(.white) + Text("Playback device").font(.system(size: 13, weight: .medium)).foregroundColor(palette.primary) Text(model.playbackPinned ? "Fixed" : "Switches automatically") - .font(.system(size: 11)).foregroundColor(Theme.secondary) + .font(.system(size: 11)).foregroundColor(palette.secondary) } Spacer() Button(action: { model.setPlaybackPinned(!model.playbackPinned) }) { Text(model.playbackPinned ? "Unfix" : "Fix") .font(.system(size: 12, weight: .semibold)) - .foregroundColor(.white) + .foregroundColor(palette.primary) .padding(.horizontal, 12) .padding(.vertical, 5) - .background(Theme.cardHi) - .clipShape(Capsule()) + .background(palette.raised, in: Capsule()) + .overlay(Capsule().strokeBorder(palette.cardStroke, lineWidth: 1)) } .buttonStyle(PlainButtonStyle()) .disabled(model.multipointBusy) @@ -472,50 +483,48 @@ struct ContentView: View { let connected = model.pairedDevices.filter { $0.connected }.sorted { $0.slot < $1.slot } let paired = model.pairedDevices.filter { !$0.connected } if !connected.isEmpty { - devicesSectionLabel("Connected") + sectionLabel("Connected") ForEach(connected) { deviceRow($0) } } if !paired.isEmpty { - devicesSectionLabel("Paired") + sectionLabel("Paired") ForEach(paired) { deviceRow($0) } } } else if !model.multipointLoading { Text("This headset didn't return a device list.") .font(.system(size: 12)) - .foregroundColor(Theme.secondary) + .foregroundColor(palette.secondary) } if !model.multipointLoading { devicesFooter } } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Theme.card) - .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) + .themedCard() } private var devicesFooter: some View { VStack(alignment: .leading, spacing: 14) { - Divider().background(Theme.cardHi) + Divider().background(palette.cardStroke) HStack { Text(model.multipointBusy ? "Sending…" : "Switching and fixing are experimental") .font(.system(size: 11)) - .foregroundColor(Theme.secondary.opacity(0.7)) + .foregroundColor(palette.secondary.opacity(0.7)) Spacer() Button(action: copyMultipointDiagnostics) { Text("Copy diagnostics") .font(.system(size: 11, weight: .medium)) - .foregroundColor(Theme.accent) + .foregroundColor(palette.accentText) } .buttonStyle(PlainButtonStyle()) } } } - private func devicesSectionLabel(_ text: String) -> some View { + private func sectionLabel(_ text: String) -> some View { Text(text.uppercased()) .font(.system(size: 10, weight: .semibold)) - .foregroundColor(Theme.secondary.opacity(0.8)) + .tracking(0.8) + .foregroundColor(palette.secondary.opacity(0.8)) .padding(.top, 2) } @@ -523,15 +532,15 @@ struct ContentView: View { HStack(spacing: 12) { Image(systemName: deviceSymbol(device.classOfDevice)) .font(.system(size: 15)) - .foregroundColor(device.connected ? .white : Theme.secondary) + .foregroundColor(device.connected ? palette.primary : palette.secondary) .frame(width: 22) VStack(alignment: .leading, spacing: 2) { Text(device.name.isEmpty ? device.address : device.name) .font(.system(size: 13, weight: .medium)) - .foregroundColor(device.connected ? .white : Theme.secondary) + .foregroundColor(device.connected ? palette.primary : palette.secondary) .lineLimit(1) if device.isThisMac { - Text("This Mac").font(.system(size: 11)).foregroundColor(Theme.accent) + Text("This Mac").font(.system(size: 11)).foregroundColor(palette.accentText) } } Spacer() @@ -539,11 +548,11 @@ struct ContentView: View { if model.playbackPinned { Image(systemName: "lock.fill") .font(.system(size: 11)) - .foregroundColor(Theme.accent) + .foregroundColor(palette.accent) } Image(systemName: "speaker.wave.2.fill") .font(.system(size: 12)) - .foregroundColor(Theme.accent) + .foregroundColor(palette.accent) } if device.connected && model.hasPlaybackPinState { Menu { @@ -582,7 +591,7 @@ struct ContentView: View { VStack(alignment: .leading, spacing: 0) { Text(model.deviceName) .font(.system(size: 15, weight: .bold)) - .foregroundColor(.white) + .foregroundColor(palette.primary) .padding(.bottom, 10) aboutRow("Status", model.connected ? "Connected" : "Disconnected") if model.hasDualBattery { @@ -598,14 +607,41 @@ struct ContentView: View { if !model.firmware.isEmpty { aboutRow("Firmware", model.firmware) } if !model.protocolVersion.isEmpty { aboutRow("Protocol", model.protocolVersion) } if !model.deviceMac.isEmpty { aboutRow("Bluetooth", model.deviceMac) } - Divider().background(Theme.cardHi).padding(.vertical, 10) + sectionLabel("Appearance") + .padding(.top, 12) + .padding(.bottom, 8) + HStack(spacing: 6) { + ForEach(AppTheme.allCases) { option in + themeOption(option) + } + } + Divider().background(palette.cardStroke).padding(.vertical, 10) Text("SonyBridge · not affiliated with Sony") .font(.system(size: 10)) - .foregroundColor(Theme.secondary.opacity(0.7)) + .foregroundColor(palette.secondary.opacity(0.7)) } .padding(18) - .frame(width: 260) - .background(Theme.card) + .frame(width: 290) + .background(palette.card) + } + + private func themeOption(_ option: AppTheme) -> some View { + let selected = option == theme + return Button(action: { theme = option }) { + VStack(spacing: 5) { + ThemeSwatch(theme: option) + Text(option.displayName) + .font(.system(size: 10.5, weight: .medium)) + .foregroundColor(selected ? palette.primary : palette.secondary) + .lineLimit(1) + .minimumScaleFactor(0.8) + } + .padding(5) + .overlay(RoundedRectangle(cornerRadius: 10, style: .continuous) + .strokeBorder(selected ? palette.accent : .clear, lineWidth: 2)) + .contentShape(Rectangle()) + } + .buttonStyle(PlainButtonStyle()) } private func batteryText(_ level: Int, _ charging: Bool) -> String { @@ -615,9 +651,9 @@ struct ContentView: View { private func aboutRow(_ label: String, _ value: String) -> some View { HStack { - Text(label).font(.system(size: 12)).foregroundColor(Theme.secondary) + Text(label).font(.system(size: 12)).foregroundColor(palette.secondary) Spacer() - Text(value).font(.system(size: 12, weight: .medium)).foregroundColor(.white) + Text(value).font(.system(size: 12, weight: .medium)).foregroundColor(palette.primary) } .padding(.vertical, 3) } @@ -628,18 +664,16 @@ struct ContentView: View { return NSImage(named: slug) } - // One "L 82%" chip, with a bolt in place of the battery glyph while that unit is charging. - // A docked/powered-down earbud reports no level; show it dimmed as "R --" rather than dropping the - // chip, so it reads as "in the case" instead of looking like the app lost track of it. + // One "L 82%" reading in the battery chip, with a bolt in place of the battery glyph while that unit + // is charging. A docked/powered-down earbud reports no level; show it dimmed as "R --" rather than + // dropping it, so it reads as "in the case" instead of looking like the app lost track of it. private func budBattery(_ label: String, _ level: Int, charging: Bool) -> some View { HStack(spacing: 3) { Image(systemName: level < 0 ? "battery.0" : (charging ? "bolt.fill" : batterySymbol(level))) - .font(.system(size: 12)) - .foregroundColor(level < 0 ? Theme.secondary.opacity(0.5) - : (level <= 20 && !charging ? .red.opacity(0.9) : Theme.accent)) - Text(level < 0 ? "\(label) --" : "\(label) \(level)%") - .font(.system(size: 13, weight: .semibold)) - .foregroundColor(Theme.secondary.opacity(level < 0 ? 0.5 : 1.0)) + .foregroundColor(level < 0 ? palette.secondary.opacity(0.5) + : (level <= 20 && !charging ? palette.danger : palette.accent)) + chipText(level < 0 ? "\(label) --" : "\(label) \(level)%") + .foregroundColor(palette.secondary.opacity(level < 0 ? 0.5 : 1.0)) } } @@ -820,7 +854,6 @@ struct ContentView: View { } // Factory so the Obj-C++ ViewController can instantiate the SwiftUI hierarchy. -@available(macOS 11.0, *) @objc final class HeadphonesUIFactory: NSObject { @objc static func makeViewController() -> NSViewController { return NSHostingController(rootView: ContentView()) diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj index 7079b2ce..678b0a5b 100644 --- a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj +++ b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj @@ -23,6 +23,7 @@ CC0000000000000000000001 /* HeadphonesBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC0000000000000000000002 /* HeadphonesBridge.mm */; }; CC0000000000000000000004 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0000000000000000000005 /* ContentView.swift */; }; CC0000000000000000000006 /* HeadphonesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0000000000000000000007 /* HeadphonesModel.swift */; }; + CC00000000000000000000A1 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC00000000000000000000A2 /* Theme.swift */; }; DD0000000000000000000001 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD0000000000000000000002 /* Assets.xcassets */; }; /* End PBXBuildFile section */ @@ -58,6 +59,7 @@ CC0000000000000000000003 /* HeadphonesBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HeadphonesBridge.h; sourceTree = ""; }; CC0000000000000000000005 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; CC0000000000000000000007 /* HeadphonesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadphonesModel.swift; sourceTree = ""; }; + CC00000000000000000000A2 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; CC0000000000000000000008 /* SonyHeadphonesClient-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SonyHeadphonesClient-Bridging-Header.h"; sourceTree = ""; }; DD0000000000000000000002 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; /* End PBXFileReference section */ @@ -107,6 +109,7 @@ CC0000000000000000000002 /* HeadphonesBridge.mm */, CC0000000000000000000005 /* ContentView.swift */, CC0000000000000000000007 /* HeadphonesModel.swift */, + CC00000000000000000000A2 /* Theme.swift */, CC0000000000000000000008 /* SonyHeadphonesClient-Bridging-Header.h */, DD0000000000000000000002 /* Assets.xcassets */, A8DC790325769A6600447738 /* Frameworks */, @@ -203,6 +206,7 @@ CC0000000000000000000001 /* HeadphonesBridge.mm in Sources */, CC0000000000000000000004 /* ContentView.swift in Sources */, CC0000000000000000000006 /* HeadphonesModel.swift in Sources */, + CC00000000000000000000A1 /* Theme.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -260,7 +264,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -315,7 +319,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -338,7 +342,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 12.0; OTHER_CPLUSPLUSFLAGS = ( "-std=c++17", "-stdlib=libc++", @@ -369,7 +373,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 12.0; OTHER_CPLUSPLUSFLAGS = ( "-std=c++17", "-stdlib=libc++", diff --git a/Client/macos/Theme.swift b/Client/macos/Theme.swift new file mode 100644 index 00000000..78e5c491 --- /dev/null +++ b/Client/macos/Theme.swift @@ -0,0 +1,284 @@ +// +// Theme.swift +// The window's three looks: palettes, the shared card style, and the theme-specific drawings. +// + +import SwiftUI +import AppKit + +enum AppTheme: String, CaseIterable, Identifiable { + case refinedDark, nativeGlass, sonySignature + + var id: String { rawValue } + + var displayName: String { + switch self { + case .refinedDark: return "Refined Dark" + case .nativeGlass: return "Native Glass" + case .sonySignature: return "Sony Signature" + } + } + + // Native Glass follows the system appearance; the other two are designed dark-only. + var colorScheme: ColorScheme? { self == .nativeGlass ? nil : .dark } + + // Sony Signature changes shapes as well as colors: pill buttons, uppercase tracked labels, + // monospaced numbers, EQ as bars and rings behind the product. + var isSignature: Bool { self == .sonySignature } + + func palette(_ scheme: ColorScheme) -> Palette { + switch self { + case .refinedDark: return .refinedDark + case .nativeGlass: return scheme == .dark ? .glassDark : .glassLight + case .sonySignature: return .sonySignature + } + } +} + +struct Palette { + let background: AnyShapeStyle + let card: AnyShapeStyle + let cardStroke: Color + let raised: AnyShapeStyle // status chips and round icon buttons + let track: Color // recessed fill behind mode segments and idle EQ presets + let primary: Color + let secondary: Color + let accent: Color + let accentText: Color + let onAccent: Color + let danger: Color + let selectedFill: Color + let selectedText: Color + let selectedStroke: Color + let selectedShadow: Color + let glow: Color // light behind the product image +} + +extension Palette { + static let refinedDark: Palette = { + let lavender = Color(hex: 0x8f8ff5) + return Palette( + background: AnyShapeStyle(Color(hex: 0x0d0d11)), + card: AnyShapeStyle(LinearGradient(colors: [Color(hex: 0x17171d), Color(hex: 0x131318)], + startPoint: .top, endPoint: .bottom)), + cardStroke: Color(hex: 0x23232b), + raised: AnyShapeStyle(Color(hex: 0x1b1b22)), + track: Color.black.opacity(0.35), + primary: Color(hex: 0xf2f2f6), + secondary: Color(hex: 0x8d8d9a), + accent: lavender, + accentText: lavender, + onAccent: .white, + danger: Color.red.opacity(0.9), + selectedFill: lavender, + selectedText: .white, + selectedStroke: .clear, + selectedShadow: lavender.opacity(0.45), + glow: lavender.opacity(0.32) + ) + }() + + static let glassLight = glass(dark: false) + static let glassDark = glass(dark: true) + + private static func glass(dark: Bool) -> Palette { + // controlAccentColor rather than Color.accentColor, which would resolve through the + // .accentColor(_:) the controls are given from this palette. + let accent = Color(NSColor.controlAccentColor) + return Palette( + background: AnyShapeStyle(LinearGradient( + colors: dark ? [Color(hex: 0x1a1d26), Color(hex: 0x15161b), Color(hex: 0x1c1924)] + : [Color(hex: 0xdfe6f3), Color(hex: 0xeef0f6), Color(hex: 0xe6e2f0)], + startPoint: .topLeading, endPoint: .bottomTrailing)), + // ponytail: materials, not .glassEffect(); switch to .glassEffect() behind `if #available(macOS 26, *)` + // once the project builds with the macOS 26+ SDK in Xcode. + card: AnyShapeStyle(.regularMaterial), + cardStroke: Color.white.opacity(dark ? 0.1 : 0.8), + raised: AnyShapeStyle(.thinMaterial), + track: dark ? Color.black.opacity(0.25) : Color.gray.opacity(0.16), + primary: .primary, + secondary: .secondary, + accent: accent, + accentText: accent, + onAccent: .white, + danger: .red, + selectedFill: dark ? Color.white.opacity(0.2) : .white, + selectedText: dark ? .primary : accent, + selectedStroke: .clear, + selectedShadow: Color.black.opacity(dark ? 0.3 : 0.12), + glow: Color.white.opacity(dark ? 0.12 : 0.95) + ) + } + + static let sonySignature: Palette = { + let amber = Color(hex: 0xffa032) + let amberText = Color(hex: 0xffb456) + return Palette( + background: AnyShapeStyle(Color(hex: 0x050505)), + card: AnyShapeStyle(Color(hex: 0x101010)), + cardStroke: Color(hex: 0x1f1f1f), + raised: AnyShapeStyle(Color.clear), + track: .clear, + primary: .white, + secondary: Color(hex: 0x8a8a8a), + accent: amber, + accentText: amberText, + onAccent: .black, + danger: Color.red.opacity(0.9), + selectedFill: amber.opacity(0.14), + selectedText: amberText, + selectedStroke: amber, + selectedShadow: .clear, + glow: amber.opacity(0.22) + ) + }() +} + +private struct AppThemeKey: EnvironmentKey { + static let defaultValue = AppTheme.refinedDark +} + +extension EnvironmentValues { + var appTheme: AppTheme { + get { self[AppThemeKey.self] } + set { self[AppThemeKey.self] = newValue } + } +} + +private struct ThemedCard: ViewModifier { + @Environment(\.appTheme) private var theme + @Environment(\.colorScheme) private var colorScheme + + func body(content: Content) -> some View { + let palette = theme.palette(colorScheme) + let shape = RoundedRectangle(cornerRadius: 16, style: .continuous) + return content + .padding(18) + .frame(maxWidth: .infinity, alignment: .leading) + .background(palette.card, in: shape) + .overlay(shape.strokeBorder(palette.cardStroke, lineWidth: 1)) + } +} + +extension View { + func themedCard() -> some View { modifier(ThemedCard()) } +} + +// Light behind the product image: a soft glow, or Sony Signature's warm rim and rings. +struct HeroBackdrop: View { + @Environment(\.appTheme) private var theme + @Environment(\.colorScheme) private var colorScheme + + var body: some View { + let palette = theme.palette(colorScheme) + ZStack { + if theme.isSignature { + Circle() + .fill(RadialGradient(colors: [palette.glow.opacity(0), palette.glow], + center: .center, startRadius: 40, endRadius: 105)) + ForEach(0..<3) { ring in + Circle() + .strokeBorder(palette.accent.opacity(0.3 - Double(ring) * 0.1), lineWidth: 1) + .frame(width: 222 + CGFloat(ring) * 36, height: 222 + CGFloat(ring) * 36) + } + } else { + Circle() + .fill(RadialGradient(colors: [palette.glow, palette.glow.opacity(0)], + center: .center, startRadius: 4, endRadius: 104)) + } + } + .frame(width: 210, height: 210) + } +} + +// Small picture of the EQ: a filled curve, or bars in Sony Signature. `range` is the band value range. +struct EQPreview: View { + let bands: [Int] + let range: ClosedRange + + @Environment(\.appTheme) private var theme + @Environment(\.colorScheme) private var colorScheme + + var body: some View { + let accent = theme.palette(colorScheme).accent + let span = range.upperBound - range.lowerBound + let levels = bands.map { min(max((Double($0) - range.lowerBound) / span, 0), 1) } + Group { + if theme.isSignature { + HStack(alignment: .bottom, spacing: 6) { + ForEach(levels.indices, id: \.self) { i in + RoundedRectangle(cornerRadius: 4, style: .continuous) + .fill(accent.opacity(0.5 + 0.4 * levels[i])) + .frame(maxWidth: 34) + .frame(height: 6 + 48 * levels[i]) + .frame(maxWidth: .infinity) + } + } + } else { + ZStack { + EQCurve(levels: levels, closed: true).fill(accent.opacity(0.15)) + EQCurve(levels: levels, closed: false) + .stroke(accent, style: StrokeStyle(lineWidth: 2.5, lineCap: .round, lineJoin: .round)) + } + } + } + .frame(height: 54, alignment: .bottom) + } +} + +// Levels are 0...1, spread evenly left to right. Horizontal tangents at each band keep the curve +// from overshooting between them. +private struct EQCurve: Shape { + let levels: [Double] + let closed: Bool + + func path(in rect: CGRect) -> Path { + var path = Path() + let levels = self.levels.count == 1 ? self.levels + self.levels : self.levels + guard levels.count > 1 else { return path } + let inset: CGFloat = 3 + let step = rect.width / CGFloat(levels.count - 1) + let points = levels.enumerated().map { i, level in + CGPoint(x: rect.minX + CGFloat(i) * step, + y: rect.maxY - inset - CGFloat(level) * (rect.height - 2 * inset)) + } + path.move(to: points[0]) + for (from, to) in zip(points, points.dropFirst()) { + let midX = (from.x + to.x) / 2 + path.addCurve(to: to, control1: CGPoint(x: midX, y: from.y), control2: CGPoint(x: midX, y: to.y)) + } + if closed { + path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) + path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY)) + path.closeSubpath() + } + return path + } +} + +// Mini preview for the theme picker. Native Glass is shown in its light look. +struct ThemeSwatch: View { + let theme: AppTheme + + var body: some View { + let palette = theme.palette(.light) + let bar = RoundedRectangle(cornerRadius: 3, style: .continuous) + VStack(alignment: .leading, spacing: 6) { + bar.fill(palette.cardStroke).frame(height: 8) + bar.fill(palette.accent).frame(width: 24, height: 8) + bar.fill(palette.cardStroke).frame(height: 8) + } + .padding(8) + .frame(height: 56) + .background(palette.background, in: RoundedRectangle(cornerRadius: 7, style: .continuous)) + } +} + +private extension Color { + init(hex: UInt32) { + self.init(.sRGB, + red: Double((hex >> 16) & 0xFF) / 255, + green: Double((hex >> 8) & 0xFF) / 255, + blue: Double(hex & 0xFF) / 255) + } +} From e2e8a23c84cf9bd9559f9b41dc14c3e908c3ba59 Mon Sep 17 00:00:00 2001 From: Amit Rajput Date: Wed, 28 Oct 2026 19:10:26 +0530 Subject: [PATCH 32/35] fix(macos): theme layout polish from real renders - Sony Signature rings stay inside the hero instead of running into the button row and the device name - mode labels get room inside their segments, so "Noise Canceling" no longer runs edge to edge - every switch sits on the trailing edge of its card - Sony Signature pills are real capsules: a continuous rounded rectangle with a radius near half its height flattens its ends Co-Authored-By: Claude Opus 5.5 --- Client/macos/ContentView.swift | 46 +++++++++++++++++++++++++--------- Client/macos/Theme.swift | 5 ++-- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/Client/macos/ContentView.swift b/Client/macos/ContentView.swift index d90c992b..775ffa30 100644 --- a/Client/macos/ContentView.swift +++ b/Client/macos/ContentView.swift @@ -209,10 +209,22 @@ struct ContentView: View { } // Selected/idle look shared by the mode control and the EQ presets: pills in Sony Signature, - // rounded segments otherwise. The content shape keeps clear (idle) segments clickable. + // rounded segments otherwise. Pills must be a real Capsule: a continuous RoundedRectangle with a + // radius near half the height has no room for its corner curves and renders flat-sided ends. + @ViewBuilder private func selectable(_ label: Label, selected: Bool, idleFill: Color) -> some View { - let shape = RoundedRectangle(cornerRadius: theme.isSignature ? 15 : 8, style: .continuous) - return label + if theme.isSignature { + selectionChrome(label, in: Capsule(), selected: selected, idleFill: idleFill) + } else { + selectionChrome(label, in: RoundedRectangle(cornerRadius: 8, style: .continuous), + selected: selected, idleFill: idleFill) + } + } + + // The content shape keeps clear (idle) segments clickable. + private func selectionChrome(_ label: Label, in shape: S, + selected: Bool, idleFill: Color) -> some View { + label .foregroundColor(selected ? palette.selectedText : palette.secondary) .background(selected ? palette.selectedFill : idleFill, in: shape) .overlay(shape.strokeBorder(selected ? palette.selectedStroke @@ -241,9 +253,10 @@ struct ContentView: View { return Button(action: { model.setMode(mode) }) { selectable( Text(modeName(mode)) - .font(.system(size: 12, weight: .semibold)) + .font(.system(size: 11.5, weight: .semibold)) .lineLimit(1) .minimumScaleFactor(0.8) + .padding(.horizontal, 8) .frame(maxWidth: .infinity) .padding(.vertical, 8), selected: selected, idleFill: .clear @@ -275,7 +288,7 @@ struct ContentView: View { .accentColor(palette.accent) if model.focusOnVoiceAvailable { - Toggle(isOn: Binding( + switchRow("Focus on Voice", isOn: Binding( get: { model.focusOnVoice }, set: { model.setFocusOnVoice($0) } )) { @@ -283,7 +296,6 @@ struct ContentView: View { .font(.system(size: 13, weight: .medium)) .foregroundColor(palette.primary) } - .toggleStyle(SwitchToggleStyle(tint: palette.accent)) } } .themedCard() @@ -346,13 +358,12 @@ struct ContentView: View { } private var dseeCard: some View { - Toggle(isOn: Binding(get: { model.dsee }, set: { model.setDsee($0) })) { + switchRow("DSEE", isOn: Binding(get: { model.dsee }, set: { model.setDsee($0) })) { VStack(alignment: .leading, spacing: 2) { Text("DSEE").font(.system(size: 14, weight: .semibold)).foregroundColor(palette.primary) Text("Upscale compressed audio").font(.system(size: 11)).foregroundColor(palette.secondary) } } - .toggleStyle(SwitchToggleStyle(tint: palette.accent)) .themedCard() } @@ -382,12 +393,11 @@ struct ContentView: View { if model.hasSpeakToChat { settingToggle("Speak-to-Chat", "Pause music when you talk", on: model.speakToChat) { model.setSpeakToChat($0) } - Toggle(isOn: $model.keepSpeakToChatOff) { + switchRow("Keep off on connect", isOn: $model.keepSpeakToChatOff) { Text("Keep off on connect") .font(.system(size: 11)) .foregroundColor(palette.secondary) } - .toggleStyle(SwitchToggleStyle(tint: palette.accent)) .controlSize(.small) .padding(.leading, 12) } @@ -418,13 +428,25 @@ struct ContentView: View { } private func settingToggle(_ title: String, _ subtitle: String, on: Bool, action: @escaping (Bool) -> Void) -> some View { - Toggle(isOn: Binding(get: { on }, set: { action($0) })) { + switchRow(title, isOn: Binding(get: { on }, set: { action($0) })) { VStack(alignment: .leading, spacing: 2) { Text(title).font(.system(size: 14, weight: .semibold)).foregroundColor(palette.primary) Text(subtitle).font(.system(size: 11)).foregroundColor(palette.secondary) } } - .toggleStyle(SwitchToggleStyle(tint: palette.accent)) + } + + // Label on the left, switch on the trailing edge, so every switch in the window lines up. + // The title stays on the hidden Toggle label for VoiceOver. + private func switchRow(_ title: String, isOn: Binding, + @ViewBuilder label: () -> Label) -> some View { + HStack { + label() + Spacer() + Toggle(title, isOn: isOn) + .labelsHidden() + .toggleStyle(SwitchToggleStyle(tint: palette.accent)) + } } // Multipoint device list. Read-only for now: nothing here sends a command that changes the headset. diff --git a/Client/macos/Theme.swift b/Client/macos/Theme.swift index 78e5c491..fee9b435 100644 --- a/Client/macos/Theme.swift +++ b/Client/macos/Theme.swift @@ -176,10 +176,11 @@ struct HeroBackdrop: View { Circle() .fill(RadialGradient(colors: [palette.glow.opacity(0), palette.glow], center: .center, startRadius: 40, endRadius: 105)) + // Outermost ring is the frame itself, so none reach the button row or the device name. ForEach(0..<3) { ring in Circle() - .strokeBorder(palette.accent.opacity(0.3 - Double(ring) * 0.1), lineWidth: 1) - .frame(width: 222 + CGFloat(ring) * 36, height: 222 + CGFloat(ring) * 36) + .strokeBorder(palette.accent.opacity(0.3 - Double(ring) * 0.08), lineWidth: 1) + .frame(width: 210 - CGFloat(ring) * 24, height: 210 - CGFloat(ring) * 24) } } else { Circle() From 4c722238e50c7c4ac65263a1d9f0f0c9e76c6d91 Mon Sep 17 00:00:00 2001 From: Amit Rajput Date: Wed, 28 Oct 2026 19:37:16 +0530 Subject: [PATCH 33/35] feat(macos): menu-bar quick controls and a taller, resizable window Menu bar: a click on the status item now opens a panel with the everyday controls - mode, ambient level, Focus on Voice, EQ preset, battery and codec, playback pin/unfix, Open and Quit - so the window isn't needed for a quick switch. Right-click (or control-click) still shows the menu. MenuBarController moves out of ContentView.swift into its own file, and the pin helpers (this Mac / pinned / playback device) move onto the model so the menu and the panel share them. Window: opens at 400x820 (fitted to the screen) instead of 380x560, remembers the size it's left at, and can be widened to 1200pt; past 720pt the connected view splits into two independently scrolling columns (hero and controls left; devices, EQ, DSEE and settings right). The window no longer forces a dark appearance of its own, which had kept Native Glass from ever showing its light look; the theme is applied app-wide at launch so the panel matches even before the window appears. The window and the panel share the mode control, chips, switches, product image and Connect button instead of duplicating them. Co-Authored-By: Claude Opus 5.5 --- Client/macos/ContentView.swift | 626 ++++++++---------- Client/macos/HeadphonesModel.swift | 19 + Client/macos/MenuBarController.swift | 190 ++++++ Client/macos/QuickControlsView.swift | 181 +++++ .../project.pbxproj | 8 + Client/macos/Theme.swift | 114 +++- Client/macos/ViewController.mm | 14 +- 7 files changed, 776 insertions(+), 376 deletions(-) create mode 100644 Client/macos/MenuBarController.swift create mode 100644 Client/macos/QuickControlsView.swift diff --git a/Client/macos/ContentView.swift b/Client/macos/ContentView.swift index 775ffa30..22773ca5 100644 --- a/Client/macos/ContentView.swift +++ b/Client/macos/ContentView.swift @@ -5,12 +5,11 @@ import SwiftUI import AppKit -import Combine struct ContentView: View { @StateObject private var model = HeadphonesModel.shared @State private var showAbout = false - @AppStorage("appTheme") private var theme = AppTheme.refinedDark + @AppStorage(AppTheme.storageKey) private var theme = AppTheme.refinedDark @Environment(\.colorScheme) private var colorScheme private var palette: Palette { theme.palette(colorScheme) } @@ -26,14 +25,8 @@ struct ContentView: View { .frame(minWidth: 360, minHeight: 500) .background(palette.background) .environment(\.appTheme, theme) - .onAppear { applyAppearance(theme) } - .onChange(of: theme, perform: applyAppearance) - } - - // Not .preferredColorScheme: on macOS, once it has forced a window dark, setting it back to nil - // doesn't return the window to the system appearance, so Native Glass would stay dark until relaunch. - private func applyAppearance(_ theme: AppTheme) { - NSApp.appearance = theme.colorScheme == .dark ? NSAppearance(named: .darkAqua) : nil + .onAppear { theme.applyToApp() } + .onChange(of: theme) { $0.applyToApp() } } // MARK: - Disconnected @@ -54,51 +47,70 @@ struct ContentView: View { .multilineTextAlignment(.center) .padding(.horizontal, 32) } - Button(action: model.connect) { - Text(model.connecting ? "Connecting…" : "Connect headphones") - .font(.system(size: 14, weight: .semibold)) - .foregroundColor(palette.onAccent) - .frame(maxWidth: .infinity) - .padding(.vertical, 12) - .background(palette.accent) - .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) - } - .buttonStyle(PlainButtonStyle()) - .disabled(model.connecting) - .padding(.horizontal, 40) + ConnectButton(model: model) + .padding(.horizontal, 40) Spacer() } } // MARK: - Connected + // Two independently scrolling columns once the window is wide enough, otherwise one. The pair is capped + // and centered so cards don't stretch on a very wide window. private var connectedView: some View { - ScrollView(showsIndicators: false) { - VStack(spacing: 16) { - deviceHero - ambientCard - if model.mode == .ambientSound { - ambientLevelCard - } - if model.multipointLoading || model.hasPairedDevices || model.hasPlaybackPinState { - devicesCard - } - if model.supportsEqualizer { - equalizerCard + GeometryReader { proxy in + if proxy.size.width >= 720 { + HStack(alignment: .top, spacing: 0) { + column { primaryCards } + .frame(width: 380) + column(padding: [.vertical, .trailing]) { secondaryCards } + .frame(maxWidth: 580) } - if model.supportsDsee { - dseeCard - } - if model.hasAdaptiveVolume || model.hasSpeakToChat || model.hasAutoPowerOff || model.hasMultipointSetting { - settingsCard - } - if let error = model.errorMessage { - Text(error) - .font(.system(size: 12)) - .foregroundColor(palette.danger) + .frame(maxWidth: .infinity) + } else { + column { + primaryCards + secondaryCards } } - .padding(20) + } + } + + private func column(padding edges: Edge.Set = .all, + @ViewBuilder _ content: () -> Content) -> some View { + ScrollView(showsIndicators: false) { + VStack(spacing: 16, content: content) + .padding(edges, 20) + } + } + + @ViewBuilder + private var primaryCards: some View { + deviceHero + ambientCard + if model.mode == .ambientSound { + ambientLevelCard + } + } + + @ViewBuilder + private var secondaryCards: some View { + if model.multipointLoading || model.hasPairedDevices || model.hasPlaybackPinState { + devicesCard + } + if model.supportsEqualizer { + equalizerCard + } + if model.supportsDsee { + dseeCard + } + if model.hasAdaptiveVolume || model.hasSpeakToChat || model.hasAutoPowerOff || model.hasMultipointSetting { + settingsCard + } + if let error = model.errorMessage { + Text(error) + .font(.system(size: 12)) + .foregroundColor(palette.danger) } } @@ -121,50 +133,14 @@ struct ContentView: View { // copyrighted and can't be bundled) over the theme's backdrop, mirroring Sony's app layout. ZStack { HeroBackdrop() - - if let image = deviceImage() { - // Background-removed product cutout floating on the backdrop. - Image(nsImage: image) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 190, height: 190) - } else { - Image(systemName: "headphones") - .font(.system(size: 92, weight: .thin)) - .foregroundColor(palette.primary) - } + ProductImage(deviceName: model.deviceName, size: 190) } Text(model.deviceName) .font(.system(size: 24, weight: .bold)) .foregroundColor(palette.primary) - HStack(spacing: 6) { - chip { - if model.hasDualBattery { - // Earbuds report a battery each, plus the case when it's connected. An earbud that - // isn't reporting (docked / powered down) comes through as -1 and is left out. - budBattery("L", model.batteryLeft, charging: model.batteryLeftCharging) - Text("·") - budBattery("R", model.batteryRight, charging: model.batteryRightCharging) - if model.batteryCase >= 0 { - Text("·") - budBattery("Case", model.batteryCase, charging: model.batteryCaseCharging) - } - } else if model.batteryLevel >= 0 { - Image(systemName: model.batteryCharging ? "bolt.fill" : batterySymbol(model.batteryLevel)) - .foregroundColor(model.batteryLevel <= 20 ? palette.danger : palette.accent) - chipText("\(model.batteryLevel)%") - } else { - Circle().fill(palette.accent).frame(width: 6, height: 6) - chipText("Connected") - } - } - if !model.codec.isEmpty { - chip { chipText(model.codec) } - } - chip { chipText(modeName(model.mode)) } - } + StatusChips(model: model) } .padding(.bottom, 4) } @@ -178,21 +154,6 @@ struct ContentView: View { .overlay(Circle().strokeBorder(palette.cardStroke, lineWidth: 1)) } - private func chip(@ViewBuilder _ content: () -> Content) -> some View { - HStack(spacing: 4, content: content) - .font(.system(size: theme.isSignature ? 10 : 11, weight: .semibold)) - .foregroundColor(palette.secondary) - .lineLimit(1) - .padding(.horizontal, 9) - .padding(.vertical, 4) - .background(palette.raised, in: Capsule()) - .overlay(Capsule().strokeBorder(palette.cardStroke, lineWidth: 1)) - } - - private func chipText(_ text: String) -> Text { - Text(theme.isSignature ? text.uppercased() : text).tracking(theme.isSignature ? 0.8 : 0) - } - private func cardTitle(_ title: String) -> some View { Text(theme.isSignature ? title.uppercased() : title) .font(.system(size: theme.isSignature ? 11 : 15, weight: .semibold)) @@ -200,72 +161,14 @@ struct ContentView: View { .foregroundColor(theme.isSignature ? palette.secondary : palette.primary) } - private func modeName(_ mode: SHCAmbientMode) -> String { - switch mode { - case .noiseCanceling: return "Noise Canceling" - case .ambientSound: return "Ambient" - default: return "Off" - } - } - - // Selected/idle look shared by the mode control and the EQ presets: pills in Sony Signature, - // rounded segments otherwise. Pills must be a real Capsule: a continuous RoundedRectangle with a - // radius near half the height has no room for its corner curves and renders flat-sided ends. - @ViewBuilder - private func selectable(_ label: Label, selected: Bool, idleFill: Color) -> some View { - if theme.isSignature { - selectionChrome(label, in: Capsule(), selected: selected, idleFill: idleFill) - } else { - selectionChrome(label, in: RoundedRectangle(cornerRadius: 8, style: .continuous), - selected: selected, idleFill: idleFill) - } - } - - // The content shape keeps clear (idle) segments clickable. - private func selectionChrome(_ label: Label, in shape: S, - selected: Bool, idleFill: Color) -> some View { - label - .foregroundColor(selected ? palette.selectedText : palette.secondary) - .background(selected ? palette.selectedFill : idleFill, in: shape) - .overlay(shape.strokeBorder(selected ? palette.selectedStroke - : (theme.isSignature ? palette.cardStroke : .clear), lineWidth: 1)) - .contentShape(shape) - } - private var ambientCard: some View { - let track = RoundedRectangle(cornerRadius: 11, style: .continuous) - return VStack(alignment: .leading, spacing: 16) { + VStack(alignment: .leading, spacing: 16) { cardTitle("Ambient Sound Control") - HStack(spacing: theme.isSignature ? 6 : 0) { - modeButton(.noiseCanceling) - modeButton(.ambientSound) - modeButton(.off) - } - .padding(theme.isSignature ? 0 : 3) - .background(palette.track, in: track) - .overlay(track.strokeBorder(theme.isSignature ? .clear : palette.cardStroke, lineWidth: 1)) + AmbientModeControl(model: model) } .themedCard() } - private func modeButton(_ mode: SHCAmbientMode) -> some View { - let selected = model.mode == mode - return Button(action: { model.setMode(mode) }) { - selectable( - Text(modeName(mode)) - .font(.system(size: 11.5, weight: .semibold)) - .lineLimit(1) - .minimumScaleFactor(0.8) - .padding(.horizontal, 8) - .frame(maxWidth: .infinity) - .padding(.vertical, 8), - selected: selected, idleFill: .clear - ) - .shadow(color: selected ? palette.selectedShadow : .clear, radius: 8) - } - .buttonStyle(.plain) - } - private var ambientLevelCard: some View { VStack(alignment: .leading, spacing: 14) { HStack { @@ -277,40 +180,16 @@ struct ContentView: View { .font(.system(size: 20, weight: .bold, design: theme.isSignature ? .monospaced : .rounded)) .foregroundColor(palette.accentText) } - Slider( - value: Binding( - get: { Double(model.ambientLevel) }, - set: { model.setLevel(Int($0.rounded())) } - ), - in: 1...Double(model.maxAmbientLevel), - step: 1 - ) - .accentColor(palette.accent) + AmbientLevelSlider(model: model) if model.focusOnVoiceAvailable { - switchRow("Focus on Voice", isOn: Binding( - get: { model.focusOnVoice }, - set: { model.setFocusOnVoice($0) } - )) { - Text("Focus on Voice") - .font(.system(size: 13, weight: .medium)) - .foregroundColor(palette.primary) - } + FocusOnVoiceSwitch(model: model) } } .themedCard() } - private let eqPresets: [(String, Int)] = [ - ("Off", 0x00), ("Bright", 0x10), ("Excited", 0x11), - ("Mellow", 0x12), ("Relaxed", 0x13), ("Vocal", 0x14), - ("Treble", 0x15), ("Bass", 0x16), ("Speech", 0x17), - ("Manual", 0xA0) - ] private let eqBandLabels = ["400", "1k", "2.5k", "6.3k", "16k"] - // WH-1000XM6: only Off and Custom have confirmed preset codes on the ten-band layout; its other preset - // bytes (0x20, 0x30-0x33, 0xa1-0xa2) are unnamed, and the 5-band codes above don't apply to it. - private let tenBandEqPresets: [(String, Int)] = [("Off", 0x00), ("Custom", 0xA0)] private let tenBandEqLabels = ["31", "63", "125", "250", "500", "1k", "2k", "4k", "8k", "16k"] private var equalizerCard: some View { @@ -318,7 +197,7 @@ struct ContentView: View { cardTitle("Equalizer") EQPreview(bands: model.eqBands, range: model.tenBandEqualizer ? 0...12 : -10...10) LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())], spacing: 10) { - ForEach(model.tenBandEqualizer ? tenBandEqPresets : eqPresets, id: \.1) { preset in + ForEach(EQPresets.list(tenBand: model.tenBandEqualizer), id: \.1) { preset in eqChip(preset.0, preset.1) } } @@ -358,7 +237,7 @@ struct ContentView: View { } private var dseeCard: some View { - switchRow("DSEE", isOn: Binding(get: { model.dsee }, set: { model.setDsee($0) })) { + SwitchRow("DSEE", isOn: Binding(get: { model.dsee }, set: { model.setDsee($0) })) { VStack(alignment: .leading, spacing: 2) { Text("DSEE").font(.system(size: 14, weight: .semibold)).foregroundColor(palette.primary) Text("Upscale compressed audio").font(.system(size: 11)).foregroundColor(palette.secondary) @@ -370,13 +249,11 @@ struct ContentView: View { private func eqChip(_ name: String, _ code: Int) -> some View { let selected = model.eqPreset == code return Button(action: { model.setEqualizer(code) }) { - selectable( - Text(name) - .font(.system(size: 12, weight: .medium)) - .frame(maxWidth: .infinity) - .padding(.vertical, 8), - selected: selected, idleFill: palette.track - ) + Text(name) + .font(.system(size: 12, weight: .medium)) + .frame(maxWidth: .infinity) + .padding(.vertical, 8) + .selectable(selected, filledWhenIdle: true) } .buttonStyle(PlainButtonStyle()) } @@ -393,7 +270,7 @@ struct ContentView: View { if model.hasSpeakToChat { settingToggle("Speak-to-Chat", "Pause music when you talk", on: model.speakToChat) { model.setSpeakToChat($0) } - switchRow("Keep off on connect", isOn: $model.keepSpeakToChatOff) { + SwitchRow("Keep off on connect", isOn: $model.keepSpeakToChatOff) { Text("Keep off on connect") .font(.system(size: 11)) .foregroundColor(palette.secondary) @@ -428,7 +305,7 @@ struct ContentView: View { } private func settingToggle(_ title: String, _ subtitle: String, on: Bool, action: @escaping (Bool) -> Void) -> some View { - switchRow(title, isOn: Binding(get: { on }, set: { action($0) })) { + SwitchRow(title, isOn: Binding(get: { on }, set: { action($0) })) { VStack(alignment: .leading, spacing: 2) { Text(title).font(.system(size: 14, weight: .semibold)).foregroundColor(palette.primary) Text(subtitle).font(.system(size: 11)).foregroundColor(palette.secondary) @@ -436,19 +313,6 @@ struct ContentView: View { } } - // Label on the left, switch on the trailing edge, so every switch in the window lines up. - // The title stays on the hidden Toggle label for VoiceOver. - private func switchRow(_ title: String, isOn: Binding, - @ViewBuilder label: () -> Label) -> some View { - HStack { - label() - Spacer() - Toggle(title, isOn: isOn) - .labelsHidden() - .toggleStyle(SwitchToggleStyle(tint: palette.accent)) - } - } - // Multipoint device list. Read-only for now: nothing here sends a command that changes the headset. private var devicesCard: some View { VStack(alignment: .leading, spacing: 14) { @@ -488,16 +352,9 @@ struct ContentView: View { .font(.system(size: 11)).foregroundColor(palette.secondary) } Spacer() - Button(action: { model.setPlaybackPinned(!model.playbackPinned) }) { - Text(model.playbackPinned ? "Unfix" : "Fix") - .font(.system(size: 12, weight: .semibold)) - .foregroundColor(palette.primary) - .padding(.horizontal, 12) - .padding(.vertical, 5) - .background(palette.raised, in: Capsule()) - .overlay(Capsule().strokeBorder(palette.cardStroke, lineWidth: 1)) + CapsuleButton(model.playbackPinned ? "Unfix" : "Fix") { + model.setPlaybackPinned(!model.playbackPinned) } - .buttonStyle(PlainButtonStyle()) .disabled(model.multipointBusy) } } @@ -679,11 +536,112 @@ struct ContentView: View { } .padding(.vertical, 3) } +} + +// MARK: - Shared with the menu-bar panel + +enum EQPresets { + static let fiveBand: [(String, Int)] = [ + ("Off", 0x00), ("Bright", 0x10), ("Excited", 0x11), + ("Mellow", 0x12), ("Relaxed", 0x13), ("Vocal", 0x14), + ("Treble", 0x15), ("Bass", 0x16), ("Speech", 0x17), + ("Manual", 0xA0) + ] + // WH-1000XM6: only Off and Custom have confirmed preset codes on the ten-band layout; its other preset + // bytes (0x20, 0x30-0x33, 0xa1-0xa2) are unnamed, and the 5-band codes above don't apply to it. + static let tenBand: [(String, Int)] = [("Off", 0x00), ("Custom", 0xA0)] + + static func list(tenBand: Bool) -> [(String, Int)] { tenBand ? Self.tenBand : fiveBand } +} + +extension SHCAmbientMode { + var displayName: String { + switch self { + case .noiseCanceling: return "Noise Canceling" + case .ambientSound: return "Ambient" + default: return "Off" + } + } +} + +// The bundled product cutout matching the device name (e.g. "WH-CH720N" -> "wh-ch720n"), or a generic +// headphones glyph for models without one. +struct ProductImage: View { + let deviceName: String + let size: CGFloat + + @Environment(\.appTheme) private var theme + @Environment(\.colorScheme) private var colorScheme + + var body: some View { + if let image = NSImage(named: deviceName.lowercased().replacingOccurrences(of: " ", with: "-")) { + Image(nsImage: image) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: size, height: size) + } else { + Image(systemName: "headphones") + .font(.system(size: size * 0.48, weight: .thin)) + .foregroundColor(theme.palette(colorScheme).primary) + .frame(width: size, height: size) + } + } +} + +// Battery, codec and (optionally) the current mode as capsule chips. +struct StatusChips: View { + @ObservedObject var model: HeadphonesModel + var showsMode = true + + @Environment(\.appTheme) private var theme + @Environment(\.colorScheme) private var colorScheme + + private var palette: Palette { theme.palette(colorScheme) } + + var body: some View { + HStack(spacing: 6) { + chip { + if model.hasDualBattery { + // Earbuds report a battery each, plus the case when it's connected. An earbud that + // isn't reporting (docked / powered down) comes through as -1 and is left out. + budBattery("L", model.batteryLeft, charging: model.batteryLeftCharging) + Text("·") + budBattery("R", model.batteryRight, charging: model.batteryRightCharging) + if model.batteryCase >= 0 { + Text("·") + budBattery("Case", model.batteryCase, charging: model.batteryCaseCharging) + } + } else if model.batteryLevel >= 0 { + Image(systemName: model.batteryCharging ? "bolt.fill" : batterySymbol(model.batteryLevel)) + .foregroundColor(model.batteryLevel <= 20 ? palette.danger : palette.accent) + chipText("\(model.batteryLevel)%") + } else { + Circle().fill(palette.accent).frame(width: 6, height: 6) + chipText("Connected") + } + } + if !model.codec.isEmpty { + chip { chipText(model.codec) } + } + if showsMode { + chip { chipText(model.mode.displayName) } + } + } + } + + private func chip(@ViewBuilder _ content: () -> Content) -> some View { + HStack(spacing: 4, content: content) + .font(.system(size: theme.isSignature ? 10 : 11, weight: .semibold)) + .foregroundColor(palette.secondary) + .lineLimit(1) + .padding(.horizontal, 9) + .padding(.vertical, 4) + .background(palette.raised, in: Capsule()) + .overlay(Capsule().strokeBorder(palette.cardStroke, lineWidth: 1)) + } - // Matches the connected device name to a bundled product image (e.g. "WH-CH720N" -> "wh-ch720n"). - private func deviceImage() -> NSImage? { - let slug = model.deviceName.lowercased().replacingOccurrences(of: " ", with: "-") - return NSImage(named: slug) + private func chipText(_ text: String) -> Text { + Text(theme.isSignature ? text.uppercased() : text).tracking(theme.isSignature ? 0.8 : 0) } // One "L 82%" reading in the battery chip, with a bolt in place of the battery glyph while that unit @@ -708,170 +666,102 @@ struct ContentView: View { } } -// MARK: - Menu bar - -// Status-bar item for pinning playback to this Mac without opening the window. Installed once from -// AppDelegate; reads and drives the same HeadphonesModel as the window. The icon shows the playback device -// next to the headphones (phone, computer, or its multipoint slot number), and the headphones fill in -// while playback is fixed to this Mac. -@objc final class MenuBarController: NSObject, NSMenuDelegate { - private static var instance: MenuBarController? - - private let model = HeadphonesModel.shared - private let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) - private var cancellables = Set() - - @objc static func install() { - guard instance == nil else { return } - instance = MenuBarController() - } +// Noise Canceling / Ambient / Off: segments in a recessed track, or separate pills in Sony Signature. +struct AmbientModeControl: View { + @ObservedObject var model: HeadphonesModel - private override init() { - super.init() - let menu = NSMenu() - menu.delegate = self - menu.autoenablesItems = false - statusItem.menu = menu - updateIcon() - // objectWillChange fires before the new values land, so read them on the next main-loop turn. - model.objectWillChange - .sink { [weak self] _ in DispatchQueue.main.async { self?.updateIcon() } } - .store(in: &cancellables) - } + @Environment(\.appTheme) private var theme + @Environment(\.colorScheme) private var colorScheme - private var thisMac: PairedDeviceInfo? { - model.pairedDevices.first { $0.isThisMac && $0.connected } - } + private var palette: Palette { theme.palette(colorScheme) } - private var pinnedToThisMac: Bool { - model.playbackPinned && thisMac?.playback == true + var body: some View { + let track = RoundedRectangle(cornerRadius: 11, style: .continuous) + HStack(spacing: theme.isSignature ? 6 : 0) { + modeButton(.noiseCanceling) + modeButton(.ambientSound) + modeButton(.off) + } + .padding(theme.isSignature ? 0 : 3) + .background(palette.track, in: track) + .overlay(track.strokeBorder(theme.isSignature ? .clear : palette.cardStroke, lineWidth: 1)) } - private var playbackDevice: PairedDeviceInfo? { - model.connected ? model.pairedDevices.first { $0.playback } : nil + private func modeButton(_ mode: SHCAmbientMode) -> some View { + let selected = model.mode == mode + return Button(action: { model.setMode(mode) }) { + Text(mode.displayName) + .font(.system(size: 11.5, weight: .semibold)) + .lineLimit(1) + .minimumScaleFactor(0.8) + .padding(.horizontal, 8) + .frame(maxWidth: .infinity) + .padding(.vertical, 8) + .selectable(selected) + .shadow(color: selected ? palette.selectedShadow : .clear, radius: 8) + } + .buttonStyle(.plain) } +} - // Phone if the name says so, computer for this Mac (or another Mac), otherwise the slot number. - private func playbackSymbol(for device: PairedDeviceInfo) -> String { - let name = device.name.lowercased() - if name.contains("phone") { return "iphone" } - if device.isThisMac || name.contains("mac") { return "laptopcomputer" } - return "\(device.slot).circle" - } +struct AmbientLevelSlider: View { + @ObservedObject var model: HeadphonesModel - private func updateIcon() { - let base = pinnedToThisMac ? "headphones.circle.fill" : "headphones" - let device = playbackDevice - statusItem.button?.image = Self.icon(base: base, accessory: device.map(playbackSymbol(for:))) - statusItem.button?.appearsDisabled = !model.connected - if let device = device { - let name = device.name.isEmpty ? device.address : device.name - statusItem.button?.toolTip = "Playing on \(name)" + (model.playbackPinned ? " (fixed)" : "") - } else { - statusItem.button?.toolTip = model.connected ? model.deviceName : "SonyBridge" - } - } - - // Draws the headphones symbol with an optional second symbol beside it, as one template image. - private static func icon(base: String, accessory: String?) -> NSImage? { - let baseConfig = NSImage.SymbolConfiguration(pointSize: 14, weight: .regular) - let accessoryConfig = NSImage.SymbolConfiguration(pointSize: 11, weight: .regular) - guard let baseImage = NSImage(systemSymbolName: base, accessibilityDescription: "SonyBridge")? - .withSymbolConfiguration(baseConfig) else { return nil } - guard let accessory = accessory, - let accessoryImage = NSImage(systemSymbolName: accessory, accessibilityDescription: nil)? - .withSymbolConfiguration(accessoryConfig) else { - baseImage.isTemplate = true - return baseImage - } - let spacing: CGFloat = 2 - let size = NSSize(width: baseImage.size.width + spacing + accessoryImage.size.width, - height: max(baseImage.size.height, accessoryImage.size.height)) - let image = NSImage(size: size, flipped: false) { _ in - baseImage.draw(in: NSRect(x: 0, y: (size.height - baseImage.size.height) / 2, - width: baseImage.size.width, height: baseImage.size.height)) - accessoryImage.draw(in: NSRect(x: baseImage.size.width + spacing, y: (size.height - accessoryImage.size.height) / 2, - width: accessoryImage.size.width, height: accessoryImage.size.height)) - return true - } - image.isTemplate = true - image.accessibilityDescription = "SonyBridge" - return image - } - - func menuNeedsUpdate(_ menu: NSMenu) { - menu.removeAllItems() - if model.connected { - menu.addItem(disabledItem(model.deviceName)) - if model.hasPlaybackPinState { - if thisMac != nil { - let pin = actionItem(pinnedToThisMac ? "Playback Fixed to This Mac" : "Pin Playback to This Mac", - #selector(pinToThisMac)) - pin.state = pinnedToThisMac ? .on : .off - pin.isEnabled = !pinnedToThisMac && !model.multipointBusy - menu.addItem(pin) - } else { - menu.addItem(disabledItem("This Mac isn't a connected device")) - } - if model.playbackPinned { - let unfix = actionItem("Unfix Playback", #selector(unfixPlayback)) - unfix.isEnabled = !model.multipointBusy - menu.addItem(unfix) - } - } - if model.multipointBusy { - menu.addItem(disabledItem("Sending…")) - } else if let error = model.errorMessage { - menu.addItem(disabledItem(error)) - } - // Re-read so the next open reflects changes made from the phone or the headset. - if !model.multipointBusy && !model.refreshingMultipoint { - model.refreshMultipoint() - } - } else { - menu.addItem(disabledItem("No headphones connected")) - let connect = actionItem(model.connecting ? "Connecting…" : "Connect Headphones", #selector(connectHeadphones)) - connect.isEnabled = !model.connecting - menu.addItem(connect) - } - menu.addItem(.separator()) - menu.addItem(actionItem("Open SonyBridge", #selector(openWindow))) - menu.addItem(actionItem("Quit SonyBridge", #selector(quit), key: "q")) - } + @Environment(\.appTheme) private var theme + @Environment(\.colorScheme) private var colorScheme - @objc private func pinToThisMac() { - guard let thisMac = thisMac else { return } - model.switchPlayback(to: thisMac, fix: true) + var body: some View { + Slider( + value: Binding( + get: { Double(model.ambientLevel) }, + set: { model.setLevel(Int($0.rounded())) } + ), + in: 1...Double(model.maxAmbientLevel), + step: 1 + ) + .accentColor(theme.palette(colorScheme).accent) } +} - @objc private func unfixPlayback() { - model.setPlaybackPinned(false) - } +struct FocusOnVoiceSwitch: View { + @ObservedObject var model: HeadphonesModel - @objc private func connectHeadphones() { - NSApp.activate(ignoringOtherApps: true) - model.connect() - } + @Environment(\.appTheme) private var theme + @Environment(\.colorScheme) private var colorScheme - @objc private func openWindow() { - NSApp.activate(ignoringOtherApps: true) - NSApp.windows.first { $0.contentViewController != nil }?.makeKeyAndOrderFront(nil) + var body: some View { + SwitchRow("Focus on Voice", isOn: Binding( + get: { model.focusOnVoice }, + set: { model.setFocusOnVoice($0) } + )) { + Text("Focus on Voice") + .font(.system(size: 13, weight: .medium)) + .foregroundColor(theme.palette(colorScheme).primary) + } } +} - @objc private func quit() { - NSApp.terminate(nil) - } +struct ConnectButton: View { + @ObservedObject var model: HeadphonesModel - private func actionItem(_ title: String, _ action: Selector, key: String = "") -> NSMenuItem { - let item = NSMenuItem(title: title, action: action, keyEquivalent: key) - item.target = self - return item - } + @Environment(\.appTheme) private var theme + @Environment(\.colorScheme) private var colorScheme - private func disabledItem(_ title: String) -> NSMenuItem { - let item = NSMenuItem(title: title, action: nil, keyEquivalent: "") - item.isEnabled = false - return item + var body: some View { + let palette = theme.palette(colorScheme) + // Activate first: from the menu-bar panel the app isn't frontmost, and the device picker the + // connect shows would open behind other apps. + Button(action: { NSApp.activate(ignoringOtherApps: true); model.connect() }) { + Text(model.connecting ? "Connecting…" : "Connect headphones") + .font(.system(size: 14, weight: .semibold)) + .foregroundColor(palette.onAccent) + .frame(maxWidth: .infinity) + .padding(.vertical, 12) + .background(palette.accent) + .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) + } + .buttonStyle(PlainButtonStyle()) + .disabled(model.connecting) } } diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index f27d7714..add153d0 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -432,3 +432,22 @@ final class HeadphonesModel: ObservableObject { assignIfChanged(\.focusOnVoiceAvailable, bridge.focusOnVoiceAvailable) } } + +// Playback-pin shortcuts shared by the menu-bar menu and the quick-controls panel. +extension HeadphonesModel { + var thisMac: PairedDeviceInfo? { + pairedDevices.first { $0.isThisMac && $0.connected } + } + + var playbackPinnedToThisMac: Bool { + playbackPinned && thisMac?.playback == true + } + + var playbackDevice: PairedDeviceInfo? { + connected ? pairedDevices.first { $0.playback } : nil + } + + func pinPlaybackToThisMac() { + if let thisMac = thisMac { switchPlayback(to: thisMac, fix: true) } + } +} diff --git a/Client/macos/MenuBarController.swift b/Client/macos/MenuBarController.swift new file mode 100644 index 00000000..140e97f9 --- /dev/null +++ b/Client/macos/MenuBarController.swift @@ -0,0 +1,190 @@ +// +// MenuBarController.swift +// Status-bar item: a click opens the quick-controls panel, a right-click (or control-click) the menu. +// + +import AppKit +import Combine +import SwiftUI + +// Installed once from AppDelegate; reads and drives the same HeadphonesModel as the window. The icon shows the +// playback device next to the headphones (phone, computer, or its multipoint slot number), and the headphones +// fill in while playback is fixed to this Mac. +@objc final class MenuBarController: NSObject, NSMenuDelegate { + private static var instance: MenuBarController? + + private let model = HeadphonesModel.shared + private let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) + private let menu = NSMenu() + private let popover = NSPopover() + private var cancellables = Set() + + @objc static func install() { + guard instance == nil else { return } + // The panel can open before the window has appeared, so don't wait for it to apply the theme. + AppTheme.stored.applyToApp() + instance = MenuBarController() + } + + private override init() { + super.init() + menu.delegate = self + menu.autoenablesItems = false + + let panel = NSHostingController(rootView: QuickControlsView( + openWindow: { [weak self] in self?.popover.performClose(nil); Self.openMainWindow() }, + quit: { NSApp.terminate(nil) } + )) + if #available(macOS 13.0, *) { panel.sizingOptions = .preferredContentSize } + popover.contentViewController = panel + popover.behavior = .transient + + statusItem.button?.target = self + statusItem.button?.action = #selector(statusItemClicked(_:)) + statusItem.button?.sendAction(on: [.leftMouseUp, .rightMouseUp]) + updateIcon() + // objectWillChange fires before the new values land, so read them on the next main-loop turn. + model.objectWillChange + .sink { [weak self] _ in DispatchQueue.main.async { self?.updateIcon() } } + .store(in: &cancellables) + } + + @objc private func statusItemClicked(_ sender: NSStatusBarButton) { + let event = NSApp.currentEvent + if event?.type == .rightMouseUp || event?.modifierFlags.contains(.control) == true { + popover.performClose(nil) + // A status item with a menu attached never sends its action, so attach it for this click only. + statusItem.menu = menu + sender.performClick(nil) + statusItem.menu = nil + } else if popover.isShown { + popover.performClose(nil) + } else { + refreshMultipointIfIdle() + if let panel = popover.contentViewController, #unavailable(macOS 13.0) { + popover.contentSize = panel.view.fittingSize + } + popover.show(relativeTo: sender.bounds, of: sender, preferredEdge: .minY) + popover.contentViewController?.view.window?.makeKey() + } + } + + static func openMainWindow() { + NSApp.activate(ignoringOtherApps: true) + NSApp.windows.first { $0.contentViewController != nil && !($0 is NSPanel) }?.makeKeyAndOrderFront(nil) + } + + // Re-read so the panel or menu reflects changes made from the phone or the headset. + private func refreshMultipointIfIdle() { + if model.connected && !model.multipointBusy && !model.refreshingMultipoint { + model.refreshMultipoint() + } + } + + // Phone if the name says so, computer for this Mac (or another Mac), otherwise the slot number. + private func playbackSymbol(for device: PairedDeviceInfo) -> String { + let name = device.name.lowercased() + if name.contains("phone") { return "iphone" } + if device.isThisMac || name.contains("mac") { return "laptopcomputer" } + return "\(device.slot).circle" + } + + private func updateIcon() { + let base = model.playbackPinnedToThisMac ? "headphones.circle.fill" : "headphones" + let device = model.playbackDevice + statusItem.button?.image = Self.icon(base: base, accessory: device.map(playbackSymbol(for:))) + statusItem.button?.appearsDisabled = !model.connected + if let device = device { + let name = device.name.isEmpty ? device.address : device.name + statusItem.button?.toolTip = "Playing on \(name)" + (model.playbackPinned ? " (fixed)" : "") + } else { + statusItem.button?.toolTip = model.connected ? model.deviceName : "SonyBridge" + } + } + + // Draws the headphones symbol with an optional second symbol beside it, as one template image. + private static func icon(base: String, accessory: String?) -> NSImage? { + let baseConfig = NSImage.SymbolConfiguration(pointSize: 14, weight: .regular) + let accessoryConfig = NSImage.SymbolConfiguration(pointSize: 11, weight: .regular) + guard let baseImage = NSImage(systemSymbolName: base, accessibilityDescription: "SonyBridge")? + .withSymbolConfiguration(baseConfig) else { return nil } + guard let accessory = accessory, + let accessoryImage = NSImage(systemSymbolName: accessory, accessibilityDescription: nil)? + .withSymbolConfiguration(accessoryConfig) else { + baseImage.isTemplate = true + return baseImage + } + let spacing: CGFloat = 2 + let size = NSSize(width: baseImage.size.width + spacing + accessoryImage.size.width, + height: max(baseImage.size.height, accessoryImage.size.height)) + let image = NSImage(size: size, flipped: false) { _ in + baseImage.draw(in: NSRect(x: 0, y: (size.height - baseImage.size.height) / 2, + width: baseImage.size.width, height: baseImage.size.height)) + accessoryImage.draw(in: NSRect(x: baseImage.size.width + spacing, y: (size.height - accessoryImage.size.height) / 2, + width: accessoryImage.size.width, height: accessoryImage.size.height)) + return true + } + image.isTemplate = true + image.accessibilityDescription = "SonyBridge" + return image + } + + func menuNeedsUpdate(_ menu: NSMenu) { + menu.removeAllItems() + if model.connected { + menu.addItem(disabledItem(model.deviceName)) + if model.hasPlaybackPinState { + if model.thisMac != nil { + let pinned = model.playbackPinnedToThisMac + let pin = actionItem(pinned ? "Playback Fixed to This Mac" : "Pin Playback to This Mac", #selector(pinToThisMac)) + pin.state = pinned ? .on : .off + pin.isEnabled = !pinned && !model.multipointBusy + menu.addItem(pin) + } else { + menu.addItem(disabledItem("This Mac isn't a connected device")) + } + if model.playbackPinned { + let unfix = actionItem("Unfix Playback", #selector(unfixPlayback)) + unfix.isEnabled = !model.multipointBusy + menu.addItem(unfix) + } + } + if model.multipointBusy { + menu.addItem(disabledItem("Sending…")) + } else if let error = model.errorMessage { + menu.addItem(disabledItem(error)) + } + refreshMultipointIfIdle() + } else { + menu.addItem(disabledItem("No headphones connected")) + let connect = actionItem(model.connecting ? "Connecting…" : "Connect Headphones", #selector(connectHeadphones)) + connect.isEnabled = !model.connecting + menu.addItem(connect) + } + menu.addItem(.separator()) + menu.addItem(actionItem("Open SonyBridge", #selector(openWindow))) + menu.addItem(actionItem("Quit SonyBridge", #selector(quit), key: "q")) + } + + @objc private func pinToThisMac() { model.pinPlaybackToThisMac() } + @objc private func unfixPlayback() { model.setPlaybackPinned(false) } + @objc private func openWindow() { Self.openMainWindow() } + @objc private func quit() { NSApp.terminate(nil) } + + @objc private func connectHeadphones() { + NSApp.activate(ignoringOtherApps: true) + model.connect() + } + + private func actionItem(_ title: String, _ action: Selector, key: String = "") -> NSMenuItem { + let item = NSMenuItem(title: title, action: action, keyEquivalent: key) + item.target = self + return item + } + + private func disabledItem(_ title: String) -> NSMenuItem { + let item = NSMenuItem(title: title, action: nil, keyEquivalent: "") + item.isEnabled = false + return item + } +} diff --git a/Client/macos/QuickControlsView.swift b/Client/macos/QuickControlsView.swift new file mode 100644 index 00000000..98f6c0c6 --- /dev/null +++ b/Client/macos/QuickControlsView.swift @@ -0,0 +1,181 @@ +// +// QuickControlsView.swift +// The menu-bar panel: the everyday controls without opening the window. +// + +import SwiftUI + +struct QuickControlsView: View { + let openWindow: () -> Void + let quit: () -> Void + + @ObservedObject private var model = HeadphonesModel.shared + @AppStorage(AppTheme.storageKey) private var theme = AppTheme.refinedDark + @Environment(\.colorScheme) private var colorScheme + + private var palette: Palette { theme.palette(colorScheme) } + + // 320pt gives each mode segment a little more room than the window's at its 360pt minimum, so + // "Noise Canceling" fits within the mode control's minimum scale. The height follows the content. + var body: some View { + VStack(alignment: .leading, spacing: 14) { + if model.connected { + connectedContent + } else { + disconnectedContent + } + Divider().background(palette.cardStroke) + footer + } + .padding(14) + .frame(width: 320) + .background(palette.background) + .environment(\.appTheme, theme) + } + + private var disconnectedContent: some View { + VStack(spacing: 12) { + Image(systemName: "headphones") + .font(.system(size: 34, weight: .thin)) + .foregroundColor(palette.secondary) + Text("No headphones connected") + .font(.system(size: 13, weight: .medium)) + .foregroundColor(palette.secondary) + errorText + ConnectButton(model: model) + } + .frame(maxWidth: .infinity) + .padding(.top, 6) + } + + @ViewBuilder + private var connectedContent: some View { + HStack(spacing: 12) { + ProductImage(deviceName: model.deviceName, size: 56) + VStack(alignment: .leading, spacing: 6) { + Text(model.deviceName) + .font(.system(size: 15, weight: .bold)) + .foregroundColor(palette.primary) + .lineLimit(1) + StatusChips(model: model, showsMode: false) + } + } + + AmbientModeControl(model: model) + + if model.mode == .ambientSound { + HStack(spacing: 10) { + Text("Level") + .font(.system(size: 11, weight: .medium)) + .foregroundColor(palette.secondary) + AmbientLevelSlider(model: model) + Text("\(model.ambientLevel)") + .font(.system(size: 12, weight: .semibold, design: theme.isSignature ? .monospaced : .rounded)) + .foregroundColor(palette.accentText) + .frame(width: 22, alignment: .trailing) + } + if model.focusOnVoiceAvailable { + FocusOnVoiceSwitch(model: model) + } + } + + if model.supportsEqualizer || model.hasPlaybackPinState { + VStack(alignment: .leading, spacing: 12) { + if model.supportsEqualizer { + equalizerRow + } + if model.supportsEqualizer && model.hasPlaybackPinState { + Divider().background(palette.cardStroke) + } + if model.hasPlaybackPinState { + playbackRow + } + } + .themedCard(compact: true) + } + + errorText + } + + private var equalizerRow: some View { + HStack { + Text("Equalizer") + .font(.system(size: 13, weight: .medium)) + .foregroundColor(palette.primary) + Spacer() + Picker("Equalizer", selection: Binding( + get: { model.eqPreset }, + set: { model.setEqualizer($0) } + )) { + ForEach(EQPresets.list(tenBand: model.tenBandEqualizer), id: \.1) { preset in + Text(preset.0).tag(preset.1) + } + } + .pickerStyle(MenuPickerStyle()) + .labelsHidden() + .frame(width: 120) + .accentColor(palette.accent) + } + } + + private var playbackRow: some View { + let canPin = model.thisMac != nil && !model.playbackPinnedToThisMac + return VStack(alignment: .leading, spacing: 10) { + HStack(spacing: 10) { + Image(systemName: "speaker.wave.2.fill") + .font(.system(size: 12)) + .foregroundColor(palette.accent) + .frame(width: 18) + VStack(alignment: .leading, spacing: 2) { + Text(model.playbackPinned ? "Playback fixed to" : "Playing on") + .font(.system(size: 11)) + .foregroundColor(palette.secondary) + Text(model.playbackDevice.map { $0.name.isEmpty ? $0.address : $0.name } ?? "No playback device") + .font(.system(size: 13, weight: .medium)) + .foregroundColor(palette.primary) + .lineLimit(1) + } + } + if canPin || model.playbackPinned { + HStack(spacing: 8) { + if canPin { + CapsuleButton("Pin to this Mac", action: model.pinPlaybackToThisMac) + } + if model.playbackPinned { + CapsuleButton("Unfix") { model.setPlaybackPinned(false) } + } + } + .disabled(model.multipointBusy) + } + } + } + + @ViewBuilder + private var errorText: some View { + if let error = model.errorMessage { + Text(error) + .font(.system(size: 11)) + .foregroundColor(palette.danger) + .multilineTextAlignment(.center) + .fixedSize(horizontal: false, vertical: true) + .frame(maxWidth: .infinity) + } + } + + private var footer: some View { + HStack { + Button(action: openWindow) { + Text("Open SonyBridge") + .font(.system(size: 12, weight: .medium)) + .foregroundColor(palette.accentText) + } + Spacer() + Button(action: quit) { + Text("Quit") + .font(.system(size: 12, weight: .medium)) + .foregroundColor(palette.secondary) + } + } + .buttonStyle(PlainButtonStyle()) + } +} diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj index 678b0a5b..fc1b8bd5 100644 --- a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj +++ b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj @@ -24,6 +24,8 @@ CC0000000000000000000004 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0000000000000000000005 /* ContentView.swift */; }; CC0000000000000000000006 /* HeadphonesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0000000000000000000007 /* HeadphonesModel.swift */; }; CC00000000000000000000A1 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC00000000000000000000A2 /* Theme.swift */; }; + CC00000000000000000000A3 /* MenuBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC00000000000000000000A4 /* MenuBarController.swift */; }; + CC00000000000000000000A5 /* QuickControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC00000000000000000000A6 /* QuickControlsView.swift */; }; DD0000000000000000000001 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD0000000000000000000002 /* Assets.xcassets */; }; /* End PBXBuildFile section */ @@ -60,6 +62,8 @@ CC0000000000000000000005 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; CC0000000000000000000007 /* HeadphonesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadphonesModel.swift; sourceTree = ""; }; CC00000000000000000000A2 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; + CC00000000000000000000A4 /* MenuBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarController.swift; sourceTree = ""; }; + CC00000000000000000000A6 /* QuickControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickControlsView.swift; sourceTree = ""; }; CC0000000000000000000008 /* SonyHeadphonesClient-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SonyHeadphonesClient-Bridging-Header.h"; sourceTree = ""; }; DD0000000000000000000002 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; /* End PBXFileReference section */ @@ -110,6 +114,8 @@ CC0000000000000000000005 /* ContentView.swift */, CC0000000000000000000007 /* HeadphonesModel.swift */, CC00000000000000000000A2 /* Theme.swift */, + CC00000000000000000000A4 /* MenuBarController.swift */, + CC00000000000000000000A6 /* QuickControlsView.swift */, CC0000000000000000000008 /* SonyHeadphonesClient-Bridging-Header.h */, DD0000000000000000000002 /* Assets.xcassets */, A8DC790325769A6600447738 /* Frameworks */, @@ -207,6 +213,8 @@ CC0000000000000000000004 /* ContentView.swift in Sources */, CC0000000000000000000006 /* HeadphonesModel.swift in Sources */, CC00000000000000000000A1 /* Theme.swift in Sources */, + CC00000000000000000000A3 /* MenuBarController.swift in Sources */, + CC00000000000000000000A5 /* QuickControlsView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Client/macos/Theme.swift b/Client/macos/Theme.swift index fee9b435..6d23d38b 100644 --- a/Client/macos/Theme.swift +++ b/Client/macos/Theme.swift @@ -1,6 +1,6 @@ // // Theme.swift -// The window's three looks: palettes, the shared card style, and the theme-specific drawings. +// The app's three looks: palettes, the shared card and control styles, and the theme-specific drawings. // import SwiftUI @@ -22,6 +22,19 @@ enum AppTheme: String, CaseIterable, Identifiable { // Native Glass follows the system appearance; the other two are designed dark-only. var colorScheme: ColorScheme? { self == .nativeGlass ? nil : .dark } + static let storageKey = "appTheme" + + static var stored: AppTheme { + UserDefaults.standard.string(forKey: storageKey).flatMap(AppTheme.init(rawValue:)) ?? .refinedDark + } + + // Applied app-wide so the window, its popovers and the menu-bar panel all follow the theme. Not + // .preferredColorScheme: on macOS, once it has forced a window dark, setting it back to nil doesn't + // return the window to the system appearance, so Native Glass would stay dark until relaunch. + func applyToApp() { + NSApp.appearance = colorScheme == .dark ? NSAppearance(named: .darkAqua) : nil + } + // Sony Signature changes shapes as well as colors: pill buttons, uppercase tracked labels, // monospaced numbers, EQ as bars and rings behind the product. var isSignature: Bool { self == .sonySignature } @@ -146,22 +159,115 @@ extension EnvironmentValues { } private struct ThemedCard: ViewModifier { + let compact: Bool + @Environment(\.appTheme) private var theme @Environment(\.colorScheme) private var colorScheme func body(content: Content) -> some View { let palette = theme.palette(colorScheme) - let shape = RoundedRectangle(cornerRadius: 16, style: .continuous) + let shape = RoundedRectangle(cornerRadius: compact ? 12 : 16, style: .continuous) return content - .padding(18) + .padding(compact ? 12 : 18) .frame(maxWidth: .infinity, alignment: .leading) .background(palette.card, in: shape) .overlay(shape.strokeBorder(palette.cardStroke, lineWidth: 1)) } } +// Selected/idle look shared by the mode control and the EQ presets: pills in Sony Signature, rounded +// segments otherwise. Pills must be a real Capsule: a continuous RoundedRectangle with a radius near half +// the height has no room for its corner curves and renders flat-sided ends. +private struct Selectable: ViewModifier { + let selected: Bool + let filledWhenIdle: Bool + + @Environment(\.appTheme) private var theme + @Environment(\.colorScheme) private var colorScheme + + @ViewBuilder + func body(content: Content) -> some View { + if theme.isSignature { + chrome(content, in: Capsule()) + } else { + chrome(content, in: RoundedRectangle(cornerRadius: 8, style: .continuous)) + } + } + + // The content shape keeps clear (idle) segments clickable. + private func chrome(_ content: Content, in shape: S) -> some View { + let palette = theme.palette(colorScheme) + return content + .foregroundColor(selected ? palette.selectedText : palette.secondary) + .background(selected ? palette.selectedFill : (filledWhenIdle ? palette.track : .clear), in: shape) + .overlay(shape.strokeBorder(selected ? palette.selectedStroke + : (theme.isSignature ? palette.cardStroke : .clear), lineWidth: 1)) + .contentShape(shape) + } +} + extension View { - func themedCard() -> some View { modifier(ThemedCard()) } + // compact: the menu-bar panel's tighter card. + func themedCard(compact: Bool = false) -> some View { modifier(ThemedCard(compact: compact)) } + + func selectable(_ selected: Bool, filledWhenIdle: Bool = false) -> some View { + modifier(Selectable(selected: selected, filledWhenIdle: filledWhenIdle)) + } +} + +// Label on the left, switch on the trailing edge, so every switch lines up. +// The title stays on the hidden Toggle label for VoiceOver. +struct SwitchRow: View { + private let title: String + private let isOn: Binding + private let label: Label + + @Environment(\.appTheme) private var theme + @Environment(\.colorScheme) private var colorScheme + + init(_ title: String, isOn: Binding, @ViewBuilder label: () -> Label) { + self.title = title + self.isOn = isOn + self.label = label() + } + + var body: some View { + HStack { + label + Spacer() + Toggle(title, isOn: isOn) + .labelsHidden() + .toggleStyle(SwitchToggleStyle(tint: theme.palette(colorScheme).accent)) + } + } +} + +// Small secondary action, e.g. Fix / Unfix playback. +struct CapsuleButton: View { + private let title: String + private let action: () -> Void + + @Environment(\.appTheme) private var theme + @Environment(\.colorScheme) private var colorScheme + + init(_ title: String, action: @escaping () -> Void) { + self.title = title + self.action = action + } + + var body: some View { + let palette = theme.palette(colorScheme) + Button(action: action) { + Text(title) + .font(.system(size: 12, weight: .semibold)) + .foregroundColor(palette.primary) + .padding(.horizontal, 12) + .padding(.vertical, 5) + .background(palette.raised, in: Capsule()) + .overlay(Capsule().strokeBorder(palette.cardStroke, lineWidth: 1)) + } + .buttonStyle(PlainButtonStyle()) + } } // Light behind the product image: a soft glow, or Sony Signature's warm rim and rings. diff --git a/Client/macos/ViewController.mm b/Client/macos/ViewController.mm index 6577dc7e..dfcc5aa4 100644 --- a/Client/macos/ViewController.mm +++ b/Client/macos/ViewController.mm @@ -30,14 +30,20 @@ - (void)viewWillAppear { NSWindow *window = self.view.window; if (!window) return; - // The storyboard pins the window to a small fixed size; open it up to a portrait layout. + // The storyboard pins the window to a small fixed size; open it up to a tall portrait layout that the + // user can widen into two columns. The size they leave it at is remembered. Appearance comes from the + // selected theme (ContentView sets NSApp.appearance), so the window must not force one of its own. window.contentMinSize = NSMakeSize(360, 500); - window.contentMaxSize = NSMakeSize(560, 900); + window.contentMaxSize = NSMakeSize(1200, CGFLOAT_MAX); window.styleMask |= NSWindowStyleMaskResizable; - [window setContentSize:NSMakeSize(380, 560)]; + if (![window setFrameUsingName:@"SonyBridgeMain"]) { + CGFloat visibleHeight = NSHeight(window.screen.visibleFrame) - 60; + [window setContentSize:NSMakeSize(400, MIN(820, MAX(500, visibleHeight)))]; + [window center]; + } + window.frameAutosaveName = @"SonyBridgeMain"; window.titlebarAppearsTransparent = YES; window.titleVisibility = NSWindowTitleHidden; - window.appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua]; } // Legacy storyboard action connections resolve to these no-op stubs (their controls are removed above). From 2f8f05b7ff760163c1d0686176a7a467a3961037 Mon Sep 17 00:00:00 2001 From: Amit Rajput Date: Wed, 28 Oct 2026 19:37:17 +0530 Subject: [PATCH 34/35] docs: high-res screenshots of every theme, the panel and the wide window Rendered from the app's own SwiftUI views with a populated model and placeholder multipoint devices (no real device names), captured through the window server at 2x: a three-theme showcase at the top of the README, full-length shots of each theme, the two-column window, the menu-bar panel in each theme, and the WH-1000XM6 ten-band equalizer. The landing page's screenshot (also its social preview) shows the new look; the old disconnected-state shot is gone. Co-Authored-By: Claude Opus 5.5 --- README.md | 36 +++++++++++++++--- docs/connected.png | Bin 259275 -> 231617 bytes docs/disconnected.png | Bin 57505 -> 0 bytes docs/screenshots/native-glass-dark.png | Bin 0 -> 2179149 bytes docs/screenshots/native-glass-light.png | Bin 0 -> 1566693 bytes docs/screenshots/panel-native-glass-light.png | Bin 0 -> 470294 bytes docs/screenshots/panel-refined-dark.png | Bin 0 -> 127898 bytes docs/screenshots/panel-sony-signature.png | Bin 0 -> 76287 bytes docs/screenshots/refined-dark.png | Bin 0 -> 822295 bytes docs/screenshots/sony-signature.png | Bin 0 -> 438412 bytes docs/screenshots/themes.png | Bin 0 -> 1834414 bytes docs/screenshots/wide-refined-dark.png | Bin 0 -> 969641 bytes docs/screenshots/xm6-ten-band-eq.png | Bin 0 -> 67744 bytes 13 files changed, 31 insertions(+), 5 deletions(-) delete mode 100644 docs/disconnected.png create mode 100644 docs/screenshots/native-glass-dark.png create mode 100644 docs/screenshots/native-glass-light.png create mode 100644 docs/screenshots/panel-native-glass-light.png create mode 100644 docs/screenshots/panel-refined-dark.png create mode 100644 docs/screenshots/panel-sony-signature.png create mode 100644 docs/screenshots/refined-dark.png create mode 100644 docs/screenshots/sony-signature.png create mode 100644 docs/screenshots/themes.png create mode 100644 docs/screenshots/wide-refined-dark.png create mode 100644 docs/screenshots/xm6-ten-band-eq.png diff --git a/README.md b/README.md index 87a8de22..a541272c 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,9 @@
-SonyBridge connected to a WH-CH720N -   -SonyBridge disconnected state +SonyBridge in its three themes: Refined Dark, Native Glass and Sony Signature + +Three looks, one app: Refined Dark · Native Glass (follows light/dark) · Sony Signature — pick one under ⋯ → Appearance.
@@ -51,7 +51,7 @@ on macOS, and a matching modern UI on Windows/Linux. - 🎚️ **Ambient Sound Control** — Noise Cancelling · Ambient Sound (0–20 levels) · Off - 🗣️ **Focus on Voice** passthrough -- 🎛️ **Equalizer** — presets *and* a full **Manual mode** with 5 bands + Clear Bass +- 🎛️ **Equalizer** — presets *and* a full **Manual mode** with 5 bands + Clear Bass (10 bands on the WH-1000XM6), with a live curve preview - ✨ **DSEE** — Sony's audio upscaling for compressed sources - 🔋 **Battery level** — live percentage, including **per-earbud + case** for TWS models - 🎧 **Codec & firmware** readout @@ -59,8 +59,34 @@ on macOS, and a matching modern UI on Windows/Linux. - 🖼️ **Device hero image** — your headphones' official Sony product render - 🔄 **Live button sync** — changes made on the headset reflect in the app - 🔌 **Auto-connect** to your already-paired Sony headset +- 🍫 **Menu-bar quick controls** — click the menu-bar icon for mode, ambient level, Focus on Voice, EQ preset, battery and playback pinning without opening the window (right-click for the menu) +- ↔️ **Resizable window** — a tall single column by default; widen it past 720pt for a two-column layout +- 📱 **Multipoint** — see which devices are connected, switch playback between them, pin playback to this Mac, and turn "Connect to 2 devices" on or off - 🧬 **Dual-protocol** — auto-detects and speaks either protocol generation -- 🌑 **Modern UI** — dark, minimal, shaped after Sony's own app (SwiftUI on macOS, Dear ImGui on Windows/Linux) +- 🌑 **Modern UI** — three themes on macOS (Refined Dark, Native Glass, Sony Signature), shaped after Sony's own app; Dear ImGui on Windows/Linux + +
+📸 Full screenshots +
+ +| Refined Dark | Native Glass (light) | Native Glass (dark) | Sony Signature | +| :---: | :---: | :---: | :---: | +| Refined Dark theme | Native Glass theme, light | Native Glass theme, dark | Sony Signature theme | + +**Wide window (two columns)** + +Two-column window, Refined Dark + +| Menu-bar panel: Refined Dark | Native Glass | Sony Signature | +| :---: | :---: | :---: | +| Menu-bar quick controls, Refined Dark | Menu-bar quick controls, Native Glass | Menu-bar quick controls, Sony Signature | + +**WH-1000XM6 ten-band equalizer** + +Ten-band equalizer on the WH-1000XM6 + +Rendered from the app's own views; the device list shows placeholder names. +
## 📥 Download diff --git a/docs/connected.png b/docs/connected.png index f5766a04bda59f3b38122adc1e908658e8a1b989..9f504ba36c11170f4386adf80b15cf9b1bd9b65a 100644 GIT binary patch literal 231617 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 ^8HI)FSEv@vpS>6R1ddbQjIhB87r_ct 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 literal 259275 zcmeFZg;yLw*FK0l3>GvnK!ODe5Zpb%CBdCw!2=A=;1D2?gy0TAgADF&2{sVi-DS`j zoFDJ*es9Qk_Al78=X9T`sqU`R_0+9?A-8UJqM zMdATZ>#}1zzhxF9CoM+qVS-5(-x=Ps>}->KBB$5>%h<;HpXFakb9Ao-*y^K}VvGj_ zVxaQB<7|p-q-aXh^J6~ze+y0;R7PARd6iyIpnS2lUTX46GH?EU>0 zy&I%tpt``JEidS4WveRGSw$s7Iu4=j_A(Q{;61MyR8=z~e7uT5cx`r@p zgrfqmBK~`{I}%MR#}Y_HO^tVI%*h`pX_&l-H{6B}59&1-)+(0nuBLnYxVVg#8MZp= zlpEI&_(O+jKe|9qY_)?hO!z?LSzQ*lT^6*&@KMdStEBX`!K|o$UW%ipB%z}WgV`ny z5tr2vG1t53p`jr!dQhQp`Lz_Ac ztPOc>QQkIh3&^$_Fyro=eO&A4M~Uv6aux#n5N875Mf;rS5}x}phNlZajjySW}J8TnL+%+QXzN- z!H!QQ#EOQ#1)C~{Y6XJ5DZ`5UcDk7l$q?V)3Q^!xRtn5^Q@}^j^($jrX5gN>aKs-Pgq7VCA zchVsRC z<-aY~t(vJ8SoG|2Tx!LiN{`erc=4o^Mr=cYii&L?m+)*~RPHuTO&nY4mUr>1m*ABv z)96n1{6-i`8ku+F4kY;OS!7lG%5asRI8gjL_NxRpl%*bv-YWKT)hYeo;bKPX-5DyS z$grR}9=ubpJBcu68z1teb$10seTeEAx+FxH^dE98@TO>B46OjbXfCgZ|qXa z-^{?`zhbE+x(zFeeNv}vgypS$B#L%>dAh~zS~&NaS^(k~jT+IW(&}#g8$_S<?AEniEvG;h^4{@=4=@G?bDL3H!qq9Z0yZ`bA@gCl+5EfWI@x9Smi#4fYg3sxY zfCV2Q4L9%PjQpc7Mj^wxDz3k%9!4Tn#GPYPXyiwa7NOH_TaShY&_OX@;@+YpAj+0f zjW_UALTlgcX**;Z=)i{(VJV;4cg641YD~F6@()4_OoTQ2@(0~pd$xLuxz>0!JTz88 ziONZIkXH4uvLomEj#I~i1J2{IF)jXZ!X(D}UBf2-0cLzwS&ji1>=_Y=xf0te`^Q-QUNf9ic{;PZbuY!GYdtm^< zo|=Wrhy5g*R|Sc9i11ZEN3_&V$nfXV{)o4~u@a)cb&0a_YK@a$B|XXdjHeaO&z~sl zcSTAzkkM6=9UD~VC%|6U%d17aI#V8TGhI3S-`V z<{537-n*jkIN?JLSKV*g;Ks8b?79Kk1t$g01#N11nzaR){{1Rf^S6=5J3=xP8DbDk ze+G5p$Iu}YdAgy6g^JmI7EVh^n@wxW^x8y`Hvgm3hMwzlw4oMN&yvWqhiFXjn41iy zy!V5O1}|UmHGOtYNTY;&yh0wWT-srHFAi#|{DE|TwVF#E_~C!GPjRsn?ul@#$i^rj zD_|<%Z*#rQr|DF!Q8TGGy?q+xR`JYX3h`aqGtIGX&Fa>><&!ogAPQvE4 zCvJtMvEFCB%Jo-&{RfdF8!UAT1#Y!HQ9eO1?=dCfo4&DeHLvyX^lz=clF`DZYf;~Q zv(RwtO!WSUXxF=&IDat-2>|nLZ~s2hAKEFqE-l4riIl_w{l9uz5^YflE$ntLyc{*y z?6XR+H*%P#;7q+`#?<`Rgr-p*AR_riyrS_4Ig~7lk>xh5uP-g7*sJ-<2XW|aMV2KY zrZZP*?oSYraBY@(jrj9(ME764Qimm*>HWbm7KDmF+*9E~&yhKXrFLr^e0@`-#cZ^1 z5&WX}cX$8XtGY3@r*)b_RX?XVn+jv|?;+~^Zs{Us+}T*fXl;BYa|*9BNJUIn=3zBN zt|X2kl+q{dQ`Y=kvtRRK#9GFy5eOyF@Ghu760|!_^mAqKZC#8}o8MH~+70Jn>!*{Y z40(#ooyr9+x01|w4X!=ToXn)J%MIrVL>HB{JFMs9SfixgE`u77mm6ZHShBMv?m^h)cmGY3Lyyg* zn+oefoiWKY+Z2C~8pmjGI#OjFIoJF{=?~lU6325KVeaq`!)t<3YZNhS+s;G+r?zgy zs4Xov{9tlSVFYJ}i9+p$9@{1#TcB-u)KKrp5-kNYt6vk@k@sco&xD|Nl;ve(y7I$E z1RBBL9(xc8Sa_X%PG1tk&TR|}2%tpgy(B1eTG~tzg<6t$*VF=zbjw3ypv`?-AH<2= zfK8~=GppPA`7|e;rsn4THdYor`b?(;LKc!IuHkx{o#l8zUy#pN7I~*QrYp3e;?5V} z{Vryn!8@K+fm**!o0TjNy-339ZXBKD9kNVy+5#2L)RB0==H}Dq;IUDsNjA?xfRB~o zpJZYheeAKGnWxqY#SJyKT;UM~)YDN^VUX{IRy)R{_$H{P`a#1}B&%QfjAl(jiLpiuzxMcxR48+5eblW6{bYWXZttWfp{vMGu z28wf&87lU>oh1C%cO;TPF zb7M_gjpngsZhd#ZShCM8Iyt1Rdk4R=Q|N*>i#3p{gN*8|!p3&ogXA_&vsl zX@sp{Y)>oWAQ&E3?gowm_7wn^sE@XouB5f7?~=95o(Vs=v6v3)kQj1$!|PHJ{&bFM zM6(UN0myxwm?`F{CZSOgr(oLCTmR=raDM$8B-M~l`E%GFSN#<{4ORte-}n90te3Iu z1XpiOT4o{5@p?txgDDpbou<;1v%6b2X+d204$+LE&b_FSHfq&hs=ODw!1Ef>aRkb? z?O0X3zRx^D}$FC zHEojl;OM5@0hR4w$6AtKvPesvqjx$dFf>4|P5jmpZo8~LJKb?0WRdqO@8}lkhi!K@ zNOLi#zVf44#0w=(lEYh-2Qz1deOQ-!h5o^N~`wmjzP;( zuTEg)yO&=J-88{kzU3<4n+$#(&_*9w?jV#x#0q@_pr%!brFGx)%Qj>MXJY{43NpO= z>xx_4qfq!mY7Lk0`<@6kDhGaQBb*g&BuvRu?HcYV-ST0pg6l>Ymyj^dhJ7b-yG-Zm(#Ot@0D8_b`oO*Bz-~+^ie_m*SGtY2%oTbtBoo}DT_c*f|Y3a6Selc%@)(-Vs^#>#0--XLR#>kt z7>zB3UB#mM;%XZZ>WiGtu?*BerrA9T|Hn9F5MiZu|7i*{d)ee%lqu&nKwOHLA>R&i zUG2s;F>0!>hnN?cm`wMHV@fGhV1C95T&V6kNbn<#Vgs*#Vm|O8)NyT$49#}F%z|MU zfmmJ{VT{H9(5=Bc6p&lYy-aUCB|O1qU-yep)Bl0LT8(FST%q5?BidR8vDY!S>3HyUT;F} zvcydD_6#eE$2}u8QQ$etJbWdFmyca$JKH&ndG=E~BvBokQ|Myd*|kH_;R^1`5Kk#C zo@HFWa&(?`MPT-iBfU?F+_OaIUuX!AAHZ+FMvm7Kk8PWBV+z^qU?Aq5fA498y1W7-V**eyBAgmYo% zRCj+Y_bU9_9)7LOC9@PZ55n8t{X8&eo?s0XRe28SrA7Lt(LixH1S3G(QGeI0p-%~2hUmRt4$O(diu#O83>P8xth;Y#z<{LqD1PyF;a4&DMRoVKrxpr7

q1{%KxKUUDRtbv77MMD%T->wKAeg`FgNq6%K6Mz*I ze2ectlMKxgdK`sA>BKYb^WdXJxgd<=9m;i4Dbd&7Q>67T$)W^SLVzXbglo>F;Xf4y zvSK;U5X-eefrs$s7anRQ$zRFt27879?tJLne}ddL=#9#U$l1({8xlxWkbWYwK#i-=c4q>2kq zc7lZry{wKtTmW)I{ZPCi%h0?kZ5d`B-zP%X-6iqj&ZM|56<^4{f|DXWiz0v_T-=68 zLy7tS2yP-;;R4IL*ZPPRDSZ5dwJz(k0PA+{Rcvw}i1=>(-S)6`@ff^wo?9e3-EPNi zF^qlmW+K^&F+^4p|PHm@fpB%L0puc}hMF&c7pdA1^%HHEZV&^sVc zVXy96d{{PN#c>yH3SWBd*SlLFqB@fS&bL_#{amJ*bmCfg`J&!}fbVt3M=L>_U04;6 zel?U*j1#GTE|6%RqaUD?7C0##`$2&`mL;pycug=RPs3mawwf7a~ z@mD!2GEZUSlk0#QAE?p@T z+_8KOUEYqg6P{O5@Uq`wc{M2F)H?XP1Tcaf%N(Ghq4X_-ze&W#R<1$_GYnsfrU?oy z=NM)ZEpr*!+LRWISSS5{ddQ`sI~P?Ds|%|9z&l?-W`bN#NKXE1;0=-wMt-n2ai;Du zK^s;#g0hS#70bj3lFLrk$3NQnba(a4j%+pkQiQoe>tIJl8%!g9kwio`5);nUgSGs* z>V!bA=^uaKkVJQ4C!6DgXWg{x6As{?5TMrJ(^ACoo%hy@?~X+?T}-bTyL}6S!pA{1 zxE;Hj8*~qJEs5jm>kIs$*MTM>5$hczpUS>rdL;>98Enc~R!-k-<^Bc zocoZ|?Gw3SnqS9|?-t;v!Ll1LLfDu{AdS3|u^swqqeI(h1 z+0b!?AIYL}8^4YAe>J_IM#ZtlavSs@Y#%ey_f0cI6J;S$EW6uiiojejxlm2f6*UMk zfv%G71)wi@nN@HwOMTg(++C|k87ca@Zh}6-(z)PMY{9N{u^>$yt!^USR6Xm_aA-=9 zN_*6j6KKS`<_o_FT9(s4y4sJuR9deydo5AWInj#Gu~w}gBX>hA#$t#QunmDr`P=Ag|jC?Q05-SayS5y_ViGe)zB9wguwx3 zc&_jlGPrZrn`3J@kf6LSZq^Mskkb1D&IzI8D^z3WX{X-h>HdmNQsAdAQ1HSwxrYn-<9sHn#p8&dJ}6Gx9dL+!H!KxY&H^U&+{s zrEEwq`GbiZj+CVUF0mBX*kpa3N{eg&GM^IqfNR_Z4MFT|$xW#!F{4P$#(nkWTv7O9 zXVS88Fo#XDHJMydSMGooE;Wdo5#p-_jPrGNU0ImuR>8VhtrrY}h2Or0d>U`T=@EX> zEyWGZMa>e*L7+v6UIjFh?wTnE5dbtvygZd<(h}+a5Dk)8rXE!}t<3kzKDcM40Pr0O zla|?^a4r!%zDT%mz+{xaL9npG8bzb3uj+bQ!Axz*0Y^4+)^sx5^T&iQBYHOG zPQ%A=@&PQZ21EPCEH{Ct#-sDfTOY5cyEK(MGStt#BbgR8?3_Fosn^$XG@L$BKg;Hn z|M+IRJl0>cnUmb7HX4#VBN;&OVhR4Ksg0)|SAtU=-dLaSEKi}d2b5NlOB_Dbf?h+$ z3j`yhEdWHBc}s2xYWbrI+W8bn;iT#L))lh;sn3qDZe2hb`N`H%;EIE6Qt}B1?|7eN z&_;9-{|h}CVQ*N~60Xdf!n0BC;aAc&%JbhN?V?j1ziy?^ zFWA=yB$Nj`@;ZnD)Q(7b@f(*6mxtSu*sD!HA>NR8x_B=U)nzUrx1#TfwsM&gclA`3 zJV9m6i=dF*6I)`rBpJ!02z_69jeU#O0>a^u!+RlM*z3zqLX0kP^UGGKcM5$nc}+`( z+F_Znyn85(T8SP%chF=aNI5tC1dI+-&8Ie1sB#m{p#in4VPx~8$<*9 zlAn8yNT(kjgqT$)n7!$PaY}ph&qWuadN6!<0s5D-8vAJZXBwdMTI#+ZK&-$*Ho?Vy z_4gr_gB>*1LeytR6m99@K4u`zf4B)=l9<8wlU23)|*@gZsb<9Ov7}_BcarEiflJ{kFd#ok85C-jHO#SPQhyIsa%$4K+ir^PW+sOXM!88K)ZS&4YFx)X=Ime zdfm7~6!v4>ZA{SDA^K$(VBP0H??P9~j<^KxZ`r95TimSd3%{b9ol`p!V^F$9w&eU$ z!<2?eK+IlqcRRh*p!(pvGOwY8;-oaX7+*?;^y8f-&Nj*>VCb@NRhq{8Tw&kyZL?kt zc|XcslYMBDrrOfb{&j|TuRTU9;v$m!GY>D}l|wfKwz?-zPVy6_zD7d=UKlDz%PGM5 zhjo=iWI&DdwFi+6n9{;CJh$V0e!}?t(5CimD5|FUl7I=M+$5teZ`RMiW&_mB>(B%0 zIqYO)?r02GkJ8DLcnrFaB%O_$jhM|wz3QYq~Wx3*deGN?~2Cq|sJ%MI^iOEU+*V?)-7LqkslF`33Zx%yuk*QZMaG} zJ9%9?)Qy`o1Qw8Xr*+8gU1u4;tuj~H;=qHF+-~}f7K?1T2BKL#VOea7`h>|O6#ZrF zcsRt!_L!!fW0%pF$&{34T)2=mLy(xW5MKf4MWJ>7YF8`-+Zf*ji|6dK9rMSejZzq^49P~rnsYb_CF7&5&OkqA$qE2I`Sa)CZrKWn8<9m5*nC(|oAJ=W z$5#8L9rhV^cKAD-e$@f=9JZ4}4wqDn9on02+vH*4;98ee1}JIJl$a;WdhjJJ1C^sF zX-(4CSI*|t_CJk7`KTPawp(&#&6aF{6+-nrZjJO9V%J|}x_K0pB^od&qlOCXCvjeG z@m}HIPLk~Z`2cASUocIqa6Vr&J?U7mvwdQ%46a`{-7kS1o{YhVJz5=%NcYStN7nU` zBW&zD&{=eUh)|$!af?UMQO&PU^XeZoJmYdC{VEW=d}!Qaae2VFN4rH%e8@ZS4x4b# zpKeu*Nn1sC|MKU&)UDzIM!j@NO-A01ahNly-w<%<{^_=k}4SRRjcC; ztoH@_JTaZpKT9w{`Z(x+LX0NP#2Y+;VlVxVs{zE8oC0+7h1_cQ+&F_-RTJsN+a?UF zoj4aOEmK-ng7Jens|DGcs&{!92qs?K^+j+%M4F^%sYsxme6VB6(+j@{p9D*qL&aEO zJ%Kq>1N%4!*sI&FsX^oWK9Nb;b{hRP+X`zRFM=omCZJo}j=8|h7f3QW*|_(Qrx#Pa z!m2^#1Y%g`OgNqb85UA6WTgJ|&|H7eqXu#s`}vI;`{P%vatqn4D9K0uR%=k!XiZ_+ z-9c63pe?_AMV~08NVjWeWUuIM@%ymZb?neQ`;ceemdch|8=mnF;zfSy@sd7=8bBfh zKR$o<)PcSDU|G_*e!ZG*H8rBKE9pEOV$8s9(C*ZK0U9l9b;WgSKL+h#;49jt46DT0!`ykSS~>7xjy5bZ{@l*BfsnGiYT=SC?gu>g0h#7Dw&x zT91@%v9sN&D-g_as#uq8Prrr_b?*kd8ccjE8Lfx~hve?NpJn3Ou6RK6&AedbOLEmv zVcA!5+>UU<9VREKQJIUacirUzsV3qd!1s|e>5QV~w0-ZhBkmG84n8jFM1qtZ+e352 z<$syQagSO@!h(XtdS-)OkneJyAKXz-?a$SyPk5_k`Vf(; z@3VU+VpJ?$*!dQpXnXcaPJDuA;%ak#4bA;&NNTIicL~E$g8pS|WN9+h9gu_B?>#GO z1kvUcgVM2-ukhx70+zxb&Qm@4k0Th zwWJwhp1(_nVHTfgR2n8@&5hZWtPUC9A{-UBT`s|+Hi%#0=bb3iJ6*W8axzpP%^Bl& z%~>zwHX>achTvI$nq46#C97A>_HQJ_w|d@uge82oQs6Vhz@&%0M6RobsMwo2Xf*O# zi>#qP1k_cqP@OM73t*mH+A8Y^z6))-VtY(Lk)uuWwrXvcA6Ectrk(OEj3UM{;#oTl zje}|s<$E6Xhm+B_lHUDRR;C-FbMlz0@u|8`>UGIxi9S$*Sr}N2zZw$CV0S@Vq9}G= z&1#vFHC3w@)YeZ!%I6zb+)aXnjowcyjei|mcu%O;x91fh5fv|F$H{k~RDMPu1Dln& z#;VPg_K3St#OlfXsKcte^mREPNZdHsM*j3y7acFUZ}c)IhI~r)HV9W@=3dhIs z2>VZvKgfOXB!_DVp7eG7AeJ@5%zi;q-}{QLf64xp!&R@P2!Y1sai=YtC0`<#CZcnh zZFqafChEhajOi+KJWpzYJ7ppkDYgb+1?zaaZ0ew9PvC&d(YRK?0Lw{_;~8}*H^U$G z^}`WpYx?&Uv0qHPUR(ePM?MUbdD6)8 z{%BUHGn@0x_-cV`Cc6SylD~N4LqqgQSYY4yxR3^XS6#D-Gu>PqtdcjPW*@-!nK1i? zN)zizy9BKdf#m!W=De5gj>Pn~DZbPP-0cfe?*tC|laaZ)gF^}5xm~BF8a-c17P=oc zn4B7V$#J;4yU4`>Z;(R$L{x{Hr>>s;E3rACSp5tKvJ9`yWUi52Kis=xjRU6wUdpHC z4LwBU+R}$!6#ZT$vPSxj&iBu|#maT@9XWc?Rw=BE8xPytFe;W;Bmh5M0MfkKd{pKO zw>sO;VrUG<tFrg5&mpBl&f(1+R1=|(D-T=9(Hzd?5=rmATQkJCb-?$^Y zbqRCuS&=IE{oM-VbzEEL`t$TI;$X_nAmQ?^tA!xlUh}s%Q=QXVuR+6@p7PJiPK3PZ zO1}td&u^*KZ;bdA1F}_J@D-@+pj^`nd5rbz?K~y}_Ee)m`A3$hxzdK-oU3xx^y};S zCPw=&qcXbAF~lzmVU$=1o)91Gs_&b=1CFhrp|ZPk>V#%)C)c4D{53)Gv<{3ECV=LK zrw>~o(#DwzD9yHw^|mlLMG#J z!Bo=bFmKmxX_4J(pN?+di8g9nDE&Nv=pBX^Q4>)PZPTAl%TRhol8C-n1#GHMR;%7e zeXccX#h6NsB0o^Vo!X}+?9|bK5wo8ew(rc6uNZ8bwP~5Du?glbeJ}1S2`op085hkB zr7Agok`VVG)^M~kwah&Iq!76+h@CUwCOkk`=R6bGuhQRFIMWxl_b3!@#t8kDLp?%XgAg3HSvUs47K^OXd2gQY{}IR&F^r`Qe%mnX74G% zM?($ZcQd<75CFns4u{SDFZHsWm@*_U=3ElDO~xxUkp^?lUf0s-2>$JK#4IOW4NI z%wfazZPK6%{PknRegzlF{yJEg7A{-mi%ho9zZ+r)AglMk1d{LfZ`8J&pI^iO^r_9B zLf<+#9ug#C)Ag&&6~8hV%Pq{9_VvaU@t;^GbM0t_&x&35|5RcBUOLBDlI_57_8vHS zi(+WZQ$oIsmY>=F5s4}3MkpukWmsJ7&Xt} zSJZ}Mt6|#tiqtx9RkmC?>@yz)lJNVO4U@%YH^>~NmIsk6;@`g=jpgJ=uWuQL_`nuB zb<1ZZ{7;EjCoH61f>P4$-c|HTV(%eOqc`gSo^)4wTG(VZovvC0HYxsZyJv!yV=zo* zcKD$1yehn>FLj{Kj{o_g$TQNZ5K!WD-Pf-FS%=0NRP$`E(tb;FB~n!j@1 zMT}oZ(7O6m*iOyjUxVr#VRX?0=~N-2WJ&M}C63$E9VgX9!bnASfcq5ruM?U)>2G=u zp|r-7WHz!Vzbh)@bBM0v#rvyCVD~a`pq2SWyetf zpDY#F-#u^i+Y>3Dn}U2fCphH$_KZR#^i`|uNO#QQ$0R)4-^Z)e$Y>t{lUKCTS{PBH zuH4)reuu2P$vt2Jr)j4TC5OI2KFtNLFt&l zKScIv@4BBOu_w+sFL$8mrJ7W?HBCaUryNrjprx~^waKazkw+_i-#cYIKS~(+(;vqy z$HMs9%ed$B)JUblXF7k0G+EPoEcN;FPmx_^Bj&(&_u7rUo+rv;^@}4DA){LJSAYtq z>S~#01N=uwCYVRj+8Z=Ka0dUd&hBJO(V{#0&`Iw`UTyulIKITT=->(Op- zlloW@YbGl|t@^Rk)U-6bWV7SwJLyDn)6P2QMU&fHHZ@>4S}-J`A}gU4egU8<&JLE7 z?bNG}8D4OtJ5fP35fl_l@?ev|{3124BS`3M$i5K9rW!^Q43L^$`}sO`a77rM$tbK< z?~VE~d+<6N;}K{5KoE7kue7AU zQ#($6mzF(clg{9Ck+ibVu%~u+>0r%WqBB;9eAEhYHRln0&1CtW63c^$s?D|tFzMa4 zvBo9stF?LU=S!U310)8DpO_LPrtoVYNr!jo#~S|XF65&mqnH{2G~zNE+V7iaYUd84 z=Bl;UUpo*PXgyiJHwlXuUlGQHr<94AJ_HRz=<2pjsOsYmQ(Dd5cSHia@3Q)Y|M9U% z0-u<*(Xib*n@}dU0=_N;kNn8r3iNwt_Bs3=C5j+h=LUvIkA56IH@znb`xlPUJdC;K zKRp->@q4n@c?=mVRBY-4Z@&;u8@`@{(G80%__BPUch*4tVND2Uon0&%@+_Ku*g0Ko zAh)idsQoZB$q-^6^NYt7vRpOitiei;Lm=xJgrE0KTt56x^EKj{!=PB2Q6^mgvc|sP zO*c{6jaQi4F!-9!nXz+$31xBYHtbUzafu~<5M}hde(dq6H`Epkhte>!9xIVG!sC6&E^L`Lf#2c}vUfnQT_gO+Z(N@blGg)# zJLB|27|jp)mNk*6A)HfSn=7+QLK(Z?+9noO7FC5VkY~MM#cjXYcbgJu@zUN1;l7& z9WNHc_6U3YNLHTBsV_NTEcCq(dDZC9?HgWMMsFoXKB$Q^##j_3`coT5H~;L`reW*C zJV(u6c~nQ@j$jge_%dpCM>x2goU^4PEiQ=IClbGEo5Li?06&+=Wz+?r0OSoZ#x_BI zIl}@P_=W8L}V zS&tU}0a(q}*uTv0GyKk}>L1m&ugOYw-nn?EQbj$k^+^Z_x%Gih*eySPfmjk`?CZWA zhY#$JYhijQ#BkV*PI=(tWDHSNw0fUEDX*H%Cb|ygoARY^A19XlC)D2^rE(f3Y|i&6 zAK{_dCN;V!ZLbWkGjI9?v2xp%Sg1!E+XtyfD*hpxV%ZG)y)9KVobj(13Vb6gIa_t=O(StB)|7mH7t7{Fu zV(-Tu(LYY7wTITm0_dcU~SP_G~x5xB02#@EGEUvX7Kxr#~0V zPyBzHp0<3zz6nov;xY6Q?Z$*(AWOLYA7uV%9hCeqsGO+U=l?VfAxC?@j|i%q{bzgv zjhN`n+6DsNwLB7w0IYrV2MK7&D&hYJBhy6e*V8Z_(|7-dX8-@M{1@o|@1q=O&qbv{ z{kO*t)B2?{-J8yGH1dZuGw@Nj-C`80cvPE!aBRW~On1nJntH-z1g10%JQFCq`zycg z$j>Az#79oHFN?nv5CRx{-6d_QWc^7GkDsF7?_PHBRD3orue&1Dsfghd00skz;jtY` z}gK8w_L@tDdZL5(8m)y zp!cBvyyB?B{|fq3IuyHw_miNsAW<9_acr+0{VI@`4dJz2=#}$~u7bUt16%A8*MlmA zrGJq9+vAs`Xx=TR*#$@W+q7hh)%gk!@p;><!3o#{mo3^peA<#^X&-xa?wb9jp(njeKrh=A`|xz8m{9^RJpmkf zAs*wH(ZvvJS2yXgApF1q6Ol4w*faZcM<9TSRUx-)Cro?M}wOoJXL068uxu zMq)s>O|L1lJ#xui$^WPha41v(#eCBC(0f1E-MUA;XF=Bg&05Bq;+3D5CVrNu`Mbvt z`iumE~f1nRuedh$dp>?5>PV9&K{mvbuhIBlC8$N6$W3;0M$@UZnp2@o;zcAJ`ZU{ zkRs9|mbU^`h~b#N|Dh6){z-_whI&;dX&m4l>^L zT;f7~q|00%9i#%Jc&Xj{!|`dQTayyKD8#n1n6R&duQtb>{`N3Q9cA>E zDbgF~ie;Yl$7vwonrgH~$>P&N<&~$AB=BM*3y??$5A^FKMv6`962*)4B8+>0-q&vT zQ4+yEb6{Y(u-|&FZocGZ$C8#-c(X?YA8Lj2J^3LmbwYfL2v`yfCJ_wI7g zPG*gOPi1mxs7O`YWP?eq4vH(sV81bc(OyswbJa(d%O`d|Mg5c@eH$MQZ^ zIpv>9&7#t?S2!E-)D~Qw!xb9iTDl6yVum`^gH^(tH2!4L@8mn~me);lIX!7m>7m@O zQitNXkl4G9d-Mg0E!tpCe%03tS~ZUi_)8+R9LCi2Px3IrTZ|}6GnInZv}AL02d{d( zM0G*coOf2huv1w!Fd=--fqOmnc9VkQcesUlq($^W*nAv9r_=vr@sszX&@;>+By_IO zSEZZtzL8`;clnk+c9RbJ+u^Y<_cfIKNXLx@sPZDX$fCqQnHq-`t$U4ox78jV@tN{M zDwgb-9SeJeWtvjs)1s{(X23D+IPPC?1;3!N_}Z>mJ%5Vh9J!pHZzB{dEr#Qlk=z+m zLC?;3dgM=fE8>v4p+|n*&MgPNQ_y(WqoN01FEEu{{q>}mxt}5ZwrfelRl-kjZ7lt6 zgvA@pn1_&8QejO<)?S^tF2}roX+nBT4?e0X$jiVa=@Iig$lU|n2n!xx`uC+apcv<2KxfF%v$}@+I$u9Eh*ePRg%3=e#_H}&et6rPEOyRtt%gX zw{ij8|Cc!Exh^JzcTtMCmc<@w5OA ziU_c~1X`-kHrICTApy&|9uiopT)J-I(nofbOjn(owvil`{x71NlLGq z>z*8|xj?7k(G8hTh|H_va-l=ykrP+k;q?d@*j6TU^Qtq6=nKLO7rTR zEX7JZA#XX~GOaTMK@l3(nX2u@q>8qULb4|YzDrA7lU~p&Q1u@4O^7`dWGC6h&dG3q z#7wKHKJ{#gC!LFSubkIrLNh4xsXKXaILY)T9_=K>vLbsIlbaT8txS4*49rMJC>_p6 zK8xJ+%*e>7&C6qCOMsl(VT<&`n;_ko;G2hZM)C9NPOV>BH<)`qbEVhEN|N6?-TO@S zU^OkG%y^&WEf^)*FzV0!M`DMJ0oT10)t^B}$3- zzqz`Bh^NTgp7p<->DiwBG3{V?!uxaN-YnpqFSsR@t(rYFl=UJWN7i#p&hzI)=WUF^ z32x{hbRIteVJlQ1S+K3T@>6C-&4Z?P;MrBX)_B$3b`<%Oy13gkIi>5v1bJRchykE*<4@g`AL{3~6`$ z=NkeN7r_z%ryAE?5;v$#u3Is69jzNIbA2J^T@W#u^cag3p&i$f2=uqxx^^tkA4dJ= z61GmVw?vQB6|>||!O{)3vKMpvTpX|mn>sSJ=dQaD1^=z)-!Fce44wWR$9xbDz6jUw z*u|V%NkncOAGr-f$qQ z)sW3z@?S?JqP>-f<;l-hT((dUX$$Fegs_C5d?N;vb?IHO+Zbtr5Vz`qS$eTmQTAj_%aajkT2fMs_18r;}V3^1<)}4wYZN1Z$eg3o_ zai)2(1s*c?3KhSaw<)&Eyc|R{)%eSe0}!E8fFCboUgp!C`E_tzbycW+_y)-w7s&Ph z%dE9qCrnVVytlxO#SDGj-`xX|Q#{?}kktDua^S=N7Msb2HC znAvtOdRwuP*ZA<+0$hFpfvwoY#KZ&G-63p#BJ8{=^eKvX{q4&VEAR$wrbfxBF|M{h zlPanCoT0sl1Q=@Ue`(1Dy)yPamJ_ueuBQ!{+AGji6YVqH`z#`!8uH*%KW|1qe?(vq z5F+Euk5(_XjEdU%=f*swX3q*Ft=`rxdgC&P*|W=Ws~ryud#MC2z(V;c7s9kJF*=QS z)Jpj`;*jP0uvcl#xK<1#1O)8B*L7fO_B$5v#gUna_gSIBvffy%ihqef{`sMUW>1Fr zH^`FK{0HSnO9b)2^hg6v^E@mG_ucPJLnEP^t36Q!Vg5&MnP%%xAN(sXoNJboHHO)b z4eJbI4@o%dysIj|l*lv6oIHC3;U(c4&~%aT>jRpWfb4+c@tPnR*V^$^g>B#fb;6o=ix&oxSm5C zccX|5#u;E(+d5ic(;uFG0+P`CY?*L%{~CNSBvisB+GWsyrIJhUfvG@mqI&XIrSwI$ zgJhki)gxD_M;+*<2d4eti!ENUwrWHw*|Z$z&G|TND-VSXEI_olGsQ=02jiTiK3 z_jHr4ZC1uij=nuSLJV84QU=(_z*mc|nvjX=bZ&>5;f2A(1FMZqwN%1_o#9nq2!Cdw) ztJ^fJBOw4&t-wv%W#@Z(j{#Bg(LXtAiL{eYUX&G|85i&*HThi1dzZGFub-(KG9Hg# zvo#jp|KaT|quSb{cH!XO&_Z#m;o270mKI7W-r`OvP~0^nKyhnJafcR)26xxu?(P!Y zNl5aAzW2N5oN@2(JMt&lV~>@!=bCHEGoLkg_?+d;;@~oEE33lOdhg4qa9flV7}cQl z!rFU2Q3yUSZ!&}ke7TvGI(b>+5I3~;Gi$-BE(BOVOSQM&6Js}HFErvdM+^ zi%WE^l-gIPEe!IR{9m5S&Xbg6aRuhs{wp@^nwBV-%FPhGjKl13Noy#tHVAu66z8Se zx09@5Eh$`*1(gua%F5WfQxy>sbHDc6hr7+<4kJ2c7U`f#1DEaMb_Axa%R*dd>V9_z zOyt1Besu8v$mtRsuwB0C@R5(GchNgO6 zC416b2Z1s=(?hY-%|BNrp{3kWL}=m`guV}Ax4`HW!Ck)4;pSOV_yy^&h+<~v8G-Xzd<9~f3F*x-J#r-N8LL^2Vc8G|eqQUI#U-LGB@bx6HZ1f5j^ zNt|GAmTt3Bm$gGh9W@pn{TL%ee_lLE0h{X;jrwL5SF%Jbu8j%-z7w1s$0vjI!^J4K}egDxoht(A!zt)}E${7Rj7>%jlgd zUo7ISq`&_!-+;wN{ssBjQjvIZ|8bau?rK1D!%RAAC;j2eK?C>lOzQy^)Vj)Su+&*r zxc4MIEZQ`=nRY78({mu;KnQbIygD78mtN((HFz!Qi+7ccMzOi=&wk)~HYnL4Ik%u3 zW*h8l{8Hdby);$qg42E_FEJVm%w0 z{Uk+TtKEK4PjZqN%|K$NIBn}j^vyaaCzpJv$ts@DsFXSl+#HMHe?+@^Gif5qEmUT2 zZfx~*>w?|3ePvCQrM-#w?hF>ji%)&RL`5iPgb_NPxjKeTS*Aaz3cV5womm>5Akai( zH{GE*1y&sBj#?x71yq4!mBC3g#fa(7D(h5DihX>ojLHqRHLa7xc+~53M&I)ZsCV?$ zcbc~$O-c-3|6THf5Ry_5QaN|TK;J*8cxJglTK6sPw4}y$x|gxHNcR%y{=L032WIz- zC&XNLGEZLR(dNyTG}`l3MdAhg9-*V|<<{0#>F`AueOB#s9Ise}%FtRUTiQ_oy=tZ2 zgSU5huKAj8!jL`aE9L<5q`WCvv`<&_P|1tQ*^0@~Kv1T+)H~yhPytV4@Z3O9`nAtJ zOyd5y>Hhh@_#dnZfI#ucmS5_4j;nnomht+8r@rKk)`3p*mYjDuegI9=q%h}ZkLEq{ z0g9s39jNJOWQcr4rc5rM)Plvf_0anwO%Rs#Sz~kzwp2FF*0DVJtotI;zTwmUi|xL* zwVN?mRehmt0SC{47s642=a(l!@R2rCecin^nwiy)zk>DXBy`MF?f*d-WpFPN0C;vK zkajJmxbuDOQjR2AgP^R$xC`Dd&x($|!kL0m?%>OCx0N=Hiyam4Y?{xB0y8b1bf4;W zIRk82k~Pk@a`s}@dI{2uN=MlHDj2W+gpgP!nu?+YHi6ykkIrI89Igb7%N8&mue;&B zTX3?pre?doohd2t6t9FMb*D6Z zPq_J-2Qlc*JG-}+avR=KcQHvxz+N`{2bKuiFLo%GP3=z>>A7J@HMcQ+d@ea3C5a~Y zhawHA9#=3}a(BJd@pmr)0@lW~mXR*m_nJ%k@c$OD;ZlUOr4&D>95`}tG-;0I)$lpZ zz)LmZuu?P9)zvL6c20$jzaKc{aZ3A2F)@fbYXCsB)=l$ zRBb7@pZXt@w;r%cw7-8kQWS)pRQ#;b_p=iB7xT2oFZR4>#t}8ttmG!`oOSE`;J6XS z;O|w-O(<=8*uxYOhxj#l2NcNdZ=h@34|2Yxlhx3vp46z)(=ol`{ zGheYdh8=Y!%oT@FpudL*DSp|3p=>N+4oKClFg#aNDK48Si*(SZrR?7pmsb&H5`+p=h=8NGaru7|hy)gF zHNtLQycPO!zD`gs#k?*}We|r_I0c3;Zj|WN$jkb$Rh=2Z)Gflfy9VOJpd*j>*!BW{ z{|g*(P$eXFIsWXvKnyIM=c`dYxTI$?!T-hqdSOf1`9e8+`u7CW29p(C5m?ppd5gxh z^EYnfj#ZJ-OyVRD;!hw-g1<|CwpCs)@e4A0BX9N}^R!&bCWB#=+E;kUw=xkJvj61W z+i_MY?N`c~j|Yw4Fp}(zi4r3;3qpNOop~a-+N-KXZ}x-7jzrd`gVR-dE59IrHV~cv zt9E#Y(9g1y>Hb-T!x)`1vnwV`Fl8FpeEP+?&pm#lOFgvpOEhIV0(cWzhxYR_3nGXM zE^ZFDpmKdwwmsune-h!Jl`P)S zra&-Na@KBYCwXv(-YqE-C$dc(W$0~~3Wy+fMk%ZN3K-Xun)i@Z&~%kq?0@PjFj?rA zw+6k7vH2Dan&0L&X}(Ll@b8kc2RrtQ2q^ILre^o_~*2^y3@ITsG&8hdG|9#yT0AHW+7Pp7Vn3D z8t3~*_b^q7px4iNuGIK1S+;lD7Q02=!#%sRHz|p0!}pzP8y>dQnozwptb;Tt*Row-!9eWY z!?CR?%tH;*K8=fq4)&FYH=wWIF)+TD-fqFaRuO<*kmXxhPC23Wqq|;!8GPzFyxLFg zEa4Gl_dMG(2;3dodek`FH4B$RblhZ{PsSze8DV6I^c@%fmkdiVGCZMEV|M?-c=e|n z>!P~kbk8BRbbj0OiHeQIR}=FleoG6bbU7|jNVAq1E@R7JLEk@d{a?<4ALL6T>d8Ot zCozq2TFhiHbP55FP&)sAW{kPxPq!f&|DPR-2_WKHsC;&q6@oAFQ{_izQnen2BL`{o z@&B3OEk(i|Q{6|Ph{ykTzWevfv?!(spZe@Q*?;C!a(G+E|1TDZnP!PIW(;wQ-*o@} z_gBVCw-tK?mny-3FK=PSa353^{O?0GQDEom^fkUVa z<9{!w-i{$EJMmw(2SORcYFIMz6Z`LF@!K(+gYy4{nqcO6k&59jG&N(p{_lR8f4{ih zjcm}-xJ3O2?WO5{a3pp%=GtCFk}3`74%2MBF_JsvauH7FUOC`20 z7ht_Em7GcJ@zqB^x#?~KnBPjh9HX z$725EXnXx@N6A@bba&w=0+bI#|9SPiU)`hRdl!a zIQ#97yMF8}ItxeV?eCk%PJm;Zk7H?tQH~EmjinKj*Zi)9TF`^rl(%K=)}T0ggwtWv zyCsS!g1C!O>o+l`0hEvZy(@2jy-3V+z7z2qFiTbP*qV_1yC#&lSt9eF4f>lGp6V6p zU278A1eY&%a|#<^Mr?4$?Am7crA9ek>}WDSc7XhlLryD=7O>0K$b0WyMs$@h+*`t! z*U;dQ@QFN3_R#jqc;;oMaigJ~Rj(kHq;y%~@_CsAMbV5^uXk%>h5*9^($W<;~cIOkiQQ5R}d=jDus)ZtI0Ple}RQdQw!B)Zny zaO;<&_k@9l<@JSpeNUx5_)xsDVeE6S7ZR7~Nh9w=e||8`J`}x)LQ{=O&33ekO^R!B zjtAcEbOwHmI0^Ow^Xf6W>erGVlFiPLp7n<@-T9OuIzMedZ)R45cuV5&B@MyK+q(vw zv4w{AG64Ap`u-kdS?OEcT)MeqL=@ORc;dN=?KFODluNM^5$&2?Ys*)UU04*-?=ogF z`ZIcRGJdQZEQ*lz5AAhHucxS zyDi!I7BwjCtyw4`Bd56xaoHpoSwxzARalsw8{;X66r)YqK+ZqMgqdwAj;N=XLcRul$rp zhNRSK#=_7WeBhZlOmX4Qw?_`Sz+#aFiK~uhMhw6qkPlUcI4LaaSIWy|UO}S5i$Xr8 z^RDmVHmIDVEkDx)0A-`f9y4qWiD^N3rG+<%G(y9`rRXDORQCBP|42wy(uT-g6Va&9 z(B|vcSu-~9M5Hl@d+g9%xV?N+$Hr`6z}44AkU89r?NCfU5knp)hEU+~ z9yf!Cz-r^+qW0Y^F5xcyS1V$ybJN|JjZ{iz`#_ew8WeIErdOi#)XwvMu~@?ealX z{lcAB4tF0`Ti;@?fq@7&G)j`XwZg^u;rFdGYv71Adq<-G6DdLzL!38jnD%C_N0fi+ zrRM;`auDiW@}paVa(M*WJa%U_nOCN@Exl$rI_3eqvz(!`>9T+V-sVjSuNW*(=WDup z$jV9<5kBHf%w_hG=_2rYZl6kXJqXO4U~eOC%R9|nXotK33Xy*KON1`5$E|oV(Uhsx zjxk$vPss6BYn=23gp1RzZq%lzVGBFg)V?cAbJ56Yi~Xx(GrP=Ymz^w>`z6W-VNh^8@_;t;bPBbGUIW1^jSzzN;Uu;@bRAx* z<<-ah;Gm@)coxXE=v({If_ArNFEDX;9sIV|p+VH|%Od)3aE8uK7;dx0%R1Zzy zL_%-XjYs`?B!x?%0^Z zC%)-nsTxX?40t092EcBzNX#xCg{*zZq@N{SO$H~463^oYcVFl?TvASrcoXUiZ|3=Q62k~ zGN$6QMu*z;=<2(X{xZr`7il8LWxZD7{ULSgOC~L*$sKHcb#}v@aMa9@?m5Y|%Wrrssf^mvtOl&FnM zBDG-i@_8!%2qAL0M#mybsf7JXG;gIf^v>L;3dS@Lkf(p=%KmZH2TrpSzs{!VyM0MT zVh^3D_E$UI_nMK_XgeeLX#AeL@0PoM{}wsQCAl@@+= zWcbP@lZTC=NW@mFMEkkK)q8hL1oO%mf%~y^N$OebZ5T+1O)0!K_Sq%w*fZeG!rP|E zlf9~vu&n6)AElle^bcd~_##G>)f7t=TNN@D6rX|RS74be4?ap?lt$0k-*nku{e)bz zzo!NIe)@zT<8SO2y|$bv52ZdSEk0M@qlS@W2@`rRMh|I6wTUc}SS-DqoLhEwnHsZ1 ztmx3tBj~%RSXn4hlvgIzGkzuV)9=F2+$7j3AYDchHe8n{oZfm7b?ssS=h8JqNQ?t% zLQdKv;~I~<=ogKCTr@dn^TKzY@%1^7?vb!*M9_T!zcAdA0|)68rdv!kQ{7_050wA(c8kYaoR69)fgbr^*?y@_yD6%(tvUa>)yg5X*KrP26`oPV{v(s=N_M|6=4abu|t9-mC2AH)N!I!AX1Gca+J=FgR_;PMhOblPDaR$AePKO4atMbT*YtOvJOF!i z-K4OWr1$qdT3k!m_HFNYBhIbZ$|#iI7EkhOhsd_@z@u-8yLtC=2ufoNVHdRt9=huE zGqV6SxNr2{-|IQaN4BAnhe+RLxpZ{YmWAQwBl)`ZlIVBb(!53KTdhv8E$@;Gp6A!b z4;F4~9~e`M!KDGCW|*)0cOi?j>RJ4HN|?aieQI5&v3X`<)=Rjr_S9nSizMDh$}`H7 zvrG&0+mc1^6py{tUe#El!fvuxetsPl@rGVR^))D=4s_N;av!f)cFq0+V$wh{&>)98 zg?1CidybOpWC9922g(u*(_bep+>Dm@X^Ng9GtYFtiW=P&o}x!#G}I6D`~6#{Pv0@; z?t*2@$Ku+Dq=?b%SJ~_q^c5B5c43x_7R=g*pYn8>VnlA-nvmY~-4jz6-tSp%5*5T535ws)^one{{dJXRL^V*~TQ!8A8Iq5n0o zyRbJScfQkfYYc7VSj05#;^c?^?g>R)c0l(p7KZMPFshs5>mX;F%7c}s$p+CB2g$J; zgVcDwdi3D?XE<4``hK3NW@LJJ{PzpBk*IPBx>1k5yS>j>vY31n*&UaM)4tGrB zOr9mi6LhyPe6(Mv+dzte4>-i#ZV0I^M}M&rI#=~TNeZK{b)-7|4d#PdfS`y~p|i$A zyQdF~u87qNl)SxPzZ$keWMLYm(%er^DDkc83?-uIlwhNXa8$v+sXH#R2la{G39z zM^8?3pR;`?tA)0SptkOU&9^B1(9Z@q?=kI^eSiObKX6KZML~<6c+mKD@e7;Lr}h`u zL*PZ&;FTAA@ z4Vv7=@V;)V8hVHsp#_g=p*~gZD%}TZlCQxI@>WG5Iw#?3jtRmHE(1h&tsfdK<^rXM zDnCyjg~hpUTN;gfZS)F45!0n+ZoA_g=`{>uE`*PA^wdcx7>oIgJqfKy4#Wg@l`H1i zcJkYP;ejzspk~tkfq@t6!KLukDc`=iu$Y`>@#x>O3LzmBU6c=rjul(^kfVGvT+jwn z`^NLQ@EhO57h0TAFq2WuzM_HZs-j>UxJg~XQ;du-bT$mZ{H*h{_QMipT%mgxYLrsb zxs`3cYd*j@hQ{)kveIHTwdN5IQ%HB0UKWHTV}Ujo{y60q$7eMq35Tf)YDH(jZ%)r`D-(`Em9l0 ziH7B+;cE13duGg)I&9WrbRO-Cr*1H^>*z<4g>Tw*?0`OEnaG%a1gG zUL3>(1HC`*fOnxg==jLdspZ1GAo}dj*^`ssAwnELp zxwiRM8c{B7jqXNYH$w@%bk`H(U0>ZPWkltCwOH`+y*@F=Fdd5He*r~#*4{aeaco-5 ztazCk^ivugZdXTY zeBBL{^Ede|<&WAWFZ!C+VIH{S=y712*Cee$s3~}j8mlRK<;N3q z#Do#@140G8Bdp3=#~;{3eQL7(JK8KfrnDs%6h;~ZqfZ4$Ca}Hxh*-Wqn$I=tAZg=X zP6>-#o8yM2-RAVwgqWPZda+uL3p@Hpi-?K9!L@@$)pvI;&mb6sJF=urYElvHD5u}E zj8^hf7*SH2Tk}^>v9bdCOA?CIZScR_=))vnhgcRfYN?1xmo$k-L>m%sGmP=L$O8ok z6>z0X1ZdU(cW4l8l{}=ZNeCR?k!k#5&n_ApT$Kcp5MvxxnwY!TB#$4Hf0uhiB=G&y z54jkz=5wf+(V>{Dn@DcGMUHpf+x)zW&lCBTurt)>{Yq=}CAgk|$)iQ;l+w`VgEWBN z`6p1*7E51-&sBKAC8oB1ev|1qM84)xlt>$n=PnWC(>7M>5hNaval)yHs(1&|&3$TB z2sW~pNfZOP&c};AJbmd_c=jh$FkN)sV@>Ix|JjfW0TT^C>L~#uZcE=h)&bzy2iznjimMrtcU%k zOkf6P9$1A$>*lq=QDit0$jug^_h%HTACK=hm4UK{?dk6oToEhKc%8!$K0e8E1upKxA~x!0ICzb25z?p13iub#@_Q2t{R;g&CuGo=*`mcz zs;jvQC56b+-ThDE(0k^eZpB5Si*pmHTA?3Ycq6H{XIVj9$-$G&Q4r8H#h)y-Z{`xk zQLBIz0})pCdJu~Uwd`VZ;M;KyW^_xa9);>PPvUr3Vr2uoA-@6qfbUHJH*R>twgMw_ z-s*FDnI|_#^uYwk#{?YvudvI$1{Wt2@*Tf7+{i~|nK7KaHS^kRWAHCf68V1GO2B*; zcS1(5e1t4+f`687J{rj{$$TMQ)6(H5u$=3u#>%e+J)IQCm0GHk+EyINpPghjD!}`> zmftR4J}A1yaET!j$X}$j`5nNF5JAk=9YO};Znzmk@?ESq?gZ1XG7P8c47h|neX)4t9iHzjWX*#4WT@lJm>T6J&3_gADoAc^jGx>Qd$)wIMUlSs zU1pxamxa;LCSF^&$~>5oo=GWR42f0};0WH(Np0k$Z_B#BKR{HjzLs=cXd&6xc;E_k zovX5a_JvB{yyTAT+!D1Ef9D(QJog3H_(!G_Qkw~864O*IL2}E?8HJHwAiO?bHO>TD za+J(ZaC?bAYow0W7$)(@g=yi$GvH=})mYb&dclav zgIvDMbK8Q%NE|W16@|yFUjZ=BWldLVZ#2*c_9S~03&9I8I_&%v_M?Rru$aEdKEC@O3}3&hgL z%KxHgzpyQ2zqrTK26z$Wh%3@7Xg=%HCW=py@yGL2c-|pEdSY{2L*<;U8nBL)sJ*>H zH2g$G(g$#c4b9I^lQ8?r2B5;D8Eaq*vD}^QRGbQP{L?MKB=2Q>@P{`MYk7R7U0KrH zV?{jr&T^?qJ3b%XdBe{>nlrXvQEzCGC88}81cpD>$YSDa&%Z-Io<{7aJ0gr}K((I= zG>cB?$pKP6-#|`JYqnDyyJ+nYvh_C_!7D2dcxx+<&*w^N$)y|L6**}n^~Q`2RZ4Ee z_uXz7L^FOF*B}ZUc}iN2|EUP8T~#3?D+E$lH$1LvWLcNVMQ>4s?BJ?V2T=88Z*yum zuN<|EK^ALthI?>E6`GF%(fq@9nx5igPENftRXTwL{aa~#gD2QIt+wU6!O_n_FukP{ z5YzP^c`xew-1Gfp5TdUHKG>^0B!r6g!vFv+1>Hlx3l_bVFtf*+1U#--DKE3xr5qFM zDhz$Fwj$WzWk1O9jp;=_doibRur?hVu~-Pe=gY)jnk6ezvf4FBqvh1V`=F_q`B~vwh2uj_$TaHf^i7)2p4LHHp{6LXt?R|f# z!nc?T!5Z!(0R))Q<;3HW@AC}v$bkN|2G@YmmqQ-p)>q>=Gk&cOt6@@mxWjl1c6H|# zi>5;y!Vvd)*J&E#7x*oGyLX1~Pj`PW%*DnY{llu$qj88;eEx{Xl=vdxrh-s#p6foNm@rY?>OmYc^T;Gt?so^IpkRPo*4k8Izi)s@_(xwu&a zXH@gVK(nMDj9=UANSE8%?`nx@7x&Zsp__&Ze)U88f;>;x%kV$t`cW~3in$YP@38Pw zxZ3q~?PIe#8qhncZ{wZ>0)1Z2s&Uh2Q{-2>GIEH8JzD!+=%zk_c=t*+ z@zc2)r`Yium{o2R`Pfz1q;#Ni`_+4DR{?Wu_`s8%u|z%zG37^fS*h9Vo}pJ50$DA1 z3BosAmiMg~PSD2cFSflA)*f$%b#b-@FU@4xu)=aVYCfOT<4LVL#G1F}V@rpbXQTqY zPUW=1GB(PiQ*b>Py!T3T5{@3fgy%*M;8{N&#)qg#zJQbdx&XswU(G0FlO?b_C1I>; z$++M!(!ep#nsZ3n+Bnp*geFTkDEM zW$T~4zT>CgD>1Mv#y%8p9_nP^pJv^5j=fjT#M^x10qAWwOsqLpT*@ z-G3gSIrWX~iwuINdVbXxeQC5j$7+kiwy>RqXMD)#sD*YZmn*QWyRve7BFox~(Gcw$ zx<6EiPB7UiX&L_JYn+Yc4Dn?HJQ35@y3Ej>9^rs%r@1d(*dIC4PjcpqI++}R{J1h+ zUqvjF835@|AYugLetDkW~sJGXDsX$mJ&6+5~m#%hl)0u>Dvs%%P)Ib zvtb;#W$>jPC_Rr@RAi$g5Zg(XU`bWNl3`MmHkle!8%nl***rGnQG>vo^nk1_;0xV@ zc(#bs1HA9IjXky3Sy>@r^n*!#WM&m#4SA#_C)HFrZ~yAIQIk*L@ytHLdv#L!XqVMR zmfBM6+Ew(Gu<6I7+Zg5bZ@<;T;@9jxRH7J1Y%i)V?%xM zF_)Bz`I+n{d~yPr9|!{Dd+2?GdiR2hLX#^O11PjUTM|7g=}hd$-v(?^?^A zS<#KTY?2tKS6y4L4EX|8eA$x;>f`+yS{fjd91yx|5xO6dBc5BSTf*{xItc2w3Epgp zVf`iuZX3G`H{K@*p~&c71$XUO(5Zl4yCtHr4>J6mg>Yp9F8s?H*BhKVKM(Px*fKZK zx14|EzIvs;_hc#rR?>K zTVWy9a5grJk&Zc@%C`>55NG~sO}m(?Fnq_kBqI9?oso|{^4;f<*AQ6>W*4=tcL zo6Q&?s{R~y$AvBZ%t71}Pukv)VIx4(gcJ)Vf>)x3UwCgKr%ZkK^_;TVy=k?`)w|Wd zTt92jooc4N-**(loLdw5w7E~7%TxJmTkrg}n92F3zu8F?E#GTE?ZaiAYmtpW)2Ivv z1_mJqG{pO=U8OQUqI&MruGE+)-_V6ONj><)Z>R~RL`92rbG7A+6aj7jh+$qyk1M$- z618dA6USx(=rxb1%|+-W!Wg1z8HAEvsEA8QjMjZxxl-gkOJ2J9R8SrPN;V#t{lGe8 zz)G?#?L%4E+&piWv!pEC9L_o`#?=2T%GYrdT!u*&F1*P;YNa4i_qK>Wkx|ku%Pmo2 zYi~a;#JS5cWM}1#cd{emW*7?Hb(1*f+wK$QD^(-{0g?bs=5BV98OIp=<8!h{idx;zfckY5k$%%Z#Ao`-VbF zKI6o~sW?FW!y-hT@;0-tO_@VG)}C|OonlcNb0F*qeLt25WB)RxsnP zNbQ_JRua9%zwZzB>M!S5;D&bMScK6!h9>l&cu4pqS;I%NoT;`X){6QUJ zYteQ6E>L@l|hPvD4)DKRyzHxGM12*i^ZwPZ0<9R z=aLmD_u~5b2XT;@F<;%VAz-oQozx_lbZrpZAd8 zBfJsIcKhs$pMgQX zA0JX3x5HUmJ8dpKzBArS=21G@sz)OGc`pdHk@5>C-(n9++V2SaO2k?To`0=?mDZVM zz!)-$(KhROaV*szZzJhfWIv?2^h3UXO8l#F3HYWZ_krpkn8*5sj0kq|7ByJ1;4@J( z*3AH3oMC)!sm;>p<2bLvPDqcGH!WpG)RJV&cdx=Tp!k(c_srRvS?BfsFxGplM2J@l zDkIgNPc_m8^0XIsg6mfiXU_8ya-N1CTKNL2*Lg~3KeMunxTjraU%t??E#kF=4EWjW zcPC{tY*ON@)^ndgTo$d3%O8`7vn(D}6P)XFT@B+iZz?d_iJl=l*rZmX#8Do?lC;V^ zNeL~WKR0`xR#Y20OGknxF~hwvRL29%<**)C{Fa!u7y;4Cw3{Tsg8k=AllVS0hAX;N z99C(>qZ+-%`BK07HvZZ$4IJ9(!}KY^Ax`TIC7e`<$cv9C>oQw|I!?etFCtfCsZ9;P zM`qt=8z9DGWUO7EM0>RH>J|S+KO2$vj*mVrT}G4nbb{%P93V^p@}rPlR>$Mg{+~(- zUOuN-^;wB&VJ~=PN*g2YVH4&k87KJA$a;lnoNz`fQ`w2;Ytc6Zq(sczDH$Ot9r_rj zyh9De-xRau6#y7ppTxOH@qYlU8h^`WZqZw&2fGQq0JuVYN?LG++qf8K?cY zwgbdF8bjC~RD8J5} zy9=e^iFtAU7|q)?uk}J;X_r}Vj<102pan(;_f+Wq6pJ9nCi62QOX$>1{lqA4vtEwhz}0EIp`GIBoj=oY_`Gj0*0La(WyIwX-hDwnqL25yPh z3+T$BaxAlcqPd1vG!VV~`e0BTyeaH(w1#Iis>s(kj$Bwmrn(>NlwzZOz0qy{q4qu@ z=TsmA;ibIw^xcaK7?ZpCJj36;ZFHM7qYdXI$_uf8EVC2CQD=BrvsPj1AG|++M#?3o zcreD$g(3+8ib;Vx?cq*3m3KIChOG!NZ})u*jt1?SEzF_eJouyp5-sc2W!he#1f~-< z=sf6h;b1*RrRw77!+RM{&lVm45TKbxl{+Al{iifMtqE^09Mx*d%zbGi(I%H+X}=_* zszPqWJ^z~Nl442X6lj|__+GO)Bi_NUKYYGVfzkO1i?FARs3(BGg^nfaN!n9eh{wrU zpz_(-xeDJqD)r`-&&N#kOZ$GJH(!Hcct&SDGnv8EcNdS0A7zr^c}f|+PCOPBI>nqh zYV;oRUR<+lMp`Voqhp~yzXyTiBCH9_<^==OmEdgVDbm#Ma3|W5 zLrpmvrSZW3U`hA?Xb~LzvMT6w(I`M;=_H>mY z4iSh1d`f2z>&vTckB8)=Zq}%A7ZGI&EryYo1Q|f{+I7mf>tRD1mJVv29*XB_mTaP< z<56B6m5<5#8SCDs|G1CPqq5j!98=T$!Us3cegqSBCgfGY8g?cdW;0F}Dme68I5K^+JEd0PD}uh*5!Xg-}nEht!Xnuxs>9*)P%FY?)# z?C7fT5Hz#^MuV81J1I-bL}XKVD#XPLV;x0%bZ}_;{yAwNrEhsc1)2ru0S2CbNZl3h zgE*L$lu++uUzFZY6Zp8#$9=Nf?t=&S|CR0(!Z5w<*Jx$CZe#p{Qvg?SOsBYL+C`=o$p8p zhF$l7`}9T+Yqyw&sAp*Hk?>02Q-{v`%*PUGS3lW2nj#R<=&NYEmL}(;HfrQI1i~HN zc!_4FEfw5=iql6rUT(`vcSQ}{Bu(8f+baWVn>0qtQV<5m9sk^_fzG~JyI8%P@&!#) zyXt@h0(`8VtP_t<{GF`oYbwGJdRAl$71TM9LZCyD9Dl6PvfmI`{BG(c)#Q@ z4%};k!JP=gxd9YXOn{^fIv|_e0X(iI@4V!M0)jG8B}T3ru3f@{o#b1kFd9fDV)#oPn1_qUXNP`b}O zHWJx1F%*F6C;0kCDhi3LdT=6RNPp*gia?m=?2R{fxKf`>RA5?ZfcPCq8e}j;dnHlY z?3&u@ct9BJX4ths^LBe=Kz7c}WARV7_V`%5uYQ3mY|;~QN2D7Wbaa}Io=5?bhcfk?bF}Uvck(u zUS~5(?Ayfftl}8icpGu?&A%BbUbf#l6z>0xi{v{7x8T1;JCFb)dkqDK<0!5J*zg*vCrMltBG+fLwUr{J|%>0G5HTC9Sl}N0q3@IjIQ1h>` zGlUUds)S#0ZLrB5F99~{QCJ`y!;E+#Y%2y?@pH(fF|rz%=jBk{Zz<~yI6I@39wi6N z71sFGZx|NjJ^^DY-4A2a=zcix|OqxPJdbty6C~XQkdQa zo*+ZV&ii)Vg9HQn8!R|om)?!f?9%`en3f9XO^4e*u6nglzX*o(s^<4yPlsiJp72;M zgpat2;xxGf&#<@zp}u&F)cKb=yZV6uH|4Dr1ES)cBtdHl;Mr@VHYMSO?ZvAu;W`pN zpTc9t(`1Q4c>1#$EVwl4I2uV~bhApmFrj6%zu<|#AGixEt{;S;KYQm1*%(HNABf-_ zN~mo+4|xtc&leb;zjeRfK%25GDeoQ|aoV9JuUhM`LNP{C}c z|FQeY_+_2Gr3R(k_LDM^_@)2?o%_>N{J%{n#tkQ-p9|e)asT|p#=N=thkEU*lQ0Wg zPOzvp9ZPiVBK_BaCmVuL&sgs^KIuiAmk`!vV2cHTDSVB)be+j_U5#maf3dM$?kL}M{qe5DK3;CFdwfGlY7HGa4!U_*kj zB{n!R&VWG?p&MtlRHkEP%h?exqbZ~2)k zvYC47XqRMR`wJ)IPVkN*pL6pGSM%!PQIPPJlD~f3bGd3N?-8zz+4#UgxLaL?9vg^u zNv2xc2q97%OLv}`4sKjm zfJHy3ksP&u=jtnKVe$bCL8MyJ%Hu7`9?bQygAWI#5bsV)w_qjhU4$)+fCa|tB`eoH zr098#^>W)YE2(QpCQU*Nb%s__m4@bf^bgiz0&8_4n!_;#M8-XH^vw9A3rH06Hu-rx znh^rmi2J*qna;yoBRI(nmj2u;8z#F61TNnbB{Ut+95E)&QwC8M-`IbOnw@Go5SAVG zAC6bbbu{^j5bp%8YHzF1eFOUv%s|r|R zx@LA#DRrk7V6Q}i6KVsOZ{CQxrGuu^)WaGK;Ck&#(XOqV4gt@*6Xu@=@}d>YBkL=x z1C7#@GM`tB#eHAzz0HyE^8HBnsJ8=qOwGw$vi@zUcYCVkycN@~2udpQUT(zstGE^#E@A0;^7 z1j=3F=D)NOZ^SpmZm>#I3fx_N-||gtB3EJ-hSS1eU%TpXBXNfBH>QZm97o5dZwjlS zrp0tI5_SGTqW4A!yi8#>b#6Gs?*VcI=dgF{}ENeQ49Yqm+_g^o%jRBwkf%5ses$_ENkqs$SgXx$cVxB4A`8Y^zdu4&6xy z(0bc>z;T05U&rV7}=O(t)w(Gc%BE(1eohe1D zmG}_oz`4;5+IS%b6;I6yK<&sTwm2pl;*%}Drt8y{Gpq;}eXXJRCwZ3QME@43*XF1D z)8gBzAIAM=Qs$6u8~0+L%FB;jr29JmTU{nmLlPiK&N5f=n)<84*#o7WSv_&Z4`ZJoK^ZF{hU-d~y@OS^b} zS>Jq$4en?4!9wd*FK(e=%}uMQ3wyMkoEAecZLur>zFLsW%NhTxFg%BRtmC@OS83lI z7HjgcS1EP~}YfaPszL=7oKb&9esyOqt`4J=f*wsa?@?ptjXA0Q9l zZsLqH{dhDwTKV`mgZXBePMVVC>zIZm&Yt7XC(D~(W$zptlK}erGHO6AIL2=%Ret3k zvfgJ_2c&zjGoQZkquQw8outj6U}S&F_t0EjNFqX(Nl}PHhPmLT&Xr(VEiL-U^%hZI zSmX6+z$m5f$2|n;xV>=Qhpuk@BnOhDQ4X1v&IuMRz`)TSD}HTd)$03ek53PPznLpU zSHa-Zf$ExQpLHXoHiK4ALQNj}I7Nf&{o-F!L^x_x`h$|4^ zOJ|=W-8Oek;^bTO8GL>1Q#x|K*;7c%(DN6fzZukvm~Y-uvM&?7#AyzN4=nklMM@t$ zT7zN)y}tZie(LqqzfYtfRJ zOJc2)CDlhw%jVuI*<_zxtg#;}3U805D$o6XdthFe6jgLSyga5XJ{2PJN&XG?x_M=; zEfS6+sS4UrG};tes+=LK(09T|1n&nJjxGLwG@XTCli&aTH&Q`BMLLFWL`1+zBaNt( zl!$Z)A|Txj14KYty1ToZfk=0a?%wF$VDP*7d>_C6Ko4i78f!glW%KgIsXLy0%_XaC03w*2NLStmcs23x)W{z=T-N+K)YE|62rV=d=3-W#RO z$K?C0;tiu+TMw=exj6JbPu`avlQ$(+VsVk>RKl@FCMcmof_YBKG8*#S%iR1(Tg$&dP2 zK7l&{DuD5GR9QU4y8&BH(1M|^y+6uYtM9wWe&2cZik++lGp6JTE*>#R zFyWD+L0#8O>7l$9hO};v<8H?n>@U6qlr^szf59CAT~v%7Rt!c&OP2&o8{W4E0u98k1edlNoDSc{6@yRP`8I`qgi6RH zpomjW*J-B3Pt{XO!NxAZjI^`M3VpOj91i`o&1ZV3M;t`Yp+t51|%<{*-60fdcF zDSYnBLUYdO<~gPXzS30tn%O9*vo*9_&6L)=)DuU7_BDudD3MSG{H_3ggF!8{TrBPQ z2pfZF#l}bGZ90_b#l|L7Nh#fgb-R;i3!?bkE=pH7G?3$g*ArlzHGY>*Tiq6CSs^jh zLYm0lfRRSh%{3(nYfx7!qJX=QeQX4J_<(h-TrvZ~6eZ&|dnpP?Ri!(IZ ze@wALtr(UKtdqi`=kL777C6m|AFYn@PJMTK8to?S4z7mcY-_lJw%T08;urJlOvLo4 z*wu?2fGPLCZBdzwHp7D3z9LFGBX1xxz6aSU>V5GVJ1V32R3d%+pPa9tV`F3>rIyHv zUo@^C!z$aT9W$=Z+wy#L7nB<~@AfCuEZwngT0U#z>z!By_>f%FFN|c|1$d1;sqA!x z@}3*`l8JVIB64|4HnNHj}POK_&LL0>Q(gb!sIL}dE^ zYtscRjL*9BaUMFq(n^g$?*1%lXT}Ak5X*u4HunRKrTiE{_09FN&AXNT7NsV09uZ4n zy1T^PoH*2x6w71~o!=tx8%e+X^R$KaD%6wD*U1JJe5CdgM#HJz%C?1;l^gVbAM~?^OC%B;SIutBrb^ zvn<6v=k5-CHf2o-Q#Go5+Xdfd#Gfui9Om|sHBBB=LbuidpKl2JfMB(^NF`kYFG>m*8ivN-xHf{s*AwS1gli;;~hA(62^IZef za@yW2Uhh(@@0{-ai28PagwdmZMOIl(Z!Ky`^(mt@ztQIlGPf;G|8DV{xcQtoy0CYl0si~ka^g+;2r9&sMhyNiHMq*67PDw`hDt4 zh%?Zu7uo6_uMOG^>BMA&q4KNtjUXQUxC$9s`WYs(sj;dz3VUpxul}blyOKQdt~kHe zaQ%7rW7hn^)H!Uq%(SYh28o>b-h_Kr!|{@C>!mi!S|S1L)fx`6n}pBycV8ah;nM_j z!0r?Cr<+B2wgm#`q0^rj3@_0#JH;~2`U^_W^1rC;Bws4e@tcoQYcDCpb22khgg`Gn z%JIxUA_J>=;?#-|F6n*hD*DHN;snM1;MH?R34dY1Qn|NH`ma56^@hdeYm&X&Q8g#=g&8i=pX3}6GjEl+nHQ}jZfeCV$?k5 znn14x8iSPgd~2d=@-Z1(8SKMiq^8u@7VWYH9DJXs#*&~TUN1gi)4N)h)xg6d)HZr{Ca z<0mKy;RL;WLn-xA^mER(Gq%xh9&o|T&$BmQBt6a}28T(v)TF*ax|!eT7|oldkJ2h@ zOaExyyPWAht5{scREn5K=gC!r5pNu~E8}hwEG1TYgX^2CUavEwO5kaH{i-kc8B^%W z_PshPex{%`;;IYhWfRQr4jjr%g5Sc6Z=+xJNAs2c4K^;N%`W-eq!=(5;+;zZ6B=GMa5*yq$TfF}$t%d} z5?u-HmNnTAi48BZRAVHo zoi5&Pud0B4<0$o5QPr@dND*B?@SVHbn&B2+qtULJZjldLV~xQ$STKfg@{|}Q!Cn( z`6ZhJGyB5qPN4-kn1k%WFI80#(&Oh3pdo0{65l|+tt=JVpX!LvWL!QmWR6u8GsKI3 zyp1cv_DMSRyrN(k0p=&GUir*m9TdL(FCg0M{d&P$n+gNH-^ViqKc$KcO!6;_F;c@j zd>&>o;j~{k{{=5o8D(J%(l@r-?xPaWF&J1Z&r%BY15#T>i(iD_Gw`h`e}k` zV;gq=qszu6CUtEOWFw^S7@GJ|2?{I9hYz0`zn>g@zDGJiI8^Y!c+F9YC(f(ocq?8W zH0}&{kGZHo6g&fI!+K&lwdZA7Q`Rp(u`SlD?J*07PLd73JPpk zmS)gi?Nx=$`UZa}hK9;ARQvg@6uTUE)7w{z?`)~3p;7xhX*b13_qsU^6LLKrcrD&W zM7sV*CAk)v`_ziPKkt;dq}g(ge_WtDYSoQzbw~h(#hjtA$&Mu>Y*X*p?3so)!xel= z(@M3IUqXhHggWcRhKf8V3)Rje3*B3CQc+KEAQP2TStQjwV)_>wx;|`c@)A}Ub9-8h z!_8d3byJmdKASfAiKKQX^VHp8JD`h;?PhepMqM5)TAFM>zMLCc3fJ=*v8Q6T?*Z0H z0ykxvC}OJhc7LO8=H1+U7{z$k!IR=sU%n$^dk%h<5$ADftPr6>`-@o2-@k(>ka~iD ztm-@8Nj}&sMd1c?Y|^|Wq1b@m3r%_adYSvM7ZRy3Vb>VXSs`b=R{|P6xDWBJ$%!La zQxkcXLz_S8TZWMM) zqFlNf0daF(R(0N$ zwryZSLA__2ZX;oefq14dc@NUhD>ewBw3xR==5n5zuw0R!jzU&#DXi}-Loe@9(RGyG47C!LDScU4Ej=zh->YKi1ew;PI65CP>yiKtmTEM=1EX@{GEy#Uwf!C8RF5nt9vc%kwFC8jNy ztDgU#Zj;j$D{;sh!RdoVtoP!MqS(&LjVDO&_j4xov=TFKOA9f+4)q{4Ei(8I*ABO0 zbEt75`<>Tz-bnBpZs_j0En)zyk3_ML6H_QlNnM%==+_ygpi37QBV3d$qS`cOvOEV= zK--ie?cR$Ud0yD{=km*0Cxqs;0_Yhy3}o*owV7mPG7kq{nY^#zbI79_h;x=v6JSkP z92Kv(kree1btdkd~DB`@+BvRp~*r9ox6b9_0!(|Nu{WAdm7#F zY%le-_*Ice;0M;(kP4?&)Pph?1{+bDa8$N=LfDkf_t2k?IGm75mRY2okrO=%Rx)?r z-P%YK9{TkRTPrpsdMhH(?C~#j4wJ&`qxl|57+%=66m?m*czTg-rf9sk%}grGWz~ni zyG^uY`z%Iu=skW(76qV^yb+5J$LVrUN6lL>d#Gx;{f0jL=|4595=qcOMQWMGV{&yj z5Lr(QA0yLXoH4lbV$uEJfdu(91t(jxaRrN7s#|Bgp66#OT+huQ(p4D-k&4!+v2c;f zhZ#AfOhMj)u#{*rR?F$~c3qF7oEs_a0f_!Cpk*+(LJXpXENQ7t3Vu4IWT;EDfP~y6 z>f-cop5Ff9I@`W4bnNEaQ6qJceO#rkk6}OH;k(_|LPS*awNkIYzeTm8fLeXDD2YKSi*OyVVz9!nmA1ogVO)2T00)MC?= zL+t3O-5 zT>>ScW00r!Uf^bfV|$EZSfCP|OoSSbmC2{ye%LSzHX>SIYdw`}HPGbbIE$uW@tzOo z-%J;hU~mL|Dn3n?zm3OQIEe~r7#ku0VQsORJlnC&r6dl~F)t6;UsLn{T#DD>cXBRcOoHZ}Rt~mu z`Hk;+5R1vQb_}CyFyy1)yk;{!F9_f!2#OvbnOIbWbQxRRW~Z|Rth31*3F*E5r$wfW z8wg&0b-TR5^GXoL51Wu86I~Y{`N;yY`L)DHX?5(V0!say1j<>&1WPU&E=7Y~A%o6~ zhm2lFw$*E=B^Fy*bz|VFX}X^mB9WdWrQ;C^r}*^hGc>5Syp{Gx&c!LlH`Zx4Ax)>N z!Fx~W!|EQ0ooH-~^2K_5Yd_F~JrNsddGiEQHpYi3{cY^&R#X)CT2I~>J+zn@uH{?$ zq5?fSJ5ysGCw_hmEJ`xrK4zO7mSE0c+JLk2?b)eZ3*xu6%*`Vg>#|oKNFxcTm$ld5ob+->>=;;7&9jwU_H z1K$vB-X&nl<9L-F;k(UG3HlwimP+CqU7h90bOns~MtN)G8Mh5*1)+(Ryg9hAM<6j! z8PBlDxMI-Eayu=h!ghi8vJc_>Q8(lORbkUV%LZae$LCa8PI0Q~be)teYW{Te&0?Kg zCc1cn9p?o&>NE#JM-F;JX&ClR1hbvBP}h3Kd66)D-P9X4EPnj;jKqq0WHb##Ry?@! zest4*$TRQFO_uBD9Q$wLTl+eYZ_Mv+v)?%kPzAUK#fDNqUP^gyL)>7^rBqY?+>N=` z9-c9*EcrSt^|LWu4uz_6bd?_!X70Z^|FoxRg7u9vGiWP4l5v4D?TatDc9jxWvv)bD zVQHs3IqbylloC?fo^IVCN!JE*MB6;y2&v7Ax}(vqQ?Zb|P9L+zYmx{JDcEzi&g-}} zbSFADvdGoGYFs?3ancu1W~{Md+Y=z z{HYITF8lYXO3Q(G5Ff=pfiFi*5zP(m>9jYX=7YpH#SaPwJ{{bb8VyyLB~Ch5YD8=Y|8<;0()(>*Jn{7UO}e^+&CG8P6os!@jbVTh!ZisIW4e=&f8-PCqtyA+e#rnb{(!llZe(+ z4lC>Q8X0Tj_;>Mgc-so!QLxQ4$MSh|DfAZ(o84WoQm5Kdu|=(08^g?i*7Aeo-o1hE zkL`Dala442Az`(6z#aNL!u`PgcJxXP*A)B}##cO(?A0+E3lc&CinS>YEc6A_62WXJ zY1_vqDW)-hrKWs7tAJ8?tpdbIGrRfl8fYMzvH*D`?XDc|@8#ms18)nuUhK>@t}qFk z;3Bn$K~A#7K+`VO=wbPrLWdja;?2MZW)f5|SBGpShM*gNs7J<>z{X^e<;gdcq$RTB zY=kd>m5cNxyP7r)rzP8Md}{NhX-C(Y@pT=1kCW#><>OU&T7ikXR_1Rf-!BEd_mo*o z*s8MaUU`y#X^01YOCx>&u5=)&nZRpqpl=RK$}vpfP!K?7l8Ix#r@4jZRBuD<3IWfv zd&9~!or-}C6!YYe5my~4a>>Pxoj8rxZm?@ep|&p^#p#mvgkY=|n`aojE>}JPDZ)$e zJpMz-5R{OY-S@1Ur0h}m1Kvlhxg<rV9s6J*LZ1?)T zm9DX^T>)6`754TXt|P@KB+>eW$M14Njg2p20yT%9Z6%X z9k=_idu=C7Fn)dL8cB)T<3>s0*>Ed4Jhf4hOD`QUj!E;VNF|!h9O5ZN2XG+`71Woa z!)D$s%`hS=kPSD?zwNVC%b`%!+`as z2CJ66>i8xBAJ>nmj#QWpRtqZ{g%BUZHR^F*d{tTF^kG)YbHK+VU3XJIY?Fbg)Y4{W z^8}mG|;a<$s#uRnAfX>J1zdI@Vi`t^vIGCK# z#}xa3OP_lY6>CgBD}2yA4mx?cL@0I|vq6DkjjYUs>40uB#3pLS1H}lOdlbHTY~*Nk z#VU!%y5jJjnsjiFKw9yF#j)XD4u0-{Lu+x`FZz%oyzsM;T8|#_M_2)R@+(IBO zgAc7^$=8+kTZ#~{K?g4TJV4s}}JFW-GDP3-x5?fE(MxdiQM#SWxDa;$43TG6xST$6as2pAD- zUTQ1N=$hT4Y<@gLp7&5osoe0_6;oM5(s!*a`BqP+kBr$@wDJO;A9wc3^F*t8n?%>@{+tST1sds!q*gUMa4v`+?-NKE;ikD-u?}CxhaMU* z(1Lis95wAX_Je_0z#Ysm^s?4d_7`lHa=k^xLO$$cf=t#HDe4K0^^9Vmce9cDOe9pq zVMTbK8EyZm>;v@;O<)P(#W9XE`c9f_B}jd~07zmZ+9>casImt21xSxK z4}1SJF&qnHO|Gm$9tGEeY!c(Cc_f~I=sfUi@#+)%4g+!ZqdI?>?+=Gn?HDaYTzvV0 z>*v`|K>tOrm9n488hrSVIb39xpD7@b;yhrHHu&QJe%sDgD75yXJ4{+v5be;~61$j&Gxy`rjrz4zT& zJN}cjKl4Y3<7{b3zjTiJ`_`ea>gK-1^V2X;($t)F(;(ur=?Nas0maWxGnHSF{x>+f zGjIiORo;Woaa?7YB%XCB9f#f=Wyk*^NSpaSm(UJ+&5ixL`;sH=3o9plHBH@7A$UV> zMdEB^ZcuK4E|0IGilZ^x@|Q0*vw4GR1VwD1?Z3p(Q`SWTe8OGOuLJn4mwo_TXqiaM z$4PU2MOKu}vT}@_Lewaq%+a>xn=xsHzuw8z{C0;1j2owVJ;;LtRa1s#zvx%0@7bGf z?FVfJ66%qYtKJmgCi&6}@i8%s|0nAFNp0#Mwmlg%6BHzS(Yz%(toK)MN7!z!!3pnJ zPLr&d4#)_0Q8GB%hRpRH7cx`8>&4f~TU{$VX!AIntLw{-E$vl}|2RoSIV7lYF|cwD z|2Er?zWaXV1G|P!E&4uS6{+G@8h|Y>u7}BpQ|iWOK$dlU0dH)p)RIvgO-;6IYh*pf z`-3NhAmU`){5B1Z>Nii6mYq~ftVfJnRSqUt^lehvC(yuFu9DT#R@Y{#O zZ>6r3$D}r`hXW$BskW{Z;={2wjE1`B-0EklkiNYPFVDf#I+Q?P?ugh&$G#58zCgg` z0&b?Jcrg{iS3!!a;H5Z=WYh)`aF@1f)A5hC<4Nc?(7KS z*7_wT6Vi^s%Q`bEp07uzW>o%WZ(F4d^QfQ&C~-yj#)T(C+i-Vh)aN z+GG~pCKbC>#u9FwA^RGJ^h>@yl8%WfY<(HJ z6CFOD%POT~pPH%Tc{b@p!a8pvc4BrVGx-vp3L4YF)g|T!;anFpBQ@o-Z6_|(xQq1X z1#&5%vq6W!S3pa9d#d=1Fj$fl{xo}NJ@SFvI2^Z79hrdk{(JCwBNxsy(w_Cw;W&VQ zB%t;f9;bHwKZ#MIiXc;4na4KwPNR)aAs9;n5-to=o=fs4%0iIG?edR6EEl*OXLo+D zx{j@XLz&2SKqiR*zJ!pzMJGO?0d9$e$Aew`*w3sFDe{i!KP%~qbPJLV+SzX~y{DW7 z`QvD1`}s-j_b`Xq#$nO@^DJ>XtB6uf>!jbZ?nt1xBc>G)Y*n~ojrG@ARMmvk6AZCK zztmN|*R6=Qg$AI_w}2YSieVK2rU>As?_vI-U9f@Tm8Y~5(kIF^Vz#Zt9~X%A4sis2 zn5UdQkK_Bs{Nl_X|6EC6%Gf6;xwDs6gZJ(=KB`m5vAsGW@ik*s_?R$Q`$tA_cbKG> zj`*AhR-thLXPWmzAF;eZ8*%V;&#|O)JN_2Ua=R`*`(`%b7$}}_f9ZR=cMYK_4lm3L zqk=GdE@o}~AeEkt2BZd3!NIbnzx}@RkxBVv`6ojveR&WQ6SUfbmzs{|MVVg9Y>LNm z?|!X9(tNsS#E-tAxr4eWyL4vI&C1>Ybct#GWA<)V-tXHTg)-Y=^ng56ZAYiOaJ2|y zbxAn8iuJE2v)oP%WkRzFC*M$cAJLOV&tzA8aKUsYjx_!UpVO;ls9_cTiv8(`rysM% zm3WMd%Hxf0oetOf$cJa3?sJ574 znb?$(whQhu+kzgnKJV5tOu-Xe`{fto1=tLWnM9%p`PpynPYj?+ek}ae6kAa!p?k^& zAtArV!Z}VV$2y2%WeUBLgbcf0D^y!$RUirWY*3f>E`- z%L2a5psR%@Y0D03y&L~uObt>6Crg{>Gq-~~-#uibuM0l^-}lpPL;_n@L-+xB3jwVg z2oUJC$ZEJb>UdrUWmSH5Q(7|qJw&>NrBu;(%Kn#Azib zU)vAiQM`a`fnOWl-}1odHi3?%7AXjr!u79zYIYn&Lg;E#9g07;g0wV@gSpRs^R6E?5nMkdtHimKF=HP7wFbm!?5L8RTbt0isCnyKgf*IfTl$yu_g{t<>*;B! zL=pPCK5r&ETYy3m;mD66!)JyicJtfQFZ5IP>>*dv-Pp#}#D|BS7Y7FMW*%c+Q#$sR z^hW6nrhfSPo}zxQZbmV|pA5stA=r~T+DRg%xp6m105+U@D!X&v4qVxJH6hEt< znzVFe(Q-#$Km|ure^oX{Kaaap^4!KH&dRC<#1e$e4P?!kT1?ay%H2xhKB27gM?N2^ z-J&yhzSD=!aB?=XXW`f1;}A#pQZ)hd`YzneSquoKaEnjwaNp&GGFzPN^gO-g_(onL z`p&cDa3xRr2wAR4eVsBdm}rYZ&;vpShX~>GX(NEvMs{~SUpVSc*?e_7a=X?32)buC zV8|ga^6Ojh#th_SjCsf6t?KRb)?#wRgDKK9j6p+MC95R6B{@0*E~Z1QYorVPq`6l# zYc#8Oys#~K9g(*7I^fr@1%N@Yg_0{Vl`mGgau6#BnOT(ukT_!dXU7^fU-?%SY&I7A zuoU=U^tbA?p#8;5eKD+VH^GQ{5)(ABtfrWn+zj2iJn@<$$0GsW=4s?k# z{rZ>Kd`H6JHW+S-gEd_CU!m|elb~jLweF`aMU#K=aX0Px0vD;$!+Rr%exczS$f;6Y zR4Oo!4$ZHqvs2~NwJ-4c*EOz35W>48w&AC#lX_I-1&*M7S{zdaHDOVONw)WZ??7by zA8Vx?S}W`9Bl_<=dTQR2bteztbR~oc>Ll*I5${94Tkf^RPQEG=@$UuD;?EXP0#?3CXlDndx2Me4P8>IiwT6wT* zWV!BvXyf2DxLB%fBXMOT9Ms>@aqxM63^4jNC!I@MB>jQ@wgK`b!bFS<%H`z|EJ)lEEv1!J85Z!*HO@%yZNP72FD~`n zqTM^$q4oePXNZ5}gh;5N~cL$%IL8|9?9DtK6+i1{KI4l_TdMSEnI0 zp(7)f+k6rlONu(fOV7@1QN81Ob093rVMcP;-*+dBq)U@*6Qnv76)Npe%4?peB=(iK z<(Rn(7;8?0yDDN5Rc%V)H*U_rmDx2N=izjvad2JVlH-)F)ka?oqs!Nd?!R*0^A98N z*^7}to!Wy`8tzg#WitI@a8O& zx%VNes2E;Km#%02^UQSEuo+*6m98S;^sJWPFM&aic3(l3eq%207o9T4pC1duH&n%P zRT<1?1Gp;>Cy>?SidEybzD-nCZ}57TiP33yMjOi=wi7pyGeiyyjvd${soHocs-L;{ zNNn$9L+Qg+TIl)t;yY^U>Zor6a!?q)^4}bTzhgc=UKhZKp6RCfwwO2^CBYRuvU6GR z{s?X(2;1W$99Epqr4ih&o*WK;fht$7&8(<=Se(7?@*k7_g-a`Ku+TTb>%)!(dA;LR z8rSWlj%za}1lFQH7wgLE7am-Z3v{8O^wT?IHkwa{s;(8iMKe}}s&=wN9jX015ai(W z5|Oos_+2q>f43pXe&6l2&knW>Ydg+|h`Lt3W?u6oEyU`GGP=KNRW)sOh+M}FxwBbR zQ$9aT)jhy!Zcy+e9ZTBsxh7%@2u$V>d@^|GEI&79C#OBdIKCe&Qptu0UFxUrGX-w| zkiDzflVv<6?^)F}WWb~>3ycaz;Q-?RHRG_ZDocwq_{-`p&zO~{!z+1HtJXuu1(j}J z|7w4GH9Y|oc_D8u!*Bm#PrH&lTiViGVsnhSca7sUaOEOC(MHn58&$vR5GsnjnOQa-(TtQ-%Q+nmJxm8LtQfPx+_5QblHn-1ws(G~z*vd_f+liAW#ORry`FcV@X@c$EGu17p3Klyb zF(cC!Y=LgpT|IJsH;R!6|7f_WFp4JMzP#|LlNGp)YU276AiYEJb%*}9l%E$g#^_YF z6k`zcdbd%K2{WZepJmkib!4uz zxGBDT=0r{YRQ_j(+2Jy+sc_1V9KRU?Uu zL@Ou#H_savuTv9moMOV$!jfY7e)wJf*KdYs`!gkhh1&KOv9dFn!{`v#rWwdzlXMr$ zS3jH#tMUiS$SfK>u7kF(c~lg&2eJ!vqcsq3W(bNz(^I^fx}6%yJh%Nm;7nIi(G2>M z!Ww`yfC4P2S2rVwldPFn86nlJHTFRQ^^#!m@v~C){@_=Nop;M3(mA$?hxV;m zRQy?4liy&bo9EfY)^7*7-rKslAP{w?N=IeyHM%?deJcdYWCUboUS$gCNqfd!F;-boe|QwFrFGCo>mw0 zU><4Yz4LcTd7&TE zxqGN`>D6$Y=#7IetU4V=PB*iXoaLn7nQ{CW=ZQ2wej9aQ23ZKRq?UvW;wms?h_a}ug24(Ji?E?lOLLa+0jVFHycl! z|2>kf2WCQd^MK@=Gl(B8Q?${psZfnakWng{`i6uMn*Nusi%{{%4G4&JSN7hA>KT|E zo!GHJglUgFwozy`O`t;O&r?M#EO-MlI6O9UdFjkED73JRK^&POm6{N^N}7S7?+w#B zcD*cK42OR>5pJcNo~C&a}Lo>ax|72@va z>6U+jms-1|tnk<6{2XEssDrQ@(wx1Q-TQ*Z*YBlgCm6r2SSvrZpBLY{dztj{jd*Rn z%ImGs#Ff{>9mS5I{%e)&>MJM=H#`5Xcl<)3`%BAMweCi)(X@$*gi70s~A zuM{=-q~EjIdi2R#j+-->+wq8zN~au~1b#Vyb}|}4Drb>a^(zGWKyD_zvz}Jlc=lZu ze;4yx+`x{v@?s+dZY>f)&G0K>_?Fl$8anNwx~OpPkg$ykbjoldev%8;&2u%1e=Uc$ z-}64NN^1au#j_YXTYAs?Bq)VfZ;GF0!d@02)c!6~jdM*vbJZA<@Ga^4K6&Ae;2_bS zGL-9^4#}12M=`OZ138Mzt-s;Om>d>&`3Mv*aq`gu zbOzx1Wnr=&!uklDeDD_-z6D9P&*Y_%Afr*Li2yogw+GPBxnsSmH!FO>KtDp~H!tj5I4VCeV?;b+5SfNL$R( zKc={{6UdqJ3t`42{Sekm)=aTmFg>=Cf;cwddSHKK*Z_0%B6=QDO` zNOs`K+Q+Mm?dQlEas;-8GH!u?{_dvg7gn{&8cCkHBm;r#r0!CM-F9-Uq8Nk`!FkE^fBmskIyOFa%S#U9 z3S#(plDL;(kMV#|Fq=pqV+3xW_M^iOO|aSJIuYcb@_Lirs`Tu- z$a;P+`NdP|7><;Q!ml3hCv(hFLST=4qQbqejd;E&cf2N8batJhD~`ljJY+uLT!86U@Iu#^Y_Bb) z;jRB5`qL6knfgc{F$Va6^S9S&-apKr6^kMWlRE0Xo4+S^ndrvgBggqK9~VITgUL|w z3ak$GSw}c-3E`d?;qWacJ-Hm#nDOdTYq>e|hD3oW0iCs1uN=!dzGHx|%v;=+rQVBR zvn^SGYE=Y$DOOJB{u@0Jj0WlA^|YASEvl zLKs@SCbak%M6&%ASAtOpBPs26&~o7h3yZ-55|0zTQqb8gP;VW11(cWXD@{eFiJ!g$ zyIsBw<``K{wBK*oY5@2ceam8lM>(lZ63e9Sgs?XwWQ+=uZpCs*m;==L%LX+#blqqd zO;n7Jm>EwyzpcM3@tyuP$bfpC%4}THQF&yh{*HfR?K5|`y#z0?1ZN0ZFK0BPieB%_`GgGRlJ)|%p zFAs4nD!snYAJ51th;30B#-De7z^~e#jNIgtisu1N4Mp54VN=)M0yZT<^K@q*Gp8FU zX%|V$xP5PLj|GoG^t*bypodJr_=o-aHPSlZ`GC79+@d53B2s2~_>+&ZJcO8J`HEE> z9aJ}R_xRk84EM;s6ShR_6Ki>z!GanH{8F&?;eR-Ncz>yl44CTYUh~`9yuO?dSE?Oi zOCvftK&>?&O5R2m0~kCm!G<5*!=wkBJ|2BpBrOiY!h`F2#DzhwM%|JSF+lK zA^nMOw%erU!&$A%&-kqLofwY)s}y62<4<$@lvP{V5M5(d(xD{j7|j>W=cY4uzpGD&8loy(J@+31V4f#IqQ}i%fPT&8UvVhVPvqDsk zb1raOS*H!OPEI5eV17SI!RB1{M_5C0+5TwojhWo<%6N(barW8#`WE&=au1Y?^Y|;h z4SSP+4-;qKQ{~a>7r1~tDr|7XeAS{{PqiDCM2~`$%4;hqdw}NUE>7**dOuR39zR>q z_U-fuZMoxv<3W+R|GmgMCaW0%7Qt&`5RotRmygic(ek ztRjSCaiX^c<^^NAUIX*i@6bC=s95dI*4%7-xWpg99U;}n%?Zcx?8iC7k*`FKhs)5s z{>SIDSzI+_2MnERS%k0(?&yDcurF%tQ6OJttVKz3rdIL$;%yN$Nn3#Xe6~y-qw&iM zlgkVGioiLW(m7eO8cgK#V(6P>-%Rs8E##xRVC(P3u6oD?e}uW|bgt&%i4m!8@S;+8%;_x`u_Xm4!LljakmSRB3LJ9qNa5QV`st&rnnD zMOivJyI3vM)`R5YS|bj~h7Xa)X^uK9gm9Ih-Y7zqFl2;SiDX)aDIA&`F_|(Kxq(5qur{Dc{`n{bcro9Y`G`s`Z)kd%Ux!`FQ0U7r)~%^)4qL$P7hkx&SyO53onr<; z{*njhGVVxG4we<@t6k|_sUHmjJ0w`;uF8kHOe@wk+>EKk_D8x+m3qNAZBcAAkXzC^ z=hk$_{%LX>m^fAtIe#ylE(0w#WP3;8F?xSp{LqKY<>BAa=)6?7!VAC>GjjY#d(i%S z6bAuj*Pyo@eRJHyEIR#M^m5rx)W8RNs=7&~R1AzjBlCO^77;9@IHpukBtdm$gfdG4lLEIXA#+Q)JHTa6iWyI`z~1fdqj_cxWibvDfXpQC^-( z2pNNllJ}}mjatq~u4Hv#-p3b3(xiyuRIL>`O0ib{g+Ia~4Xeg>Ug|wP)&(5AJGl)l zA?#CmG(RSe6z9gcvtlP>V7dihi8CD^M|8tkjleS}S{9hf z+i`UjN87^MLauWMVF`LFP}}P-j_<)w!jjgLZD5Zfaeo&!0J!G}(Yfd3@a!1;4m1U$ z`j07%8$?X|A3|ofjqFlbNnuVtd^0MXj92BP8^Q=TjH$5V=BHG+&hPGW(X3ozDF5Cv z=d|Q^p1EJLKW!B5?2QqJp6p#dky2u^97|*Uc$1)z_OtUN*JcgtF%PcVH|i>&QB3VD zLo8LAL06M*Yjp}eU!;^}!O3bQXV0RJ!F7uCWg-|a$7 z_ZhO|;P(>PxC@cE?tBh>HRq}(RJmt04|*WhiF~DF&#_Z=C-1_xZ!Lmyl)x7XAox+^ zJNkZ8^H`$^9+Uqq7@%i)>o18kF#-<`RT*n0vxcOng;u6jE0cpR#Qp^GtjnoP4>PZU zBAu5@1h3l@?@_PB_nL^JH22TvtS`D14Zq^WgEUMDliR{y^ozN+{oWp7ixjhsC|!#t z!7;}C4evSf0Vdhm0WAo5^PvJa6WG0_=J6EUt^~%OuRH5fpSgN|cL$!(N;^i6-|YaT zYRs3jq%usQt=h1ltr&y4rK8!bNvUzyU9B%`I-{Pc<2laW$u5SBE}qm}YpqRwIk9G% z#QIFFkWX!jigt7~oYk;c69F}kYJHc={X$9D#|y)Gd?SasI(+B8l2!=!SCE?8$tke5 z8m85dqcw$}aONazHGC)GHD#KoMhEfY`lDNS4Ae=!vAU)%;HYj?Lu}9W;hbUy{h1)RjllA~lQYnR@( zUT*t08eh|Mmgb3YUPxbn=x`)H8ieqYG%Cu0g(bV5R$U)B_&NFZ?C%L*+a}hdMSx3< zKm>f$dw>X?5CEDuJUotWfp%zL7s&M6vI5J*wfA<|oV2A+b4tlFy9JNqV$p4BMAkv= zT2q}oa*ilH`rYwSrHpkZTC7^rA8>UVJFEZvT|j0(hOZoUM{eM> z3TjsS=lL`&I=Cf_F47lKHMnIMlL9AIJcx7*P^qN$XU)sbV6+A})a~LLkm$@XvbQP$ zXI|sE3j6)~H^(6{j1QTKg|F|yXnou-BTaUB-?F#-84K@;0;kMY8TWs2cfA1B*>%!7 z4~%v<0K%U^%ilCP#XaKKp~Lr|E;}Wg)#75+;Np2zDfX)H+;i@f^Rc{;SiYutze`y- z7Xuw#U5#xz9b}E}-kyolJ&U;BQ3YKQFEud+zq4?9kn3?Z`6(UHVFR^GLl2nj)=?_9 zuQ<0K1UM~9_5Kglyd9Ug($B?Od%1o9l&J|2<=?+@)JvxBU#C$R6O}jUZL-y75wZ=GJxiwMV!~O_&nx-|8ZPsU-z4RhO9Dr=sb1 zc+zos0$v~*MATdZg&Y{tQW!)np70A9kg4}3Bzrd*x-WjSA1)fv)-_xukXYH>y1BBe z(<5ck6p!RnUlXNP8>Nw&4Cvizhc{)`Ej4;2@oQ~#Y1 zKe>JRi-;Kjn=5Fs7P%Z3OTH4cr|G>Zx}f_+t1JX7hYL*vHAH%d$*EV6`RfZ!18R3J zT4RElN_XB{spWf0c9w!NbhC76bSzX!AuUu=lRoD&x*mwYEg-D(*~-4BP#n#*vZ!y}Ww4N+3ky=1fE)7t#6Ow%)MhuN1I z??nF@42)Nvf5l?c|3AroowZyeiqKl4Bg_RvDKcJ99DR!WwR|>K+2(wh0H-f6sxML# z5*<1kj>yy~A_qFh8GO#IsVYDc?IKv3{xeCCMkK`u>AXgWe0)y^o-W;UI_N0AoG$hN zU)*>KT`rJ;9d3}+^&+XFq7T1QupE4kB>8!@L;-Ox-%N|>d)ep{gN^?fQ7-5@Fe=X` z_GE*Ty64OEXwhf7?e_&?xZicovDlAA+ZGqY=scm1<;;2lb#gtLNspmQ*ZXGzc&eOI z(jK5~=o^zh>$$k0$zQ~)f&Y7~!zNhvv&-jZp8y=0=U*vrs=5El& zVW;PfW-EGTw4oW>mtmf(Xj}LMTf=@`HCYqsBMALMb0z7uhumvp41#QjN5^5@M_h%O z_2E36)8O&x0wt?$XF(PqnXsyP+6PEuDH#YWUQcmDhBr@G1^uh;RoekyAF5p0T`Wg} z=WhynI6Gh!_~!cyX)Aj>6Di=vEK-T^%wH5`Ed=A-LS5 zwy}ydlR}pkUTkyvLoHwCWut zlML0_MqB=_=EKuwDgRBWa<>ZEA}ijp#3>F`(JslJ9>$Su+57t)#XWsncwgc+@oC)@ z{cH9$;4Z7N^N`6ai9AC7k$FpzlFRAgi%%*c+IoMWh-}v;je`DF!hW${=zP997)V#D~%I9w-X>!M+Utf{RbH*ipV50fuy&i#*T$oA$f*^r#0=VzTMp+hm=Z6WwO0WF_YfF znDE6>Ex=WQCdr0X{u0B)%zrjR-!NoOpzV6rVYBeJq?w&Kg6^`beqCnQksyV>d>w}& zWuQhH3Hs9Cp__*0VHHJYjwKzacG(-|A_UL`0r$V%n}LO2<6jS73VP0(a*?Cpq$K;d zg4+$fPENBgOwN}_wtmm(tq zDFBFDVQlw5hyt6r>G1E!Oj1jzT~8%BJx+luH^XfyhU*87j&ii~Ws;~F;@pQlx^w~& zvy6^nSLW$tvK3DK5|=-^;wTz%39C*vv%D3*j&C&{Pm1I;l$G-LhOcnT@;<=t>hIiskoy04K$Ab$cL?gX5O+Rx>hm;j^-5xEb9cO)as6|i8DGG>j z;r=e#KmsE=QX$zYi&i@zEbnhvq=Sq-+SS56%~!~E1)8_=$X--eOiP3wr8TnDzxiQ( zGnv2&ry1)qsoCF9v2upwQoc20%|u%P@0r#!iqVqF9iw2$4go#kHLH4|41I%xB?H9M z0S|>|{}GKI{a~Q-xjp(LXg&Z&tThM>4JIl%^2(RN4F(Hv{d#+b9ibF32*_D}HVg4y zqHc)fzb6b7&WMo-F89_(MC9CC*RIkU(WA{pzE2?>h1IxU&%%Z)QV7O)CVdX(`Nk?J zB*CQl>MxwTa&5`?LqLX_{N=Ki4|-Ez8tv@t+$;8iN_5nlZD~ zYKPy^gK}fxbzw!Yr)AZZ+Ne7VXl1E3#irDQ-a=pW++P{vg9o282&M@8uO@`;Exl^_ z5CTmo68)FZA~C&nB2L%N;96`g=JO4jvllP1!I$!J8R2o?#&Q{vM5>mZe7x9EB7`}*OYq2{V#N?UE(7}z`y44kMn1{jLL`7) zF&3Z06Jya8G^pdWa_=qAA`WLdE-7{oywq|rD8*T&<0vL z>}pQqM16$E&v}BG;6vuhe~NWG;J1n*Tq0?91F?MqYcGCQ;adGZz)>%y*?u)=)MJ`| z{LuWALUtDt38{fmZI|pmS50b^QF&T7*_Y+`iQ0ik(saR`5GGo#1l9=>1uAQu0B)U&jPE=-k?tJ@&yCbu8Kdh=r>K9yAOA%V<+m@teO<0{y zcQYQ}P2;za4kx#ajeQ^Fa`lm*LG1l0fczsUfYj)-3|@_gG}P~XxGi+_1WsrdPEy~* z3W$}+;j93mc>I}@2jK{heKU?v5aqRj=~O2Cl8I>!e_EQi`}>D9ly`^ER>q>~Uegz9 zxHyFpjT(aFeii)@*WMp#pW3k(6=VKj$1%UPM{xj+8N!GG!WBddvIwVIC{klas@_W< z9GBHJ2FvG$v2aW|Fr*SVG z7Siku@s^;1`|kGFgQfaUE|yv^Db|w-%Zw+IwDTz4#O`AoS|eE*4qn2 zod3C#F7(vW^*l=f#u04wV4hjhijeP?$S{G)hV!}WZh3m>#=gxHDSI9d?NWE0G3{7f zPgUM_bsX+v5Bs^uSR2YVI$iQO{RMb+buAMnC*!o%&H#57s9v*Te35D$7Z@Mt>>1J! zuDUjqOIL| z-_7sDg=6B6f_I|XJ~nd^Vv9?iu))udufzE#3ym2>hD64?8q|bGH+$Vs;ezn>by}Fb z4NJZdYhURP9vx=l754^}*YsPmZ+f~qTpZD%s65q!hYBs!W9L=#=FD(C?JwrR|*IuyU0qiKj461i3Mp7e?59$ zD4{kBd9%56e3?-Rc=sJy$AXaMEs#ig3rRnE;sEv>8)|YZ{#u{WV^pdS7HY zBl@1(Qcj*m)O(MZH-pS;vPJ(;@gzrOnuzxmn{O$jJEy~yTXpx9Jc!&F&^GS=u7zB# zd1o~LI+_@=@`ud@1Ue5*y*^77IDNvus9o$C3x{&bl*=QhrQWTASKSqOJTqe-dn?x%Mb(28lZWk28!`>e64w1;DVCF&~*AudZ|6UzI{A?lsXdTjvzlJ zUx>OU*mTS-5$;DlHvyT{;*LXQCJ>Q7%cgvRFn#MLdwAkTlwy=GfXSa;Zt6wq8Sf1A zx+<&3v-El6KwY9G$&8vQL5NsQ$>UKQ8+|?1#=yxrj)Nv>~5G)~RY4OaxO$75^ z+2zFLZ56c#K2my38m~Id;q39{^%-lEub$NLNWa!pEaKmL*_W=$gGE-U37!-h@2e7=WLfOyKmTvy$Sot+(CRD5Rwd>R0Dkg0(aFe2A;IV!6sN$}xk zt3QU>6_C;E-l(QdsEOsfuFfPjH&$p`1ps_|GxDWAC_W6%GHlUM2fq?vLvA6o=Ni=2EdGX(WJ1TuqjT}m=}eO zT^l1skTfPFNRVx7YObYJji?Srq6v)tmO9)E*V#;1Zpr?~a|+}{r3i}qYw`EcxFtfk zr!}NMQHev@cDFc*6|+yNxw!Zg@)R#WJmDKWnzyvBWxujcS@$^j$a|@S5|$UzoYy`h z7)Q*t?Jsxu^lKJ>Lba7N`s>m-#A(vVwvZ}Br zcyx7$@4ecweMpbjb^G!7_~v_E<`0$wKE)56>>2qqp8Rn9XSkz@Lg=&N2DL61Aw9$1 zHl3!v4z1}CZiY3}6b!qhn0St+z@K7(9e`_-)chWUeRXr)8G)%q{AYh0G^#+h7t(zD zk~;pK2Q+nvZCvq)JBTXm4uZxjRbMp?1PzuwpBk7hP1=yrWR&^bn;1yzP^tac{a>44 zYi@xsM#XRqpUDG_IT(%06VJq`oS|hWVyiai;kE2&d2AZ&Ph117k-MqeJXTTLr$&$2 zYv{iYCn@y~;kWq>{4|D!y^L$JQXU5}bLr)6H+h&SQ8JjgrNws1T@ zf;+?Kj!oZkH!2(PN@bUmydDD1G=6+tI-$RQ*bc0{B$Jl?mf4-NN%i(^3zaMQcQ^zr z?P*<&tMWT1P9zfKfFPX#{>T_2D`wwQ)0qJ8rjh9)1*Qt%RK2A3I==G9haR0!B0*l! ziuHuLTwQPch@Tm27~g-?S?2{E-#LtF+eF>ZmRWs`0^O>X7sIWGg<+o4F66H5SB9>& zF;Q18`z2=irxfk^Q@(=N&8PO6gv~#Iw9{q_glN`j)@xiKoW55LxC{t0vXFf`5;V5|*^1QGNpw}2*qHy0a`S5}Tk8}DWs zeYv*Co62w0P2<3nPr7f@vlZlTn^B4xh6TSQ78zbyts(dJ%G7(#5elOh=AW&#iZ= zN}gG@>2S)X8eF7%5JSvBjMfTF||JFsTPwfY)s|Gr?afoJtt|ou?B#hX$#WkF2&p;c^ z0|rjhIT)vOSM8Xsc&c-TZDq4z;(4O;eBau z1ERw^GQl-0Q$S*U)~iywoJIcoyCOc*=&s02)Yw9%0TcvE$(Gr+Ziq~|0?ZRJ07B+& ztAW=#*Aj)~A}5dz`)#!6SNN21%h7gwv39ds>49$)nhDkoxe)ip#^cK3vk|5>I;T*N z_T-fis#2QkfW2@F(LVSPi3Cvv@aq_9f`R+G;^Anv>=?}>D43GNsHMH-7_R35+dfW| zh2humcK#`4O*a5LA;W-{1g?o0T(6(*WXhS$+IK)Eqxl`THz_&=77;4W0*6 zJJzEZ0XBPq+Z5b-QO|qcH3DsF(lp5SC?b?{{Mz zEzy7R=|>MWubhn6PJ-Vo!y=rB+0u{;^XXFIyh5!y4vS5D4R$sw`YHQ)C0M|Y2;XL~!>6iK4zii`$xpQgGe;~{3bfcL^)(wR|jku*50iQ(O*NoFQ3RYU%S_288cBgj3|Xv4xsvRjn3W73tT zvwht~D+!{hAU7s8G(}lNQIU7mQQptEo^q1@SQ1Y^>w#DreS1_Bb6L~W6_Hi6n5v;> z68no2)C_uUw~#7%xNM3J&`$?`AIbJiB80d&sj2a}3;16A;a6BWvglnwuDV(VamAc- zb~KfGU;k84woc2HK|`Gf0gCZ3&dAf+@nVvk>~bkxPdWy&jKaqlo%znRIa^3hhw%nl zKDKY}5p}gCwwCw9(`gFwonxdSX;c-OOjo9LZP^9z^>oqbxeNiM2TjHP3Ef|5^Z6i{ z6~d#m>&07u>}G)bk;|wA?dMj+@(b{6dKoEHevLu(-9?CPa;%OT%}e-=LD*_+&emC zdqQ=TlayCM;`blwN}qGf%L{EP_t^buO9%_Ws_wAYi>@x-eX}Lx1rY*n_f??puS(jJ zh}hS_O<@+5U$Tyj*&ub5QrkJeWraU|#7RdIXFh7RJ z&YNT7fq0uMckDoTRRc>(i@{Lxlq4MMo^hPJ<7K#2R@ac?%x&$)hPzk?H@aW!cQA3L zgTnM_z9X#qO#7C}uXl(57=EM<-A1If=g2JEqHIXdh-|CN<8a*ugI9o+8gNJps$y(O zfdwDswJj!!l7&f39IKvB#AG+Z{L;71M_MH&EI{8;B=~C;>FLYfX-m-eWRlm5N+Bbk zPBo~(WsFoeJ&RfYTg)o{4EW}UsMQinIRR=NVt040TP5$;xFFk4u0qFj_S@-^T1a}; zDWzQ5ZPwHm9UmqB%-JVnQHH+jn&+l4F}qrMyQFRnB!~RJY~v5pyEBfTEdPqp1BMKk zC6$V!ixLO?a~l1|d~NGoey~QkZxNl?+Vc3mA1nRXVL(;;tcuAz2==1;ZW&1#iEA&A z-~t-Y^&-9A-v2>orpHmFUyd1E8u^=hH>w-!`*e}^FeV(^z3iDeqIdD21Lv5!vJIbSaCtvmY~zA@ zWUIizBT5lod=$7%hRQx&XeOTfNM2mCMo(sBh)#42T~&^&wyWLL^A#w*lE(GcX647N zj~i%0vD066!i3fywK>F?Nz1~#@r9Awiiv{C9nZ3cyx*Li498T)Onj^0Uug+j?scof zxwk(YuHWX4TyN;cF8?|orlGJf{tFaGk(C{p1JFiPSK}P=j!@_KsSkCh$_w&$6&pqN zY?gJe`YbM5Fj0CFdOFjo!UGOscRhN!Z?eaB!v83;SHnWF%GMvn@_qXN%rZm#VCBAf z@jd~VV>jRP3^URnX=QhKq@;cP#~`jdcxxj!>?}G`;X{yY-R!9$2B&p0PTX{QV0ZWL z(y_~C4E*hcPU>)KcpXB;&|B2`(W~~F5>xIMePWv|$Axejm2*nhlc^D8jfljQMAD!0 z`-M$h$ce<0nb34TnPHJVsKB_G&ZW^xF7ObUZXC%1Hf4$ANlnb{JG)0Egjx@f`OMNW za`VvZ)oVsLQ~!6@Y%IiI^L9{UL85%j&D`zp=$Zmm&fSS9RwO)#&)n~B{ZsWwig1Cw z`<*ID!^9|cyX34x!0TJ)c3A2$4%&d|8Ka5%ogb>>qK3}cPMkSfCv1uC)O&9P;U$B8 zZC(Vc&78sE$cg=lE-}KEfV^AkWnxN`@QW7{u)mB{htl4g+GovXJFy4kinA!59F8CE zWqsuXG7f~KvsQQebYkqdoc{86hK@ED{Qg9UNjQ*0=(uIBQ?6}3S%qASCART$8(uplP_q)vcfKydEC?oI?8*(zpKg<$ z#{Ou&vg|M9aQKhXat1O*mcRBX57HKbyLXM(L-riU*RL;rO#%Rj{4H)X?+AfE+?YEn&%!mY2Am- zK&>u+%M(X+kjKSEGMXyx_?Jjl(xI=fkCsa2s07@V2d{Y{qK2=Ws>5H-r{fOfr$CfsL9{@;RTy+S&We9ui& z9rv_e7K?_GxZ=lDw$pS!I2zC#DpV168ULIvgRd&UGEFVrKflJtTFm$vG;HLE3W8%{ z9Q?-IOxNH_?GvNe?Z8S$Xzg4cE$a?bsi4CNM(GkKrLUkU_c}_=nLXstfVV+WIByxM&^z@iMa#3RC7a`{u0nUy|n1hnV z2)(*qH`km}4yYl3GNWd1sk};tGEXx>PX6voEmF1QtiqScI{KR5ne8ah1REExqgxA* z&pPXf-)apJODa>t-*Onn!T9+1+ula5#bItnOM8qnc2d&o+f}MAn#lObl>2(TSgwbH zE`RceSyRrXe#9~EM|&?FY)mcG6chT=$IFj;XqG3dX0z@5CxI!4)k}Yp`)M9ofMQrn z@@Ov>HmRf?lZ*dgK8%A%!)J7&1OMwPdXk$Lc4A7#s)wbbs(hDxF!#X-3o+Ebu0n0D z(qjXdliKL6#Rs7C_@8ZyEkQmiz{u-~ah)&%4yVK|Vr)4-2?0I)bKdjy%0ll*Kqg|C zEaidLYgvAQtrl5aY~@H>fyWc_eAL*dZlib$0U3dQ*|X66Fe=RHed2>PrmAazVckF5 z;>+Ws#ym`^&r2Wc#x#Y`_+Ta(y@#S=0mx4WOcdIZR8LHzjXY&9t_RExNR7fm0a_K%x!q3jgJb5x z`*wO~Spv=phrGVqegYrWHU;9&y=aFUWYy0)CRQPrM6V;{4d$7x#yw z@Mn*u`h$_5vtAb0Y48}p@+O*G<3 zd2t==AqNske9z5jHZJo;&AKgJ2${JUXoKu?@ezYh1e26evb4uvz~Kjfj${^7xm$8s zTw1ti{F;g4^{u+An(Uw&#IYLjJ0S4qPwF;XqeJ?Wam_$=05_RL3a#JbGySD}z12`{ zWIGJUb;-GQzWI?n3UyqP%b#WcGu^Yz5jxDRn>@a2ZUo6&@EB60J!5w5^J|jcMCY@} zjM977;pN2okMY-ME%I>VsC5{pZr9n2E-#D&K?lA8bmOPB_3P{x8H{haZ+|3P7danGZW) zoYcWj_~=ir7#@2JGcfH1*ngjCXd|W!7H4_|y}v+>U4<1KFDW;ebEUTT;i~NestBv# z5axL`U9hxkbXHBVd~~jzq^?RK&xEzS%^167EiSrzE}l>+SRR+AN_%uqwK;_Y*XZM3 zChMa4b&`Z>z?JDn)?@G5M{XU-gS!*XH+q#N&~9lxkD;tk6YrZ#?)1CGjxr0)8zT8c zi2iqA4tz^tIy=jop}69Tus7wqUo+s-uV1!}Kuj>p5y9T>-g%C&k;8xk5JAIiNBg9rYtG(hcFa?QLGxS15$1!_j>@#%6N)W7RJX`AbY{ga z+jkOWEhQ&&cxO;rtRq+aaa5$g(_NI}3suHL<&l+n7mEUP>WLBfCV)_;yUll<(o`awMHpgB_iEi@sj`i``Xa z3^1xYr1{MU-Pq!ET13c<>SV*EH8DT%18?_D$54`-(0L^pT;zOte63LB_1GOtREoyO zjtOU79!$a{H{TT4-byq32@k9zOtD6 z__sW-mnRDJpeD93$-YbXeM1gQy-V!r|2=j2N5WGNM5L6*5On(TemU4WT)@GU`b1Fd z*k}>q#{jQ8#-Ov|$xb8;_$1ddJUlE1O64wjQsbC{2*Uy(8zfQKG59bcJ*Taj{TxP2 zug*{8yjb{34B*?Vd$Cj~a|J0bwiSKG&`C3?`&F0l(Xrm2WJo?VMW_t*Hpr zW@iwY;)?xoV4WY-5dLWpA8!Q7GP=a-&P;?;i94+2-aEX1j{+uXIkRRst5m7YIKeg7 z8tKt5^HW$#dV;f1* z#{pPQjp0#yPtR_dV+0)$ssA=o>C*R3|2SA||CF=vQO$E z(u6}mV&SeKNBY$J@w9(Vo`*) z!pXm4OQM&9e*#Y9d^h8U*CbN;2xAFSnn}Eh6lqGgVJFRG5sBHt_!k}&kIlyM`hSCO zHd!v3ZJ9~{=KR$QKr-PBqJBh*yuw}8H)6OSk}IvSm$J#3R3*TL0o4I?P_%FbCBCqT za#kg4se+2ID(qsEfw$){whZufA9j`6{_*=bRI}!Pkw{B+wb&bQlqB0o$tb>nbVS|} z>=15@cS=mRmd^3DAxMI=nl%SBg?E%`9;3;u{0QER!lhj@;8r`nJ3=b8@xsr8G!$4*S%+UY>1GJWxH~OW`1NQwDN6Kn5^Z1 z)_^cXk42o}+I&+@4c)btj2xL9!F)qUby8w#iN|P3O*H}A^)pa_)_RPvk{TdA)B*`3 zcV2DNp9b1!@yp!$yl|haD?_!S9=Dp>JMVE{x|iKPEvEoZ^U zyxtx;5H_}`RYM**t3S-c!lhqp^b%pvibZ9sZo3qZMDS3!tP;lN z`96lV=!0X|i^55p9!cL^du`{3bFuUigu9*`WLMAj`sH?kIjYHBkM;8RR9O8I8H>#N z`g&~|@Oks{B_VF(3`>AkM9&ZZGFvwh{l<2br}}20-Wgp4lSJ=D19LculS{U<-16m5 zH943sJ2AGxUh*f~8zm_yFBoq|Bu)6yHUXf^L$+v#d!j*OY?Cgunq;;kXzoDu8FK&W zPl@6t9}PE0@V!a))&{@RsH<gO-tgs9zN9d!ksPGB(u?|VDIe}eY zyg{F>gOu*!CZF26E*zGSKjMXH@VR;^>IC=o?PqABUNGoL`fQl_6&nK(6@*oojMqg% z-%&l{&>37xl(ycXHltw~{IPD7sR{yYcPPE4yg8%kmj1`a<3n4TgUS16{cGO6X zyvNIdp;$ZHp?Oo^Jt86i;)dAk#V(2ikN}8XqBGs^)sMY)oE7CG)_O-OC%;p%of~KW z+tAZYy|+*`+q)+*%BC0swdwED#M8G_RtaJtVTD(1)1C*c7(^f^OvUbM5 z8A$Oq}xQmjG1&g)~juRb+oF68wRl?ADG1wRp zTzXAWSC;f|F0h==Gv;}8U~aKZdYKly?`-$HVVCEIh|yZe?z4Rqb1}xS8W^19g(%PsmBLPVY-^h-Qm_r zSTi&sMJ9woeNb!TXQ>_uryjy@R+Vydk;aA|JT0VOOx=MCt2j2A+eEAjg&b6aWUTf0srBa?DJRdU$U@7f_(rT!uQcP`w=-j;OC zM+09zR4ecDpB^P>dTeL>x$~F|0J5+B!4aBT!9?oWBqsf%>u-WY@wr^-X`4sg{xq~W zn;hUvb9e6x#|cH5RY!eaeSbX$qJhEx?i0Q_ceU`wNw%&3&jRqj+L@i3U{mS5`8Xt? zR`A}8MWpTpL7=i1rt<4uBNSijXH_a(x*YAJlY<^;Q&+ zb7;xT#-_}@Lu%d>y#TYvbnwf#vC$xYHW<?%_*rSYOPdOQB zGq?=s{tkoH1{MDAPiet0^J&7!oNzmN(hwAVNA0|}(t$L=&0o-#jaBQ?X>kDH!orPq zg$h%DGQS1Ba6bp!9$cim#R_0GOM7m|5yfE4#bOTBh{_b0kH$3mHCCn9acND}h4>1L zrl_Ql{h%l;syC^c8dDu}Sm&cSw=)Q>T8OliK zGG(csNS5oqKJDvfzoD?kZ1HmM*1G7$iU^#Dv=8apci+!Kc9BzhV(>KehJ>gIBO^Jp zSQ0e=>#a=%bOlHPh`-gM(J>(#qO0THHE1+D7tc+}>>fQdnJT&)U?)(sw-I~)E$WJ4 z>v#F6;+W{J=S-gV1IUJL&9FdT{+mRqNtMz)^}ulXsb@^7&%Man{tjhnqfNt{8DWwh zlN);~TWywqk+<$+w^|^N4q0!tJwX0DFE#cRB?s#gwrLOG0a zOl_E}Z48auyjPrn2^Ge}xOwCSUJ1&_3-|}z8Fd7+x%KUIae38v&-I$S6$JQNkw^0x z&FBSh!)Pei|i-;GFZB@xb7 z2{Fwel`#_!_ROCwxug;>uoxtJ^!SAF&b>iY2;?GwuID~NgHAf}G?+g^|Lz;5Zso?4 z`dvQc)lv5O&#&>WQAcT>cmFaFs(-4HPa5??mnJk##1WQBH5bT}x{i_WKT(UVv(7A> z5nC}?>a-TKZorLMudf94yGI+rHQQ)!^g9Rfpac0R8w>LWyS^i%*ItV06~|41Qowuf z7xv>==4`@E@^8x96xnF{1qsMGxvbgpoU*SuO-MaUSfaY#SX&xWVi8%mS7(kOZz2&S zOd?F=Qw}mnUcKST;az)Jb)N|k%6G?|?PMFu8Nni@?S10r=eFRQ%Z34u@6z ziu`Voh4j45jgBj`>ODDtKgChorcD<0e&UkS=#e76<@MhXWaC;{UfNYV8F#;8UP4=u zu6uYNvTpMMvreQKNJd&njsKBV|nx zph3VJqBnrq^|gP*VyH{Nb7F_!faz8XZEN$4$0RJ)GG{S?(rL_d?w$yBL|U=Wwk@T> z+B$9ir0}myq4#FgQ}l`M!ef;}%wGT=Y7_T(y%K}nAf}30g_v#JL)D*uM48EJEYHXM zY-jc|g1r!DWKr$u>bx5Dm3<4(HiC4KC$Fn%chOr#OOvG^eJi$pre2sglCAo$Up;m3 z+iWOAPo((^cp~$k_v)qa7?#i4`M)cdJD!Z34z}oo(9 zoz^L)QJ>gHRC%DzSGne`XU7}*ceK5eQO!;SDWvqwR={Yei>WS?`{@4ef4HYdt-1Zn z#y-XmW(AHbut%E~sUMS)7@6ph_RY*P-k`owyGUW@uwrZbEcKjWul@*o3*Q+-J=Me$ zzwzT$W9LnahGOI=&7|Kla!5r|L87xV#o!hxrp^-X##6H+d$LW9XW6+$p|Wu|>A{hu z|3UFvzoP_h!pU8bE(6HP&38s9l$`Db!JP*I4$1*?pw$b94&Apr^s!Y#Izx+mDGB73 z_V5D8>HTEDZ#pme=l_&ytzAt=h7j8|$&b&e%UtTT94kF#LX0rP-e}qe48nknXuXxaZ<3+w9Yy=N{PUt-( zw1-<)Uk2RWCtBGG`M}FSHyp&_XvvmwFc8?w%LZNWM#=d#dajp$`-~wpWt>1IaN0d! zXH&qn4CXL-L9xP_@fP<|nXn;_4FlKj4wGKEg;+M3CnQb8IRL!_Bb~~y9?#YC`W&~g z`xSu+ft2+Z&`Ib1st!%#^}?XkA{zTzqZI7awrw_xRAJNCeTumHfyH^7a9z4Xi|IWh z#jybf3!JXFB6ktQvx&NB!z_YmV^a+J$^B)k%-^~dUuEKxH@j`hnyZzi&2h*sGRd_U zb(L1t8-K#k0weE>JdXx1m1?F{8V*9az|bZm$rbUNFX5kF+DY8mzs}zGH?P&}Rv>@~ z0c2$btc|n{r9&nYaEFuz07l1qJ_cFN0LJEzw+$I@yAJA$sGu_`B|GEveQk z`5B}_+p#x4&$re>s?RU`tP%$~7~cP5IHFgz&y?wDr!nS-Z@O3y89(SQ1M@9$(I_>k z4}AS;W9O#+(F*EaW}+zinZN$%y>ZDODv<7)R9SAo>t%VF)!FjVwvUfa($!qkmuiG= z0^Y!fv=d#AfxLu=Jv18wK>U4bm&EM4yn+k?c*rBKFVAZ7UNV8ZldxEKifK|=HCP^& zGoQO7i7wS=fM(%EPd3HqfJ79Ts`S)wQ;;(v8xctR`ueu_E5$kUSXpfg zE{(@j!T!e!%>iwERkKToAn$)a9tgDkXMlYgS!{z3)AYTpFvg6bbDWE(m*NekUyPYfdX?1xu+=^;qjsgZlN@#_bJLA#=R4W#EQ>*%z}0bk=5 z9`H8I3PO*pFx}aI1%k*(rt^fU0)5EQaY~S1KD;L_QjUFK1f1xUkhIQpNp+-TBk%I^ z{(Hgn#kbXaz`sH0#9B#C30U^fd4Q9pL(tGb9bFW0fJVnCB^TRj8XH9jdV5~Kjyn|m zC65j@CJ2-iYGX9}EkXZ$K%*FPFXNK})0-NMABtd+LV#xOW@Y!;x=*!H>H!4sk5!jN zV*%24-ty?wEL9|X8;~MQF@l07>sRNyC&EpN1jt)|T>So^$eUD=h=7VIe!hjn-UJ6# z^G8s*6Hm8Y$z`;?u_o~69~LJ^Pf2f?ShNOn6Y~hSf%m>hU2mwbsehBQph0s>p$Iv% ztLy_3;}z=iZ-JNpdLI*QO^Ukr5QH(t8)rhiuvH=@0gq`BT?I^cO}=;1rQRb}sJA%w zAVO+~^F}@v*9=Bh|HLyVkagYeI(6Ha?;`kL&L}h%m?L8)DA2;&9>J(0NJtB^u>y-IlWk3M}907p9 zW5jK_p1(`U{>fz#6-C@KIc&jM+z~V6Q8)MO(FX$qXC}WxF~9PgQebsn2QjJsEdoni zs(Fp2uN<4G)U282(K%CZ-IIoz+Jycz|1x19kkmhUKN8?Ons(R6onC>p??TGKq>Bi4 zv6Ks_1<34Aqxo+A`yh4?ENC4@M7(=-pD&+n&F4NULEa00q?{zRsERKE+}62$z7`PV zYq469qTw`rRJtqiXk$J19;nCoywcc-sd6$ilX#=)562uAmIwH~yu<`V85Vvcm1-+b zz5KUy1L12t{9=y=yF~ttcb(0@HK!7)y%u|xdXra`mdlYIe-z88QJ4ZsSrQ@cAb=Wx z9Q2j>{rVK76E{7&z$bYU~Tj3(J3* z6F;-nt7%ypM$0en%Gl+heF2}07{M;s>cgi4f0l13b}Y)d^}E2SvZSR^-yIS7Ua}K> zlX>|SBQjpF>iTN;dcIi}kec?bVCC~bbQWyD0wOGWnfrS8@5eBs8rGXgY|a-2X``F^ z-4jZP4Gkm!Zp5u73f8rq+TCMKFu))N`Xk`bSA=Nc_9?Y4$&dzZb}Wa^jKeG@re55u zvzY?l+ebvV1u0_*yZVPGGH)8MF;|}*abvo!E-%I8wz7Q0-+CGm{Fjk|$T(+R zUEN+4zfrk;@}$Q6Hb~tj2P}g3{7Gz_tJwDKKF#dN+FlW;#`7Sn9*KkGI}d4S^RHrV z&-Hd+Jvs9aINuH{QMy1jX*QJBtRY?TKc{~Pk!)Ij(H^CC8gT6E59GL|b%is&t{mB0 zol*#*bdfn6{H>|yP=0AOJo9okcA2kgO{z_z`zEpw-$WMDfcRQMF#)9kXb|l*GZlNy zZ81K2hpO-!s?SbZb0m@D1egIHam70ht}Z+S#6PlXwf0x2)J-{vR#2Ua@tLBAKQjsR zXcm5F36nhd{`I=Mbb_~Jo5W`|6(|~nH%BV zw1dYd5_`Dw^KF;QY^n5LJ6)d*sL{;8PjjZ~h))OwPMjf!dLsdy{{Pr|%eW^0H}3n~ zMz^Abq@W@>3F#CC5eY?UMwimLk)yi==@bM+X_$b-q`O5*I!43jzQ*r=-`At-*&gq8 ze(MwOqwy`H^o4A>z4Z_+ZLgrI@d0-Ut%u-_&yl6?*hvMej$6$2)#bSqQ%s}_nIrIb z7t31ey{cUCp`+m;vLC$2FnbcbL4N(Qq_*9K%W#SOh&0nf@awTyy$Dq%D(IBmkAAwR z{YIn|x%m_A*i+AO+j9U7FbdHWO*^N~I(fdQ=DYL<)pUvsxQ7gG7|>$CE5oy5eV1~N zvosk?hkmOnT|!H4jub}U)w=^Ak^Bq0c{y@ooKF_YHwA4(ifkl!N{uIZr`Q~aS8n+= z?qYfNvM#zT8K)tybzXLR@(ov{Ui(j&I% zkw{Vs=lN@D;jD_v}uk(aj=JV4V2?3J1f9n4T+rHPLFtE=!DPZ*2Z?HZ4 z{_(@e^5CH;q15K6gFIu-*lSakiKTSM{w)~q%(1eFwnw+2Kzdq7?uRLc{7re$k0_Pq z`b_E-1G8&^^OW+BjKcz3`vyCa^rKZnLrcRM+NO8liAEXuA3vtGT};2_m#8#i+#E)UqbqO3Mi*Z(@z%95=UxtO)icf zr^gSNfEcii!13Q8TILFSCCPQ+hW-9u5d|`rYjz?wF+2v5pv?2Kwos?%W&a*ukn8?@ z0rKclmGg6g9VWVuRz4mVYsh+6inxod+ew=o{qsJ_Ju?Bv%byUWm>!V)`iCG-PPD(SV496iA;OvwyAsFiXzLxHo`Lg?0_g$qy-UnsW zQ42LrK0d#XEt{~PONFGG8-39vRdAENlT6Crwm{n+^A{TLZA!29~HGwR<8?!-*@{JH1V64J2QD~MG@Z_0ZcA)c8ihYi+R~1*iHXrQ$#rvdo zN15@zF-gp|^$fdt98z5aW&e#zosrB5cYS9_PrCUs_NpkJFI?mFe|FU5jYBRr>D`6P z^O=!umf`Offyr>l?cWRLP|p-^V7(0S)^@f5LAgieQAT-TgHN2p=QUKR!&w~#iqci5 zO^QJMST*m#Cln(Xm?n)BVOHa=3lSW6;eE9DZuZ}x(G&Ux=J!&yv9NUdn1*w5ufDs? zUQ}Fxj&R+7FBTZLMrx{oOm5SF8yo65PO0oHQ zxXCIf;V{r{5tbN0w z@K1i%5Au;J)hdrylvB^NORJ<;D{o$OQ#X0DqZ9KjoWk%2jD#S`&(~SJ4~9x;snkKD zK%gy$4M_HGHhcapc--sy`oH>@RTQyVT&j~Do=00#JF@ZO^=+O~RenEi8nDLayq+S} zwB+dcgZ1@P+xIEQNn!&6&fu*>4Le!Z9zVpz{(PY!cLETwNjdb{z{c4@5 zG(5_cH}KP1FV4FTMOzPD>#U?-vS40PFNi}6PdM;vKYTyh`w}3q);j&{XIQ@`_nE^@ zW_T92zP)>*CzS}p>^5RBcQ%$?krEsiyH%0LWJH~FN~vch$>K|ovjYy)UmHwo4Xxa~ zX^jqU>YJDt<83(09}x4#T`Q zuf{VyBn#oIIyQl}&wlrW7gQdME60qQ{%iGGU0=6(rxm@FU+1&#S-taf){nx5jEJX0 z{)oHwZO2|5;6$Ttlbe!}g>n?NJ@2uNNF?9WYC39LDDQ~A6SC9PAvM6g(v?*eANlA} z%bQPb!OHyRGv`nDPwZ0_eJ6(l??NhYFvzH|t!8&m;)Xhpuq0*QYT_L?T*haDz+325 z6UIdZFXp-qaaCZWM=m?zSKl|q`HOJu?-m}*hDy@@G#QLykiwDgB!GPb+GAA%IDw-bDJ=49M8X=j^F{ZA4b#C zR#4g~b)4EI;d&~#f05@V`Jhc^y8Rr5-qr>j=AgXy=zu4@hBV)!I{OQ_BBD z2A>sHUb%5v_^H7~s&8Wk>R-+n8Z$4S}WOiGRWS{0f5 z>8oODlX8l(hMP(ZhLPGZ*Vb2m4<}NVeE-u&#%@;A=Ad~SZZ$Q7pJq(YpOtM1Un?v9< zU%PNQsFBJqbm=JfK@Q&HAXU+USsd;zwA-RL5K(V4g1}9flT?#fUkFm4V_ABe)g5#G z%KJZ8bI};*ymy!~Izw?m<~A^#u(a`PeIY*U>~aBzvi|}~bg&c62B;pDQIpa>x#a+; z7xLtPSEhUx;Un_TC4TRx3O&KPrNv5bZdXLG*WIK7V%N9*-nE;~d{60H$4V>-2i;v! zi_d2dOMG?ok0)6i)eiTl70Jp5bZ|HMeA1(-MKO!CSMXWmW~?BA?8KxAD-D&M=}WYP zN^BAX&?km{FPB|y>-F?_?$%_2tawR0+1}F+Q1JK&3#z46&*X&a9xAOODMY8fY-=Uc zb9=9ik6f&YIlGuD=BdCdu`fjB7$H7veI>HZ^g7Z~vPHV2dKPq%;Xbp*v80cqdi7Hx zDwwuRPs{5?|8YyL{-;*|zWHog9p)C9 z0*uo*Ht!0r7b`#yF$Mwz3D!Y^25R1T+24@?vhBfJ4M%h5kxD^Q?ZaWZlkpq`2cW{v z#V9-sTKVvNtL2>>^J>%pedmI5?)|=Ic1Cv{Fi(>0HJOKx)K*?Dyw%abK$mYSZ~1+F z_N`0S!z%0j(Fns{nNIGlh^=xFmMCzLbKqk4t8oTO-o@Q>k!wYk+<1;Y)2+oe4Qfx5 z1&89yy=B6{-eyP{Mjg9x@N&9W#tp+H>*pST#3l^ z#*X|u9Rr;lT@ozqCUi`V=Mqic*PumMU6{Z3WDAmlf1pp}i0tlyWs4{41L9#~E?v@`s2nZNN{icNQ|?UMCZHoMU1 z{j6knb)pKHsslAry7l#gFC|=^7NbF^<=Oa}k|JB&2-37VEEn?>uW4kjJ}z$=8Hp=H zu%zU4hg*=Qdy@h*iAib`n(2Z^xiY5w=VPnWf*52UK;p+TDby;1BUf>Hr)qhcRC5p{ zQvnoSj)|4^mVFw&>j_&E+i*CdmLJ)iTCDJ`Y+r~H9qGqtVdMph30~<#5zN`{J+*}f zmXz*;^8YMw_$+WlWFgL{dIP+Eh*p1Kac*wi?jpP#Uv@U$@S4-^r3wWdxAui9EmD-- zei;;ki+m7*v%7zhIP9OfN^;t;M%aU(%RAe3^xHv1(eI z8Xe>WOksQ?_6@vzweBXc(TFCrtKRifVfcb|F73GYo{>P<*Q7J9QYrCTzDHV~hoF;% zMbiD~nZf3d<`3(U{a@(*XRas=+vcwo!cMZU+XSXQbfewu+FPjGIE0=?{p{& z<=qPA1=`W+5Sp;4O{H1^0@z+44*sCkLT+)uC37~5_t8U_>VDYJ{ z*=anVUhLs~0?LCdDLKcfHrmeZ7-^UL$EU51du`zLLEd*bVmOR`@w`vHyu<_*q{y;h zs6m-v^ajPaJkz26u7M%UQGAF1CfKjBPf@2n@Hep~K0KRRE!L*o^certR8g&lSI0)R zFTpuM7|&`jCR=oOkL_9!QSGPd@kHT(u#8fDl}PvOmgM#PXJ<1@>UI#c6)g zkVkwjh!GPPU~@Lm@ceZxJmKETyBlc~_7mx2eq5KS({%G%b2bAZA(_wWe|lZsj^Uew zF*k8l9C$`^}>ZPbRn8<4{{LeLlNS(Ayn`Wp9DX+I?ihR(~$Uj z_#QD4in^yZ+i2!F2Qiv;P`~~{+mL;-FLPbFFyqNm#?H3YW_|9oc}4&;s3A~)d}X`| zLB7}7#pv}*ozrm0%49%4&~DHkQ+li)fJOG>Nm)rA-?jQmrrtw;w)sZJ=b~o7;6&aX zGnliDuij38{h(Z6v=2C?=uJ~Tn(>2r4f?t5noxuX(=q3G14oX!7xQrh>otRM$yd0* z`{jN0_J~TP{lR^78aA7S^hY-PWkG{YSoH1!(UkAL{Z-V@TwWA=;+8<6JM{|gBvt4K zPngO$$tT|JrxE={b5fgiE=EXY)0R@{+zvVfh>&1Qr;y8a(93LkS3vaD*hGP`(QgvZ z1R8Yts{-1`oIT1;f4)7(4x$ z0Oa%VPw>ztLC>j^;@nulbsvd8#4rQZSyyXWd_LztuLFK68Ul1MOBaf{Z$a~+???;3 zu8(~#aCwiI1n-KLD`dM5tKLm5b394fIhj~c^jUg}+FJ3MQjBp=FU@2YDQlXWL-=!9>Y-aVIp#2pA;14K8Vod`kW*GB-tc2qA7rTC|I1bOdix!!SfGmZ@x=9H_9>(m&HqAA>27j~rmdUab z?Unyduqql!Pi7CSUPmA1g@Ll|P+_u$&-0%|Nmq2ufz&IMjt@FU#e_Q8C<&V&E?4qKM>@otg)wT*!NK*-Ix(0nL&~?y9}!j(2N0ToYW$jc1O$qVrC`l1Hr?G-hd2~&47&__I8klj zM!%qWri5=V5V-N#O<%=Do#C4!`vJR_%>Cuh8f_fXd&CgzcZv_ilO6wpYavv7(WN?R zPLe`1a&AB&*T(j@jzREFIOq5F%27Dg%lEjzDDZye;a<9*It|>b2}mWMQowsmJ_YNh zeKjAT%4knNMIenA@Gob^>bbHQ%oa5{?Rz38Q*gD^MU4v87fK6UWVhTRH*HJ-3JcP4 zRPg*qTVd_t5UYb1P_s{(%xTmn2J6_WReWul^4UX!+4nfNs*PfN-j5^8V_Uvj(RZ7; z``fB?PF4bB693?9fQd^$qHvYFXNJ8y2lS&a4G)@fNi`^0>*UR> z*bJ_z!Uv|g*sWBAo2QhbCVN~9Vy0s1{b=^PGbLR|N798_C}p+)2;f&%4VKPfxq7I+ zY0iw;D;XwLYuM+Pz4NT&yETIFj$6N|ai6qJV6PHk;=H6MAW=cdC~8(-{~h!IRHUhu z)W9oCfPT*ezD7y)JL(;Tci_fhjZC_{5pi9Iw_RwY3dQs$XG#i@jB?6Yd)9+|#rN>e zK{NRUY7$f^v%Q4xnQt$~LVQ||qGhbAP}+jA;$lqgt}X5E-NOtUN58*)Lxhz<>+cyZ zHrU~m-Jd}YTrp}O4gA_j$bHPc`mwyBj()4XIu&0wS%E5%574ai(HVqoHL;#5jU{b( z?d8#zqNpZ9z|(5pIo>B^k8;LiIEQEaB_i_)U}ivDNxVG%(2Mdu58HUS^WT5hb6e1Q z44CkY`sfO9c52y%ymN=vcn7)7WEuen%0OSb94)+(m1O^x*nO9Sou%f>(LT8Ud2Ad0 zd}~;Idw?nD{N4K99H_A;xtn}orpsfMNahXH&T|v#ini6 ztd8TsHwsd+L{H?>wyt&)w|ZCx0itF~9>a;}(0(;qx}``5(dgcAyRdJk=s(l zyL_kaN&{(uXVL%Y1hJ7R0o}-T@ocwd$&rY*^O@tu?Qe?j^-`>|nlpt>2?mL+mcCJt zl7lXuNayg3wnPNcnUh3HF~i%l9G92w(Riexm^#mwpkEV7>0CzfDOUoq_xWPJKcFnz zDo(PLN?>1{n!R$P-E^|=4DJ;J^GAS|8=jmh3cPzQy=^%dG>MgFB~*irO8H!v?O}3b zCXdoSZU#8I>rLz}NHpzpO}YEhn=#LEWPakv=!|c#nr2@b68mrK-K&&6=@Ig|?3TLG zD={s&ynzpf7;FqY?hXTKjzUOY%0pPQOYqna{qclMNV?zg0k{9g(~xJY8Zj}QeBksb zqXX?`6HZYR?KV4iC*o>)*_-sQAil+c+h9YnM+j z_=ebJFp_zYRck*!*~z!aj32~|Hx#P|z}q~Xv9 zT=ES92T=fWOG=ct@mz+56aM16P-owkl~Z)NukiCGF-+QfP~~^F52~q(0?kF2w+4Hx zx!P`3P1rYYYTOZ-y>OIxkKt|9PR$^lvY_(?FTReAbn&gz8oS6Xe^%0NVE*A5%!pYk zF2n|n;;UaYru05_e2j4k_;Ks8&(5*iS{rwiwc_<-MQQ6O{JmQJlP`MzX$HS; z`XBBcB`F_qpdf8P76O3G%C`tu1Cn-8Q+C`}ZA~YuFbeW)1=&b111fYj%!ngDst3<& z;Y^hLMD|fRN)~tv_~39zv!cGTl#=uK@cY>;9_brKdgY`g|HyK(!d5fgnZ8% z==^{)8O+A~htN@LB#UXdWoo$vMa5RInBryr7Wq#_GSvbxI@ynKr)&Qzb!pD|D{Ie$ro9gmcrgwf7l)7QTB}JueVg5ZcZ2Z{s>bW>Oas zadY=bp&9AxTD7n_94ZaNt&=}@g8n}fy8On37EGvRp8yBo!WUi!NJ``#S#a!rpS{mW zeeLzM9DX`JMfRH+YRCn}ml`wW7>_KIva~p2R>LrC+HmHg!Hw_L! z^(V1DNjjp{+Z}$SXR4Ydwl-zI$#8SPo}Rbu#VgvDx57h`qW&cA&;S-1nfGVU7)M1me(*@X#hW zs~)ZR?d-3SXstZwn*;)#4C%quXXd7>W#*eSnUFS;#RE+ubJV&7>S#q0MIS@7ThYNz z{^)0r^GPmHw64D@z7hVU`FV3;{TKLKXyeJJg}+w=zN>W$h&$P4 zj)(V5zP?xdadk2hQfQdaamMfac#(+$cj zAPAGv!{amV(cT=A6sD8#&37;-4Q%~cPCj&FD5Fj8f12CPiPK^K+BpVC=s^K8XUGLQ zG!a!juCRQpcn$9X9m6$2f2%-rz^-XoEJ;wzv-FY=)PKK|yL3WEsURP4F-Vns(6?_o zgvywE(x1z)n>O3&PcQz1vi5 zkTr|N2bn1AC)-OXbMl+d0jLk9QP0LDkw-=L-usR!EVqIcx#BZ11ZB@;5PV|aGiiw@ zw8*7|K5($U^z7aMi@%IXCg2(SZ3<&7h$#?Z_{Qk+Oc7v~lg%s^ zN%v|=xxy*r;Vhn)8{yaIKc%e-7I6A<(pRzJJNAOYt=zqupRlGTdVYrE3_H&@SsJgp zaWLD9$!&RNX-t@1yw@Mshv`3_>$NNDH2{Y;--rJiuR$`cB*)=v1?j%Kk|WWisj{?K z>W%yWgUo)N|7urtvD!2IEogkE!Hpy$AL=Am$c|2=4?YYx%bys(9@KVXM`+@vfY|`c6 z`HefjMw1tTdX-f5gV(Sl!cE21)@$U<2Yx6YkL^3P@pCLgk45<{4t}5h?~HH6g^;~= z14E#1!OVdE$BiC}=i|{vGF^!ju#uCFPeMpGaZV6?%EOY<9rx7riF+>p(`T&wiowU#lcS zy-o0loX?Nl+AJ$CpWbO!-OV7!~^L9QqzIW=ae6p(P1z~Lk`kWdnFI(Ykj@p1D~ z7MB>fHI{^`B|<3a>{A)`2c~Env_`$3$3yW=+A(9evm<)I=cw|M@qFi^e}~7ec9~|! z{sK?spq%U^p7OXq75Y+mYg}!HX%5rt+HSdi;aT)h5BDV+>EC!yHPJTPS}0i-8UPMd z0mqGfXk-P%T0#yVx*3kp+uOueD}(SspF}n5DC3B`#)3e2pYWgDGRhF30(Z(80+e<3 zL0QD-wievGTf$<&E8?65&JKNpl1W?2zthtzOfpYg&#`N3BL$m6DFJQRBE-t-@!e9d zww`cYMXMU+x>&ee&SFUOlsMME6Z?rq#A|tp_V$k7WDk*~a1L^K2%&St z$L973F@;(y+$5HrPeDJKm?lf;p0u#$bCg0UBB16Z3E#39b?~6i?($v+pg3javuC~J zk{X8y8tXnF#-H^-Jg>OH^(p(k?wN1*@K$hT*pgZ5g#Ao#&Q#W875bwwFmTqaD)MFX zukYpGEulOyy=lb$h1!ioMyHc~R@z19`o#Sq&TYz`0VCnaP^5shEjJwZsx$(=TomP_ zi2DJDv)`&?RN_Ip|>C-)<`kw1WJ)lA7P;6;@syXxVTN{Vg8yMY>hn0_Gc zu}ibTz}>dctiKlnJBtbb+pw)jKAurU`3|K1*E^1&kWe3TQsfV(=H{&v8lVHgK-GBI zK_VW(CYL%gQURL#k>;;UYwsgIlxoiQ&Z;Mo##<#6G)!RD;J7ko!~kz23p+&NgYC;QZxLxREEt2gCS{|M zw`M$muIcoQ8Iu_mw8^e!qGd5ERs>uj=1?78pHN&rL;NGH1#P{9qI?2dD#2Zc%~A3SXoB zlVvl2*zU)rU@06{#%C?A<1UJ%PtRi*=K%)Dci@M&%T%pnluhc5dXP`ODjgGeJBlK3N!=!3Kq8zd`Zf>e*riWu0tKn5zP`{&zxK-<;6S`p%`e6S@KbB7u{I4rV}s zOcwt4*UTRX8ZQu!*-9}5cQA8lG?)xgrDgq%9UYTVMBW2EYD6ieZZXQ>^e`Jm*qCR! z>CCUs`7C>!BEKFMgh4xe3C@!{CU8SUjyrrWI(!(}P>Z7ssQDTW-$zL86URh}RkT*r zi}-pwCeN0wFH%@gHr_BeebPg|c7QUn?@ln+WtX zT}#DJf*r|7D{+aq(|B%V9gXsr;_xBDDJTyQyw^W^OZWVUcS1BH>`(XFe_^I_*`57C z{G_4CxxZ3`wm=n;2V6+KhmDP?z|W&^ZR94(-ZV zHkHDA0WRt3gIC0+8hk6s?BHaZ&;BA_^iba00g(Xase8Am1K<9`&;lNcVa`_Y+OmoI z0dk@aN0NvjUTHWPNvz){$9}+#s2-!CwTa*@u(=~2;dWgvP0dOn(DB{9>V+f@s*#mbUT^N8@bwQ=aE$X)T^S;T7288{GO?{ z#I1gI+jPxLe==xq$gtdcYybVPhP@vq`zknc8x3UvXZZVQ&+@(9Aph!xKqi~Fuknm- z_e+EbUa&qj`fy00`AlQ=L&Im$<;9hD^K9$eU8i;WW! z(g0iiXJcRKhyVZ?w`pp20g^GEr$TYy#foel##5)C_LGJl{n4x(3D0;YXpVLrK`-XD zZM1Rzr5_BWVC+)r<&UJuCx7Q|J~Z^eX09UI-_|AEX;aV8SsD`svypGsld$(3gM_XK zr5~Eux#geWMv-VpUUXizZ6;)ZWSFFPpW7(7GZ{dsMZ|7hZJK_BYvQwTf8Ui(>qxqi zizqI1p3?CJ_I7_ajv9ZoQKCQHt{G<|lNv=uj#Tt(GU>rztG=?gPc0;7da(?Tw}dus zjja=pb3}eaj7fMNS$8|ejMSX*zSLS%_9d>$g^s5Rz;k{{-)TE1+t`SdVEI=O?`tz4 zy?(&SEuHFnS1O}BXvw#UB7PSe+sI>Ik3F#Uy)LxV%Bzc zS$%2o7HJa;1~SJHZZXcc$LRlRRXIlbxXQVk^yT z*Nb;QKln5-o{)#i2hf{T;3|aU8aEoD8o8q8BV27m7np0OWX_hp^5;fIRqQTmA3~UA z!+(dqH1@fJU-go3@CS?b>?32eOyHoZ3@RKS9V#!rxkmT^;&fA_-@|3mtO-p8+hcM? zL4E*khNy!;1fVM&-zyx6>xGen%={B#6lQGz-4JkTi*mu{)l2t zE01}#Whk!BDB+fe*0?UV_x_%2nC#|IjL#r0j6Y#unlKE8mrJ=wGQ}ntvNFpKXxurA zvZRw9_ebEcV$}9sY<#6<=(o(LdDgk2f4*^1+P;^S&iNh^aLsCH8pLBT_$i;B|LD=2 zSV5@=b`OWTpw%+;uD1O+VK{AT7#Kv6HfRsVR#CAU78n}TZga0u#uUl2toxtcpG9(4rxlIu#-BJCn8g9!ZyoXy)+}*gA(Nj^&kOG?Lg=CG%u*gjHGAz05uV$%9iYom z7hn#{SUM8c%_@s&cbbXiry()+YFT)_=oh8r46>jnY$t|FnU4qX=aFTE-EFSuJAQ@0t5ZIvkw^1ouArZg-{~_c#2JXm+mF)Ed;K8G!;F#BU|Mg&prEB(Ab1=`18E=Q#sSqzL9u4L{p!gI>BG!*a85u077TPrC8# zOZR#kx@hP+!C=;&9=D@fKP!-B_vhgIviAw-9X-CIZ`%+(*<)izzCyxmo4>H74}*>H z1BvKJ($)Ljz>^v*5HA!_dE~C(9hFsBHlzlx1|($bIrssvWC(6tU9pH@S7hOp#>UMa z`CRtzTzC?G*uBEx0c{RR+YbL4+OxP;nBMD?uupDC7K-)8j`Cj*j#v;ViRTFr)tM=KV$y zr6{s^9tMUd#cLp>4ie=WWqG|orMoX!x`}O?a!M2A0vZQ@>-o8OeXhf&f{Nqba@K#I zwwcR-sWh20YUYBX8S)9eKN-;5gAdkY))C?^*O$lc9k*H4t_v;YoN;)A$>#M!C;>wE zndkQXt^kV<(edfc{_magrdThX9}=Dr(&M?1pHVqqJF@(kOy1hy=@!7FL;pw-(ldI% z6T7n>N0)!Yguq3>jBsAV9K@cTRW}>iFijc(Iw7*+Y}eaD=WRIh9cp;Kns&CgGAXWf z|11m^Z&f~Web)`JF7d7tZ*Hu{#(zafI5QwE{Quh8@A~z#wfZ$|eGDd`Jqz@M`ERU^ z5-iwWi;+f9cc|5poq4T~5>I_XKWj%eT`DH0t^U|uTktg8)hBegKHbl9EtQzT+)x5; zs#zvm1^@Qf4m2AZ@6CuLS4I8X)M;lYL047>`gP6?xvmV!fZg7_Nich(Zh^>}KUfna zpj$0gOFR0ie*R>r2&ABAQ@`VlYw8|P7o5&mqn|=)_xS>jY6KHEu$@Q9GZ_2F`ZAp# z4AwS$yUO>Bl&_N+I*la=<(xzL^I%)8X`+o*)a$R*gt4~S&Gl@{h{tIGX07kmNzHlK z%7UhH_bKoW0sS=@u4&kx5vxWIXUk_AQ zV=bSa(Vd%@=i_MIF)=-(5FVfm=yb4Qvz8^6wfNnrFD}><5rDk9tq-UZIqFlYf(!kb z=NQnQqC=1}kb7c@+5gW1c#@jNC6zx2>NhO|Cxf3qqqKT1f_{Jwyh!&pQv^x9GVmgv zdtaa$!mF^kmt~mjy4!Xu7Fe>Dn9X?FF)7aM5KXW|BrAE@lg}a$u`s%3+ID@ob43~7 z@P<*^D=X=GJf>l0l1ESHM4c)VA)|?XJR{L~x&ycIr^y7*G z*(5z-w}C2Q6*!b$rk&KIIz%y5L7||AJ4T?3;&6zoLrmy87xgKGX)r+216xIqQA^az z%Xik+h&Zr}zV$5i_#us?N>jF;t}a(e*7v#qSk_~A5b~jBbDS|o2~zTithLB? zkR9_ZmDC|Jf<(=hX*Zd`o-;|myq_wYz_C=7StV>^h5Gc=US$#^mgY-^obut znP75!%+y0KWOb!)>H}h3XFOf3Wx-@7nxuaCAhlvk+)yay6iTZ>O&Bh7mMgO!YN7UX ztJK}W>fY&_bb)t@O_>^=k3UW>+NgnSBnaKKt9Y3#6Jr=eTY5b5Yff>>D6T_y-xop6 zkW1}m0zyhvQ{Aqy;CZIbc)&mQS#|oRf4W=}+wpMjS+GU$Qn{V0#+WA~{_c@17(Tpwdw;8yc({=4~U zJ{^rOFXE*O=s9RA|6fN400n@#Ko$>KDp+TledEMW@3MwghcJ6hKRYUQe>Q9{ceEpK zwq-Xel`4-=R9&Ec#^o6lH4Vh#(STl(%;QhTQir}J(}u)u+@bQ5^kYJm?7DzigBbyV z8TZLsgZK`3l(JV?CsFaZIvmO-3o1Oe`dQk#x(9d&FL5dd?BYPJ=_?#Ff39M&+btg@g@Jg>8J@{l#r7?@A&qT< z8|Elu&3WQ-SQ&=2)^p6I+g!d$-&?#tnxGvsACIL0Ek|;m;g(+weD^nDgsbPe-!}aF z5N#}F-(4;JdCz4K_Q21FIy)#@?2)=ElhZ`N0NjYhjNfn~UJa?>m3=72=;y_;zQ_W{ z-O=L2-sa1bx|p1kFGn&#FZw5`OID@-X7YG#F=W(Xr9XU%-}o;l+W|f;Va_P;PF0|x zVlA8fk%^AcIfML_e`2P9Wt@K`xo$T0nWN9MqU!#;!<_J}?mNd%Dql0ne6F-)EF&Xg zpZljEj6mlhuSTmtFbFDrf*cKU0N{9y)(|x-B1SnSJv6xsykSq;i6ru;Gqm!vj`YD@ z03u4_UC;}iD!P3%6e1~r_enn%G6y#l_b8n04FWa?5q%i}c;77}JhETmSsokvW@7HFlJv-bpm)q{NzDJhVU1yC( zinibfAVmE;`ueE^m8sg3??=mj`_^{nbEr8)Rm_|A4?H$RF3U1gW>!v78SIgLdb4L5 zZ8C^u8DXjMw{Q9I$|Nj{NMm2ASz@jes?2p#-uiOB(d*vrhmfSOmlw=*B%f?5W!r7>-x_zzH3`N~OxAlBtiny1l*>|TD z(f4uFJMLOnA3lWNwiv^-A?z=+H5jAqy>VOH-wA*1wKSiWw~V8~uQRMqO`=ew7JQxV zK$9isrFq`zCuLO}jydt>Dp$PMJsBN_e{w6#mu}$w&%po|2N13Tum+vSV>p*HvlofG zd|3oL<5Kg46W2H}K8S!|2Lrd*n97(z^wlEUCTj-?A$7N3x)6KZZje=!=?`x({70*( ztcF@&)4NyaI@Yh6`h#o`?{a*9;28(<_a7Wp^4w=FctOkeP^-A{G3;zui|&b`h=W%z z^4!m)4|V)H%@*(kT3sbn;~UO5rwAem2Fj$KmUBFWUxM~W1d)F}FQ~}u$n6R$^m$&FR2F5|_plqJV!6bp8l8hg+IIH7@*4-qbuK@hrpZPCGZ7aH!b@c>qKUJYB&9R3-p67ql;XW zy){SjqAyo}YmOdu0>pZ3EJ_xP8fCqoY83higEww>y-D35XcW_RY-*rJcL`C-T!ilN zQ&AFCT{*sf)L~zubFPF%vH1Q|$atu%WvGHnZnO z&r;Z{xnMA z$F|fPl!j)G-=;s=dA1KjCBm#mT+nuSn3_&@`3R~%BZR!EbIOfN2HkH{1f#Cxq{Wl8 zV#9dgjyroUU3L?2(sA?@4VvM);xs~E5LBsDUmG9H3`_^ zy)yw`O88HXXwoh(ybz~wUFKIwRiF&Y)>wP0IU~gXNqt6nR_@AVFbX1N#4)Dit!`sk ztj*HGAKG*Dc{1n)1lKgBnDQD=y1uDqwtX}_*WFLgCtyHV4UUz8eYRO82nUiH5jdcG~9}8-qd#S#wFPUF2EN z9EX4h>L2hjhS|Hh|4_zE?G;Q{AF=!yM%jmhk=8dzU15$y4xqgnQ5=^AYU{MiuSVRl zorxJ{xRQg1%g`6RQ+@DkRgM%0Mv|bE>B2foGZ!H_$r>UgFzz2fv03c95SHsxciR=d zchg&<#pV7AHkUVzlvl*6@Mx6INL@tE{Etw!m32JquMFs}NTymnVBE zO8SpA1r!ZaV*_A*EFVFvh(*w2Br!4o9f}!MEnk<)vI|-Rr`#Sq7E829pdtiKoNU~+Kn83&pBsvk(_yNjCfUeeMtTXCT z9XK`H3sdu|I6)Koj7aY7D}3zW$)r#d6W#auBl`=|5KTx|dYQU+zU6yuEK?m~E5F^XD_XaG`-|jaZ%) zjwzc#Vjx@vaZA{yR>$pJqk}NlXO0lI(ANb~2UTOpt-i8!Y^4E9I;uZN=f75yc4lUG8njAZ9m4)4Z1?oWjMlv){|nS8PL4s5tvEXfk0Ws5iJV<2fgK zgtn;h%Vw9Aue%KiOxI-TAX4$FNlTNaH6k{WBg@W-=Ig%u&hQkK?176RWvqSrLjwt{ z0mNRl6u8h^N`EGPz!?m~at`2fVL{95gTF<+@zBpbTQ{RDStM}~k(JGw*PiA3w)Vas z521$VCWo7rGCfGI`pz&f@Rh_)y)%!+_pU0?+41`%L!WPclT4`Q>zW==_J|ur)z2BE z@531B=QIHBabha#O~eE{JlCDdEjfF;_J$wJ*}-u_m@!D{(4FMhblPWs7B0lSha3~Z z{rx+QF!0x^rA@?_Bj~ z*{H|3tvNTu0JB3B6HSW0ieWxGe$-u%%kayv(W!>w20{`_2gqu>DxmH#vKshV8-GbT zzuaA97K5)lJ|ke;le9^iRn_zRmgk~vU%U`UZLA%5ZAA%i@r2E_?J72S;Pg?|eG_g0 zreY5QNSQ=q!HK0*ZUleCg)#h>-&#Jr%u;VPQ9-AlioWSOb0>;ORGJIzY()eDXS7$hm2xvgN)~dc>TzLd@ujyB8>5-M9b=#+m{nzRz z+hBeUV2@2$4cfVH79#%o&M6IKR@3NHYv%d+_OF5C361{bWfLAjV%Dm|V%h^=56S~( z(GsaAf0`sc^^es`r|BrirK*WqjO0Yny`u^mr-cHm>ZCCn^tK;Sb+X8GbX zS{lFz$bqljb>NYGYHEmD)&tU6DBy||JA8~)m)Mij*~b09wi2z7Kaisrda|=eTZdtf zgx}QS7)ak6VlGClBwj0cdAtAeLu(rp|J)jt)oy&dsah^$4m((BTiWIJ4$_xpk-dXd zgn5e=S`trCl6yKmo?_3k?v7~J?iRYt6x_lIyoHSy%g}Q!!ECy+t6-7(oQ2L;sOTJa zQ|g9Y&efieL57zKVqOvX(DH)f+0&;Hil{*pJUi}DVS3d;?rUodRweEA37u&qC7;WZ z5EJGi_<>>_8$_4FJX2tOd+NAG%?jRx{Oqy*g%s+iERAR{niRL0a)n_(CB4tOzF0MY zBBj)xhYlHg8^a}ksI?dBE-uAz+nfD7{mHqdf!nJ}3D54H_f5GstZe%YiAZ1VJ;DSR zin{%ID^Pz%z{(DY>dMzmutmhH5t&QWZY#{lcDvp4taBmq{P47|WFgqLEnY!S2-%xy zD6NXm42%wqE%@7#mRFWpZqapcdMYK@a!jG{pL|K*9|v*#Xk|~kYXtU~e>IH}R~54JQ-S;_hGxI^LdHKSds6+)>Th9atmt8B8Lq=>HJ)7Jf~?Z`k)| z446nvL>WC40TE%+J;LCNfEc8tgn*PFokNh2E|Ko;kdm0vpmYq7u2C{#FlyZM_dNIW z{0rA>=RVhU9LM=Sj*Da(gia19n-jpBINcne%`!Qk3rg85P`7BStk z!?&gB?tgfZL{r({GYgN`sl0A?syxwd57KI3?;c5Y7JVZt^NZ2nM8WH*3R@d-|Ge*= z^r;D}=ik}0!jrTeiGF0#OCQs7l9TD2gY*~2G2j;$`>W#Fk+shaU5o5?h1)6x!s`g^ z?}^A&16=np%WWvyZ|)$&toEyk^5wx;K%FVu=sdYk#!nGq!CsL!CjN18*fVP#J(Y^! zQ3dCNEw*UcEWi5TqFE`tn?3aPz~sYb{r`+dNFP4D0(3iSG;(A7bq0hGoaC3O!|>5f zELA_zvI_vBwlCbDe9!uTlm-ACCO0F>W_qn zI=TS^^z^^}r4|y}1P?yCp&W z(QLw@>(x3CCwF3KvaJ#%@-){FB{%b5-R}skzD*78Oj>=Matj_1euJaVH%QQ!fIM)eKF78-oBHL zupNY2sRzrC(d#2U>o@LfzJkdE7!aNiz4M=K*{$Eq7laoKAOcR#|Mcpen36EWsJ8gV z+OnNmereAcweR$@PtRqViVsO?1Mz+&R^?d+9Wo%{ND) z#?Kx<@c?V-W7(}=emP1wp?T`Wg1V_errQg7UUi&SCWPWxxld3nZAXmVPK2uRp%Wis zdC?pT&s-5-|K=8aSxy50#uF;A$}@?~&$0vRybBr84*aWZS{vP3`yH0OiazhP#vLvu z98Qp4rxf$|p2HgTx~&jiV%|#ZeOHQ=Iob+a%@^T7ruMH+WfuZ>_ov2Y-5=~d_L?+| zTb9souUX)VD-L7Ig2sLL<6EVJUkxggf4@7htDk*4^ECa?p@j4_E8iq_gNr^m%a!Y` zY!$|Zw*oraUzg?RxS(#cnNm|!S+$SVl9Y*x99-Ii2MaHJ+;Oy^%OV>6Vg7?3{S=u6 zktlf=v!6AyJ7~soOys!tpNRQv@1Cpj=rqsoZoB3GD(hsfx@fqN>=~J!;7C8~`TCPF z>HhqoxG!9|vxToi9|oi*TNTb4Hl*H2chDDL`&I&Y-FcrzXFR*%q^QXix4A&E!%WdrAbm=31B(gEJ?nA((?&iqv zHXqE&hpQ5xQ)gG3388bP&kyp9m5Lrt#8e9-l1#x4( z&w+9HY`>Wx`x1(al9cFK76>1)(VTiR1qvb4eD{e%0UZH1b~J-rAqR>si%jxnQMbH0 zL2|9#$qd>(ui1~97=Tj6!|jEr-4<~*MV(5RPijPb_c)-q55(n{f{sxPhZAC!{3lN# znW0pujC*EIwJsovm;%&=0ojkI4DGz06Sp=y#Ca4LEXa!MWmNa$n#-2sn|mH# z(?2I1%j|}iNdUt&1JVVavs*?l<=H<9rK2;Kiwe?~G80FG*I;DlxBt7Q$$vbOHKyad zxgzR8G4;&1uREz%gQ#u%vs>pQ)jqpLPaa~tj*vD?bZ?mk9UKIQC%S19svQpfH*W<~ z-CG7s2IIuiZ69>4uY2(F7`@L=HG47D1g?gO$q56?^6PG3Qm@%_jmI0$91q5wKjP@kU&FHI*D%e(dCl;aZesT>4W(3Px8< zkpRlee*4b?g=k~rLo@CuKzHaHOU4?~dU=pkhb&(H=D{600>uQy6M!E(NFkY|fhO%u zWv3fu-@HRpl=Tq2850m`K=!oSSadbVpotQ*I>t_jR+Unej-KS>J_MijQI*bJ$H}>_ zD$Le#wtQ%uzS(w|>#$+tUcVc%d((v1zm+Fb2fUpsdI*^!?|k^_F(rp!ecn;Pew5si zE}j%|=s%8l;Eu zG303y3H`=|#D^wMY2W*KwP`OKuJ53!QN6f&yK?-=^3CL~5O?*!GnAIcIj6^I+Dpg@ z;MetA?)cC0^1qG9_l-R{e>{sLa|XwdJLiW5UfwATt!pX_XT&`T#8MYIdpTP&FEXh~ zZ)D1K2F&jmmSc{9}u|n?1==*@52&2;P=~S6}zF^{^dgaO-tK3 z;w-C%hc_j9?%O_UvG=%@$p@!or}b&b5|lQ`=?`+~OXXMwM(av}N0N`1Nr;h3Gn~;1 z?cWCr-JkjRbI)fo<&JErOvEy@+@@{H7iE=%b*)EU)JwSzr+n}rG&H`;)Xw-Sg0V0D{sueLbIpxL%Z%!boyP7r-95zXKgG?o5vt{;cifR$eMGh$5*82ljrYxz*87S^puci_%@PKJQEltAe;L6#>~XkdOh0S zho8LyA6;E_*Lb}3AKftvS<{N!a4>7aZ2K4wjA*y-Q+$kmd#KQ6+Q#fvHrY51Hbmto zH1akg<~eUHDos^#Y#_`$XQtAZxfdavbp%Se$i`+EB!u7r|j1959VVVF)vHVSpj z5NHbZ&bz>MF-~oq8K$bdxfgriV>*u(*@4f2U-Z;P$r{KVHxA-oIbaz+rnAKaWo+RV zCEJK9VKKq27{wlG>8yMUAC>jzYkd7qn$KpQdR^Rs_+Ad0DgnDp`YT22vfpM2nr$MH zy?No%LwW+dYtAeuAm-ex17Z9|L598W*Ke}=u7nGr^qp2i$+aT`*;*B|mlH#GSl@qiB$?O!wXs_Ra2G1DIUZVecF` zrH}MSHm^B5&OfsT`mRAsVQ*lkC^2o2?>E*j-Marayy|L_ji`j}`0u>zvUnIeJGaFC zl}7xq(0Pt|Sw0QNc6be8xt1P%N8#X(%y*>rU)yi3bLk+aYu9cG48_g7WVy)Y0?0gT zCsFM8e_5<(MLFwdrg9?9vl&p#dNrk8GZZ*b=JPI!uQc!B>jx#o?5PYee@zd$8okDr zA(?7Q?-MAe#sw}I-MmCuJNh@b!W2??+aY<UBgq`ASy7`Bhr>2B&D~)7NVW zK1-b(Bm0n&+Iu-h*a_4lJhjG+8%nerqu4+;^J^mMOo+vlw}VK_Vv!gi(|6Zv{-9>V zBLf9h-+RGLu#PJeQ{x#IL{6$aV8-P*jIQ;~lXaW2v@g`Mxz8wJo2y$1!z!RTOuGYW z8Z9OpHWA(b;IW7259X8e^r0wNaTWi7Y=oF!j%M7G^&7=1UXI$X?Slk^2d@dYeC1QM z$$MOf99B;$0k~8S9X`*7m}ca;u}ZuxEWP)mn8FM0Kkl7Y*CEckvZQZbnb1Avnl!X( zV`T?Q;ks+zkX#*ur64VJ*Guv#G=v1;0H|R6v45mC)hOcP6ERU40@Fek9mB?ACOYsK>E~W5%HLy|S;; zHdJFd6~kIE&N z+Xya`!IQ4fmMp-qk6+twfqGMw(uptN8E5`LcGA_s<`bIfF>{f+#bqw7Vy>x^BB*S3 z4zzkG;Q;5Mv&bud5?XPX^S$*RHGEZ;`6|%%8yV^P5N}MxUhc~ZoAd9V4S8iAqu2Ho zK1@y-cpgt5abR(%Xp6I}hRS&iu{4z?gHmYF1Ip;j+4+m8aZCB*BIiHZz&n(l!b5;c zyA5bwl=i1~dde{Rgl;A6@A}v9T`t1%Rdim02O0u&x(Z^L@!on9Ka*PZR2F9{pK)=_ijg#0{tz4#$Q|c8^}55{)ZV`8 zlz9C2{c~uc_l}M6*0P;vu~ZC%FW^Yhr+0gx>A8KhWVRO3aKG%u?>@PGO1rN#=Ovs? zrysupP?$^JU|=5a&Is&XXPlY)o+Di`G~y_q$I?54nCs){?l=;el4d=PvefsXDe^9^ zvdkGh?=JSSor*Q^duOsk_G`*)&>=9f`UDL_bNDP+sIvHUH7pdNNeqP*i>gk(E-sh< z_tX#m{eF!z@GSN2=)YR7Iks0DJT{)pK9>-5sa;ha#n*`x8wqmJTA_6ozFy+}&Wwu@ z-irryO{dXdppV>nNCl~tYHiUZ04)_*yFG5g`dOXR^_^`t|_vT$o~ zbhqyoCbnup-xT-B`DI#N-J`8{%B!(iOuj2M!claW`-sb>Ok(rFV3E=J671}=kk6w` zhiC>;cauc>oy`!_4a28#bJ+i0!y@?9!~gcF(jSf!rv0#)2Ug+qCC2@pW6Bx+&%Pk1 zp5?q$fc1%%{|9dB1vhLclkMNUqv6vVC+?i%N2RvH;dkx`Ic~l&nEM&I*umOs=67LT zkY=xpN#3c;i#Rgn&fvZAt|-cjBxYjnb71{1-fk2b4T^bk+E3VdtxVnykxMlcZgA9J zeBDtNmgq`O`4qGz5SPj>LwIx%*Q(@)!^Mpk$m6XcWWbG|fn|53-A(ewj#Or{8|Dcr z-;IH;fSO+dhTplKsb=|d2KW!h5it`(jR=wAB6nl@Lee`&~+e(in{i?vDjmnIdEiPTrGICj4d&@p{x$B4X8vj=^GEK#NMoUAk zyDB6n;W~ZuzvmZ%hMKJtx~K8@Oa>>lWYvWr5~3JHJohGX3XJScKIuA*(Q!U0!J_r1 zsNkF-3Z>#XhJ+!01?knEqvzmTCy=HQtkoP_Pk^yqw4e+B0j`v1#j`pi(Sizid3saY zo4H}tGdZ)UWr6*P2c|PD`?UZiTlF_`&OY;x1?1ijLhU#v4c*dw9&I=|z$-UhwusTT zOOM}1GFBVswtJeM_&%SU=2S>*NeV{phh|NYRjwYR2EWoM7SJ`l2=32!1WU!Htj1`| zd^Yqyg;qbBB>XZ9^1<0!DnWRjsdY&8^3)AsWN1GGw;9 z0|4jtxhwk7-Hw=y^Re#Y$>z1LO@8B(r}&Fqze)JyL9BJ@2XW4zx)fFZ#(hK&89X>6 zZ;P{B@qLZ!>*L^xqgU!S#b3(7E+06dp-gPQZ(3_3rbg&XI>`tfWOY>%^Y>so_p6_7 zl;E{jjzG1^2{RVji)AgLd3AeWRBRAvArJ0yMaU8DAo3*$vhXyeN_tCeL*uV8;X~#x z7i$*0tZXBPY*VE%=QR&NdLK1b$OY#g5V+kip?D#B*PcgignBC1a_7EtWDO~qvKJvS zr)x;Uy%_~LctFT-p&q^Q{sUwK%nNkM?04SXu~~kn+2iZ)&|5q#cB-_K%ZHk)S%ZSy z(V_~-C^+bidCwfKs!NWW{Pb>@#i7>oWe4#7V~ex?%4RHNgB{_8NJc`~LPYqKB=bd@&7shlmDIn zq-9GNZzaSzZtgA&P_l2@$lq+)^{KE+A?%sBL?59b-Z~n)?h;Cz)b8{{;BJk9ex!s{ULlVX3 zX{F(evQB}xGuugL>?Cl~%?1SLuWGb(@F$zvZjsgX+&e>gl7HiZ$5>Jr?gMy0r*0td zys&<*jQ~;zmrbkvd6eR{d-39%+wR<^x`St&JiY1t&O2P%TN}LRrYzqFFkBf{oqEd- zEln?=toi&z!wvd{(-mT=Xw)R;bx_VIPxOLwM=EFtM zkDBQidCXPi=u6x!W$k^?y>p)l09yy{Jm{I-zo$Pr@?TPcQ*k8HIpJ4pOFZ;LmSnfQsig4i?i};q% z8``dr6>rbV5LA3yqneLXu9y~O6c6?cI+@w}gzRr!m$PBOQ#@F@K?7Le0*U~+S9Q*f zAJ+NCYtmhk0w_3I4lFeK0GmI5hV_7=#;NYB_*j9H??#j+dBz>J0TS<|z4qiXVb<7E zmI+Q3_WXo5=jH}^Nt^aVNR)!T#Z*J&!dlk0$s{b+#=he! zMn^NC!lEuaiUh1wuB4>>@NPd@2MuOx`o-AE9H-e$#Z!i#B5k)c&r!zf=l3rkd+|9H zr2VNrlofe9zZEHcWg^`RzgT;q7V z?CYOYFWrf?P&n%b>RvOK(&d4pxG#jDdC~U>YJ{%vTLa{5 zZHM$uFZS=yTxdajNBWOelwCc%-j;4Th+ku3SUDkrRtJ_T2plZnxjIeuTB_2rCB)1Z z5$(M_W(B{l$cj&vZ?cjexMxiD-ww8fYFnl@)+A3c7MSeOQTY?|)a%$AFC%2F85nK5 zVDul|G6zk}zc}yJch`>gSh+u4 z`w_dHVj8cf&!dQ_LYiWrZD^{ZbX)@>D)yXq=*9wdignzMNKd|692>TF2N<5ly!Cx4 z6R$!iTb@HJmKVym{;r1a%+r8HuLsRjXWj!jgflR2uQoh%=F$yYepL5mnX4BKsePEq zj())3fm5)Y`TdV2#gDJ>94|R%a{;Z1d(BvtJq_o)&2`SoAg`OXXhzWo+X|&Stz5bw zv?|+hvKkw7J;6trn>c)V$bvjqnNp%dt?4) z64}M(`B>48qWs5|ENcE^S!)xofq^uci>3NVgTq|9ix0S=IHK2jJXEFt#&fPqJH=7YI8P{z2g%`h_!ldp{~LU6mhO<-J>AOHlEhZ@x603Z%HbR{@R>vZ zWqyGfH<5kUTlt?ff2N+{gr>+eLVv6UC|8%k03TY5AE7}*Q`pfdUHmCr3gXoyBBYv4 zY1i@j;+B4bh&pAzvX6bFe@F|9i);^uo?=Y2SU8(2nHIc#|7J${Yz{NJsFaj<(OC?cSL~De zdtUSR#0DTyM3t=voAd^)c4a^OaP&j!c1o7FQmd_JyrF)zP+n<0KUN&{%yg-zzYF(( z5;zX`;Bi)K#==%ciM_mOn;W|08IE&I>-pUZFrz|kap(Ni2pWuYbKtT{;&LZ%3x|ID zKMjQC0;4bV6MPOXXXUfC@O?Dy0*iQOra4teIr&OM!cBXx;UvS4ctW>AYUZ#!3+3MR zUYEJ}PsyH$yH-0*E$_=;A;|u)t$YMO8k2%>UL_lAC8K&)Lz`tH59b_(_jsGvA?kX{F02Atl49Q22&S1UH@^ z33+5T4~Cw19OuiQV!7t%7_OKva2?0l`Q6H&ZC4YuQ>EvDZjvRElRCR%4H8yO}H(<%Q(#Av6&;X z+JXH3e%E$8Bf90~TbK{``YE3UtA+1H>{)UPBvPJq6DAV2;*4_CS3rLQT#apM|Hw92 zmm{n?OQ&8A2^N&dZq_I>$pKU-e`UDO*eI$pisYNnd1iq(8>_&KnCTyVb?EnA-xbG0 zg@0dt|E5A4t4w9he~@sdOZBbI9_)%G>oFOJp1zWwRX$rszT{8*fZY%|bf(f|?OCG8AO8J>*wFM_6$bd*+qP_fnNlo31`rye)tV zWZS&{;a)y)8?R#4UU+SFTAz)-hyUoyr0_xl2SzayTL0b7)0nHCQA1PsvGvLd=MS4AmZ;TrAeiI9%3&UCukjnIkD$j;3vBhaBK)+QU%8;oz!9v$I}7 zRu7hxj@r;xHK!u*rPO+=$kzv%2$%eVx)a?lO2VGt`2k*r@BGV@@jQq2+3v`DyOsJ+ zg3`@7ebeUn+Bt9w-^B}oQng>833OWQZEqqL@u8Y3V{ZgSNzga)--<9XI8VZs!z^o!ZC$|EKdDAzU z3|>duC!z953OWF-{v#4#Ul9&QacYYW${nY^3oh$1lL2K$&5nVZM`TSjhyg(w3yPF@ za=NTU>DwQs=duH%REak-_HhwcaS}tWUtbB6H}`(Xg8M#~`ldAS{vtJpZRTbP4Rh)B zW##R>)NvD@(0`sCd#=+`U%BD;W~6L*78b6!pPvzo4?)(w6k8XjO#1R@3`(S$x%X*c z+mIK?2GynZ(}h?xFH<8qgV?cwzHwi=)1^{?>&yI``y++ht19Gij4O)Zj(?gt9zjU= zJ>57m-M0=XGbX^9ynO2H5=9m&pLLqk0-Vs=50C< z*TCZRa`m31zFcd>H~IdZ<@%zkQ16jGGpG)RSp!0lLqpOMJb1P+-I5)Uo}5(Fbz3ndF_G%JO}32|I~xOEk?&&`@ki7E8q3e$B7pn zcssX>XsW=7cj>G$c8=4OCC3Hnt}pSHyBB6>Oyl#+cR}aB&eY)x{fr>{^PW78jqxqL zceh$pPv6gJoVm-_9OpQ&q=o3ys72J++v zG zrZ`Y)7B=h-ucR+>h)ROO7abzKVU{rM&sDY_S&`J3XkmTjcX1YyObtjkVb6O zUzGB+J0K!Cp8q9tQRo^IKKhd{HC?gU zN0@#M9jUHW_we(v&wWE@RtR=kN?inbtT<>FmWYZ zA`%}jpLq*Bb#C8qH$cN8K8IgXXa^v8BzFkKw;igstw{fI>K7RAmM8XZwp|{#Rk|@6 zEzXlI9QXD<5#KZrH;WU$^2Y2Su*=7E)tik5xiZ??MJ{^zJA<+0GFH)6P;73|kDj&pA91kt)TkTPLA%ZhHy4IyzdfSF~Q z%a@AxWUoP7s4J%X-M7OxQ|geTw5$s4_xMWoY#m4^UJh*8_JT^;k={K!xC88Orh$fx zS}4AaCYmIQDkAPMk$(qn}4GLI4lgO#*OkQ)~R&kTn>5B%<|XnuD>)^ct{B& zcC^Kh(ls53E+qP$B)%zW-HUM0Bt@lpOY|LDzBR2S+Z1P9o@5*ssK>v6%bW4SobIUF z#jY1oc%NCME{-@jV)h}r&=9d`!)^tr|Ve;gblvfJbt|j zNI&}l(p2zT3iUY}&Xiz9xsRZzG7+{*`GUAOv+*4JXL0MMpcmFlJm^8bBYq!BV=h&^ z6ko2MoS*}GJEx$^L;pv*MCHd;viBJ$zbr2>@>T#$fx0@x8p6^9%<=wOQvrLVUhVL> zzyY5Zy!Ly+t*`r@ZvXt*Y?p#r^d_N<$tuvo*4jZ(R*Z!zrN=a{Ya2#B+x9!gW7GPZ z9}8!Q9oTrh;IF7}*bT4E7PoNNES5K25qdHwCLIlk{7B@~QnL08mwq}&d8 z&)9tT70sH(mKjhzn-Wd)HfO)SUH|1uZ>#Nh3*6!~E4=dw4?m1>HIwCwXuc)S+~)q_ z;z9$tcv0!L%Z20sx_gFp1EmkC+d!v!sFYD#Y@6R{x4w@IeYgC+P?;t2Acm?0x) z^50%ShLy+(0jn&(xxASjmi~qTn*O=c=RaP_P6n>+PB%>0Ty>H-_TezL{)FQEQxxtv zx5e$?jR;uk4ewDWCTtJoLQi@UWN5Rl$nV+wx~mbcIh=F(fzKigN{4?btxK&KON2bO&Y^$QU=u1(dy|U6@Em4wrze)Q)8k; zlf8-!BBqS>O)x6Tehf5$@jMtZNw}UuzEYW}Ff-D=#q|7zq5USx7X^hWKq?16^DLwb z$a(u8@Ao6zD!V^_17JXG0f^_%@tY6R*Z8x^h*-X8#O$i#ltQyPK0(JLQpAdSh9w2? zO?JN0@dD;Gz8iERTZ>mDa7WWh_h`7#MrDptqMqx&&?Prz?M9scM9@r!N)I31_3B78 z`E>@PSlm8@B~$_^ic^yKbG8lzY3n ztS0E3N}_o_PMgZaY^rvbN?3QXDK0}$8Z5KpNV^f8ku)m4v$@c$h^sw6=OzBU4`|ap zBkc+N)WNmkJ|Q&QPDtHOq|Xtwi>-Q$((X3=y9M;<&ES+}#!ei#Yjf!h4~dpUff9~` zB6%2H!$<7xEDVtbDe>vwj}>^FHhI$yc>FdwqIp(^q{(PZ#?3;jTpT}zVi5XCjK&Kp42x7j0f*ppxP?g{aq6N0D}$geDY(l=tV zfQzH4l7%F#%!Eymv z8JgxSs4RgOxDl(Y!D7XwEj!NQf&X;+cFGR)mF#QV+3fD=QwiRMN_+uLv2hnJR9v%r zE+tcCgTAT#$L`&(gi|v4_lq{j2YFmP8x<61&%dB$7zFF|ZiNY(rndsoBs}cknd-Rw z@dt-OBiu)rre(V0mzhpRj>F|_+Veal(w4xquNpPW^2;8|E?HM&w^{1#&Y6>6lZ|0}~jv@wP6~hOl?n^g( zPNW0fLD6YP?=~+7(`5pxz+DAd7d;PN;0Pp0hR0D9LLY>;q6F;v7XviM{Of#V^xaKu zsLqb18dpfwq;AhCtt?AuOPXvuK|>5HGlt(?rO?xFt8a@^HX6TcvoL|e^%qwW`>2P` zl$j>=n|%uSl0H+a!n!z)>%(kd}} zCMGgg<$mL5t)R<*wwQqXXY&>#1sDprI2bJza8cC_cQJ174>U_Dd!U-=K6snQv1d(% z3ot*lu zZ)}0$4TO1#TB}vqBE39=|HWAbj_Rg<=2x~q-UpYKJI~HuL8c*?Wf2}S@=XRD*i)gv z&RiIjY`l;HB}k-8C&TIgFAKoP2NwVrrazx(-_`!T)fk;6f9j@8WWL9iqL?^Q`O#=U z;Y6D+tz*Dd#^#WM6b#RRoR&$ZR1A7X)PIFIFFT0Xcu)E$U3GDth`d>= z<%4}y_Zkiew@#m+K|V11h<$(uNUeXdeC=DJW{COD7w>02tO%zp>RJ*G z+Y-ZvVv?QS9|rnv+VPMPwX6VN+Z$0^4q2smFdu2V_xOVIMq{SRhgm_+I34|%i z5p3;ls+d@8+mNQKXI#u{U(L=TXiFA8@SENB`CzNN5hX?R5;d8IvaaLXY~|$MiR@L- z$hPV_*h1nDP8ia5$c?zzr_foi5s)QlC`fL0g-Q{0(2|GQB4%OH5^4jQlE0J-d6q+| z_G{*3TvJyxBwLC2iW&0v1?o>ZTvP0u_nu@F4n6U*%J*(Q`{7Q85=k0+clmt|FDSFK zwzTQ9d*)!z08cTC?KR)UE&2@fn}=jp1=tg);7j}~azp|H(d*72`PJu9?AR`AB|}9Y ztuJoFs;v>fgSDGNZ%mm zYk|+TclHDjve$umnb+Fed~xdT)v6MNN{aVgpVDx*Vc&;UF1U?BeRniOSK{A@$riU+ z4yK>3WEO2cMtH_(ythi+18e9!Pg+^gb>X?7uxDi@?!T>3r#`_lW%>^2OoH&G7_;wy z&_*TqKq%yJM8h`mbWNg7Pi|d`9BqA;ob{Dl4*G-Y7a+RIG#KTT?E-60>T@p!m%nH~&Zo9k~mzmq6 zb9hA>*5R0fhnP;x2$O>HzS=d(-t{OVw(TqXr33!2+ojB8n%sG~*7gXKQmgNQ?6|^& zwTy<-r9hJ3P@)@ho3rp1ynZ9ERiM8K%WbSb*R8DogK{|XQ9bR;EZC^m!dG{bcRGIe z280})=X+kQgZ!DSqYtEJwFQ%x#C;Py{#4xzuC8)X#yO9V&zU>OT+sWK_GxIt&ll#U zF`zNv3&s@m;M#-03{_Nd_=hC-P&=-V<24C;o)s;(xF=1~W+g{iT&NJ|Wr%wp=X7?j z`R~{!6J-UMzpe?ivi*n&xOz(F3JB7@4H3w&&h57uS*iI+b#2+yg+=cc;%Kqvb67>~ zPZj27Pv)4GFFnwGg?58?Z%QbBbl>z_-|YGmsW9#N!X63&`q^2 z2KLjhoE+&RK=K8J9=Nbs`POrdnF%`%EH%&TDxW*rbC(+##9kCGYcoH^ejk=G)zt1r z8yztS^xICE-rs1U8Nqxq4qfzzpR|J>H?Gv>JZPy7GXnolq zR*@Q|A-|tD9nIVLIY(>Svf5t|qt1R##-2oo*z2N3!%3@`wra@DT{;uQGUNAZT1;2o z{BYgQ-r3_d?!@hKVoDiNWXihh=IMfw{)r{)>;hGU@AnrR)8&5=JNza(bnQ}4S>_h_ z4;t$nqoU=0Q8}n=9JD~{g8psilnqC<+)Nn){|W44)o0!LPi>i!mWiDFtS@^+8gS2gM-Wg5{TR=HK}ip>d9m=Z;@X7A83|AOH{F6O5t zWmI4xwog~0b2-q@s$&MfkT$ONv%rFSwA{39JdBA3PN87F0T;*(VJc2>Om0496ZFbs zC1Q`cvw|hSw;{R5-FiKouA22?k&EO?_pJ0OdJm1|n+|vQ9nZSSy!Y)@EqC)`RwaaB zW^kc1Ptk%>jRL*DgqogMol;FVx6r7vmX3%tF1Tx(zd`su!0dV)zIE|&GM#SyjceaL zo4;(W7?CFpDBd$Q`H|E-mjVaOV{_E+P(aB4YhCE#t^e9af{m>FhC+oL`}hi^f%&Rs zb3e!escm(y20Qg6fHq2Yzp!P+^UDU(xM~nS6w$h#;aC2M_LT38#;`J}YTGrX$l%M?lpJ7F-d|fUrG>DCL6{jV`x_Bzlx?h^;yq#lk~sij|DoT z-~LRCf!QaMdzRmoxkSacl?+B|+8ehWqxb%j0_N~txv?#`M;up5M*&uQ1F03ibC-uV z)lc3Kf!nbni~Qr(c|G>cc6fuJgsjj$iaYT-sWYsJ`H?7IiQP{WK06GV=AKi2GuvUs zP$c2ix{NJ?mh6{iLGxap>-1w+J;5f^0HxA)sJ6X|SJK6vrZZ}l%=Q`Ps(=%(E-29Q zHqw2pR`v3^$SIAi;bwJP;bcAQt^5o2hVKIcLIqZu;k z6=9Hw|I0qnH&oG#2$kEaobjS)mtmg!g8j++uY&Ft2B@3KiY=@D{Z>KyV3flwNc?ZZ za^&WVv)J9o8ZvFtXNMx*v8D%*D44*HT#Lr?`L8f1>qJ#Ew(nPljbE$=04U8>T$N6XI$x6U3ty( z4IHn=(8i={5#pHXD1FWv%^q&4fndg_n_lmBECN+aJ&P@1lRq79`8!C0%jz;Oj~JEL z2^jIt=+3&K>waQXf9jDBpne6Nk)y}a-$ zmcKlZuir6&odnkv@;COp)(!DFJ*YX_?TBsBZH|IP*}ZgnU*&mJQ&B`PBELl9B2~u1 z95-ieKcDoq@asmcueuK^N|%(SCJu(gFkZKzJG))CPY50g&+CEMS;&j!otFon@oi?B zl@;VgXILbj+^^6eWxM}>kx|SG?I73`P}=C~MKRkjtr{hG6GeB00Z@RgUT{hNIj8+q zX&5L#ReDYqu8TM8gf5J)#(kUCnj8DRvJ~^eVqe$ZSi(MmuS?wat{IQPSduVm@D2@! zAi#b|;teL=pXNub2;N_qcW-p{Ww87IoIPmx|7rx(6UI z3^K~yfVwjcmZEBYhr(oQp2c@xt!X(k(Ma!kwc8FSzQ_Mtu=3msGd9@qS`soYQhqy{ zU#qA82a7R+o?yEr(J(?JIuP5mReqr5;cM1h+V2pBOqr{iZGCq}<7eqFAgau=e+P16 z+v_niGxrvG60+OUM$+tOb+El(S5*Re@a1P?;qoseNn0y+WF3qZlH=Wf*3WUJ61I=v zrFA>i6@9W!(^e%3^9Lk(SM7iD?q-?Mq?i|qHGbA_@}~9&v(Gn;JGwtFyk>bF;oZBn zL}3C#Nz#H9Iv82yr+(rl#Pw&nNH_H}c6amvt{o~341ca!aqC=0$CTxqeNNd?1@WU~j9!OJqL9{Yn>RgItpoNl6VCE4 zm3+K||JJrsyiZGyEQ5Lu1U4iF-ah1Tp4 z=P`k$FkkbZ#2Wdtn(;Q`R@-UPp|@zn&YNnm@yJp3hOEV<_R#Jjebd2@@~QT{Ia=BH zqIBof%A1}JHNHzcp3JI4MMf)zLE7sq_RpZ z)bfXqJhtd~THnjpA3s<%Qf$2Tc+hd}2cv+-&Zp7Q z9y)P?GYW#z%gQ`KD7QMsD%v2JY!xl)z9IS8Fj!t8kt4@6A=KD6W&rgcT9zNbUBnyp zthPYw?K%4Kg4)GDWA&!8>cd9WV=VjNQ-a2ku^IE4E^BRrc^ z&j&Bh^ZeOtKRU>PJS?no%2xRJV&HfO0k*tt;rRiE>a#Y|ohAE!cNR=Zi#qEX$;0|1 zIzuMGw)2e?R%}>$TbQD%Gb`?~Y-QJ^u)H?#nN`BZzAJZ%QP^hh+hEIt!(mk{{LGT# zQQ`Nw6t{_+Qq*-+iE-Nd9@|S)EnKjTx7-=c5b?bwORuDx$v^Uzf+8wd(F!9bu^@)C zkodAbh!ym~Zxx9qp3OMZ%D7gma;wM$FN(fgsK)gx{ojz=_X}t^$vMd$#jcU%o=`~= zvM9f7%SVl$9#LgZ_u46YwVS}x0Gp0O5uqIhW%;M;+3c6uHX`;3FTZQgg3W>wJf?m! zvJLojw_3_==>;TMcHP+N^__-R_DsHlXn!@r(*F!7S31lM@6|kH_!jLy_*E9bCK*H* zv{^wfDl?eUDla}{oTb7+CpK+IHaFpPV9dh;4r^OkX9B9fj$TE?=ITCuLS-DFZp}O9 zhi(m*I}aGhAaoRXQ`2mWYRJ#>a_bm4Hac|vsLN}d+FW2bE2bWlA0+nbo{1-xvfjhR z?$z17Y3o{LJ`$TH0h=}d&5_Z?9{jROV+gBynxt|aBt>v@{n8rcCy({&Vv397O?P*~ zIegYByo}#j7am#eQ}tanE4@3}k)v?oIrA>}xM&WnKMLMTiFHsnKGe2*1C5u6EKgBl zZHeH~iD=pjDG>M@JM}m*yqXOFWrE(*1B!oAFL)d*3or4;mkFz87DgqmJ-{9M#QiZk zN4;|INaa1%CuNr~B#RzfG@w2hhoF*;mTngmXT_{>x094<9> z_f$gawpWg(r;XK53O&D$nQAl6B$LkZ3Br2IxO-+>bpwdz-X~v@1x|q%WYYK_d-C6ls zE9jmp)B00vHRe$yOw0b&lp8ZEAJyS8y z;Uq-$S-_nTSJk__HIy~AIlJpyzqOY@YFXGguPf|ST?kX%Qzv)s3?B2@v2oa+hkEXD z1SqZVetV1EH-;HHMY)m)&VIE!TdT($RtE|P{dW92)}+6>Xvl=eF0xz>hz6NEiohD~ z3`U#|$m}{RkVt_aIZZk@TY$0G_P$Hp+R`$G5!zp(mibOT7+G%*ePTC|-WLw=*>mpX zwt`CK@KO@us51^e-f^iN3E%zJ*UTtWMNO=xyLcpnrDDoYJ$i~f$qVl+Xt>{v0A#c` z^u#P_s=obqE}H-p#wtSy%=+Ye@xnTB-5Lb7g83f5YKAl%S6$8e6A}&UxlJn%6VGJb_!fxAJUsJsYEKL~`Mnn_Ep6yL{P-{bRIibjE$GiEqst^~ zb$M+kW?fSIf>lAjSAygrJj9bSr-LA*@6YbB7`p#M(^+ccfp*5hBkW0z?zNPB=$e z^Cr8v=JUKl6bsh%7qGkWX)!>eUFkI9odmJiGS9cRlphy&8dokBP8=(Q96*Kj5B#CS z@Rj))9P>@7FYyJ<8!oHe35}`KkX>98+~;bfj4Spr1jjToq%=6Dp{F=mh+~Y_EAI*bYTPxmS-Wp8GcmFeI{2KaO~WgVUVp1 zqY%P{8uI-;vfB{FQ;o1ua4m4j)abrK9CgJ={+%6dMQKg9rigqtS+BP=QgsxcZ#T77 zWxDNl$|G};m17$?|9+=-Gtn?4s8SsjhE1-*%6GiR7wCkVgTOLgcBLFU`rjbw>I5*< z{F!El;Ez``?>Bz4VPCBXo-^#e6}|~YQWC+YSe(rwGCt8k>XyP9kxZ5i3Y zxbz1SHC9c+HboS&6i3y-ZoBcwqINoIN3IM0Ka-9$Vg}y;X)x@#G!kQF=gj?oj> zd=vCvzx?aYmD{Kr)5G83}JuK%4&~%_ZUd8 zTaUG7bwG!s>RYg=tfV>x` zX2=evg!wOz`Brc*f005ywE>G~SFc1xDKREH<{%3$dKLqTYoqFzj1@+C#TqdF&FlOB z7;G1honIp1$NXqn>4m_s$Ev!<=o;u%xTL{PSN+F#Yk`NNTP`)_i-MJZ#$VXwxh9SZ ze>CRU{xZmi+y|yH(K`PGR-T6`#xV1>KqnC_P@nCa3&pzO@N?UZ@+3Bg{s1|+y^`qb zwb1wIDIkdTz61;3VaykinPfFTnCXlLNGP7&I)yr@7&zZilZl>)#%0l$O=)=4A2*sKV|)Rjkwsmx$T`XhZ5VZw3B5g zUABFZTFxn$At+H-8Lm~nL3J;xu|j%TKUPQ&r%T~AsbzU4Rt*r9W#-6-<-LH=Nv3nw zW0@I{V4Cu}y}^cGEcVXFgAYGRWpbfj$Y z7$Y6$la@d8S{2899E7mI*VEc7q-S||bqQNW$iVouR`8(`$P2wJeYV3~$;CG+5bXKn zm*W!?S{u_INfU2%R{ztMKX$cB(Q~+G{mXr&KfHW$EvQUVhS9l%e#1AS67Q&~FW2nv zrsvgr`@LyCH7=kRF3Sh6|F4E@X1ETfEz->Sn9gBs5@!!Zv_w>*&b#-MQugDvf_rGO zAJl zn(4&vNo z9WGr8xG}6|4Pc62IbcH?G5*Xz4PJeF3~cLEzZ?GrOR&=K7}pnhq3?Q^SJYGBX|bNY zNd*7ldfIAZh*GnvG=@$pt*$>Wj$Zf@;nMOE%76as8GMrsH2g@|xBNwo_o(POM7FNe z-EF0YeqQS~%D-lj-e6Fq)eQZ`&1m=87!u;qg>uq+!>Ha47*88h!F-%-B$=`DnIN7_ zZ0zIUV1^As)OUF6<$sfo{miOFRhBF|rb^D;Fp26nyg`K$PAQ|7`PE@)l#WYIPRKzL z5ta6>UXA3Yo)vF0EuvaO6}Rr$&{HGBNIz6jx^t>lMxEb<>Rew@yM~efogxu?mTmLN z-~QZ+F$Q3iA)ovj;WjUGqA;>j*VhmsAHP_x( zCMwPpLgB;uoYrZeo9OH4U^^g^a}qPn3?r~qQi|4IZRjm1!rHn1P1W8H7hbYC9J%_z zFx~fza7RwMZH;X8hm&Opzm8mR}-T zX{X*fA_N;L+TN}>twZC-n;Na!gerM-r)Xl#Vcn7mNiX&f}BtpHW z2b{Ll#GoDp_Cn(PuxYIzp8S4c_Zrf7(HlV2)Pi?j{&0uV^u+nKF$X? zZYdL@!Bo`P6ChKwfe@1ZErhcIG$$(A3vs;>M>r+{OgnJFrm%&K}V8?y4-7K#(6CTa+t9wg<9*r#EiREhlEKrZsKJZHIdl6J5hrd1__S;!pQT&t(yr$?yx4Uuuxud_mkCTZPPV@j z7|n?P%8YpdUW!Y3Qg?8n)_8EdhOJ#OvG(15Cx=k5B2gl!5z7_tG2S9xCtlSThV~*I zC2VcXhuCrZJ|+f6_K}O3U6Eq7>*^uJSz4^krdYzu0uugC(oZp&O)(pI1MH`{F%eph ztE#6gJ{2CB?!kTsb_TvgNw7oS6nF1t^*-WZRzczNTe%t@;w|ASj86lcFB6nOUc7j& zCr;JC^iiu}34OkI4to&ALLenoha4lF(Hk!5%tGkM+HgQEb@4$v;+cF@;*HK~`Vn;% zrvKi^B&W}2_CM&*qPEN(oyX#zJ4ML@wnG2i8)nkm_EW777MPX>wqprlJx$x08j@#Y za#CU6G*6?U}c~3S)*;UJ3dHE*$r#X53dI~63YdSP_AX?nlw(EwZbT)WtApbg5 zAi|S9F|awn31?n!;h8W0U(gxI$HJV?GQR{%ciU2Vq@)9&h96G-6f_dDT(eHP%1?N@ zlCCj|5V)BHBImboR5_Y3st+`{{&(l?EFsR9JJ#2f zCWE8#E_G&CaX+PG`dSXV^a4DRF#f(G@xsWu_d2MS&)EKO{${3{sIR%r+{R!9*osbj zGiI{El3TX-C9B>^WYfra3 zro-I7PBkAkMR%6^)IR!Xbigw9;^w$*cgxbQ4<>mI(!+BP`z5O>?2Ym`R*W1wvYwyOIuJp39{}=@NUCRb~@5sm)gN~D! zg9Wsa%+U*((fJQO4BvM-XsF0trq^0A92G~Eda%EG|CT~o!0k>omT@hAw?$spqVF(n zBOQ*h9vg}H2w_FtE#72G9NY|=-=6Rn#3IJS%b)unm@|~QAGObo1o{VNfkzP@t-6T( z#Oi0rI4i4T*UO-`yMy3d;xi`C2@SCSZ^t~Z7cqCc{3WuG%SyBhlWA|Jv(itPiSwOe z8K3XpJcOH@0Iif7LbQZdv&8TQ(fqbk;< z=9l#<$S9T$#_FaL!#|!r>TPm-|V;~!R zCsuyV3qN>i-k;Fg%)h=lp)gnmI2%AOZ0S}5rufZPzF^MAVC2Jzbv<5mnI-jSfF5Fg zZtU0F?#+62TuNGPGjZ*z`I_>cVH#pG19<;sT7V+G@)w%v{o7Nf6MUv@-}aZC@)8(k zPo(7;|298QpzwjO+Y25GiHmQ?JgACpzUYV}%-%phkGeaATQ93SXp>m1UrkU6&aD5Z%<@yt!R zP^bPV?^0$_l5$&_;RHhec(q3#y!Q6vBQ+&<9P9H0JO!g9+Ph;^|28l`_DDB_&ucux z@;VNa?(65Y1UarC85Km{?emxCCI}MUWCa#;izGGdV^yqPL^iBoz+h_BMZ+yoC-d(mx1~vv!VKcn;?xUjlzWqyH5P1v> z&4tu_%?0;y)AdAOepDdu*Oko&-sUrVi0Gjo60R$tQfP7EbQHLZ^(PR$?a}7pO`4uf z&+ho#lD?sC{G&(xQg*lb#b8{HGK7YhX{?FK#c6V@muT*CPp4x|$WuTjp4O}rFR*S$ zrP!uPNg~`uPfy+wTzf>jr1lIoPsed^z;Od*m{+tKXFiB`C^Bmi>-Y zw2;L*{w+7;PGijJ2W(~zBtQyL<{)baX?@%KWHBKY`OM!8b_B^zB(H&2o_>NejvzSc&}nk!5tGP{ z4b}zQw8>t6WaqG9K;ZR9>k~crLcdcArGIo>k#BN^E0k!O+$6fTG9S+i9Xor262$*6 z#w=-5Lda-La@ZKy5;@E*S4vQW?0XtxBgTbR!PO7${^{z=3$)$!NkP;3ywO}bZzrn|+qg~L;KTOK2@5X~v4`5rQ zbnxmv(X*339Oy}N26-M-&90V?k(T74jjBs*$)U)zvTj4m?2J6R+^nmNF%S2(iBQ%Q zY<>j{#zFu5tHVDbC!goCE=88{)Nc6QKX!;*p(*nlt{|0ivFw?9Sed>-VrJv@( z8}a)O+Pot|1r*j&1qCA26Nz!X?ie29fS5JV^Ca04(U3G5j3^-I7u#2tfhg4n?GJuXZ zO(X-^uVUQjJ0{t7-lcZlfF#rcgGY8qV*9qwsQmKt6l&YS_kf|^k;f*}KH9r^p0!Ld zX2`DaJm;d5U?14zXH^-k&@BJO_>0eV^aw1HfW9uvi*7k7hqwK}(Oz2XC1PLO8sZQ+ z$axps8D|#w3W54D(==?z>K!eg6muG|_dYE^ZJxkX%zHN$hrT+NLt6d5~ zWej+9e0{vmAy}U7Z^AQlyIb&1aAy8EsUe2Eu^6pM=R(F0%na9rLA*-EZqqbd;l$ya$fLXORxj)=YqM z4Ro1{)hgJEJ~Te0k;ef`H^INHnsV^56;@bUWL1@WIO%ZJDs^o<-Mn({2D}D1ZA4+- z;ac)nm9I}XU1|Icnn1(>IG=JQ&Xai8xy7MjBvGGwb4#KHr~Sv2bqb+2CyD&N0bGH` z3yh>DB;a%Bt72D7bSv{bD5 zdVE>9$DlI~V6ow?V9ZNfVDf9lag}r24PDuYG0!RUU8Kkhf^dPn&hkgE4tGk3?gEH+ zqE_^(N3)IPHR%a`W+sDuVa+|NA2y`^N`C$A37q+CN;((8mBUz|@+3w(umFf~FE;bQD@4pOuQye;Ak)RCO#CaM$-Fc8O1l<+oxvGs}?IMgJOPG<`p6gpI|2iS% z9J;CFYBR|o#&oI?BBMkHddc{R-u@HdI;nX9{h8hBn`Dj<$g&7q*2X23GW~(RJsrK! zS^$Evd`NC%GxlTU*<8spgs85O!H2d3(FT48{Lu}OZOCKhhm$@AkH-&yMm*QMhs*d6 zSn{Ns+?a|kHbk|Xl(-4Ielw-$Ott(qlxxj$yA*?@tm%Pq&%ix6FzxBNhOgJ?t? zZ<7k|sLi|{;w^8Tu%GkYqIMw{5A|^zB_msfFhb~x_9LA$eY=y_fCl&c&Tnk2m(4yG z4kl{WqvBjgpcbO40_K2N9^omnuWx(X{ca3NSq&Dfn3w-WMNd!bm>3y3^-#1wEBD)- z$cu@|#M=>xlGJB{4an2`2S70S?>?>owE_^r4{!eiOSVhxzmj@Sk6(rTg|6eHCT5v= ze(uqxQPuQ>ryig7wzXB^UExqEO=nc>IoITd9`!{T?yk{w?U7ieRs8CCgm+4zs{yUg zKFwnT6wz5#(IW{xMj)*fYh>01gB_C%YdN*(5Al^6%tmoDoI_r_Jv%4i+eA0ma-w6S zh(Qx7)Cqv9+|-Ru>bJ+U{NZ}%4DcVqS~@nHwdLvWNdsOR@Ld*9)MlQS?`dRRC&HFP z{Ki)hqMbVd4t3Zrw7*GL z-7KpG`CzFfz&#d)1M{CQywrUUF>V@N<%3N%>@qE|8?15!eww2+m2-0;@<+1hfgWS{ zoDiIG!F1h1Ddsd_TGM}n%0kEjfgs_c0OTFqt93F|l^bJg}b z>Ug*Z)W|+2=YUwJ3ZRjsmC`sg{u&*Cg1z|@!hSW%q&4@RNKJ3nz__HIU02vgR4+v8 zMDf)R9~m4?ebO;Cb}}B=_6vo_A~n5?OJdMhQN?v(EtIdj0}rNy>yIn7twv{kOu0Nw z?^aruAI)3{pV6~Rbo#M;7USE*jdzT-l!|z&#VY0CKu+G}vNt_VGlS&?;sia9K-JcU zfGOP4VBepUW*2B_)hjE_Z&+X%x};1@gy=#M&gB9p8t)fcf6n(70$$nXSSCOWD?@J@ zABGq3wk#$kr0$x#@1scTM8h8_$%q~NOOl3L=%2U|L>H`ijpsD=#TOJ)J1@2J9qw^| zFuPsvch6e-It|=uoit20rPw;0bpUyyaem?da4~&!w|pe}+M0`av-Mz*5_Wa9bw?Z^ zcC*jmxf-|^VRD-b1(vo2(?B*TE`$Hg#gPX?&1ML{*Y$4E%?!gv1&c+?jQWx8G2$X` z;Tzix=`-J7-{1W_YcFyf7#-%(Y*>NZJbG0u%^Arl_2iQY++b_GBue<> zYL>sLkeZN7jO6%#zK%JQJ4vJ4kh@}VZ5u2l?#x_!1JICFK3IZq5{#+gm zGWe6n2;oE>LlmPpG--1XUPSwnM0JbnPKLT}D2RJLtTO-nji9N1PGW&~DUB0zny-Vr zZ!QO)sBMU@x79OK1I8E>;7P9&+fH{W^Jv>Qng-Bw3M(!TIi!Ab#=d@q{);<9f}>{y z(_N%T74#5KRe;^-afMenB6VYb6f@g#e|~>b0@z}U*Uo6{-?7=tOUd}RV0=KOubpY) z-i3$A|EZqb`O+}DCmMJH?K`QFbeb2ITqoyl#~vD-P+ABD;@=+jVE22v@*f^5@6Mil zeUWV}F!K!Bkx)N#bOp>JwSkK=q!w)myWl^U@k(Gnr70NF-$dnde|B=pNfj}z5G-yI zC66r{OBOD!Tw|)jSCet-{KOVJ*>Bq^)dOHnW0h=)x^YzNVDM}X9GIyx<$o#7-CUx24TdvG4n7O9 zmM>L6=XD_tsqEE{M!y5QFWHcy6xbbv<_$$G13iN`>Gyvvf6RCC1+3;jmTYs9j*p-8o~C_Xev{z%Gw6|< zndbb`7 z8Y<%RI$NwohY<U_~*ROxC8JaNeK|Bz{0hn<7Vw`?mUX>iwd`cKXi(mWOhQ6Mk zB3s|Nc(7pXQirc)jZ$LG*a;q7R3aa^Gotwr#)lC0C9cFh?g<$lOMoS+C@Wt!or!y7 z>bGt3IF(HIOR?SVMt?NO`*+;c!m=Y=d?A#;f*zK5nzVi;>ce36>-r0) zO5!&MX;r-Q5R&;8u|jeghG*t7*7KzMmHrL68A29h4TUecJsNHGgn6^<8m?HO7rTI< zXZjzvqf`=!JWuoqNE;h(Z(?M4>=T|LdyW+T7-us~~9?yITjwVI4YD;4GtUk+8*U8CfPOiP@K zT{%SEx4}nJ02gTxkFPjwt|5t>c2DyvYOm|; z+4g@qX45+6p18hGfGMQO0Ag_wq!S#x?iYSIZSUtiKE79!$I@`7kaZ;a_4z-N44b;+ z1>E5o=@&`&r|vM#tRyXmsR&#~RWTcRw?Uo7DOPTzVs1GCSe;Xl4#qBzyKJ!%=5UddvNEQ>{Jw&5mweJ2 zo5U9ye?-)iRawK^TuS9YXB*V)^d{E6*f$Ngy^tv2!_W+IwBBZXh? z8BC1j-6r!;8e>740WSfW%N@OF!Q>^Pjqzj+T{Me-q@z!N*a z3X|Y96QinkER`d*Mq#!9D!&O-jJ*q8SJFxS8GH3&R;QM2{hd0{=$(H|B@dU5kBM5J z;B<^&ftL}9flaa2Lw-^iX?vX1+cUF{dT!*ZY8DDFtijy{d1eD45_ktZF!Ku7f=C zk^5nvp<~WE8`CJ0$h2vA~x3dU$L)e&x0QF=t|KD!AVgB05KaR-X-vu?MiaW(2c_;}i*t^IetFZ$k4 z;>V|cl#Bi*7}!fEuLy!)?eaF|V%_3j%9b5Vc#Y-93Dm2K;VIV$fGc+GyY%s2_5 z+#webS&)AdL@Kp&q|lki#!V}Wa13qVTuB5}#?tjvvuR;$t(LK^@hbNp?v?El3?{^y zbCi=ZXM9$_pUQOf-GARlEwAQnVmL@`4xjZS!;>7vi+;aLs(NEW)OJ4Ok0QkeuSl(f z=*Q~6>^P+vfq3Ah-7idAvSKxqQw^~yA6@mPfCETAV0Dsh3*h;rAE-ZAV;%-OFpi;P zM1)!f445|v!X@QS;VZ4fjuZ0Lr$~kc54r;(>il6{17EFKVJw{p;ii;VUrArbWtPGK zIr_w!or-9npvn=(u@IAtC_JQXv$PO3oJs)6litCK4$b$w{SWHZ{p8Aa;hBnpd{2|m zWMXp0M&9sFSWV{Tv&VHq^u5 zQ%4ALIY3c&Qwn%zuN+gQ3K-bj=faee3)7{M_G`! zJ&zpPS_SIc$C>3%_^c0zl&o@W3mf1tDUY6vWDkM6Y>(`jGu-&>ueor<7 zlFoSBW|qxN@&MQK*}rSFRR>xdT!nX#+3-A3g!ZZHDR&CeQ*iY1t~g!5jIVM0eQ9Ik z(;IUt=vL`&$^ZsPjx<1mF+#HbAcuum8Dmvz@15}~nG`BFEYk*T^QEbBA0`TL zh`<8Yr!99Eu??Pi%5SlFp`wTR8f9Sgx4mx}lXTW_jb8ckOOWd68|(DUNr^zy0?334 zZk(h;z+DdULfykYS7!Eyjxna&7of-yL)0r*3s7qEfs*gU)Ow!TaS5$=vaG(&PNzlo zxSCioed`!7zFteUFYYf+=t6l+6$GzWcO)?i5&b{2)#nYsEX!RuRWZ@6A6S;x6nPC`Jn`_ui--EQz5&eOl`t;S`({ddhH@8XEREWq@ zMQGgzX7(jwWoFLT-wfRxzI?}e)}>`piTecCW6hZ8FT;CJt*u}(+*$E^rgbc8c|I&o z_Q(L4m>}$5gAVk&cG8E%O0J`_Qa#QW5wXJ1|8b zWr>4goAGEF(U0X~)RF4VPl8r1U~BB{#x8nGGGcjrd&w5%s1Jnb{ik8vunW@crOD9nQEJU@gyH5p4%t&oJ(CwCaRHCv1)FGSP`a?ssH?9TL|#T+ct zR7-gN6#0Tv_LZ@GT|b=iU}DaW#J5cido4A&=v+Mn?w{mF@Y+IlLLiMB>*xANDT=Gl zcRRLRx2`SW8p-(f2H5d)j!2CxI%#VBugnv}Zs~33J0uO8cB!vYgdIipny$>>(cLVD zrsQO0)<7)}2@`4s-@gR=wSS;)f8*;_o$To~aL3>w7qyxH4xcTV`t`Bf$Iv%4Y15fQ z9{x;@GF}bdZ|59``dvRA)P`2>`2XNL~A|ZOn=jT5CP8(Lz$LdV- ztz&f$yODLA)8oOY<6PnUd{*7T+-IL3R1bb*d17Gk<-!qixPie&bI@LyrkkzkCTBvW z+3u6t7|EQO0wq-{%}Vcr-?7s58BDfvJ!uuvQ^%~2a#g!t#-=M~x|R!;?mBtbaM8HY zd-1HNK9ThY0&-I$_}UvUBys#zztvnd{djYx(6RLj#?N(cAols_d-~9)8{tK`Nk|uh zc!DTQ=J`wPK*MlB?4SR!VUh)^iNs%9X>H>jMz%BC;EK$I?JkhcBy|9hQ#{>)^RN5a zM67+;1)bsc-)O`wcTj80;-9%w(*u@Y`xgjuQ&Lx~^WIeox17a(=G&8RQ#bWzd?U8Q z=a-j7yBa`D;`(;TQXU>=8Kf)g-TnQij<=@d0tK~I)8pD3?5h_v{Jf9$FEwVPye4ez zbju6JSlE*doel^E&J8w^uP8~vf5>Gp1ecx7K7sYThmv$!c~Ja63t+Y_8Yu29O&jrw z2+&U##H4sdbzca|A^Of8eI)IXq-X@so49;v>AhPK(UmH1TP}E(Hsbm`79SgURPbI3 zq~J%s0nmI^X~V_dZu75c78%{9+y+`0=;h`}X9fqdlO*xe)* z`tLEjQ*1<_x~rGY^DXl#H5zD;F>YgJvzs1QMPk$*%wsiqpHTUO%Z~_qFDc71l6y2UZ+)fVH__?JhPQ;)WBA0g`N`_;-7aVWiG#jBP zkk6y|sGkJBH5CFXiM5cFUMhb1n}D=fho79~mTt!0;cm=jhsC}X)eC{$As@HhfoN9$d|9U6b;>T?zii!90Gk+-rs{jUK1|oJ z@>#XxlDHn3675u7+c;QMtP7pJl3n^a`0sHcl4A_JdugGbiEsZT(0RT5=pbo$Io=BH zvhvk)E5#b2oJu7`Md_82z`}7a%NhBbMf9hZRmmd}w|tz6o>^ zS9X&~!YmZr`!=g(T`D9%pA3r|c`4L_fXy`RD_2Xwr#?vxoGt6@{#u(DMaV8{x zG#K%IN=F}D#)H}?sG-|`E8RSycA=z1NNzTgKr#?=wfLjw<&qkTcPJMe=RNZ0pM!7< zNC{#WyofhXgAV`O9w6v}A?KT|CKXkNk_-Cx9p+hOgJP7HVq_n%#UA%l-;jJ#PsERu zV_g3J{Fkipc3y>U@ZuLk4y&Wo%Ix~Gp${Io$g~VS?}g3xt#uYac0}O;iyqq{7nfqP zlvQo7Adp+#;(qjngicJ;Dh?Vww|pV|__+Bnvf)G6MGqcHKEVNwD&x`lM|i%1EF=CL zBXMACrG0TL`!^Z>B{W0(m$bvg)y47uln5d(`=H?YwjVX~sA8;mk~sJ0O7r+(8ymQusBQNGI;yC{YG{J(8FGGkV)dhh=W@SG05$wB4CI$XOupbQ<~#4P_TAB3 zVdbgrF?JASk|f`I#!3pje{I$4&aozmw+uFg)8Ad|SK$&Gt3^ls3g~e9x^^iVoVX+5 zr6hjoGP1lh%#S44?M#Sy#XVrgaGEEqC~l|tQo_@}n%qyr@79#@&DeR4E7<~rD@9_o zUyc$=dsMYftIk69 z^an_UbIEkP>@;uB0UimTqPK8%a%%rMrA~AE%}`K$^q08@yvt%M^RApJ4SQD>bDHWv z-9u9*gz<^0zEqD;jeZEKG8@g27mewhB)dnzX8$sX=!U;AQsU=JW&-|A1zhj5u$nI| zb9?7M>M$)Rm-HFLv3n+TA|;YJDjF+kHfzS|NZ|&v39x~_}uj6P_O=m(a#TX zfH<=C4{hesMJ#fbwRQ3U3S7bIAWM$8n>M+t?`cu8UcQGNI~u3+KJ2@DOT+42CEb97 zA^VN#nNf@Sh&@mV)4lM&YD9)4FMKuM4(NRIi3uJn?i#nhr4rN6)lYf#^Y6qjVLWd) zF@!DM?)#>Nz3|O6Uv~Z`D%-jlk zxRSmYO*ylW^QsR_Z^tJ*H`i>XUs7{#M$Fh6-0jvlIa@5gS+8~~t5(f7hy0u_&JznS z>00o*m%f~Uwom;FTK9WC>WFFo^sENwZvoVB=62uzPNUGjPN?VT2kIm+<@)cu_g>|2 z@1?dnGw{aGM9YlK!RX4Sl(2)JcM@|iTkN-TR_ZLz1ih%F52?MyMfH?(i+r_O`I*E5 z>vVWJG$!|VT=e1g^yWM7HTRqBG=8rF%fYvPDbTB7hUfTRFJiSr(Q$FJt8c`}$m_$j zCd4!w7}i67>|{-p$`J|I72QWvl@4c83u+FXKYW797?GfAVra$dxswy#%Wne~n78tHxKLkq;M?`8WIy~g z;@0s2?U*;KXF@94rm% zWW-#ITM*B5&}}9l-K!jlnmjUeT(MK>hRpJ2*>q7JK5-#u+hXN4^Iy5U5ZV5V)Ja|| zrp@qNWxDz`w$)ZX;zKu|!;7Y196+pRktC55^4YUT8D2fPP~u%+J+~^jtsS_ixnKSd z={?!|iCfyTW%l4@xi+^|urqZ^o2K|@eso=-G$c&BJ&;DWo&EiLlTLb?b6M)<_&nGc zi-sOu9y0jXKA{92R_9pZ%^+29$tcm`V)d1k)r^OnnOzrGu^> z0V)wArosW!>2jthx1SIxbbs9*Cw4(&rzax!`jUEE-z=XX0fa*$tE zCnbXXfA&Y-88@ZuTXE%*fm1H-%5UaJ(fdr>kE<&VS3?jVS^)eHv>u+6TxTlZ>?di5 zC+d!$$i>ry|EMu`CV}uevho1I$}fPqDRIIW09~L;k&lkVLUKZtHoLLswM0*@zcpyh z+8oxQWB;(_XYONS_PM7Gt^WPKnuHNST3I!_@O6J+rV{-kq1|jidiUYy?HyKlZ#k zpM|o$Ub*ZQu^(6{Pr6#=yDn1rq1GPRWo0M|Cr{s3eOs68durjyKh8* zbu};rFY3DV&8;q{3w{5q){#WG74x7H<(mu~2WTuG@kepbK%*5D)elSkojfR$az3Q$ z`5dnc?&C4{>|i-L znAnCS@%k{*l zP5v;cn)D!dzs7f8b5+f7Q(eQGbtK(rcm80GXqe?`@2|Xl#?Uak@r(#zcRV?kF6JuEFjske1V;K z+D^Be^KBHK^EnfuWg@oA^DP~jd{1?xE72uIkgNRkyAbbHnIXo|P5fA&iFHix)J@HD zu{y=rER_6axctD6SIv7SQ$V>{j0(FqNyUI0Yz;c{3%o4o(SW#p>J&-LltKiSLh zdW^I&gd7HVzz#eFv?f|dYk$+M{p)sC%m3Z!^*j(0e*~#98iN^v1l1Qmm=~W`N1ipN zNyqfMeGLk3Tz1^w;%nZ?t#N((T@_wclwy!5=4tCX6uZ-o42$ zz9VtFle^|*Rr=G16xU$$HQ|K^!gK%RYn=3xr}oS)|DF@FfA1c4eR%?YIXT8szh=dV zBK>;(PF3Ca7-If?TmrxQ(<~E*V|^VS8g7ojR@v9@c!4ma3Dg|jw*V>G@4+RRIM10an{uuBrMB$A;n7c_VPoKaOoN*vn{cr!@y#!5Za2ZT<0 z&6JK2gh6n!HQ`Ut{P|_dzxU&-6=Q7o{m^UD-JaxkAhYUJ!?7jLpye+YDa!4eGX`n@ za0R@`r*9USPP${Y>+{m2^E1;VZVdjhpg6oQe-UQ{xf;eukMN!C%e_^9(Gbl%pUf+q z&*rnic9~jErxxSS7KD3-d)t5C%wK zukR^cJ=Gmk1w5BFg=Cjqnp^ws>3R^VI`cLR7(yrlzX4~=uvoV0Q*GFcbjFouyL^3_ zROE!39=LWyk*{}$NIZA>{bbE>y^Q|dACJNM+fA5n!GXKnGrA4KK0_>`MICJwp?^@4 zv{C>2(;l4A`|9<+Ar*7g8h0W2Lpd#RkK_2O>!8Yr=0e}{%@kFjnkGa5Uq2zjT3-F3 z2<;Hzar3*1nP_tc$_*>Y(UXDzVrH8W zT**c~?|$90!^Gkv-g2sPFR^PhSMpu$hHvs!|7Q0uaB()vd=x0EYTg|EOM7GX<&c?) znSU-toJVC?ulu&>b$Ni^mZ-R z(Lcg|WCrPhbCI(0TYm>j_wto4a?dEW{`Kkq9pSx>gw+GMHQvvwmdM74l_cauPCWD8 zQ=S_AblZKoUT!JE4f{;TBl7hF$J_SD{t->P2_}X$^|kL0qJCXR-evk(M&1AE3K>*l zctPc}Lz!EJh`VMzgp{e)H*d`4`iotAm3^|H%%jN?z$Y~e4c?mpdp03;QV#fdnhb+z z%<7qZy3f*nLIm?fMS$(w)4*K~Rmmmh+P`dvt9+22)f)F+<2xvc7hQd1>sdjNDz=#g zf-2`O?!KyZqifAGdb;Y@a!9iK)US5q+Syd zqMUTEYFVJ8;hXXqP++P!>u9~{R|xSvRJ&9cPnNeca`s)lD8<;%i;>bF87~<1bExim zHH2|hBsF{SFKTA3;U4L4us1R^labAAa_3bQW<0( zo9@_eUeG3t&>gp7-e)Cx5KPr&u}A!jljgKPP$@DGg)D@qAYqb@794#c_|dX+LX{@A z9WHu%98*w=54{eF{;b_J;JY4PpDO6WkjX4{!&(J)4Z`p!q2(TR#0vp(Y44}#TIBz@ ztm?;i-4m$4uzjWIYyQHMiGKc*lRhs{VKD%>mentAKym$yA&2Vrm~x!QbVDPa>KuMn zZh3d*Sm3&U^3E?9C6w%c-XF$7_+!FW1u+wyKJ9&e#^iGyKJjw*0 zU7rK%Pw9Hzf=VHUH%2vk8?ntk>3M;AtoF?Z*nV}n{t!iE#WY^h7cvLQk$J(G2Z zk6?OP(?K}C?p#o?jhjWZvS6<>00+uI*`w_WVXzz>>3f9eEwQ!%_ruibneZ!DRnVZ0A%LN|?ZhM>NVe_b(>5t@MK&>&riu?)w9zua{e)C7Cs)X>`OGX}CR7+Lnx~F6JUT#hUJ!5vGOZU`tDTYw7(#Y786Q9WRSqbCuIyKG?tm1*lNKKDvxpCK@d8;K^;=6-7Gq@h^*bcmv2-QIAsH?GK)A{UM!{l`gWE zvktwQf23BPMsAcWFeO&6X1)-+GBB;)P^h4_#ub8SmU`A(2zGx~aUJ0NUE1e()7^Oj zZ)BdCoZCQ?4TAoC zlI2tNvQYU7YK^Ht@Rz$-3l6GgSE7euK!Yv$r(LdnR0^gtl89gt-~p9JrWGymboQ=0 zKAF#ASH*NwWke-oIFPREPNa}=`9Rptf$6=+X`x7Km6-G1TS}dOOAQt6Trt~FUiVHs zTh4s(eIWCeY)OUR#tm-5@D$e3dWc@DXSp{0#bG%QI_5YZiQ7=82rzh49@%Mw1 z^yQp?ri6aa9R6)K?$7PGs0E~Jn!f34>#iM~BkjBHn#_X_j9GE^iquIBg1%3v1bswB zAq;e(;66EP?Nw(HrSpC5R6qq-&cfBt-JXxjd^P0||} z^vMM(P6u2@+&F%hJG7ki3LN{6dESlf0F+P#hHImxyg#B|A>WCTV?J{aJ&bP_46$lo zHOboF8YaB)RZ7Uqfb_tIgQb{c~^Nc%=?D8rc<$XCiY zx2#7{zq1zYmTa?iYOAM`Uo;e&qF(Gwgfb&C-%tBy;w7pw=`QPk4fr!3t=^A=NURwe z5t=j7#{OXxK+97^-bJ8x{`P;ySqX?JPkPKeI4HT(` z+3@>Ynepepd6a`5ek0EoqW=I`dto{D-ffwuk&*hlFm!lN|Ep=OY)kbFWkm;%nM3W% zw+ro?+npb+j88aW>{?`Inz-*rBOBq7UDrmc=!W|z1S~8+Hlqx?S%87wE5%KRTnrVS}@N%PqZ7IG~uUIc#;P2I5A^iJary3)sZe5_DoNc9?fd9n1G* z7ykZ&j0l$3gD*34T|Zr5X|H?db%#|c&pw?o`VwK=1?dxFhd$`8`&CKt>P zL&X=5huz#%fKz=uZln@gmgU8&$zE1tg~Qo$F%)a8-etKo)w&(ncBUUV{4O7^&mPxU z>Awmm(WSzE_Kt{uhJcc4o_TC_77NkBb-hK3^TgV0Ckq`D>znI%(Cw@sqF>CSW-gVn ztB`POQcjsZNy=7LWH20jM6^AbK%I^?05QB8m`u77`5Tb++Av>(#lFd%mTMJDInQh}YqCP2{$L-5TByUv!nI?$l-G+gy z+}m~kqM)Yr|_hLeUMIFlhlw_kSSWimzeDGxWdtLr> zhMn*UOo>$q+4Bc%#*9#zQ8U)PvVhiAl(+jyB1xziowyFI`Qns6aGFY5qB3JWUlmU2v(HOVrcY2j_tihg+a$zb%%j7J8!sIhc5#8A%E}LT60C6MSZ##m$0YqugPo*cEAW zq|A$%Mrld#+wucBd2-rZ+j$+Nmx40CW|($~z*Mkut5FLC8cWjO1-jBoqqa8^ZeBm2 zJL?~BxKLhBGw*eUYy$>1eQfzT`_X>}wSbwP%3m=*eVd$cBwpF6mEgJ^_B|lZmywGda~YT%*o8rRL!M-2*1#y*(kW<8yFVfa~lBEpo!Cnt1C;-P^IMW*&8#^*V= z-{SU_R9zg#yf%J2_;f2$JY~|Qc3G?q6}QMlkELTg9+XIJ5SXeG{Lt1hr0dS4JRb?2 zd}8P6bN5n48=Q#~w>Gs+{=1tV$bHgjD)E_)*+pAAk&Iodv$1kI+lyn|ZCZv%tQuWr z;HA-B`s=;|jB$?mwDH-z-%=iy14_o`gYkQJXPbgo566cNSZ#plW*6Qu@{#$6vpz#z z@6eqt4>QCNyTqY2uaOJf0pQ4YD(UWL@7@rL`Tb6!sz1C?@&5ipjkdKY+ouVze+EcD z(hL2#!zNQ?`MPb-40l?-<>{7<8*t<8;3HaZ4vG*TY5>lo5w z^EbG>UVrh_xFmz91WRhUz51@uS!#di9lG>PYH?-0Tet%(UtIIltq1d&^oQNP_X#KZ z2!o9SKBs$eYcK3aifm%e6X8wpcnltReQmY&8-Q*$nHSQwJ{Zo@TDodDE>dh8+F2-y ze4ZJ8SSPb90zfl6mWT!`29=y2RX*X2751#vk#TN1kBFoF#&C|p+t*{mmuY(sav>$c zpH{u8+oG{(uum+$j*g48r-G-WPvfjP4XY?&Jpu`!>kj{b`j@+t;EMs)Y%Vp7W3=?z zK7p)qOwV3H?7_ikF8JW2L~)T%XeePsL6P280vT>Rr+vHX5L&RmpYM+(eP}`0z|9X< zi~!T>0vc>S{0#adGfW;pv&9SIiv6KLe8+f^foF*Oe)ja#Uf~MtFkyS&Zwd}#GXxnR zpA(g+T~$^a@MOfz`QN!@-XI4)mu#NamYBDk4@?w))$&Pn>9a~yHe~U7UJ_^%mSYoH zYjGQ`@6#oI^ZX|GQJ-By>#r+d^ZM>MH51t>=>m>Daxtva9PV>2t++1|=ZVo{o_Z+W zFCK>X7oDSpz{C`Vw&l;v&v-h&Yg26?bN`LJC5QN(wD2R!kkDKreF&c{J;<*`{zXb= zFqf>(#77M&)AD?t`o=1oR%xVj9%~sfgkPf(5zYjCx#F@O5v>;;l@eop);yS(nNnDe z2;UdP3J>rjOz|6wFgeR*R4IhKo+dq!UrX+G&xYN-BT7A}14-nQo9|Co!N{4;i%K*T zXRH?zGJ$m#0L=XYTPz9T0*;638w^(l<_i(KvM$V|{|0MDnCEr?zV@dzebEXiV0HM` zByFxf=~soG9oyP-qA9I(W0!YH0D5CZh@q`(>@reunyqw030T)3`mS3=m+Zf0tdt_D z%(lXnjAlKMw}&l%S?J0-gTvJaco)=PVVx#qU+XyC95#pym9`2`4&2SezULm%uXI7) z)fvLC&{G3)6+^ zjQU@DE$-?xrpWA+$T?#T#PhPYZNN7MXPahekm%Qi%CWRtl9m2|J|DHQcE`M?fm{Uh>Y_!B3S*L4dbMj7eFP&0#r9)`brr{ZC9`MnV_pFdplE zi8{2$yOH@*`}bx#JCih8rWnXHvtp`^J^V;i;|tPNS_AWV06tl}jWZS172Er>#Iv@H`#IxJrM|KE(rKchxrqT zmo-7aW8B+!PNQwDBY*Qk2#5@u9je)Yp8ZiSq>K79*__7+=sMreO5`46*0!OSNyt<0CrnNYt66cl~+kk*gRo z8~2%thi~yA8?v(2NSFA8`QHV;|j+EPQ?iJjq7SMAdv-dkBRCktUyisu2eg;MnZ~DZDp9O7_GTu;wg>ih=dMwt1T) zy5%oj1lyU9`YVomSmVHT8f(M0GODY+(qCfbrzp^O3iPOP$DVhxSXqI)~irO+IF;>xKp^dZA?F!CA2Ld+Qu#JSvo22Y5cH} zgcy8;OTHKH$e&NVvoAa}(*5VIM&B=}AwI^UWX-S^kM|dU-F>xExN!G*uHZSd!RTX( znp5K4NA02xKL3tG)_uyKsi;nAvhUq8wI9eId2`#HPM0VoF4QClIE`}M7I)Z6&FQ{O zQ!-V{uzia&D*lSem{#?f()Z-yewjzSr%Pj2WiY#16j@eX)^4+%^8sOka!c@jsj>7P zFX+`EQ|zFhH}QfM^6*b^_o)f~+*JO^@!0%S&ec`WPPBx{)NOOaeMP|zPkO=bMcYt) z?)Je1KE~yjnE_<0qd?8WyROU#bj*>G-1|C=eAMWyp(btMAqINhA?5tWIM4#?zbo12 z0={zRfl@#=#A#KG_jG;d&AZb@y6aB)J!mA6mV_2=>XPHraREsLv9>CQB3U(`gSGVM z9@iLhqc3u&3uoSelUfOPk&v?Iv}`v&Rh049KmJYA>6$h zFg7Z2QV*dD4sd2?J%lEkuR&U2QZmd9{DU0cwj~(_V#B%Lm`~yqLhwkOY+Jd##!0?* zC{ubC?-LJM!AKHyx!&X2C-&4jgS`jFH{afLg|;3C7&+bzIZ_MC8(Y{BU9-w+B>s+! z+xv8XOZ1G$VpaF4`C!LkZ?9m@={pm1(quhsxD!}>r8Am!`_N?SDM2`>0 z6Jw4RaO(Fu9XbC4zYvyyTT{NI6BtvOB7=@jMBMb@>CTQamT#}s9;ut@HKn;YVH>@7mZ`j zG0;egc+S22*0JyfasoQhtxf2+gWKJX8b>Cq2){3MNi|;xCmXv$oz}cB^r-~T5qn|~ z_R+_N3S&M;!(vGbN3yWbxqm^p@>bWci-d&+=y}&vmv~N@#|)72(s&ag#7#e3dzT-P z3U9vli!~2vBlU8ln=nc~AqRtErN-*=KSBSvG3QpmFMQ8ZnI36l3z>z)h|@#v%F&Un zz6t(XDz>FbA`mU0MKihgpvW=H#^qcl%Y5pA`q1Xkw-w)*JKc(5v$4-4*i+Ct{t>a> z-=Q>Ta8F$t`mO#$Yo^J4xS{aznWX`<+RWiw3Vw>WEBEkNQyM6`sZp$YDLDOUZ%pPaRP^JlOjFErxuAF(+IBD$KeEs`_esb%7 z+^p09z}DVP(&<(M1e6ncdbEkBf4`;h86H{qG{vIp#QE;4neue|q4rX(t;kGFOY@CX z_>3(WNr~}Pu}zI3uRG$p`qGNBJO=yWN+U|-#`BWbd*;HTdOQ+czd^*FM8w!}!4zuJ z9OZU7B@370WLG-)Jk(oaIs=y9+-^V1CIntYc-0! zKloPts67Ll2!J0AKGp&le`My9HjnEx5HMEnziB`2^S*ge7AP!;ww51!%^1tKlK45$V!5^JAl$ONiux>e<<_z=Y{k%C&luKjI<{^S70UNvD5f zyo!fw#}-SgCraClVb+C2?{HpUK$s8l8l0Tqf6Sc;-uS@H#W6YUYt$g44U~P zQBzY15H$^4o_zG?V|?(9M56QM;6|GSrpKki7elFUHiBo2%>6$yyNCUrswG>B*%D^S zpsM5dQF6L+!b4n*ytBMY@oF)wXeu$+IGrg4yU-3G#bS8}z-if*{Bw2Z7%Eado1QJb zH*k5@a46<#pQlmMGMntBXLOMKBlN0>(t?jX*oZs>#Eo~-gj{~>$=xFismN-~elq{- zsA|=6s>+w2yZOMOW~F}GE|PYyIP+uG;nz*2rn5hjqE9IJ5d5O$+|r@vzjRkt;gz>7 zBg;2e>r|L++R;R9WP?X8Z7OFBD1PUU#6wHY7f{3<_}-AI4Qc>dKH?AxKiHuEigtuf8x%zK|h)z`a+-ddDTvmp*_1b z>toGjrCWw0VtjaL1_zOT2ezkW%^E5JByCUE4=rpw={<;2eZ|~r;klY%Y3cFt<0zbu ze0cpErDlI<8KD)(vnGbStS`B}+r_|}`U8u1=qU9NDLhnQtCpPTwnGHJj)AsxS?%pum= z>XU7jQFwKmJYJZ2QmS|<04;9?u%i1+g-|r)r#At-NX8H%I-ZwX58ieYQh+t{pa2Fd zb=zttj~QKazmO{5uXi3QR9HQUbN<&H6$dj-v2V|wCw>^F4;bGm*yrC8#_r2Ol2o%! z2CwFS4B)QBGECBXi{k}r%PI099>N&_Hy3e8m2;2Q-R5RXX0BUfc~AHet>x0}_uXZ3 z+~*nBMQ{}sFr{wn)i}d`&*)R}mml=CEHWn{d5F0FEqcIdx2P-mp*cZ^?zO0gw7}fSj#dT)vAeWI6MHe1i8IoWK!mZ@m z9sirBOfmn$VHEdImAqs{%f<_)?3xi3Ac$?p^xu`GZxZplCk%z<{h_XLUpI+8S)GP} z7d(*QX*9KzPAGg6B)QnKwL>lvd&8RLRchPWM{WwUx5*1VVcofY;WXv0&tlVfBAZ#wy75}Do4nS5@WG+|pYhvE4W zhs{taVMAM&Ob@k#))TG^SBcLR4h^Jpdwu8A_A4?2dF6&L&fSn5)oKZ@xrYWtCHM=~ z#*(+QmW6Jw`eLqf(wc_OmG+h#+E+{xQ6^oPo%%}GH#gst7zuQIPQ|St2|1U0yj_?9x9U}G{W5l4525C z-2VmzRa)yu_p@(hbq)9>nBj)OY|wI;S=E&9Xnk)_c0Aj5JqJtg0rr5JcTxcyAgT{v zf{AY6eNih~A&V8}uzuc|WPq6g<hBZ}EHEzLZ(;=>u{~ZnSC}izON-Fg zLMC+fJDf48&VMmvz7TMX33x_$t$KXWi4*^(qM)@2RkyRPR#qYWyu?dT`e&I|)nZ&U z0EeGFqu7hvz33vP^VmEvz4fjoB(BdTxz#U8G<8nS%onegGF-ZlNg z`Qbk`Sq9|chz)7#HKjl359yrs18m%^?YFoJ{Pe^ZjCgJ)6#6r4<$LwW#$U-?UyIDo zSzlEba3}C1dbtE&zQV@Exz*`@96vFyezkn^s73%H7=1eOaj7peh53=LF*Ir+-JUQt z()_byuO-dJ0{KVQH#C;)OcTu9h##WyKoH6qm@B;+uq?>gM#CX2iz|wt-nMCMJ!7MU zz(*?P?H1PiXjR8~7e6l@zuJl-4?i(IqVVJNm^ex)Y#C)TbQo`Zp&L^l{Aln}zU;{5 zXh>BrKF=o5F_X&H{e>q!7Q4+*fe62~0HO0WC^Hz!XJm5Insld3bFD*nHnY<|q?J4a zl`QcNU417ETfgY6>jDitOE(vuM;!qgv)gr|J2NpoE|Mx7Gd$uN@}E{9bZ@k`#C9BsTvv2DYP}HV^}M=x{>OE6wKXUo z9D9!^YJh>M|M&heF4Z#E3UV9ep{(DM)4-wvap8)0fH&)!@=nwX-tTqi&9mLpMKf9jV9_KgOQG%u z=s7lUW;yb>T`A>F<(dZjL}9O2O~YTxsg#~Sb1OdcE*%2XOlr5AA+NuY2`t4cU3%COap<`g>d)!?d`7fQE*nL~)|%MLXH%zw^)LwV+U8o6JtcV)=~> zgvrvi?JCIhGN^ia|L%tN6A&8hkhI1Xn3W8^TG^lj&2-SDF502~eQq@*<7u`JN@M|G zYyB{Qs8WNdEtm@PW8#aRcRCFwy;6(yikl2$<(-fpP7!i-=mg2xV?!Ij|7_w^$iQ{8@p41$O(qVl`*;#D+!`QZc~N0e z*D%X9oOEXd0ECxMd zj=r2|c791ON9xlQ_Up;KLd(^N=bV_BB_GAxxcaK{-aDvz%dMfD8h2ai7;XENgVIu> zCl5JDM?Zt0`|)n~hdpLY*|oZS4X59hg{^8?`L#z93HET;hmnOI)k8PWx3!)In&h|X zu+0pIlPrIWxmYVWG$rx8%8geoy|F_+DJao%$qzAdeLvf~;#0ew_3mcNqG2{}*}Oq5 z&Ag~}v)TeAV{*2#Hg!AS?h#;YsBzlQ6eHXWf3&#Sw|hOGCm}JE9ElPK`~9Bis7rqs z;OcoE#J2}oOK^S0x2j|oCW={o*TlRQPl%~4F@3jneF{SV0X}uB>I^q?6@;<)swNB` z%1=||0=orkaIFDB-Z#MU$X~#4%wBBH#52>oANImi;PSU!%#{TLau`ASr1P6akV4sH zuxjiETY?GA5Se4e?)^;MzbAWckG!Et=)r`}3?HaJt04J7FRCjRu0{R+xP3c&?p8+w zv6+c*nN5$L$F*5_OX-7)15Vl+AKRk?R&!BPlrf)ubruHBwM1w659v1>PMYRg%b{i5 zt5U_pVg=6)Z?UW{>V<*5%)V3R za*a#3iA~8H3q~Qv&#}0sEP^XufYT#a;F+f3rsn~7gRrOTQiPW$Qu?tqpFy{^QDK37Ar|eu1a;k7z_P0%2g{uy3afRryM3z0Z4pS7P* zdRuOwDk(oDIE^cN|JGowv3KJuTkshCWImAf_L*tbW9i_KIj7|<%u9YlQ=B@v()utZ z{0P3SPL`zomN%fPt?)d_K~<+u$ANVGpfm`52CL-}`61OK=K!1G@HbL31q8@EHtkNr z@}G{hTy@>$@|J#GJJ)!Yk3@!&7tS1|^rRlS%KVAmcYLNMIzA*(m`Jc;g+cUpK2{9DJO2u9B{K(rZ&4#FZfoyt)fbP#4_>3H6+1svnT{p8g-HKf>0#FZ`aXh0|35DPk6f=5 zJYR#{pUz)A=^xVuQgB8|&h9FKg4kmAwYDe9&z{W*!z4WfcQ}Ma*D}<~nZIF6LWtkK zJk0(SlC1MsYxc8i{;yLh{iHkmjqSP*39FOX-O|CNc_OR%qim7x{3+6oWlot>4z8si z#TKi~+se2`xJP-v8|S+JrAYTZ74e<&+91vT#8c(ZGc?t95>=7xFSs-|NaitLs<5wO zI-lhmhCRfL{Ov|b_(U)nnCuLn0C4--yCOk}1l&mFoIXmNM0$kgpUf>;3wqA%t6{73 zbO)c;47PB{sJ$4xnLsW?vJyYwr+PNlmv5NtMfjev6d339Z2b%p#2sq9t+h~q9+Tb` z620iLu@ba=Y=H*es#+ky324Tb`0!lzsanl8hOA#neN@gX6<-a6cutvN4slOorcJmjn))w}5wt*Tl?lGLrHW$k@Ld?SNN% zgD~a1lcEvtI5a+Gw)MPxyyr>7lQ#HiVsHO!XL(8A*Exi4wP0quU+g%>CSVN@2lHM1 zSIAGptIT;>=;-WVjda%95MWlDcJr@!Ocm8P^sbIcB|3?M&UI-$R8H{d*QFzs_i2X& zUuX|ZnlR}?JW~s3&TSjuAV!(ogRix>6TdL&4O-^Qdo7V{>H|If&g)wT zcvS`nC$z7H#`+d~uLdt+<47t|Jg5KOC4WYmsp>VG)*GYc@3`>Jb5J{m67uMK0>Hf= zXE5%G=S(u5}((N&937nL9%7nQ@Vv7RvVKW;ba(|gG1JHLn7&K`V(19 zaCdnZzw;Vb!L)mmeIEB4Nr$SiQ=eFs*$pb%Qc;3Z=L53Va543ztOds2d}sDN!jc4} z;gc;J&nwva9!y;yM%k*hVIzIk_D^b~zoRK}W2004nl{87x~v)V#4OFLLmsewJHL*- z<{e=)`sNf|TM?|^od;&YUUNK28<#jC?&xIT&Y^l@?6uDhKZgafJpZ*>HjJ>0Cf0Rn z78VYZZ9VxWVpS8vYD)tsKJGC`o{zPbLPr~KB5tcfXzjD0Fj=R0+?KKh>m56l3@PP} zY_GGbouIXoKReepSq}TG=}JpPzLT@VN0q3vbY`ZYdN}ycEK8rcW6!MYMKrr1ofMa1 zwL;UVwgb20K7NEyLWL-7hIg*F8d%6ie?;xaH(1njmq7*<2Ac^-mwpF0anVeY3geAH zcZ?iSW^S&oMI<)Z?h)rY!4*_XQ`C5$vz_6BP>gfu@!-ikaJdLg%K)GIvl^64tqjHQ z?H=<=XC3>xvO>w!Z_^6@D5vLtzEZcf(RU3r*eXD#A_8Fnbhl=wlgX<_qo+eA=iVP; z4lNgi!o6WuH)?aLr|H^gHJ!4nkUvh9EhGCP<-fTHbRG^P1j~_q^n-NsLW80iJ_a#9 zZbXHH%mfofM9`kXn+$x-g-QSWS+6Z7I%}WXKHp_aIwBzny9KnN&&4=l=Jj!@u5r|` zYHFOTtKDn|-bbs(sssor&-1e+&iN-_nGnODOuUgZN;sx$$)Ne*4q30qLK743o}Ibm z6xG6B7hZ?Qk-}QkLWaztr6skq*ETzfh^8{OWDW3bj2yIw1M|CqGG#SSBaD3qGHw96 z`lMieyPfgnOB?i^LSzOygNK>seWUAd>0GJ0rNxA9^8uWKJV#B(ITHtB-MB3+?qYS+ z+blf+BB)?M{`}--gPLP&sfp*_;e9SKu2{X`er`S%$m#p_O zuf&NBupz_ZoL>kTs(p~(9YYNJBcfp2iywT6Wd=|; z*n?3qR{~D>=cjv{@38*_vwDNC764zgfEz*0@MBZ2K6bLM7T<@-?`WPtY<7?LK z(BnLSL8RkhLLuRsf=+ZmH;8&##Y=vfy|3d0U9kTSG1;yS5H5#rjZH)bH-jj)6)< zq_+>7XbtrzdCNtveYcYX+_(&?Ip)Fpr5Rsb&PON>YUFVCS20DoLI+lU~Zte@f~k-)ARC%ql~`sAkl z{w646`AkaWJEalpd(BmPCSoboVSo={Xvuh`_gtL#bXVrSNr3adn-r9oZ0S!29*bn= z{rGMdR#L$g@C|_PbBTdWw}JC-(uQ!GW(Fnr<0DKG!2Mg5%&7*>40`MPjQrzK%uP)i zNfe{@bXdJ4H&u5)U)XA-vu(1oh9g8|@Ov*EAp&b#jmE}4jkkRxdB0LE^4ySBBkFI+ z*lbDrd=lLoPGz1}9-6abkj1l&!K-Oo={X|7nG8-ac0|5@ntbeGJUf(*Prs(H&t-ea zE1#2&g{8B(r@J=~6TLasVsXph?~8AWo2&s(%c%w#ruxs$!UVRcnQ1Efusw{{yc+yG zbdA5doEG^aibn8Ej*UmM@Ah%tNc9c#Z+qi~O5Xhj`S5)G;N2;+9Y#ZXWXisGX}%-y z@I4v%{A780DE*iOfxq7}p;bA?PrL$hot2y(un^yKE8kf!z#Ljf+HbLfUbLU40 zEk}MBOOU;n`wo>e@zEA=g${yA_y@9L+E^dHv$Cp>j1QVf|mymvefe| z=uT=id^cW=hh6Y~7`J8_6CC8NT{r)l((YYDtSplu_xXHlBc(!WzWAcHQw{rcF{(3Bjm$H6-h zKZ`WQ$G>8_Q3x+X{hcFo@%Tqjl7#?n`g|||4Xp*UN;PNT;`+O;jx!5I`DIi(qhT;S zm0x`v8^@RaI$Hp7Ru$tjt$Je&v6E7aPBl;^=6@NL>W(Ys>0a~Cq^596Fd>NkM+9{< zfXiA;2gu5Gx7{Htmg-YLBIL%-S`22Iuw*#1lByK%RroW7j+C$<{KaoHZDud#V*qz~ zL?BMpAPm@RHd>S$=2-=PnSYuoD-FRk-S{h<`KqMd4C4b9_kyf)F^X|*raf13D`v6i zcez?t{Y$qSA8s!0tMWIO1D(+6#+PG$F_Lp=IQeOqb2iPjWo^aW7Ecm;5aPU2;KARt zLc|$aS=@*InGH5{G1Z*`*b#drG5ri@aa&X5EfYz3D4o-F%$P*s;y#0GeF+hj z7#i*Xa@fJLVm3I5}zY%ngj#_m?k*HiI-oG|$(HcrD^5xes!SQC%D8)4HueyD=GFax5 zg!n2a3|6O^dC!%4mS`15AaHESLi==hxPcJ+Q;T_LNUEqa5Nt(kiv98I_4%Hlzcehz z2o-%;678j9gnxGDM{`Jg9Oaq5DC=t-<{&zpbbv2r_b!BD%?fVzR`$lInT!1fD4W|m z+q}NeQ-7k{R05;JX8dz`G2YCY5(3N=z$t&O@-6IQnIg1Oio^ZtOD6w}O6q9!!)e5R z;7ACI4lML2no(eA=6y&GCsz2RxOn-7#R5lu3oCTtD=R(YWUR zEqG2M&JCHjxgM5fvT7tew8pK$3*lc@>V?dm34**e0zFl1kQgY3u-M1!dGJGrM^14r9JN|FOubu#P2{X)5jT1yiWL{?VR-`Pm$vc6#=k4otG^ui`k*tJWG>Jc9q-|ail7}C0GIpb{{1DJFPm?YeSD?>%C9>k2 zaHw=YiTEhw3_vjG&6;jx5)lz?J6Wtck`s*Mgu>4a=$I)ZTa8c@TugIE8?fBO|ElA- zN=G}x+L$FH@P0q_C-Yy>PnzONVitxwcfA0+(_yLAoacM*)U%t$q5jg{{oTnt^0IOQ zt~Rix6+W>igr|$6g*G-5fZuiU}!c3pn4+?FD9f+ zlJ;bWQ{oDEnutp&7>)m!2C3GA4Yq+1Bd_9>2k?9dFEE|wKThmX=;j?%Rr^<$kuNZh zPI|3+PoKQ^SLLu7KI6DRMW)S*jnq1aIqnN|n72xz(|9G8-zo&R_cNPYM@}|LhZgjS zy_byvDC)(vQ4qSvn2hC=m6*KXN9Cl8D#~g8+Yigs>g5Bc?5k2KrA5=ErJR`2vD@LX zM4zgRNJ+sntlRBtb3UhNsrTa2yK}Z@d2Ft?TBhRR;l*>?AA8szWYdaf&w*WX`+pW< zOE~_n(qAjb4qI3iqZU*wqrIhs(ufJSy89Wfuq^*k;tmgAbM;uJ#312wyU z+Vs+zKFcrCLll!vdAA-{vusall~Q^xFeTCQd;f&Ehy^CfW_J)rrqu0r5Fx04g{arx z_>ke1+~>?a&oy#=uHtQ?!=mVoVBAUR69McDx5O+hm(C-GrS%F0zzgrCz_vEAW`z;b zcD*^M{rB1E7$6DP!*iS9Yp#+7&r#?Ia?aFr(gEnq(xJ^+gT2a9>YeE}k$&9ea^;-g z8m$6eGa-a8r|U*=)^KZT+76-@dH)<2HKc;f9Rkks!vo@(t(pGU=^V%bL}QQfH!F%} z5exugt58mV&@Ih*pcpAR#7nP#dfJwiLa9F4&B>bdWFUC{c9IwM?twv?90RJ-q|L>u zV&vj(*dlOz=?J3a9g=^Nsua|%P)z@CPtK8DVN}+yOt2kr=zoSNh+)*?dH1-g&*~8g z4|w3Y8W4Tp(o{j3w2@Pya4q}{R>I*Q9m-qv4aT9Y+2}kFK!qwYCH9fV!e*hKj$l}f zMx>M|MrJV z%AcDTDn=^SM9ex^{MEvH*9nwX`f9yxTP2HI{q_&8Zr2C%emW zXKU$p9sM#^3^z5D2AlqU+9RcMKOU^dlond(jDzcbj!F7_Y_cE$_*eR=1plAxB)6*} z6}Dt#z7w2kJdtk?HdXr<*9B+l$Mbn}sp)dFCcCSeESri7Gv}d=Bv;{VB{33i|9BM1 z*62&)yILuqY0*)F#1zL*9^Hxt^75npD0lMVzbuZS*~-BCD@!XT*G;(;YfEK-ya8cI z4F+Of*N#EueLsFgx)E+Qdvz0DUouHtmN4_;Z|F&%);F}4UF}x*wC=e}l#iVkeQltD zm$8noMFoCEHVxq{Et*YHeHA%)kfV|*0oRR8s%oK3aeYBPrw?82l=wN~+VL=Jr8%v! zI^VKK+7an5&`elmzGGsMKnYc)Rg6Vr__k*~t1CFgm`8@;Xk4^Mr0JEs#wI&2oRMD?UYfh*KIH*6-2k zdTta*U9I7ZoGc0zRLf9RfI}%My`^&kr7@|l*_R4@XNists)U3b-viq-URj`X)!1V-rRoEJe0HbkO31mbXD(9 zez%V2Vrk_~97cd_pwQc-gO!OymIyX^RkjkmYBzDymU-A?hyoX=;qvk5KW20>D*qeI8x+o$gjiL}WL(~RCdKqUo`m#S z0$F2Zb+L?~n4U~hT(oz1+rP!SB4Y405r6PyuG*c@xzIW=*JSf-U5q&RIGyh0#hjn~ zFmnAVXx&UZ;dYDVG`UAS<@@Dn79y%8I#XDJ2TC*L>t!C>(;?pmBaCfs~sSIN~bGge(xA72(_yw!y-`7K%0{Oq3SqG?T21s%e;D!nm`Rv8`OZANkTYXAJL3JFPUt zt5uyD5-%~WpZ^8hN%*JQEowI>I`Ns8Nq47+^Mec+2K5IwEnJS7r;8QR&+x!RSG^zt zvk&lXjcZw%{WY1}E~~WrOS=2Do%$tv8)?)&h@5U5bt-f3wB&}m6G$gICpJ6VJ!ICJ zT*s%KpQDdVE<~bpTyuPjk#X)*bgjMFo02&@Hujd+-PLlumKXEUuejMoyTM=NX@*zt z0Fo8kyODNi&EGQAH6@ym@PUk#&-Fjq=$>eS;*;d+U4kM=*TBU^k<=~a^KpjADXQ|C z#XC_$b0dzst?d7x5aDp33Pmv{BOkg2E{s^wP}Y2cc#t2QriKVjt^=2tq5tLfo`BlT z>ivyOV$55)JNjB;UHO-n(_Lg(M7hNRFj-Od5H>`C0sIX)(n#Iv0FC<4bm>Jhl?9KIxGMk3uxBmWuUE81z<=ZVfC|5I00#7a%iSpDaDhoy5%3 zuz!*W5HDU^Eh)poBem~j?)rAq0boA=Do^G*4{`PlHP5OZ;>WWaj`kt? zN5TihWhB1mY|FOy`k!)<#DO(%&IL~6K{nfN@O5n$I*FC_DB%(`m`K(b2v!;yLoJVe zmm>%1-u*keD~GNenEXHX-uf@9H~JnWhLRTP8XBZSxAuIT}_oDf=axABkzyl@Jo zOrPX`wLCtvl|&}Bjm=jnmq94ypA#YQ?uQR6lC?sUh6gR1B<58I=DL|tPf?@M?rj%la6g&E%0I1W( zN$mq4C2yO8cZYYdF_<(>p@=Z?b8$PJ*m4z|StDh-s=1LR8&-<~Q~aq9Jq8SZf5 zRz^UVmi3XfV_hy@5G+M(tyPkY*)KkG;dn#6w9}!j z%zmy$EUqtW6db1*l2OU~ts6gCQ=W~@MgWU@G%wK7Qs{i2RHOoD?)bsd5AcyNS@X{B|btW0zjw1+* zYpp7!dh+4otyd{vF1x_p&0(#Eo;b~rYUuZD3vY>9J{Lj%jqP_on$aY?Jukl%^oUKq z)*Pfxep9n^(Qr#lV>7D(azO5HXZ7xs^{|&_iR}-!opvkNpo$Ou8ARVk>h}w70TTr* z^uqC$4NaE@I4i`n3@6a_!z?Hd9^qK5+-YP;tYff#ixL_VD;lGt`*L zqJa%%(uty#?C6xfTo1GiDkn#c-Og#TWKjc(RKEYd5feR8`@;V5 z7zH^5qnzrlONiSsq92aTXPtaLE}kW)zuFADw|E$a|Mxot^n!mp2!>StH%m*3v>Dc7 z@%?Q9xEs$YF}z&Pf55_;CKLd@7K1 z4OE1T`AoL&xaN+^&DEWWPM6J<^@dj?E{zB7du9vDoqKC5_%v`cAXma%siT$2fBK?Q zN`3_4KG1UwJ=whU*4L~V>w>Pp6^}yyB|Jl29&Uil?$gnFMhU<+37`Ql3VvPv)RcCH zq8r8tib;MSMr5Vncl)yhf8}CKqKr+)IDF{z>G6~kIOtj-yMOpuB?SD7@xI_I>9QDv z34ti2qbPp+t*=kz;#i^ci(GP<;&2mNg=T4}2V>t$F*bx{g|XF6%t!`Yd3e6!DFY-| z*V_F3FPeA7%5GQI9#$%^G8dc|E!HJ7_X)Iz$2hMn_sr$Z(%cfL+$y9>bxt~85}B|E z$CMaf(rb|qw-SJ%Fx)0AzAtMS&79%cnQ0<0^u4GToeuG%UPH6i&eeV|?=CkopP#kE z*XLQruji_Vz#m*lfsWl&8a;6D7}hYbRX>e2Os5Wa;_YbTgY&3yT|&bot(hUH^|VvA zDIBx12W56iUofnOW;gSGiwQH?B2@vMr8|WQ0b+n&pLhq(PXkN*mKgg3Na#H`t^Wo5NP4r>9W2d5zinTj^TS$~J;H)ad(sM%L zVp^rjGV_$9>go5xw=J1H&);W&5Y`+jzB=F2!>CAP$X#D{X)FAzt{Tk99&bJPTSLP) zi_8{@c5ejHmaL~?59%sJEae1`rvOrCg%*qc1t`9M9}0|S&ZwBw?Vx;{-nN8{aYlyY7$I{_NTs_WYfEGjHzYHy_td$(#lwfS z-G09^wq|>twP^qv?fEmuaZ~-hFaW*kgTCW?UwSN}vnlI?Z}2|GydBgDGIc)x#wFvD zjQCxTmCIROU!f@Ru-%Zx1%51sa?}94sgbMD*)ty5)K;M~$RL?IX#3%sErZupQ>mnGuksZisG?cf-oY zXOx9SDM2j0-Yx;JPtJ0iGc_$A^{8DvT=Ys&Sotp-&3Ns__jYGPPU)Z`e;ETR>uOJK4;>3&>c#Ik)DC@r9B`$qY%+Vi88VMsB*<* z@FnF1vPlV?t-*24rvVr4T&o;GV4ivG#&gISC+v9Df!3&Y<4cNNb&Q32=55|Hmm^bq z9=Xkb^q1F4-%zV>^gCMU9&Q;sc+m4{XJ4`eQyNERNiYH)Yl4Zeq4~vgmxRSbcN!w)cMc^ZzXE|BE3G!~zKk z((TB(KFE$gITCBTpsQTWKlj@^@6e`}Q*mz$#+&v$lGVQdtcSfXDYW#Q2JyZOtbs`F zrwxFfB0zI#Wb(5eE@`9nt^4;8Q$x>ZBTz>pKiAP+I-}yxT+BTD0LjvXzPGR#AO7==+24W!$zDgFG&9*B$$NnnaXlSN?n>=uNZf!`FPycg^w4h#GHnsO%fTG~@ z1=~K?T(({tRZGu7^aS;eFh?6URxOZTXo_sMd4|a8l7z19EdtIV{~ZPI09lMyIr?W6 z7GNi!2le95op(Rc3qjeEN#~v{2TE-I=VRHQ0VP04s>&32r9&RTGQEjndQ43}U!#!T zykASZEPggPdj3iSKxej$xMKQ0jCh?7xYJuc#PpH>`R7}_U(2)){dWKT_1yCP?|XrM z5E-yGmf$eUT_8NqK?Rn`f3bb>9NWRU9?|00!RtEm6iOP>Sx|KGs>{{;R&SVA_6pu9ZB)a~tU3v=__M>1_pk- z%oKF|4ZD`Dnl4V$hE)$R=i3+?S0tyT@aPx4LUJ3Ykt?&zOHNO>-Pzgs$@tM_yw)d+ z3eDKOXGwm{R*guPfMDvAd!uEaZ}w>XkHo~?yVlJmC{$^J{8HZUuPr=0eV~wF^%SG4 z7jC%7RXpBj2`_2Io)>svq(c67IHsaP7PT`qT%4Yt@J;+t8%f|_?!`B~`B;8;OoMeP z1cLJPv^2I|+~hMRF@2!MS{@c;kcK4iaR?#vKG1T$@sHMbzho(t(XImrcb&%S0B=cQ{kXqfI&Oz!} zbt}JT)=&?)!V6 zD*Lt8R(r_HgX})+HH-{E<)yn+ze$OdpGC6?f;w2CO3EFKWwRa}M`g)IYyKc7@^ZD$ ztvpDg$^De$(L{YK;_r>5H^gu&QFObb;`V7lgg~(A=j$h}w%luayiTIpayn^AsRbG- zytkGJD3tH<2rZW%q90cf($1O`Dzb;Pnz00sRwY=Y1ZQp{AtJl;<3jp+ zdl^f@Yj}fc>2#;#nsX547YU#>UYB1>44s|hOfbIp=ZsPWzuE6sC&TUE7Cz6BV)Q)t zc5*_+zT}Fa34^*h`j$|0J8=CT7McUpK6uQs%jO7{S^g9i=`JOEz<&EDbNKml?NuOh zp084^W7J0R{uSo$m!sOYSi(!QGQ3*m%-JOo0Z4AP^#h9)uEPU_Ch(no@np$+p5IM8P zjQo)7L<>R+Y@e3_hds<&$Bi@N70@DN2U48jxk>lFrF(USu=8)E>sM$A0XtOEBy2M< z@=fbI2U-(cXC{W+Sp1sNQ8fml{vZ!CYFPiaF|JO4Bn;*fKFm?Gv#otHyjH30vB0nK zg^fS|QJluP!Q`uzou*HDL=ZcDRHUR>fxxj;Qx@Ij{{Fs_tu0n8*jwzSR=f*#VU=^u z7PqvzA2gt8W(ifL8pUa!e7(!UoT&PN!qDa4FMij1mS~?#q?3wEKX1o zwovz!oLcVyFIc~}u;L9N=7^#lxvKo<3594y^#-hVmCRV!+{tT>W$V38Dt(`G> z?6sV>x6_=`U_A5)F%Y!M;@F8p;P4q~SRBY+-n$BZb2W_}i4-^xh;U7ldS4>Gp5E@% zCQS3?3m5I1@zX>NXU=u19U5EE%fr$JO}taH_I|aOm>%J=yiA*NufaQ4A_!Js>bVDF zH3~RAOIzF8vL84a^1Znn6ZIv<1)S=T0hESdl|WV~j)wyyV<$ny>k+3RX5Vnzw5L~L z6n+=2hn)DKN^};+k0e@r|H4kA$e6Rtmi|&&K!Nm9K52HAe}NaBM?dDRC_FHmfIr-M z(#onI`OyfqWB8>`n66Cl_UXZa#&3I`VH0)3Y}>-N1XFuc<~2pmxqX6a>g{RFJtbk6 z^U8LLNlSa|2+`jHA&_bc83z_i8D#UxxfoRhnK|TiaB72|!R4m#Zq7MuT{8X0ML-mh zd@6}scXpY*ks@XLGTh7HQnEG9u;*PPF8uOZ$hb~8SRfc&N~3&ANcmx27pXMP@I<5K zyGpIoLix#lwmRuf>9vA4IUc_iW%%2!A6MshI1S6r)5+}_tuN&E*3YAgt`Y`qjp5`w zDFT+l$&ci#t$*L$V*tOS$e)sUcabkF(J?{%I7pqmeDhtadPZP$IeMD+R{`Jl2w!NA z4nyS_>A2+#1Vf7@`Di#nrKyJEj-Cvc5Of6!S#)Tp40TYiP$h<%0*#18a`)K00(}T5 zXq`wOl>!eXOz`gU(SYW)#mG^T6#90|>{ii@@e|1cSEt$v4aZ&|cTTV{cbH_|Z!CH* zZyJL)lLxK_GBZIzdyy z`*5I`?hpeJeqk}fzM&Re8dMe|Q-pzx!DJ4@@0wcG4q&xvP!k~=s0u`D=m6=ph|RS# z68z&S!2Pwfl#;TYd8qBq(zli3GieP8q}+1#6_8S1s*x{VT^}TmY!zSamF#wW!)>CL znPYfo)CI4DNe!rr5gHD}#YMJip>=MYObS>(Ao*{*N-P7Baxrwq&DF2k#w|s^kqyG(pTO(*3SL`BHK>U zacgThk_QdyUlZNP@5i+&j~OVHFY_g`1lpLYt7?+|GSpwp1_tUm9~^8Q2V=kT)YLqE ze1mZ=fQJq;Pz4=`=(MIR%IXA4g2A|2$cWPCkJp(T-R=D--SY~SF+V;QeaZ#6z#Fdv zgYhI?JR~p97$kB!sTRM%0&#ub4dCzMy=3^w(_p_pnY%yN_86I0gwJ=;75eMU$UXV^ z_;_E2+N&-Wxta~b@r`v2K;;6e=fOCLwz z*w(?`jY`?vz(tE4*xh3l&R(k^PvIyl4DF|zD%Po*yjrr)bX&Ays`(4GFx?*fxWAvD zsWv8lXVbWw;XO&Hr5Cd^mRUw0e)amr`~1h*MDg3Ht7=kuYdCBKCF%N0i=*rYR#TH!`7N9+j{y%gBkl|4#I{T@f50a(SBz-?3K(Hv zc{tE&Q}X5E%Jrv9m3lEBP4xNm=P4jMde+wa;p?*Hck5&`(RV@Oou`2-WBj4t@5sbR z=iim$1koQqw+E_$ATrCX_lb?R%&uA5IzHYKfAG_lo8l-%0S??e$t>g1_kHmVj>K&B z>O)B~4d){%nzz35ue{zS2e#)(2He^1`N~lQ-Z`Deek*Kg`AGG5haBt2`afl|jjMUz zG8n)*{n(#!%P%7i25s%q;NS}#m3K`tB_2_ocsz zK(n$g5{JcAlm38O`;cg-;enDQ+RR&2dXNr&5{+|o5 zk`5?dR0Ung_1;eoAiv*^0&_SRuE zH?A%&dCzu08ONA8(Oe3U+IT{*qt+el@EV$jM7KX`AXJ{U`@6F66Y6Q_K83s3S+V`~ zFyVH>|Hj;g~1tNB{ogHOZ7h_UIA$&^^^YxaVGlxnDLV(m~LP4Z_`$ogU zV8He%pahzYv4v}fr=cF8A{lUi!lVi0rFy@z!bb_iUVClE(#xv4e8BwLqhFA5kKLlC zPa~if5kDP{5`Pozdt|x~7(uCJJ{+y(0TKSRnDdFOPwl{p70FBHUQm9O%KIp>6>!cA zzkI~qFZdJnxA~a)pj!pix*C&yitQBpC&n!}&nQwmeHUE0&uX;m+vPeNB!4SIg-#R9 zvNdrMC1UQNlKQ#fN)EAQzW&ovvCkIvYNgezsN9>rfy1{Hm%pFD;Q@Bj*jS{nqnbH` zePH&_7M|pPOU!UNjcB9F$#jY5ITVgn`W{s~-RqzbgH^bDUMnseR|9pQLcS>Ta-g=> zjS_wQQ{9@MHyoBPQRsQO3aMnFPS>}0$z?;j1Kb~ko(C9|1lD}2nnxDiZ=m9)z4-@` z@O$FE;l}!k!G-Q~4G5vv{(0=bK*aEhTSdN?2QtYM)Fpnh+u}G96znhfiX?8FjP#h>*08R|Otf z2O}pgFm~x&oT(NY7A)9^677;hbBc&Y0lrl*c8ZuMlcL4ZkQUeTP5WiG9sAwLYx?Qd z@#Ws-E`{_~2&zt+x1`_$`#!sutF%`=s}zs8MH+ENr5wiZg|CbRC|U zjc`$_9EpxNctedH-O@t`-?|^<`%39mX(O+=lB#9&O#CROi&;BV_r);c;={uFrHgB> z!*x{r$UlZ41c3u%?Rt8dI0Sl-O?$bB50;LSIG5*83K5UvYAem|m0hNTPSZ8!a(hhe zyZOJ;ZkdVkqGbjv*;f8nRhj#`{AQbF(QIYJ=2bHXlCMjbGVW~V^xY=}IGaxRm9^40 zny_K)Z2R%525<_g9c*P3n==`)@3kXG3sqAKmYF4<&3Z1SC{do|UzF{f)++6MuQJ{~ zz24G56@nzFYQ_=E1BpU;A%4M=*~&DT+-+bxz1(^)x&8E_sT7kWLiy`PLIUYh+0Vt6 zkLB)@?OjRONeRzZR*HE9%&87vOVJ^SY;Xu}KdCI~@2{;rfCkw>%>!^cV?!lL_o`j? zp|JH}+RTf}S`wtc&xM-?9om}96rkan?Gf~^ zS>;nsulWPIT``Ss_8k!W1=W5U_`cC(mD3#-b>MoyY(5R6p|o8f}KY+A?Hmg5`bixv8ZD9PzEl*fsG_ zpoxGjN%7^BexXu9%{-NfP%&ITx=T5~@_QNnt9esg#i_iI_&kSLSsgrdJz|GouvqtS zSzF}@D$yHJgN4f3_|fhUbZ)ha{m)wk>HSd=NiYTpNyczw!Nc;#GddcjALlD4so zw}qLeu?!dS9YVelJldr-e@ttrHU}#YOGS#ja_G*kvfc&Q%&~17{jl2#WhNkzY0K&z(cF!{h$w?!9m|r6)T@$>QD6hB`R~&I^t(EQGgep<@$Gy{v4m6 zy6fTOr5t;oP4d|!v*nI^#N|?E@}TIGOQh|8o!8I9A5fxf{no`{CFM`JW$t36j$%L- z+)Ip9<37Ksd^*mL_v;n9k&dNnyg-Xpsp!o}E&>$cpK;smPU`-_Yvn}IQd}PeP)Ara zyOhVxzfkKm#~02k;La&&NWI&7AllzUTxxwM+Mf0HewFtF{%(_Ow~Al zK)c2`wNxwEKi!#H&1aqW5TEq)e=BZ&YZUOK($==biF#OxDZ}Hp1)}}rW@~UR_3sn7 zzQ@0@DPT`eAmJNJd84cq;JJ3U$`m|%b>O=V2S+$vt$LTi06r%B!#`aA@jEG5>(7(M z7=5Zg2YNv0jd2!zsJ_3#hPvkgnyoe(MzgIcWR_MrCFl=<7Zh*&X~bS!?&LvWf0=N@ z*6L#-mHBA$Gth4fG@Mmb%zwy!a8#EA2U&7}0u~H=$Hs1)}YdVdY0T`b9U>pHR`I z$EGQFfy_qpC4H@|?_L-8FTBCZM7D*{T+;M;$R=V?yAJ{?Qa$Rq>s&`pcH-;>z0OzX zX0)>%%;qKAHdW!fG)^nm@(t4;=9?wxpf>I9^xx{J2x9wd00C<1o5Y=`7eF!j)}kXK ziQ~RxE1<8qv+UgVJBR8B1LEaO%-x(fxOnXksIRAv3hh$dZrF|-cWIOz8=?jzAkDrW zGLkkJp*86al)IBRjT2KVz??mNc14^CRDJURL5Ab|#`|H5TM(WqiyW29{N{vy4_kjo zH$@e=Ua6BzEcAJQ_Xb&URmFF2nD^DiQNZh@qLxAvjG?-gW6nvysp;=S(zed-SQC@} z;~lG6!<^xvQ{2tWl2~un465l~NX9e0eabvZKaX|DAsU|vuNxl zD+v=&-DA>Wypq|^O){A5ATigw4>$a~G!9s_o9e#}ecT`chX&jO%r5&qGriUCj_Qs- zgb#i53gsR*uff;HEct1A+K+kvOADYFnLw|nf9y0kiMKKYzqDVJ2!7Ig|MLQ!;jIgR z_!QG2Z9WY&MiEAB1-5%gBS39J7VJLO32UJFGs_%3(5O?8tWbZ z{7(+m%TtcmM?!s-Bf6M_K}KA%y`vX>d*#}(B+?>aCZaDH!GIgbj&xMwsL%I*{=3fxmFyuh1F*# zEFS|ANNIrmj*%Wo>WIm#N-noo3<+=Q=bLMQwV~;R@Q+54%4ZCj957CBsG}Fw*>#ne z6=pKbxiD1#<$S}Yg#m&hYAZ^BD$9GEZM&AsS!o-$kDW3UiTY|gTytzQce`Na+H+|c3p zL0H?ZCEv3m7q%8DupApD4&SS`S$Hv^i;SaTfBbdp>Sl9Iqp7|k`t^goZMWCjpB9?m zc%NsNuD#yZ#qh(4JOc2^J(GvdPu$yd!}CT@es?Z`M^76p1O3`DHEsf#cfGJIQ*4w&IOXbm_k?+i8(SQn>QBKm2@xM%1`z=D} z2r_9M2pw-10#qBK<%V~Qa|a-4I$G^8#lD;?K7IWg zZd|PR!T_)3Cl=d1%ZbcY+7YW{zk{q_Bdxs zBlL`6V@XtBiWR;VpUCSdk(2Se2xq!(xd__m9j`NeT8|q;K<;D3A$>RZ0@k`tiL#~$m*Iahf-CsL)#P)Ti`Giush2eqdO;|#Xs>pCkg=y8}I8H``~( z@^Mh9vRk0ZfH}cd%;!K4?~u)vj`K3fq&lsGr=WQH?Rgh$UQLYJ zc=84T4Ji!E{m(mT<~eo2f1rYsx~?D4i)ogz@y5UI*TP1%FrR9(5c} z$P@ikzfYL_Uf-->7)xjs0JT!SaV=Q0p~aCW=hgr6bB_`p_oV{?YG9jJ#Y5 z|MnXTuQtY`Dve;wQQY453P88CS_&kN`|rP-MgtSX(b+``Q*Ls&i?B{i|I$m7SYEGN z+f759L=sQsDM%ulAFaOk$mRYo(_Kgn*^$9l2!pl2oPe{BV?)^(4_ z#%a_ozthJRt=3<5jkhVVGa2Q-3w!=8EzLsEI?C^n4C@BDkj3`O)fP=c3N)aWIr~e? z)ma8F`YZE_2pxn(2S!K^Ogm#x-gL2;2|;h*7geyunSZ^ATMjNf;g)$lzO0JK>SAu>3HU&F*X&^DeeMF(DU4l&?h7VImVKrN7O z$G?enD1PN188>w~s{|*c$^7)-Mc}U|jU?(Hsth_>@kKs~o$O=Ma$aUzcdc4x8liT*D-B{5EZE z*%vd|SQQ;8Tgvd{bu+zB8Yn)YX~6^*FM+C1)$pd1_?7%3am#Hh!gb*O*9)~}%I~5? zH@`k*`g|yUdy0&zoN%I3!n)sn0L*7i3Sg#PZ^$tO3h4FMc@M*B>-+s~ ziz%*&g2P>*4|M@8yG2@Zdbq%kyW*SVgW>mzT>EDnNCi|5X-weLlnFz?J?{x89_nuE zQKGFM4o*T43Q&;b0>@H8O~hPTMd;B;bIj?My$)>~Lj}!{hv2qVBm7D`=^u=;m;Ij} zE~V5zNAHqsI9!YfXeqwh22WlwE)6kIH)e4v3(_W42lKajC9l*MY|m#Qkk->mo*c$_ zL8a1Y+|>%O(AbLJU|pJpNR*Nb%lHZQ1*t4R92Sj-*eyRej{K}>T$~G@NUe+s#)_&C zl-Xk=+20}Y#n4WXc&t#*Tev&nEPYosVN}1HR-W(5Yt`^; zEjN`L{240O&Bb;Q2n4ygxrNC=6sNG0qY7U)W%!efuO~{+1Mt`7F&fR) zJGtGsDY@AK+B^w;MWUETAd76esRMn{0FNjs3HQXz9sN)xk9trCCV^8VI&Q1h7v2Ln zFp#6vcKk_MjE9us24vCKvpBbd`R?lJv5fsTxo7ZH>OhUGoPHVb;_-^W3YuHG_A!gH zuGKM6)!xP3#w)0MlFLGN{wjX4pnmv(nlasXXw2d73hLW_E^p(|LwfvF_?4Ln(Mgcx z8bf3U4juK(+*VvIeb;4Pd92?B|KjYFUPOgQf~6%_U552kksTdq<=}*@pK?z9uABDH zx^QQtJ^BfvMJJ8Z+hCK*z`*>LaPi~Kt3Q~I@tfPU2$kQ&u^7RB@h~R6%B$^W_|}XQ z9qu7)Pwsm(q24@8RS^b^^=fK<^MAUg3pIHPvAr646j(O7+x*8mP2%{Fw?{PX(CIN%*oCZXA%)OR8sV|p^}I8KUW8(;c9 z773dLmEubt;Gp(@UJ5vwzI#56I3cmP56r0pja}cBM8->Vw!=%~!`V(*bt;96BWl8A z(G(aGuboGQbj#g{Sq~)_{CfNHtB+-Ije^HzK3Qp*-Q43)bHyZipz*o< zpiA!iX|BI*_XNc&9g$ZsFu676Z~fkW&k?o$`QPv6R~i)0Nle~bqY%SO)uIpaRKOPc z9YI!|J=%o51!&StCR_TwqrQSj2NC>auUqD^ZF{)dFJ#K(Hen~y%0yTGTs)kS$l1N> zby#9GGo)YWt5hX^6l1;*ZM0bjx-!|I@1n)Uo1W=-kc@IK*CfBAP@ws?AOrM@DMUIL zN`|s1?gvS8$|H%u4j}a8m)t@`71oq#{Zbic{}?5I#^PzAC*Ijd)4$uRIZ$nhR7i<# z-H)5Q?4wDdqM$xd_W-c*1c#u=(66aV+r>Ub^ukV&it$E0Lgud%r62Dq8ixjj;t`Wk zEYY=F*6U9jc29oT`UYJK49ZdMs)^3YXY5u8Cv6>1l27TbIz{w%YuMTzK}l7X-PbZN zy>S}SYLM-|XzwhHhx(zO_dui6MG=Xq6<%xOH?y6|<~5VYc#;c|R;wsV+%2Fi62%Yf zTuX2BD?b4xexb6(2EmvsiyF|`JBrzTSgx=b3m8Quwb>-$nh%HInWe zu{=Zx-wAHT78gJL&WDc_C~0&LHgdncnGoQ^1~C#MiB8jyLf$2AI&Vld6Ci8|?#?u# z-Iuv9JIbqW?t>%x;hWTDYWnFdN+*DB1sD^A3c8sg_hc@@L>DEb4P;|-%`u z20<)cvH%(W2rCB<(oiFsZ03YKd?9yQ0FxeJgh{O~qEh2YrqB%5CYSE{kj{zCArxB=rvLH z8BtH8=tA4_X!3gDbBXbNbMHoz*vx}^jWL5`$p2*84oo%UMe*nYYUp(oT^s8;%3&O;q zUfwuHg*HFrt1d;bkx`gJe~a9bnBj#L?T@@cUHIN~YAdM~+kwuZ9()1GY?p6pUp-|h zt23bZhim0I<=%lJL7>7GqdHw1h`J5vGOI!Hi|r4Vn9H8d>_c)i{(BC?bnn)dd3TEN zUZ5gvk^~yxA5_)+`*)lZjk~<;ed>!*M;;c8M%9}p)6e;Ed>XG{R&u1q=h^QZQA5S! zx)~{uTh~m;Y8B}r`RKmpTUWi}wzMB23+3V_wnMya?^N+(^70W4hpM8{dCPqohVEPG zTvG*EI z@_mm@ul^mHmXY*>BekQ6db;A~X)eAZx0$@`;n1Ub>`~ zePd-|X@jb**$bSNCcUn4_z(5=+ZZncH|?PTV6}MRF0>vr!R*2Y^SLP@`K^M=bDZ#)_%O>D}q;R#tt-?d^Tsq^I|#OS(T6 z&1?~A|D&vsgASf}B2xc`{0?mImT3 z+ZhwlK!uH2wb&q#3*ggriiX?pjgvHV-lbeSX@0k6+fBAc-fU9JdK%y zBHhQSyiUsePhOSmVAr-M!+P(hA)m6I^k6|-tf&>WJ6*QVSx_-?_|0i50}<(-8WoHF z#<}-SN(r|b)y4sewY9fMtg5oNhW{X`Z57m7NI&CHtBL0x|I&q+K|?Tci;2SdXktGr z826pNAQ~^y3~Eu+Y3ovJ5m+=aS~(EWsz9XCAu2Tz*Q;NKVtWy+*t5T7$_T!Av#alx zo>1EKm{Q#pwe*7x9*8}y$K)X2@?TT4(b|6c4KyZbx%kmX_1C)ZFmz^>t->n~t@yB% zx33=>PzqBYTm!sP#2Q~GwaV(>zAn9{c4s#!?f(+!bM?No(#TUCKIeZcz#b}E17AFc z?Wg8GjEf&1J^W$bCTaXN-a8PO+lEb`f2$n@lPJtOwB&9?hDrme zkVYkWGS9Fx1Yw;P3B!@LH#h}5TmlN_&}({xA5Pt^`8VdhVXefsWV-?_`!R=lAn=50mfnB-jV7gEYtzsow!VRmm<*wslyLy(?2XJB=x5?reyt{u zxK>Uo{_L)B{Eqd?!RcLcqg2iWG7@e>K8LnhM+zTgj%>ddEz=WZ?s)wx`BSN0w$%?) zJ7gkLRLSYCRXgpadH8*8tC0D`YEB@Y21mybKb!Bz^nZMHf@jDAgMI*0!gb-p=nwg) zN552U;Yv_bkTvmTg;NRp9I8Jo|4C9ddH99g*Z0IaTTcLepaA8@Xnd*LQ35zPUgh79x)7V<~Sa7LZ=!8XXz`8|wF+W}x~GSGg$Ed`mPBbv+oBn>v_|1kI0 z`Ax@oFcy&vXOAa<@!EKSg68ev{OH(7f%y3CDSh@36;xo=<4!N9-rKo}_O#VyS{jxGf+7T>$2HMOVP%?q^MYtGnDCNyfr ze@eFsq@5sL@O53=H>M7&_@iL=JtMQi*n;0{=sL4uj12_r96|Wd46g$ghTv(ddWUvI zH0D4#OQ5qAY$iqDK`sQeQM^i|7%eM~8=-d0+LiZF@=Q=EavEyd}FhDTGM zn5=M{1UfR-hjcUUW;ijgF8DYepS$=s&&1jr>#A{&moy06CMbkqAnJerf`xBtfGONG zDO_JB0yIjWEchleehy0P)>c618(DO~&M}Z;*=@-dS}uV3=L`*-<1maa3KC6oY#o!_ zmT|I^YF|1ys#p3Ff1}wZoAWaoW7NyOc2nE1Y<#_{*D^s9*iaOm&#CLknZ-pBVedQ9 z#0`>S%!IP(DZAsPh=kvx!E_p&a!nQ|O}Yn$f+b`8dL!6jn+DBR+(8yYwiZme(q4tc zL`DjU*gH4v8d8k1)PLiWVh%xAFBJmnGyES>yhJCd>9Ve**kLFl<&qLn6OPsGmq!Sl z7_^@Kr^1o+!Htq^EhQZU8mvX14wMA9oQKC}?x@avxPJQlOs!35pk4@2przL~(~Xnn>;#JX*N>>f3+%t2{rd-{O+xY)6;S z&Cq**?$pY9YvR*=Vt=;U&nKWM5%+j$`1EmWdT}BWk!{UuFS~|QHJVMV^!d?g%L0#1 z+a_V01+M_yE|ZQX5%MxqUx6rOQIR9jVe%}CsTrW8X$RY!8!lXfDQo(JH@CIocvoLTB=F*_ks3Ftu0Vd@tUe{*FZ{`gmCZh3Nf|z4$eS zX5w}UBXOREJ((!#OFE86CDd;m16glN`@0Ptn3HrW$2D=<+-<;i@k|RKb!wO-R_NGn zg*2;qvWz0r_SJQQhH{nmq`8sVmNI(ojUXqGhJJdv__5^oDuV2Ww;CA_jB9P4?7mfAGNR#nIpe2!NCFP`NF-9 z=MQyPv{uvNbH%h>zk7L}iEp^VZvI`ZW1_0{7BbOaiRHJlwg4(16Ks15XJXLPM(fsA zd?Ze@8-yACc!-rO;YOw=R*V1Sj%Hq1g5Dr0gn?`AcGUe~=>->Em!{(KCsVhpdIE#Yy4bOsVx77b>w$ zaTsD2-6JCNqt=}Q0(7otGiyxU!sm=#tu^ZpbW3@k?cVkRgp^Wbq|&An3h%Z&Y#rZx zh^2V&{)lf^d$2PS$@}O(QNl{Dj2yZd*M%ad&6-1!yEddb)GXS%$xFnC_s&ncdMv*8 zo771{{91>icx_CDON*ltq=my_&)}wNcsqLALF%VM=4Xb&S9C$d_eGXJ%51OlfS9nS zdu(7xgV-o@fZ?w~^vt7VlM@Ok>h%_(RB^7-N%91duEi)f-l>(t=NeIR= z8E8yovgc=(FH4hhWxEJ)7UsgTVn~>R#KdZM>I=l^rw3t}(<5w4#SeBxy)c*Sfo5by z;{&hBH&^0ZP8&`=gj%nYSzkp`l*JhLyQ46ZFBh`PVrk&U$Z~AqQo{gsl@EzFqViMk zqBc=EAUTDaOH(?Q=?Sf8-#Ejz*Onpe__3HYxma68D4$zNhO>g5KbdFyrhf?(v0@3n z0eov*u`fgA1XugP>z_Ay=CwRr8B;gy+udAUbF8NFew5C>+uOdSoKo3&gVPZuMR+VP z-gyU{t_Qm4s4NQsDyGI_`D-@!xu z@AKj@C-_;gEGkJvFQ<9`ANJlVEUu*q8$~8qa1vaDg`mOR-Q6v?26qp^-5o-Lgy1g0 z17Uy!g8Sg^?r_#*@BQ!W@7$k@^ZZvcv(~I$E!EZCRd2nuU67ssQ7vRpnJcR zeB1sZxRKWW%Vl6423Mf6tw6_ms-A1$dwB;BSy8QSz_*hV)k|WYQo^zQPb~gykdRvQfKlp$RfFxw53Y%gmN=pf4I4_;iV?uOGH1et8XD z$S{g64TLo8NaRdD7SBZ~Avu3kU5U@%27YrHZwW3;`R-*Yst9jb|NI>)*V(Ci-NSrI4PDr&lHX3!N&T#YEaA5}R{ZQh zW_Z&osPS&>xR0!o$$UJC=jr~wn!3^~(RDl8#K`&gLlQg!S2y1ot(NeM1>k8l=kiHQ zZiJ_1I9o;lD%0|uJBr?%JPOEj%B7At*TeSNiG;liDd1%=?8~4BS;0uRK>_+leb*6* zSA**_!lMX|l;JU3Q2X^ar1A7ld`(vMryv?WI7u_mlj@h7E)qIMw+Py8+UPNLq7Ywm zjH)k3u+$j*pB-9`8^#x?CkI565?|4hURADI?(eQnksho>$0~ijI<2`3B#pvll##;~ zqL{R#z)P`bfyEwuk*Yw$)IB$y&Q7nZ5rJ|dOHEmttTV^p$Cy{{`fi!OG{ISvlR7qR+$5t+ z40_iE+VzzpidiZSK4QYJAWR?FYOaw?anzRMoa-Mt(jDj-TR6YI{f4YZ?O zg$$)a7J`0Q=ClNU!|OP^c0JGyDPwpOGWF5#!SLFIxt;m@ z^v)xB-cFC?S_Z*A`!DM-QT69US`=va-%~%R6)WU zBix+NP#A$l_(N!50z73Qe>O$E_UmeFX5BOK%=*(GB2#nD|JrxN~KL zaD@f{`>3dEtX3)cluQ;i9x)CE-H8YcD997TkTW`x3psVMvSJa^AG2BENFubb=EGub zZ$I%|OOgLr{F-HYUWB)co>?j*o2rj%j+9Jv4A=J5lWnWU~2qO z$?rUu)X3MeFPZ3mz~U21c9SrKt?;lP-sGxTaBAzw|KhOqQ)KAX?#*z3=_+8xsaeAk z1&B^pc)y`2m-Bj_`e&!)2ylA5+^y_c&3Xh-m%>hBv?pv^<;_$&y6qN&X_@yA${DDv z>CZ}o(deHTAPXvc0l+yk>g<#k!y8Z6%$4*`I4uC;%PHrQumscDVF)%fF5<>qOY=qq z&vj+Daq(_rYQi9lwev>=*CiQjI#c`A$_^2Q%tzR!k~!u1{V(_Dbu-*T7yg~ODLGbY z^p$sQV0JvJGcv~bVe{zJzv2)|uQ9c4LD|g5@fTrq7_OQPO@JY4ES4{) z0K=1^S90sejs=F_V6D~23jz>Bs;h-euLdmK8_*!lq{yBCcL}EM3l+(3>D^=b1_@?n zjD;T(maeQzRAvT9ur;>$(M*fymWSq^kiGgCujoV8Nwb~r*zZui$qN;uf8}*TCef6v z0Yrgv$8POVH*<#wGK1!E*`tTM@sknrdhAgXH^Zu>fUyuf!_WJ%cD9JIHeFf@PQ-Vz z=e{f$mxH!@rQ7tHOS9MU1q7_w_G}119=Ztg+vv*x7Qln4nVFDchcp=%y|n0mo5Sj{ zh8u(Uv{x8{6oWhOjD`?!>0y-0F)Q@JjHE2w)I}8|7A(%WI}@j!CLh$+#(-fHC!?9# zWkmYo5T}m<(sXo`UmnGD!`v^^JPDb+C=v?h+R*Vm`$YDlGEsJ=cKYL-v*zId$w4^! zHM2#ymb+=F<7iqEfb##WF88s*Lz4Fdd3N52r6Rtb^ezkGU&}B?vOW%L5&A^|3krX- z7HH1Y4}TqcJV-QL9AP3yckrM_(YOcPB@Pa9j4B*bXxIL%H=QI~Yr%_tZ`#UWy&4vV=;T`|%66 z)s2PyL=0Sd-$O~qrufa~P~oCA+RDoXUONQBScmB2w8lB31{FRm1wtMs-`P?=84W@+ zuQDrL-8pwB-a3rMJ7DcevRL~$i=-OY4mLNI6x6Srri>FfX~J`8zt+@H`&hScV0prN z^(n6^@i{%oK9ERiXGNUw1fv{C>lTpi&{?1}kdI!lYFIS%fD22YPsV7*%*RU(~zH!|Lyybe5lXa~>6uC<)!W>Uiz=GcL~M zvW`S>@r^IMYkTsEe@Br&IK$2-F;Ax4mkuAb`TPBVRO7UdkW<870&PI8inrY{?*9JP z{1_Jcv2S1q(fO`xpDH+--xryLB&Wp&vFDrSXrMNlLrg6f%(q9XmzJ1bTnnCZ_51-% zJ~{=}Kf%4fcE2cZ#2F2XmpgH@$E4LucFTjjd?i z-y&3olYQ=k%Ly7SUzQbB#<=aycu9*ZtwzZBH#`!&6A_bYc{Q>D5lb-5eZ67l><<)9 z?LC1&lB=r^$RyDPghTOr^=M!bG63S`~T2YFgY(*6A>?u@7ScO~sh9NHV4RAV?_*UKcR< z`81eFbzBJNAg}%0xZJJ&jqV5r&>ch7pKPtLk>q7Tp6PR9^9=0|@$31~SuuI0^%kpL zyBNn`Hy5)~+v{3oGs&N{x_glMm>mf_*xF94<5aVY33`4OYrmt2m(7p#sTP6^=Bk}AtV%+wo{-kB zZZBS+FT<;pO^f;8ShX!p+Fq<7DjjNZ9#vyFO+dErC(qYz&NKOa)L#&NR3uu#I|PxT z9)($&?%&8UU7Oc0{0!-%8a)_aSg6JKb#yRIDUJb*(kVj%m$suDMk=VDwj&Tug{iG# zhRGevYpssUUtzwKPfk8$Av!*B!2k!1voV9T$l%D-09zp67hZ4OMT{wkKjQ^7;A0yL z$)sa@j+`9{Bq`oW)*9~=9`%*@>RV=is3Mc6u_f7TJa#+hE*0cLa;4Y2uG>{9RTy^mP!tkkYu^h4y2)yR!E3%qgO`%4O`rjUZZcs?1s+(O6 z5M~H05aMwwIn00 zZ4W?>dg}U-#w!4@q`lg%x!`Ifn;k;*G1QtP8X<~|$xHek+}M#9*DyRVRK#YYla$dW zdB4@@3nSZ7VQi)q(b)B=+0$>8Xz^DN?TxT*7Y6^-cay{Q5weWK_}-*1qMG+VLouj+ z5s*yMkYmX4WidEXUJ6&DL&obZIuXcwj%i}LSmtWX2hRpupdn@q2Hrti6XpB%!Q8fF zU_sc0CJfK7rxTU_3bzA*)w=lPE(YFc({1+}K%mrhG#|LKu{8v`Tjwe{Jrs3=OE%SV4?KL={SQ!ih`JMB#u7 zO29PsYF`$$NJ(5~io@qhFgKZZY_^%pPX>kml~+b_ryr)s5lAT@DP~N zh}|S=A(Lq@CelUUjv#8eJlp+Rxg~O2`vM)uVg`t#Au`xV^wi(>d|Io$ArCl> z&5TVdgl4F@q%^vA`RWWmS?ESZF?m>x#uyAKUpqmOBSg`_HVrM51q6c2!VHSJhar{8 z)p9ZwnEqY=b0Sk8hN7JtcH>lchB{E$p|)RjWF}E)GxM7aYK$oYq@~On#V#ijy0Op| z0riKL0iw*sbA2tIT!$@xs_WdhrYWl@lCxT8OXVp0))ltC&FLCegcESXM65UPPMChQ z=LKQYr{CW-;(bD>Jp5jfHb|m-^_|J`^Bp%-AE8Np;N-IimIw(1j)9&NSku!OvoVYg zRKkYk&XTVlHKN1nj(e4_FXHy>yFYO|fwklZYht~kY*euuW2tN>b`3R~mT!2Iys6qo zo8H=86X`*u_gh8=UuzK(d_*%cDdcar8kEZ0f^T1L`PLc3weEYKQ8~4-j>h8$uj=6U z0X_dxmCL*B)jK1)<_eEJ_#ok>=TM_NJ%T+F^r+Dv3$ymqfM_2-&(gP*em6d9mGga^ zOro|`gypyAqkadpe4(pt4|UA%Np}70HRy>jk2u5JEmrC4>-Yo@Q!PmrC!;++h&}>s zn|=vIAT7RR35^GSAOV4~Fp20gr|~@FpM7Kdlj?U5yqB-1l|C<}E+yy-d{;1+sv5@_ zS(NeaXw7+Z!kFaLhLN6yKIk(m9OrM0<6917=_-f-$^mwJE#!a|(%@HQ9U#d7@*f_~ z!mIHKaupbx+*W&Y##g3~A!u{DKR2nppp~R>HPxcHQUFxOq`fJ47Heo7>X<0VS8dn(n-{}xtte7 z1VL_IE=vwXlOiE@M50Rzjkz30YWor~vaVVTvw069x_NeO=n|5nK+V$Eka~RDWgxI0 zZ-9y(4NxrMYRlr=B=mL=vRZ2TY057@E#zqEBPZ|17d19OfPG$X9Wcv2RyGUiVcVjF z+&<~+sUBh0)w4G_#}_46hcYHO1qy5L^@&i1L_#OAKb9kzH#nP2jYueTx_JVE`~j=` zSZ}i>voh@bYlS>^S?Ro+LWia-s-n1__lKOEA3j-@l`ebsd48p<*QR99<_Zgdy8mtb z?|}j?LidC4fUhksSQ6zqAR@oJ>7Ng8U|1`|lz&4f|Ge`Z7KjG;r*6Lo>Yuv;Kv7d- zFDrnZ`ahR`m$(WOM1HaQAwjhFKbL_cE-6sdF2%E{|9v;me#~2^U()#||EZENxiSV& z)H!D4?tkA9)X6Oj2sgJ?f%5DBREZq(a~M#RH&QQ<2C{nw|NghQ9SY2zc2d#b!C`;49Ul=IoQD|m>=nYF zm;YB5|ESsj9ghF6hNF`{SXj!`a%cFwF!do>_g3{4SHZXjaeO)Rd4Hv;(yIdf3Pz4p zJ=OetI=57xQDIZMbycGQjI-!3>dpG3=e&4ymB|Aql|m^4el43)&GEL<_UpcxlZ)}0 zKH`e`Jm+99Q&ZDd=aD+4%(+?eEuv9%?Ze0Lm+OFYN(4{U0NX_GAjK~RhKq{>IpRn`7NMDE6ol6=Uxi~mv77BckTpcP=-F0=TD(LLn z&NTt^MWY-LTq-k|#;hcl${@qsdh`za3_=QTYutHeWyer7G&D3mKhNMCnQ5`{Bg1;K zOy?iYiiwrmn;W%i?O)C>D*-B~bMk=ZY`KMn1#18v{TUtALbFV}#5{?>FDomHDhBl{ z$}!SlgC!JQ3e2XC$Pwrly26VGXB)kGUIjUYk~SGhcx=M8yo27A9JFg+(+k&_RSmRKHB+X%%-hHl1YvM% z{H)+$JWrBk3!YRfqLp2nM7Hy(mX0InwS>v5Vxbm7un2 zH9fto#D}kkxq1HQrH{BXjIvwRJ7P!BpdqNHL6rnFr7`~s10X##Sa8~dw;|*gTx%i5 zqQ8EcQyW#+;hpx5&yCSlyb|5Gm9zGi(&BY)^c#iD4a@2&WaUOGEF{9ei+G9>3}Tpa zA8ObC{?UMs%)71QB@+|t7ppznsy9z2U1XSS3Spgmbf`6N!bpv>9{`3E>yetmk^o(w zSI>!hb%%*S$7G^sx(Ec7Wmx2W%#}OJTEz2?&a7Z4B7N*D$44 zTNl&N!CmXry7Q!wjX|?hQpAgS;rAbMBSJkdzI_UUd1*Vv@HSUtTfcNR5rGt2@D&q zHjM+}`z^i2Mt56U=P9Gk)!H5=_1}wIzX~bfg?99fGmhogx+^g==q9E{z8&oSXn?zT zE22TqLJO>^>cSy|WM~I4R*_ z-Kc}|fE`GPe0x9%ADmmaY3Nh1>(HbqBjf->eyFgrF;07+0GMKpc!3B24MYSGp8k;< z0TP1-_TuE^tNoD=lYX-_xoWe|j%j}@s#kDtsw+jY5P?2qnZew`+sGVlDv7cT4~3<; z1+CwT)@1dbJly2CD>}?ur>Q@qKS?=tP`c!Ae#tnP5$6>`R;nV-rup#fM6tZKx_;GS z-l1oY$^C6c?yCwRRR(IV2qnMLo`Z3I4icANUDi@gU%jR%T*lg_3{rKA2FxIw8Q`Z0 zsddp3_`zmhROmkpB`BnpE2Il-eFz>WK}gHU&CRVlSx*}q4tO{{15!q+8#ozWwoDbO zDe_P&WN|7)@c3W#7zEs(XClbm0t5t=*90Ja=YHy)3KzgBRKVl1QSg&%QGd`Xt!rc; zh5kIf5&mjpIK4VWdsj&%jRb-^?|-|``=OK9D0Kw6{Tfx&bIiD9s>E0yx*HcZP6W0P z{)rr(>QI^`8zdGL+!tu~q2%;3p~g{#y81I}fbF&M?OU1sL9L>;MhMOG5Ov7)FTd>; zJW>Vb$mN#oBF&Ix#`X%>0DlPn*;=G7DHHdT>SQkTWHps}-CS_FVw6J%r{6wfae=*A z%^oDnAJlU_e9wTuKx2AhBJ9k1)igM5S8imchQcYoO4^(!X-+Y9duB3 zA`V6XJ+a`B&i{1Ae=9$16rgEHLg(9K$ph&%axASi9C)6K)AT-n8fawix!zkLBc>UMTktGAV z&&tr{+aUzjw_wapQH%_aM;9=(djz%>c^aqW@0xIPLq#iV%#V!t&-b z6H_LR3oeb*sI+J>T~uXjyjjAsv((%r0Heu%C!hMUb7 z78Re=>n`Gq&`YnXcl@X7;1_e7#l?^5N`tKRL9Ptcl;>TObrXwjp|FZ~x}cx$R|aFqPl67humV%@eC z>2SK0aw%iEMfKe->bru=Wa zvW(=O|GlsagCe`lf8JXNgPX3t4%)EaclSil4-`zc{!p^VvGr~r&zl8I9*WHu?+SG2 zIH*YudHl&!IHXoR=zRi{UBw6S;U^7oEY z_#X(Ab&f%(Dun&E1#U^>(djt~VR?WIJQ5N71abm>pijH*{AbKmMBVa%R6^I|tImN8 zbB@&%F-iW?ys1|+wU$~k9CB)cm-8;KzUiAeui!i;ZUogiG_R-fatHo!Xk2h7RMOEt zLv=dL(D}e8No3qMu@$^(xFke9>Typ|i5FxX zLMlt&Qr^FbkdfwO;wh6n?Gt)XDc>##Gd2~m49Nr-%g$wgVQ?=6o&n4T+LH~7x|K-> z=EvVUb}PPqVG@WBV7S*_uKslh*y(LX`V0^sy^#cYS@A#Eoe2WqfiD&O3~Qav>7WWW z?!fWdw*s&R5pjR*;>fFL;Fcq6X=t!;0I5#`!7`l9{GzwZeePT}zKT8e!S;LYvm(Ym z?fCu*iRCmkCuF*)q#p<;gQOInsjsUv$R@2+3c~qN5mSE6Y2jWHR_8{|$wbMY*<(*- zXA?IL+}zmLbl=CaHOgIf+*M((BP6Ko9IA}Ykw090!t%N7V1A~fBZ+|Z;%i#{O^A2^ zl&Xg|+won6;x`^mA25#@vFN_0zciobW!}SCv5j>YSZtJH`DzK8S9&MZ1#qqJj%H}D z3kcEgvA_u928Re-Op7hJg9DCx@oaTaVb+{?$hK1M#?1EbVr}@H=Slji0etoEmIv~G zh5Jk5Y3Sh`t#VvI;{R{~GGqfG4M61E!zD) znbP$SZ$7}53KbaQm%WE|+I(ZJkn{>3m10YR;^L%Qr+Of&qos`ao9m3bm(MS%0}**~ z`)2?#2CU112!a`b(QQ3)yc-hGz%=~YXpdq5H&3?@BoW?m7bB!S)!$rIZ(21jvFyz% zluNS_%!wm6BXJ&j#akxu2(Tlil>o+SbCK@^FO3sAmfk%b7ad0Y3;_^aUwlvAlmq}q zv2)_?;a36xlKQJJ;3tN_wZ;Q^C?8yb6=TPSU;eX%#a}Il3nBzg!nWEyDnOsevw|Y2 zDaV^SS+?tCP_ImC@t%4oDx_*Wd&jUCt4ir@1b=22US-^)B4gmh8LhohclR-w-b`P- zI@UiR*w;W40n1D01tK2Ni z1dZps5d=ItVmwP#^O)kUUv2 zr}S%b(lxV7GP@A@Ki)3x8jIreK&d>S$C+0^N0ch}h(J4n6XbiI zS=03Gs9xt9H^u*a!ocpv?EZ#z=%VQhxL{IJhEkEK#HegtroG}-ol#l}m4N1h+rnJc zJ7=fMgvy}-N7%)i#CV_Nu0#x>!)^T(vk<8SX8M6OUA0AAy#lG;&4>QtT-kfSm6{i& zJ;_yNa&N;~h;SWeCeU(8qxf*NjZQPCto)5CP5^2UIRJN|I>>KE+DPnsn87~B;D0Se z;+9;I=rX3j6;-kFg{tMs`_yBBL#dsG&uH~HW|I*92?Daq=8z14=Bm9}`~)TKu$@S8 z2Ixq}ZFuM19j^f-^QZG0r@l6wsRpAut9(@M9ZhEJ-}`iy66hjWlF9dq25#J09)irOe$kmVNmbN?wREyhddC@kA9H4O9*Bs=6^FICA`&{Jab_Qx3X9DgjcItvW^Vd-lg2wd* zya!E7e-KQRK z7X7!nG)6jNi2VJ%vp_sBPHfpZxR3;8K8jv`UF$V%l9hRhCv}m5$(sXgY`x_3h2n6D zjMu`I@fMG;28(Un_ef-EDb~rsgN~x%zV6pQec9R{3+vW3$J8vPJa+aD6xvQGJ`>>z zWRl`~WPS8quP493026_b*vTBa(L&KmuV#Vo+fD&a9z@dY?Z-f*TUg673yg6My|s+X zgoYMf$wlj0-fPoPRCF_HvVJ*!*pG*>1lp@Ir?DQbVzK7iiZWl#`ms~OqA=Wy&xy$# zkBT~{zFIyfLBIyN#{AtxU`2S~*FBZ(`AZ_Yu%^ozDHXPNpP4K&W@)E{7&ju}Ey&Z@ zHh>9_O9>H2N8f30X6cQt|UX*L!$^X+B0@9jzRdGIrXo^`m-*;#cSeQ3C@Pqm%o2IeQwCHcDYYx6f{_xnpamq~yV$#7m@AXnw8g z-CSZYIpH8(x~}CbTy_mFdeloVHQ8>NoR}mM)*9cd%A94(UdMAhGu#g{yawCPTI^;x zN1reH?o_9WRS7um;aKyTV>65ARgOhowpHi{WALYXo%S_~Ab4f3rLC32OtP$k1UG5N-NA{{8=R!hufAlsXqG*meNl}w=TU3i0%bz<)clZBEx_xDRZ{39x zS0JT@vI`0P^(ys(l&-2)4XOIhb~gpNb){yMS#y8G*LK!&s(cK~XGoDmbPbQ$C^J{@ z+<6C2Rga-R^IYHxVkf+u_Pf{|N#x2$zR}-k&Sc^P5)> zH>@*FX{){|<6=ibZnLz>tx0L-j1H~G-(N*sc70Eg<(Kk!oPGzRSo z^yD?7{dMw&o{Rva^cyVbo|vT{bF1(CJ#SQDZhwuucCX1|(LD{68#xou=BI?ns7j7e>IcJ^dY#vBa>vX$L zsa+zK+M4{_GuO*Yq9x$kW&1KtAf2};(jj0hS^XgGa0xe4&8RYYfj{%?W-5Ii1-6gt z5%BseLWvE_G}*Ld*l^vEt_Uo%^WQmUSvxpPO*m?cAR75dbGo$xAc~Z$#`^j%9610S z-jsuwW<1vs;0~R#O+Xgu*!mcyUZK?4`$#IsUqDjI4)5YbX%Op04{0P*}N?&od6NTP?m|!I7gr`KU6Iw*oewn3YpH|s&QCK+U zJw~P_m~vovZ!*A`Z7H`C{ca*K{!}FxKl_wbuTe(xYnRC)CGJ}Y`LmwwoIQm4xqqr;(VRwYqxwm^Zg9m&@K--=3Bu^BYP-$i zhVb2JU$O?g4SO0FhOuuU2`d8jmWHXJfKr77ceGs1K2;-&k5hTR-b5b!PLk(v2fO3k zUq`6pSE_F03MVCebS~_OjONxc^Lk6``HZPbSb=F!pW8-J*4xQAi8pkXFX(NjHhVls z8;KY;3VPqg(xVN&5j{YTKS0pWG+PR)6bMFOxQf5WQRE)ce=B|{Mdqj8VQ0Jj#5O^$ z8Ph*@W@EU653n~dk~o7YY}RQR+b?|QcepyPW3C<=ZFzRp7QxW-K~Sf-|URMm- zj(L+wn>aXmo*eWYg?}5Vs*sv)W3(^_1@b$($0+V4C~C~FGi^+5U34i*w+bwDlnlXc z)yncQ0-3&TkFE2gpKPa;o-caS99;Bcu;dl4G-_pQs|IUVW)Yfi%T5O2;pOl<;J=6Q z2=^B_;aiB-34n*|IDPPmlSAJf#_?V7ik+J)MrzK@7x!5o92^@{5-O)6f`g1tzo_65 zklmr!z;va(SSuurcYdc-Cc!yOJbJ^CcxBv)EC`P@DxZej$e)(VWT2~1>A=X|5gGf> z=spMBR%8ahNvH(i$}o{5`j$!Q+pBEO>+uG@;I7e7WEhlc7N=fpjF0ifXPS)`;pa_w z?+3$Ql-VZ<^jQYfxp>i$FBW0%a(;jIrcriG1IrcbX@hoqFANh%OS2%M3q-&9p+L8} z_t6Mt{=-rap>v#)KmieJ4jN#x#w+zH)?JEal$bJrtsL15QsH{iFnMgp+{N^3X}D-5c%nlX?1 zYp%vuC*QT{elAV)m2UZ=mZFt@wG_pnTajAz;puLla;}<@Z?&KtHUj)!ex0DOc9x${ z-mrg&eCR0h}q=V)kR{jW8hYnN*63S~UHD^pz= zRb5lO5HWpL$k#w8So~yDcj;{yFQmnEPjL8S^1c#RG@}x6rz;km^8f8`1-xre&lg%0 zHwqwNGNCZ^OUC7uPwF#vtvPdH1DoP7bXRk^-)(B=`6X$u_I_vdKYu}_173@2zF5dWkN_8K&=5mEVp`noo_3#2*c*hi z8|9m;5KY#HDdV(+NDb;wsgFJ}F>@|Iwf)*U6foD*W)YYllsrK@>1-yp(#DSm=DB&^ zTba`c@0Su3XcRDUdD37qPL6vol5cn;60u74*Vf6{4=Y|u`tMUEE!>VMrFe!w0R$e` zWhi-EOPVf?y2V7I^6Hyb&U_9Spge7aGpFb>cWR_NuKv=>P)X-QGlbhSfk5&lYsZRr zowcQ9=r_jb_g(`K$loVd8b-Jn>RNs+)RXSn^A2pkM>xhM?zqYGgI>Q-5g5(0_Ak~8 z)Ma!2^}b~hOQ5_}$%MrhgD1-EdPk*iMNW8hWsU9qR(zk6ok;xEPe9GzO-udu*2+W$ zo;oiN%BJ65N%SzpWn{M@4pAG=Y;sr{>YI>5;CVb`bUOUvnieq;#vi3Qo{?~zr7(y@`gakN|1)QOhmXOQrIi@0@7VB|6RhKa~kHiEM?xS zB7%zr;#n@z?lQzjGIGz2Wj{L0qlv~V^RSO<$>KS7OLw=QM)hqjrVWWBjMuV- zL1m}OPpxUIu+hywD|WBk_O8Wz*^J!hw(KI6>%-B;25i0cP@4 zhgyHJ5-AK!hskXH=dy;|Z1UH&`PZu^+Yu4q%KiK~5iTosb^}l^@ z|K9#vD*h}a9R{d<9!w0r#-C+CANgmX|16#c1~~cB3R6lx|FaC}ljIk_-C6&>3%G_1 z^^ha~3RemFvkd5yK(+tVkpEll|9|y%$gyFVzLz7KEL!kzttHxwEn1;EQ<|FCfL0QC zn>S2^HLSl)kTnboN99j3kjDoZB0nUjAU}?}Ec=iy`B8>C$6#2DMVrA^%KR*Xob|2d zPEQ5@BFboBNMS{Lg|E4pJXQr;h&*!;tp~;UU2i_e|AGi zQzt;1R9t=e-#G@4^%Bh#d-$YQzrrH^Cn*;@er0e6&*G`?0I~%0rVG*MmGmEi2N8Y( z>eljvj!g+h0=06T0)oS# zg|ca@vvP=F)S>yDTLhhkzj{+68u1XH{mT=|JIOmDY-@t;8HnN3S`8%}D;m!*Uf5;- zmuDY>QG{auwp{)_^8(4^-Qq|Q;sHl*S2f2;(J?ho*i`i!GsZNzl(xRCDM`)nV}aUf zKH49KWCznm#N*RzjwRm}=ik#_Om1;>64bv&`LTH_x^&u7$-&+uXwA?Y*ubqc4ZyeT8eZr6UlC3bYH8W7NdeIFF`5UCNc z(C=q2ts=Fr;OljVbIS{Z8}-DkoDK}GRE`gIc=;;7xO%2$&40^FlYI)x%m0VoYCS<3 zUp3Hq*qAk21;^RC2`;8bcAr%5tU|`7rb^dHYlN`ArPE$ScUlqWQHgwd6XcO=z_cu= z7Dbu6>qT*_N#iB9wJjLNX^S}^49i?*FrZ2l}a3pc3s zs8>Hf*}0p<$H!&o<2URrNxC;@o}S~r$F-Apx|s@kVau{)r#+Aq(%5kqw3Xp-lov+N zL>&qsU(D%equYrK2jl)Lu$^ndFj{s7Br2(leRIL(jg7@MnXyiC@qs-)j?RahrcOdY zt8u)+KDhdbYPgm1A-)vV4A@DO&c06anqR6p6zs2Mm56Tt7(k#KWTJ)5IV3i$YLW%t zw~J`XKO>|guAw+bY9_NbVbo{mQ0Etv)Q)jdqvYF&5P+eJ|3)t1TMf41;#8TGQhngi zCVPgO#PRVzVgUmD@IwSTo4KY9tw%CNlcE;b*5M?P9l4-Z(lYE(qBK; zdXPGLYic}njOmFYwNb?jZ?z$XpT(-G3#+(FR9Cb#xJgWPx7Zqq_h@J>bofow2Y!V6 z_%8ej=y?HxXd1RIc4Ggy$3w?q^I^ti1{Yg@e1;4pgU3T~n14UjCEyZr`2g?@LW*Td zvtEB&?o5&OLuiWW42A8;8%b?$ee@HHiEYv!;QlY}t&AG(q3zR`rHVTeb%eo5LtjC@ zW2uYQuui-w?{10nFGULl0 zMo;u+cjx4VE{5LVthZSf6u&g^b`@t7}XxbH`+P`#Fh4&37} zpIdBIc>6(tZ{1h^_MgoHcZixP+0C$;scdsHQj6c&G0WegwIy;2j=+!y z^Ihc3)^D7B-|Mh2g(EKE+P4;%Ri$as7 zsp$jxtEt|${k~j)(@OcYhg7+`+`$Tbp`f_O!?(2hRHg^YAo_15S#q!fO*Oe`$tqXo zWE@9kH}W`?_WaBMfRvf>M%s3BP%YHc$3`bUEtRH;MC~udp6w z3y16Jb($rG_h50f28C05W7PiBs?KL(ojfnI)yL~BpfV`$$NhmkL%|WVZKJnx<{d`Y zA5{W0oTMoE>5s@6kG3YOPd}UpT`LSMgy_R9R%3As6nBt+373eHKkrA7@wnKS(~US&oO<3YzXH6Teh(A3B?k>i!n@y zvqXu$(QwP~EQe=_mx+?bk%1G9Q9V+`pZ$mgDnfyK6Up{H(ay$N@g9HF)|EZ}EEFOY9a)xDkqz47Yqo(jn!Gstigw+I3D)5H(MN^*RS#vTvRffwZ-w+$GIgxwpFXZqWQC5fO7`sXLDzxTi~pLLiO=~ z;ig4|aDZU!O8uIiII$sf2Nxth=yo0JGsaIL?bGm`#)6$%x>Bs z;Mr5BSC2PZ>rd<6B%a!phQx7qRaL(Zc#Wp-WjLB!mfgHbk|%d?c-YAN5KBW6_f2TF zb7qxP;i~@t@y>BA%ND(YB(6WVBO-Zmm(<#m@6xuWABn`A`5ScxObe|{Cq|pkJe2Cv?%MJ*90s^$CCKfBv zF}rz6`h>QZ0nnB8nw{I5;!!?F@847gJJH{WbZ${(CitRnXwkf6_xbN9qCs>JXzybmFOJCsMJaytA&CNYeVgvp9E4Z^YZdW|M-9$GW`{IQ2{6WY)nKfP*-nmH1hf2 zRJx8d4ppvWPsDfhZgJw=3qs0_9#SCN`#FEo^KjF2%IFGZigU%*`^bZg0j3iwfum0NR0OB^1NFoCeoAg!qGlXo3uaHUw`QPL{~#k$vyG5B zOtH#F$}rLeB4(n|l}z4Yj&K$a1y+p&mRp966 zpve1YtRrz(wYmw_FQuwtUl6Jt%|=8e5wPb2fm0^lgL)7X64stus2dzgZxVg4nU$x6WOziITfA(44I*>XCr-ufG2kj6&B?2g%A7^e+=B5%VDcI3!vZj{eeKk zH?b^{C`T8K9RdOXTP%l(bPhD)JgfaU#z9+pXJ30BNDh?E32?&Ibs-QHm=C5FhLQPm zGa9sv4}{(53=t>{1u^?BKeYzD@AVg*hd(-i_YHdDm3~@``R|&6bT}%b;c|hDtBdq)O!)?kaP4KKMK+Xf= zReV?VL7j%>JiW=xXZ+y-b}ZM!BTd0vcSi!#CEIFpSCuo(+Rn8$-EIsm;)mG+N4!@x zjakT$I{;vIr}5`Cpc9ViVP{7#C~tr;?AOfQsaKYZ@3O;wq^>KehK(utf%~hyd{1Vd zZB{jI)T(OJi>NQUt!UcZZR|5roZv=NU4PMj3Hyf}DfV~vHWhM~t!on7V|fqJg)$i& z?6S9&2CNpzc;g9qEiHDJ!_A6tA9&71V9ZhIz_o~8mZV_Ak!(1graorG!>&BXlGq## zRU4ZhY}g74*Qf~Z>Cvj<)3La`a2ndYI=retYHch5#zClWFBfKK?VQoIbyG6JTW%n( zJ0-BoF0uy#crpGAmk72F6DjT4i-y_*ux;o^Hp- zU0k$UjU$?Xd-hPg#2(t)2S~545XD%mtiar7X(tTwE^1lUDqeZjCx;?y5+i9b&QU0ehx%Fr&l#q z%h?G(nG$WTQ4+i*vdlP^y5E?eAB~^N+oDb5m1(oF`qkN3(YHgg-#rFCR&S>i@deV> zj!na*ANt_ux;58aqY|^8WOH|>-K-9S(}dLQBE`--m=A42_}_aqoL9^7 zeGge|XWNrv&u6dN();05NnNTUQh9?C-~iPENblH20o6Uq{7qN>f4TT z)VSyC1~$%p7}oTK1okrz0vHJ7S}6;bo}orapq>Gl*;Zyp|2;z+`JF>;#sEGE-Q4BQm}<;Rlx0pd~g;YYv4o93}oYT?|a?&Bcw$x!yJr z5U%2soS7e8;U!=M%aiG`g|yjOmg|19r|;maeGt4pVl9UOR7PWto|5h9JDWL4G4#PEQ^aSo4L{1!T+}LA_mOz8qdoM~<|VeD6*3pc z`LE&7IJmfEne9$?7T3_DIx`tPL_;?D6VSa}h+&9?=92=ZD)v z1Os8@j^1exWw7;GlqvG8C!fVR_!s}wPLR4w6uc@7ny>Igu%=<)-r!CINaR0c8hgGD zKittRY2p92gUFhM;aDVie#xf%h6G{1QSQyGMu&QF7AvgByz|UjMn$Cjte5O!nr9y$ zB){cre*etkVwOKZ(NK7M@c6Y*>OSnsCntZ8#}RB_g93lIT-^3)VxTRb;_*RQ@d^-E zX0)}SZ0cu^fA3}|`2b^epEk%f+-rD06r>W!Euz_jQHEpx99i%L$e~&+cutpK&g)I? z5#vU4>3SDWRo8uwvbdNhLsUS@8o2NUr(Yhuz^_7TY{4D`dVvbtB{EMWF1j0C6ze<@~Y-H_PVsGd&g=wUtu=eWezMGspr9gXA{$K$f)x9!2lp}i zZ2%Cjf|@aX{**0T3GxMl(Q%TYvCb9$`;s_;UHt^^_Qxo}G$1ty#+xu){xmw%Jk~r_ z?cOhaU{I`s=eOO_w_gtu3?FZ}UdCBXdJW}X>O?6D60j$k#nMvyZ~qIBy3w;AMT0Hyq2YFI6;>E34Y5 z7E8ol)Z&N)w=UXk_Z{r`&>2=DICTmn6%lcjMksoPm>rh>IC&Nc6l0|*-VQA22Vo%hO_|1|948Xb#1RG zb194{3v!Qs7Umx^!<`{M%WHqbZz0wPMKOXl@0upIDQDtX+AkuJIT131$_h9tVSJMV zgL$RwY8RHJbWEgk`XMJ)iL@B_1QfxT?AG~J7p{905Fx2)nDVyzLsal93Ye6H?t=5Y zsu7JjKK-~9$GF@u6#=DUhj6){o%h-gPF3bC*RSYY3XzR&INRhrvPe}9Wl>f_l66~6 z5qu_!Ja z*d#C=EZJdhI-K@8+g?ekQ8W5yF_z_?U91y8{banBIm!FX33wh`JG#8NnHwon1TqF% z+NEER8ky%I8h0p@3@>4+diuRe^>G;CES8%z;*Q&cO*<23$8|yi*QRj_Bzw=`8O8Lz zhS)=*;Z(*#nO4t1&L>p1qzuogtsO^1e`2FH;7)wq@kST6z{iS7B1ctYPB99h&q9`g zPu)L4wn)n|CCo96ySB4#$_tX*%}?5I`GwW?0ny(+%@6IA!9d~DCC85F-E^BW6~OVu z?dA2R+3E05g{KdpA+nv8&)$-R>bxQ3gh$oe9vBM!m08amFy{c3JM{s{6!Las3yE&M zzxo84B!v=&)e^2(@S(l77ID`HRUVKw4UnwiokBuPxdJ=zwx9zkD>3?NP1yBCckzYC zoN9B?)%OGr|JK|nf%8(pfrDfK<&a0$fat;Q_pYtMgzygT3k@{6R{uLdm|8nLBWh2- zZh~uNouw?*?-<9>E}e9OK^kTx)VG)Hg)K`lK3(wR4gd#V_Lb!0wme-a!EI)M%`>k@ z%9k4M8WFBA=LzJ*G^wAGx~caZ)$Dq`i+{t27Adyrdk%>j8uD!t$Y7)~tt0?J5?&QH z5OFBiE;~n7d{3~T@(g1avF1~3SXy9rexv)A7=j+Go$6>af&HYQqCr8_+6sSsfm!35 zl)O?grk@{+n_D@T3X}hb5?^^`C8s?^KgVHtxee5m2Tfkcf&zwxc`Y@_V;sVjPZ^3_ zt^HBLFK_zPdU&Mrt~wD64fJ3dfcO%o@W1T0@}4R-G`C*IsI{GgpLYv3b7#5F@9z2? z-_8I5iRWs6X%!O}w+Bs$KE3OJXT!pLnR$W{o!m$b+6S5uL&ckZX2k1&$|nvUt5;5U z!Lir6UkwKF?OEMrq|5PCY)pGR^^{-E5`t4<=rFfT3Q}Bzwc+hnRlO}P*NOc$0EN{> z)qV1P2Xa`Jt7Id&9H95%-&c5U^5z9O8UrnsR}-+~q9OIM3s79Qq~ z%H3nQl=bsRSMt7J_w)*mMh9c$w?!`<)nvDI82oWFSu z+~>9|;3$Yd<-=bcF}o@b-a&KDBiSGjw;bSO3V0g;&?Lv*W(>+XrKJl;oh|3|=_3RP zzI^fRtUhcM-c2s|OkQ8;BccHuBmnwzUb+K(4^K@2g=210f8(Jy*?D#l!rk`y9S{a7 zhqd4nPChT&OKt|Mu4X)}o`LReaRzw(WkuK)J^$soS)nj~Si52`n#-nJrHB}rci|-; z#eOUsN$HcuE@|Jpw$g=I;E~m32%L}heZlPo^)K4n2CD&UiqvD#+^L-;eqq&xZdKfEk)0s#f!wXEfsFG zrnhqQ;RY!C8J~BFgo)WaTDt?{2tklTTgJQxqCjkG73&!T;_#2s_J~I$k(!kd4AlC& zs}(&P9@Sc|XG8}^))K&$v3nfw-~$AnQGa7CyAC06-NR)vO6#IoNYS(X(b$;FrfnF9 zT*G?^Q#4A6b*5Pfz75mP`leH0S2C#68i|+$1MM-T$R*R|hkHB{^v%>chQVH%m4m`g zlr>b`*%gZjqEC_@KuC81AQLCAfd=|+aLwf!${>H71q)wH5*GrisUxsn$;Jun`Q?Yc zm4A*xm_Q#*!j@kVr7y@&o0a#y2zxvzywf;`1O`=Qyx`v@n zMjD>4p95EZSOw6pbcL!`0OhuU_wpI8sX_l8$q|s}^AKtU$XTE!z9-(%Pf5tL7{5&?j4xOMoE+#QuEw)1fyI)}q#M)Ep_^ z0uWfuaa~LI2Cn4xAZ>jXd`4FQll)`72~o&glNf5J(JH`k^%Ge?F)e{EyH2RQ?x7|@ z0}Lm5aJX18^JFx+L!-LgHS_NEhT5;+!@sG~y@(B5)qh|2q(=R?=jY!%HW9jX`o}p3 z$YEOmnFTfdeVjL+9l#%;8eKF7-N(oJb`lLrCpqfb);Ni5e>WW;;cOYid{Ka<@_J%7 z7z7llc5CdE0vON40K<|R#5dDCm;(Nod&RXfXgoKJieVy^P}v5VUI}I{Jpt*>tJYjC zTdK|ZADdrp?m%xP2x67w%I4gd2|Y!8%4jciLJhy2eLZ)0xO9NWMKmYoW_c|4jsHIS zO>Rzqj~*|etYL;u&n~7X+6>%=HOPn_@;5-0>YqdvfOJCqV1q82B}R`w$rfHg7sRG} z=Y30Kx?i6WF?ht-9#BYxYFNS!Uv{|8d1>(hImY zoYgeui(|VzP_TY-{)IU6dr0VU0!tKMC7nydQBC5yP)9gB;%8lg;-#v!V3Ps|=7LA_ z6{Qc3apz!h74DC}c!ED+&t72LCaW~>=ngh!$}tp8 z`$gD4p~k7g%4bCfh5B2=UgDx)kA2ani`*FT%8wS9G_q+{oTDY<6aV4tXK*tBzR%;* zHDhC=-Oq4nh7g@XtzmlNT6I8{O6*UL?Hf5Nk{7veENMA|o|S9XE_*Be-en3G2fwnP z@xW5mzUO(@d6BWApZpg@pVlM{TNB7^l1k_GD0ZDxSFoXhC!FIwoV;Cl`@E75zOnyA z;<6(4YbVs!i7=+7;;=@~CUpN%a-Y&f(Fl;_EN-oN+|b}V1C7d00GFC}ul+HNAvvEY zHSlV^F{Qrs?AAxo1p9pJvmZdQC3>2ln3HQjm=n_m5q z=}?r(`fi%3&qo2nMwFz42Ve8PIy6YG4#WDYc&2fie>V)&DCGA?hFU``%?l@OZb+Vd zNEJZqKJ9i%2|)hr==GTFsJQHRzlaG` zI!{$(_sR6GslemM$;cU%W(pHK->3Ldqh;!T>gl^3{-+*vk+ zP0CE(tQ?35PL^Di0UjA<0$z^hjwW~)hB-Z8gAq%_+~xpb`5z^ z{tz4QUFPKPPCBY+@-%3=>W}9Lo76CMq4a8U#W!CXp}`lcG#B`;y<7?zn5<;l>x~ch zw^5s3zZ(^NL_Ci4BZC~{yzy><{FDMt|I^5tkt;c3zv&aBXq0WTG(X8bMBR*W7^N+o zhPuv?2`4rF4ERRbqTxof1-c%VKAQ7>KCb&i6C2xcQo+na zL(R9-3CQ;SgfBROJc)(ix(8Os@KiK0Y%4TRqe&}^?PNb>kGooGs7btX*()08MHn1= zD~PNGZ?M_-qpxQ=SxCOOe;343?%lTP0R+p%=a90tYp$g6o4nh(pkx;gZfU{OEZKIQ z06UBg&b&`w@|M&aTh1n8{|z=zCAO%wX_cJ^ytXwKVG^bVREP+23?`wU#3R&F4HZ6L(^*C|saTZvp=z-nt?P|4rOzEE&?lpAjHRRNBwQ2&s5-#%|z za^JS=b}lj&QVO_LCy(MF&NTL$6gGFPg@iNzO_27f1NpBq_rcv4uODYoQ@*n7g>pJ> z>Kv8qtH{_=dP4Li_ncC}{s{az;544bS7}MV=+8;CvkFr z^{xJCtiF-deebia`_;RE+Qvi>t55tVfe$yE%n~UAX>++Z^y@`N;yg<^WpN%_os*Qv z%Cg7UzuM3lp!}~KE)5OYRr}DV-O@|j&Q!g1i7-9CfRw9@)<5U4#tLyqHbK$e$hbrSP-Q*_= zBTC2OS77ulHg!BkY;%_t@vCpitbE@YIadwbfgI*v7Al6;7buDR{S*oU*N3g#T;1GO zK*oT=x4E801-x*j<$C|NXHW+Vx8M%6{b{{pK0>P zfj7)8_r=1GJgBa*>Gm@kcDL?>Vq_bdxtu7C!MtFMGdA(R=|Fg!A(!b+5tk~1hY ziD=2MMVT^&Fn1YDb`~`0wPJtT%GEfsi45UH#!BE;X4}qkTYJ^}8N2*4)uxWj;>hAO z3mcxv>S=RX#0xkvg{Wk5@J1WRaTvZLgo<&U*3odMp|8=ftLl3m!w8w{KFiRa{n6( zXQ#F&*&n>DY0IDIEcRjS_~Kai1!p^gfC^R^lIflsKzV4_e#~I)#fg9V;Bo_0Yv$Xe zvx=1uLgtU^%?yG|WVE(R$6Fop+QzM!YG-I2y?2#HG?sA*BosbU0+d`)9C~=zg8M@K z>wIEGdAjeQT+L^hsV|*G``B(=9y+ob%-t^n9XvQhzk-5kHq`3wPXU1Q8!Y(r-dc4&s3rAiPxzMS}(}E@}sOF<}9;I;l}99 zMT0q4J)q`EqCOyHyW*$M?N3`!Cit}-Jl2#|lfpbwhAPIS;dWZE#l~*6mp&GDUDkX< z*75Y=Bw*cS3H#!xpS7HCf@N=%cVyGfsHv&>;qJIrr`0q@Ld5T~GP{}->sL`!lRmPf z#HMgRBmJe%4|E*h!jBy9?0x+QFYq8u(HiB7Bm3WHgptAjwYEMAVt(Jpsbxa@W3;P0 zRwweqa*eKF6~QSaRfx-0BlB#wTrMO_{tqo7{^j4qo~Ol714^pk7tbT6%gPlR!mONF zwqJCj&h3aZeD)l5G@0-R&Qj#N;NPw~H-KZAm@xS|E+Xa}XwRr+BR83&lTNA!fenih zI1pX&?;DAOXZtq(xSo;Pxi$}*S+%wUb*xt*!jxb$PcCx2Vdc)A{Z-Rcdwsy5N;n22 zp0+0ygKW`aJgs^`^+-%5e8R@ir3SNK<4obY1%%A08T74=4@erI$guLr4KfRg?!y(> z`=Y(z_%+U{nCv#g#y{hJgPvM-gbn;@>vU36ZT^cIb9Zms$0rS@{ZV%JJk7Rhz0(jc zQH4!uQE>UvTN-BD-PxaadtEI<>f87{^lx=HpEj$0<*eWA(Zxgv`($tQ8DHZGcMMIK zZ1RpIQ6h>)X6PpNtK#5IbeXe9meLW{y}Ly%v+G3^aX53dwzgxvIrv|CYarO}AJL*+ zqW|9I zc2vJv#Q+twZH$Bjl&LWc*b;aW7MTv6#Z!R2+)=O)OyJ2SiI;Rby^)@CJk@i!NH{GE zms7$>$ABZWj`GHzW;rhL;w5 z0lVF9kQ?-_uM_Hi2dv&QT*V-tN{l|>cm~CFkM$yS<toNIG@gME zixw7kLuB1ldBt>#Sok{=XMJLW3%^qX z{r|LY%GkhMVCFNc>}TBc82*K!ZB@36j3nEhr!()kUAGOXntJ*f)RFS9#HVgH6tV=E<;^WH|VZJeVI5ekbc80@vn?wo}6x7I8uLOm3Gx~O4 zx5QY*WZTh4eP41`uRk4dG#unzBR;Ax$4nTSePkQi4DrMj-ZY}$>J3Duz2sV*^WLww z4jdHtH3S6(G!NN-q_|1NVDB4$lwBeha&E@XaGld7Yq4w`h9~8{86T#ixqm9zOLGYs ztz`D8v9#3dw{=dkd>KcmB0{F8UlGO2O~2&4eGc_~cR3mM7c&D3^9TPvUJg4zl_Ltg zf5S&_y-1i8k5m4i-ZCPcr}5w zRGsHZpn}vcXfGaaJ#>D*EucV2EUAf*OOX!Iu3l#2ycy#9217x2_3m7AKnp}XSLy6p zla?-m2MKlDKvG6#0jAT6LFr$nJGZE8lJ?UmD-Z8{=k6&Ud|62I#C3b@#W$BIH`DYs zI|&5M z#X-*s2hizu&D(|U;GeX2=i}LW@b^gllUV5CTekAH#q509)=wD zgnnPy?AqE%hr22Fp`v#FjlWc@H3yx|?o-<^IWL@g%TYa*Yq$Gfv)3&cFhlS^ zQn7s7BiHk`=gC~>7z-?GD-c7XM}&KZNJfMfJ2;3zAK(|r^ZfZUIw_N+8fU;s$(=40 z&XUDP>0H5U7AZ1FmYGI}x-EVb_vHCS5?`)R^YT|}Wqc|yvS1kh_kmCNP$ShEo{r)O z?!^E$SsW>y5Les^E%^ef#ayL)+WwPgHK`xSrDY{9Bx81j;Ezw`?0d0rh2uN`9Mgn* zwDvp)YYUJBGX664fyV$5$vW}AU+FWeKx+b>@!sKP5!<)WD1-1!G_Fk z+gV0>Zhkx)=cc&%-5l}zrY~Ge&Prvd5<+M;j=q3ZKYCR9lT#8mMo`TsXaB1u4?O@6 zH_8)4?`49)NJM-_QB*RU(-To7u0Pb$6-iw!hU*=Ftv3WQ-9lxOmV)JtF)gvt&t6)U zdrsF~ufFgijpJHv7yFuHw37y-d}SBe#$i6SxcKw;e8J;unGeUK-NlN7738==B$r>q zM24i6iP&|`oZk5dTia`-e`>f|3CLa_JRBy*r&ki7&s(;U%$uWXry+-HsAcHQS7$fR z=k=GWKMVGGZ*=$eJM=P|?{&uhgKNHW3twDr)1L6Lc~k+UyYa+}?PA2^F3)gFOnc8q zp8o#7U9Ut5ZE`9^j}m2BN`{8^pv=63h`f?aL`NiG@RcL=?QBnhU&F#>LJ^^*UVF)t zvI1uy)2X<_Uf_A)^z+mR{i7FSKqRDUZRrm9Rl)@PqXR2)Y z;mXQvPwBDaT*Dv1q&sm^&^gjx%7GqN`vpp!iGUP;u#hsnRj}qU$Hn&qe2lxhm`c>;qKSf zQHIuypca(GGd=V^a=-40mk0{WjHO_)MjSk=i(|&*?ZisNS*J0i*b29qgg9Fzf+95w zwx{(RW>Vs)Q2)o>d1#B6=xAvvlciO~mQ2t`Z$GmEb)=RkT(MDyb*TBq%Mpd!JhaE@JFd1Lo{n6H z(vlM!&6c>h?Ns_Hh7H9oEpgDxJuXC>`t;Re2ix;!CcL+D9Glz9K5c8%CB32y^VOr5 z&cOk;yr0O<;69t?caL#(C{UGmtTe^wsVNGE0;wHo#l!i6zOgA7l0TC1KOa+2K2ssD z6yn1_m%0av>9_$k>x3}&npypzlP!QI9oR+?vtI<&HM#gKMRZy+i7`D}lVs!AiN|63 z4nYT~xHj`k6$JFZiNTj2HbX>|vzVxs<{{3yxvq{#+|4%jpj$B^h6fwH2aDlM>(foC zBu4HujCGv<`;_v^gJ54^tS^Zyi;(gaB~zC6bk5eUFHsewUH2{(xMG^I=RX(TV_*b+ zHnZH`xLXA9?e^3(?UU^*!qx>c-C#@0BDYbakQCf#=hy>yeAu5qo$yBjf^`6I-P2<$Qm1UR`bB9-qbg0ABtptH6FzA5?T+&UC-M# zzF(Q;e$ zI&Z;@xUI4=nP4=`UO5tM;O2H^1J7Y`Tw$*Iey@J#O+f@`Ys1NN84IsMCN$5YnWW4U zhvkW>g`jc=n~GcFWzg}<3I)?>`slnfZ%iE~oN+qv=9AL8YR0aC=6md%>qjqUS3yOo zmg;Q2-0Q|=+@@{yD&iM^BgrdkKFd?V_qM+3`_0F|s@Vsc7VI0+ttr6K7J&%hamGP< zCUM>QM&GxBG%RY_uuarvLg&N~7D#iQ!1=4y-@hCC(4R4&Q|iU$vmVLe0TiUJ++GAd zA^a<7@A*YIAE_i)$94?-nDBn+HO4ypT9Gq@$((`|Gf`p z?&G>ONC=JeC9Ry*0*#34pw%G=(BtiT3Dnb2LS-_YuxV(tT(9G3=^5!}3UJiFyf}@y z8_kfD*eBO{F>CH)pI?zLBM2|7s|%fd&RhU#l$<=H38oYy;~z~+r1D&S97!$xI55O@ zC_@m)DBwwE@&bq!VmBTkThEH;HZi^8pFDpu$KZd&T{-Jibm+-W`nE><7QjB*`)GrU zhQV{vtWnmZGjTBk2B_Wn#VmZrljx1n;9QR zS$T@xbsFJdr!Vag%hm29p2hs!MF2E*J~h5{2qk^myLB=1(8tw{R~Lt8q4z4$qxmfB z=4L0G4JU!_4w$X6O@o&6kUlY*Tw`ps%8+#z`wfMP7srD0)xg_>_}h#wp zdPh@R&a2PC*|!c^Ezsr@#KRjf0zNYy5O7*t<2bA+zWnm;2d8f!hqG^!A8esE>rKDL zcT?B#B>r!4k9%K=GdZtvatg8Gxb8k(53Rv>K^c6L7Bk{B*5}Ob*X;LQQEP79ktg!t zB$qh*(l_3SAhy}^ML^M3X<0Ma8EOWXcFb|xT%%<_=|mSvjCYm}g%n5+^Zcj-MruPX z)?RyRrp@*J>G5kf9zA#7R4I2uJ1MDG=Z%S^@8A3adA602=h#-P9f zmEiC+CKIzwGMEb+%~{OrQO#+0?QO!)lCr{u*f)|5iQ z=F{qV!;{1tjf0}`kZf_#-Bs$n(yaBni2^C3rfHGy%4B?_c~BaV4GxXgQQT<+GqE0I zG2kJ{oWh05W6?U$Z>+lcaqHY%$hG&&02h(<-i{LAHdMMhppVX~X4}$l8@Lyk9Ix@1 z6)|Vra~M)Fn8KhG@P-#h|0b&_~VMewfcm;XubEe5q7e-c{{l}AA`GdxwJ$ad<2ajl!f?!hbVWTau7 z#PADxBFlU^fnEqB?$_WIT)4T7W-v9vj0opTOwhHceT-lbx8vdAguNh{Q3LA49JxaQ z>1!h6%KKn`W?hB6Hs#7aPy6x@gXsq9qKP^NZ%|p9xkqy@$BVO~3u;sC9%lEz+2ch^ zaUL0M<8ymSXj`?PNmWR>QwG!zWk&Yjuk2wIJQ^kVZ+dU!OYr^t#RmCtQUnf4RQF;8 zmu1Yv`L2gZWr>{9y!=u5E_nIQu(G1%q&;#Rn7Ov>7nf&`V?;_M15ljUPsQ~Cybo5+ zPJbiHeEAcHsn=yQ<+0B>vR%gTTZ&YK_zIuWfpl<*R-ZG^zj<(G5@=5=!;d9=JIF~B zQ1;_;coqZS!EayhFPzoJI(JB>tOF0E&v1D$4zJXU8J}+RhtGfm#PhJX#cdA$z|MI2 zrsLwl$aUfri8aSfh~Ea};>6dOiA!5x4rm)p>3;MCK5d6FlOa8`qUPeRz(yf>`s45TN2Ogd!#3WqMBYM(73B(*1Hla~-*^YWYSzr4zE%`_ok@n&^ zyy#7&lg_)SpxAh-XPBVtHauMtXhvbZzJ25EXqW_F_{(Fgj+`*(ySWkn?)*0AFPpFh zTtpvgiWsj9;^6oG@avYw-gKea((bb=$2Ehers_I#E^foZJFiNkaA5SrV17o2&g=^M zL$M4gl3y$`!=-&)lJUQcAOmD@FgL9;AtxUqPHP(Lmnp83@Gb}-&1j`ATY0tPZS@~< z?__yE*ZM!d2t%mM^f&&ZXt?GVhI;^z!qhFZUyy-horKC^kpV7w3v%V3s)-&F$`^oA z-2k?U{6cR;lb#S6M!+*v?Qn8Vgb#6yHWEOOf!l73v4%0@!WnxeinK;Q-jb(2p&$E$Yyg z-UWv!9)@drd4N+&@ygT;;8`jFeY!@eKm3K{_vge594<$T!d`_k#~$-espn_e2KEcy z3FS>!%Stt?x2#-V!){?Bu6=?=gQU5fWG8JB7q8f3TBpgDjZN#SYyZ$eg}O`?OZv63C`XNdqc+c*X+Q zzhUn|qeWu=mbty(-F{^FJ2;O9W&Y0>ffMj<9)cL2au<=O2e2?KW#)ca>|kHX{+Q?-o4?*w6E;q zS&Uf{PEww6fw-cCs49h#R@=DA?3nTDnsB%!OzPDO;`>t!;UH!F)VW(d-4fc~lBaaA z9;$}9HvWVSF%F`7V7?4ak|)tSM^5t>#F_QJFe6vUyq0mf0nWoS;grEoDw!-$VkB-9 z&oCThByh*q#C<~ZFBn(io-^ z+#};~emo3{U$MfqHdnh*GjyLdZjPDJYh3gZ z(+`?@LhL*3o+xz|JtSm~+XjUHJn26+(jp5!DsMb=F#c#2Df0ooU2~g6*f9Fe<2$vG z>h=DVKxA)(oj(}7O#1YB4>r2FK@w{Q>XsW#_5+f5e8BLM=McX#;+sly-@~w|g9C;& zzPn_EWVlLYInM?utO8Fg@?GS!DlE;z?_o*%K;V1g-o#LB=Qv2|Gu48Huz;Mtbk-@}SB;l5i2*H&U!67?}#{CxNh%{G!* zeY|8yDzku0tW=Ns{zBtb1%ocoEN%Hn3ij(4!Muo$5f#BDGjRPS#p**V>J@Bbre%4` zV*HiNdM7P4>f$2DD^c|RLF}JVwvtiV_uNyUaaxH4S>shVN?X6fXa4Q~nI%ie(I%II z$-jQ~mbU)9BtGU7jd)WCfusmU?oA6F!Aoz{nEY}+kM za?+@Tmh8DNS5kikr=jGcJ>CJIK&oKmde@oFIn{M-;mBVd_>m&!k22E>SPXvPIbHO9 zNW)_#-Ts;i7XgFezB3IY$xC%r+1~QL{Wafk{N<39Y~JNn68C*-MM?peXI0Xo34AQW zhV1=KI)w@jehZ=#yf<|uUh6d27|u@9xQTDI3HI-c!4Ds9jyVH#POan1?&mG5_6=ek z8@TQ+EFf`79qk(|rd(@Q)3rE9`krduTDK#bM~2-vbcaUKVguFebZhZ}Vtlm;o_@Ny zZALBAPLnn#-M9MpFoIP57+Q01IgC;5+Hc5a{QYH3X?gx!aJ%6&v`|ro4Jc6cSIg2$eq|ZSuAfvux#UQv~E6rP4pbW9nep5-& z*#gs}P9khx#XRa=-?Fq6$ME@*^pUmmci#VOmK$F`|1NYamU&c4rmH*=7g^v?(Uo$O zw`=?Ci#&Ge9RCb*n(u>E=-A|McM28KwNVrv^XPij>D38vrDM#JfV&2TukTM6F4c8@ z9H`=B28>b;=gn(a$_pG}+yE;r1HEW49~?n>xn(sBSEaDO+Mky)AE2Pd6j8XG1yUMv zFAZkeCEXf@hAFfSy{fG_%YW~^-ePx94=+q;%%u#**ci3qAZSbH&NqE$v01;Fpj4#@ z4}oE|XfP4Y*^@2ywiI3LfL1b9L3dm8ba3#1Q^gR2o}N2|8cD}Fujzg%Ckch0a`W1+sL>p9jd)xxz)`aI%-*sNTQ0SPQgP5BfJ0aB#g*ZjqcYL=gy+?DT zMJf(0O1s=wW8 zLvM)nn9kx;sL(L*ATZNW#d;mqSkObtHrAWBgn?StmUZ(nDY4Ns1NTECJvfcw9|<@H zs7`jod9grYNda2!e~|$*2!KEoyeOqVWD`hdG%}@n`1Eac*^6-oAarz(PmbT-F1LBV zX*z8L8gKbjjfZv)6C!C3S`eFex`qJ>8~J5be{ON{^ct>PF(fjN8jfj;19~@L&P`^0 zu=C_{Bxr7h+SDD9h93BMK`F1Iuqja>#_@xLTrf9pdmy9dXy}Yzx;P=tdLg0Zh^>2bt1wpOxssQS?0Cl*!Xxj8RwQQfl>k^rv1+InDTZdf)^L54C&8srhNpUdR;b6zU$|wI*0G$oX8vSWa+L zum*lBqFm9P|4#$=6II|hC1}YT(xBPcgxLvo9m^kbRS>jI)!F8CtUiaR*qa% zLbp%TX=B_Qe>UR@buwSkVO;J7mpk-sK1mpI5ix}(a!_*5#L4#JQu1{^f_-LsuCVA| zQ`Nsws+=I#J2{qEM)(r>1p~hDS#Fot5lyBYzkDDAORr$_%;?yBoG!OXZA(z!^4og@0iLF z5}cAd^QW$jH~g&f%We2{YU!Olyl@4I%qe|r)8dZTgwP;DJ1$O|nH*)JIWZ2UvxdF#w3k@n`<9@9_mfj((r!s;(J*9 z0@#U)TYqfAs%(rRamTq?+z{{6mS&Q<+r8N6t6}JH_!j7^(5JS@oqXLCx1{n<^M++p zQ{!5DN*5X21G{df>leO==Z(Rmys#wl7xG-t$;6; zFaJdsu3}EUuDAkgr}7RbK7PE(WYeMgd2QjZ~l1zcanRLyD(?2h|PyYCLXu6gn{yrR27DI@R zFNjmV_4_=9(P)4^013hh{GPavb*(7y&l}hcl(agS`JL&f%!l$rf8TT9G3}!uUC!~7 z^KP<=u&Zk(MSnGm_L2Pf00!hJaXCA#4Y_^$;|R3rr-5UW`PEFR=%iw5 zCC)o%Rk|D8*&Fn~wEpj?q5K|A+Vr7B$vw$5mp>kUI$rg@h%QMoZG>8F z_S&A$Il6lU)42g@Bc{D^$u_QUx|n~ux?8^Qsz9%I{WqIZ(rAx%wdJ=ar)B)VJJx@e z;J?2iqs1q?wKSN`pA;)qN8QEJ?h-Vq8@oC4>_Ld->Dxet>$(JW^?%-ZO_h5$cOPgW zsB3*oxYyRiOU}-V;h;vX`~ZQt9s}B7>-R*3g~E7-A9i`J0dB*VZzXue*aIQRH} zIIh4g*J`(uSqzf+z*|;)wHO=pzLC?==i1~Wv&4Oj(ASx+6RH4!XQwM`RQFpK+_I-u zce|mlU3& zzq)*wS-LE{Yyutt=E?&=u9D382#UO@NpLrOXLzpNSawZ*|Foq8aaD!X$3DEj)AuF* zKVAi50H3>0{9v8!9Z%tS7=}7AIcYXRb25eDZ$OXtn1w2Mr@6M)qt^v_w%Fk%0$d>z zD$25i(8lbGFq`T0Q3>QAe_4I~+%Wy!{_ZYJy9xtWc?GE~N-Lr7wg3w|<^1O{A(^uc zK$gHRay)lv&L$`kMip$9xXheW;V&ZU2}zLf#`)^1D(vT8%xtQLCo2;Znv@JjsDbIS zpMR^0d!UTC0li!Cvzm2Fhi8+BDPi>Cx;@9>oj-efFqeuU&&A?M!R7z;n5cmprJQ=P zNcpELJPw5!-E2_wK6m7GC%MVGf}Y-jktg(JR*!*icXa}}>)Ynlr=0z2yya5OVjlqt zi)=UQ#ie^j%JcQ{nHkHOF4y=79}uQObKRBAh~-#p3$NO#!#v%p8|tIRVeBWSQzFO5 z;%shlk2x89`GO4bM&>qNNsxPIEhvAZ-13vZ!%X^eS z9u$0><8#Uv;o%<3_>aqgMnoItQ-&w7cAw1K9eswUR6DX+2Dl@ra7o?Fx;kH||FDud z&BkWoHPq%x`)>KJ%gdW)^#z$^)}X<$^M=x3*Bvjr_LT@5Q(OO3M|e(&b#1Iq4#pBq{SFdV;)O zdx?UCQ`#U)mA{z-e6;hH%yZJlw(WCJWwhMSpiVy^mK|8dSc2AFszp(I=IdoAmqJqo znPE}pQGL-jj~nRJ+dylJPAwdniP+3+abCD^bSEh$X7=6!i#6p$x7*fe*fc0objy=zxf;a(r1#QO%-EvI!?mxnw=3mm8PmQGxQ{BUkf0h&W| zgQXK*@0dQ%UJ@r|FdDkXK-{1<-v_7s}Q9pCFp=7GFKbv@i5$ZTW_;?T3t#e=E)rRe@On&&l?|!8M-VpqE zx7=I+{g}2l2f=*OD|4N znplQ&Uy1doQyXMB;PpR*4{U5GQ)ViLDKB%}9qhg|m$e^B#M9_4CPZqmEbtLhfUc;(oyW$I`tK5+Yv^L95UMcX;N9M6|y4X^rDCEhJVJhms`caY61~bZN*mcV@saU z&V_iOr>t9>?f>e=Zd<8S+0QNS-0{c; z*)i!q!ZhbrG`q9AlUco^5k5u7BgHGFoU55haS}X4Bl`4319$|q4uFMbClVuqx#vCN z8%MVtK~IZy#OE2DJ%U42>0`U@eSJ5B+?dnhh5rj4LE*j$z*YO<-osB6u*LK}jbfTk z&OMJsKlo#yk00_2!SCzq8PcZQf1Cq>wLzd^a0eVG*(h4r^~UdsRlnixPbM^VGL^~v zU;UJ8*GHZBP?Db0uMS)=%PBMWejeGtqS~)(^Q)i7eIT&*2n4ZTd+Z{l5O6{dsiyz^n`6f*dZNr)v+&|6DF)_iMtCU;MjCj-Qp&!F=-G z<1fY;*V6|9>VVfB+Dc_ct5WZZXyBiE#u?{zuKLYw}b`|&=nss56_%fPuPFS2-B zA@4b^(x7?Hn&KYsyhMD{0Rb2^w)E9`rM*ePG~_wte<)F}4z=q2kOXNDq^`q9Sk zamIOaAwV5>g6ag`?-}e-{%Gh~tC3CAGNJdjQC+W!_q9-Wo{bDe*}W7!pWKsw2tMtk zyL+Xz8^Z8gg2ONAIey&xwRwntfj|`k^=RN#hx&Rob8Ph}@6tq_>gz)pBXcnC;~?>L zP&${iuRUAMs=`@}^l!{QSL%DEzsvPH4*<&EEgGH=m?~aF35&Pf_i-(c#6|4XVXmz{ z>)z@-XB|0pU4#n+#u0%a_TvcVWQ@vweEip{kOBMA(sTb&;+6mC@r+Iy?c;QJkT=JJ zGo*zX3p$B#Qy+mmOO?x-HskGvoO9jU+G@lVa*to0;b==mzxHqn{`21t&o^hVz&rwy z@7u|eb@$`HGvMXdQxKZS(l{VcD)p*eHOh=$A52qx5N&pvs;`r2sH$17ev8rIQ{VJL zl?=iS(auDjFw*avDZKVW6VXy?x6M85J2OD0j1HD`jtjW zaWjCx`GDT)vt%Jz_GPdgu;hntJn*njeTT*q;R1niM<9s(xI;R*A}nguykjK?l@663 zLHo%x0!wF1$L!j-V))6G^YN1w+`t7Q0+GR%IBW0GCRNN6hR1jOig7| z>vZ(0erouTO4MJ7dA(+ubn5C^X?32SzpoI zqKz1A;8D{Ehj5b+fgtviu+Sz#ScBXz^Au4$rOJqPZQ4BW`a@BgA5H^0S!3m6f zu^@71ZDcmb@O(^nyc~zAa`rahe0iQc3vhK&9PvtXt^#hE!=1g1R03)1h z?)@G99NVdkPvmW^2x!~bdads=CAbW1w5_VDjuGdkR){mYbxdwl_w@CsI%)FJ(L>w^ zWQtSLpmLyWW@=$*Htn9;0IX&F9<%@U0q#WieFvM-iDVK|Dm-dmq`qG}Q8jd=jtw?R8_nK4Z9IF+w86|-X|v6?k~vLl>gdqBj+y1b zINLR2GNbs^rZKJT>FG)xIkdM5r|qf-iS`Z_`LJ27MruqViC)(DcZ;VvFDLI z7u!m)?(iJUzz$cmx%coz|8X4%I06G&G|LC5>Sd0T23ph1_Knk=ZFWrC&D%B2nY$ou zvH7-ohq)K4RI>>VztJ50J~wKGEp?2=uTt`tT{aV|SDoaYz1PbDRPg0+4QlI+s?&Yl zEvdbwF|}{GAZ@)_S32N1C~~^fql@oL4?eIc-E;44IxkF5FIlX$01D4eJX-LJ-M@w; zj1oN2I0pjbhCmSeaf5R5MpWH-(g}0$!{^iF{sYG|4(`!Nay^}0HA!eI z!^?5>aMKyPsgQRk2#|U-^^`yD!gl5;w-fSNEN`y^)z7B_9@Tj$4s?s}zyJp>KC{6L zm$x4@_k=CtRtz84fdB~fYmsb6`-W-WwmYXCw%appxBZ@JvrV=WN$*GleJwic_qWu< z=9X%c8U)mfz?(8D@0OFd#H7Cy6@vR4*H+&q&3eD;AN7A%ony5J7N5JXYHLZ&z`-T+?x84^6Oaf z-boAO9^!|MCP&6E51vX|>{TQ$xf99S%@{b1gz~z3?q%a`qgXzaV`F2p5&Gf)IQz-% z$-`GmJks-Of3<(V`gS~0KK(iT9#e?yvUy)eN8VwIwvx>j@^4gi84#w}-pY~0X`l#^q}j7JO}p;;qBMX0{ItzB+t|!9vpwBCD5Ycusjtsc&j^dtr8zB$)md^Y z9g~hRW_h5AhwQIhuPsbjt1ds4T;!{Px|QaCK&0P%m6#pi*gz36Gm!MHlP%L;`yQBf z->b_^b?&(HZ|SbP7N);H@}PFvxg*c;X&_<0CmMJ#_^2y&OCH6@P2Mv@+Y37oLMZ{=px=ULGUI9&aWbfy@}o$&|_PDv4I; zaP_OEMrqX*j4dilV)T&i1}T=@!5-cSw8gb#Pj+{Vr+7 z%-u|BLcMTBNN$gLR=GO8iMxkD>vvpa9>VO7foT&P>MK9Y4s5m6Hfh^!w@v%(^Ju#B z&fC)6ceSO5A9^6I?0P1(wKr?5p^qH)bt#|9vj!(Unz>>jKJoAoF8XEiNgvYOEYmfT z9VGRnTP_2h*S(%ED+DK?z^YE-+mXhKctm$Lz6V^+Bv3_ zx{MHa>UXlSp>&=cu&vj{9g)>PD%lu}%J3jp#b5XAoe61kHqcU7A?L z$bW^%=R_-*F!=A&EJ8zLed=hNrR_Mi#igX)V)Jd%CL3>+_TFuebla^rrdw{mK0W%# z?K0C@l3K;r84PrH^=NPYW)c0orDuJU20v;GnCZ9GwlXnp3#4%3PWwQc%t3h;-+7r8!XK}r* z5vY*ZRZ=!hvXe(Y5B1g3(qUUd`tM>-k4$swF>z~2o!!!QH*ToyDd(iUc0Wv7`a{x2 z8_v-WBMW6^gwj`MAEF{gZ+8%UC;7zb1Hz%Hj`y9Dd)JItez&t+QqahYM6+23W+;%Y zv7sexyy5ogkmqfk7VNM~y7`uC)9nlYn4VbtKw7b4rEQVfuRfq(0|WdM7n*zf-O&Ju z>k2t{eEnROX^`Ak@;or8smD*asfa)j`>9x}&mvEBjvV}OU?&W@cMX{n{AUqec&$PJ zY`xO~SFXX>NlB0FC;i&}`Msa3qKw;hhyZ2a?Eu0+8PTyaIHS$r@Wa8oVj23gbtvwn zOUf~F+#FBNJYx+5QDIxTiBY0%uTaoTs!BW1R7WSYOtZZgebAuL~mWd=v2U%#XNTk2a> zGDYC+a@~-6&s3R6+pV!_yJGf$ug)S@U#~WskV#QXYo3W>fw(d$f?l6C-DKx<{4w*> zZaeRv{_uxiq}%TNQ|jqjqCt+nTHC6%1$}wTX5c|nncH<&B9VW!ZeDy$1 z)TeX1Oz;O%w+Q|go9~`pci?wsoTeVnHf0zvGjQfaP5UicAovjT!Uspr}|SFXdYJpzuS6BqxX2lu`{ zEec~{l#cv9|KPgcwNEudjt2sigO?u!qPe-%w8+@N2ao9}jt^S{y}u$y@Q> zuQ{W+Z*FGM?8?FN;CZ<9i-7dWCP2dwo~T96MkrmjYAvxpS0B^RX?w`GHn(f{mnLlp zGcz5y|B>mC=bn@{*S3}Yde+v~E|Z&H`*N%7Q}kQeuZ6aCnqi(H`<5;v_QVL0r~jfo z(yyVppLngkYs?|gI6reebjLa5YpC~G2ASpPH{TWr%U^@)cVmh50WJEF)y%ZpE=Q%! zH{C8>bIm1b(W0BuvgHqJZy)7P0~s6aHnNzwR|5l2&(EYgoXaGCl>yd}avLsOJe!ON zG|Zc~-Ff^#KK9sSCO^NGY8PdavHr8v+Q!yVIB!7tF8+@X0%$?p1cx6)ehB&Dpic0^ z!*#f|M*tk106Lc5*?7m}xN}zP8%!*S%ODi%?SeA%@|=#-uR+AXKA zFK_>-N}=|rU1nsi)2m%#8Z@GCLQj36PEcQHvm9QZD(OztRpocPk^;XE{QkqK%D)u? ztXC#E$Y#GIjEGPYu*av)b^6d2+gq0U>(i`Rn`k@F-ObkisU=UQu9aGNt8r8vJM7pX zK{FGMFD6ltd_Qc#EHV`bzg+7ut-e36lw3vbxEd`2-CZk3>vf&_3yu9cg?s%b#*a(! zhmQO9_V&RaLf-M?=$$1$lHtaVfMf0i(eLSy{96J3wN30X@y932`QZ;Yu?Tosc%3h% zR(zIsX=%&m0`f!|Iq~!`?%(6|^7i*}UKIhy$T4#a@ma)}_t~DhO>F}*m-kD@zlSZx z?$3(x72n78cpts0WZ*wKy%Y?uDLYbeeYiw+sKb_ zt?LmMm?c&EY2MjPfb}12vq|jW#eqyZ8{cQp<+AHC+>}BfH1<=fI9JV#|G4pk2NA*f zH60~;;kq9`uNq4{nP>zk6Nn6F${}|I6P;?rzd8gche}(?yWkW%(ba{GcjJpdZWB(3 zXeX7nGQKHAY|jRPf$|Sk?pZ1!`79I+lGjZl=$tc=)ow@9wl~PW9Fp19H6uOuz+=;q zBK2Etv7-oWyJ_$-xnbMOfd-M$K@BtI4~d1DLXxGCw`<+5H<#;VC3$1gWtq!Q2jwrz z?S$H%lOM&QYs_lM&w#Gg1L&;WYImR}&04g#&rDlyHP?P6A- zuTS?{P%M>@wEiiz$jlRb^S}Wa{XmBDwWVKOa(W$Z)Ch#ee$-Hf$MHmf4zZ{egQ(!p z2K(1CxyPTM-H$zpe-nxTSW^}($V7wB&L5CRG{o8NzT8nvs1(yTaxI@j(E*9dp_SWx;P6ZKbTMSS6t~mFp@2;=vdZ$OO@MzbPxCZD0(M z?CxO~n>O+FW-XQ#VP%IK5znKKctzT8--FVet>@_@O`@eVxO!=##ZDWvV@$6!()feu zW~Tw25mL0zin)4MnCxja|2-b}GREImPrt08M^W-jW5l{D*`#cgWZD9xQSD;>Y#Z0omwf8Awj1FSb;OHdXMV>S!PPpMaCOTGHg zm0=_Ep5h0yvV0l4%7?8?koY%+5Qw?{DO8xlWrYsVJ4M$Bqq&DnqOs>k*PZ+G`#4WL z0*<+t2PQdAN+v$_NC5=A3^-R~Pg|j#aB$80YCnPE#3KOal#iDOgJ1@}*}R~VzL%k& zD{tazVi15NLT3FuG?mBUvI_B+r(&2PB%i!-@K6dlb~Cef?~`Q=Iu7 zzI@~<+!REB+81sLBjCiIj*e@blSrPqD_;AvIIkN7oV1{cgg|od<(50mXr>cg62mnP~Z@Yy3r=T`@sf_-~lwlFKaLMY%XC>*9>9cJ5ayXHQoq zA|mT0w!xG+Nk{8!eT=FuwX|)Tjy&>(=?EQ-&Dxh;3(~bHwom)i_hLg|CxV}v zMOZOap(Sc|M)vl4t3&Hs6sEp}VrsOGzOK^WjW*Pp{XxQuho{3i|AyEZf&TfxgW_fdxiic^cEyfyIzz%lTe4^`eXnPyoYS4#z-+=M}o0O=rM>cr zNjAoS4NfoyY;3ZO5J(6F$~kntsh{ts>h60_U)@&do4Zd*r_Z@{>QwF8mA8JE<0K#F=f1Nby;5{ov(J02~U^|sGm_j!?VI`1p@UO|EiJvWcuMz_d+qh#xbd;mu5VC$)rqt+H6$Lh2PLd{C{PVoCcMVG z*sGg4P^0#Bb9Q3dt2qFOHxR-zgCQO0<+yUEdO3mPFbm>vosBD<+5MVk7 zuvgOrur7h?Ibc6bSY|!nLLPm-lt0-KDi>C$^F;yqtn1GVx?UY*H8D9OJ^GB-r7vj3 zRyx0+juv?y!GP(EkWCR}3<3{p$ zvDth8n)R{=plXsAI;n*3v?Yho(xN>x&oIecWzd#{N1KAm(u^`8_*Jf19oE4`+yMk| z=eX{Sx05`pK)biB2WlEsd)Um0}y&lmW|@>l!wD36WzQNO{#VNWl#lCO}5u8un>60RU~mQE+5=G6C2OHV%MR=Tf#@X?@g=3clTh5;(Wh6v#EttUT#^@)g2P!^JW$WFyV> zNb>GC$4b4XM|SWr1@nhReVN(1QpJWR^rPUI~$OQZo z&t?iz>(S&mH?OKrB`5JycXA+F8@n?HG1ZskfJub`jW#H9w}JAK5!4Z2Mw@*w7PdjT%x_=a!IOeEp)J3n^Ln*}QfwDk1{Tm7iGaN)S~UAtYh z46IC`KU!Aprg5>SZ)L!pdT0FahI~V-?a83dP^Y=$9~_6BG4a)yFaMm5q$iIl9fA|A z$_Pu8CcEUHD;nQiz|xrp=>r^)h61j6 z4gemz)YHDxC;a?$Qe`XEmH~ozFq6i202WTAT()djrx#8s?zD6hCp3AOQvRdBr&`L= zDvn&34!p5Wmi+J>Rhi<% zki>_>ftXZtK0?B`2mA@cyQ1u1%vI+jpfi(P#j z;9x2y@tjGsapM;E@B`m*Ygb<5E#-I>AgKun)@$O`>sPUpEOW@*C?-c4dt`SS9c>`c`LaL;?*^+?J`8zGO$6cfiF?dG?&srl<%=L{Rr z8wK{1m6e;_JH7n6nLg?We4f?D*rGPT7K;Heq5_#H_Pa+OeA?Z({ch>SBX~iLgwu*&Z8{R-=Q}1ENG&_j0j{7kmzz5Q@q?(!G+K_GNPoA` zRL#d|Te+NxW$W@;8%!6~ZlGD%$^&}9Jijr90mw@CP=AoX=R9Cf>%bcZ`dp4xG$y^F z{#(7`9nT@oAh{2Dtd%}~m!5n#n@84Gpqa^vx$3et|M=cG4x}YGnVHH;LOGuWZ0b!kkjShK@V}W2uYBt_}{QG(j(_En_CMw`a)B z=9BKuuYSv&IDXK*^R5oCN=Vl}S#)`gBd9_3$QC~13I|weZEoJtwGNWvPdk7EsnOAG z|42uE?AS3+4g&-;YWzCE_4W6a$fz~2bOME)PD5zOESI)phHl`1zpG@C+>&@ks7ztzoqyOiZjyTT98(OO1Y)s!%Lyi>G$N zCWX}1<+?4KcDN^=_+PFsv(aUz2@_T!^Xjjut4W(sE^rYa z8cdN+`V&wASmUAtUi7)aiI$@SXfWU+O$(Cpyc-=Ib<3A8_rEiJX)Pb#;6DENV^3R3 zYBTEhy^2n6FV=g?QI#GHRA{i!h?3H&e8lYmu)MZ!zs`O8+uzhUf@UF|o(398H2V9c z^C>C)fddEqgrSEM{e0vXBv74TQ-4ziT+qTrUT_S4@Gi$>r}VD6ysCdUmC!{Td64vm ziBoTH#;+E24sWf#*De6)1dxY88`ZP0nHFjMz`&sNZr8h~o{~C*+8Fs985(wj0|Rd5 zik0s6uYT2yPmFs>E9Ue7X2j>4g_5J*>1UM-_0xMQ4e3}^y>H)7+6*cNI4jfkQL{8s zmZFFH@m`meiA5&Gx!kN9>|gEfzwb%6ZS*SwniG zc2522#uCfxL|Q)vO8(CH){`6*&vR~gWJr4T3AbPs#469x$cDhD^-c)ff0;Rn4c4tm7_BLnVb;!A2egv;iF zZogRv@dUN`PXJQ^*jGPOZq?5CNZ8ob$ARj0P^+!fmqK&Dj@AXEofO%xvTofv_vDjL z>N(>kCMNs@pLcx2d)nkf4?X0rzWQpNXvr!W?JYR!9r0c0Dq${s*B&48Q%$e6qxMj= zbW)`b&CE=?-o9S-ubN=$;HjH#y3gHt=VL09Vfhbw8|>7jY<9*AZ0OrVy}ht+TRNO; zOimeF5uD-t#7YwUJ{@3{o$hg8z5O9~)6Ms|O#gB>B>@rRs*1=v_|MoJyT!?YxMg*D zxy}df@aLjK<%)*mnT8!Y*XA-HNa+in1~$q9DA1|@^{;>J4j(@3I~T%W#pbD}o|H+n z<(?pH^qRgefWv47=K|V|{-nTqQG?5Ex7_9)df-9V4`7jmzE{$tSyXv6m*DDA8vI6b zAyXjQx+RHGS)HJ{Jh)WsVRC}xmDP#>oOmXW1Cp+CxAG(|dv~dLOqeLGc$#0oh(~)D_36a?!8MZrbVrgO0Sz0lw>-r zq)@NW_s04eWi~tKz@{b3!MZX|JLilFjNPE-itx(o(x->i84UWe7#>(7={);og0QQo zw(0lZl+>Z>A|U>_BRSBz(W@h~-~B`}fYx%+0T=*K?P~c|hiSxbqYv;-XKq$-0QWDy z{IWZH_N-S02;hF1bmMsM;4U{f)UQqrJKeGj zB3(ix^%WNYv;RHkq`*puPJJ@qV!Z5BI=huF&J*o{w5a2>NdPH889(Yi zzj-!#D)-<|Si)GFAU^5~I`jZt!V~7%XPE5}VCKqX8OiGGTtrPJ7A6 zuhU=)vR@ClOs3c{`;c3{VvBwcYf@R-ALkEdD)qm3U-^Yrwj z@=EI^lpf=pjue(X=z$!vp=K%^g49wZd6> zQI^n!!!K?l&F8+fsa(7%a4K)O#8-cktO`Q>mh4__wpaUUR=b;I0`sbkI-xcTkPmGV%SCbfSj6>W z@n&slW{`Jf5=+R^T9hN%S z*!tri|3vCJBO0isw<+m6I`n{sew`wV!=euQ!8>;B@M;9;&a*j)Gyo=AmGm}zE3{XE zjL2Y93DbE`@D3ow-OAditp08O@qJ+&h_)4*fG#Yi%m2#S2I*1GR)4AMv>E&><;+CX zF4EBc5nrvt1eI_>s-Bhws8jAg|MTD7KmF4`c?rGc2Q!y!N@r8{#KfeJpLF|WeT@9~ zNmm+28^xbHj(3=mWfcstZ|U%!HcZ-tF{#47x}k zaRw5MCNCY-iG@=WGwxR}{?Z*id{nyey{=D|Nivcw{_qDsaQ%|}^#T~Q<3FvucwKp^ z1U&TM{q8oI?n_7n#097~AQF}u$v4&eB2~Og1{S~y#w&wj`E`Z*822Q&dL_rCW%_x$tEYs2lh0LhF85a0docipya+sg40H#)ye9FPf!T#@klqlQg*i<kLKI1%~XVbS#*rDcP z>Muy&v4#;g&V^GbPoF;RRcZzXuq-uO(w7gaZ`ia4*k5O)T;^z%+vR39Fh)xrLPU(9#HR{moCQ;Brs!P ze-j$lX6Fc~N)ssjG;fkRz033txxwT{x8tU-xi1gyaoNI@j7Tgjz4)u{;6U7}x}%)t zr7}8*0ZI&*m_PUV9ATU7NP__%sXZ6Ezzq5Zx{<;YhMoKxlidq1yddj1Pq_^n)_LHM z%FW;Y?GLrt@BjCpfo1>QyLWl;?*XqYB%8E?_yHARqQGQg?rO!{yfV1Jn^H$O_hrZY zf;UmH5-m^OMSph;(OpD{@zB~!l;5q$MrCpas79wgfOD*gAPq-4zjEa&9lCavTfcst z4qaR6)zGN>(AwLJetllwG2vr_Ytc_`k*uR<&psAwZG{F#vAdXF&Ho32S=h2Rn7TMkA9UmkOEJ|ZNQ8A`%ntsqIb*t?q>SSQ+eE(LPASF46}W(M=~&w)Kh1XVz#Px4Xjpkh-&vUW-e?Xa z-HkWg>{hSZC?Ki*PvSqTu((vJR}y@ls0SJcR8-(eB+P*NSr0CGAG^kJfQd9r50fUp z`iJUW@1Qm}Z*g0;UgM4&`^0Z(PH0lriZ6Iw_nDUX)iD*aDw;MvBHVeRWydZ@V`$KSm#Eg!BO7490Z!8ibRw zz@by}{`QA|t3ec04Lznh$zaHq97@YLxO z?%HkFOZPtG4g~w}w3UH!Td_LZnh6!_h+qrX>d+)uSZqFzC-1+n8{R#rWp14=68kR+rX>EQ#?Dx8$_wQ*_ zeGQKOD75u(r|sitm(~w>j|Kf9FIHaAL)&NkB7b3WZ|N;4`bGbd%o?b4;1T5{feZTA z@GvRsMv|)csJ`U1BGe<0PM?}c=5)z|8GD}6{pz!CS6%&Iu1}}SCbi;(jdV^y;zsv0 zs|jHOl^aZ63djTIQSB}=UeW*hy0LIJr}N`3qqrCY3ZipXv|(r=SDg0aMp2tZv$Ch3 z(WDkz?)k!m@*>(bE+qUIaZ33Z)A%x`vF3~$S$@u~Ts`5ItvKg~mrb~I=CtTPCn_hz zA?+K{$^&XF@SrI5&th>z@yfKMc$Z{PK~ZWhs{5&;tU}G|(5_keON!1)1+4(SdS3Wn z_|)el3Q&CPWnlc*q+Vs`CsF#%CfY<|#wF6~I|`zFX4VZ4t#|Ldvs2-85M)~U(VmDv z8R0MIqOQcwIMAsl&sy(mbjJ6X11;r1UXsP_+qZkmHedVN*F2DT_uY5B8o^61z2r~M zT(f44I?SRDuUg@MBhkmS<=(w}b$s^o?ujR!Q0E*}7#Q4xM3W=7!-l?=W~jl58EC1F z)&N_zfBbu49H_<5`FOvu6l#A(8Ybbk`if*7$$0>(!J^cev!~pVBS+oI<0rfs%X8<> zc@-GK5C`ppu^fw1sPG`EM?W7u`%I>%my=<;Urq(Tl z_vUCZn@KuDLqqP1FFto~zx}p*=9#Db$+imV)pkDqc#k`$4Y;J8*M@k$546?JccXks zr`nNj>>9%Xf54O`PbyILv6^54B;|T~RL<(VZ@h7b)Vfy7-~p;w>=g-hhhi~%>5ZYJ zb}X}+L^w?-ywF1vWG0+5GZScy38w$Dy$$E`tROxhtNhi5$off8z23G{=2?(MiZKh)bQ52>#yJ8KH7aq zMOu(S%(>wkK}j4(`#BH;`}UVX(kT4ECWz3nm0>G1waf z=%VqzR$0~pHMQ~@`&~W<43J*_7xjfS^%yH(>MbfYfBDN_yviBsYk=^x=T1qLCRm69 zP_bE-wu25W)mWIuJE`V-U;((m*{XxJ2mJVs^is);2WzC4%@*92EnB6&GpzL45ZkL$ zYJcu0(3mqsZ~n~bbCPOuMnp=I{$IJj`@6r>arJ4peED*}=VfwI6KzTTGnsz1&9IM# zeFLp>tuDJ(<*W7S81VFX-q#^`>rXG$3J!ZYyvmKRI=6KTR-pRaQGxsq|N5!>;^;vEe3_3` zJIv@1sHw3Tw|r=sUoj}C?Iv{cv!7)cn3sKjzgne(r2Jh{{kk0Smh|dt#lz&Dwn+Kq z)Ne4!zv22D-R_Tnr+i3tN-HX{TYMadr)ynarUnS2*`N{QY*3HB>$GP&(18J+iYHJX zB<)Fe-+lMG+i$Bdc=E|7W#@jG2NI~)5XN-(3Bv_|DZ7hw ze&sM7`al`iD(4O*x2wo9Fj&pwR`DB94JZP5+vaaT^vRPa-JU&r+-IMC=B?VGFHil( zq77|^urzaj;-^3jchriw090Wkt@9gek(}ZO$R->hhKsOF9EcY;JUr|H0PPFa%#$Zi zd+9s8U=uE@0MKeQvtovup3Ztnpr51&WLaDGFI(^@T2@w$+^rvM0SSvF33T7*0`H*C zB!DjeqE48l9(l>Uo>#6|=dRwoRrQKGg)jxxEmW~W{i06K1@(<*(~Rgy2)xR4zVGkT zDNQP;RYx^Z9ngM|Zs&jv zV9^1NJXQbh#C)>cS(HxwfWSmTy=-nq2Tf^EzVB=IxE(j#;BDAvbsFY#&;Hzf_US&o z6M#`iwR+_m_r0h8#sdlf{Qmv>{ia($3X*&V6~H|MQPd%9nmcqw-*(<}6nJ(Xb&G={ z1B30z4RselY*KW9HV$x4*;9uBO8|NgnpCd?hypaB?tlr(a9|Wm>qr6ZbXuxE2Tq}; zhJW-O`qF&MVKo4C(m8eNl)uw{KKS6TbAU0De5~)Jy{>gITMO6+yDvpe(W0OnjFsnQC zxzt_#Z@SA1W#@&&bDZrUfJ?uh&=`@C>dC~|dG+<@wYhh>R&;d&>rJYw2&qL^Y5J?M zB2kx`n6JxzOP0L2GeHqP*LcJ36{&WXgxh?d)q)tG%21X2);G7guimju?Eopf4p>ZS z^+Gh|Ikg$dJbMhhBURdggjgEGxEkk(SCbste}wPwgK`PuNC5h)R<3hfN3WM&zL??n zJ}9Hr_r?(x$J7Q61W`>J5{{E>EC*<~)s6wK(_LPm9tTKZ*$|KcI6yM^*kg}*fUtAt zP7l_9``h12&v)2w-Xk1pIY{pR>%acX`y=6e{`rEWDBl)937wgGthp@kCfF|I)!aax z`74xXh4#={SLLrWN$*&yjEA+_ioI(l@zitDwuvZda-qsV9k+p*jd^Tjjnc&P$g&|n za5H!V&I!+VfNbKPmU6JYqdVXm06;3ufo|HEEs1CFOUUfyVfXL<{_j4Hsi{ft4?tmK zE@}JITFy`D20zQYRK1?|s=ZrmTztS&qI9o{uAt)&)|s+?*{ z0O%MnPyzcg&TGS^wy3(zGIPnQ57Ke(0IQ`sh=kbcbyNAK>c^QUeVBdKhG~T4eUh5z zX4vGNarfM_K?kvEsv)GK=HpdwnCCJF&KGoMgMhniF}ShuSvPiW(w#hY&YeGVUK>tR zZbWB342=xv-seVE_PdqKf=W)0(qzs`Q!2V?)%`wq?P$tv**NOnc;l=)aNvY=?MIY= zfV3tXObjXx5G_Ig^-=Fifcl?GX|jYt!wKBZs|;50hvn2}O*EOUKtwq;)!NpEenuIC0Da0nA$R zJ@EkAnJi#4e+qqNp&C{V*oemj8r$|`V`F*_8-00?dJf-1S8X?+f9=p$;@i&hyb?M) zBW#$Md5JARz6RJ#mCDdtmC^nS)f_i6w90L|YMYnPtBR=ZVLFw2m;&nHhxf}eE*!zoGrM`gD^@G6tmO0zP@#DO{P1CK0s zuf3MlDeAJmlV0ZA87Tx;l8pNwv^@x`uOAo7gY%OG9!X1l=dYqJusGgV%?clGR#r!B zGT?!8Dh#Zcb&Wyi_^P@+Py2FP~3e2C-JE=3| z!o-67`$MUuh|IYX-YlVj1LkOh)V?6Im|Ojcw3w!a_AkHu(oaBu6trb%BpzsNm1|{M zt;$o|(-B%vNWBKz^a+_xX7#2g+2_`*zRGP}zfDRdtc`>2`1mo62PyaHBO7J1QY}CT2lbSqRvANw~Dv!V9$&p-DESYd(>i6$yKTee*74t#k)RzW5uK^zxgIq9}bPd|?WrT74V`SObc zo*iBdLH@?KPUex7DZo!d&K#P%f&NbBE%k!7g4EhTb(E*k=Vs-DbOEIXhDqnnJMVDc z{N^|PiL>ai1Jt3#|I^*TJ%Ah#MO)#bEqK7MI4xe{vwYaZnUiNnHEFo@*4re3+@bcj zUj0Qz0A@xi4Pk?B_zv38)8+82u!?ZYEjPIbAAC@N2dQ0J6NKaLgZFppeUQ+HcC5HG zxrT;jJIkBpn>?~lfZt+O>@LCqujh?uw{(eP3e8lG2^qBwv%%W0Bt*z64SuPlPBGnn zhx*p9=-r5TOc{sz3D3DM?MSEo!qN26>#FO_W=%R!iZ`zezG>kDUXkPiiUR zqg@5}=ARDB5QFw|6#xf8_`Vq%`&=#|6*8Y&wIhX54fgrbv_vRhm-0ronLHq+#-IF7 zO&8pOgJ<02iAl9lt(-9_5E}@KA*hX4^|>$ipVcaWHWufwaS#6(hlopQXyQJ1D(+t` z;14{6z|!Soz>iDxNcV=Zu6*LJvcXvs2?+!aGqFGLw%Vvx3pLkBDv#{b@%@Zwq}^NF zsz~U4wE7d`_i3Bg61>ND?3ZAnw>!(-Ft9Q38vqF%O2UJBKrGThKs*x^0L$HX-|fN6 zU;nyGzw_?pmtU6T{wcS5^%@T%(7FH4cfKP%`{yM!%t>Oh-w0YsPy#351a z>x&nw+Fd_8G5yLw)*9+)qtt)uq^aF7$v|3fwD6vduBf{lJ95lVP|uz{BXh8mQne9y z5MYP`dg9?i(zs^LTB+^~dzZPmO?u4l*tkG z3jhd)q#IqmcC()C@W}RYBB52L1d?!F$wb!OyknEwJSuSQ=aX2RV(*D_Z~pPT`*iPV z5jvvDtNgUNc3OGzO81_8KF|bK`NR1+fq#nDUxo1p8|oxxz_G#}IXv!u_2L)qv2R`N zWROP(TKSKpgzwygk8X9pf9a4*_YX=vXj-Z-!PY+^rl)oIl}s~B*{<|KJ-0x6tr(b) z__Fh=Gtex(e_fmkyjH6&)@Ha@Psr?Dt$1U<&gMXjZaTYs7DSyj(yjpZS}Wy18>D;y z1Hc4QdvrDFkOv3*)d>dBgVgYW2OjY6-+AXffrqU7@BjX99hUPw4_uI9u3Wj&{pd$O zcK_!;{*Oy!lQP?PT&6HzmR|n1{RDw@m?-cq>CowQx}zMe)3vhgbeg+~z9@fNO*eHG z2bf2~jbk#)MsR>QYBT%x?Q@^+|I~wLM1ocakf3^-;`#uFzSCMI++ zkK#2+J!UhRG;H21siti9ty>oke*>h`HWCu;0mxUcS?Svnr#bU2?F4_?CC^Cni1#G6;u^G4H7ENf?q>5fW2s5w=_tu}!yHEC>6||K)n=HW; z7+a)Pl#*p1Cw=pZG}@%lMkG85lLmZ()SEjK9HiiykZUy~t5vR-UfS!v{`hrnK(AOS zfU8;*le*3ZxATL8ZXmN-QhrXx%}8xW69_5#`w2h_9R%6&hQP5;O zt(nKBtG235+iC5zTSA1%o0saBr1s>!VzM*zSKcrF)3F?gRdG7DXs(Pf8ZgcVeeOZM zpu-!YI^Zo^wzzdVfC>pC`S62@L@snRfCD;bI{^`ugsV1g5{Q`c8v~KTqu;w>!v?>p z5S?HE$d;?G_6Pe+PEL6n_~;X_TD4MP4|-`L1C*&VTp6d^6B=Fs_yBL_;8X1CyEO;F&a@$=#wsPAoc8PR{h zANU#E{Gg}4lo!j_)En^#skiR@1D2}y)lce`UJ2l#drtj9_q=~#l{TjSP<3obp{@kn zD~bj?;dudR)jfC4-T%-!H?&-2D@#~}!5Yn9ch0yEKRl-ARh%VPp;_Dt&h z?tGWjMm^cR*5W6+y%}wQLUM>1%m54k7GaXYK|3K&vU7jmeI9JQFWugWi3zFS{6d>$ zpLADkzRG7A^_<5ae?li@{!*&|W7;fr%uP)OOC7}9r;UMF2jRJs9py>K+#O}v$()>@ zHh9}E{@Mx>fRu7Zg@tDZVpL>Ir3Hx@U^OMc5==`XF;{)oH`EcE5L+&Z3m1KdAK|#j zFTW=yrqn*Z@OxGWn-S>2+Rlm<%l*C;_O2k+!$AuZYD3UyEPj$<|$fKg;2#gc+d&hAJ;^8mGs}Gb|&BoV9jcLVG`^2gfI)h@gbArlJ%E_ z2h55H@;qqfo!Y4CbiyAn#qWfhmR^6aPMj@d(^?&#bRWET-raNGh*#wyM$NI^U3YDC zFaPoj?H5}sT1A0gkT!AIDu9A6&@q0MK>a*1u*ybLL<-MX3Sh^!QIC$^U9o(nJAZD> z=f&sW#}W823!$;=N)E&l`>rgu3egN=49HyeY;TcV0}wjd3ATEGapR3Qc%aTk*^m#U z4FDWqxD1Sgs z(yQ=Dx+%#XUocq+t6XPfBJ-qH4EAYKeAM5O@dasD~aVAJ9yGsJGPL zX1i!vksh?!1c^Mw?qVDW{i~^3Xf#palEfaMD~J4=&7K9ouQr=*zwRq;`!#pUcd!ob zHl|+4ewrllQ|^&(u6B7v$u@u)@VF%Ae|+P(o1W}fJ?xWIT^rhLY-;!F_q2QHp@%$x`0K6@-HbZymtTIVY)u4kf%T6k zo_O57_`*wGUzyc`FyTp*_4zxUN6=TREa6iv|8B@nr_vY(v({1PC8DbH+{50Fu<3O5 z>eYTFD%AOu2k>jxu5%mKt#`|pFVnR`m(&Y1&Kk{jr%u?#YSx)EXZ+;%*s){&8Q_kI zLMF{Q>EjcJZ+9Nthm`{m05tXL@Ey$L(GFQD@IXlQE+c6l?>Y1b$Lbetl05j81?34x zm{vKys1c;wNO|KI5{}=e?goQ`H6R zQCW*P54eqXfPHYYW&7@7KMX5W0|O%h^wVxohf)=0itep9zjROiV2htz)1)+?cDLL% z?7lo8TlliZQ`Dy8q{cH^MzB5UHWrf;AjV zn!dwScn}c8uKPI9+2Y*p<7Z6q6>@+M7YW<%e)l^M4sN({yO&y`io-xnX9Pg^QU={| zNZkPvfQX!qxqs}j$Gk-8{rA~WJL7)&%U`>C*!9rf3m zwJUuX?ARM!o;CpuDEEFo1V8w#J9U5guq65Y?&{Iaz73r{d)DpUyVrg4$tT{rPC7l} z^GKS+f#e>Vh}$p4Yw%~1&F|1w1Qbw75K!O(6rhTO*;xQRe&mNX%AGiy>5LcAG@4yz z(XS#+EmUK{V%%etn~Eu%8En-2yB#}L(iHt>T4}cFJc$A6;j6u1 zCtvM&)=#8;vQ7QtRdBRo!I&2grVII??a*#dJ3vuELWF- ztsm@~+YeITsAH&?0fb4L$?4s9-=&qNC$y=2wHr{~4fRgoT6Cg9!#clLv0*cyKN(ha z8E*~BY@YQtsTsc&e_E1ORM>dSrrOP$x40XwztR6ba_o?Ts9p*A5H|py6)oZOP}9}8 zNG~)41_nOE&kqtl4(gz_A9?t?*{Z&Uba3zu+5vDJu0?r<&58bX{AV5xBxE9zKGf^W zOL|>U`Km?eALXk{^@lR2@0m@=D$?wr?8HCrR<77AKgstm=pTIrQG9lvC*cNpuUU1} z-F(X$uqgkPYRc_;H|I_rmwo!Y`hK#Jq#=~*tk0MKDIdN7yhAH%6f z1Y6KwCK(=tlLwZmQp`AXsXw6q z@NJqX$$)pY(y(`>AWQ5PtKuxN0`G+E(lBvR@Mi;IwZ9M8ra#aJUC;}tK>~=GKl~W5 z0X!Ur!+Q>>Vguh#e)1Flu7~r%<%okrb8zpy_nyDM@WPAQQ2QM>Iy&k%^A3uKFojiHmtLmINg&ljriY%LM0V%Y34yWt$ z(m2$1R;*Yl)0XS}VON8LLp}~R$KHGIy>3Wt0z33YO=1D`q)!_(GndWGcO&ACwhw!@ zvTQ{BOD_(PTo^Yj@9>j4%ALA}%2lT@=j;Xm06+jqL_t)zwQE-d(5zvAkpQ)qW5-Tu z%+L?$4Z}mz$b~Q7k-pj~JYvkq$%OOC6Ha@+@DHS{T&a}~Cdqin1%CR+w*8^adwK-& z!^9wv0&RiLr48KMRxouY9IN8g$-s7hZk+>-&^iogGXF{gy^vDETeu6~w#J7}kj@cW z0P*Ia%iiIKo^KdjWYs`R{{QhG|KZhbh6cllp@czVhn;)E{rS&-_Nx^yyzqki{`bG{ zZE}+aOOHSL(T~dDp3^jYwAm0xya0RyHtpsOG(j`@f)=BPJN{g;tB(Wlka}kPHOZFo zxW3pg{WVM8sNI+<3j;0n5L1^-Q~~k_4jgd%KHDRm;WIu$Oi}{$35SIXOkM)S*~l8` zPxy%|_4xSl6UtjKLrI=??6}EWl$x5F@p0|gvBRt6e6;Hm59;BENxv^%ze<4S(phYJ zh)UVfpH<2-^cOKOskZ=pKP;6NEV@u9n0N*Wcl-OFRcqL#>i_#}j-7Yz^r>_5(gAOp z=t8qbLtU&&RK^#i)r|oC7>=R-A>lR$k8)D~IV3ZeYt{byR5a{hg@r&sqsrN$Z(B&7I^`2%XQr5+Z(T9|t<8cWxgK7G26V(9t0S3UStW zJ1w&ezBr?qI}UnzXX**~BVET~-3IC9v(G;3&>6OT0*VNC*IjqHJMOqcafEn({_~%E zRWks~luiJ|lE@E#_(PfX3wpuC%gLT}a>NU`52tE&M(1U~p1d1>xWl8^)z1NV$wfVC zbvq$l>LqCd#JN+CKl|)6_s{?Q&;I1(ciwr&pV`2MHh?QuX;@i81t%%>2z}zOpwk}g z$Ac#F+D*tefPL)LqmHv{*Dm)j|MD+>MT~k*8@v7X+kKjFlDbBFFkaNp-PXil?E$*2 zJX@3UVoYT&EMTt%^+af)JNS2%*)zn=x_Jp?88U6QwCTVl}Jj{H?uIo84w*_~7 zcH#`cfhgcJU~in^oi*fWID6l&d$fb3}qw|J~%Q%&OZ;H|3#QXzlgq8lZ>Y z{yH)=A{t8a4dfhWPfzM#H628yraa4r0q^L))qj>jJ^rEXg!lFRrS752U(lEp##DGS z~rqDI1mH- zmaw^biCCkgbFslKn%cz%x?16*-?rj8N;gs=00sBx1<=53AJPs$H{S&C)9)pj&p-dX zzuP2+I0(lfR=3@Do0mp1Q6L;@4TR(O%9ShKx4-?km(XML9^1az+>~@kgRXL?@CSOK z#md^srTVw|$M=PCAlg=_f30xnw38Nk%dAB4Og%q$?wqfu{097U8Q5md8|r2NC%gl^ zqpp@M>FBd!g=MI}|NFo9Co&TcX(7F*KAkyp+P5M6i3@N~n+b7s*Fa7laOA@#XRRo^ zMW04VdP_gUCT|?|$LdTcXA%Z2Q*s?%;4+Ds)~PinK8t2*r0? z&<+0LVx#zq6)QYYzwt&a;Gk!Z#2#>u%1v0Iviw_}XGM%Q#qVyZV^&_!Yrx*~f{q|| zb#VYbhC|Uz8qEZ%{rzGkQ;ZQM$vFMKcmshvcFDd?2Z(K^6T$ zZ$V`#hag6)X~hCSS^PphCy8(-B<}00K1@U=BxSPN@L+uaNryHc1O}m>X#+uVl67++ z2KIHcu)Pt`Nz`(_^Pt0-XMpaMLE8X{<%2tZfEoY~jywSBanNl5pWlSOL&lGI=0u zCphwtGahvUO^b;J<7@QN$(%+n2n}p+)0Ogkta*j^3J{j;{joC z_O2PUEVVe{DS+5`YZJ(F{c18pNZZQOKq++qzi_8r&{o;=5tTrOi5^y+QYmcJ^G#m$ zHduN3=;K|oP0e?lWzplFe)>tbefzbNN2e(>iE+d9GIG#@O7ldtCo9l;1qQqaI(> zHDL2>qSW?iyH*cTvk9Bl8E3;-0*%OtI3Fb(_;nfdU6lC7yv%C<8U2Q+q@xkNVZ60* zsFF$y_A9*T{HGY$cYYbwMIjB#7r*$0x0Zw24L}A-%1?gs|483>c^P20f-e9O@?d2WeYU|ON{8jw zz-aVc{Cs5`FrM32wc3ik>%=?tADXQWS)D*)k2M|Y4|!a*YL)x?*T3%m;UE6N?>#Y< zGpt1Y@sDqmvqoIB7utlyResr_59E)0Lc2NRhy9N43*Z2!8mn*OQZ@5;%&fA)Q>$NE zKnit#lFM>1nGR{wA#Bi?Och*Tzb3)D&(2zXD8Za2NbRk^pdE5h72}Q9r*}EgAsv4W zxnY7K;f>~>Gt<;l)Jwz3%yl!M&IqQ}&dZJ+y;9k;GB5kvLu@g}IMMO<7}$4w5!Fwi z>Frj}!fC+mcT~aXb!8Nh2RcqVSUOd#=a66QfdA{i{;PZCl~>$PfBI7o;tjxa2MiDn zQZa<0e2-N#7_*{^E->5qSQ2M-)6*Ec4; z@SwV{sI*c4c}M-Rb_3nfvg{}#JD!-@Pyl`+6}S4p@9CK-@mavx1LgK+Y+_6kSJ1N@ zs{gCksGhqiZK$1An`R}acE0=v4fvB3TA$TqC#|%s59vv1^(-;rmaPnj9@5sdpdgD? z&YeFu>1mo(f5W13yWQmExJY0lZ=gTqA*?=hPaoKBE_Pn}rETM#M_5cz<2b;87nNo; zF6Q>fWFW*kRV4BNeSV|HvS-g8KPUl^O%iFk%uvsO_3X1hch5ZYj9asMy?}kMSI04l zCeoE=I|C!6!?QW^X28ByCma3FzKQQw&VeW&X(!#(R*ZJ)vDFdosF#h8Pqkys9&*-hkWxu;LYq}(pB;0O zbf>0r1JLL4UF;>)bS|?bX*+5*r3t0ZT9MTt=cWaeC*AsuYyD({sIbJ01)s4o)R>0d zw1i4Y36Z=d<;zT~8Nnu}RF+uiAro4mN$4u`t7d}Doha2zGWNV;4#dFzidoiOA27%> z=oz>-$qTtKP|#U9vW`O?&1JZZYUZ_0y7Xe8 zenj~QxV5&zyY{>4`c_R5b)B}1E-xz&VZT6+tlKa^=dwDK>cfxS$Gi7>0H4=c4TQm@ zE2qygfhE5<+6bT?uwtj!Dw661JMOo&70NDJWYuNcafEjSLDcd2K`v5n+6Sh9vAj+l zIe-3q0E6h3G+82kDHa_)JmE%1brP{TdwfmV}v*5EwE(Ot-a7}#IPlSS!cgCB#oxy}GCM$N+RSOc*j{)FMOFwLfE zDaCI*wL5&Ko>2DGD=VK)<%!h`>I`|XI&UjY{H9KkCnm98Z9$S*-gC&6wH4meW&rur z{cJW&mODNFc7YL)6Ufo1`IFF^-j3%x>ef-sQZ7=aA!20)K3d+Hk}LvyWJ zKjem&D;+s7GpT*{>6kaeS&*sA-rhb*?PbYI#vIz|&YaOvy}lenyU|~t7igNl{g9iv zb%gM->l_X=rgnEuequ^$aDV~NzzU7E(+BGsS(w+$bcX>XJac*{V20m8f`{ZjNFw-+ z0|?kNUkH90lRqey6w=Ip6b|4IF8ubY}kxTA*y4Q9`N!$#@auU)COe2LX2)N<-{3AH6a zRG9n(J@w(?L3hoy>%s)06u-75xFd&85E2%8M_=D=cUqIQq6pF=UYG-wKz_UFiqo%; z1MRO__0b=HeHk1uu*iUIz>xc583f6P0d(~08H51&j5lLFmD5u=@P>m01kZN zJ1)L!wu_d5l?k*(%c|KlEcN)U47gM7#{X{M3w4Hzx(n?%%LiZ|Kg%Ea0_@Wkn8;4b zf)tz0S@nvBq3&5c{-MMFKreZV=GF4k;iPvwd8%6Fx{)Zg4JLzZp6vu4r=>>u$tTAo zywT)V(t2txLi!y$mY0C4JT8#V*AM8e;Gz>?tAi_6E^|ySbhL_hG|S`1IrK2Aem#JH z6ChbU?YfVRjrq1iS#pK`BoNMX?7EW!F|hB>a=UD*=~U3?qa)^?la4L6uEP=6CDFk= zv9+e-rW2`k%|ld`H=SvePC8nC2M|*MJq-T5tM05&IRF6JHwNqo7wxnw$OJvwM<$|WVO#LDR_!549C5v~=Uk7^kNQ(RX^XhaDNs&Q>U2St z&}P#vtxTk)LX%8$pl=+ZWn@LT!BVS_%bUW7A8sE;Y9L*10^w5nYuIpIczPr3W= zQ^aaMI$FXzEdsl@-#hK{g{ze95xwZuTtnlr3x_U-Pz(E8OwI(pV~TRN&!vjJ{_^~l zpGGlBV(Q5Ork=}7oVWbpL%_7GMPaEX6N?oKITw&NnvVI-6@CB-f`Dj z*^<{Ds$TY!Xwq6tYIQ0nz}_e0IBMTIp|+T0AC=mc4mFO zV|5He3`N<`pPU|deOetZ$_kE4O}krf+2l9yYEewz3tlUpPd=HEv_2SepxzR1CY{lQ zAj&_VRD=F7DVK|=8U^7ME74))x|qwl(`QcjRcZ1DUH+3&`=Je)Fu=cv|8x}xtOa)! z(J`@?&jC7QYot7zKB_h3%a17z*$fU)HdYqa>D!)wW~3L#c_9a?fgt5TTe0@SZyV%z z=CU?*VQjI_m2m)YGe5wA@76}(JI*G<^kr5~_Ra^;pXxF-|M*_bfhyjY)mAFdAf+-0 zn`b2)DoUM17IKapJs?#VZN}Cr4=$h&z6C%6+~M z;7!>JRIB}J3yFK|8{1s2aL%uQrc(oMsCSvm&uCSbL#^0fl~8`P(t!LNI4qgHvLF*S zNr82Nd_i7Gxh41R70}fR7vW~K%A3_HhD&7J$l#zr|AZ{boOj!AT;aA{qulBhTm{^p z)@s6@j}N0%A9puwhn29V8rY7OC;bqf%VAUACBozDg}{U{X8oiNlhKn z66R=`A+0?Djd3ckh;%;0X%i|0ds4f}DX&tonbm}b^2Ge+fx~-!P-{2bX*c9EZa+V3AG=X%~LxqR-|R-&?~0>resplncMD+=3K_fh%^+BO^s8D|X$}+6UMs5RRbl{8!#LH%D z!vY%5qva8Is10N9WkqCVVE5=pv=zWT7tgr3e4-p`&9m{mR(V7zurjoJ^j-XXxf}@K zJR#5s->u&F%Iqb&>ND91cl6ko?!@Usim)UcGJwh5KhFmW=kvc@+UADK3 zL?_}V+^LhZ?)~?tooqx1Op6pQk+f;6b5A_E(QVu$q@OsU_b0T0R1$o^eO@X&I?OOB zskgAbz5^WVS>Li@wwRR+KAV#+ecBE5OX!l2>P_;T8yJ{&x8JqJ-F5G1p8(2*)L2ML+u`!k&rHSNTa5dD5gJ znbh6@?h144*nXWly?;)!)@Hy7cFhS8|L7VHP$Ocuh&e!GwL#GuF4+Z0V&=~Ls_%=K zB^{MD%7(JQv?g~tRGe97=_q0sAu;gZ+DEPIQ5=+osjm@+wqot2);FuAzx2fPz zCZ(oQGqFpRYt4_Aq-OxJWvMzAP`nFw4-b7Cu)ayaQ99z;{FwW6-_9WKR(tRu*ni7+ z7Dp+nnl}Man-tW1e|esnL0P!TPr8ZeNm+T)PTBl``{J|nZtrg8NLiydotZ(X<=o(~ za}Pc`;=cC47M)J3cAq@s`ulX4A=Z3mrv%KW6<+%9lIG)=)Rj`+(y5{({j~XUrFBwL z`e}FbZR_1r-`gN*JtmR?&br8wq8gX#%^%-5k|TABw)S{#~?vMca){=pr%3k6prnMk#r9Np_bW znFc^;uryR_xcCEB1_nZBfPd^-&jI*uV1@EAd;9qDY~|N_%9cioR_|-^89z*(n(7Dl zs0mcQt@Yi~;9P5R8Rap&wz8nDSlL(^MkzACxO}2qxy)w)bfonG7PAQy@GQ_Pbrr-X`S^5iu)};a^9a;mIEc-gca#at_uoIL z-<#Y`w@Ot<8(*{1jp=3fA?UvCnxwmW%hm3P799Ti$r*PpIWCJjoXV`@YrW~uQeH~! z8#A6gx`sx2+|{F-+_r0b-N2wG{3RTX1s-hH^OMc8zyIAqnFv*YVn+L8u|lJMLwfZH zZc>WVo6Ia^ReyT~`s-teZC(}yK5x~NrG(Ue3Q9Mf>~jTK=1Ive=d30!M~{4=&A?&v zbF_^aHMFnl{?6XT_s-`)4D36%(junU>l`9jk@TMjS zY%{HX!`sVuoWFoWr6!?`sZ2<)&XXt(xQ})oc4K49-B)iPa09~v_u4qBeZPKkLb97i zom)S;LMzw0q%tq{c{e^*&^NO8u6CTs$m-3oPBWLJpG#IP{kN#b6HS?SfO_HTz1nv0 z-g}4K)I?fR{b9-f0o$TW5`W@Tb=Ks;tmAOPvzQ>>*5fYqHRVA2q3!f3^ZERYJ3n^Z z?fYz(l9hc>IcqD{maNZ;#~{z1uKW`N`>rgu#u065AT(-#CXLw|dMq)npU?2Jy2CV} z0`KW?0WTJge%|kxzMzi!gufpURCps zyqiDIgrluc2FBxWsDM~s{NGqp6ApoAv4Rjj>8^OQczr>5vq{BN+7L-g9fzy$`s}achhZ~ z-S+D>QG`APl_`4f$dcq*{$in_xQ@-GLq5L*u-JWu^jlTc`N2bT-JTqDcB<7p zivH%=+6p{}_mlyC=HJ=5>o)4>e}Dv0SWxMckdB))Ub{kN*=5@8{`g&Oradp!99ejm z)I6w!gvr_kxd+ta%HX~dcX)B-f3YkRtjmPB!%Blz%Cu@Qt5ar^4mYoKY=BT*;sdFBEPhh7`H{nW&F)0$tpDM|U?`jhnO|8UeD zJ)D&-`{k1Shp}`(;GReU_0fLa=h*W>V?b$=bmh5@ei5i+lHex_b6&xduu2T^#aZ=T zvbq1^?zf~`HKEiiD__yi;^*$?KrFHE{xYm92MmxV4MQS^ngNbMHI|6g#ajPy6o42Y zF@6K=jmP#5z8j#aKlM0P+)=6HvT`q{hqejx{}?nmF4AML|d z72$pCTFZe@mjzHk%#!Q_?EN!vUS~n0w**Pu==;Ba+^)b(=PcD&cQ)b0K)i z*XLJx5y=33nZcL(k&_zINq6ADK{qqGS$%j~cHuM1q0&rY@1B)d@ggFqu`~eMMe!)5 zQ*ax@3#JMouaz_^Pple*RW7NtrDohA*{(l)-^!1B zwEXyu>y-&Sd#)}k^KS>;-IAv9$au#cKl4XYZ*2v?ctx?nC0n+FWAS>Kvi8Qse5R%sPx7YfNKKk5GVtVJ_;oMJRlzTpm%OsA(1Ql zoAkt~kM-?Q^7nFnB$!h2y?q02Mq^uXTJrnUux!~6x)Ud-+=)|%J$dWa47n96M%=O$ zQpXtxSD#L-#W7ErmKwS&VY>12&Yd`36sSL^eNi)_p8jBy)Q^^H(vWg9xk;Copr)q} z!5C^|Qge}Rd$PQt*hi^9q2DN=v*ej#{tLXrOCJy5p13Vi1N-5gNJ-tZFy%hl^^Wo- zl_7=GPK26Mj|EZ^f7U@9h=F|v6-GNqu>lqEi3HgOPe2UM_P!moEw(h_rAZ$F_57yu zH)p)|1E(LT>`i=c7YCwkfM*<&;7VITY9H)A^NupK^0V^9KX&tTz<3~rMJF{iC5TrQqVz1du2NDPHm#yC`ouxXgVRq^Spp#NQb?139s^D8Mc$JL*Wur1GhF&|fdgjO5Jpj1Qmb@9}_MLViv7 zb!sguOeM9Oa3@Ne%qZh*LRLJ@bhDahacXc%8+cEgIO0CuyHj}#s)TX>)J)E|H|`kN zx0nBIPdz%A@(kbvsL(Nm&aLevb~OR;6n+|SP5NkjpVg)+1B_(UKq1cno9H|IV%HuH zP+nX(1C+FtL}JFb70NhTRu;BB)OJ^@#;a)EXWt2c-X_4t+h{p-S1vo8S~k$)OyXVo z9m)nEkLg{(P=Km$215H@u{-O|oIUAw?b_*9uh^!>A>9_mVQnNtTKeljt^wOQZx;L` zdU|WI1e%MQF!)sTn-v61Op2iLN_1W#c=D3z8IYd64ztS9N2jG)xUI)`T##EP?|XbXm8$9>SGFvSxe?FSn4V0)K~9j1?I)uVv;>= zN>?T^>vN(Bc|)n(Y(iskLUUR+_-C{~<)e>x>QJhK(ygBsJ19gxjNM}7Ky#;yi;-iC zEKfF=+8rrF6nrkS?6y2R42;HGr1d6!G(Q6>(Qv%Og+aCDB*zI>alk-3gCu2QzpXsI zWKQ2$ncC-Z`57nXzejl#<)5vJ1pVNO3XV;7DTCNGp92BRhIA^XB?V&D4nkYdM%4V2 z+x^KdS%MiC_$^s2Qt?#2ZDv^!cZi>P2B6-%63DkbW7I8H5$J!VKO?Z)EA<%xY=PTE zS{8I(!wUaay>|IDsiN%pf+!I@RU$+YE> zx*8@nMwh1t8<||?4YMHrpo;0=H{ee=dmtJS6S8nkOpLj`pMI?TYsas66btR5d|G_Z zvBZAymFX4c2(VK5gg%SqQv>(I!&*J${mlo-a&z8nT$#4 zA)6iAmQ1jFQwD90qH zuUoSM@1-Ul=878EiWLiS{v+P|&AA~8G7hc}P8)@72oqmefekK(7;MIuUX~>F z^-AlNv?Tw9e9HCd)ZKheHu7^?dFWLhwGxqH#X{-!B(m<~oxgEke)bpF-^=N`vMzC^+ET*`mlvoQVZFt{ zR2is;U+^#*cB%7ivE<)?Cn_TVQp%cg=c2r=-9+{WeYR9SbK zYXZiq1QTJDgfe|hD8d+ofR0JmvEv8bCwo2;kY|z;cplCgh{x}``QM=t#K68o3#Qd% zRS&!dPyzOI8URxqgKc%#h0#g})BPQLlo!=N4j#fgB=u2Xzc7BqUv(k}Y_dlAQr6a1 zqV>Y)wy<`u6~@AL&;8=<*z#z3wtF;xgsJ8q?`wsPeiuKtp94}{5vb3)bZ^!jJp7S+ z_x;y{y>zL$XnN~)@=c2FCG>uRr`5``o_YK8(A5;^ATBmGr+Sz~~+Z@T?oeyA0bNrC&)VThVwC8`zjyP6R(@lg)Mz&^^2CHg$y0E$0SG{6b~pJ#wQ z`gt}OFHx42vyH?GXHt5b_?Yw&P|vfyH=t9FAb#j-4p`fvTx}vZIXUSkbG6Ev@X@QQ zGk+PxNAqgDihc%Qs|6bNt_DlUd ztoQ~Bff*I3;qfFo@CgpIid}sikh+stnUZNyCQD3^lN_z9dpa}g4j=v0?fl?1g^`I% z%E$}Tw2?R|;NSgnwfb1Mh`+A1wnd!DIBWBBAUg2Q4HYDD0M)28jb-u}q*gc;1s?zs ze%oXSwE{MinaMZa+f|7ne(H7(SRJ6P&^DL^PfyFPwQR7PvvTK-vvz0i7wbKm&uSi! zXWB~O*RDn*=1x$Kd(Ikg`(5~3uErBcYg1VpZ;8%dv!8yX|g5JoQgy0 zfVR=N!}A!EcjX+2f&G>9Y*Bs@9Y_s)kWqUEu$W{GzzWzmY4xIH$Yo{)O>+E$ljbwOlWy|+9YaEB)b>P@HK z_`y4P8uu>?VtGqH!cIIZxTzGIPA8>?GcMDYe{wr_zTr|*&%tiHx7LDgeM!H5F{og+ zl*t!OOe!@3_i8e(M^gA=E-yR%lHm8|+=si~R5|=XI{30%pVy{YO`2y50`yXmDipPk zrJ^Hs(G=pB-N%90Do*#6SwkuIjXk0sV1q070QOlL$1FhD<(pzd+CC62vlK?lsJ|v)?b>~>UVCSchD7Ovp<*9>9@TFcj(A2_r{wqy0OV)Zg^NL ziNf(k4%k9k@71Ch!x2iw5U~C-=)4%>meqM>(o%||gK9Kk8&pkt#yi5|@B_dixnJrI z&}RHVLd(Pl-p$9?rOvO#mVdyhl{MuaEqk76BY;<%5K~vIO>tlBE}B=K;TODsC-A14 zU(w%$ja_GRfC+0pUsRb=mlLj6797)3`#5!CpVUBpr?!FJbj)N{*=+X`{1{Z$Te|c; zvr_kD9Lme2^3Xt9Z7itZ96r2Tpg!&W`}zi5E~`~A+1OXNB%xDDYF{q_@%J6cfw*OL zWU;i4C<7M;+DVzg)m+8j?A?dCAcJnWa{lB^PO1$cH+;`Z0GGudjn{w>cY9w+r;@%6 z@XQ9tC8tmr7x?LM znM{BAq*}OQVU0ulwmNBddspjT{e7)4_4r*04N=-HP2&M=0bu~=IoRZv{sL!tAgyS6 z_N~Pg-#d>3ob1YBPpI2SAx$bDI-p9HR|>jxHDVHh=SRyf&U3~gR z`b)aTlB}rnGS(p!(Qd4r&>m#8%_-GuBe2%7X@kY~(*7c~rg|#+9-T@_n2ceA+zE+;> z+xXu397seDZYr5CP6;#?WPt@0oOiW(bH(!2?xySS75MM>;BqRPcLM{10;BaEPSyF` zsh>jH7vm{yhYK^7jI))tqsf%^IpCkmopYb=d)K}3#tTx*Ij_U0!hvs2w(gVV1IQSY zN-KrsJrDKM8OP9B9EgE^XO%}6P%~G3fDVSi+OA9{0Q_V!n8dUUF@Q%w0v#6L;#WPm z!D2*(_#br3b5lI1JK# zzW!M~gL>)=VR6yA8GW{Q&8}b2b+I&P14c`fKIrE=r1YV^R7_b$^Xfm2|8y+}B=;5V zs;mCMDY8NT$M#GKdj#%}pZL_h_0~&n#fnw#s*N{Ea-4O2sXjM8KIZ!RdLp4{XwN*cF}42-Mq{q<#exqm-2g z`Us%rj^`JnBYxLC9EgE^_movfQp(_M13KW|fNyVapO;9|8S#ETaA4n(x#}<%`>s*U zu=GjW(lsG3t&r?}4-ruv(O{Hm1*$~}f(Rm_3n_ZB@y9b~&N=(+z4qE`b%F3L)@{kR zCSe3OeQ|_J4=#N_^6rtjXL-lF7(tVv{xkN1Bg0MiT@Xo^$MgMozgze>Cl}MC5fzDI zp`>Jye^sTJ4iz!W{;%_$rN{ok2#%s`!mvQCaCp*&-9NPO&2%Rc#31O8C%vV8rxl=^3$|ez*cU;7 ztd>8!VJ;UWlg>j*hm_cO@v}P9Vjbzds-dcvrN7S!lE*Y90~R~)+8M95$bl!kog+{7 z8}U^0Qhp3Y2UDmIVmn54_1s3=W?5v@?#)%`K7jo0HM#buS05)I!U@t4&u@%-yw-Bk z4P26KnSnICIj@$o9w+ufVYl=VJE6VT1P$}Tn!{waG|FJ|q{yImy z63>4MG_qH~w;du_{AR-PrtZ%YM~B3DmJNDFLwk3CoZ=Dw^4ZJyvIpIqKZ0`0=^TtS zNiO8MUgnNJRvY(qDi2a7jmLDcPX*6PmR~wzjzSy>86gyZoXsjXV}RZSc*F07XD$j0 zdyBulXW>ObHPUXG`9U`sv(KY9w@!}j&Whc6Ew;^ zkNf=gla~BSy^810FXQskp5ay1e3Gg-z(4sS+5}xuIG}g@5#5vJg3J;F7o7rGQoLM50yJqcIb|jypN!ks#mB?g6^5m%9N(yegZdugU~f?<9pkAN-~X2Q z@#B72>I-Av+B3vla$tJ>d_0kQt>oUdIDN ziK!hv!~}WUUtM6|h3EastL;Q)`rTieL|hhNQ4}-h6nxB1b=n$VP=7ODyU7qbjC5<(e{in({Xj_&dj8Ng} zq!0XXRN;OMf{_yZ2Al1URh-tUu|a&@dF{vUZ{USUrqgtuvw1T}gtVHbQG|yIUyp{s zOm4aCnY9(u1nj9NtUJJDHK;aC`{d9G4(s%SO~d0At52>|<>p$TPE})H2lS$MZl-#{ zx2WhJF{_?}cwZD6VxHyfYgG>R^D_rHIM*vB$*3GbEv5*hwpV=aAKi!gXpZf@ADxA` z-@@I^KAPABbdK--{NetYS9B(oqL9J#%t(ShgK2+@286<>%4@mJNVawR6|V(OxeB&CQ#w)$bBp=u8&Y> zY-}x7`^ic!!KpWKLuJ?4U*1qtnaRt)Daf9!;~Z@9i9WsV`oAl6mSQ)z9jQS?kgtMGY#C2hOwrY=Rr@Uer|~t-DQoOr zfAgJU+sjKK7xPszPA?w3wqWdOy?yb^h5eHY5PS3>NxpN?DhwZhrE4^57D%q-Z-~3r zn)J+dz0fi8!ko%|%}p5Nx02h^s?^#6)xG$08`fXI>t6b$`DbPBVhg(OqJhYP2 z9{AG(QS$B>bu6i;vuSCt|9U1CJ1t7#UGfEsk#ie_;=(ER!=km2^q8L?Yq9n?e}+2X ziTm^H^GmEi`OTWko29Gb7}aELQ2jzaAw*ay>%$hgehyTa%_T19alOk-h)<%X!+zVs zbT&sKpsy2IX3{FOdgs{cIQvlmX#o4LjG5wmY}%#kHs!o^2qeOxa>t0%U;PH;Gf970 z{MG&a!}1V%Oke51O?b$?CUf-B>O?(%OSFb>>~~caF%3Z?gA5i6ruin;F^VA^qd`E0lJju2ad8*vhsn&mcYDIOy+C+cN+UBbkdKYd3Om|42i z;d(ex>`mO=FR05pqP+fW`{(EJDy`7B#^@0`PWC#{MOR;41hN~8U7RPxaFji9UG?HNFKM8`zUv3r^R1^1ES+s@p$ryE;j*Q-60!e5jly*qKP@chPmR zl|*81neR8p@K%M1ti)k zK~k1sLK**MdAZ$SwA+E>>ks2rZRvB+IeH0>v;O+1-Alk7swerxZqvt{sr$Uy(5Yef zPgdN`?fb#|t^y$_A(v#jm&0HUjBc=O4tT@sV#GyG+FTm_0vr&3zj^o^$x#J#?=e@=H^%RC%}-^OF+l zf~B%#dX=rAG+2iD@*dj&8a}5}N`JqX3-Y~eC|}B5)Rf%7lXZ#5#g33Zvk9PpQ5blzL% zkbZ^hPC0hNldHgId2{0>{;wYxuYB>vSrh#Ii79xKsY04c@0SgriVHth{Z_|80jN@s zv6&NPBS&}3SY~3d+P9Cqe3emao3ENGmcLe-H~jK6P@ON-G-WepIDhkXBW%58iHr4^ zR%E2_(Y`o$=1H$r+}0o;-UDqreF@t%E@tRAwNE_6Q)*#@K;Yx2_h#RxMc-m^v5|)w zK#Sr6bo6iO@w134tfWQ=M=xqj2yI7>$d`aM?;i4k@Nw#-Fo73}ZQD#LZ*%=9wbW>KgS+eG^WWxijszAPDcoFnQQ|fA-vxI1y#7$VyDmKI z2|0n^`Mt&t_QmlDlsitK*rJ4f+^APke{*?pqzT=oCZ<1JY^qU_x?9f$IWCrZY+gzw zX-M8wO$#`t`Y$JGzUX-47Z!q_mDAZ8QYAzYDn1txqQBUw{1pjQQPFQpICbAv0Dl)Cy47%;jyfLe8+bw@1vDfROl3G-uO|HKM=deF4fDy^M zwUM2O7YSSj#Q7{23+2*gi^^N$K7~q z_K!y>=#G$y3d!U3qTTj++|bOfB!K++6&33tUq3ruiJ1;b-Bp)ZTh}!uzOpt}m~?&u zS^6)vX%lbRzY-J>nj5+z$KdV)hBe-k0rQpS_vf42glJz8p>Yxl%&h^d5duk9(!f~W z;W{R~4{q)6>nj}R)o378)ceH)xwjhnjmHZf3;jaHBb@CbIie^-vRmT`>H8%8ZuR~5defW`gIQ8F{7tc z>6OKr!3FDz;9eXs!+(BcF8&c=Cd~g8z)59e5<(@&2b|G)s{T zSJY4?Ul?uP5PE;cZ(aHvGfJh_?Is-&5k=AI(hk_{^{p2 z%zqkhOJcQeKquYa0p7ljy_(R{nA+l9<2%Og{f_QQ@_%~{YJ8aC55IvEi!Va z6fZHq(H=uK$jf|r`p>RKGtKxj3@A@BceXCiX8iG$I@?2C>8w+$^>Afh!dZIJc#;JvQ-5iOFQ~+eGh#8W3!ae zL7_33A_!ZO-|*V2t?bISnhv=NyxRKeYP1kh%7I2y5vMgt1=Ie~Q6aKE1GqhtHWke! zRk;~$H}WrL7&L@04(Ks=k+vsEZXHz%on?BxSDo4u_w)*LQvO)d&NPhtc`yT#Z3{vt zMEn09MD$W$8{o+IS|x@AtFX?-+lN%`UeXK2+pabGRewEB!Q?-4BP?gZMx1mx4#a{2 zPGA=ogx)0$c=kFyeZF|u`7Ov1BCJxL^bIAmLTP+^Z+cCDwh;z{Ln$bwol ze&ZVkvZ83%D5hoZ6Y#f&g1ILdoi43?rp2WjwM4_X##XuwDYWicvx3$*TX|jeCi>Ss zAjhk4(8G^!@cwU_(G#_5of7R@l^d0BI9NHahF_a-=6rD5F84K1%@LF~J>{O@a+Yy? zczGe_Ez!hc~3EQUIj z4r@3)sqG_zfC#&HIv`u^Vjt5oWmhGAu#m_*|E){yTtwb$L^=1@Imsg;uO@I6AC)hmm z7~t(OJDr%FWo&qDarxELbdcz=`#Mr&oebX`_%~V_<9`AQdLPv!u)gty4qZ0=V!CAK zO)>G!m?3&*Y8>h%MuIV6y;<8e&9sW#*s^V#?9)*VK>P%MF6CUDQbk~!s2{bE%!T2N=5>!V(u!@wzY zrg3gOPB<9v0y)m@fX-qX?Uus@;A0#I&}RWB%U~VHz2+Ycv_`MK{;qSV=@%|kfZ|h- zog)!y`nd=3xF+A`1LTe~M7X`vaW(1uySLr#`BhD!IL9*s&-=mB-K6;D^dbM>3URQs z;(`V%e`I>6G1_&@>!s?*6sX;+!&WDRUkk zv>PmMu+W=MGhC;@>Qt6z!P3P4o!F;JFN0yBzDr*kcFdMWB7Axp-<7I-Htw=`+&fF6 z6gp-qzD4~;Yq{UBR`Wd1{)Df_q!jV^4j#0ua2?o1$7**XTJxRoR{2nyDu}O;mg6uc&;6-gefMMbk{}jVgNitT_ z@o7eIHqjrq_p%HwubI0yBv<((B-cXql_dh!OtElsN#JlfYx8``zTgu&}Q zR_+2~`im|2EvyBBqkCscP22Il%0w(()#{RQ_F-W@T}t>ku^d=RO2-i=Dp15X0Ff*2 z%1W*k-8p6)jfR1ExgG2SqC95xq^nEvKxr#t4HeXCJz+4K0SWlG-~EA%{C^^(3(rt$j$wm@;y*zI`XRWoRq!L5{j+ znN1=Tiwmmp@0N;H_`d?~{|!U0-EsD3Dh4`aCWAJgVDhK*Lnd3f@H@!K*my`^sl9mi zUiy<_!i%;(-Q_~ghai8vZw4$+abn+M4N6+(Vmc-aicRKK)z{Q;LT8KWBDS>X0*3L3 z$am>0^VG7LYjFSP_jzrEvoYlFaTYTb$BRY!G7`Tyj3oF3Pt_sT?Y!_>dhIt;_u&he z7u%&|O9@E}Wndw$^wyB7e%{fBn0y}ZKa#Wkm-JaJ&;MJ0cby!AnrkdAa=?4+Qm~~6 zw4ro7%g8(bq^MDTWYAk#MJYn?DxMPhb3CDv=i^fxR_T1>V+r`@#K)eV4rMPF?kvaz zRXpGp8z%=c&p4n1T9&{}1M1o5Rh?Wj09a0Zwtp4-e6Vqt)*{*&kBck{)2XWwCi(9b zUi0}c)i}GZ%$2^{dNt4=O;wh6zmO;3hM1`h6hIrD0n+#Kq+R-|b4~GEv}v)VfDd;b zLvPaNM`zq25@~2>C+>HzZ1<@+^php8dq{?*u4*p0Ozzum$61L}&%5VG@<92@{~KE- z(4TeAk$D9Gnx5!95}2!`%~)1e;KS|-zrnJA{cJH>?@ZEQba;p63(H4xomaDefcsi` z_4Wo$4k}km?vOvFv?w1nBH_Y-DmE(H&8s159(_ek?=gY7Vro9?d7FiLD?7Aa>@2Pj z&ziDGvPz&Jjq4HX5vz}0@f%vDxof%Xm-5^nx&`)+kB)MrnZGOi18=^@w8R&&eP>1e zJ&mnY(|>~;KFSB-2i$B>f!~JQw+%KmC8a?DhU3gShte4W`$JoF3(O4BhP#^x1<@0W zzV_FJ-v;!pUH+_E0+5Fb@Zm~Mz6_)D;Sm@E9=X8L{JV@2!>LV~2m}oFQLnPLniH-6 z?Y8Z#>b^6o5}n4b)_!%UhJ6oPZqRnFaqipVxJsMkvg@ z5n-+!P80FD9yL(W07q<9NBG%OpFP!}_`j>lDzmmXTC4HJ&QLOtbnVG_bY6FKE1Exm zb|8}&%MlYY@|^i*2cIfIKHq%;@f-{Jzm}pmDzq*mTg}Dq^|Q0@qxu6-q2y5af8|GV33m6_FfjD;>*@~ z`2FXvc9o2gcS^V^icu-K;>jv`Ou0czI}Zul!ddgv9jmr?(sVSxreXDg_ibhfv=>L# zEaYuc+aBMbm=zL<)HMRl2@RSB9R~d1$AQVBt~IEq2O|7m6C|UB__~b60?|O8#(!EV zc@KMW4}&#+;AXBfuKziVYx!jOG50cZ6a)jZ7+BpSZ3>IdS0op+%0yzj>t6K&ox2hz zAM@@HZDR6IpAT?subDb$&I&-4)iqBfk67P+>vBk1Q20|t%l*#Tg_M^ikvm<*Cz?O{ zh}N;G#M>_dzkRNga$$kHBp9F-HxP_Ghe=FWCYtV@t?oD^s zCrYeHAM?4M{1NxNI?}Lm6miBeP=piV{sz|q!81nh8|@UMgW2kr?CYb{v~cf#fRa`A z4o+00?%|ryXs#|6Jvud_uV`JWW*e%}8asduEXr#jTe3)X&d)(;Y_=YR*azkqW!CL! zt$qO{FVC?pK4`-i?6Eift8{@h6TU%i)K}RT+v0!5A)%O!u9=tKxI~H%GjkVTRlb=t zkP2QQ{m|J6I>*9cm1E#XCNaL4W0Ma``(sbd*rsujb5R%rX*%gF{p{fur}*4_YDQpe z5QED<60-md*4$0+vCO+@upUz@%kioRQ2L;f6Yn^c^z1KIT~Kxr=F$G)D}|PZ(ylT5 zakO`<<5tB~Jmg#M9n%2Cnd)l{^TA{FK#Fph*U9yjIf$-2lfl|kKAlCgjZtK25aZ%i7 zK>$R|xnSE28N49G6^DXV^6qJZGQ8r$>)pG~r-s-dvyI~9imOEu#RZ(ly?8XB6lwaH z|2fYLF1Gl6N#_%%QPY?BdscBf8q-XTD(P`BL7u|34lx8K*QD7T* zLiL>SV*GK-rWYTD+|JeEf`z>%H%C!bG-umjBp)Jj=k5U=3AAhcCzUTeGL9}h>}ORh zTc#%yMFrX~k&8|$RT9CrS69TPj*Cs`s@8``;(9G^>cS3ss8kuHYvQ?`0>3{2<`LsR z!1Es7RqHptCmuGejtOqQ-4M_*Ng0=V^uLT~r~)RqLQB=*Y*IHWzG$iX>cEXsyKWaK zF)gniQ%O%~*+WbJk7@9wiHkXg>q+OT3Z&X!koddH-SJfipOG)TWPikpkHlOW z(T?`X`tBZaeDZK{+Dr2JqJ?G+)_+a)KN%DEFKJSg+1rh+YK9=e*zREWIflZ?aDTbc zvY+xxt^;C+Vsn$6g>}rG_MDUBGW!iX_1S@ER6w2_-~Dn$dv`p)->4L%k&ZT>l06} z^fLOY4gXQ3Gyj@mhh>l35{OoB8yYpQouPTuaKMQt2F)xp&7duvtH-uZ@6oqT-RFDT zX~_0}MP7oPhM>i}6a;fK(?Y}+^W5MTV3#A&8dx{V>UBrIQ#ws+TmF8@27s2;=A4fuZ#2X>1*(d%CBJ2~WEjB4TI?>-x$57z= zMR11TNeCe)H!+JvOyF(Gc{M|#TVa;$$?+VhThAKiqqVUKD%P8 z8C^GHep7)7t!{qCe{}Iw{Uu~brLAAe^RA8Ly4*TgN64^*rO8-DTgOf`q4lIT6B``5 zzD#+F5;Yxu!>x%L@ZUwPK6WK6UUlqBSmXZFPkf^aQO#<0NRB8!$;htJt^2!Q_{`y2 z$U&D4RQW0r34e?~Txo0(RM&LwY8AP^9+1+eU&uo@o0!H>o`Sk)N!wNXW7AciO=48a zTf8aagi?CB8a)i)PKG;FY}GTOAL<;4{yp?0ahKwKtv=FUcjK`;EjBssvjNuBq;RQ* z18(7EP_$EsGd3puOGvheoRbKbHmb=Mc|13Tbdmuk35snw2{q)l?anrvt65ew zUaNA_s-th*9(SU)=J)KT!-L1V>K`XV_~zn=|* z-v0d=jZy!@nr3QW@E|?gHI|4mI=$S;wV#652=E0FHZo9kd93ql&eHu39V5h;LD~Nq z_G$cgsvHBN>$^^WaOvu+>A7s*!Zm@gngS7%J6Y=+no4*5E)P`*K_V|Ijhrj859y}gM*{yB z8^Vi`w${PR5r2-0g~t?6Ak$Y=y2{~`vA!s;j!d#?g?Lda=sm7 zQG0mW5a+nTsI0ba(X^&@W{YBY6HiIW=JtS2)L(wi*H9J?KCnHTM3QG0AEJdZheK=) z11@KHjeIoQ(7v$pqN1ZKFV#2rAmWZUdVNC9D|)3e{cU&<=G|;Dt}!VTd*hXZ{dw21 z1QUHaPRiKVvM)n~RMk`0-iAy;qpj3byMynQEPqX~lBWd%Qd_S#qF?9;n8(_wwKmG} zi3Zq>eNQk0l#3jJpbqOF0I7m2&tlr~Tgb@1oNp$$)M}6x$h6DC6n;?zX zj(TXT&&zKzr538bXl*L_+cVA8L=90mi#_3$VRW(yWoL_yqI68-axkF`H!hmu#TM73?M+O=Gt>QCOw7KJ z?))GR@kQ^G6^kA0<|Vi2gh+HsDs1GnU{xBk)aIE5x`$+y6Z1XUvZ!OvR0KshzvbWQeW&T<2N;})^<2-uWWWQ410Ld_VRJ;jX}EWxuD|EJ>(Th>GlZMr1UxCkQOVH z)LFC05)TJ4YXbSq3{%mRTZ}i6%!V3oz2=n#=1WadF*5Xb2feysH5pIx4tWz>pRv60 ziWl-%2VZRa%lO^Rxg#-=6;$cWEKYfqua4i+k-hplawSlq9{xV%G*)vxZvfY(G-=y;ZJLUlA1h*F{vc7RjYV ziH0MUC?RjFpJDn>HIS0HouMxVM@I9g&=@|?vJg!?yu|pN?!Zl zC30DT`{iXBxH-akjW7uFzwOjvsC~E zLVI_B_%B!cp9>^C`zK?Ws<;eGgbyw5_%Y_hk(-Dh_R~aGm)LBw$W1;Lx9-1REyMn3 z9P5fGDKg-O={0C1jzWG{(`QsF6fJ}=@du?cJ%-*@L=l9Va6QL`;mEK(Qp{gsj^N%lGQr^UO#>)2Uv)kDe|vH6KlzpFovVW9Ho zk3mGsA(Gt(=)K&p;J z48#PY7j?7Kyam|lRb1k64Yo~g1+Rx1SW z4kXIk%N7l>%+ZgDU75YvF%9oIpf{3$D=0e65yN)ID`< z;;C>u+uY??53A^;t9UO23@fPlkRTd6$gXrr3wD}I?z5z2G8(}{=vC&}R55%2Ij;YG zBFJrB@ZmnHsaChn+-Kq}{8mqIhqKr-5qo`I4iNucT!lyV2PGY!0Pf($8{Fnm!6lbo z;@OjzrVXYq8@4bL@)KbgPNC_`6OvADttP%Fj1F;C8JP%I{Se)ZMWECKOmNZ(_YMn3#oxMPs|jjmSf8B{ zLyZFqhV!?-U)E0Lp|*Yp+mrfKxr<(Q{bio{$2`Fx^_+{v zkcc&BrFJzhU{vr#F9{Ez3l7XFVKkXN=HqtZqcB&BaOmO{b?R_lVU5*0ZlHdarLxXN zmzE{wb(nm|$w%$wxUoNDuSlU1NJ2_KZ0;&z|0Vq!3Z0GTcA<-Cm;~>^lkx#gsj0_7 zW-0Bv?<3CL|yRJJiS5k(yW3;E@#gSp}3;H|u>@wg9OwK<{+SDH>3h`C# zM+Z-m!lPwVlz=uBdwaJv2zk70&u0^Nx7f?-UR<#1W-0L$d-PtyZ)Q~$nf*9wBWaQK zdOT0cBrLF7@U!36x{~J#vmTdSUaDAC+-dAaPQBaq@I@u~wz7Yx55T}}g+_|=cz?&8 zM_GnS78=vE>d;k@9;i|3%IhXBqk5TyRUOYhyaUAVH*%3@shxuFwrl6jB|txHas)JS zP;$t8D;e6X)l-H?bneZ51pp+y<@bwsRHnKlZ4<}=`(A#S>T^!!I2E_s9`QYWNF;l& zOhn=YN^cnnyXO9#|9Xk&zY;`iah#h8$CX*auA#I{VmaVS=+~f(Ph!UhdEr1Zm#H8k zm+=9CD+iWF4>&JhgPAlsEZe{NKus8%p5!X8;Ud)P0snH2+h99cc!3y!Eq}vSAt@g5 zv?Lb44?FS4zsanuJ-_nLY3a~?O|!w+YNDXp;<{-)bgIW|G{R{@?K45bNQ*XsZXW8O zs0vh~v#wzfY^@Ua(QDXA=_BfEU%jVm-xWLdDH{j=mw@aq z>EJVFlF)>2Tt65pAizZ1+~%?wM)Gj?0-E5cTY2rR#|>` zkuX zz{`iGj_QIjn_$OJRU6LayIP^rBT)uUX|2}L61wGyHsU0f#%iATR^Ro%>Wru~XpZxk z6=_GPg#smHC4B+Pa@UL)%gf8iKYhh)Nu&VU2|1syzbn)3NQomgS&?s;+2bjb&V6J2 zi~=Ji`hG<4hd!f2?&O)UL`1}{=~+Gw{&U=sUAYme_AV0kY+!12+ihY z#5cHMZV_M;~L-HU~` zn&3vH9lEDQrwqQy0-HfREy-?->o!s^q@*6Ds(h`3R$T|$50~XSSs!818)(pz_iAv| z_kR53F7}9Yc`;2$?Ly`_SP)tB7XOCsq}eh2dbzzx$dd0s_p@9R&nr(X=I+o*bq|Ia z9J=2M)!Xu?mWZ66A}qm}!3pkUw4i8#C-4@9HNre@!@S5>hHvrjTjKkF;K~Lq{C;?- zDjvGGmQN)KpN2lZ#3yC=lra(K@JeWjE4Ew0K#%F`O7pYQ0Hu7`+rpn@(vm!YNsDFv zz4U^*SRC??vp+5_c~H}tv(Ya!dMQOXCs%fdfGeSh7S8HkPm$rK(#nh6C z1>fh65872N0!D%T{i(TUZ`y?$9e(QZ=$!n)}@V|f;Q7A)p6oY<>bPHpcx+q^oh zeS{2F&>*Fn0Gg0hhW1x1=^Els!TTv!X&sB(D4miffm3A2SJES)tU{v8hS}RcGZW2< zD`Z(ONk>QOldJZT*G_~1sGjtcN7k?RS%&z;xms$Lh9xv|y~EWF4GXh*;}Q26jCsdX zeC=1pwF(Iu<%3#U0_JB%w|*qEpblMB>0eC+wSh@$MFu+ulO_9THQv5Gbm!6bnw|HP zlE_9dpPa>E@GdX5uc|fc3si>M?(I+gPA{z@Xy_r67gbQ!21oLFjI5Gvij&xahPbJ#O9;Bxf0pKgaVbK`LzqApq?0oumyil-LfsQ;Qw-;6@xRDtUj@YP2YFwaTP zwR7b|a>kn*u7^7*JzO;}Ni?XE8PSyRe1n}d{S}VCr0w_b(fU}ya`G6}qWZ{&ZYg!=9|E{3Z9)m~lcSi-bxsuhN;`2&gD{js)r z?LQs*c`-gb!O{wowmmGv-}_xkhe@xs6Jc@x?eRF8>gE_3Mfx3hqp4VPFPiB`H@n6B zOrdz;Vqh$aj1rx1E3B(w z`eL9t+2#(t&hLYaE9X07-{_FVKKgX|D|u)dYUafN@D6Mr&uvKvc|3f)bI-XN(Exhh zl02@HG`1l5p@(?^$c)T|kMKF*eKQEJSCOyRO#LZe*XXM)#(xCY*!>*zzWCWX!hZi3 z!uFlbPWj+|aHNoHf{Uc|*U#ZN`{3?%hBd@btjHiWrYwi&ZzkuiSPJjMjYjMhK${Mg zhO{5<^Jg6zy_+&10M&dT5yt6oSW!6I)=fp;B+RHlora}wne7?Z=azb_GB-h+UL<;g zMd3PWjHpWQJPH(aY}WUd1sobE(M-pMe3iqyKsC+v>U$>o_uSZ^_w4f zeLkVoU~y9ncX#w3KX9ZmN}Pj-67pXz;aTC9Q^$Ps7ki0gIDY5D4OsDgmG+r!r~f2S z@-uwPeSt0KN(6CxBY(50&)~vOW||L243Uw)1Z^E^VUq}@ z7}qocpEXKwKCU>wjpn^M)}NB&I5&mTt38U(*E21j{ltiRrQ9;YV(iMWXbU&8fW$T& zVmK0ZQ~ZSfaMSBEsULL@xKT*c)sF;dYR-sD)q$U`Kp9Tx{F8*#0=UOmxac;{!3QBw3K!68h3a60?3?`ezzbi@6y3-TpJYcG~Ho3YP^0A4bQd! z?(Hs^a2+Xr{bMrJ(c(Vn;p9)3ic(jLRQJ^=={X@AMEO5qlv42*z|k9<>z*n zK{KsoZ#s7y5x-;Ds6e=>Yf`97ZT@LQjJy3K?ru|4Jz#4+`wH_uR9e&<;y{LO@~6w< z_@Ly4F-g~gLvb0MN0X^&E)UEG|Iu}HFjn5Yku+7>U?d9-z4v{&BZHaw6ifek%^8Dd zEf0Y4eIMo#19q4i)*vC~8l#G-DCkpcM)mYV^-}h49>G zH0qk0T&|T27^is5qQ=~cS*7>_!L{QAY9uCv-VN!y)KEbu*o?xX5Q8H1{CcMy7A0AG znPo~lMk^{N4swA`(&o1Atn1lHlDh>bV$>Uwi0%-3oRdXk9rR3soI*DW&keS?Xb}){ zwR8o34Cu7+SuMVZ24AmxJlu>N8vPJ&YW5yQzXFx%rWyc(yw#Wlp9y63*!VUM_FS-;h3>Syb~*CWwlMM9R4IHDHZ& z;(D$Ug{i5W&6?W35ggvX{7=zeYfOLj8b0{jK)%@(_EBSC>e9%_Xx4;hf$@`e;11N})A*_6Siod0svV<&9xH$a9Szw@2P={+KD$qgl;EFs zhvqkpaJ7T88z}2W#4$!EdXJ|0c3%cBcL1X4f|&j?Q6DZvEEm#gF?Hn#s5jMKLqc)E z33r7M5@{g7&nVYAjC3o4>C(qVR?T?OMFl6qefZSA_>!05S;Xz(#qHZU`VOHbmr%Of zvSRcsS7}+U@9=Q~)juV)>zT*6$Zj#(nr8sM9zox9v9$mO8^Gq^v!%g34($Z`6rKEU zrB?Z158}$}V$f!~Dq>%$d@|m8llD&zS!FR6?#w~ijAdw+Rzr`cpMfCFTC8ofx16)#F5;6v>2ZX?!}hS7u6pEg9{|DGmoztQB0NedNsKXx1`bzr{q z$^BxV3pc2@bd}{BKAhi-lS=S9oG%ZS3>?riO+Rt3LMj+Ca8qLqzJU2k$#!KZ7&kjP z-a0=Xfy;nbCl5I*1|0CJ1`Q#{JG58R*h6kGGDc|Sw`BT|P?E{xb)1O?SJ!nRVz&ot z`+6-?@}tC{xF;z@7WT2k8mlu zRq7XeKeSIJSvyRbH+8msTu3fS)u(wE-FB~=Ft)v|W0;7ZJlgX3w*;LcmjZnC>i*_P zAt{7zeN}x;<=SdqcC+x^8X&PV!diKOI8@Yh_IC0vFg*SteG@o(r4m5&^-i*t)6J4H zpE*+p_M%{jw0p%bM0%AOWN&~%`wCoUC9j;tdKW81QRBo9 ze$IJeqqFJNde9d0MiHvJ$FDd;xio6d(E8`Od#pl??Xl_#*xoUoSVHj9(4wb6icr@% z$#Ji8N9%6CvUb|N?7eqz<*#`yFZ2NOG79IkzeL(p7H8=NZV5#g%?+PpyZDU%ajjGu zXWJgrk!-sx;^#otm$r*3RcMNiafL?*jn7kN$U6yiTN@5}JO^rg>nz%H_icph#SNR> z2UG6(X*z?gTTqVHLf}Wld56wfa=%61ZAS2>(R_{G>DfRvPkzp6L`-zV4~#0dzplTe z&lJW~+pedK>&z9}&d0@|PpH`WaJZ|@Ffh!lLrM5wfe|0T4s(NZ3j{xv40@PYDATRa z>45o&Pt3x>Z#3%yYsi#*C2?YHrS963h}rO&t>W1hAN_pU)U_vsA3M-G_m(TH`)inL zwBo--tdoLgK~^J__T*O~lo23Fi-aS7*Rs?hQLBdFpK}VdTSelJ!mRzM4Xdw2ppg^s zOZwfh=%B}c@xE%9l6UKI#r8F=|Ewe9Ei9id^s)yn6s+FlXxhhj&Tqx^fXMuoCEbFF zTJM4)HE%S-#^n+Gxg8Ye4A5z~(taT=&W7V3PB+M3ldd>_gnP(Ce?Vbp@nZPVJ7aPmX300gwms1-j66Ki@<&FT)T{D!lDKHB<{v&hbZ`ZB-tYntVV2l1OI=@`pSSRo91syLRygSM!NIRA&nxE(kUI%jna+MEg{|ANOvd=hi*9Z zp?NRwc>a37d^umZc4ud1XLfgfGt>Ss^Qe(aUh1u9F(?_GSer1o3p;CuIjz`G$>?(E zL07jU9U}Q1b7F)GQ8=VJ(||0g<=m2qd@?B^y&!K_p$bas>xPMjHs4A!LV||WVi$pJ zVNOR!MOO7VVl$=ouKEcA`|4%~h5!3X*!+y6qvdlA-wUu({8%pymX8a`d8ZWJ0TIE< zwIpoy(|HWSb)pNCF##=jDWXAhRVl(FYAx4Z+C14?HLHYYoc2}hp)&mRVULkvFkBKg zRa2$%I^Ku1Gr6YQY;V;z<0UuX&&m#kE@#aI8#Yo!eKQ93ZkM6U=f7f$)8^h-HdWba zpMwvaXPw(k%t;zug|&aoV7C~$7rnE0U$=Tbk~_cQP3!NkC%NV=S4il)^!oWq=)Y~)otY9@4x(*;{aV;o-4#Z zS~LMDP#c^VcOUp-KH=-h>p$MiNWDK<&`}-}xz+u3E9bO% zC@jc$;V2{oq;`F>yx8NBkM~A27WA{k+|1zKH_6j2%)Y9l#4VDr3^ z*4iL&joDxvnohbCCaDya8CtV>g2(MAuNgj+;y_jcfC}HtFV|SjU|6BnHQ{`kt2QT| z>otb6p*M+(C-08IvQHNA){b|o}gnwr>3W4l`}wU z(3w~l$edw#IR$TvCK}RJq9Ts9VZ}7MJ$TC8Vzmm-@^GPfXdZ!%jNcp!EBhLIMLPQ6 zIF(hqrvD{U)dQdJ8DHG$yEvzQTX_}Hd*_=^`d2Rn0a!F`_>{CnLLPvh))Y|{Gvjj4 z0z2nwQDLBAL63$`xv*aw4@_COOTuT?Lb`8x=0Bx#2ss$Jwzxv{E`GMSk#+8W0{)r0_4X*z?%-emm8r~<6S3oT0yLbn%rhDNbI~O^*OiHx9xyREX zwz&f)t{D-XA5`Kpbq+^?eQ@xM`GtqsZT!Nv*O_lA1ENs@nJPD}M+r@S!e^ei zDEaa=qSe!t3GD6RCsK|?moHSLBXyO0x#b`3ec-EB7n|9ngpUI7wn@cWUUylnY3MNTbYTki^%5f-%muJ2m2lqS`rUY zX%7B^W1f;NYdH=3XhzP}s7P02 zxqn&8$)(BWep?nBX8n}Q1b$5PDo|7v`^$MZj>_zXVn;G|aW3#$G0uS7u`(hzlqSAsqXccwUe7&B_XJs`8 zon6jAfOA(~8af+K=CdJt$|OQzW1$x^o9#(B3FRFT{OHV=EykxAzpH~_(oCS5!|rJk z|4NXl_Wg9k*NoAYcdpvjl-IXN{={rY^*sRXCo4>7I+u+RRsi8MsC;WdhM?>+=7ac&Rx>|MPd>xBb)T2G>#0U|;a4{n00$ zzUFR2-L={W7Q1~t$`uVv=_uEcIz?!nX2|(4V&^lpm!m&v4nl{Azp>#MuSeD$f?xAW z7rZ`>=+GU@Bo)RaAklZ<{4(7JM4%U3MA2emH-XFO{poX`>=E8$QX_EoT&HXM?b7L0 z_1s>L?qIgfa8N9t#4i9ikP#Cr4G1l^r+QU>-SoZqJpU^%p>!drbLA7I>>=R|rNi-H zeRsV((^iYfto^)jI(VJ$<{3VtFX5+-laP-ceHRv%%{DS?m@<7w53ne)-6;G*)^Q%Y z!berc+AChO9V@04Hs_w252xkh-^(~rqQGjlm}oT}R1KY1u_-Y5`ZPh8d8ZJK5}U2( zp2glQNU>JkgW5tT>?OZVTuCakztaQ&yoi+hr8eZZvwg$31}|;bo&&pdMl zkP@r_Pjz!OFVj3~aCNx=skjy6Z97YcBn^q&bSl|34{Y48g(s#KqRl&VZ=S2)(08Y` zrMJH35F_OX&1Ux6ldLEOTfs<(s`7pjSTecoL?W*tM8vx@isEA*FL>|>ZGn1CnHA0= ztvBtLRkx`S3X}f=SSDB4Ob^fP?%oiWRXz-Y8hfXFWAF|?yyA%`jSe-Yuy@8La8ENk zyjz{-eZ9PzfO`$^PaO=Pm8gSFB@?<8NDny?7V?RDW+x`G-LNGY__y#q>z-_-)x^LB zG!G8X*YT$2^rgWlJ?{M+BXsbiser+EHL|$V@>B2`T+18%AQI!w9S)$_tMTuPt!4^< zw$lrWNEFl!FdtjuF>@k#v8Ph)yw+_~-x<&utoM#=IXz5eJ}muc_U%AKEY@hZu70v1 zD~aje2807jFy>Egf|T+%^($6{t%wQU6f0J4X+3S8;CPt85Vw%hi!V-~!pZYe(Z5^6 zA1N_v=Y;^M?!*nYYvyL8qvSc%qeNcAcod(7dOMZJ)1S>#qv_4ewm*x0UV1WXRsG;j zd(#2JnXkdfrcw(<9tnqOrzLV;{8~l4MN+CIzKoKz^$S=eqq}ZBK$C>L5oH4=EZy(>wkAItOBvS*4O*90Xw~JgoE{qj5>TS zS^9Ebk-_$@kbW-1k*Ga#MopQInDuV<|$S9|qMrGeEbKgXS3u z)n>!5ecZ8=1(Nn z>eNlG6;D=L;wawS5pE&ygz&{H)1;Y(qWJkwa1kLLCbdJHO_`N;h=@@*GHpDX7^81I zueI^CpFhfs)?+8LKjzz)V*-I%gNxPXcG`^quqQ|)P-{^TeT9%D4fLq1AXJ3D$M+qR zrX8zK%s?LN_`!g!RkGY6&c}D>iANHeLE`3c_HI=7K(o{g9elcp|DJNEb{CE1jcFJNC$NO^;}1#g%ICo* z>z{%lxeJX>1;c%nU&fA(&BAgeD;gU-;+kP#xFY4G#NWugOKMQX3k>2KO)5SsvTUSm znx(9lo2s`1`&2LW(dN~^YU#o|6wmFC4n;*pw-n-fvbeA!cDW*+0rs3y8!Le2j))%WmQ+)MsO+f@g>eyb5&Q{>DP~liHBr*yX4(JpuxrZ zBF6Po1d5wrOhzkK#xv1bo|7LO&V=m{yKB%z^~ZX`GE#-MOtA4wOvVl|Z`1A3h)3W!xH9MkiS0mMmV?aMLb!HQ;Qh_f*rqGh(DH?ST_@M zMmodo4R^!%n!wAK8Z*w+4~kHmFwR5;8Zc zOY_ce7@~N(_4C1-ndR;j^gksx!My&+eY=v>7JZlFupM&HbaxZrc#73BX6nwC>P~nu zN$xbCHu`Lz`~oK$U-NVvx^p(Q!JE*DRyA}#DO*C$fF6iU58XI1k544*6IUZxmGHexOncU@!>A1{C8BcxA7^zVKH=*z=74btYmD2r}w{Km6i+^PEQT2?`6C53V%IbSY~YmQ2xk$k=lfu75w-XIvh3*HMeSVU(hc&)36^(Lk7=M-&%P9Mg=;*#1-7cOIj6D#p-&VQ6m5ENpAyIDC}CLd9tHfvw@5c-&y^sY1N=ET$KG zx`?aGjs9ajSOIuuX{UdjgH&)%jMBT$W8upszVrApT6s8=l^sB+tj;@vI+8l7#J7}t zL%FY2jXWpT%Ngt6Z36D@7Wbie(Kdm?2|qzU3MZvY&yu1<@MHKB$=L$ZAuSh1Om$?H z`sn<$xI3zLif!wm&3u-8^F>1NWM1OCGyuL(9s7biw{cY1Vqgmgi(7g44JI16x|5B z4M$@K!q!?i8)r3vqDhPrUgc;iAGnMQYcwNcR=~X-oi~<#I)&ZMtU@^}x^f(E?!2Sq zO$K2i`3sQs3-XJggvL?WRY>JP-@#u(239$3ptjN6mU!NmzrYjA5M2&X7t=D7?$zf zoivr%V+`~FGAJEtpK}EWTfxYk`aBgu7^EYMr<$CQ(PxW+ICZSOT+c<~>}~|31|rmy zt&G^Ve~!e*ZOQfv#>6@{96NvyBw0JYIP4xI!g)-224tzm3Af+uF`3mz%{})2fSWN)@aIs`W3qj<+z6`fDDV;3KR{4W!m z0{zJ{ps)N0-nS`VbBhU~d?9#F@xefM=;u6+vHsZ{MqjXn^I!WkG6*>M%iKyw*?YPf zO5(Y3;J9%}GMsdGbY)&}_2BiG)g={`DtFlQk#P1aKkI$c%+IcH% zw)Y)O&V3skh>C}(7f**=wODUt`gh^C9Y@!><8^NW$$C|oQlaNqrh5%Qh%b16YeUMl z1Y+@wP*?0*Co0ZUzV8Ev_#Q5qNhto5mg#9ztcY-ns11gW;#poU=iYmTnbRSoKMU2Z z@RC@vK*~2KR>~rSAH_Jbx^$7y%|C8Qiy3i{%tBU{AU=urM{eTUH5Rdl>VDQ#LJ0I1 zC9vWcG17|lvr2@M!&yl_eqQ!KQkc_Ux!K<_MXfnagcO;;U!z6d2fBtl20TF>mWn!+ z!<;aij`%>n=TBGg18Js!eDi{NvZYvstKnE=;D!*+5xudmW$Sudzh$?#unxlnn7y`gy{ zsk}6bYV7a^foY?oQHIYVSVX#sR7jJ>jwQ<}=4pYe@JmL>Nd=FR|3 zy48o(h`IbqaU-}EI2-1QRJDKn+?O*){&0+BwysD_A&YQ|JMi4WC(`Z6pAZ3&v1aV> zrqNCW4Ua@;)ROun#%GXH+4t1g$JawF6*`bJmgclck!B&8%wVLj-|98;RGS z2Sb0I|6DB!V^Qv!jNhKML0j1?+ku!OG|4+0 zBcRjuz@Mc$^>ak{H+rn}AwxrSEQjk4PC{JR>&q{PMsu*p zj?#q}6AjC1pT>N1sZIVA#{8D9q5~RAKa0*c#04E&>w4Ur5iy0Y0P0z0pN~so?zLIv z1KkE5c$nYS%PCKm2=TkY+0~GTa43U_t9Ln z4kxdHW8mF0hSc*P!FL=Cd0_T$GFwTMgZD4S5RY~9$l&hzw+8}kZv+F45^W~OWd`%f z%HvNN0`CsYlt6m;hZmPwOZ1qY+M3{TkO19hQp&%iVJ7CcO=LKBM2bGQXfT9+T}{#` zbFwx(55lXdGT^c52@Td=A$kTrC+4*tSMah=T9Ghuzpm?V#qajRcWp;zHN{Tbfh?u+ zSx~WAQotu8qZPF%GE>0AQ@w~m9n3{ z^af6tdhkVj5@%E$0U9@m2y;k*{R~y%b?H2m$|YxtZ+QXBDsWr0eY8tV#t`if;~nbH zwvp~A7p$OCyIo$^{VqRZBY6LJDPKROL(>9!>%tF^C1>5Rf zS6)=hdb5kte@pG;Fyj*zq__~#?Du|w`QmOFC^q`H>boJ=uxi>b`)+hbDA9`-cwpOG zMUIQQ=>H+ye44MdkEno=tZ?gibQu5Isp1m1r))i5l-(Jz3_ zqB*P7#@Cj0MP?Y9)h_qC(a$mG1uVY-g~rnNEe=6sLLZQE+$r$g#o*j!&ocH4Y|ExF zChdJ)(l2*}W`Y+AZ@w)Y$(eF>P?*5Q*IpW+24SW6xT9Jo%EsB+6!G{z%uOzjao2wu zO4K(AXHXHka3(fT?fsRRQg^j6b*vCrCXBqU{c%eQrcp{nNU++aNr&roIuXH^2xDXH zzMKi_h)`AdB9#tFX*p%}o{m-q;TsoAB%Q{_&kINZ-?#q_1qGyTW+a^4o6`29(4{yWOC`8z8`mdh^@loMJR-=Y2z%Ze%%po#*YH`Ee%L+(F|dt1M7TpLiB7qu8XRS-zs zv5%@7)n938Sc*!+7cv!V80Z^Hg@xS}C{UbfxgJ_ZZa$4k-1pkvvB@SI<4U0kY5y_l zAwo|`206^PWdq0Nc`2e>2<;9iq_&KZOuUx}3F|~bcSvjQjdK!NWICk0nt*gtS)DAK zMfsE`Av?5Lt`qYzNi0yvT4-Bhru+mVWc_&8!Bm$jvvx2j@9oB_ne==}QgQraMS9T2 z3~UmRN8ET<18S)I&~gZ`sO(sqNv^Td{HE;2yCriecM&#NFy*ykGSB z!~f2O=Ei}Gls_O|?)3>0E}0#Ye=xqM-DFEOd*)|ROdV4j@SybBbmN>~*h%ZBSKt!q z8MSg3C$=L_xUfC@r^9dFC{dECYY9Zi{x=V94N9pcqBApmS~uTqR5t#u>U4}n;1fNA zOZzz}&KSJ>E?DFE)nGb0W%TP+*__#wuDzGI&rK2F`p{s>(D16@rV$IvB1wOKqqz8$ zjrh;Qg1^{TO7^YWW^tmqZQaO_^Z=XQP2GSAE$6E{7+S z>PiI`i%||Q>p8`Z$eyl)2xJD>QlR5)Dt;!qPyaFzz##b;{;wcA61CT@dLb4SQ^3^d zK^olj|2NAoFN$UH5`kzL7fF8^K}LDqQiS-~98T%03+>x+kyL~TzP0U~f%68(HRGcu ztw@iwz7cYKA{^MqcdZ{jw3o~F{X=rrDwaL#e7{%C1Iv^>g-jrvznP3*aEH`JTQY=Y zp6qX<^=sb9Ph#J#4vG()=UE*;f?U*fvJ+>QV$gN2#u{?BNI#Zi=ac!5537V+OMSiZ zV(}ajsEBdkZuE!xtMaH1^S4{6ElG0o{^-3H6wZ8wG9N3{NSQc(Z(V^aXYc7}6e9yPgsWrQ`{tmhPQ{V!KykzzB z+>pZxdFbPTI@w6~1=W)`&B)65>9CJmOG3SFMII(*EC%)&xFVqe zBL256`t3suVpwKr8Sb-DaV|E{L07akEVbhGH+2WMC+0A+exQ~~D%aos`xl+Z(?I2G zy?H?I-@M4{>=gIL(ESF}@NcoL|E)w)!Y_TXZ*c^)FdyB+v6>SY2tVMxK>pfW?Q_Fw zD2U%+jGLP~_bczWN#%_H@8d!-m?IRV5#5@~k&e`lvl>cP{hkku_P8;NXP!}y2lX9-{fzLyHg#yR{rpXxH=vt|uUhw^c%nr_a|{~3Y5I1?G+ zcc#=(V6{*Du5j_Vn@rXFf`jPRKl|a$#Hjv93TWgaX^zeBpK$ZTt-JL(M4@bd^z0Hx zv47n@9pXBT+fBC84dKzAbZM({D0(|L%~x|7$)Gxs|NDwlNMW~=dj&??$c~aBMX{mY zjT8RngMm*_XSq4#iFWqmABVDk%*}lf6cn87FsQ4A7RF*%%yAray!xq{UOzl-{|UT9 zg?0FsL;6RoE2Wg|`Q;vs6)K1MG?xgS-FsKk9pab-QC?K6QevwvzF{XUvA8E8ij+@Q|&eGYHpGhHvqO7BZB`fDO(ypNb2bJ#qE@8W7_<@;A^X58Hc>= zG#@t;UNaZzn-IH}{rDd8wU-W6YXIo-cYW>#PjmoO>*wehfL%-G zxn6e|542wSOlRe0G{%4;<}IZzDj(2|iGh)G1QsZHGbHNqk?$?2hrIZqslGfZ-%T&G&5dOg{x=TsV`JOr2rswJ zoE5-NMQ_<%%%l@HHOmhYtLL|@8#r=}2k$Di^BcK1p;*$7eXDtIa&l|3XxHMI5_Sc! z4+#~{&wQ;+?zzpaPU+>IW}Q;WRjj6_j_$>QC8$h~Vz1p(Xm34Sw5EWO>|IuvgTrrL z$-g5sq9b-qMNj#D;u>GLy#FF3c96dO-9bT!rcTj^-aXb3EnTZor}v^{cyD@CRTke7(8;T{y!91%`*6d30{UG{I4J%e zZR)-d{a_nx3VtvGFkz)J}9|BkNVB z{axeoe_BF747;sktUvN`p**suN7q5ym&H@Ygk6=0?u%P)(W&m>|Y6(Y+AE$i8Tj>xt9g32g-hx`U+s7&>3C9|`!=r^Y!;Y=~^p z!270%5pzCc#tf?2i8heU`+xdmPetWtIV=UMfa;bS?6G!e%NXkVT2$hEuABQzxJ<}( z$YZf26j~L&8I^0LYy;Bd0ae<4G4tM#jWtzYvg^d$-w=AtTD*KoCF4wnv4up+Xw09O z8R1T1xsa4d&H0B&F<`fKkv!LNP8i#_WCuxBeHiRyXE;-cr{BGKJt=fTp6+A<{W@_; za#0wy1O>$SK;7hbY-~UJEpkPadHX{2nWYUE6YGl~`eT(}AIX#Q+0#hUx!eBSixK{Q zXZ0Mcq>i7RI^ajF9AAwtt#~6eWM`U>@^@{%+~0ND+qwatcl$_5>fgRPKq9>MzuP9* zmnC8vo%;8f_KzlHxnm_o%sel@z0Ss9CsJ2~v`VNw9xAO+PHc%F| z4a}@f@`pDEiiZ0Eub}W0p&@@-QL(IREQaUlH_dD+YcIaQdw24I52eF@whPwGne-=X!9KQfM#w3awB8<>~3 z1I-fty9xy4*|j;vHLh?>PB22dHus-Si301JWY&S6!`|Au)qlPOxQq?={fISig>Rx9 zPYL}`dJup{<6nksPPOzoToX%6X-VVLjpNoYFF&}i{r>}zP$Pud?%lV%c`s+$FFfxN zo$H<5Dk{_d`VH}a*54wHFpOL9W^f~8$t-;ZsnIt)M5gXPYg%ETV#iaVFXLusH~1;o zC>mxHlJj3Ki>)A2`=PXA15kLqsmVn7((gX|6Z6em56CmbJ%1`Nu&$0*Vp%`HU^|-S zmtr0PF}0a|9sNXwEzdJ+IXFcu-& zf$|@o0oM3^pstpk}KOoSOAxoLReH8jN5>$&LmfmcoVYGowOGoTz3UH!F&xz!6N z9G|a?Etxo?gqE~QT%XojCv3$!iLv}Wp|>m<3q2?gKNGbwaVx0*Br$?wCC!S)?3^(7 z!T?^E*;mF%doL-XfYh2aGGp{eKgxda%V13Hmk{A1*tGTNA5QU$iAX*NcLM?Okfrh{ z68dK$M()%CGMP$r4PVvz>VIcYlrI9^x@vM_RJ3Gl{k1#Y>DM#deSu|uEs*SHbBMR8 z+h=%OV}DMfoUJ?FY0Uiq)t0XwF?&z=7e-ot_(kBxK>-&Zdq4%Ias`2jARZi~ zmSHV;to&N7NOd(Q#&;PN60wo@S+%oDuUoER)G$-@t$M$Lxoy}Uc8r%?mE$2*A>t>( z`ssI%Is;tpg|UB_i!I=$)zjM)?(xtKH6jy*I$z|EC7rqv%~?mN_c-A9b>t0?R{M1! zs>kS3f$a5Yy2-%9vOXsGa7SM)z5_0_Xa54Or`E`$E&6%bX7mTp+V8r=KLHpy$G|Mm-Qzh^&IuXdQ}_$XCw4XaK0f_T2hvf-E@jarSN;Sxux44d+() zo1x$Ll^_+e)z3q9ZL?3Ao>E#O_wa{*yWQUWA>B9gJHM4R5z-PPk^FFG-q&)bb+3mI zkQ~&z4N_+Cd`&YpQuZ6$v?|FXnYbj6Zi(`d!Gh! zRqgKWRR|59xcBBK>$l?0>`czCs0@03Gn9L;UxP=htp$$tN z%j2=uy0UO?YwcpJEazkgSB?X^H%DfsdF(fDVn({iuo+VXi&J*0nD~N7+}{Zxc|>lZ z#o!^MS8HLkK&|)?3hhLqykw}Gm~m9FXm(sa9H|!rDUsV7G+{ zefuI>`1i>X;Lrp8oP;&D9G#8qOnfWGkbPqLCfy#F+4(rdC0BNRGHI-=tQ0nvm$4&3 z^B#DfT@Mq}=7;wPw7ea(wojj_tn{q}@@9}%)Yhf}IfBmb=y>z0dbXW=zDy?Y0NLHY z&qZR6+<_zOW>{=_O!*z2bAp^`P}|GZIZl9fi{QfxFZM#SCvJK9jiMb9>jbMZ3rq9) zt*z7pxCLMt_Dks(UTu78$EmBmSJ@Qj7P}lQgBxv^k~^-aPoDeu-ueCKJ{-k{khb25 ze(mN*{7jyObgkXAx`&*Eg#8n5jcSu2^`P=4NdGHYBcJO{0OtblHwi0I@0;@<6BEfE zo@YN0_*6TxUqSkOO3*~i_)1fPEb0r9%}6zqvK=Dw7$3eZMm(;ddm2wv{I0eDs9ho} z{n5W=OWWU(@6itXyW%Nw+`jxfvAhdva&WTjC?aoOX+6ANtBoz z?<~hMKr%a_V_*Gxr{9~$Qy$jj%^|)7eSNNPX;T*c9>z)3OE}^}^0xLr#+_RfF2)7Z zUi7hFI^sl{-}o(}xnm~&oSBpJ*i3)l@Ju}a9rt=;6F8y96(Yi=25blty7q29NrM~M z*Fdgd&Z}I#;snzqW2lh0ZupxrfiRwEUNId~l;DE8Z82Z2D?maV~mk6K%i^*q(5}90)Ldhp}H8I_oz| zCgb}eI~=^|fHr>3MOE`_FBrg>vC!-s9Q;84QfhOdXOdslsh0?kl<0a! z(P8>AfSx>{;6(Uh#nTG_i~pe_u(DYhTuny=Q7AL#`}V5asXphN5096ly@jElk6sU3o$EuO5bY?)Vc>uSQ&@Yh_l<727~f^_mK0Wal;-VTMd*1EGR z`MkCJ(TIfwCn1K63`fpu=vL zeQ~<^cDX*5riHW1ON^{64#R!xUvuoz+B%E$^--+x22M^Yw=2Q3v+VT`T;SMCjyuZU zx32|iGN>YHWkSRLWQ-;a-0Icnh)QDGBDJW%E>&MsG;_;EYN`qdEm*pmri=39veCg@ z_LrKNPwqQxVNl5O^{7twzIDwEglk#?BFBW1oqKACQ*^#^=B~!5(EqrOOxq+U`xEsa z#{abhVPQD?enB!zw7IH9+1!`benh)8Tpk;%JZ&OW*=JI-F+Weg2V+W?&v1$8AQrX;Wg%c9G!eK5!f^cYl>Qj$(@L>JbHM|?M*9Qc= z_XL_EuQ8tgtzQ3Xf~qvdwP|gche!iwblYZQuw55uNR+wj)05)fRDms)hWu2zl&{^I zemV=9BsHCttMi5Cj`mkPi)k^}w)Gk<-U_)RdF4+iYBD@Qwxnx{3>bJ%2_2W)Kv{)A zZ`f+3V&40F<%0FMPZOS^S~Ug}kiRx|R4sZtoO8NDjbpl*?HY2C`MY>K;HhAc&{^LP zd%)%m#>NZLXXdlGxgUfn2$7J$VbTYu;y9e`U06Y9aU23+JBSgfFH6p8ar^3i*4n3i z`7(RHyWU4#4;Ru7URdDSH|W!swx*hf|@C;h+8 z_P5Lt;NW%21=wHP2^^)Ozb@^IDnG*j4aCMvuG5hd#0DFGuU%cNaX`lpj{iOaZV_M* zA@z0iQM}CXX@_9gFSzqgzU&%s(kQiu>dz^ad#}H60R#TGI=z(FO9DApSNHrrMJ|T| z=`==Ke3|NLF4+(b=u*JlSGp<$mPYbVQqZtpu7TFldVwyc_LI_|H~Q_(dS8-}jvfR# zS@-%osUaZ+hkqZKdvggCRxd-`<*%mrembik`I1Y^#G@4zvs%lxR+v0r2O%@6bSzHi zX>ONPavB5Kg{p<(#yWb(2Z%R@2ULZw#@e__+>a2~jOV#62-cc_z%{W@2rxbW>IMaZ zk3PamjO%)=ausm`DH3awA6zgUc`H)&_tFt^jDq}(E`c=SqsV$P)`tOpfyG7s7Wb3H zu(LC#vpwj2+72;T8C6;?F+SrYJUnB`fXUCM@?dUG%fbG5`V#~K!DrLE8?)7`OUl4; zy~VMD-~|jA#1wtv68ruH_k7(TK#`|c6YU$SstVN~G(BKq`#E)qG7iY%b0|qs;a?jc zSu+|&?5K@(&AqkCbGvaK0$sQr&b>_Nsj@#)U$Egtt$f^lV^>xpeBFmqjUsN?529qN z@ENS?S#%v0>e-!9D+kY7G;jJnBY-zHO>%ft4_vQNKnU z^6uUv`+fWPgYo<~io6_$SK=j~DTiIPeaaa-5QU#%dU+W0<9mAJ$7snFN3>^rmK+DlAWsN1&TZL8jlq*F_xQrz>V zZiucXs98H!z~byYR*S{=Ths1!qHz zrl$#KkV;mGI`~!@ySd_pb0O1R?A~C>?fy}#Qfe>$!-uiZjP@Id9jOaY#to_hZg1L_ z0*iV-?qx)~FZf)5Gqr9+5k%}q=uGAs(lUwNgWi01Eia>h^5K&#*)MN&>#Ai%YT?gd zb4X4TUmZ= z#i3p?UijPQ0kqa0A#GR%%d>%@`{A@oBmCL@O4+f&)fo+b5E2_3n-81jh`LbokNr2EXutcyxtg)^Rht7$RSW)Ty0F2uq%CM|BJrpl0Fo4X(*i}|< z1XRz>4ud>o_=R;NgVeft$w|YpWt_Lal}Q85HJHc9_uT}=r6zkzoCR;U>TB-1GV4r`EOb7GdT10E+8eJhJ72Q#PGqL^fB*MpJ;;O6t z=z8+30HVKi#$lK0<9mLq21VP2%C?Js80*8dE0zk=CAR8k3O(QALo>>xWIs08Yg)=6 zC2fza9>*l434`~=XvA$&{1xWBQXKjwCJeTJ{lswQ|HEJ7C=Z1>%Jcg%a& zqCFpaY$SEixE1t@(Bt^ki;v>Dfj_2LZu9vvebOZ7E7_5!EbC{&4-XGxO(jwkpWdH7 zXvs0bBcIO7j)~LeFZ(A8dru6#|mKBEhUE*u#~N-OMX0*0{aKA8yp(sVUgpWNU>1g zGQF*TQ=<6|JuHh`wwu~;(_jMkG9_p8gSD!(=UhaayNbz$icQ;NuD*BU15z>M)_cE1 z_rAK994)_{@!BW%_UABJyV3BHUC4Yhx6l0<-%Z=k9JfcARkpkR3^I`K&3&<_$d=6% zBpPUnlaZ~}E?S+DDL7Ye*&KRLTWNl0Z;c}tH$jE1E`j@$a(h>OTd>Qd>@L1he2oJJ zSyogOlCs_`R3ynNu(xDr8!hK}h;}P(`=yNz$y{%hBs%Tpr#qeAjPT`L_EVR+5OR^d z*97+j?4^ih)#*<1%5kbh^QwaSj8f58k6k4ROCOWAmV#C3qRWA2%GO=>MACi8zJk@&`u6)FyDEC`Hal0(F#@sm z-m%ovT_zxzJCk=623|Fef@_PoQay_= z?5CdV2otaFYxHIsJ8523b6C;e?e>guNVx0)4NlHJKa#%|GH+#&MeK(G{^X>UrOG4> G0{$OD;fK8d diff --git a/docs/disconnected.png b/docs/disconnected.png deleted file mode 100644 index c1d518ec5131f326edf9c817eccf85c82afd8d4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57505 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ξmgr7Tk}N;V7~Zcr3#32z-;%CL$keg7wvtM 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