From d4299f736fbd57018b63457390554d62a0c34506 Mon Sep 17 00:00:00 2001 From: exttex Date: Thu, 13 Aug 2020 19:39:22 +0200 Subject: [PATCH] Updated packages, rewrote player = gapless playback, faster loading --- .gitignore | 2 - README.md | 7 +- just_audio/.github/FUNDING.yml | 1 + .../.github/ISSUE_TEMPLATE/bug-report.md | 53 + just_audio/.github/ISSUE_TEMPLATE/config.yml | 8 + .../ISSUE_TEMPLATE/documentation-request.md | 39 + .../.github/ISSUE_TEMPLATE/feature_request.md | 37 + just_audio/.gitignore | 70 + just_audio/.metadata | 10 + just_audio/CHANGELOG.md | 114 ++ just_audio/LICENSE | 229 +++ just_audio/README.md | 222 +++ just_audio/android/.gitignore | 8 + just_audio/android/build.gradle | 48 + just_audio/android/gradle.properties | 4 + .../gradle/wrapper/gradle-wrapper.properties | 6 + just_audio/android/libs/extension-flac.aar | Bin 0 -> 644206 bytes just_audio/android/settings.gradle | 1 + .../android/src/main/AndroidManifest.xml | 3 + .../com/ryanheise/just_audio/AudioPlayer.java | 723 +++++++++ .../just_audio/DeezerDataSource.java | 264 ++++ .../ryanheise/just_audio/JustAudioPlugin.java | 57 + .../just_audio/MainMethodCallHandler.java | 52 + just_audio/darwin/Classes/AudioPlayer.m | 1138 +++++++++++++++ just_audio/darwin/Classes/AudioSource.m | 37 + .../darwin/Classes/ClippingAudioSource.m | 79 + .../darwin/Classes/ConcatenatingAudioSource.m | 109 ++ .../darwin/Classes/IndexedAudioSource.m | 68 + just_audio/darwin/Classes/IndexedPlayerItem.m | 16 + just_audio/darwin/Classes/JustAudioPlugin.m | 55 + .../darwin/Classes/LoopingAudioSource.m | 53 + just_audio/darwin/Classes/UriAudioSource.m | 79 + just_audio/ios/.gitignore | 37 + just_audio/ios/Assets/.gitkeep | 0 just_audio/ios/Classes/AudioPlayer.h | 21 + just_audio/ios/Classes/AudioPlayer.m | 1138 +++++++++++++++ just_audio/ios/Classes/AudioSource.h | 13 + just_audio/ios/Classes/AudioSource.m | 37 + just_audio/ios/Classes/ClippingAudioSource.h | 11 + just_audio/ios/Classes/ClippingAudioSource.m | 79 + .../ios/Classes/ConcatenatingAudioSource.h | 13 + .../ios/Classes/ConcatenatingAudioSource.m | 109 ++ just_audio/ios/Classes/IndexedAudioSource.h | 21 + just_audio/ios/Classes/IndexedAudioSource.m | 68 + just_audio/ios/Classes/IndexedPlayerItem.h | 9 + just_audio/ios/Classes/IndexedPlayerItem.m | 16 + just_audio/ios/Classes/JustAudioPlugin.h | 4 + just_audio/ios/Classes/JustAudioPlugin.m | 55 + just_audio/ios/Classes/LoopingAudioSource.h | 8 + just_audio/ios/Classes/LoopingAudioSource.m | 53 + just_audio/ios/Classes/UriAudioSource.h | 8 + just_audio/ios/Classes/UriAudioSource.m | 79 + just_audio/ios/just_audio.podspec | 21 + just_audio/lib/just_audio.dart | 1293 +++++++++++++++++ just_audio/lib/just_audio_web.dart | 957 ++++++++++++ just_audio/macos/.gitignore | 37 + just_audio/macos/Assets/.gitkeep | 0 just_audio/macos/Classes/AudioPlayer.h | 21 + just_audio/macos/Classes/AudioPlayer.m | 1138 +++++++++++++++ just_audio/macos/Classes/AudioSource.h | 13 + just_audio/macos/Classes/AudioSource.m | 37 + .../macos/Classes/ClippingAudioSource.h | 11 + .../macos/Classes/ClippingAudioSource.m | 79 + .../macos/Classes/ConcatenatingAudioSource.h | 13 + .../macos/Classes/ConcatenatingAudioSource.m | 109 ++ just_audio/macos/Classes/IndexedAudioSource.h | 21 + just_audio/macos/Classes/IndexedAudioSource.m | 68 + just_audio/macos/Classes/IndexedPlayerItem.h | 9 + just_audio/macos/Classes/IndexedPlayerItem.m | 16 + just_audio/macos/Classes/JustAudioPlugin.h | 4 + just_audio/macos/Classes/JustAudioPlugin.m | 55 + just_audio/macos/Classes/LoopingAudioSource.h | 8 + just_audio/macos/Classes/LoopingAudioSource.m | 53 + just_audio/macos/Classes/UriAudioSource.h | 8 + just_audio/macos/Classes/UriAudioSource.m | 79 + just_audio/macos/just_audio.podspec | 21 + just_audio/pubspec.lock | 250 ++++ just_audio/pubspec.yaml | 37 + just_audio/test/just_audio_test.dart | 21 + lib/api/deezer.dart | 14 +- lib/api/definitions.dart | 14 +- lib/api/download.dart | 3 +- lib/api/player.dart | 725 ++++----- lib/main.dart | 5 +- lib/ui/cached_image.dart | 187 +-- lib/ui/details_screens.dart | 111 +- lib/ui/menu.dart | 11 +- lib/ui/player_bar.dart | 2 +- lib/ui/player_screen.dart | 39 +- lib/ui/search.dart | 23 +- pubspec.lock | 826 ----------- pubspec.yaml | 10 +- 92 files changed, 10270 insertions(+), 1450 deletions(-) create mode 100644 just_audio/.github/FUNDING.yml create mode 100644 just_audio/.github/ISSUE_TEMPLATE/bug-report.md create mode 100644 just_audio/.github/ISSUE_TEMPLATE/config.yml create mode 100644 just_audio/.github/ISSUE_TEMPLATE/documentation-request.md create mode 100644 just_audio/.github/ISSUE_TEMPLATE/feature_request.md create mode 100644 just_audio/.gitignore create mode 100644 just_audio/.metadata create mode 100644 just_audio/CHANGELOG.md create mode 100644 just_audio/LICENSE create mode 100644 just_audio/README.md create mode 100644 just_audio/android/.gitignore create mode 100644 just_audio/android/build.gradle create mode 100644 just_audio/android/gradle.properties create mode 100644 just_audio/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 just_audio/android/libs/extension-flac.aar create mode 100644 just_audio/android/settings.gradle create mode 100644 just_audio/android/src/main/AndroidManifest.xml create mode 100644 just_audio/android/src/main/java/com/ryanheise/just_audio/AudioPlayer.java create mode 100644 just_audio/android/src/main/java/com/ryanheise/just_audio/DeezerDataSource.java create mode 100644 just_audio/android/src/main/java/com/ryanheise/just_audio/JustAudioPlugin.java create mode 100644 just_audio/android/src/main/java/com/ryanheise/just_audio/MainMethodCallHandler.java create mode 100644 just_audio/darwin/Classes/AudioPlayer.m create mode 100644 just_audio/darwin/Classes/AudioSource.m create mode 100644 just_audio/darwin/Classes/ClippingAudioSource.m create mode 100644 just_audio/darwin/Classes/ConcatenatingAudioSource.m create mode 100644 just_audio/darwin/Classes/IndexedAudioSource.m create mode 100644 just_audio/darwin/Classes/IndexedPlayerItem.m create mode 100644 just_audio/darwin/Classes/JustAudioPlugin.m create mode 100644 just_audio/darwin/Classes/LoopingAudioSource.m create mode 100644 just_audio/darwin/Classes/UriAudioSource.m create mode 100644 just_audio/ios/.gitignore create mode 100644 just_audio/ios/Assets/.gitkeep create mode 100644 just_audio/ios/Classes/AudioPlayer.h create mode 100644 just_audio/ios/Classes/AudioPlayer.m create mode 100644 just_audio/ios/Classes/AudioSource.h create mode 100644 just_audio/ios/Classes/AudioSource.m create mode 100644 just_audio/ios/Classes/ClippingAudioSource.h create mode 100644 just_audio/ios/Classes/ClippingAudioSource.m create mode 100644 just_audio/ios/Classes/ConcatenatingAudioSource.h create mode 100644 just_audio/ios/Classes/ConcatenatingAudioSource.m create mode 100644 just_audio/ios/Classes/IndexedAudioSource.h create mode 100644 just_audio/ios/Classes/IndexedAudioSource.m create mode 100644 just_audio/ios/Classes/IndexedPlayerItem.h create mode 100644 just_audio/ios/Classes/IndexedPlayerItem.m create mode 100644 just_audio/ios/Classes/JustAudioPlugin.h create mode 100644 just_audio/ios/Classes/JustAudioPlugin.m create mode 100644 just_audio/ios/Classes/LoopingAudioSource.h create mode 100644 just_audio/ios/Classes/LoopingAudioSource.m create mode 100644 just_audio/ios/Classes/UriAudioSource.h create mode 100644 just_audio/ios/Classes/UriAudioSource.m create mode 100644 just_audio/ios/just_audio.podspec create mode 100644 just_audio/lib/just_audio.dart create mode 100644 just_audio/lib/just_audio_web.dart create mode 100644 just_audio/macos/.gitignore create mode 100644 just_audio/macos/Assets/.gitkeep create mode 100644 just_audio/macos/Classes/AudioPlayer.h create mode 100644 just_audio/macos/Classes/AudioPlayer.m create mode 100644 just_audio/macos/Classes/AudioSource.h create mode 100644 just_audio/macos/Classes/AudioSource.m create mode 100644 just_audio/macos/Classes/ClippingAudioSource.h create mode 100644 just_audio/macos/Classes/ClippingAudioSource.m create mode 100644 just_audio/macos/Classes/ConcatenatingAudioSource.h create mode 100644 just_audio/macos/Classes/ConcatenatingAudioSource.m create mode 100644 just_audio/macos/Classes/IndexedAudioSource.h create mode 100644 just_audio/macos/Classes/IndexedAudioSource.m create mode 100644 just_audio/macos/Classes/IndexedPlayerItem.h create mode 100644 just_audio/macos/Classes/IndexedPlayerItem.m create mode 100644 just_audio/macos/Classes/JustAudioPlugin.h create mode 100644 just_audio/macos/Classes/JustAudioPlugin.m create mode 100644 just_audio/macos/Classes/LoopingAudioSource.h create mode 100644 just_audio/macos/Classes/LoopingAudioSource.m create mode 100644 just_audio/macos/Classes/UriAudioSource.h create mode 100644 just_audio/macos/Classes/UriAudioSource.m create mode 100644 just_audio/macos/just_audio.podspec create mode 100644 just_audio/pubspec.lock create mode 100644 just_audio/pubspec.yaml create mode 100644 just_audio/test/just_audio_test.dart delete mode 100644 pubspec.lock diff --git a/.gitignore b/.gitignore index 7f66c9d..e78915c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,6 @@ freezerkey.jsk android/key.properties -just_audio/ - # Miscellaneous *.class *.log diff --git a/README.md b/README.md index a607241..7cb3b4e 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ https://t.me/freezerandroid Tobs: Beta tester Bas Curtiz: Icon, Logo, Banner, Design suggestions Deemix: https://notabug.org/RemixDev/deemix -just_audio: https://github.com/ryanheise/just_audio +just_audio && audio_service: https://github.com/ryanheise/just_audio ## Support me @@ -35,11 +35,12 @@ BTC: `14hcr4PGbgqeXd3SoXY9QyJFNpyurgrL9y` ETH: `0xb4D1893195404E1F4b45e5BDA77F202Ac4012288` ## just_audio -This app depends on modified just_audio plugin with Deezer support. Repo: https://notabug.org/exttex/just_audio +This app depends on modified just_audio plugin with Deezer support. +The fork repo is deprecated, current version available in this repo. ## Disclaimer ``` Freezer was not developed for piracy, but educational and private usage. It may be illegal to use this in your country! I am not responsible in any way for the usage of this app. -``` +``` \ No newline at end of file diff --git a/just_audio/.github/FUNDING.yml b/just_audio/.github/FUNDING.yml new file mode 100644 index 0000000..738822d --- /dev/null +++ b/just_audio/.github/FUNDING.yml @@ -0,0 +1 @@ +github: ryanheise diff --git a/just_audio/.github/ISSUE_TEMPLATE/bug-report.md b/just_audio/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 0000000..bbd2a31 --- /dev/null +++ b/just_audio/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,53 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: 1 backlog, bug +assignees: ryanheise + +--- + + +**Which API doesn't behave as documented, and how does it misbehave?** +Name here the specific methods or fields that are not behaving as documented, and explain clearly what is happening. + +**Minimal reproduction project** +Provide a link here using one of two options: +1. Fork this repository and modify the example to reproduce the bug, then provide a link here. +2. If the unmodified official example already reproduces the bug, just write "The example". + +**To Reproduce (i.e. user steps, not code)** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Error messages** + +``` +If applicable, copy & paste error message here, within the triple quotes to preserve formatting. +``` + +**Expected behavior** +A clear and concise description of what you expected to happen. + + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. MacOS + version] + - Browser [e.g. chrome, safari + version] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + +**Flutter SDK version** +``` +insert output of "flutter doctor" here +``` + +**Additional context** +Add any other context about the problem here. diff --git a/just_audio/.github/ISSUE_TEMPLATE/config.yml b/just_audio/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..dc89ca6 --- /dev/null +++ b/just_audio/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Community Support + url: https://stackoverflow.com/search?q=just_audio + about: Ask for help on Stack Overflow. + - name: New to Flutter? + url: https://gitter.im/flutter/flutter + about: Chat with other Flutter developers on Gitter. diff --git a/just_audio/.github/ISSUE_TEMPLATE/documentation-request.md b/just_audio/.github/ISSUE_TEMPLATE/documentation-request.md new file mode 100644 index 0000000..1d61cd1 --- /dev/null +++ b/just_audio/.github/ISSUE_TEMPLATE/documentation-request.md @@ -0,0 +1,39 @@ +--- +name: Documentation request +about: Suggest an improvement to the documentation +title: '' +labels: 1 backlog, documentation +assignees: ryanheise + +--- + + + +**To which pages does your suggestion apply?** + +- Direct URL 1 +- Direct URL 2 +- ... + +**Quote the sentences(s) from the documentation to be improved (if any)** + +> Insert here. (Skip if you are proposing an entirely new section.) + +**Describe your suggestion** + +... diff --git a/just_audio/.github/ISSUE_TEMPLATE/feature_request.md b/just_audio/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..1444d42 --- /dev/null +++ b/just_audio/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,37 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: 1 backlog, enhancement +assignees: ryanheise + +--- + + + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/just_audio/.gitignore b/just_audio/.gitignore new file mode 100644 index 0000000..07488ba --- /dev/null +++ b/just_audio/.gitignore @@ -0,0 +1,70 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# Visual Studio Code related +.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +/build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/just_audio/.metadata b/just_audio/.metadata new file mode 100644 index 0000000..8536f75 --- /dev/null +++ b/just_audio/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 68587a0916366e9512a78df22c44163d041dd5f3 + channel: stable + +project_type: plugin diff --git a/just_audio/CHANGELOG.md b/just_audio/CHANGELOG.md new file mode 100644 index 0000000..fc87c15 --- /dev/null +++ b/just_audio/CHANGELOG.md @@ -0,0 +1,114 @@ +## 0.3.1 + +* Prevent hang in dispose + +## 0.3.0 + +* Playlists +* Looping +* Shuffling +* Composing +* Clipping support added for iOS/macOS +* New player state model consisting of: + * playing: true/false + * processingState: none/loading/buffering/ready/completed +* Feature complete on iOS and macOS (except for DASH) +* Improved example +* Exception classes + +## 0.2.2 + +* Fix dependencies for stable channel. + +## 0.2.1 + +* Improve handling of headers. +* Report setUrl errors and duration on web. + +## 0.2.0 + +* Support dynamic duration +* Support seeking to end of live streams +* Support request headers +* V2 implementation +* Report setUrl errors on iOS +* setUrl throws exception if interrupted +* Return null when duration is unknown + +## 0.1.10 + +* Option to set audio session category on iOS. + +## 0.1.9 + +* Bug fixes. + +## 0.1.8 + +* Reduce distortion at slow speeds on iOS + +## 0.1.7 + +* Minor bug fixes. + +## 0.1.6 + +* Eliminate event lag over method channels. +* Report setUrl errors on Android. +* Report Icy Metadata on Android. +* Bug fixes. + +## 0.1.5 + +* Update dependencies and documentation. + +## 0.1.4 + +* Add MacOS implementation. +* Support cross-platform redirects on Android. +* Bug fixes. + +## 0.1.3 + +* Fix bug in web implementation. + +## 0.1.2 + +* Broadcast how much audio has been buffered. + +## 0.1.1 + +* Web implementation. +* iOS option to minimize stalling. +* Fix setAsset on iOS. + +## 0.1.0 + +* Separate buffering state from PlaybackState. +* More permissive state transitions. +* Support playing local files on iOS. + +## 0.0.6 + +* Bug fixes. + +## 0.0.5 + +* API change for audio clipping. +* Performance improvements and bug fixes on Android. + +## 0.0.4 + +* Remove reseeking hack. + +## 0.0.3 + +* Feature to change audio speed. + +## 0.0.2 + +* iOS implementation for testing (may not work). + +## 0.0.1 + +* Initial release with Android implementation. diff --git a/just_audio/LICENSE b/just_audio/LICENSE new file mode 100644 index 0000000..27a8b32 --- /dev/null +++ b/just_audio/LICENSE @@ -0,0 +1,229 @@ +MIT License + +Copyright (c) 2019-2020 Ryan Heise. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +============================================================================== + +This software includes the ExoPlayer library which is licensed under the Apache +License, Version 2.0. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/just_audio/README.md b/just_audio/README.md new file mode 100644 index 0000000..60fb32f --- /dev/null +++ b/just_audio/README.md @@ -0,0 +1,222 @@ +# just_audio + +This Flutter plugin plays audio from URLs, files, assets, DASH/HLS streams and playlists. Furthermore, it can clip, concatenate, loop, shuffle and compose audio into complex arrangements with gapless playback. This plugin can be used with [audio_service](https://pub.dev/packages/audio_service) to play audio in the background and control playback from the lock screen, Android notifications, the iOS Control Center, and headset buttons. + +## Features + +| Feature | Android | iOS | MacOS | Web | +| ------- | :-------: | :-----: | :-----: | :-----: | +| read from URL | ✅ | ✅ | ✅ | ✅ | +| read from file | ✅ | ✅ | ✅ | | +| read from asset | ✅ | ✅ | ✅ | | +| request headers | ✅ | ✅ | ✅ | | +| DASH | ✅ | | | | +| HLS | ✅ | ✅ | ✅ | | +| buffer status/position | ✅ | ✅ | ✅ | ✅ | +| play/pause/seek | ✅ | ✅ | ✅ | ✅ | +| set volume | ✅ | ✅ | ✅ | ✅ | +| set speed | ✅ | ✅ | ✅ | ✅ | +| clip audio | ✅ | ✅ | ✅ | ✅ | +| playlists | ✅ | ✅ | ✅ | ✅ | +| looping | ✅ | ✅ | ✅ | ✅ | +| shuffle | ✅ | ✅ | ✅ | ✅ | +| compose audio | ✅ | ✅ | ✅ | ✅ | +| gapless playback | ✅ | ✅ | ✅ | | +| report player errors | ✅ | ✅ | ✅ | ✅ | + +Please consider reporting any bugs you encounter [here](https://github.com/ryanheise/just_audio/issues) or submitting pull requests [here](https://github.com/ryanheise/just_audio/pulls). + +## Example + +![just_audio](https://user-images.githubusercontent.com/19899190/89558581-bf369080-d857-11ea-9376-3a5055284bab.png) + +Initialisation: + +```dart +final player = AudioPlayer(); +var duration = await player.setUrl('https://foo.com/bar.mp3'); +``` + +Standard controls: + +```dart +player.play(); // Usually you don't want to wait for playback to finish. +await player.seek(Duration(seconds: 10)); +await player.pause(); +``` + +Clipping audio: + +```dart +await player.setClip(start: Duration(seconds: 10), end: Duration(seconds: 20)); +await player.play(); // Waits until the clip has finished playing +``` +Adjusting audio: + +```dart +await player.setSpeed(2.0); // Double speed +await player.setVolume(0.5); // Halve volume +``` + +Gapless playlists: + +```dart +await player.load( + ConcatenatingAudioSource( + children: [ + AudioSource.uri(Uri.parse("https://example.com/track1.mp3")), + AudioSource.uri(Uri.parse("https://example.com/track2.mp3")), + AudioSource.uri(Uri.parse("https://example.com/track3.mp3")), + ], + ), +); +player.seekToNext(); +player.seekToPrevious(); +// Jump to the beginning of track3.mp3. +player.seek(Duration(milliseconds: 0), index: 2); +``` + +Looping and shuffling: + +```dart +player.setLoopMode(LoopMode.off); // no looping (default) +player.setLoopMode(LoopMode.all); // loop playlist +player.setLoopMode(LoopMode.one); // loop current item +player.setShuffleModeEnabled(true); // shuffle except for current item +``` + +Composing audio sources: + +```dart +player.load( + // Loop child 4 times + LoopingAudioSource( + count: 4, + // Play children one after the other + child: ConcatenatingAudioSource( + children: [ + // Play a regular media file + ProgressiveAudioSource(Uri.parse("https://example.com/foo.mp3")), + // Play a DASH stream + DashAudioSource(Uri.parse("https://example.com/audio.mdp")), + // Play an HLS stream + HlsAudioSource(Uri.parse("https://example.com/audio.m3u8")), + // Play a segment of the child + ClippingAudioSource( + child: ProgressiveAudioSource(Uri.parse("https://w.xyz/p.mp3")), + start: Duration(seconds: 25), + end: Duration(seconds: 30), + ), + ], + ), + ), +); +``` + +Releasing resources: + +```dart +await player.dispose(); +``` + +Catching player errors: + +```dart +try { + await player.setUrl("https://s3.amazonaws.com/404-file.mp3"); +} catch (e) { + print("Error: $e"); +} +``` + +Listening to state changes: + +```dart +player.playerStateStream.listen((state) { + if (state.playing) ... else ... + switch (state.processingState) { + case AudioPlaybackState.none: ... + case AudioPlaybackState.loading: ... + case AudioPlaybackState.buffering: ... + case AudioPlaybackState.ready: ... + case AudioPlaybackState.completed: ... + } +}); + +// See also: +// - durationStream +// - positionStream +// - bufferedPositionStream +// - currentIndexStream +// - icyMetadataStream +// - playingStream +// - processingStateStream +// - loopModeStream +// - shuffleModeEnabledStream +// - volumeStream +// - speedStream +// - playbackEventStream +``` + +## Platform specific configuration + +### Android + +If you wish to connect to non-HTTPS URLS, add the following attribute to the `application` element of your `AndroidManifest.xml` file: + +```xml + +``` + +### iOS + +If you wish to connect to non-HTTPS URLS, add the following to your `Info.plist` file: + +```xml +NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSAllowsArbitraryLoadsForMedia + + +``` + +By default, iOS will mute your app's audio when your phone is switched to +silent mode. Depending on the requirements of your app, you can change the +default audio session category using `AudioPlayer.setIosCategory`. For example, +if you are writing a media app, Apple recommends that you set the category to +`AVAudioSessionCategoryPlayback`, which you can achieve by adding the following +code to your app's initialisation: + +```dart +AudioPlayer.setIosCategory(IosCategory.playback); +``` + +Note: If your app uses a number of different audio plugins in combination, e.g. +for audio recording, or text to speech, or background audio, it is possible +that those plugins may internally override the setting you choose here. You may +consider asking the developer of each other plugin you use to provide a similar +method so that you can configure the same audio session category universally +across all plugins you use. + +### MacOS + +To allow your MacOS application to access audio files on the Internet, add the following to your `DebugProfile.entitlements` and `Release.entitlements` files: + +```xml + com.apple.security.network.client + +``` + +If you wish to connect to non-HTTPS URLS, add the following to your `Info.plist` file: + +```xml +NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSAllowsArbitraryLoadsForMedia + + +``` diff --git a/just_audio/android/.gitignore b/just_audio/android/.gitignore new file mode 100644 index 0000000..c6cbe56 --- /dev/null +++ b/just_audio/android/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/just_audio/android/build.gradle b/just_audio/android/build.gradle new file mode 100644 index 0000000..d63baca --- /dev/null +++ b/just_audio/android/build.gradle @@ -0,0 +1,48 @@ +group 'com.ryanheise.just_audio' +version '1.0' + +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.6.3' + } +} + +rootProject.allprojects { + repositories { + google() + jcenter() + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 28 + + defaultConfig { + minSdkVersion 16 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + lintOptions { + disable 'InvalidPackage' + } + + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } +} + +dependencies { + implementation 'com.google.android.exoplayer:exoplayer-core:2.11.4' + implementation 'com.google.android.exoplayer:exoplayer-dash:2.11.4' + implementation 'com.google.android.exoplayer:exoplayer-hls:2.11.4' + implementation 'com.google.android.exoplayer:exoplayer-smoothstreaming:2.11.4' + compile files('libs/extension-flac.aar') +} diff --git a/just_audio/android/gradle.properties b/just_audio/android/gradle.properties new file mode 100644 index 0000000..38c8d45 --- /dev/null +++ b/just_audio/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.enableR8=true +android.useAndroidX=true +android.enableJetifier=true diff --git a/just_audio/android/gradle/wrapper/gradle-wrapper.properties b/just_audio/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..212deb2 --- /dev/null +++ b/just_audio/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Aug 10 13:15:44 CEST 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/just_audio/android/libs/extension-flac.aar b/just_audio/android/libs/extension-flac.aar new file mode 100644 index 0000000000000000000000000000000000000000..62d38a23b57acff92e5bd3e09a32f9dd5bc8f152 GIT binary patch literal 644206 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≤LnzkLMfI^ZW%NQzk}gQ!=j| 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

!Xn}kgG5a9f^q-5yO7ty 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�u0n(B)}k>iL^?CZyY%V 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

0ml^X!6@>{8A@wl;hD}s4Sm?u_9?t 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 L*i>@V`LeUG6;?ga%#wie>UppPiPfd>YHtt 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 Oy>vx + diff --git a/just_audio/android/src/main/java/com/ryanheise/just_audio/AudioPlayer.java b/just_audio/android/src/main/java/com/ryanheise/just_audio/AudioPlayer.java new file mode 100644 index 0000000..f3418f0 --- /dev/null +++ b/just_audio/android/src/main/java/com/ryanheise/just_audio/AudioPlayer.java @@ -0,0 +1,723 @@ +package com.ryanheise.just_audio; + +import android.content.Context; +import android.net.Uri; +import android.os.Handler; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.ExoPlaybackException; +import com.google.android.exoplayer2.PlaybackParameters; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.Timeline; +import com.google.android.exoplayer2.metadata.Metadata; +import com.google.android.exoplayer2.metadata.MetadataOutput; +import com.google.android.exoplayer2.metadata.icy.IcyHeaders; +import com.google.android.exoplayer2.metadata.icy.IcyInfo; +import com.google.android.exoplayer2.source.ClippingMediaSource; +import com.google.android.exoplayer2.source.ConcatenatingMediaSource; +import com.google.android.exoplayer2.source.LoopingMediaSource; +import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.ProgressiveMediaSource; +import com.google.android.exoplayer2.source.ShuffleOrder; +import com.google.android.exoplayer2.source.ShuffleOrder.DefaultShuffleOrder; +import com.google.android.exoplayer2.source.TrackGroup; +import com.google.android.exoplayer2.source.TrackGroupArray; +import com.google.android.exoplayer2.source.dash.DashMediaSource; +import com.google.android.exoplayer2.source.hls.HlsMediaSource; +import com.google.android.exoplayer2.trackselection.TrackSelectionArray; +import com.google.android.exoplayer2.upstream.DataSource; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; +import com.google.android.exoplayer2.upstream.DefaultHttpDataSource; +import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; +import com.google.android.exoplayer2.upstream.HttpDataSource; +import com.google.android.exoplayer2.util.Util; +import io.flutter.Log; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.EventChannel; +import io.flutter.plugin.common.EventChannel.EventSink; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.stream.Collectors; +import com.ryanheise.just_audio.DeezerDataSource; + +public class AudioPlayer implements MethodCallHandler, Player.EventListener, MetadataOutput { + + static final String TAG = "AudioPlayer"; + + private static Random random = new Random(); + + private final Context context; + private final MethodChannel methodChannel; + private final EventChannel eventChannel; + private EventSink eventSink; + + private ProcessingState processingState; + private long updateTime; + private long updatePosition; + private long bufferedPosition; + private long duration; + private Long start; + private Long end; + private Long seekPos; + private Result prepareResult; + private Result playResult; + private Result seekResult; + private boolean seekProcessed; + private boolean playing; + private Map mediaSources = new HashMap(); + private IcyInfo icyInfo; + private IcyHeaders icyHeaders; + private int errorCount; + + private SimpleExoPlayer player; + private MediaSource mediaSource; + private Integer currentIndex; + private Map loopingChildren = new HashMap<>(); + private Map loopingCounts = new HashMap<>(); + private final Handler handler = new Handler(); + private final Runnable bufferWatcher = new Runnable() { + @Override + public void run() { + if (player == null) { + return; + } + + long newBufferedPosition = player.getBufferedPosition(); + if (newBufferedPosition != bufferedPosition) { + bufferedPosition = newBufferedPosition; + broadcastPlaybackEvent(); + } + switch (processingState) { + case buffering: + handler.postDelayed(this, 200); + break; + case ready: + if (playing) { + handler.postDelayed(this, 500); + } else { + handler.postDelayed(this, 1000); + } + break; + } + } + }; + + private final Runnable onDispose; + + public AudioPlayer(final Context applicationContext, final BinaryMessenger messenger, + final String id, final Runnable onDispose) { + this.context = applicationContext; + this.onDispose = onDispose; + methodChannel = new MethodChannel(messenger, "com.ryanheise.just_audio.methods." + id); + methodChannel.setMethodCallHandler(this); + eventChannel = new EventChannel(messenger, "com.ryanheise.just_audio.events." + id); + eventChannel.setStreamHandler(new EventChannel.StreamHandler() { + @Override + public void onListen(final Object arguments, final EventSink eventSink) { + AudioPlayer.this.eventSink = eventSink; + } + + @Override + public void onCancel(final Object arguments) { + eventSink = null; + } + }); + processingState = ProcessingState.none; + } + + private void startWatchingBuffer() { + handler.removeCallbacks(bufferWatcher); + handler.post(bufferWatcher); + } + + @Override + public void onMetadata(Metadata metadata) { + for (int i = 0; i < metadata.length(); i++) { + final Metadata.Entry entry = metadata.get(i); + if (entry instanceof IcyInfo) { + icyInfo = (IcyInfo) entry; + broadcastPlaybackEvent(); + } + } + } + + @Override + public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { + for (int i = 0; i < trackGroups.length; i++) { + TrackGroup trackGroup = trackGroups.get(i); + + for (int j = 0; j < trackGroup.length; j++) { + Metadata metadata = trackGroup.getFormat(j).metadata; + + if (metadata != null) { + for (int k = 0; k < metadata.length(); k++) { + final Metadata.Entry entry = metadata.get(k); + if (entry instanceof IcyHeaders) { + icyHeaders = (IcyHeaders) entry; + broadcastPlaybackEvent(); + } + } + } + } + } + } + + @Override + public void onPositionDiscontinuity(int reason) { + switch (reason) { + case Player.DISCONTINUITY_REASON_PERIOD_TRANSITION: + case Player.DISCONTINUITY_REASON_SEEK: + onItemMayHaveChanged(); + break; + } + } + + @Override + public void onTimelineChanged(Timeline timeline, int reason) { + if (reason == Player.TIMELINE_CHANGE_REASON_DYNAMIC) { + onItemMayHaveChanged(); + } + } + + private void onItemMayHaveChanged() { + Integer newIndex = player.getCurrentWindowIndex(); + if (newIndex != currentIndex) { + currentIndex = newIndex; + } + broadcastPlaybackEvent(); + } + + @Override + public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { + switch (playbackState) { + case Player.STATE_READY: + if (prepareResult != null) { + duration = getDuration(); + transition(ProcessingState.ready); + prepareResult.success(duration); + prepareResult = null; + } else { + transition(ProcessingState.ready); + } + if (seekProcessed) { + completeSeek(); + } + break; + case Player.STATE_BUFFERING: + if (processingState != ProcessingState.buffering) { + transition(ProcessingState.buffering); + startWatchingBuffer(); + } + break; + case Player.STATE_ENDED: + if (processingState != ProcessingState.completed) { + transition(ProcessingState.completed); + } + if (playResult != null) { + playResult.success(null); + playResult = null; + } + break; + } + } + + @Override + public void onPlayerError(ExoPlaybackException error) { + switch (error.type) { + case ExoPlaybackException.TYPE_SOURCE: + Log.e(TAG, "TYPE_SOURCE: " + error.getSourceException().getMessage()); + break; + + case ExoPlaybackException.TYPE_RENDERER: + Log.e(TAG, "TYPE_RENDERER: " + error.getRendererException().getMessage()); + break; + + case ExoPlaybackException.TYPE_UNEXPECTED: + Log.e(TAG, "TYPE_UNEXPECTED: " + error.getUnexpectedException().getMessage()); + break; + + default: + Log.e(TAG, "default: " + error.getUnexpectedException().getMessage()); + } + sendError(String.valueOf(error.type), error.getMessage()); + errorCount++; + if (player.hasNext() && currentIndex != null && errorCount <= 5) { + int nextIndex = currentIndex + 1; + player.prepare(mediaSource); + player.seekTo(nextIndex, 0); + } + } + + @Override + public void onSeekProcessed() { + if (seekResult != null) { + seekProcessed = true; + if (player.getPlaybackState() == Player.STATE_READY) { + completeSeek(); + } + } + } + + private void completeSeek() { + seekProcessed = false; + seekPos = null; + seekResult.success(null); + seekResult = null; + } + + @Override + public void onMethodCall(final MethodCall call, final Result result) { + ensurePlayerInitialized(); + + final List args = (List) call.arguments; + try { + switch (call.method) { + case "load": + load(getAudioSource(args.get(0)), result); + break; + case "play": + play(result); + break; + case "pause": + pause(); + result.success(null); + break; + case "setVolume": + setVolume((float) ((double) ((Double) args.get(0)))); + result.success(null); + break; + case "setSpeed": + setSpeed((float) ((double) ((Double) args.get(0)))); + result.success(null); + break; + case "setLoopMode": + setLoopMode((Integer) args.get(0)); + result.success(null); + break; + case "setShuffleModeEnabled": + setShuffleModeEnabled((Boolean) args.get(0)); + result.success(null); + break; + case "setAutomaticallyWaitsToMinimizeStalling": + result.success(null); + break; + case "seek": + Long position = getLong(args.get(0)); + Integer index = (Integer)args.get(1); + seek(position == null ? C.TIME_UNSET : position, result, index); + break; + case "dispose": + dispose(); + result.success(null); + break; + case "concatenating.add": + concatenating(args.get(0)) + .addMediaSource(getAudioSource(args.get(1)), handler, () -> result.success(null)); + break; + case "concatenating.insert": + concatenating(args.get(0)) + .addMediaSource((Integer)args.get(1), getAudioSource(args.get(2)), handler, () -> result.success(null)); + break; + case "concatenating.addAll": + concatenating(args.get(0)) + .addMediaSources(getAudioSources(args.get(1)), handler, () -> result.success(null)); + break; + case "concatenating.insertAll": + concatenating(args.get(0)) + .addMediaSources((Integer)args.get(1), getAudioSources(args.get(2)), handler, () -> result.success(null)); + break; + case "concatenating.removeAt": + concatenating(args.get(0)) + .removeMediaSource((Integer)args.get(1), handler, () -> result.success(null)); + break; + case "concatenating.removeRange": + concatenating(args.get(0)) + .removeMediaSourceRange((Integer)args.get(1), (Integer)args.get(2), handler, () -> result.success(null)); + break; + case "concatenating.move": + concatenating(args.get(0)) + .moveMediaSource((Integer)args.get(1), (Integer)args.get(2), handler, () -> result.success(null)); + break; + case "concatenating.clear": + concatenating(args.get(0)).clear(handler, () -> result.success(null)); + break; + default: + result.notImplemented(); + break; + } + } catch (IllegalStateException e) { + e.printStackTrace(); + result.error("Illegal state: " + e.getMessage(), null, null); + } catch (Exception e) { + e.printStackTrace(); + result.error("Error: " + e, null, null); + } + } + + // Set the shuffle order for mediaSource, with currentIndex at + // the first position. Traverse the tree incrementing index at each + // node. + private int setShuffleOrder(MediaSource mediaSource, int index) { + if (mediaSource instanceof ConcatenatingMediaSource) { + final ConcatenatingMediaSource source = (ConcatenatingMediaSource)mediaSource; + // Find which child is current + Integer currentChildIndex = null; + for (int i = 0; i < source.getSize(); i++) { + final int indexBefore = index; + final MediaSource child = source.getMediaSource(i); + index = setShuffleOrder(child, index); + // If currentIndex falls within this child, make this child come first. + if (currentIndex >= indexBefore && currentIndex < index) { + currentChildIndex = i; + } + } + // Shuffle so that the current child is first in the shuffle order + source.setShuffleOrder(createShuffleOrder(source.getSize(), currentChildIndex)); + } else if (mediaSource instanceof LoopingMediaSource) { + final LoopingMediaSource source = (LoopingMediaSource)mediaSource; + // The ExoPlayer API doesn't provide accessors for these so we have + // to index them ourselves. + MediaSource child = loopingChildren.get(source); + int count = loopingCounts.get(source); + for (int i = 0; i < count; i++) { + index = setShuffleOrder(child, index); + } + } else { + // An actual media item takes up one spot in the playlist. + index++; + } + return index; + } + + private static int[] shuffle(int length, Integer firstIndex) { + final int[] shuffleOrder = new int[length]; + for (int i = 0; i < length; i++) { + final int j = random.nextInt(i + 1); + shuffleOrder[i] = shuffleOrder[j]; + shuffleOrder[j] = i; + } + if (firstIndex != null) { + for (int i = 1; i < length; i++) { + if (shuffleOrder[i] == firstIndex) { + final int v = shuffleOrder[0]; + shuffleOrder[0] = shuffleOrder[i]; + shuffleOrder[i] = v; + break; + } + } + } + return shuffleOrder; + } + + // Create a shuffle order optionally fixing the first index. + private ShuffleOrder createShuffleOrder(int length, Integer firstIndex) { + int[] shuffleIndices = shuffle(length, firstIndex); + return new DefaultShuffleOrder(shuffleIndices, random.nextLong()); + } + + private ConcatenatingMediaSource concatenating(final Object index) { + return (ConcatenatingMediaSource)mediaSources.get((String)index); + } + + private MediaSource getAudioSource(final Object json) { + Map map = (Map)json; + String id = (String)map.get("id"); + MediaSource mediaSource = mediaSources.get(id); + if (mediaSource == null) { + mediaSource = decodeAudioSource(map); + mediaSources.put(id, mediaSource); + } + return mediaSource; + } + + private MediaSource decodeAudioSource(final Object json) { + Map map = (Map)json; + String id = (String)map.get("id"); + switch ((String)map.get("type")) { + case "progressive": + Uri uri = Uri.parse((String)map.get("uri")); + //Deezer + if (uri.getHost().contains("dzcdn.net")) { + //Track id is stored in URL fragment (after #) + String fragment = uri.getFragment(); + uri = Uri.parse(((String)map.get("uri")).replace("#" + fragment, "")); + return new ProgressiveMediaSource.Factory( + () -> { + HttpDataSource deezerDataSource = new DeezerDataSource(fragment); + return deezerDataSource; + } + ).setTag(id).createMediaSource(uri); + } + + return new ProgressiveMediaSource.Factory(buildDataSourceFactory()) + .setTag(id) + .createMediaSource(uri); + case "dash": + return new DashMediaSource.Factory(buildDataSourceFactory()) + .setTag(id) + .createMediaSource(Uri.parse((String)map.get("uri"))); + case "hls": + return new HlsMediaSource.Factory(buildDataSourceFactory()) + .setTag(id) + .createMediaSource(Uri.parse((String)map.get("uri"))); + case "concatenating": + List audioSources = (List)map.get("audioSources"); + return new ConcatenatingMediaSource( + false, // isAtomic + (Boolean)map.get("useLazyPreparation"), + new DefaultShuffleOrder(audioSources.size()), + audioSources + .stream() + .map(s -> getAudioSource(s)) + .toArray(MediaSource[]::new)); + case "clipping": + Long start = getLong(map.get("start")); + Long end = getLong(map.get("end")); + return new ClippingMediaSource(getAudioSource(map.get("audioSource")), + (start != null ? start : 0) * 1000L, + (end != null ? end : C.TIME_END_OF_SOURCE) * 1000L); + case "looping": + Integer count = (Integer)map.get("count"); + MediaSource looperChild = getAudioSource(map.get("audioSource")); + LoopingMediaSource looper = new LoopingMediaSource(looperChild, count); + // TODO: store both in a single map + loopingChildren.put(looper, looperChild); + loopingCounts.put(looper, count); + return looper; + default: + throw new IllegalArgumentException("Unknown AudioSource type: " + map.get("type")); + } + } + + private List getAudioSources(final Object json) { + return ((List)json) + .stream() + .map(s -> getAudioSource(s)) + .collect(Collectors.toList()); + } + + private DataSource.Factory buildDataSourceFactory() { + String userAgent = Util.getUserAgent(context, "just_audio"); + DataSource.Factory httpDataSourceFactory = new DefaultHttpDataSourceFactory( + userAgent, + DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, + DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, + true + ); + return new DefaultDataSourceFactory(context, httpDataSourceFactory); + } + + private void load(final MediaSource mediaSource, final Result result) { + switch (processingState) { + case none: + break; + case loading: + abortExistingConnection(); + player.stop(); + break; + default: + player.stop(); + break; + } + errorCount = 0; + prepareResult = result; + transition(ProcessingState.loading); + if (player.getShuffleModeEnabled()) { + setShuffleOrder(mediaSource, 0); + } + this.mediaSource = mediaSource; + player.prepare(mediaSource); + } + + private void ensurePlayerInitialized() { + if (player == null) { + player = new SimpleExoPlayer.Builder(context).build(); + player.addMetadataOutput(this); + player.addListener(this); + } + } + + private void broadcastPlaybackEvent() { + final Map event = new HashMap(); + event.put("processingState", processingState.ordinal()); + event.put("updatePosition", updatePosition = getCurrentPosition()); + event.put("updateTime", updateTime = System.currentTimeMillis()); + event.put("bufferedPosition", Math.max(updatePosition, bufferedPosition)); + event.put("icyMetadata", collectIcyMetadata()); + event.put("duration", duration = getDuration()); + event.put("currentIndex", currentIndex); + + if (eventSink != null) { + eventSink.success(event); + } + } + + private Map collectIcyMetadata() { + final Map icyData = new HashMap<>(); + if (icyInfo != null) { + final Map info = new HashMap<>(); + info.put("title", icyInfo.title); + info.put("url", icyInfo.url); + icyData.put("info", info); + } + if (icyHeaders != null) { + final Map headers = new HashMap<>(); + headers.put("bitrate", icyHeaders.bitrate); + headers.put("genre", icyHeaders.genre); + headers.put("name", icyHeaders.name); + headers.put("metadataInterval", icyHeaders.metadataInterval); + headers.put("url", icyHeaders.url); + headers.put("isPublic", icyHeaders.isPublic); + icyData.put("headers", headers); + } + return icyData; + } + + private long getCurrentPosition() { + if (processingState == ProcessingState.none || processingState == ProcessingState.loading) { + return 0; + } else if (seekPos != null && seekPos != C.TIME_UNSET) { + return seekPos; + } else { + return player.getCurrentPosition(); + } + } + + private long getDuration() { + if (processingState == ProcessingState.none || processingState == ProcessingState.loading) { + return C.TIME_UNSET; + } else { + return player.getDuration(); + } + } + + private void sendError(String errorCode, String errorMsg) { + if (prepareResult != null) { + prepareResult.error(errorCode, errorMsg, null); + prepareResult = null; + } + + if (eventSink != null) { + eventSink.error(errorCode, errorMsg, null); + } + } + + private void transition(final ProcessingState newState) { + processingState = newState; + broadcastPlaybackEvent(); + } + + private String getLowerCaseExtension(Uri uri) { + // Until ExoPlayer provides automatic detection of media source types, we + // rely on the file extension. When this is absent, as a temporary + // workaround we allow the app to supply a fake extension in the URL + // fragment. e.g. https://somewhere.com/somestream?x=etc#.m3u8 + String fragment = uri.getFragment(); + String filename = fragment != null && fragment.contains(".") ? fragment : uri.getPath(); + return filename.replaceAll("^.*\\.", "").toLowerCase(); + } + + public void play(Result result) { + if (player.getPlayWhenReady()) return; + if (playResult != null) { + playResult.success(null); + } + playResult = result; + startWatchingBuffer(); + player.setPlayWhenReady(true); + if (processingState == ProcessingState.completed && playResult != null) { + playResult.success(null); + playResult = null; + } + } + + public void pause() { + if (!player.getPlayWhenReady()) return; + player.setPlayWhenReady(false); + if (playResult != null) { + playResult.success(null); + playResult = null; + } + } + + public void setVolume(final float volume) { + player.setVolume(volume); + } + + public void setSpeed(final float speed) { + player.setPlaybackParameters(new PlaybackParameters(speed)); + broadcastPlaybackEvent(); + } + + public void setLoopMode(final int mode) { + player.setRepeatMode(mode); + } + + public void setShuffleModeEnabled(final boolean enabled) { + if (enabled) { + setShuffleOrder(mediaSource, 0); + } + player.setShuffleModeEnabled(enabled); + } + + public void seek(final long position, final Result result, final Integer index) { + if (processingState == ProcessingState.none || processingState == ProcessingState.loading) { + return; + } + abortSeek(); + seekPos = position; + seekResult = result; + seekProcessed = false; + int windowIndex = index != null ? index : player.getCurrentWindowIndex(); + player.seekTo(windowIndex, position); + } + + public void dispose() { + mediaSources.clear(); + mediaSource = null; + loopingChildren.clear(); + if (player != null) { + player.release(); + player = null; + transition(ProcessingState.none); + } + if (eventSink != null) { + eventSink.endOfStream(); + } + onDispose.run(); + } + + private void abortSeek() { + if (seekResult != null) { + seekResult.success(null); + seekResult = null; + seekPos = null; + seekProcessed = false; + } + } + + private void abortExistingConnection() { + sendError("abort", "Connection aborted"); + } + + public static Long getLong(Object o) { + return (o == null || o instanceof Long) ? (Long)o : new Long(((Integer)o).intValue()); + } + + enum ProcessingState { + none, + loading, + buffering, + ready, + completed + } +} diff --git a/just_audio/android/src/main/java/com/ryanheise/just_audio/DeezerDataSource.java b/just_audio/android/src/main/java/com/ryanheise/just_audio/DeezerDataSource.java new file mode 100644 index 0000000..7b45092 --- /dev/null +++ b/just_audio/android/src/main/java/com/ryanheise/just_audio/DeezerDataSource.java @@ -0,0 +1,264 @@ +package com.ryanheise.just_audio; + +import android.net.Uri; +import android.util.Log; +import com.google.android.exoplayer2.upstream.DataSpec; +import com.google.android.exoplayer2.upstream.HttpDataSource; +import com.google.android.exoplayer2.upstream.TransferListener; +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; + +public class DeezerDataSource implements HttpDataSource { + HttpURLConnection connection; + InputStream inputStream; + int counter = 0; + byte[] key; + DataSpec dataSpec; + + //Quality fallback stuff + String trackId; + int quality = 0; + String md5origin; + String mediaVersion; + + public DeezerDataSource(String trackId) { + this.trackId = trackId; + this.key = getKey(trackId); + } + + @Override + public long open(DataSpec dataSpec) throws HttpDataSource.HttpDataSourceException { + this.dataSpec = dataSpec; + try { + //Check if real url or placeholder for quality fallback + URL url = new URL(dataSpec.uri.toString()); + String[] qp = url.getQuery().split("&"); + //Real deezcdn url doesnt have query params + if (qp.length >= 3) { + //Parse query parameters + for (int i = 0; i < qp.length; i++) { + String p = qp[i].replace("?", ""); + if (p.startsWith("md5")) { + this.md5origin = p.replace("md5=", ""); + } + if (p.startsWith("mv")) { + this.mediaVersion = p.replace("mv=", ""); + } + if (p.startsWith("q")) { + if (this.quality == 0) { + this.quality = Integer.parseInt(p.replace("q=", "")); + } + } + } + //Get real url + url = new URL(this.getTrackUrl(trackId, md5origin, mediaVersion, quality)); + } + + + this.connection = (HttpURLConnection) url.openConnection(); + this.connection.setChunkedStreamingMode(2048); + if (dataSpec.position > 0) { + this.counter = (int) (dataSpec.position/2048); + this.connection.setRequestProperty("Range", + "bytes=" + Long.toString(this.counter*2048) + "-"); + } + + InputStream is = this.connection.getInputStream(); + this.inputStream = new BufferedInputStream(new FilterInputStream(is) { + @Override + public int read(byte buffer[], int offset, int len) throws IOException { + byte[] b = new byte[2048]; + int t = 0; + int read = 0; + while (read != -1 && t != 2048) { + t += read = in.read(b, t, 2048-t); + } + + if (counter % 3 == 0) { + byte[] dec = decryptChunk(key, b); + System.arraycopy(dec, 0, buffer, offset, 2048); + } else { + System.arraycopy(b, 0, buffer, offset, 2048); + } + counter++; + + return t; + + } + },2048); + + + } catch (Exception e) { + //Quality fallback + if (this.quality == 1) { + Log.e("E", e.toString()); + throw new HttpDataSourceException("Error loading URL", dataSpec, HttpDataSourceException.TYPE_OPEN); + } + if (this.quality == 3) this.quality = 1; + if (this.quality == 9) this.quality = 3; + // r e c u r s i o n + return this.open(dataSpec); + } + String size = this.connection.getHeaderField("Content-Length"); + return Long.parseLong(size); + } + + @Override + public int read(byte[] buffer, int offset, int length) throws HttpDataSourceException { + int read = 0; + try { + read = this.inputStream.read(buffer, offset, length); + } catch (Exception e) { + Log.e("E", e.toString()); + //throw new HttpDataSourceException("Error reading from stream", this.dataSpec, HttpDataSourceException.TYPE_READ); + } + return read; + } + @Override + public void close() { + try { + if (this.inputStream != null) this.inputStream.close(); + if (this.connection != null) this.connection.disconnect(); + } catch (Exception e) { + Log.e("E", e.toString()); + } + } + + @Override + public void setRequestProperty(String name, String value) { + Log.d("D", "setRequestProperty"); + } + + @Override + public void clearRequestProperty(String name) { + Log.d("D", "clearRequestProperty"); + } + + @Override + public void clearAllRequestProperties() { + Log.d("D", "clearAllRequestProperties"); + } + + @Override + public int getResponseCode() { + Log.d("D", "getResponseCode"); + return 0; + } + + @Override + public Map> getResponseHeaders() { + return this.connection.getHeaderFields(); + } + + public final void addTransferListener(TransferListener transferListener) { + Log.d("D", "addTransferListener"); + } + + @Override + public Uri getUri() { + return Uri.parse(this.connection.getURL().toString()); + } + + public static String bytesToHex(byte[] bytes) { + final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); + char[] hexChars = new char[bytes.length * 2]; + for (int j = 0; j < bytes.length; j++) { + int v = bytes[j] & 0xFF; + hexChars[j * 2] = HEX_ARRAY[v >>> 4]; + hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; + } + return new String(hexChars); + } + + byte[] getKey(String id) { + String secret = "g4el58wc0zvf9na1"; + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(id.getBytes()); + byte[] md5id = md5.digest(); + String idmd5 = bytesToHex(md5id).toLowerCase(); + String key = ""; + for(int i=0; i<16; i++) { + int s0 = idmd5.charAt(i); + int s1 = idmd5.charAt(i+16); + int s2 = secret.charAt(i); + key += (char)(s0^s1^s2); + } + return key.getBytes(); + } catch (Exception e) { + Log.e("E", e.toString()); + return new byte[0]; + } + } + + + byte[] decryptChunk(byte[] key, byte[] data) { + try { + byte[] IV = {00, 01, 02, 03, 04, 05, 06, 07}; + SecretKeySpec Skey = new SecretKeySpec(key, "Blowfish"); + Cipher cipher = Cipher.getInstance("Blowfish/CBC/NoPadding"); + cipher.init(Cipher.DECRYPT_MODE, Skey, new javax.crypto.spec.IvParameterSpec(IV)); + return cipher.doFinal(data); + }catch (Exception e) { + Log.e("D", e.toString()); + return new byte[0]; + } + } + + public String getTrackUrl(String trackId, String md5origin, String mediaVersion, int quality) { + try { + int magic = 164; + + ByteArrayOutputStream step1 = new ByteArrayOutputStream(); + step1.write(md5origin.getBytes()); + step1.write(magic); + step1.write(Integer.toString(quality).getBytes()); + step1.write(magic); + step1.write(trackId.getBytes()); + step1.write(magic); + step1.write(mediaVersion.getBytes()); + //Get MD5 + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(step1.toByteArray()); + byte[] digest = md5.digest(); + String md5hex = bytesToHex(digest).toLowerCase(); + + ByteArrayOutputStream step2 = new ByteArrayOutputStream(); + step2.write(md5hex.getBytes()); + step2.write(magic); + step2.write(step1.toByteArray()); + step2.write(magic); + + //Pad step2 with dots, to get correct length + while(step2.size()%16 > 0) step2.write(46); + + //Prepare AES encryption + Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); + SecretKeySpec key = new SecretKeySpec("jo6aey6haid2Teih".getBytes(), "AES"); + cipher.init(Cipher.ENCRYPT_MODE, key); + //Encrypt + StringBuilder step3 = new StringBuilder(); + for (int i=0; i { + plugin.stopListening(); + return false; + }); + } + + @Override + public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { + startListening(binding.getApplicationContext(), binding.getBinaryMessenger()); + } + + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + stopListening(); + } + + private void startListening(Context applicationContext, BinaryMessenger messenger) { + methodCallHandler = new MainMethodCallHandler(applicationContext, messenger); + + channel = new MethodChannel(messenger, "com.ryanheise.just_audio.methods"); + channel.setMethodCallHandler(methodCallHandler); + } + + private void stopListening() { + methodCallHandler.dispose(); + methodCallHandler = null; + + channel.setMethodCallHandler(null); + } +} diff --git a/just_audio/android/src/main/java/com/ryanheise/just_audio/MainMethodCallHandler.java b/just_audio/android/src/main/java/com/ryanheise/just_audio/MainMethodCallHandler.java new file mode 100644 index 0000000..990a71a --- /dev/null +++ b/just_audio/android/src/main/java/com/ryanheise/just_audio/MainMethodCallHandler.java @@ -0,0 +1,52 @@ +package com.ryanheise.just_audio; + +import android.content.Context; +import androidx.annotation.NonNull; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; + +public class MainMethodCallHandler implements MethodCallHandler { + + private final Context applicationContext; + private final BinaryMessenger messenger; + + private final Map players = new HashMap<>(); + + public MainMethodCallHandler(Context applicationContext, + BinaryMessenger messenger) { + this.applicationContext = applicationContext; + this.messenger = messenger; + } + + @Override + public void onMethodCall(MethodCall call, @NonNull Result result) { + switch (call.method) { + case "init": + final List ids = call.arguments(); + String id = ids.get(0); + players.put(id, new AudioPlayer(applicationContext, messenger, id, + () -> players.remove(id) + )); + result.success(null); + break; + case "setIosCategory": + result.success(null); + break; + default: + result.notImplemented(); + break; + } + } + + void dispose() { + for (AudioPlayer player : new ArrayList(players.values())) { + player.dispose(); + } + } +} diff --git a/just_audio/darwin/Classes/AudioPlayer.m b/just_audio/darwin/Classes/AudioPlayer.m new file mode 100644 index 0000000..ccbfdea --- /dev/null +++ b/just_audio/darwin/Classes/AudioPlayer.m @@ -0,0 +1,1138 @@ +#import "AudioPlayer.h" +#import "AudioSource.h" +#import "IndexedAudioSource.h" +#import "UriAudioSource.h" +#import "ConcatenatingAudioSource.h" +#import "LoopingAudioSource.h" +#import "ClippingAudioSource.h" +#import +#import +#include + +// TODO: Check for and report invalid state transitions. +// TODO: Apply Apple's guidance on seeking: https://developer.apple.com/library/archive/qa/qa1820/_index.html +@implementation AudioPlayer { + NSObject* _registrar; + FlutterMethodChannel *_methodChannel; + FlutterEventChannel *_eventChannel; + FlutterEventSink _eventSink; + NSString *_playerId; + AVQueuePlayer *_player; + AudioSource *_audioSource; + NSMutableArray *_indexedAudioSources; + NSMutableArray *_order; + NSMutableArray *_orderInv; + int _index; + enum ProcessingState _processingState; + enum LoopMode _loopMode; + BOOL _shuffleModeEnabled; + long long _updateTime; + int _updatePosition; + int _lastPosition; + int _bufferedPosition; + // Set when the current item hasn't been played yet so we aren't sure whether sufficient audio has been buffered. + BOOL _bufferUnconfirmed; + CMTime _seekPos; + FlutterResult _loadResult; + FlutterResult _playResult; + id _timeObserver; + BOOL _automaticallyWaitsToMinimizeStalling; + BOOL _configuredSession; + BOOL _playing; +} + +- (instancetype)initWithRegistrar:(NSObject *)registrar playerId:(NSString*)idParam configuredSession:(BOOL)configuredSession { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + _registrar = registrar; + _playerId = idParam; + _configuredSession = configuredSession; + _methodChannel = + [FlutterMethodChannel methodChannelWithName:[NSMutableString stringWithFormat:@"com.ryanheise.just_audio.methods.%@", _playerId] + binaryMessenger:[registrar messenger]]; + _eventChannel = + [FlutterEventChannel eventChannelWithName:[NSMutableString stringWithFormat:@"com.ryanheise.just_audio.events.%@", _playerId] + binaryMessenger:[registrar messenger]]; + [_eventChannel setStreamHandler:self]; + _index = 0; + _processingState = none; + _loopMode = loopOff; + _shuffleModeEnabled = NO; + _player = nil; + _audioSource = nil; + _indexedAudioSources = nil; + _order = nil; + _orderInv = nil; + _seekPos = kCMTimeInvalid; + _timeObserver = 0; + _updatePosition = 0; + _updateTime = 0; + _lastPosition = 0; + _bufferedPosition = 0; + _bufferUnconfirmed = NO; + _playing = NO; + _loadResult = nil; + _playResult = nil; + _automaticallyWaitsToMinimizeStalling = YES; + __weak __typeof__(self) weakSelf = self; + [_methodChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { + [weakSelf handleMethodCall:call result:result]; + }]; + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { + NSArray* args = (NSArray*)call.arguments; + if ([@"load" isEqualToString:call.method]) { + [self load:args[0] result:result]; + } else if ([@"play" isEqualToString:call.method]) { + [self play:result]; + } else if ([@"pause" isEqualToString:call.method]) { + [self pause]; + result(nil); + } else if ([@"setVolume" isEqualToString:call.method]) { + [self setVolume:(float)[args[0] doubleValue]]; + result(nil); + } else if ([@"setSpeed" isEqualToString:call.method]) { + [self setSpeed:(float)[args[0] doubleValue]]; + result(nil); + } else if ([@"setLoopMode" isEqualToString:call.method]) { + [self setLoopMode:[args[0] intValue]]; + result(nil); + } else if ([@"setShuffleModeEnabled" isEqualToString:call.method]) { + [self setShuffleModeEnabled:(BOOL)[args[0] boolValue]]; + result(nil); + } else if ([@"setAutomaticallyWaitsToMinimizeStalling" isEqualToString:call.method]) { + [self setAutomaticallyWaitsToMinimizeStalling:(BOOL)[args[0] boolValue]]; + result(nil); + } else if ([@"seek" isEqualToString:call.method]) { + CMTime position = args[0] == [NSNull null] ? kCMTimePositiveInfinity : CMTimeMake([args[0] intValue], 1000); + [self seek:position index:args[1] completionHandler:^(BOOL finished) { + result(nil); + }]; + result(nil); + } else if ([@"dispose" isEqualToString:call.method]) { + [self dispose]; + result(nil); + } else if ([@"concatenating.add" isEqualToString:call.method]) { + [self concatenatingAdd:(NSString*)args[0] source:(NSDictionary*)args[1]]; + result(nil); + } else if ([@"concatenating.insert" isEqualToString:call.method]) { + [self concatenatingInsert:(NSString*)args[0] index:[args[1] intValue] source:(NSDictionary*)args[2]]; + result(nil); + } else if ([@"concatenating.addAll" isEqualToString:call.method]) { + [self concatenatingAddAll:(NSString*)args[0] sources:(NSArray*)args[1]]; + result(nil); + } else if ([@"concatenating.insertAll" isEqualToString:call.method]) { + [self concatenatingInsertAll:(NSString*)args[0] index:[args[1] intValue] sources:(NSArray*)args[2]]; + result(nil); + } else if ([@"concatenating.removeAt" isEqualToString:call.method]) { + [self concatenatingRemoveAt:(NSString*)args[0] index:(int)args[1]]; + result(nil); + } else if ([@"concatenating.removeRange" isEqualToString:call.method]) { + [self concatenatingRemoveRange:(NSString*)args[0] start:[args[1] intValue] end:[args[2] intValue]]; + result(nil); + } else if ([@"concatenating.move" isEqualToString:call.method]) { + [self concatenatingMove:(NSString*)args[0] currentIndex:[args[1] intValue] newIndex:[args[2] intValue]]; + result(nil); + } else if ([@"concatenating.clear" isEqualToString:call.method]) { + [self concatenatingClear:(NSString*)args[0]]; + result(nil); + } else { + result(FlutterMethodNotImplemented); + } +} + +// Untested +- (void)concatenatingAdd:(NSString *)catId source:(NSDictionary *)source { + [self concatenatingInsertAll:catId index:-1 sources:@[source]]; +} + +// Untested +- (void)concatenatingInsert:(NSString *)catId index:(int)index source:(NSDictionary *)source { + [self concatenatingInsertAll:catId index:index sources:@[source]]; +} + +// Untested +- (void)concatenatingAddAll:(NSString *)catId sources:(NSArray *)sources { + [self concatenatingInsertAll:catId index:-1 sources:sources]; +} + +// Untested +- (void)concatenatingInsertAll:(NSString *)catId index:(int)index sources:(NSArray *)sources { + // Find all duplicates of the identified ConcatenatingAudioSource. + NSMutableArray *matches = [[NSMutableArray alloc] init]; + [_audioSource findById:catId matches:matches]; + // Add each new source to each match. + for (int i = 0; i < matches.count; i++) { + ConcatenatingAudioSource *catSource = (ConcatenatingAudioSource *)matches[i]; + int idx = index >= 0 ? index : catSource.count; + NSMutableArray *audioSources = [self decodeAudioSources:sources]; + for (int j = 0; j < audioSources.count; j++) { + AudioSource *audioSource = audioSources[j]; + [catSource insertSource:audioSource atIndex:(idx + j)]; + } + } + // Index the new audio sources. + _indexedAudioSources = [[NSMutableArray alloc] init]; + [_audioSource buildSequence:_indexedAudioSources treeIndex:0]; + for (int i = 0; i < [_indexedAudioSources count]; i++) { + IndexedAudioSource *audioSource = _indexedAudioSources[i]; + if (!audioSource.isAttached) { + audioSource.playerItem.audioSource = audioSource; + [self addItemObservers:audioSource.playerItem]; + } + } + [self updateOrder]; + if (_player.currentItem) { + _index = [self indexForItem:_player.currentItem]; + } else { + _index = 0; + } + [self enqueueFrom:_index]; + // Notify each new IndexedAudioSource that it's been attached to the player. + for (int i = 0; i < [_indexedAudioSources count]; i++) { + if (!_indexedAudioSources[i].isAttached) { + [_indexedAudioSources[i] attach:_player]; + } + } + [self broadcastPlaybackEvent]; +} + +// Untested +- (void)concatenatingRemoveAt:(NSString *)catId index:(int)index { + [self concatenatingRemoveRange:catId start:index end:(index + 1)]; +} + +// Untested +- (void)concatenatingRemoveRange:(NSString *)catId start:(int)start end:(int)end { + // Find all duplicates of the identified ConcatenatingAudioSource. + NSMutableArray *matches = [[NSMutableArray alloc] init]; + [_audioSource findById:catId matches:matches]; + // Remove range from each match. + for (int i = 0; i < matches.count; i++) { + ConcatenatingAudioSource *catSource = (ConcatenatingAudioSource *)matches[i]; + int endIndex = end >= 0 ? end : catSource.count; + [catSource removeSourcesFromIndex:start toIndex:endIndex]; + } + // Re-index the remaining audio sources. + NSArray *oldIndexedAudioSources = _indexedAudioSources; + _indexedAudioSources = [[NSMutableArray alloc] init]; + [_audioSource buildSequence:_indexedAudioSources treeIndex:0]; + for (int i = 0, j = 0; i < _indexedAudioSources.count; i++, j++) { + IndexedAudioSource *audioSource = _indexedAudioSources[i]; + while (audioSource != oldIndexedAudioSources[j]) { + [self removeItemObservers:oldIndexedAudioSources[j].playerItem]; + if (j < _index) { + _index--; + } else if (j == _index) { + // The currently playing item was removed. + } + j++; + } + } + [self updateOrder]; + if (_index >= _indexedAudioSources.count) _index = _indexedAudioSources.count - 1; + if (_index < 0) _index = 0; + [self enqueueFrom:_index]; + [self broadcastPlaybackEvent]; +} + +// Untested +- (void)concatenatingMove:(NSString *)catId currentIndex:(int)currentIndex newIndex:(int)newIndex { + // Find all duplicates of the identified ConcatenatingAudioSource. + NSMutableArray *matches = [[NSMutableArray alloc] init]; + [_audioSource findById:catId matches:matches]; + // Move range within each match. + for (int i = 0; i < matches.count; i++) { + ConcatenatingAudioSource *catSource = (ConcatenatingAudioSource *)matches[i]; + [catSource moveSourceFromIndex:currentIndex toIndex:newIndex]; + } + // Re-index the audio sources. + _indexedAudioSources = [[NSMutableArray alloc] init]; + [_audioSource buildSequence:_indexedAudioSources treeIndex:0]; + _index = [self indexForItem:_player.currentItem]; + [self broadcastPlaybackEvent]; +} + +// Untested +- (void)concatenatingClear:(NSString *)catId { + [self concatenatingRemoveRange:catId start:0 end:-1]; +} + +- (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink { + _eventSink = eventSink; + return nil; +} + +- (FlutterError*)onCancelWithArguments:(id)arguments { + _eventSink = nil; + return nil; +} + +- (void)checkForDiscontinuity { + if (!_eventSink) return; + if (!_playing || CMTIME_IS_VALID(_seekPos) || _processingState == completed) return; + int position = [self getCurrentPosition]; + if (_processingState == buffering) { + if (position > _lastPosition) { + [self leaveBuffering:@"stall ended"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } else { + long long now = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0); + long long timeSinceLastUpdate = now - _updateTime; + long long expectedPosition = _updatePosition + (long long)(timeSinceLastUpdate * _player.rate); + long long drift = position - expectedPosition; + //NSLog(@"position: %d, drift: %lld", position, drift); + // Update if we've drifted or just started observing + if (_updateTime == 0L) { + [self broadcastPlaybackEvent]; + } else if (drift < -100) { + [self enterBuffering:@"stalling"]; + NSLog(@"Drift: %lld", drift); + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } + _lastPosition = position; +} + +- (void)enterBuffering:(NSString *)reason { + NSLog(@"ENTER BUFFERING: %@", reason); + _processingState = buffering; +} + +- (void)leaveBuffering:(NSString *)reason { + NSLog(@"LEAVE BUFFERING: %@", reason); + _processingState = ready; +} + +- (void)broadcastPlaybackEvent { + if (!_eventSink) return; + _eventSink(@{ + @"processingState": @(_processingState), + @"updatePosition": @(_updatePosition), + @"updateTime": @(_updateTime), + // TODO: buffer position + @"bufferedPosition": @(_updatePosition), + // TODO: Icy Metadata + @"icyMetadata": [NSNull null], + @"duration": @([self getDuration]), + @"currentIndex": @(_index), + }); +} + +- (int)getCurrentPosition { + if (_processingState == none || _processingState == loading) { + return 0; + } else if (CMTIME_IS_VALID(_seekPos)) { + return (int)(1000 * CMTimeGetSeconds(_seekPos)); + } else if (_indexedAudioSources) { + int ms = (int)(1000 * CMTimeGetSeconds(_indexedAudioSources[_index].position)); + if (ms < 0) ms = 0; + return ms; + } else { + return 0; + } +} + +- (int)getBufferedPosition { + if (_processingState == none || _processingState == loading) { + return 0; + } else if (_indexedAudioSources) { + int ms = (int)(1000 * CMTimeGetSeconds(_indexedAudioSources[_index].bufferedPosition)); + if (ms < 0) ms = 0; + return ms; + } else { + return 0; + } +} + +- (int)getDuration { + if (_processingState == none) { + return -1; + } else if (_indexedAudioSources) { + int v = (int)(1000 * CMTimeGetSeconds(_indexedAudioSources[_index].duration)); + return v; + } else { + return 0; + } +} + +- (void)removeItemObservers:(AVPlayerItem *)playerItem { + [playerItem removeObserver:self forKeyPath:@"status"]; + [playerItem removeObserver:self forKeyPath:@"playbackBufferEmpty"]; + [playerItem removeObserver:self forKeyPath:@"playbackBufferFull"]; + //[playerItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemPlaybackStalledNotification object:playerItem]; +} + +- (void)addItemObservers:(AVPlayerItem *)playerItem { + // Get notified when the item is loaded or had an error loading + [playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; + // Get notified of the buffer state + [playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; + [playerItem addObserver:self forKeyPath:@"playbackBufferFull" options:NSKeyValueObservingOptionNew context:nil]; + [playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; + //[playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; + // Get notified when playback has reached the end + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onComplete:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; + // Get notified when playback stops due to a failure (currently unused) + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFailToComplete:) name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem]; + // Get notified when playback stalls (currently unused) + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onItemStalled:) name:AVPlayerItemPlaybackStalledNotification object:playerItem]; +} + +- (NSMutableArray *)decodeAudioSources:(NSArray *)data { + NSMutableArray *array = [[NSMutableArray alloc] init]; + for (int i = 0; i < [data count]; i++) { + AudioSource *source = [self decodeAudioSource:data[i]]; + [array addObject:source]; + } + return array; +} + +- (AudioSource *)decodeAudioSource:(NSDictionary *)data { + NSString *type = data[@"type"]; + if ([@"progressive" isEqualToString:type]) { + return [[UriAudioSource alloc] initWithId:data[@"id"] uri:data[@"uri"]]; + } else if ([@"dash" isEqualToString:type]) { + return [[UriAudioSource alloc] initWithId:data[@"id"] uri:data[@"uri"]]; + } else if ([@"hls" isEqualToString:type]) { + return [[UriAudioSource alloc] initWithId:data[@"id"] uri:data[@"uri"]]; + } else if ([@"concatenating" isEqualToString:type]) { + return [[ConcatenatingAudioSource alloc] initWithId:data[@"id"] + audioSources:[self decodeAudioSources:data[@"audioSources"]]]; + } else if ([@"clipping" isEqualToString:type]) { + return [[ClippingAudioSource alloc] initWithId:data[@"id"] + audioSource:[self decodeAudioSource:data[@"audioSource"]] + start:data[@"start"] + end:data[@"end"]]; + } else if ([@"looping" isEqualToString:type]) { + NSMutableArray *childSources = [NSMutableArray new]; + int count = [data[@"count"] intValue]; + for (int i = 0; i < count; i++) { + [childSources addObject:[self decodeAudioSource:data[@"audioSource"]]]; + } + return [[LoopingAudioSource alloc] initWithId:data[@"id"] audioSources:childSources]; + } else { + return nil; + } +} + +- (void)enqueueFrom:(int)index { + int oldIndex = _index; + _index = index; + + // Update the queue while keeping the currently playing item untouched. + + /* NSLog(@"before reorder: _player.items.count: ", _player.items.count); */ + /* [self dumpQueue]; */ + + // First, remove all _player items except for the currently playing one (if any). + IndexedPlayerItem *oldItem = _player.currentItem; + IndexedPlayerItem *existingItem = nil; + NSArray *oldPlayerItems = [NSArray arrayWithArray:_player.items]; + // In the first pass, preserve the old and new items. + for (int i = 0; i < oldPlayerItems.count; i++) { + if (oldPlayerItems[i] == _indexedAudioSources[_index].playerItem) { + // Preserve and tag new item if it is already in the queue. + existingItem = oldPlayerItems[i]; + } else if (oldPlayerItems[i] == oldItem) { + // Temporarily preserve old item, just to avoid jumping to + // intermediate queue positions unnecessarily. We only want to jump + // once to _index. + } else { + [_player removeItem:oldPlayerItems[i]]; + } + } + // In the second pass, remove the old item (if different from new item). + if (_index != oldIndex) { + [_player removeItem:oldItem]; + } + + /* NSLog(@"inter order: _player.items.count: ", _player.items.count); */ + /* [self dumpQueue]; */ + + // Regenerate queue + BOOL include = NO; + for (int i = 0; i < [_order count]; i++) { + int si = [_order[i] intValue]; + if (si == _index) include = YES; + if (include && _indexedAudioSources[si].playerItem != existingItem) { + [_player insertItem:_indexedAudioSources[si].playerItem afterItem:nil]; + } + } + + /* NSLog(@"after reorder: _player.items.count: ", _player.items.count); */ + /* [self dumpQueue]; */ + + if (_processingState != loading && oldItem != _indexedAudioSources[_index].playerItem) { + // || !_player.currentItem.playbackLikelyToKeepUp; + if (_player.currentItem.playbackBufferEmpty) { + [self enterBuffering:@"enqueueFrom playbackBufferEmpty"]; + } else { + [self leaveBuffering:@"enqueueFrom !playbackBufferEmpty"]; + } + [self updatePosition]; + } +} + +- (void)updatePosition { + _updatePosition = [self getCurrentPosition]; + _updateTime = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0); +} + +- (void)load:(NSDictionary *)source result:(FlutterResult)result { + if (!_playing) { + [_player pause]; + } + if (_processingState == loading) { + [self abortExistingConnection]; + } + _loadResult = result; + _index = 0; + [self updatePosition]; + _processingState = loading; + [self broadcastPlaybackEvent]; + // Remove previous observers + if (_indexedAudioSources) { + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [self removeItemObservers:_indexedAudioSources[i].playerItem]; + } + } + // Decode audio source + if (_audioSource && [@"clipping" isEqualToString:source[@"type"]]) { + // Check if we're clipping an audio source that was previously loaded. + UriAudioSource *child = nil; + if ([_audioSource isKindOfClass:[ClippingAudioSource class]]) { + ClippingAudioSource *clipper = (ClippingAudioSource *)_audioSource; + child = clipper.audioSource; + } else if ([_audioSource isKindOfClass:[UriAudioSource class]]) { + child = (UriAudioSource *)_audioSource; + } + if (child) { + _audioSource = [[ClippingAudioSource alloc] initWithId:source[@"id"] + audioSource:child + start:source[@"start"] + end:source[@"end"]]; + } else { + _audioSource = [self decodeAudioSource:source]; + } + } else { + _audioSource = [self decodeAudioSource:source]; + } + _indexedAudioSources = [[NSMutableArray alloc] init]; + [_audioSource buildSequence:_indexedAudioSources treeIndex:0]; + for (int i = 0; i < [_indexedAudioSources count]; i++) { + IndexedAudioSource *source = _indexedAudioSources[i]; + [self addItemObservers:source.playerItem]; + source.playerItem.audioSource = source; + } + [self updateOrder]; + // Set up an empty player + if (!_player) { + _player = [[AVQueuePlayer alloc] initWithItems:@[]]; + if (@available(macOS 10.12, iOS 10.0, *)) { + _player.automaticallyWaitsToMinimizeStalling = _automaticallyWaitsToMinimizeStalling; + // TODO: Remove these observers in dispose. + [_player addObserver:self + forKeyPath:@"timeControlStatus" + options:NSKeyValueObservingOptionNew + context:nil]; + } + [_player addObserver:self + forKeyPath:@"currentItem" + options:NSKeyValueObservingOptionNew + context:nil]; + // TODO: learn about the different ways to define weakSelf. + //__weak __typeof__(self) weakSelf = self; + //typeof(self) __weak weakSelf = self; + __unsafe_unretained typeof(self) weakSelf = self; + if (@available(macOS 10.12, iOS 10.0, *)) {} + else { + _timeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMake(200, 1000) + queue:nil + usingBlock:^(CMTime time) { + [weakSelf checkForDiscontinuity]; + } + ]; + } + } + // Initialise the AVQueuePlayer with items. + [self enqueueFrom:0]; + // Notify each IndexedAudioSource that it's been attached to the player. + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [_indexedAudioSources[i] attach:_player]; + } + + if (_player.currentItem.status == AVPlayerItemStatusReadyToPlay) { + _loadResult(@([self getDuration])); + _loadResult = nil; + } else { + // We send result after the playerItem is ready in observeValueForKeyPath. + } + [self broadcastPlaybackEvent]; +} + +- (void)updateOrder { + if (_shuffleModeEnabled) { + [_audioSource shuffle:0 currentIndex: _index]; + } + _orderInv = [NSMutableArray arrayWithCapacity:[_indexedAudioSources count]]; + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [_orderInv addObject:@(0)]; + } + if (_shuffleModeEnabled) { + _order = [_audioSource getShuffleOrder]; + } else { + NSMutableArray *order = [[NSMutableArray alloc] init]; + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [order addObject:@(i)]; + } + _order = order; + } + for (int i = 0; i < [_indexedAudioSources count]; i++) { + _orderInv[[_order[i] intValue]] = @(i); + } +} + +- (void)onItemStalled:(NSNotification *)notification { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)notification.object; + NSLog(@"onItemStalled"); +} + +- (void)onFailToComplete:(NSNotification *)notification { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)notification.object; + NSLog(@"onFailToComplete"); +} + +- (void)onComplete:(NSNotification *)notification { + NSLog(@"onComplete"); + if (_loopMode == loopOne) { + [self seek:kCMTimeZero index:@(_index) completionHandler:^(BOOL finished) { + // XXX: Not necessary? + [self play]; + }]; + } else { + IndexedPlayerItem *endedPlayerItem = (IndexedPlayerItem *)notification.object; + IndexedAudioSource *endedSource = endedPlayerItem.audioSource; + // When an item ends, seek back to its beginning. + [endedSource seek:kCMTimeZero]; + + if ([_orderInv[_index] intValue] + 1 < [_order count]) { + // account for automatic move to next item + _index = [_order[[_orderInv[_index] intValue] + 1] intValue]; + NSLog(@"advance to next: index = %d", _index); + [self broadcastPlaybackEvent]; + } else { + // reached end of playlist + if (_loopMode == loopAll) { + NSLog(@"Loop back to first item"); + // Loop back to the beginning + // TODO: Currently there will be a gap at the loop point. + // Maybe we can do something clever by temporarily adding the + // first playlist item at the end of the queue, although this + // will affect any code that assumes the queue always + // corresponds to a contiguous region of the indexed audio + // sources. + // For now we just do a seek back to the start. + if ([_order count] == 1) { + [self seek:kCMTimeZero index:[NSNull null] completionHandler:^(BOOL finished) { + // XXX: Necessary? + [self play]; + }]; + } else { + [self seek:kCMTimeZero index:_order[0] completionHandler:^(BOOL finished) { + // XXX: Necessary? + [self play]; + }]; + } + } else { + [self complete]; + } + } + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + + if ([keyPath isEqualToString:@"status"]) { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)object; + AVPlayerItemStatus status = AVPlayerItemStatusUnknown; + NSNumber *statusNumber = change[NSKeyValueChangeNewKey]; + if ([statusNumber isKindOfClass:[NSNumber class]]) { + status = statusNumber.intValue; + } + switch (status) { + case AVPlayerItemStatusReadyToPlay: { + if (playerItem != _player.currentItem) return; + // Detect buffering in different ways depending on whether we're playing + if (_playing) { + if (@available(macOS 10.12, iOS 10.0, *)) { + if (_player.timeControlStatus == AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate) { + [self enterBuffering:@"ready to play: playing, waitingToPlay"]; + } else { + [self leaveBuffering:@"ready to play: playing, !waitingToPlay"]; + } + [self updatePosition]; + } else { + // If this happens when we're playing, check whether buffer is confirmed + if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { + // Stay in bufering - XXX Test + [self enterBuffering:@"ready to play: playing, bufferUnconfirmed && !playbackBufferFull"]; + } else { + if (_player.currentItem.playbackBufferEmpty) { + // !_player.currentItem.playbackLikelyToKeepUp; + [self enterBuffering:@"ready to play: playing, playbackBufferEmpty"]; + } else { + [self leaveBuffering:@"ready to play: playing, !playbackBufferEmpty"]; + } + [self updatePosition]; + } + } + } else { + if (_player.currentItem.playbackBufferEmpty) { + [self enterBuffering:@"ready to play: !playing, playbackBufferEmpty"]; + // || !_player.currentItem.playbackLikelyToKeepUp; + } else { + [self leaveBuffering:@"ready to play: !playing, !playbackBufferEmpty"]; + } + [self updatePosition]; + } + [self broadcastPlaybackEvent]; + if (_loadResult) { + _loadResult(@([self getDuration])); + _loadResult = nil; + } + break; + } + case AVPlayerItemStatusFailed: { + NSLog(@"AVPlayerItemStatusFailed"); + [self sendErrorForItem:playerItem]; + break; + } + case AVPlayerItemStatusUnknown: + break; + } + } else if ([keyPath isEqualToString:@"playbackBufferEmpty"] || [keyPath isEqualToString:@"playbackBufferFull"]) { + // Use these values to detect buffering. + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)object; + if (playerItem != _player.currentItem) return; + // If there's a seek in progress, these values are unreliable + if (CMTIME_IS_VALID(_seekPos)) return; + // Detect buffering in different ways depending on whether we're playing + if (_playing) { + if (@available(macOS 10.12, iOS 10.0, *)) { + // We handle this with timeControlStatus instead. + } else { + if (_bufferUnconfirmed && playerItem.playbackBufferFull) { + _bufferUnconfirmed = NO; + [self leaveBuffering:@"playing, _bufferUnconfirmed && playbackBufferFull"]; + [self updatePosition]; + NSLog(@"Buffering confirmed! leaving buffering"); + [self broadcastPlaybackEvent]; + } + } + } else { + if (playerItem.playbackBufferEmpty) { + [self enterBuffering:@"!playing, playbackBufferEmpty"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } else if (!playerItem.playbackBufferEmpty || playerItem.playbackBufferFull) { + _processingState = ready; + [self leaveBuffering:@"!playing, !playbackBufferEmpty || playbackBufferFull"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } + /* } else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) { */ + } else if ([keyPath isEqualToString:@"timeControlStatus"]) { + if (@available(macOS 10.12, iOS 10.0, *)) { + AVPlayerTimeControlStatus status = AVPlayerTimeControlStatusPaused; + NSNumber *statusNumber = change[NSKeyValueChangeNewKey]; + if ([statusNumber isKindOfClass:[NSNumber class]]) { + status = statusNumber.intValue; + } + switch (status) { + case AVPlayerTimeControlStatusPaused: + //NSLog(@"AVPlayerTimeControlStatusPaused"); + break; + case AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate: + //NSLog(@"AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate"); + if (_processingState != completed) { + [self enterBuffering:@"timeControlStatus"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } else { + NSLog(@"Ignoring wait signal because we reached the end"); + } + break; + case AVPlayerTimeControlStatusPlaying: + [self leaveBuffering:@"timeControlStatus"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + break; + } + } + } else if ([keyPath isEqualToString:@"currentItem"] && _player.currentItem) { + if (_player.currentItem.status == AVPlayerItemStatusFailed) { + if ([_orderInv[_index] intValue] + 1 < [_order count]) { + // account for automatic move to next item + _index = [_order[[_orderInv[_index] intValue] + 1] intValue]; + NSLog(@"advance to next on error: index = %d", _index); + [self broadcastPlaybackEvent]; + } else { + NSLog(@"error on last item"); + } + return; + } else { + int expectedIndex = [self indexForItem:_player.currentItem]; + if (_index != expectedIndex) { + // AVQueuePlayer will sometimes skip over error items without + // notifying this observer. + NSLog(@"Queue change detected. Adjusting index from %d -> %d", _index, expectedIndex); + _index = expectedIndex; + [self broadcastPlaybackEvent]; + } + } + //NSLog(@"currentItem changed. _index=%d", _index); + _bufferUnconfirmed = YES; + // If we've skipped or transitioned to a new item and we're not + // currently in the middle of a seek + if (CMTIME_IS_INVALID(_seekPos) && _player.currentItem.status == AVPlayerItemStatusReadyToPlay) { + [self updatePosition]; + IndexedAudioSource *source = ((IndexedPlayerItem *)_player.currentItem).audioSource; + // We should already be at position zero but for + // ClippingAudioSource it might be off by some milliseconds so we + // consider anything <= 100 as close enough. + if ((int)(1000 * CMTimeGetSeconds(source.position)) > 100) { + NSLog(@"On currentItem change, seeking back to zero"); + BOOL shouldResumePlayback = NO; + AVPlayerActionAtItemEnd originalEndAction = _player.actionAtItemEnd; + if (_playing && CMTimeGetSeconds(CMTimeSubtract(source.position, source.duration)) >= 0) { + NSLog(@"Need to pause while rewinding because we're at the end"); + shouldResumePlayback = YES; + _player.actionAtItemEnd = AVPlayerActionAtItemEndPause; + [_player pause]; + } + [self enterBuffering:@"currentItem changed, seeking"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + [source seek:kCMTimeZero completionHandler:^(BOOL finished) { + [self leaveBuffering:@"currentItem changed, finished seek"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + if (shouldResumePlayback) { + _player.actionAtItemEnd = originalEndAction; + // TODO: This logic is almost duplicated in seek. See if we can reuse this code. + [_player play]; + } + }]; + } else { + // Already at zero, no need to seek. + } + } + } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)object; + if (playerItem != _player.currentItem) return; + int pos = [self getBufferedPosition]; + if (pos != _bufferedPosition) { + _bufferedPosition = pos; + [self broadcastPlaybackEvent]; + } + } +} + +- (void)sendErrorForItem:(IndexedPlayerItem *)playerItem { + FlutterError *flutterError = [FlutterError errorWithCode:[NSString stringWithFormat:@"%d", playerItem.error.code] + message:playerItem.error.localizedDescription + details:nil]; + [self sendError:flutterError playerItem:playerItem]; +} + +- (void)sendError:(FlutterError *)flutterError playerItem:(IndexedPlayerItem *)playerItem { + NSLog(@"sendError"); + if (_loadResult && playerItem == _player.currentItem) { + _loadResult(flutterError); + _loadResult = nil; + } + if (_eventSink) { + // Broadcast all errors even if they aren't on the current item. + _eventSink(flutterError); + } +} + +- (void)abortExistingConnection { + FlutterError *flutterError = [FlutterError errorWithCode:@"abort" + message:@"Connection aborted" + details:nil]; + [self sendError:flutterError playerItem:nil]; +} + +- (int)indexForItem:(IndexedPlayerItem *)playerItem { + for (int i = 0; i < _indexedAudioSources.count; i++) { + if (_indexedAudioSources[i].playerItem == playerItem) { + return i; + } + } + return -1; +} + +- (void)play { + [self play:nil]; +} + +- (void)play:(FlutterResult)result { + if (result) { + if (_playResult) { + NSLog(@"INTERRUPTING PLAY"); + _playResult(nil); + } + _playResult = result; + } + _playing = YES; +#if TARGET_OS_IPHONE + if (_configuredSession) { + [[AVAudioSession sharedInstance] setActive:YES error:nil]; + } +#endif + [_player play]; + [self updatePosition]; + if (@available(macOS 10.12, iOS 10.0, *)) {} + else { + if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { + [self enterBuffering:@"play, _bufferUnconfirmed && !playbackBufferFull"]; + [self broadcastPlaybackEvent]; + } + } +} + +- (void)pause { + _playing = NO; + [_player pause]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + if (_playResult) { + NSLog(@"PLAY FINISHED DUE TO PAUSE"); + _playResult(nil); + _playResult = nil; + } +} + +- (void)complete { + [self updatePosition]; + _processingState = completed; + [self broadcastPlaybackEvent]; + if (_playResult) { + NSLog(@"PLAY FINISHED DUE TO COMPLETE"); + _playResult(nil); + _playResult = nil; + } +} + +- (void)setVolume:(float)volume { + [_player setVolume:volume]; +} + +- (void)setSpeed:(float)speed { + if (speed == 1.0 + || (speed < 1.0 && _player.currentItem.canPlaySlowForward) + || (speed > 1.0 && _player.currentItem.canPlayFastForward)) { + _player.rate = speed; + } + [self updatePosition]; +} + +- (void)setLoopMode:(int)loopMode { + _loopMode = loopMode; + if (_player) { + switch (_loopMode) { + case loopOne: + _player.actionAtItemEnd = AVPlayerActionAtItemEndPause; // AVPlayerActionAtItemEndNone + break; + default: + _player.actionAtItemEnd = AVPlayerActionAtItemEndAdvance; + } + } +} + +- (void)setShuffleModeEnabled:(BOOL)shuffleModeEnabled { + NSLog(@"setShuffleModeEnabled: %d", shuffleModeEnabled); + _shuffleModeEnabled = shuffleModeEnabled; + if (!_audioSource) return; + + [self updateOrder]; + + [self enqueueFrom:_index]; +} + +- (void)dumpQueue { + for (int i = 0; i < _player.items.count; i++) { + IndexedPlayerItem *playerItem = _player.items[i]; + for (int j = 0; j < _indexedAudioSources.count; j++) { + IndexedAudioSource *source = _indexedAudioSources[j]; + if (source.playerItem == playerItem) { + NSLog(@"- %d", j); + break; + } + } + } +} + +- (void)setAutomaticallyWaitsToMinimizeStalling:(bool)automaticallyWaitsToMinimizeStalling { + _automaticallyWaitsToMinimizeStalling = automaticallyWaitsToMinimizeStalling; + if (@available(macOS 10.12, iOS 10.0, *)) { + if(_player) { + _player.automaticallyWaitsToMinimizeStalling = automaticallyWaitsToMinimizeStalling; + } + } +} + +- (void)seek:(CMTime)position index:(NSNumber *)newIndex completionHandler:(void (^)(BOOL))completionHandler { + int index = _index; + if (newIndex != [NSNull null]) { + index = [newIndex intValue]; + } + if (index != _index) { + // Jump to a new item + /* if (_playing && index == _index + 1) { */ + /* // Special case for jumping to the very next item */ + /* NSLog(@"seek to next item: %d -> %d", _index, index); */ + /* [_indexedAudioSources[_index] seek:kCMTimeZero]; */ + /* _index = index; */ + /* [_player advanceToNextItem]; */ + /* [self broadcastPlaybackEvent]; */ + /* } else */ + { + // Jump to a distant item + //NSLog(@"seek# jump to distant item: %d -> %d", _index, index); + if (_playing) { + [_player pause]; + } + [_indexedAudioSources[_index] seek:kCMTimeZero]; + // The "currentItem" key observer will respect that a seek is already in progress + _seekPos = position; + [self updatePosition]; + [self enqueueFrom:index]; + IndexedAudioSource *source = _indexedAudioSources[_index]; + if (abs((int)(1000 * CMTimeGetSeconds(CMTimeSubtract(source.position, position)))) > 100) { + [self enterBuffering:@"seek to index"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + [source seek:position completionHandler:^(BOOL finished) { + if (@available(macOS 10.12, iOS 10.0, *)) { + if (_playing) { + // Handled by timeControlStatus + } else { + if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { + // Stay in buffering + } else if (source.playerItem.status == AVPlayerItemStatusReadyToPlay) { + [self leaveBuffering:@"seek to index finished, (!bufferUnconfirmed || playbackBufferFull) && ready to play"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } + } else { + if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { + // Stay in buffering + } else if (source.playerItem.status == AVPlayerItemStatusReadyToPlay) { + [self leaveBuffering:@"seek to index finished, (!bufferUnconfirmed || playbackBufferFull) && ready to play"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } + if (_playing) { + [_player play]; + } + _seekPos = kCMTimeInvalid; + [self broadcastPlaybackEvent]; + if (completionHandler) { + completionHandler(finished); + } + }]; + } else { + _seekPos = kCMTimeInvalid; + if (_playing) { + [_player play]; + } + } + } + } else { + // Seek within an item + if (_playing) { + [_player pause]; + } + _seekPos = position; + //NSLog(@"seek. enter buffering. pos = %d", (int)(1000*CMTimeGetSeconds(_indexedAudioSources[_index].position))); + // TODO: Move this into a separate method so it can also + // be used in skip. + [self enterBuffering:@"seek"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + [_indexedAudioSources[_index] seek:position completionHandler:^(BOOL finished) { + [self updatePosition]; + if (_playing) { + // If playing, buffering will be detected either by: + // 1. checkForDiscontinuity + // 2. timeControlStatus + [_player play]; + } else { + // If not playing, there is no reliable way to detect + // when buffering has completed, so we use + // !playbackBufferEmpty. Although this always seems to + // be full even right after a seek. + if (_player.currentItem.playbackBufferEmpty) { + [self enterBuffering:@"seek finished, playbackBufferEmpty"]; + } else { + [self leaveBuffering:@"seek finished, !playbackBufferEmpty"]; + } + [self updatePosition]; + if (_processingState != buffering) { + [self broadcastPlaybackEvent]; + } + } + _seekPos = kCMTimeInvalid; + [self broadcastPlaybackEvent]; + if (completionHandler) { + completionHandler(finished); + } + }]; + } +} + +- (void)dispose { + if (_processingState != none) { + [_player pause]; + _processingState = none; + [self broadcastPlaybackEvent]; + } + if (_timeObserver) { + [_player removeTimeObserver:_timeObserver]; + _timeObserver = 0; + } + if (_indexedAudioSources) { + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [self removeItemObservers:_indexedAudioSources[i].playerItem]; + } + } + if (_player) { + [_player removeObserver:self forKeyPath:@"currentItem"]; + if (@available(macOS 10.12, iOS 10.0, *)) { + [_player removeObserver:self forKeyPath:@"timeControlStatus"]; + } + _player = nil; + } + // Untested: + // [_eventChannel setStreamHandler:nil]; + // [_methodChannel setMethodHandler:nil]; +} + +@end diff --git a/just_audio/darwin/Classes/AudioSource.m b/just_audio/darwin/Classes/AudioSource.m new file mode 100644 index 0000000..81534f1 --- /dev/null +++ b/just_audio/darwin/Classes/AudioSource.m @@ -0,0 +1,37 @@ +#import "AudioSource.h" +#import + +@implementation AudioSource { + NSString *_sourceId; +} + +- (instancetype)initWithId:(NSString *)sid { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + _sourceId = sid; + return self; +} + +- (NSString *)sourceId { + return _sourceId; +} + +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex { + return 0; +} + +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches { + if ([_sourceId isEqualToString:sourceId]) { + [matches addObject:self]; + } +} + +- (NSArray *)getShuffleOrder { + return @[]; +} + +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex { + return 0; +} + +@end diff --git a/just_audio/darwin/Classes/ClippingAudioSource.m b/just_audio/darwin/Classes/ClippingAudioSource.m new file mode 100644 index 0000000..2f3b174 --- /dev/null +++ b/just_audio/darwin/Classes/ClippingAudioSource.m @@ -0,0 +1,79 @@ +#import "AudioSource.h" +#import "ClippingAudioSource.h" +#import "IndexedPlayerItem.h" +#import "UriAudioSource.h" +#import + +@implementation ClippingAudioSource { + UriAudioSource *_audioSource; + CMTime _start; + CMTime _end; +} + +- (instancetype)initWithId:(NSString *)sid audioSource:(UriAudioSource *)audioSource start:(NSNumber *)start end:(NSNumber *)end { + self = [super initWithId:sid]; + NSAssert(self, @"super init cannot be nil"); + _audioSource = audioSource; + _start = start == [NSNull null] ? kCMTimeZero : CMTimeMake([start intValue], 1000); + _end = end == [NSNull null] ? kCMTimeInvalid : CMTimeMake([end intValue], 1000); + return self; +} + +- (UriAudioSource *)audioSource { + return _audioSource; +} + +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches { + [super findById:sourceId matches:matches]; + [_audioSource findById:sourceId matches:matches]; +} + +- (void)attach:(AVQueuePlayer *)player { + [super attach:player]; + _audioSource.playerItem.forwardPlaybackEndTime = _end; + // XXX: Not needed since currentItem observer handles it? + [self seek:kCMTimeZero]; +} + +- (IndexedPlayerItem *)playerItem { + return _audioSource.playerItem; +} + +- (NSArray *)getShuffleOrder { + return @[@(0)]; +} + +- (void)play:(AVQueuePlayer *)player { +} + +- (void)pause:(AVQueuePlayer *)player { +} + +- (void)stop:(AVQueuePlayer *)player { +} + +- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler { + if (!completionHandler || (self.playerItem.status == AVPlayerItemStatusReadyToPlay)) { + CMTime absPosition = CMTimeAdd(_start, position); + [_audioSource.playerItem seekToTime:absPosition toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:completionHandler]; + } +} + +- (CMTime)duration { + return CMTimeSubtract(CMTIME_IS_INVALID(_end) ? self.playerItem.duration : _end, _start); +} + +- (void)setDuration:(CMTime)duration { +} + +- (CMTime)position { + return CMTimeSubtract(self.playerItem.currentTime, _start); +} + +- (CMTime)bufferedPosition { + CMTime pos = CMTimeSubtract(_audioSource.bufferedPosition, _start); + CMTime dur = [self duration]; + return CMTimeCompare(pos, dur) >= 0 ? dur : pos; +} + +@end diff --git a/just_audio/darwin/Classes/ConcatenatingAudioSource.m b/just_audio/darwin/Classes/ConcatenatingAudioSource.m new file mode 100644 index 0000000..bd7b713 --- /dev/null +++ b/just_audio/darwin/Classes/ConcatenatingAudioSource.m @@ -0,0 +1,109 @@ +#import "AudioSource.h" +#import "ConcatenatingAudioSource.h" +#import +#import + +@implementation ConcatenatingAudioSource { + NSMutableArray *_audioSources; + NSMutableArray *_shuffleOrder; +} + +- (instancetype)initWithId:(NSString *)sid audioSources:(NSMutableArray *)audioSources { + self = [super initWithId:sid]; + NSAssert(self, @"super init cannot be nil"); + _audioSources = audioSources; + return self; +} + +- (int)count { + return _audioSources.count; +} + +- (void)insertSource:(AudioSource *)audioSource atIndex:(int)index { + [_audioSources insertObject:audioSource atIndex:index]; +} + +- (void)removeSourcesFromIndex:(int)start toIndex:(int)end { + if (end == -1) end = _audioSources.count; + for (int i = start; i < end; i++) { + [_audioSources removeObjectAtIndex:start]; + } +} + +- (void)moveSourceFromIndex:(int)currentIndex toIndex:(int)newIndex { + AudioSource *source = _audioSources[currentIndex]; + [_audioSources removeObjectAtIndex:currentIndex]; + [_audioSources insertObject:source atIndex:newIndex]; +} + +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex { + for (int i = 0; i < [_audioSources count]; i++) { + treeIndex = [_audioSources[i] buildSequence:sequence treeIndex:treeIndex]; + } + return treeIndex; +} + +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches { + [super findById:sourceId matches:matches]; + for (int i = 0; i < [_audioSources count]; i++) { + [_audioSources[i] findById:sourceId matches:matches]; + } +} + +- (NSArray *)getShuffleOrder { + NSMutableArray *order = [NSMutableArray new]; + int offset = [order count]; + NSMutableArray *childOrders = [NSMutableArray new]; // array of array of ints + for (int i = 0; i < [_audioSources count]; i++) { + AudioSource *audioSource = _audioSources[i]; + NSArray *childShuffleOrder = [audioSource getShuffleOrder]; + NSMutableArray *offsetChildShuffleOrder = [NSMutableArray new]; + for (int j = 0; j < [childShuffleOrder count]; j++) { + [offsetChildShuffleOrder addObject:@([childShuffleOrder[j] integerValue] + offset)]; + } + [childOrders addObject:offsetChildShuffleOrder]; + offset += [childShuffleOrder count]; + } + for (int i = 0; i < [_audioSources count]; i++) { + [order addObjectsFromArray:childOrders[[_shuffleOrder[i] integerValue]]]; + } + return order; +} + +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex { + int currentChildIndex = -1; + for (int i = 0; i < [_audioSources count]; i++) { + int indexBefore = treeIndex; + AudioSource *child = _audioSources[i]; + treeIndex = [child shuffle:treeIndex currentIndex:currentIndex]; + if (currentIndex >= indexBefore && currentIndex < treeIndex) { + currentChildIndex = i; + } else {} + } + // Shuffle so that the current child is first in the shuffle order + _shuffleOrder = [NSMutableArray arrayWithCapacity:[_audioSources count]]; + for (int i = 0; i < [_audioSources count]; i++) { + [_shuffleOrder addObject:@(0)]; + } + NSLog(@"shuffle: audioSources.count=%d and shuffleOrder.count=%d", [_audioSources count], [_shuffleOrder count]); + // First generate a random shuffle + for (int i = 0; i < [_audioSources count]; i++) { + int j = arc4random_uniform(i + 1); + _shuffleOrder[i] = _shuffleOrder[j]; + _shuffleOrder[j] = @(i); + } + // Then bring currentIndex to the front + if (currentChildIndex != -1) { + for (int i = 1; i < [_audioSources count]; i++) { + if ([_shuffleOrder[i] integerValue] == currentChildIndex) { + NSNumber *v = _shuffleOrder[0]; + _shuffleOrder[0] = _shuffleOrder[i]; + _shuffleOrder[i] = v; + break; + } + } + } + return treeIndex; +} + +@end diff --git a/just_audio/darwin/Classes/IndexedAudioSource.m b/just_audio/darwin/Classes/IndexedAudioSource.m new file mode 100644 index 0000000..316f900 --- /dev/null +++ b/just_audio/darwin/Classes/IndexedAudioSource.m @@ -0,0 +1,68 @@ +#import "IndexedAudioSource.h" +#import "IndexedPlayerItem.h" +#import + +@implementation IndexedAudioSource { + BOOL _isAttached; +} + +- (instancetype)initWithId:(NSString *)sid { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + _isAttached = NO; + return self; +} + +- (IndexedPlayerItem *)playerItem { + return nil; +} + +- (BOOL)isAttached { + return _isAttached; +} + +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex { + [sequence addObject:self]; + return treeIndex + 1; +} + +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex { + return treeIndex + 1; +} + +- (void)attach:(AVQueuePlayer *)player { + _isAttached = YES; +} + +- (void)play:(AVQueuePlayer *)player { +} + +- (void)pause:(AVQueuePlayer *)player { +} + +- (void)stop:(AVQueuePlayer *)player { +} + +- (void)seek:(CMTime)position { + [self seek:position completionHandler:nil]; +} + +- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler { +} + +- (CMTime)duration { + return kCMTimeInvalid; +} + +- (void)setDuration:(CMTime)duration { +} + +- (CMTime)position { + return kCMTimeInvalid; +} + +- (CMTime)bufferedPosition { + return kCMTimeInvalid; +} + +@end diff --git a/just_audio/darwin/Classes/IndexedPlayerItem.m b/just_audio/darwin/Classes/IndexedPlayerItem.m new file mode 100644 index 0000000..87fafe0 --- /dev/null +++ b/just_audio/darwin/Classes/IndexedPlayerItem.m @@ -0,0 +1,16 @@ +#import "IndexedPlayerItem.h" +#import "IndexedAudioSource.h" + +@implementation IndexedPlayerItem { + IndexedAudioSource *_audioSource; +} + +-(void)setAudioSource:(IndexedAudioSource *)audioSource { + _audioSource = audioSource; +} + +-(IndexedAudioSource *)audioSource { + return _audioSource; +} + +@end diff --git a/just_audio/darwin/Classes/JustAudioPlugin.m b/just_audio/darwin/Classes/JustAudioPlugin.m new file mode 100644 index 0000000..982a260 --- /dev/null +++ b/just_audio/darwin/Classes/JustAudioPlugin.m @@ -0,0 +1,55 @@ +#import "JustAudioPlugin.h" +#import "AudioPlayer.h" +#import +#include + +@implementation JustAudioPlugin { + NSObject* _registrar; + BOOL _configuredSession; +} + ++ (void)registerWithRegistrar:(NSObject*)registrar { + FlutterMethodChannel* channel = [FlutterMethodChannel + methodChannelWithName:@"com.ryanheise.just_audio.methods" + binaryMessenger:[registrar messenger]]; + JustAudioPlugin* instance = [[JustAudioPlugin alloc] initWithRegistrar:registrar]; + [registrar addMethodCallDelegate:instance channel:channel]; +} + +- (instancetype)initWithRegistrar:(NSObject *)registrar { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + _registrar = registrar; + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { + if ([@"init" isEqualToString:call.method]) { + NSArray* args = (NSArray*)call.arguments; + NSString* playerId = args[0]; + /*AudioPlayer* player =*/ [[AudioPlayer alloc] initWithRegistrar:_registrar playerId:playerId configuredSession:_configuredSession]; + result(nil); + } else if ([@"setIosCategory" isEqualToString:call.method]) { +#if TARGET_OS_IPHONE + NSNumber* categoryIndex = (NSNumber*)call.arguments; + AVAudioSessionCategory category = nil; + switch (categoryIndex.integerValue) { + case 0: category = AVAudioSessionCategoryAmbient; break; + case 1: category = AVAudioSessionCategorySoloAmbient; break; + case 2: category = AVAudioSessionCategoryPlayback; break; + case 3: category = AVAudioSessionCategoryRecord; break; + case 4: category = AVAudioSessionCategoryPlayAndRecord; break; + case 5: category = AVAudioSessionCategoryMultiRoute; break; + } + if (category) { + _configuredSession = YES; + } + [[AVAudioSession sharedInstance] setCategory:category error:nil]; +#endif + result(nil); + } else { + result(FlutterMethodNotImplemented); + } +} + +@end diff --git a/just_audio/darwin/Classes/LoopingAudioSource.m b/just_audio/darwin/Classes/LoopingAudioSource.m new file mode 100644 index 0000000..ba4b52b --- /dev/null +++ b/just_audio/darwin/Classes/LoopingAudioSource.m @@ -0,0 +1,53 @@ +#import "AudioSource.h" +#import "LoopingAudioSource.h" +#import + +@implementation LoopingAudioSource { + // An array of duplicates + NSArray *_audioSources; // +} + +- (instancetype)initWithId:(NSString *)sid audioSources:(NSArray *)audioSources { + self = [super initWithId:sid]; + NSAssert(self, @"super init cannot be nil"); + _audioSources = audioSources; + return self; +} + +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex { + for (int i = 0; i < [_audioSources count]; i++) { + treeIndex = [_audioSources[i] buildSequence:sequence treeIndex:treeIndex]; + } + return treeIndex; +} + +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches { + [super findById:sourceId matches:matches]; + for (int i = 0; i < [_audioSources count]; i++) { + [_audioSources[i] findById:sourceId matches:matches]; + } +} + +- (NSArray *)getShuffleOrder { + NSMutableArray *order = [NSMutableArray new]; + int offset = (int)[order count]; + for (int i = 0; i < [_audioSources count]; i++) { + AudioSource *audioSource = _audioSources[i]; + NSArray *childShuffleOrder = [audioSource getShuffleOrder]; + for (int j = 0; j < [childShuffleOrder count]; j++) { + [order addObject:@([childShuffleOrder[j] integerValue] + offset)]; + } + offset += [childShuffleOrder count]; + } + return order; +} + +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex { + // TODO: This should probably shuffle the same way on all duplicates. + for (int i = 0; i < [_audioSources count]; i++) { + treeIndex = [_audioSources[i] shuffle:treeIndex currentIndex:currentIndex]; + } + return treeIndex; +} + +@end diff --git a/just_audio/darwin/Classes/UriAudioSource.m b/just_audio/darwin/Classes/UriAudioSource.m new file mode 100644 index 0000000..91321d4 --- /dev/null +++ b/just_audio/darwin/Classes/UriAudioSource.m @@ -0,0 +1,79 @@ +#import "UriAudioSource.h" +#import "IndexedAudioSource.h" +#import "IndexedPlayerItem.h" +#import + +@implementation UriAudioSource { + NSString *_uri; + IndexedPlayerItem *_playerItem; + /* CMTime _duration; */ +} + +- (instancetype)initWithId:(NSString *)sid uri:(NSString *)uri { + self = [super initWithId:sid]; + NSAssert(self, @"super init cannot be nil"); + _uri = uri; + if ([_uri hasPrefix:@"file://"]) { + _playerItem = [[IndexedPlayerItem alloc] initWithURL:[NSURL fileURLWithPath:[_uri substringFromIndex:7]]]; + } else { + _playerItem = [[IndexedPlayerItem alloc] initWithURL:[NSURL URLWithString:_uri]]; + } + if (@available(macOS 10.13, iOS 11.0, *)) { + // This does the best at reducing distortion on voice with speeds below 1.0 + _playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmTimeDomain; + } + /* NSKeyValueObservingOptions options = */ + /* NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew; */ + /* [_playerItem addObserver:self */ + /* forKeyPath:@"duration" */ + /* options:options */ + /* context:nil]; */ + return self; +} + +- (IndexedPlayerItem *)playerItem { + return _playerItem; +} + +- (NSArray *)getShuffleOrder { + return @[@(0)]; +} + +- (void)play:(AVQueuePlayer *)player { +} + +- (void)pause:(AVQueuePlayer *)player { +} + +- (void)stop:(AVQueuePlayer *)player { +} + +- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler { + if (!completionHandler || (_playerItem.status == AVPlayerItemStatusReadyToPlay)) { + [_playerItem seekToTime:position toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:completionHandler]; + } +} + +- (CMTime)duration { + return _playerItem.duration; +} + +- (void)setDuration:(CMTime)duration { +} + +- (CMTime)position { + return _playerItem.currentTime; +} + +- (CMTime)bufferedPosition { + NSValue *last = _playerItem.loadedTimeRanges.lastObject; + if (last) { + CMTimeRange timeRange = [last CMTimeRangeValue]; + return CMTimeAdd(timeRange.start, timeRange.duration); + } else { + return _playerItem.currentTime; + } + return kCMTimeInvalid; +} + +@end diff --git a/just_audio/ios/.gitignore b/just_audio/ios/.gitignore new file mode 100644 index 0000000..aa479fd --- /dev/null +++ b/just_audio/ios/.gitignore @@ -0,0 +1,37 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/Generated.xcconfig +/Flutter/flutter_export_environment.sh \ No newline at end of file diff --git a/just_audio/ios/Assets/.gitkeep b/just_audio/ios/Assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/just_audio/ios/Classes/AudioPlayer.h b/just_audio/ios/Classes/AudioPlayer.h new file mode 100644 index 0000000..1a985f3 --- /dev/null +++ b/just_audio/ios/Classes/AudioPlayer.h @@ -0,0 +1,21 @@ +#import + +@interface AudioPlayer : NSObject + +- (instancetype)initWithRegistrar:(NSObject *)registrar playerId:(NSString*)idParam configuredSession:(BOOL)configuredSession; + +@end + +enum ProcessingState { + none, + loading, + buffering, + ready, + completed +}; + +enum LoopMode { + loopOff, + loopOne, + loopAll +}; diff --git a/just_audio/ios/Classes/AudioPlayer.m b/just_audio/ios/Classes/AudioPlayer.m new file mode 100644 index 0000000..ccbfdea --- /dev/null +++ b/just_audio/ios/Classes/AudioPlayer.m @@ -0,0 +1,1138 @@ +#import "AudioPlayer.h" +#import "AudioSource.h" +#import "IndexedAudioSource.h" +#import "UriAudioSource.h" +#import "ConcatenatingAudioSource.h" +#import "LoopingAudioSource.h" +#import "ClippingAudioSource.h" +#import +#import +#include + +// TODO: Check for and report invalid state transitions. +// TODO: Apply Apple's guidance on seeking: https://developer.apple.com/library/archive/qa/qa1820/_index.html +@implementation AudioPlayer { + NSObject* _registrar; + FlutterMethodChannel *_methodChannel; + FlutterEventChannel *_eventChannel; + FlutterEventSink _eventSink; + NSString *_playerId; + AVQueuePlayer *_player; + AudioSource *_audioSource; + NSMutableArray *_indexedAudioSources; + NSMutableArray *_order; + NSMutableArray *_orderInv; + int _index; + enum ProcessingState _processingState; + enum LoopMode _loopMode; + BOOL _shuffleModeEnabled; + long long _updateTime; + int _updatePosition; + int _lastPosition; + int _bufferedPosition; + // Set when the current item hasn't been played yet so we aren't sure whether sufficient audio has been buffered. + BOOL _bufferUnconfirmed; + CMTime _seekPos; + FlutterResult _loadResult; + FlutterResult _playResult; + id _timeObserver; + BOOL _automaticallyWaitsToMinimizeStalling; + BOOL _configuredSession; + BOOL _playing; +} + +- (instancetype)initWithRegistrar:(NSObject *)registrar playerId:(NSString*)idParam configuredSession:(BOOL)configuredSession { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + _registrar = registrar; + _playerId = idParam; + _configuredSession = configuredSession; + _methodChannel = + [FlutterMethodChannel methodChannelWithName:[NSMutableString stringWithFormat:@"com.ryanheise.just_audio.methods.%@", _playerId] + binaryMessenger:[registrar messenger]]; + _eventChannel = + [FlutterEventChannel eventChannelWithName:[NSMutableString stringWithFormat:@"com.ryanheise.just_audio.events.%@", _playerId] + binaryMessenger:[registrar messenger]]; + [_eventChannel setStreamHandler:self]; + _index = 0; + _processingState = none; + _loopMode = loopOff; + _shuffleModeEnabled = NO; + _player = nil; + _audioSource = nil; + _indexedAudioSources = nil; + _order = nil; + _orderInv = nil; + _seekPos = kCMTimeInvalid; + _timeObserver = 0; + _updatePosition = 0; + _updateTime = 0; + _lastPosition = 0; + _bufferedPosition = 0; + _bufferUnconfirmed = NO; + _playing = NO; + _loadResult = nil; + _playResult = nil; + _automaticallyWaitsToMinimizeStalling = YES; + __weak __typeof__(self) weakSelf = self; + [_methodChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { + [weakSelf handleMethodCall:call result:result]; + }]; + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { + NSArray* args = (NSArray*)call.arguments; + if ([@"load" isEqualToString:call.method]) { + [self load:args[0] result:result]; + } else if ([@"play" isEqualToString:call.method]) { + [self play:result]; + } else if ([@"pause" isEqualToString:call.method]) { + [self pause]; + result(nil); + } else if ([@"setVolume" isEqualToString:call.method]) { + [self setVolume:(float)[args[0] doubleValue]]; + result(nil); + } else if ([@"setSpeed" isEqualToString:call.method]) { + [self setSpeed:(float)[args[0] doubleValue]]; + result(nil); + } else if ([@"setLoopMode" isEqualToString:call.method]) { + [self setLoopMode:[args[0] intValue]]; + result(nil); + } else if ([@"setShuffleModeEnabled" isEqualToString:call.method]) { + [self setShuffleModeEnabled:(BOOL)[args[0] boolValue]]; + result(nil); + } else if ([@"setAutomaticallyWaitsToMinimizeStalling" isEqualToString:call.method]) { + [self setAutomaticallyWaitsToMinimizeStalling:(BOOL)[args[0] boolValue]]; + result(nil); + } else if ([@"seek" isEqualToString:call.method]) { + CMTime position = args[0] == [NSNull null] ? kCMTimePositiveInfinity : CMTimeMake([args[0] intValue], 1000); + [self seek:position index:args[1] completionHandler:^(BOOL finished) { + result(nil); + }]; + result(nil); + } else if ([@"dispose" isEqualToString:call.method]) { + [self dispose]; + result(nil); + } else if ([@"concatenating.add" isEqualToString:call.method]) { + [self concatenatingAdd:(NSString*)args[0] source:(NSDictionary*)args[1]]; + result(nil); + } else if ([@"concatenating.insert" isEqualToString:call.method]) { + [self concatenatingInsert:(NSString*)args[0] index:[args[1] intValue] source:(NSDictionary*)args[2]]; + result(nil); + } else if ([@"concatenating.addAll" isEqualToString:call.method]) { + [self concatenatingAddAll:(NSString*)args[0] sources:(NSArray*)args[1]]; + result(nil); + } else if ([@"concatenating.insertAll" isEqualToString:call.method]) { + [self concatenatingInsertAll:(NSString*)args[0] index:[args[1] intValue] sources:(NSArray*)args[2]]; + result(nil); + } else if ([@"concatenating.removeAt" isEqualToString:call.method]) { + [self concatenatingRemoveAt:(NSString*)args[0] index:(int)args[1]]; + result(nil); + } else if ([@"concatenating.removeRange" isEqualToString:call.method]) { + [self concatenatingRemoveRange:(NSString*)args[0] start:[args[1] intValue] end:[args[2] intValue]]; + result(nil); + } else if ([@"concatenating.move" isEqualToString:call.method]) { + [self concatenatingMove:(NSString*)args[0] currentIndex:[args[1] intValue] newIndex:[args[2] intValue]]; + result(nil); + } else if ([@"concatenating.clear" isEqualToString:call.method]) { + [self concatenatingClear:(NSString*)args[0]]; + result(nil); + } else { + result(FlutterMethodNotImplemented); + } +} + +// Untested +- (void)concatenatingAdd:(NSString *)catId source:(NSDictionary *)source { + [self concatenatingInsertAll:catId index:-1 sources:@[source]]; +} + +// Untested +- (void)concatenatingInsert:(NSString *)catId index:(int)index source:(NSDictionary *)source { + [self concatenatingInsertAll:catId index:index sources:@[source]]; +} + +// Untested +- (void)concatenatingAddAll:(NSString *)catId sources:(NSArray *)sources { + [self concatenatingInsertAll:catId index:-1 sources:sources]; +} + +// Untested +- (void)concatenatingInsertAll:(NSString *)catId index:(int)index sources:(NSArray *)sources { + // Find all duplicates of the identified ConcatenatingAudioSource. + NSMutableArray *matches = [[NSMutableArray alloc] init]; + [_audioSource findById:catId matches:matches]; + // Add each new source to each match. + for (int i = 0; i < matches.count; i++) { + ConcatenatingAudioSource *catSource = (ConcatenatingAudioSource *)matches[i]; + int idx = index >= 0 ? index : catSource.count; + NSMutableArray *audioSources = [self decodeAudioSources:sources]; + for (int j = 0; j < audioSources.count; j++) { + AudioSource *audioSource = audioSources[j]; + [catSource insertSource:audioSource atIndex:(idx + j)]; + } + } + // Index the new audio sources. + _indexedAudioSources = [[NSMutableArray alloc] init]; + [_audioSource buildSequence:_indexedAudioSources treeIndex:0]; + for (int i = 0; i < [_indexedAudioSources count]; i++) { + IndexedAudioSource *audioSource = _indexedAudioSources[i]; + if (!audioSource.isAttached) { + audioSource.playerItem.audioSource = audioSource; + [self addItemObservers:audioSource.playerItem]; + } + } + [self updateOrder]; + if (_player.currentItem) { + _index = [self indexForItem:_player.currentItem]; + } else { + _index = 0; + } + [self enqueueFrom:_index]; + // Notify each new IndexedAudioSource that it's been attached to the player. + for (int i = 0; i < [_indexedAudioSources count]; i++) { + if (!_indexedAudioSources[i].isAttached) { + [_indexedAudioSources[i] attach:_player]; + } + } + [self broadcastPlaybackEvent]; +} + +// Untested +- (void)concatenatingRemoveAt:(NSString *)catId index:(int)index { + [self concatenatingRemoveRange:catId start:index end:(index + 1)]; +} + +// Untested +- (void)concatenatingRemoveRange:(NSString *)catId start:(int)start end:(int)end { + // Find all duplicates of the identified ConcatenatingAudioSource. + NSMutableArray *matches = [[NSMutableArray alloc] init]; + [_audioSource findById:catId matches:matches]; + // Remove range from each match. + for (int i = 0; i < matches.count; i++) { + ConcatenatingAudioSource *catSource = (ConcatenatingAudioSource *)matches[i]; + int endIndex = end >= 0 ? end : catSource.count; + [catSource removeSourcesFromIndex:start toIndex:endIndex]; + } + // Re-index the remaining audio sources. + NSArray *oldIndexedAudioSources = _indexedAudioSources; + _indexedAudioSources = [[NSMutableArray alloc] init]; + [_audioSource buildSequence:_indexedAudioSources treeIndex:0]; + for (int i = 0, j = 0; i < _indexedAudioSources.count; i++, j++) { + IndexedAudioSource *audioSource = _indexedAudioSources[i]; + while (audioSource != oldIndexedAudioSources[j]) { + [self removeItemObservers:oldIndexedAudioSources[j].playerItem]; + if (j < _index) { + _index--; + } else if (j == _index) { + // The currently playing item was removed. + } + j++; + } + } + [self updateOrder]; + if (_index >= _indexedAudioSources.count) _index = _indexedAudioSources.count - 1; + if (_index < 0) _index = 0; + [self enqueueFrom:_index]; + [self broadcastPlaybackEvent]; +} + +// Untested +- (void)concatenatingMove:(NSString *)catId currentIndex:(int)currentIndex newIndex:(int)newIndex { + // Find all duplicates of the identified ConcatenatingAudioSource. + NSMutableArray *matches = [[NSMutableArray alloc] init]; + [_audioSource findById:catId matches:matches]; + // Move range within each match. + for (int i = 0; i < matches.count; i++) { + ConcatenatingAudioSource *catSource = (ConcatenatingAudioSource *)matches[i]; + [catSource moveSourceFromIndex:currentIndex toIndex:newIndex]; + } + // Re-index the audio sources. + _indexedAudioSources = [[NSMutableArray alloc] init]; + [_audioSource buildSequence:_indexedAudioSources treeIndex:0]; + _index = [self indexForItem:_player.currentItem]; + [self broadcastPlaybackEvent]; +} + +// Untested +- (void)concatenatingClear:(NSString *)catId { + [self concatenatingRemoveRange:catId start:0 end:-1]; +} + +- (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink { + _eventSink = eventSink; + return nil; +} + +- (FlutterError*)onCancelWithArguments:(id)arguments { + _eventSink = nil; + return nil; +} + +- (void)checkForDiscontinuity { + if (!_eventSink) return; + if (!_playing || CMTIME_IS_VALID(_seekPos) || _processingState == completed) return; + int position = [self getCurrentPosition]; + if (_processingState == buffering) { + if (position > _lastPosition) { + [self leaveBuffering:@"stall ended"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } else { + long long now = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0); + long long timeSinceLastUpdate = now - _updateTime; + long long expectedPosition = _updatePosition + (long long)(timeSinceLastUpdate * _player.rate); + long long drift = position - expectedPosition; + //NSLog(@"position: %d, drift: %lld", position, drift); + // Update if we've drifted or just started observing + if (_updateTime == 0L) { + [self broadcastPlaybackEvent]; + } else if (drift < -100) { + [self enterBuffering:@"stalling"]; + NSLog(@"Drift: %lld", drift); + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } + _lastPosition = position; +} + +- (void)enterBuffering:(NSString *)reason { + NSLog(@"ENTER BUFFERING: %@", reason); + _processingState = buffering; +} + +- (void)leaveBuffering:(NSString *)reason { + NSLog(@"LEAVE BUFFERING: %@", reason); + _processingState = ready; +} + +- (void)broadcastPlaybackEvent { + if (!_eventSink) return; + _eventSink(@{ + @"processingState": @(_processingState), + @"updatePosition": @(_updatePosition), + @"updateTime": @(_updateTime), + // TODO: buffer position + @"bufferedPosition": @(_updatePosition), + // TODO: Icy Metadata + @"icyMetadata": [NSNull null], + @"duration": @([self getDuration]), + @"currentIndex": @(_index), + }); +} + +- (int)getCurrentPosition { + if (_processingState == none || _processingState == loading) { + return 0; + } else if (CMTIME_IS_VALID(_seekPos)) { + return (int)(1000 * CMTimeGetSeconds(_seekPos)); + } else if (_indexedAudioSources) { + int ms = (int)(1000 * CMTimeGetSeconds(_indexedAudioSources[_index].position)); + if (ms < 0) ms = 0; + return ms; + } else { + return 0; + } +} + +- (int)getBufferedPosition { + if (_processingState == none || _processingState == loading) { + return 0; + } else if (_indexedAudioSources) { + int ms = (int)(1000 * CMTimeGetSeconds(_indexedAudioSources[_index].bufferedPosition)); + if (ms < 0) ms = 0; + return ms; + } else { + return 0; + } +} + +- (int)getDuration { + if (_processingState == none) { + return -1; + } else if (_indexedAudioSources) { + int v = (int)(1000 * CMTimeGetSeconds(_indexedAudioSources[_index].duration)); + return v; + } else { + return 0; + } +} + +- (void)removeItemObservers:(AVPlayerItem *)playerItem { + [playerItem removeObserver:self forKeyPath:@"status"]; + [playerItem removeObserver:self forKeyPath:@"playbackBufferEmpty"]; + [playerItem removeObserver:self forKeyPath:@"playbackBufferFull"]; + //[playerItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemPlaybackStalledNotification object:playerItem]; +} + +- (void)addItemObservers:(AVPlayerItem *)playerItem { + // Get notified when the item is loaded or had an error loading + [playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; + // Get notified of the buffer state + [playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; + [playerItem addObserver:self forKeyPath:@"playbackBufferFull" options:NSKeyValueObservingOptionNew context:nil]; + [playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; + //[playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; + // Get notified when playback has reached the end + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onComplete:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; + // Get notified when playback stops due to a failure (currently unused) + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFailToComplete:) name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem]; + // Get notified when playback stalls (currently unused) + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onItemStalled:) name:AVPlayerItemPlaybackStalledNotification object:playerItem]; +} + +- (NSMutableArray *)decodeAudioSources:(NSArray *)data { + NSMutableArray *array = [[NSMutableArray alloc] init]; + for (int i = 0; i < [data count]; i++) { + AudioSource *source = [self decodeAudioSource:data[i]]; + [array addObject:source]; + } + return array; +} + +- (AudioSource *)decodeAudioSource:(NSDictionary *)data { + NSString *type = data[@"type"]; + if ([@"progressive" isEqualToString:type]) { + return [[UriAudioSource alloc] initWithId:data[@"id"] uri:data[@"uri"]]; + } else if ([@"dash" isEqualToString:type]) { + return [[UriAudioSource alloc] initWithId:data[@"id"] uri:data[@"uri"]]; + } else if ([@"hls" isEqualToString:type]) { + return [[UriAudioSource alloc] initWithId:data[@"id"] uri:data[@"uri"]]; + } else if ([@"concatenating" isEqualToString:type]) { + return [[ConcatenatingAudioSource alloc] initWithId:data[@"id"] + audioSources:[self decodeAudioSources:data[@"audioSources"]]]; + } else if ([@"clipping" isEqualToString:type]) { + return [[ClippingAudioSource alloc] initWithId:data[@"id"] + audioSource:[self decodeAudioSource:data[@"audioSource"]] + start:data[@"start"] + end:data[@"end"]]; + } else if ([@"looping" isEqualToString:type]) { + NSMutableArray *childSources = [NSMutableArray new]; + int count = [data[@"count"] intValue]; + for (int i = 0; i < count; i++) { + [childSources addObject:[self decodeAudioSource:data[@"audioSource"]]]; + } + return [[LoopingAudioSource alloc] initWithId:data[@"id"] audioSources:childSources]; + } else { + return nil; + } +} + +- (void)enqueueFrom:(int)index { + int oldIndex = _index; + _index = index; + + // Update the queue while keeping the currently playing item untouched. + + /* NSLog(@"before reorder: _player.items.count: ", _player.items.count); */ + /* [self dumpQueue]; */ + + // First, remove all _player items except for the currently playing one (if any). + IndexedPlayerItem *oldItem = _player.currentItem; + IndexedPlayerItem *existingItem = nil; + NSArray *oldPlayerItems = [NSArray arrayWithArray:_player.items]; + // In the first pass, preserve the old and new items. + for (int i = 0; i < oldPlayerItems.count; i++) { + if (oldPlayerItems[i] == _indexedAudioSources[_index].playerItem) { + // Preserve and tag new item if it is already in the queue. + existingItem = oldPlayerItems[i]; + } else if (oldPlayerItems[i] == oldItem) { + // Temporarily preserve old item, just to avoid jumping to + // intermediate queue positions unnecessarily. We only want to jump + // once to _index. + } else { + [_player removeItem:oldPlayerItems[i]]; + } + } + // In the second pass, remove the old item (if different from new item). + if (_index != oldIndex) { + [_player removeItem:oldItem]; + } + + /* NSLog(@"inter order: _player.items.count: ", _player.items.count); */ + /* [self dumpQueue]; */ + + // Regenerate queue + BOOL include = NO; + for (int i = 0; i < [_order count]; i++) { + int si = [_order[i] intValue]; + if (si == _index) include = YES; + if (include && _indexedAudioSources[si].playerItem != existingItem) { + [_player insertItem:_indexedAudioSources[si].playerItem afterItem:nil]; + } + } + + /* NSLog(@"after reorder: _player.items.count: ", _player.items.count); */ + /* [self dumpQueue]; */ + + if (_processingState != loading && oldItem != _indexedAudioSources[_index].playerItem) { + // || !_player.currentItem.playbackLikelyToKeepUp; + if (_player.currentItem.playbackBufferEmpty) { + [self enterBuffering:@"enqueueFrom playbackBufferEmpty"]; + } else { + [self leaveBuffering:@"enqueueFrom !playbackBufferEmpty"]; + } + [self updatePosition]; + } +} + +- (void)updatePosition { + _updatePosition = [self getCurrentPosition]; + _updateTime = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0); +} + +- (void)load:(NSDictionary *)source result:(FlutterResult)result { + if (!_playing) { + [_player pause]; + } + if (_processingState == loading) { + [self abortExistingConnection]; + } + _loadResult = result; + _index = 0; + [self updatePosition]; + _processingState = loading; + [self broadcastPlaybackEvent]; + // Remove previous observers + if (_indexedAudioSources) { + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [self removeItemObservers:_indexedAudioSources[i].playerItem]; + } + } + // Decode audio source + if (_audioSource && [@"clipping" isEqualToString:source[@"type"]]) { + // Check if we're clipping an audio source that was previously loaded. + UriAudioSource *child = nil; + if ([_audioSource isKindOfClass:[ClippingAudioSource class]]) { + ClippingAudioSource *clipper = (ClippingAudioSource *)_audioSource; + child = clipper.audioSource; + } else if ([_audioSource isKindOfClass:[UriAudioSource class]]) { + child = (UriAudioSource *)_audioSource; + } + if (child) { + _audioSource = [[ClippingAudioSource alloc] initWithId:source[@"id"] + audioSource:child + start:source[@"start"] + end:source[@"end"]]; + } else { + _audioSource = [self decodeAudioSource:source]; + } + } else { + _audioSource = [self decodeAudioSource:source]; + } + _indexedAudioSources = [[NSMutableArray alloc] init]; + [_audioSource buildSequence:_indexedAudioSources treeIndex:0]; + for (int i = 0; i < [_indexedAudioSources count]; i++) { + IndexedAudioSource *source = _indexedAudioSources[i]; + [self addItemObservers:source.playerItem]; + source.playerItem.audioSource = source; + } + [self updateOrder]; + // Set up an empty player + if (!_player) { + _player = [[AVQueuePlayer alloc] initWithItems:@[]]; + if (@available(macOS 10.12, iOS 10.0, *)) { + _player.automaticallyWaitsToMinimizeStalling = _automaticallyWaitsToMinimizeStalling; + // TODO: Remove these observers in dispose. + [_player addObserver:self + forKeyPath:@"timeControlStatus" + options:NSKeyValueObservingOptionNew + context:nil]; + } + [_player addObserver:self + forKeyPath:@"currentItem" + options:NSKeyValueObservingOptionNew + context:nil]; + // TODO: learn about the different ways to define weakSelf. + //__weak __typeof__(self) weakSelf = self; + //typeof(self) __weak weakSelf = self; + __unsafe_unretained typeof(self) weakSelf = self; + if (@available(macOS 10.12, iOS 10.0, *)) {} + else { + _timeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMake(200, 1000) + queue:nil + usingBlock:^(CMTime time) { + [weakSelf checkForDiscontinuity]; + } + ]; + } + } + // Initialise the AVQueuePlayer with items. + [self enqueueFrom:0]; + // Notify each IndexedAudioSource that it's been attached to the player. + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [_indexedAudioSources[i] attach:_player]; + } + + if (_player.currentItem.status == AVPlayerItemStatusReadyToPlay) { + _loadResult(@([self getDuration])); + _loadResult = nil; + } else { + // We send result after the playerItem is ready in observeValueForKeyPath. + } + [self broadcastPlaybackEvent]; +} + +- (void)updateOrder { + if (_shuffleModeEnabled) { + [_audioSource shuffle:0 currentIndex: _index]; + } + _orderInv = [NSMutableArray arrayWithCapacity:[_indexedAudioSources count]]; + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [_orderInv addObject:@(0)]; + } + if (_shuffleModeEnabled) { + _order = [_audioSource getShuffleOrder]; + } else { + NSMutableArray *order = [[NSMutableArray alloc] init]; + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [order addObject:@(i)]; + } + _order = order; + } + for (int i = 0; i < [_indexedAudioSources count]; i++) { + _orderInv[[_order[i] intValue]] = @(i); + } +} + +- (void)onItemStalled:(NSNotification *)notification { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)notification.object; + NSLog(@"onItemStalled"); +} + +- (void)onFailToComplete:(NSNotification *)notification { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)notification.object; + NSLog(@"onFailToComplete"); +} + +- (void)onComplete:(NSNotification *)notification { + NSLog(@"onComplete"); + if (_loopMode == loopOne) { + [self seek:kCMTimeZero index:@(_index) completionHandler:^(BOOL finished) { + // XXX: Not necessary? + [self play]; + }]; + } else { + IndexedPlayerItem *endedPlayerItem = (IndexedPlayerItem *)notification.object; + IndexedAudioSource *endedSource = endedPlayerItem.audioSource; + // When an item ends, seek back to its beginning. + [endedSource seek:kCMTimeZero]; + + if ([_orderInv[_index] intValue] + 1 < [_order count]) { + // account for automatic move to next item + _index = [_order[[_orderInv[_index] intValue] + 1] intValue]; + NSLog(@"advance to next: index = %d", _index); + [self broadcastPlaybackEvent]; + } else { + // reached end of playlist + if (_loopMode == loopAll) { + NSLog(@"Loop back to first item"); + // Loop back to the beginning + // TODO: Currently there will be a gap at the loop point. + // Maybe we can do something clever by temporarily adding the + // first playlist item at the end of the queue, although this + // will affect any code that assumes the queue always + // corresponds to a contiguous region of the indexed audio + // sources. + // For now we just do a seek back to the start. + if ([_order count] == 1) { + [self seek:kCMTimeZero index:[NSNull null] completionHandler:^(BOOL finished) { + // XXX: Necessary? + [self play]; + }]; + } else { + [self seek:kCMTimeZero index:_order[0] completionHandler:^(BOOL finished) { + // XXX: Necessary? + [self play]; + }]; + } + } else { + [self complete]; + } + } + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + + if ([keyPath isEqualToString:@"status"]) { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)object; + AVPlayerItemStatus status = AVPlayerItemStatusUnknown; + NSNumber *statusNumber = change[NSKeyValueChangeNewKey]; + if ([statusNumber isKindOfClass:[NSNumber class]]) { + status = statusNumber.intValue; + } + switch (status) { + case AVPlayerItemStatusReadyToPlay: { + if (playerItem != _player.currentItem) return; + // Detect buffering in different ways depending on whether we're playing + if (_playing) { + if (@available(macOS 10.12, iOS 10.0, *)) { + if (_player.timeControlStatus == AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate) { + [self enterBuffering:@"ready to play: playing, waitingToPlay"]; + } else { + [self leaveBuffering:@"ready to play: playing, !waitingToPlay"]; + } + [self updatePosition]; + } else { + // If this happens when we're playing, check whether buffer is confirmed + if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { + // Stay in bufering - XXX Test + [self enterBuffering:@"ready to play: playing, bufferUnconfirmed && !playbackBufferFull"]; + } else { + if (_player.currentItem.playbackBufferEmpty) { + // !_player.currentItem.playbackLikelyToKeepUp; + [self enterBuffering:@"ready to play: playing, playbackBufferEmpty"]; + } else { + [self leaveBuffering:@"ready to play: playing, !playbackBufferEmpty"]; + } + [self updatePosition]; + } + } + } else { + if (_player.currentItem.playbackBufferEmpty) { + [self enterBuffering:@"ready to play: !playing, playbackBufferEmpty"]; + // || !_player.currentItem.playbackLikelyToKeepUp; + } else { + [self leaveBuffering:@"ready to play: !playing, !playbackBufferEmpty"]; + } + [self updatePosition]; + } + [self broadcastPlaybackEvent]; + if (_loadResult) { + _loadResult(@([self getDuration])); + _loadResult = nil; + } + break; + } + case AVPlayerItemStatusFailed: { + NSLog(@"AVPlayerItemStatusFailed"); + [self sendErrorForItem:playerItem]; + break; + } + case AVPlayerItemStatusUnknown: + break; + } + } else if ([keyPath isEqualToString:@"playbackBufferEmpty"] || [keyPath isEqualToString:@"playbackBufferFull"]) { + // Use these values to detect buffering. + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)object; + if (playerItem != _player.currentItem) return; + // If there's a seek in progress, these values are unreliable + if (CMTIME_IS_VALID(_seekPos)) return; + // Detect buffering in different ways depending on whether we're playing + if (_playing) { + if (@available(macOS 10.12, iOS 10.0, *)) { + // We handle this with timeControlStatus instead. + } else { + if (_bufferUnconfirmed && playerItem.playbackBufferFull) { + _bufferUnconfirmed = NO; + [self leaveBuffering:@"playing, _bufferUnconfirmed && playbackBufferFull"]; + [self updatePosition]; + NSLog(@"Buffering confirmed! leaving buffering"); + [self broadcastPlaybackEvent]; + } + } + } else { + if (playerItem.playbackBufferEmpty) { + [self enterBuffering:@"!playing, playbackBufferEmpty"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } else if (!playerItem.playbackBufferEmpty || playerItem.playbackBufferFull) { + _processingState = ready; + [self leaveBuffering:@"!playing, !playbackBufferEmpty || playbackBufferFull"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } + /* } else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) { */ + } else if ([keyPath isEqualToString:@"timeControlStatus"]) { + if (@available(macOS 10.12, iOS 10.0, *)) { + AVPlayerTimeControlStatus status = AVPlayerTimeControlStatusPaused; + NSNumber *statusNumber = change[NSKeyValueChangeNewKey]; + if ([statusNumber isKindOfClass:[NSNumber class]]) { + status = statusNumber.intValue; + } + switch (status) { + case AVPlayerTimeControlStatusPaused: + //NSLog(@"AVPlayerTimeControlStatusPaused"); + break; + case AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate: + //NSLog(@"AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate"); + if (_processingState != completed) { + [self enterBuffering:@"timeControlStatus"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } else { + NSLog(@"Ignoring wait signal because we reached the end"); + } + break; + case AVPlayerTimeControlStatusPlaying: + [self leaveBuffering:@"timeControlStatus"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + break; + } + } + } else if ([keyPath isEqualToString:@"currentItem"] && _player.currentItem) { + if (_player.currentItem.status == AVPlayerItemStatusFailed) { + if ([_orderInv[_index] intValue] + 1 < [_order count]) { + // account for automatic move to next item + _index = [_order[[_orderInv[_index] intValue] + 1] intValue]; + NSLog(@"advance to next on error: index = %d", _index); + [self broadcastPlaybackEvent]; + } else { + NSLog(@"error on last item"); + } + return; + } else { + int expectedIndex = [self indexForItem:_player.currentItem]; + if (_index != expectedIndex) { + // AVQueuePlayer will sometimes skip over error items without + // notifying this observer. + NSLog(@"Queue change detected. Adjusting index from %d -> %d", _index, expectedIndex); + _index = expectedIndex; + [self broadcastPlaybackEvent]; + } + } + //NSLog(@"currentItem changed. _index=%d", _index); + _bufferUnconfirmed = YES; + // If we've skipped or transitioned to a new item and we're not + // currently in the middle of a seek + if (CMTIME_IS_INVALID(_seekPos) && _player.currentItem.status == AVPlayerItemStatusReadyToPlay) { + [self updatePosition]; + IndexedAudioSource *source = ((IndexedPlayerItem *)_player.currentItem).audioSource; + // We should already be at position zero but for + // ClippingAudioSource it might be off by some milliseconds so we + // consider anything <= 100 as close enough. + if ((int)(1000 * CMTimeGetSeconds(source.position)) > 100) { + NSLog(@"On currentItem change, seeking back to zero"); + BOOL shouldResumePlayback = NO; + AVPlayerActionAtItemEnd originalEndAction = _player.actionAtItemEnd; + if (_playing && CMTimeGetSeconds(CMTimeSubtract(source.position, source.duration)) >= 0) { + NSLog(@"Need to pause while rewinding because we're at the end"); + shouldResumePlayback = YES; + _player.actionAtItemEnd = AVPlayerActionAtItemEndPause; + [_player pause]; + } + [self enterBuffering:@"currentItem changed, seeking"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + [source seek:kCMTimeZero completionHandler:^(BOOL finished) { + [self leaveBuffering:@"currentItem changed, finished seek"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + if (shouldResumePlayback) { + _player.actionAtItemEnd = originalEndAction; + // TODO: This logic is almost duplicated in seek. See if we can reuse this code. + [_player play]; + } + }]; + } else { + // Already at zero, no need to seek. + } + } + } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)object; + if (playerItem != _player.currentItem) return; + int pos = [self getBufferedPosition]; + if (pos != _bufferedPosition) { + _bufferedPosition = pos; + [self broadcastPlaybackEvent]; + } + } +} + +- (void)sendErrorForItem:(IndexedPlayerItem *)playerItem { + FlutterError *flutterError = [FlutterError errorWithCode:[NSString stringWithFormat:@"%d", playerItem.error.code] + message:playerItem.error.localizedDescription + details:nil]; + [self sendError:flutterError playerItem:playerItem]; +} + +- (void)sendError:(FlutterError *)flutterError playerItem:(IndexedPlayerItem *)playerItem { + NSLog(@"sendError"); + if (_loadResult && playerItem == _player.currentItem) { + _loadResult(flutterError); + _loadResult = nil; + } + if (_eventSink) { + // Broadcast all errors even if they aren't on the current item. + _eventSink(flutterError); + } +} + +- (void)abortExistingConnection { + FlutterError *flutterError = [FlutterError errorWithCode:@"abort" + message:@"Connection aborted" + details:nil]; + [self sendError:flutterError playerItem:nil]; +} + +- (int)indexForItem:(IndexedPlayerItem *)playerItem { + for (int i = 0; i < _indexedAudioSources.count; i++) { + if (_indexedAudioSources[i].playerItem == playerItem) { + return i; + } + } + return -1; +} + +- (void)play { + [self play:nil]; +} + +- (void)play:(FlutterResult)result { + if (result) { + if (_playResult) { + NSLog(@"INTERRUPTING PLAY"); + _playResult(nil); + } + _playResult = result; + } + _playing = YES; +#if TARGET_OS_IPHONE + if (_configuredSession) { + [[AVAudioSession sharedInstance] setActive:YES error:nil]; + } +#endif + [_player play]; + [self updatePosition]; + if (@available(macOS 10.12, iOS 10.0, *)) {} + else { + if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { + [self enterBuffering:@"play, _bufferUnconfirmed && !playbackBufferFull"]; + [self broadcastPlaybackEvent]; + } + } +} + +- (void)pause { + _playing = NO; + [_player pause]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + if (_playResult) { + NSLog(@"PLAY FINISHED DUE TO PAUSE"); + _playResult(nil); + _playResult = nil; + } +} + +- (void)complete { + [self updatePosition]; + _processingState = completed; + [self broadcastPlaybackEvent]; + if (_playResult) { + NSLog(@"PLAY FINISHED DUE TO COMPLETE"); + _playResult(nil); + _playResult = nil; + } +} + +- (void)setVolume:(float)volume { + [_player setVolume:volume]; +} + +- (void)setSpeed:(float)speed { + if (speed == 1.0 + || (speed < 1.0 && _player.currentItem.canPlaySlowForward) + || (speed > 1.0 && _player.currentItem.canPlayFastForward)) { + _player.rate = speed; + } + [self updatePosition]; +} + +- (void)setLoopMode:(int)loopMode { + _loopMode = loopMode; + if (_player) { + switch (_loopMode) { + case loopOne: + _player.actionAtItemEnd = AVPlayerActionAtItemEndPause; // AVPlayerActionAtItemEndNone + break; + default: + _player.actionAtItemEnd = AVPlayerActionAtItemEndAdvance; + } + } +} + +- (void)setShuffleModeEnabled:(BOOL)shuffleModeEnabled { + NSLog(@"setShuffleModeEnabled: %d", shuffleModeEnabled); + _shuffleModeEnabled = shuffleModeEnabled; + if (!_audioSource) return; + + [self updateOrder]; + + [self enqueueFrom:_index]; +} + +- (void)dumpQueue { + for (int i = 0; i < _player.items.count; i++) { + IndexedPlayerItem *playerItem = _player.items[i]; + for (int j = 0; j < _indexedAudioSources.count; j++) { + IndexedAudioSource *source = _indexedAudioSources[j]; + if (source.playerItem == playerItem) { + NSLog(@"- %d", j); + break; + } + } + } +} + +- (void)setAutomaticallyWaitsToMinimizeStalling:(bool)automaticallyWaitsToMinimizeStalling { + _automaticallyWaitsToMinimizeStalling = automaticallyWaitsToMinimizeStalling; + if (@available(macOS 10.12, iOS 10.0, *)) { + if(_player) { + _player.automaticallyWaitsToMinimizeStalling = automaticallyWaitsToMinimizeStalling; + } + } +} + +- (void)seek:(CMTime)position index:(NSNumber *)newIndex completionHandler:(void (^)(BOOL))completionHandler { + int index = _index; + if (newIndex != [NSNull null]) { + index = [newIndex intValue]; + } + if (index != _index) { + // Jump to a new item + /* if (_playing && index == _index + 1) { */ + /* // Special case for jumping to the very next item */ + /* NSLog(@"seek to next item: %d -> %d", _index, index); */ + /* [_indexedAudioSources[_index] seek:kCMTimeZero]; */ + /* _index = index; */ + /* [_player advanceToNextItem]; */ + /* [self broadcastPlaybackEvent]; */ + /* } else */ + { + // Jump to a distant item + //NSLog(@"seek# jump to distant item: %d -> %d", _index, index); + if (_playing) { + [_player pause]; + } + [_indexedAudioSources[_index] seek:kCMTimeZero]; + // The "currentItem" key observer will respect that a seek is already in progress + _seekPos = position; + [self updatePosition]; + [self enqueueFrom:index]; + IndexedAudioSource *source = _indexedAudioSources[_index]; + if (abs((int)(1000 * CMTimeGetSeconds(CMTimeSubtract(source.position, position)))) > 100) { + [self enterBuffering:@"seek to index"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + [source seek:position completionHandler:^(BOOL finished) { + if (@available(macOS 10.12, iOS 10.0, *)) { + if (_playing) { + // Handled by timeControlStatus + } else { + if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { + // Stay in buffering + } else if (source.playerItem.status == AVPlayerItemStatusReadyToPlay) { + [self leaveBuffering:@"seek to index finished, (!bufferUnconfirmed || playbackBufferFull) && ready to play"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } + } else { + if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { + // Stay in buffering + } else if (source.playerItem.status == AVPlayerItemStatusReadyToPlay) { + [self leaveBuffering:@"seek to index finished, (!bufferUnconfirmed || playbackBufferFull) && ready to play"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } + if (_playing) { + [_player play]; + } + _seekPos = kCMTimeInvalid; + [self broadcastPlaybackEvent]; + if (completionHandler) { + completionHandler(finished); + } + }]; + } else { + _seekPos = kCMTimeInvalid; + if (_playing) { + [_player play]; + } + } + } + } else { + // Seek within an item + if (_playing) { + [_player pause]; + } + _seekPos = position; + //NSLog(@"seek. enter buffering. pos = %d", (int)(1000*CMTimeGetSeconds(_indexedAudioSources[_index].position))); + // TODO: Move this into a separate method so it can also + // be used in skip. + [self enterBuffering:@"seek"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + [_indexedAudioSources[_index] seek:position completionHandler:^(BOOL finished) { + [self updatePosition]; + if (_playing) { + // If playing, buffering will be detected either by: + // 1. checkForDiscontinuity + // 2. timeControlStatus + [_player play]; + } else { + // If not playing, there is no reliable way to detect + // when buffering has completed, so we use + // !playbackBufferEmpty. Although this always seems to + // be full even right after a seek. + if (_player.currentItem.playbackBufferEmpty) { + [self enterBuffering:@"seek finished, playbackBufferEmpty"]; + } else { + [self leaveBuffering:@"seek finished, !playbackBufferEmpty"]; + } + [self updatePosition]; + if (_processingState != buffering) { + [self broadcastPlaybackEvent]; + } + } + _seekPos = kCMTimeInvalid; + [self broadcastPlaybackEvent]; + if (completionHandler) { + completionHandler(finished); + } + }]; + } +} + +- (void)dispose { + if (_processingState != none) { + [_player pause]; + _processingState = none; + [self broadcastPlaybackEvent]; + } + if (_timeObserver) { + [_player removeTimeObserver:_timeObserver]; + _timeObserver = 0; + } + if (_indexedAudioSources) { + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [self removeItemObservers:_indexedAudioSources[i].playerItem]; + } + } + if (_player) { + [_player removeObserver:self forKeyPath:@"currentItem"]; + if (@available(macOS 10.12, iOS 10.0, *)) { + [_player removeObserver:self forKeyPath:@"timeControlStatus"]; + } + _player = nil; + } + // Untested: + // [_eventChannel setStreamHandler:nil]; + // [_methodChannel setMethodHandler:nil]; +} + +@end diff --git a/just_audio/ios/Classes/AudioSource.h b/just_audio/ios/Classes/AudioSource.h new file mode 100644 index 0000000..c192f33 --- /dev/null +++ b/just_audio/ios/Classes/AudioSource.h @@ -0,0 +1,13 @@ +#import + +@interface AudioSource : NSObject + +@property (readonly, nonatomic) NSString* sourceId; + +- (instancetype)initWithId:(NSString *)sid; +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex; +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches; +- (NSArray *)getShuffleOrder; +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex; + +@end diff --git a/just_audio/ios/Classes/AudioSource.m b/just_audio/ios/Classes/AudioSource.m new file mode 100644 index 0000000..81534f1 --- /dev/null +++ b/just_audio/ios/Classes/AudioSource.m @@ -0,0 +1,37 @@ +#import "AudioSource.h" +#import + +@implementation AudioSource { + NSString *_sourceId; +} + +- (instancetype)initWithId:(NSString *)sid { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + _sourceId = sid; + return self; +} + +- (NSString *)sourceId { + return _sourceId; +} + +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex { + return 0; +} + +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches { + if ([_sourceId isEqualToString:sourceId]) { + [matches addObject:self]; + } +} + +- (NSArray *)getShuffleOrder { + return @[]; +} + +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex { + return 0; +} + +@end diff --git a/just_audio/ios/Classes/ClippingAudioSource.h b/just_audio/ios/Classes/ClippingAudioSource.h new file mode 100644 index 0000000..127019e --- /dev/null +++ b/just_audio/ios/Classes/ClippingAudioSource.h @@ -0,0 +1,11 @@ +#import "AudioSource.h" +#import "UriAudioSource.h" +#import + +@interface ClippingAudioSource : IndexedAudioSource + +@property (readonly, nonatomic) UriAudioSource* audioSource; + +- (instancetype)initWithId:(NSString *)sid audioSource:(UriAudioSource *)audioSource start:(NSNumber *)start end:(NSNumber *)end; + +@end diff --git a/just_audio/ios/Classes/ClippingAudioSource.m b/just_audio/ios/Classes/ClippingAudioSource.m new file mode 100644 index 0000000..2f3b174 --- /dev/null +++ b/just_audio/ios/Classes/ClippingAudioSource.m @@ -0,0 +1,79 @@ +#import "AudioSource.h" +#import "ClippingAudioSource.h" +#import "IndexedPlayerItem.h" +#import "UriAudioSource.h" +#import + +@implementation ClippingAudioSource { + UriAudioSource *_audioSource; + CMTime _start; + CMTime _end; +} + +- (instancetype)initWithId:(NSString *)sid audioSource:(UriAudioSource *)audioSource start:(NSNumber *)start end:(NSNumber *)end { + self = [super initWithId:sid]; + NSAssert(self, @"super init cannot be nil"); + _audioSource = audioSource; + _start = start == [NSNull null] ? kCMTimeZero : CMTimeMake([start intValue], 1000); + _end = end == [NSNull null] ? kCMTimeInvalid : CMTimeMake([end intValue], 1000); + return self; +} + +- (UriAudioSource *)audioSource { + return _audioSource; +} + +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches { + [super findById:sourceId matches:matches]; + [_audioSource findById:sourceId matches:matches]; +} + +- (void)attach:(AVQueuePlayer *)player { + [super attach:player]; + _audioSource.playerItem.forwardPlaybackEndTime = _end; + // XXX: Not needed since currentItem observer handles it? + [self seek:kCMTimeZero]; +} + +- (IndexedPlayerItem *)playerItem { + return _audioSource.playerItem; +} + +- (NSArray *)getShuffleOrder { + return @[@(0)]; +} + +- (void)play:(AVQueuePlayer *)player { +} + +- (void)pause:(AVQueuePlayer *)player { +} + +- (void)stop:(AVQueuePlayer *)player { +} + +- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler { + if (!completionHandler || (self.playerItem.status == AVPlayerItemStatusReadyToPlay)) { + CMTime absPosition = CMTimeAdd(_start, position); + [_audioSource.playerItem seekToTime:absPosition toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:completionHandler]; + } +} + +- (CMTime)duration { + return CMTimeSubtract(CMTIME_IS_INVALID(_end) ? self.playerItem.duration : _end, _start); +} + +- (void)setDuration:(CMTime)duration { +} + +- (CMTime)position { + return CMTimeSubtract(self.playerItem.currentTime, _start); +} + +- (CMTime)bufferedPosition { + CMTime pos = CMTimeSubtract(_audioSource.bufferedPosition, _start); + CMTime dur = [self duration]; + return CMTimeCompare(pos, dur) >= 0 ? dur : pos; +} + +@end diff --git a/just_audio/ios/Classes/ConcatenatingAudioSource.h b/just_audio/ios/Classes/ConcatenatingAudioSource.h new file mode 100644 index 0000000..2c2350a --- /dev/null +++ b/just_audio/ios/Classes/ConcatenatingAudioSource.h @@ -0,0 +1,13 @@ +#import "AudioSource.h" +#import + +@interface ConcatenatingAudioSource : AudioSource + +@property (readonly, nonatomic) int count; + +- (instancetype)initWithId:(NSString *)sid audioSources:(NSMutableArray *)audioSources; +- (void)insertSource:(AudioSource *)audioSource atIndex:(int)index; +- (void)removeSourcesFromIndex:(int)start toIndex:(int)end; +- (void)moveSourceFromIndex:(int)currentIndex toIndex:(int)newIndex; + +@end diff --git a/just_audio/ios/Classes/ConcatenatingAudioSource.m b/just_audio/ios/Classes/ConcatenatingAudioSource.m new file mode 100644 index 0000000..bd7b713 --- /dev/null +++ b/just_audio/ios/Classes/ConcatenatingAudioSource.m @@ -0,0 +1,109 @@ +#import "AudioSource.h" +#import "ConcatenatingAudioSource.h" +#import +#import + +@implementation ConcatenatingAudioSource { + NSMutableArray *_audioSources; + NSMutableArray *_shuffleOrder; +} + +- (instancetype)initWithId:(NSString *)sid audioSources:(NSMutableArray *)audioSources { + self = [super initWithId:sid]; + NSAssert(self, @"super init cannot be nil"); + _audioSources = audioSources; + return self; +} + +- (int)count { + return _audioSources.count; +} + +- (void)insertSource:(AudioSource *)audioSource atIndex:(int)index { + [_audioSources insertObject:audioSource atIndex:index]; +} + +- (void)removeSourcesFromIndex:(int)start toIndex:(int)end { + if (end == -1) end = _audioSources.count; + for (int i = start; i < end; i++) { + [_audioSources removeObjectAtIndex:start]; + } +} + +- (void)moveSourceFromIndex:(int)currentIndex toIndex:(int)newIndex { + AudioSource *source = _audioSources[currentIndex]; + [_audioSources removeObjectAtIndex:currentIndex]; + [_audioSources insertObject:source atIndex:newIndex]; +} + +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex { + for (int i = 0; i < [_audioSources count]; i++) { + treeIndex = [_audioSources[i] buildSequence:sequence treeIndex:treeIndex]; + } + return treeIndex; +} + +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches { + [super findById:sourceId matches:matches]; + for (int i = 0; i < [_audioSources count]; i++) { + [_audioSources[i] findById:sourceId matches:matches]; + } +} + +- (NSArray *)getShuffleOrder { + NSMutableArray *order = [NSMutableArray new]; + int offset = [order count]; + NSMutableArray *childOrders = [NSMutableArray new]; // array of array of ints + for (int i = 0; i < [_audioSources count]; i++) { + AudioSource *audioSource = _audioSources[i]; + NSArray *childShuffleOrder = [audioSource getShuffleOrder]; + NSMutableArray *offsetChildShuffleOrder = [NSMutableArray new]; + for (int j = 0; j < [childShuffleOrder count]; j++) { + [offsetChildShuffleOrder addObject:@([childShuffleOrder[j] integerValue] + offset)]; + } + [childOrders addObject:offsetChildShuffleOrder]; + offset += [childShuffleOrder count]; + } + for (int i = 0; i < [_audioSources count]; i++) { + [order addObjectsFromArray:childOrders[[_shuffleOrder[i] integerValue]]]; + } + return order; +} + +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex { + int currentChildIndex = -1; + for (int i = 0; i < [_audioSources count]; i++) { + int indexBefore = treeIndex; + AudioSource *child = _audioSources[i]; + treeIndex = [child shuffle:treeIndex currentIndex:currentIndex]; + if (currentIndex >= indexBefore && currentIndex < treeIndex) { + currentChildIndex = i; + } else {} + } + // Shuffle so that the current child is first in the shuffle order + _shuffleOrder = [NSMutableArray arrayWithCapacity:[_audioSources count]]; + for (int i = 0; i < [_audioSources count]; i++) { + [_shuffleOrder addObject:@(0)]; + } + NSLog(@"shuffle: audioSources.count=%d and shuffleOrder.count=%d", [_audioSources count], [_shuffleOrder count]); + // First generate a random shuffle + for (int i = 0; i < [_audioSources count]; i++) { + int j = arc4random_uniform(i + 1); + _shuffleOrder[i] = _shuffleOrder[j]; + _shuffleOrder[j] = @(i); + } + // Then bring currentIndex to the front + if (currentChildIndex != -1) { + for (int i = 1; i < [_audioSources count]; i++) { + if ([_shuffleOrder[i] integerValue] == currentChildIndex) { + NSNumber *v = _shuffleOrder[0]; + _shuffleOrder[0] = _shuffleOrder[i]; + _shuffleOrder[i] = v; + break; + } + } + } + return treeIndex; +} + +@end diff --git a/just_audio/ios/Classes/IndexedAudioSource.h b/just_audio/ios/Classes/IndexedAudioSource.h new file mode 100644 index 0000000..a308a4f --- /dev/null +++ b/just_audio/ios/Classes/IndexedAudioSource.h @@ -0,0 +1,21 @@ +#import "AudioSource.h" +#import "IndexedPlayerItem.h" +#import +#import + +@interface IndexedAudioSource : AudioSource + +@property (readonly, nonatomic) IndexedPlayerItem *playerItem; +@property (readwrite, nonatomic) CMTime duration; +@property (readonly, nonatomic) CMTime position; +@property (readonly, nonatomic) CMTime bufferedPosition; +@property (readonly, nonatomic) BOOL isAttached; + +- (void)attach:(AVQueuePlayer *)player; +- (void)play:(AVQueuePlayer *)player; +- (void)pause:(AVQueuePlayer *)player; +- (void)stop:(AVQueuePlayer *)player; +- (void)seek:(CMTime)position; +- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler; + +@end diff --git a/just_audio/ios/Classes/IndexedAudioSource.m b/just_audio/ios/Classes/IndexedAudioSource.m new file mode 100644 index 0000000..316f900 --- /dev/null +++ b/just_audio/ios/Classes/IndexedAudioSource.m @@ -0,0 +1,68 @@ +#import "IndexedAudioSource.h" +#import "IndexedPlayerItem.h" +#import + +@implementation IndexedAudioSource { + BOOL _isAttached; +} + +- (instancetype)initWithId:(NSString *)sid { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + _isAttached = NO; + return self; +} + +- (IndexedPlayerItem *)playerItem { + return nil; +} + +- (BOOL)isAttached { + return _isAttached; +} + +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex { + [sequence addObject:self]; + return treeIndex + 1; +} + +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex { + return treeIndex + 1; +} + +- (void)attach:(AVQueuePlayer *)player { + _isAttached = YES; +} + +- (void)play:(AVQueuePlayer *)player { +} + +- (void)pause:(AVQueuePlayer *)player { +} + +- (void)stop:(AVQueuePlayer *)player { +} + +- (void)seek:(CMTime)position { + [self seek:position completionHandler:nil]; +} + +- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler { +} + +- (CMTime)duration { + return kCMTimeInvalid; +} + +- (void)setDuration:(CMTime)duration { +} + +- (CMTime)position { + return kCMTimeInvalid; +} + +- (CMTime)bufferedPosition { + return kCMTimeInvalid; +} + +@end diff --git a/just_audio/ios/Classes/IndexedPlayerItem.h b/just_audio/ios/Classes/IndexedPlayerItem.h new file mode 100644 index 0000000..5d4a11c --- /dev/null +++ b/just_audio/ios/Classes/IndexedPlayerItem.h @@ -0,0 +1,9 @@ +#import + +@class IndexedAudioSource; + +@interface IndexedPlayerItem : AVPlayerItem + +@property (readwrite, nonatomic) IndexedAudioSource *audioSource; + +@end diff --git a/just_audio/ios/Classes/IndexedPlayerItem.m b/just_audio/ios/Classes/IndexedPlayerItem.m new file mode 100644 index 0000000..87fafe0 --- /dev/null +++ b/just_audio/ios/Classes/IndexedPlayerItem.m @@ -0,0 +1,16 @@ +#import "IndexedPlayerItem.h" +#import "IndexedAudioSource.h" + +@implementation IndexedPlayerItem { + IndexedAudioSource *_audioSource; +} + +-(void)setAudioSource:(IndexedAudioSource *)audioSource { + _audioSource = audioSource; +} + +-(IndexedAudioSource *)audioSource { + return _audioSource; +} + +@end diff --git a/just_audio/ios/Classes/JustAudioPlugin.h b/just_audio/ios/Classes/JustAudioPlugin.h new file mode 100644 index 0000000..a694322 --- /dev/null +++ b/just_audio/ios/Classes/JustAudioPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface JustAudioPlugin : NSObject +@end diff --git a/just_audio/ios/Classes/JustAudioPlugin.m b/just_audio/ios/Classes/JustAudioPlugin.m new file mode 100644 index 0000000..982a260 --- /dev/null +++ b/just_audio/ios/Classes/JustAudioPlugin.m @@ -0,0 +1,55 @@ +#import "JustAudioPlugin.h" +#import "AudioPlayer.h" +#import +#include + +@implementation JustAudioPlugin { + NSObject* _registrar; + BOOL _configuredSession; +} + ++ (void)registerWithRegistrar:(NSObject*)registrar { + FlutterMethodChannel* channel = [FlutterMethodChannel + methodChannelWithName:@"com.ryanheise.just_audio.methods" + binaryMessenger:[registrar messenger]]; + JustAudioPlugin* instance = [[JustAudioPlugin alloc] initWithRegistrar:registrar]; + [registrar addMethodCallDelegate:instance channel:channel]; +} + +- (instancetype)initWithRegistrar:(NSObject *)registrar { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + _registrar = registrar; + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { + if ([@"init" isEqualToString:call.method]) { + NSArray* args = (NSArray*)call.arguments; + NSString* playerId = args[0]; + /*AudioPlayer* player =*/ [[AudioPlayer alloc] initWithRegistrar:_registrar playerId:playerId configuredSession:_configuredSession]; + result(nil); + } else if ([@"setIosCategory" isEqualToString:call.method]) { +#if TARGET_OS_IPHONE + NSNumber* categoryIndex = (NSNumber*)call.arguments; + AVAudioSessionCategory category = nil; + switch (categoryIndex.integerValue) { + case 0: category = AVAudioSessionCategoryAmbient; break; + case 1: category = AVAudioSessionCategorySoloAmbient; break; + case 2: category = AVAudioSessionCategoryPlayback; break; + case 3: category = AVAudioSessionCategoryRecord; break; + case 4: category = AVAudioSessionCategoryPlayAndRecord; break; + case 5: category = AVAudioSessionCategoryMultiRoute; break; + } + if (category) { + _configuredSession = YES; + } + [[AVAudioSession sharedInstance] setCategory:category error:nil]; +#endif + result(nil); + } else { + result(FlutterMethodNotImplemented); + } +} + +@end diff --git a/just_audio/ios/Classes/LoopingAudioSource.h b/just_audio/ios/Classes/LoopingAudioSource.h new file mode 100644 index 0000000..7c524a9 --- /dev/null +++ b/just_audio/ios/Classes/LoopingAudioSource.h @@ -0,0 +1,8 @@ +#import "AudioSource.h" +#import + +@interface LoopingAudioSource : AudioSource + +- (instancetype)initWithId:(NSString *)sid audioSources:(NSArray *)audioSources; + +@end diff --git a/just_audio/ios/Classes/LoopingAudioSource.m b/just_audio/ios/Classes/LoopingAudioSource.m new file mode 100644 index 0000000..ba4b52b --- /dev/null +++ b/just_audio/ios/Classes/LoopingAudioSource.m @@ -0,0 +1,53 @@ +#import "AudioSource.h" +#import "LoopingAudioSource.h" +#import + +@implementation LoopingAudioSource { + // An array of duplicates + NSArray *_audioSources; // +} + +- (instancetype)initWithId:(NSString *)sid audioSources:(NSArray *)audioSources { + self = [super initWithId:sid]; + NSAssert(self, @"super init cannot be nil"); + _audioSources = audioSources; + return self; +} + +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex { + for (int i = 0; i < [_audioSources count]; i++) { + treeIndex = [_audioSources[i] buildSequence:sequence treeIndex:treeIndex]; + } + return treeIndex; +} + +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches { + [super findById:sourceId matches:matches]; + for (int i = 0; i < [_audioSources count]; i++) { + [_audioSources[i] findById:sourceId matches:matches]; + } +} + +- (NSArray *)getShuffleOrder { + NSMutableArray *order = [NSMutableArray new]; + int offset = (int)[order count]; + for (int i = 0; i < [_audioSources count]; i++) { + AudioSource *audioSource = _audioSources[i]; + NSArray *childShuffleOrder = [audioSource getShuffleOrder]; + for (int j = 0; j < [childShuffleOrder count]; j++) { + [order addObject:@([childShuffleOrder[j] integerValue] + offset)]; + } + offset += [childShuffleOrder count]; + } + return order; +} + +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex { + // TODO: This should probably shuffle the same way on all duplicates. + for (int i = 0; i < [_audioSources count]; i++) { + treeIndex = [_audioSources[i] shuffle:treeIndex currentIndex:currentIndex]; + } + return treeIndex; +} + +@end diff --git a/just_audio/ios/Classes/UriAudioSource.h b/just_audio/ios/Classes/UriAudioSource.h new file mode 100644 index 0000000..6ee3c2e --- /dev/null +++ b/just_audio/ios/Classes/UriAudioSource.h @@ -0,0 +1,8 @@ +#import "IndexedAudioSource.h" +#import + +@interface UriAudioSource : IndexedAudioSource + +- (instancetype)initWithId:(NSString *)sid uri:(NSString *)uri; + +@end diff --git a/just_audio/ios/Classes/UriAudioSource.m b/just_audio/ios/Classes/UriAudioSource.m new file mode 100644 index 0000000..91321d4 --- /dev/null +++ b/just_audio/ios/Classes/UriAudioSource.m @@ -0,0 +1,79 @@ +#import "UriAudioSource.h" +#import "IndexedAudioSource.h" +#import "IndexedPlayerItem.h" +#import + +@implementation UriAudioSource { + NSString *_uri; + IndexedPlayerItem *_playerItem; + /* CMTime _duration; */ +} + +- (instancetype)initWithId:(NSString *)sid uri:(NSString *)uri { + self = [super initWithId:sid]; + NSAssert(self, @"super init cannot be nil"); + _uri = uri; + if ([_uri hasPrefix:@"file://"]) { + _playerItem = [[IndexedPlayerItem alloc] initWithURL:[NSURL fileURLWithPath:[_uri substringFromIndex:7]]]; + } else { + _playerItem = [[IndexedPlayerItem alloc] initWithURL:[NSURL URLWithString:_uri]]; + } + if (@available(macOS 10.13, iOS 11.0, *)) { + // This does the best at reducing distortion on voice with speeds below 1.0 + _playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmTimeDomain; + } + /* NSKeyValueObservingOptions options = */ + /* NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew; */ + /* [_playerItem addObserver:self */ + /* forKeyPath:@"duration" */ + /* options:options */ + /* context:nil]; */ + return self; +} + +- (IndexedPlayerItem *)playerItem { + return _playerItem; +} + +- (NSArray *)getShuffleOrder { + return @[@(0)]; +} + +- (void)play:(AVQueuePlayer *)player { +} + +- (void)pause:(AVQueuePlayer *)player { +} + +- (void)stop:(AVQueuePlayer *)player { +} + +- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler { + if (!completionHandler || (_playerItem.status == AVPlayerItemStatusReadyToPlay)) { + [_playerItem seekToTime:position toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:completionHandler]; + } +} + +- (CMTime)duration { + return _playerItem.duration; +} + +- (void)setDuration:(CMTime)duration { +} + +- (CMTime)position { + return _playerItem.currentTime; +} + +- (CMTime)bufferedPosition { + NSValue *last = _playerItem.loadedTimeRanges.lastObject; + if (last) { + CMTimeRange timeRange = [last CMTimeRangeValue]; + return CMTimeAdd(timeRange.start, timeRange.duration); + } else { + return _playerItem.currentTime; + } + return kCMTimeInvalid; +} + +@end diff --git a/just_audio/ios/just_audio.podspec b/just_audio/ios/just_audio.podspec new file mode 100644 index 0000000..ba5c7d2 --- /dev/null +++ b/just_audio/ios/just_audio.podspec @@ -0,0 +1,21 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'just_audio' + s.version = '0.0.1' + s.summary = 'A new flutter plugin project.' + s.description = <<-DESC +A new flutter plugin project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + s.platform = :ios, '8.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } +end + diff --git a/just_audio/lib/just_audio.dart b/just_audio/lib/just_audio.dart new file mode 100644 index 0000000..15f1b6f --- /dev/null +++ b/just_audio/lib/just_audio.dart @@ -0,0 +1,1293 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:path/path.dart' as p; +import 'package:path_provider/path_provider.dart'; +import 'package:rxdart/rxdart.dart'; +import 'package:uuid/uuid.dart'; + +final _uuid = Uuid(); + +/// An object to manage playing audio from a URL, a locale file or an asset. +/// +/// ``` +/// final player = AudioPlayer(); +/// await player.setUrl('https://foo.com/bar.mp3'); +/// player.play(); +/// await player.pause(); +/// await player.setClip(start: Duration(seconds: 10), end: Duration(seconds: 20)); +/// await player.play(); +/// await player.setUrl('https://foo.com/baz.mp3'); +/// await player.seek(Duration(minutes: 5)); +/// player.play(); +/// await player.pause(); +/// await player.dispose(); +/// ``` +/// +/// You must call [dispose] to release the resources used by this player, +/// including any temporary files created to cache assets. +class AudioPlayer { + static final _mainChannel = MethodChannel('com.ryanheise.just_audio.methods'); + + static Future _init(String id) async { + await _mainChannel.invokeMethod('init', [id]); + return MethodChannel('com.ryanheise.just_audio.methods.$id'); + } + + /// Configure the audio session category on iOS. This method should be called + /// before playing any audio. It has no effect on Android or Flutter for Web. + /// + /// Note that the default category on iOS is [IosCategory.soloAmbient], but + /// for a typical media app, Apple recommends setting this to + /// [IosCategory.playback]. If you don't call this method, `just_audio` will + /// respect any prior category that was already set on your app's audio + /// session and will leave it alone. If it hasn't been previously set, this + /// will be [IosCategory.soloAmbient]. But if another audio plugin in your + /// app has configured a particular category, that will also be left alone. + /// + /// Note: If you use other audio plugins in conjunction with this one, it is + /// possible that each of those audio plugins may override the setting you + /// choose here. (You may consider asking the developers of the other plugins + /// to provide similar configurability so that you have complete control over + /// setting the overall category that you want for your app.) + static Future setIosCategory(IosCategory category) async { + await _mainChannel.invokeMethod('setIosCategory', category.index); + } + + final Future _channel; + final String _id; + _ProxyHttpServer _proxy; + Stream _eventChannelStream; + AudioSource _audioSource; + Map _audioSources = {}; + + PlaybackEvent _playbackEvent; + StreamSubscription _eventChannelStreamSubscription; + final _playbackEventSubject = BehaviorSubject(); + Future _durationFuture; + final _durationSubject = BehaviorSubject(); + final _processingStateSubject = BehaviorSubject(); + final _playingSubject = BehaviorSubject.seeded(false); + final _volumeSubject = BehaviorSubject.seeded(1.0); + final _speedSubject = BehaviorSubject.seeded(1.0); + final _bufferedPositionSubject = BehaviorSubject(); + final _icyMetadataSubject = BehaviorSubject(); + final _playerStateSubject = BehaviorSubject(); + final _currentIndexSubject = BehaviorSubject(); + final _loopModeSubject = BehaviorSubject(); + final _shuffleModeEnabledSubject = BehaviorSubject(); + BehaviorSubject _positionSubject; + bool _automaticallyWaitsToMinimizeStalling = true; + + /// Creates an [AudioPlayer]. + factory AudioPlayer() => AudioPlayer._internal(_uuid.v4()); + + AudioPlayer._internal(this._id) : _channel = _init(_id) { + _playbackEvent = PlaybackEvent( + processingState: ProcessingState.none, + updatePosition: Duration.zero, + updateTime: DateTime.now(), + bufferedPosition: Duration.zero, + duration: null, + icyMetadata: null, + currentIndex: null, + ); + _playbackEventSubject.add(_playbackEvent); + _eventChannelStream = EventChannel('com.ryanheise.just_audio.events.$_id') + .receiveBroadcastStream() + .map((data) { + try { + //print("received raw event: $data"); + final duration = (data['duration'] ?? -1) < 0 + ? null + : Duration(milliseconds: data['duration']); + _durationFuture = Future.value(duration); + if (duration != _playbackEvent.duration) { + _durationSubject.add(duration); + } + _playbackEvent = PlaybackEvent( + processingState: ProcessingState.values[data['processingState']], + updatePosition: Duration(milliseconds: data['updatePosition']), + updateTime: DateTime.fromMillisecondsSinceEpoch(data['updateTime']), + bufferedPosition: Duration(milliseconds: data['bufferedPosition']), + duration: duration, + icyMetadata: data['icyMetadata'] == null + ? null + : IcyMetadata.fromJson(data['icyMetadata']), + currentIndex: data['currentIndex'], + ); + //print("created event object with state: ${_playbackEvent.state}"); + return _playbackEvent; + } catch (e, stacktrace) { + print("Error parsing event: $e"); + print("$stacktrace"); + rethrow; + } + }); + _eventChannelStreamSubscription = _eventChannelStream.listen( + _playbackEventSubject.add, + onError: _playbackEventSubject.addError, + ); + _processingStateSubject.addStream(playbackEventStream + .map((event) => event.processingState) + .distinct() + .handleError((err, stack) {/* noop */})); + _bufferedPositionSubject.addStream(playbackEventStream + .map((event) => event.bufferedPosition) + .distinct() + .handleError((err, stack) {/* noop */})); + _icyMetadataSubject.addStream(playbackEventStream + .map((event) => event.icyMetadata) + .distinct() + .handleError((err, stack) {/* noop */})); + _currentIndexSubject.addStream(playbackEventStream + .map((event) => event.currentIndex) + .distinct() + .handleError((err, stack) {/* noop */})); + _playerStateSubject.addStream( + Rx.combineLatest2( + playingStream, + playbackEventStream, + (playing, event) => PlayerState(playing, event.processingState)) + .distinct() + .handleError((err, stack) {/* noop */})); + } + + /// The latest [PlaybackEvent]. + PlaybackEvent get playbackEvent => _playbackEvent; + + /// A stream of [PlaybackEvent]s. + Stream get playbackEventStream => _playbackEventSubject.stream; + + /// The duration of the current audio or null if unknown. + Duration get duration => _playbackEvent.duration; + + /// The duration of the current audio or null if unknown. + Future get durationFuture => _durationFuture; + + /// The duration of the current audio. + Stream get durationStream => _durationSubject.stream; + + /// The current [ProcessingState]. + ProcessingState get processingState => _playbackEvent.processingState; + + /// A stream of [ProcessingState]s. + Stream get processingStateStream => + _processingStateSubject.stream; + + /// Whether the player is playing. + bool get playing => _playingSubject.value; + + /// A stream of changing [playing] states. + Stream get playingStream => _playingSubject.stream; + + /// The current volume of the player. + double get volume => _volumeSubject.value; + + /// A stream of [volume] changes. + Stream get volumeStream => _volumeSubject.stream; + + /// The current speed of the player. + double get speed => _speedSubject.value; + + /// A stream of current speed values. + Stream get speedStream => _speedSubject.stream; + + /// The position up to which buffered audio is available. + Duration get bufferedPosition => _bufferedPositionSubject.value; + + /// A stream of buffered positions. + Stream get bufferedPositionStream => + _bufferedPositionSubject.stream; + + /// The latest ICY metadata received through the audio source. + IcyMetadata get icyMetadata => _playbackEvent.icyMetadata; + + /// A stream of ICY metadata received through the audio source. + Stream get icyMetadataStream => _icyMetadataSubject.stream; + + /// The current player state containing only the processing and playing + /// states. + PlayerState get playerState => _playerStateSubject.value; + + /// A stream of [PlayerState]s. + Stream get playerStateStream => _playerStateSubject.stream; + + /// The index of the current item. + int get currentIndex => _currentIndexSubject.value; + + /// A stream broadcasting the current item. + Stream get currentIndexStream => _currentIndexSubject.stream; + + /// Whether there is another item after the current index. + bool get hasNext => + _audioSource != null && + currentIndex != null && + currentIndex + 1 < _audioSource.sequence.length; + + /// Whether there is another item before the current index. + bool get hasPrevious => + _audioSource != null && currentIndex != null && currentIndex > 0; + + /// The current loop mode. + LoopMode get loopMode => _loopModeSubject.value; + + /// A stream of [LoopMode]s. + Stream get loopModeStream => _loopModeSubject.stream; + + /// Whether shuffle mode is currently enabled. + bool get shuffleModeEnabled => _shuffleModeEnabledSubject.value; + + /// A stream of the shuffle mode status. + Stream get shuffleModeEnabledStream => + _shuffleModeEnabledSubject.stream; + + /// Whether the player should automatically delay playback in order to + /// minimize stalling. (iOS 10.0 or later only) + bool get automaticallyWaitsToMinimizeStalling => + _automaticallyWaitsToMinimizeStalling; + + /// The current position of the player. + Duration get position { + if (playing && processingState == ProcessingState.ready) { + final result = _playbackEvent.updatePosition + + (DateTime.now().difference(_playbackEvent.updateTime)) * speed; + return _playbackEvent.duration == null || + result <= _playbackEvent.duration + ? result + : _playbackEvent.duration; + } else { + return _playbackEvent.updatePosition; + } + } + + /// A stream tracking the current position of this player, suitable for + /// animating a seek bar. To ensure a smooth animation, this stream emits + /// values more frequently on short items where the seek bar moves more + /// quickly, and less frequenly on long items where the seek bar moves more + /// slowly. The interval between each update will be no quicker than once + /// every 16ms and no slower than once every 200ms. + /// + /// See [createPositionStream] for more control over the stream parameters. + Stream get positionStream { + if (_positionSubject == null) { + _positionSubject = BehaviorSubject(); + _positionSubject.addStream(createPositionStream( + steps: 800, + minPeriod: Duration(milliseconds: 16), + maxPeriod: Duration(milliseconds: 200))); + } + return _positionSubject.stream; + } + + /// Creates a new stream periodically tracking the current position of this + /// player. The stream will aim to emit [steps] position updates from the + /// beginning to the end of the current audio source, at intervals of + /// [duration] / [steps]. This interval will be clipped between [minPeriod] + /// and [maxPeriod]. This stream will not emit values while audio playback is + /// paused or stalled. + /// + /// Note: each time this method is called, a new stream is created. If you + /// intend to use this stream multiple times, you should hold a reference to + /// the returned stream and close it once you are done. + Stream createPositionStream({ + int steps = 800, + Duration minPeriod = const Duration(milliseconds: 200), + Duration maxPeriod = const Duration(milliseconds: 200), + }) { + assert(minPeriod <= maxPeriod); + assert(minPeriod > Duration.zero); + Duration duration() => this.duration ?? Duration.zero; + Duration step() { + var s = duration() ~/ steps; + if (s < minPeriod) s = minPeriod; + if (s > maxPeriod) s = maxPeriod; + return s; + } + + StreamController controller = StreamController.broadcast(); + Timer currentTimer; + StreamSubscription durationSubscription; + StreamSubscription playbackEventSubscription; + void yieldPosition(Timer timer) { + if (controller.isClosed) { + timer.cancel(); + durationSubscription?.cancel(); + playbackEventSubscription?.cancel(); + return; + } + if (_durationSubject.isClosed) { + timer.cancel(); + durationSubscription?.cancel(); + playbackEventSubscription?.cancel(); + controller.close(); + return; + } + controller.add(position); + } + + currentTimer = Timer.periodic(step(), yieldPosition); + durationSubscription = durationStream.listen((duration) { + currentTimer.cancel(); + currentTimer = Timer.periodic(step(), yieldPosition); + }); + playbackEventSubscription = playbackEventStream.listen((event) { + controller.add(position); + }); + return controller.stream.distinct(); + } + + /// Convenience method to load audio from a URL with optional headers, + /// equivalent to: + /// + /// ``` + /// load(AudioSource.uri(Uri.parse(url), headers: headers)); + /// ``` + /// + /// + Future setUrl(String url, {Map headers}) => + load(AudioSource.uri(Uri.parse(url), headers: headers)); + + /// Convenience method to load audio from a file, equivalent to: + /// + /// ``` + /// load(AudioSource.uri(Uri.file(filePath))); + /// ``` + Future setFilePath(String filePath) => + load(AudioSource.uri(Uri.file(filePath))); + + /// Convenience method to load audio from an asset, equivalent to: + /// + /// ``` + /// load(AudioSource.uri(Uri.parse('asset://$filePath'))); + /// ``` + Future setAsset(String assetPath) => + load(AudioSource.uri(Uri.parse('asset://$assetPath'))); + + /// Loads audio from an [AudioSource] and completes when the audio is ready + /// to play with the duration of that audio, or null if the duration is unknown. + /// + /// This method throws: + /// + /// * [PlayerException] if the audio source was unable to be loaded. + /// * [PlayerInterruptedException] if another call to [load] happened before + /// this call completed. + Future load(AudioSource source) async { + try { + _audioSource = source; + final duration = await _load(source); + // Wait for loading state to pass. + await processingStateStream + .firstWhere((state) => state != ProcessingState.loading); + return duration; + } catch (e) { + _audioSource = null; + _audioSources.clear(); + rethrow; + } + } + + _registerAudioSource(AudioSource source) { + _audioSources[source._id] = source; + } + + Future _load(AudioSource source) async { + try { + if (!kIsWeb && source._requiresHeaders) { + if (_proxy == null) { + _proxy = _ProxyHttpServer(); + await _proxy.start(); + } + } + await source._setup(this); + _durationFuture = _invokeMethod('load', [source.toJson()]).then( + (ms) => (ms == null || ms < 0) ? null : Duration(milliseconds: ms)); + final duration = await _durationFuture; + _durationSubject.add(duration); + return duration; + } on PlatformException catch (e) { + try { + throw PlayerException(int.parse(e.code), e.message); + } on FormatException catch (_) { + if (e.code == 'abort') { + throw PlayerInterruptedException(e.message); + } else { + throw PlayerException(9999999, e.message); + } + } + } + } + + /// Clips the current [AudioSource] to the given [start] and [end] + /// timestamps. If [start] is null, it will be reset to the start of the + /// original [AudioSource]. If [end] is null, it will be reset to the end of + /// the original [AudioSource]. This method cannot be called from the + /// [AudioPlaybackState.none] state. + Future setClip({Duration start, Duration end}) async { + final duration = await _load(start == null && end == null + ? _audioSource + : ClippingAudioSource( + child: _audioSource, + start: start, + end: end, + )); + // Wait for loading state to pass. + await processingStateStream + .firstWhere((state) => state != ProcessingState.loading); + return duration; + } + + /// Tells the player to play audio as soon as an audio source is loaded and + /// ready to play. The [Future] returned by this method completes when the + /// playback completes or is paused or stopped. If the player is already + /// playing, this method completes immediately. + /// + /// This method causes [playing] to become true, and it will remain true + /// until [pause] or [stop] is called. This means that if playback completes, + /// and then you [seek] to an earlier position in the audio, playback will + /// continue playing from that position. If you instead wish to [pause] or + /// [stop] playback on completion, you can call either method as soon as + /// [processingState] becomes [ProcessingState.completed] by listening to + /// [processingStateStream]. + Future play() async { + if (playing) return; + _playingSubject.add(true); + await _invokeMethod('play'); + } + + /// Pauses the currently playing media. This method does nothing if + /// ![playing]. + Future pause() async { + if (!playing) return; + // Update local state immediately so that queries aren't surprised. + _playbackEvent = _playbackEvent.copyWith( + updatePosition: position, + updateTime: DateTime.now(), + ); + _playbackEventSubject.add(_playbackEvent); + _playingSubject.add(false); + // TODO: perhaps modify platform side to ensure new state is broadcast + // before this method returns. + await _invokeMethod('pause'); + } + + /// Convenience method to pause and seek to zero. + Future stop() async { + await pause(); + await seek(Duration.zero); + } + + /// Sets the volume of this player, where 1.0 is normal volume. + Future setVolume(final double volume) async { + _volumeSubject.add(volume); + await _invokeMethod('setVolume', [volume]); + } + + /// Sets the playback speed of this player, where 1.0 is normal speed. + Future setSpeed(final double speed) async { + _playbackEvent = _playbackEvent.copyWith( + updatePosition: position, + updateTime: DateTime.now(), + ); + _playbackEventSubject.add(_playbackEvent); + _speedSubject.add(speed); + await _invokeMethod('setSpeed', [speed]); + } + + /// Sets the [LoopMode]. The gapless looping support is as follows: + /// + /// * Android: supported + /// * iOS/macOS: not supported, however, gapless looping can be achieved by + /// using [LoopingAudioSource]. + /// * Web: not supported + Future setLoopMode(LoopMode mode) async { + _loopModeSubject.add(mode); + await _invokeMethod('setLoopMode', [mode.index]); + } + + /// Sets whether shuffle mode is enabled. + Future setShuffleModeEnabled(bool enabled) async { + _shuffleModeEnabledSubject.add(enabled); + await _invokeMethod('setShuffleModeEnabled', [enabled]); + } + + /// Sets automaticallyWaitsToMinimizeStalling for AVPlayer in iOS 10.0 or later, defaults to true. + /// Has no effect on Android clients + Future setAutomaticallyWaitsToMinimizeStalling( + final bool automaticallyWaitsToMinimizeStalling) async { + _automaticallyWaitsToMinimizeStalling = + automaticallyWaitsToMinimizeStalling; + await _invokeMethod('setAutomaticallyWaitsToMinimizeStalling', + [automaticallyWaitsToMinimizeStalling]); + } + + /// Seeks to a particular [position]. If a composition of multiple + /// [AudioSource]s has been loaded, you may also specify [index] to seek to a + /// particular item within that sequence. This method has no effect unless + /// an audio source has been loaded. + Future seek(final Duration position, {int index}) async { + switch (processingState) { + case ProcessingState.none: + case ProcessingState.loading: + return; + default: + _playbackEvent = _playbackEvent.copyWith( + updatePosition: position, + updateTime: DateTime.now(), + ); + _playbackEventSubject.add(_playbackEvent); + await _invokeMethod('seek', [position?.inMilliseconds, index]); + } + } + + /// Seek to the next item. + Future seekToNext() async { + if (hasNext) { + await seek(Duration.zero, index: currentIndex + 1); + } + } + + /// Seek to the previous item. + Future seekToPrevious() async { + if (hasPrevious) { + await seek(Duration.zero, index: currentIndex - 1); + } + } + + /// Release all resources associated with this player. You must invoke this + /// after you are done with the player. + Future dispose() async { + await _invokeMethod('dispose'); + _audioSource = null; + _audioSources.values.forEach((s) => s._dispose()); + _audioSources.clear(); + _proxy?.stop(); + await _durationSubject.close(); + await _eventChannelStreamSubscription.cancel(); + await _loopModeSubject.close(); + await _shuffleModeEnabledSubject.close(); + await _playingSubject.close(); + await _volumeSubject.close(); + await _speedSubject.close(); + if (_positionSubject != null) { + await _positionSubject.close(); + } + } + + Future _invokeMethod(String method, [dynamic args]) async => + (await _channel).invokeMethod(method, args); +} + +/// Captures the details of any error accessing, loading or playing an audio +/// source, including an invalid or inaccessible URL, or an audio encoding that +/// could not be understood. +class PlayerException { + /// On iOS and macOS, maps to `NSError.code`. On Android, maps to + /// `ExoPlaybackException.type`. On Web, maps to `MediaError.code`. + final int code; + + /// On iOS and macOS, maps to `NSError.localizedDescription`. On Android, + /// maps to `ExoPlaybackException.getMessage()`. On Web, a generic message + /// is provided. + final String message; + + PlayerException(this.code, this.message); + + @override + String toString() => "($code) $message"; +} + +/// An error that occurs when one operation on the player has been interrupted +/// (e.g. by another simultaneous operation). +class PlayerInterruptedException { + final String message; + + PlayerInterruptedException(this.message); + + @override + String toString() => "$message"; +} + +/// Encapsulates the playback state and current position of the player. +class PlaybackEvent { + /// The current processing state. + final ProcessingState processingState; + + /// When the last time a position discontinuity happened, as measured in time + /// since the epoch. + final DateTime updateTime; + + /// The position at [updateTime]. + final Duration updatePosition; + + /// The buffer position. + final Duration bufferedPosition; + + /// The media duration, or null if unknown. + final Duration duration; + + /// The latest ICY metadata received through the audio stream. + final IcyMetadata icyMetadata; + + /// The index of the currently playing item. + final int currentIndex; + + PlaybackEvent({ + @required this.processingState, + @required this.updateTime, + @required this.updatePosition, + @required this.bufferedPosition, + @required this.duration, + @required this.icyMetadata, + @required this.currentIndex, + }); + + PlaybackEvent copyWith({ + ProcessingState processingState, + DateTime updateTime, + Duration updatePosition, + Duration bufferedPosition, + double speed, + Duration duration, + IcyMetadata icyMetadata, + UriAudioSource currentIndex, + }) => + PlaybackEvent( + processingState: processingState ?? this.processingState, + updateTime: updateTime ?? this.updateTime, + updatePosition: updatePosition ?? this.updatePosition, + bufferedPosition: bufferedPosition ?? this.bufferedPosition, + duration: duration ?? this.duration, + icyMetadata: icyMetadata ?? this.icyMetadata, + currentIndex: currentIndex ?? this.currentIndex, + ); + + @override + String toString() => + "{processingState=$processingState, updateTime=$updateTime, updatePosition=$updatePosition}"; +} + +/// Enumerates the different processing states of a player. +enum ProcessingState { + /// The player has not loaded an [AudioSource]. + none, + + /// The player is loading an [AudioSource]. + loading, + + /// The player is buffering audio and unable to play. + buffering, + + /// The player is has enough audio buffered and is able to play. + ready, + + /// The player has reached the end of the audio. + completed, +} + +/// Encapsulates the playing and processing states. These two states vary +/// orthogonally, and so if [processingState] is [ProcessingState.buffering], +/// you can check [playing] to determine whether the buffering occurred while +/// the player was playing or while the player was paused. +class PlayerState { + /// Whether the player will play when [processingState] is + /// [ProcessingState.ready]. + final bool playing; + + /// The current processing state of the player. + final ProcessingState processingState; + + PlayerState(this.playing, this.processingState); + + @override + String toString() => 'playing=$playing,processingState=$processingState'; + + @override + int get hashCode => toString().hashCode; + + @override + bool operator ==(dynamic other) => + other is PlayerState && + other?.playing == playing && + other?.processingState == processingState; +} + +class IcyInfo { + final String title; + final String url; + + IcyInfo({@required this.title, @required this.url}); + + IcyInfo.fromJson(Map json) : this(title: json['title'], url: json['url']); + + @override + String toString() => 'title=$title,url=$url'; + + @override + int get hashCode => toString().hashCode; + + @override + bool operator ==(dynamic other) => + other is IcyInfo && other?.toString() == toString(); +} + +class IcyHeaders { + final int bitrate; + final String genre; + final String name; + final int metadataInterval; + final String url; + final bool isPublic; + + IcyHeaders({ + @required this.bitrate, + @required this.genre, + @required this.name, + @required this.metadataInterval, + @required this.url, + @required this.isPublic, + }); + + IcyHeaders.fromJson(Map json) + : this( + bitrate: json['bitrate'], + genre: json['genre'], + name: json['name'], + metadataInterval: json['metadataInterval'], + url: json['url'], + isPublic: json['isPublic'], + ); + + @override + String toString() => + 'bitrate=$bitrate,genre=$genre,name=$name,metadataInterval=$metadataInterval,url=$url,isPublic=$isPublic'; + + @override + int get hashCode => toString().hashCode; + + @override + bool operator ==(dynamic other) => + other is IcyHeaders && other?.toString() == toString(); +} + +class IcyMetadata { + final IcyInfo info; + final IcyHeaders headers; + + IcyMetadata({@required this.info, @required this.headers}); + + IcyMetadata.fromJson(Map json) + : this(info: json['info'], headers: json['headers']); + + @override + int get hashCode => info.hashCode ^ headers.hashCode; + + @override + bool operator ==(dynamic other) => + other is IcyMetadata && other?.info == info && other?.headers == headers; +} + +/// The audio session categories on iOS, to be used with +/// [AudioPlayer.setIosCategory]. +enum IosCategory { + ambient, + soloAmbient, + playback, + record, + playAndRecord, + multiRoute, +} + +/// A local proxy HTTP server for making remote GET requests with headers. +/// +/// TODO: Recursively attach headers to items in playlists like m3u8. +class _ProxyHttpServer { + HttpServer _server; + + /// Maps request keys to [_ProxyRequest]s. + final Map _uriMap = {}; + + /// The port this server is bound to on localhost. This is set only after + /// [start] has completed. + int get port => _server.port; + + /// Associate headers with a URL. This may be called only after [start] has + /// completed. + Uri addUrl(Uri url, Map headers) { + final path = _requestKey(url); + _uriMap[path] = _ProxyRequest(url, headers); + return url.replace( + scheme: 'http', + host: InternetAddress.loopbackIPv4.address, + port: port, + ); + } + + /// A unique key for each request that can be processed by this proxy, + /// made up of the URL path and query string. It is not possible to + /// simultaneously track requests that have the same URL path and query + /// but differ in other respects such as the port or headers. + String _requestKey(Uri uri) => '${uri.path}?${uri.query}'; + + /// Starts the server. + Future start() async { + _server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0); + _server.listen((request) async { + if (request.method == 'GET') { + final path = _requestKey(request.uri); + final proxyRequest = _uriMap[path]; + final originRequest = await HttpClient().getUrl(proxyRequest.uri); + + // Rewrite request headers + final host = originRequest.headers.value('host'); + originRequest.headers.clear(); + request.headers.forEach((name, value) { + originRequest.headers.set(name, value); + }); + for (var name in proxyRequest.headers.keys) { + originRequest.headers.set(name, proxyRequest.headers[name]); + } + originRequest.headers.set('host', host); + + // Try to make normal request + try { + final originResponse = await originRequest.close(); + + request.response.headers.clear(); + originResponse.headers.forEach((name, value) { + request.response.headers.set(name, value); + }); + + // Pipe response + await originResponse.pipe(request.response); + } on HttpException { + // We likely are dealing with a streaming protocol + if (proxyRequest.uri.scheme == 'http') { + // Try parsing HTTP 0.9 response + //request.response.headers.clear(); + final socket = await Socket.connect( + proxyRequest.uri.host, proxyRequest.uri.port); + final clientSocket = + await request.response.detachSocket(writeHeaders: false); + Completer done = Completer(); + socket.listen( + clientSocket.add, + onDone: () async { + await clientSocket.flush(); + socket.close(); + clientSocket.close(); + done.complete(); + }, + ); + // Rewrite headers + final headers = {}; + request.headers.forEach((name, value) { + if (name.toLowerCase() != 'host') { + headers[name] = value.join(","); + } + }); + for (var name in proxyRequest.headers.keys) { + headers[name] = proxyRequest.headers[name]; + } + socket.write("GET ${proxyRequest.uri.path} HTTP/1.1\n"); + if (host != null) { + socket.write("Host: $host\n"); + } + for (var name in headers.keys) { + socket.write("$name: ${headers[name]}\n"); + } + socket.write("\n"); + await socket.flush(); + await done.future; + } + } + } + }); + } + + /// Stops the server + Future stop() => _server.close(); +} + +/// A request for a URL and headers made by a [_ProxyHttpServer]. +class _ProxyRequest { + final Uri uri; + final Map headers; + + _ProxyRequest(this.uri, this.headers); +} + +/// Specifies a source of audio to be played. Audio sources are composable +/// using the subclasses of this class. The same [AudioSource] instance should +/// not be used simultaneously by more than one [AudioPlayer]. +abstract class AudioSource { + final String _id; + AudioPlayer _player; + + /// Creates an [AudioSource] from a [Uri] with optional headers by + /// attempting to guess the type of stream. On iOS, this uses Apple's SDK to + /// automatically detect the stream type. On Android, the type of stream will + /// be guessed from the extension. + /// + /// If you are loading DASH or HLS streams that do not have standard "mpd" or + /// "m3u8" extensions in their URIs, this method will fail to detect the + /// stream type on Android. If you know in advance what type of audio stream + /// it is, you should instantiate [DashAudioSource] or [HlsAudioSource] + /// directly. + static AudioSource uri(Uri uri, {Map headers, Object tag}) { + bool hasExtension(Uri uri, String extension) => + uri.path.toLowerCase().endsWith('.$extension') || + uri.fragment.toLowerCase().endsWith('.$extension'); + if (hasExtension(uri, 'mpd')) { + return DashAudioSource(uri, headers: headers, tag: tag); + } else if (hasExtension(uri, 'm3u8')) { + return HlsAudioSource(uri, headers: headers, tag: tag); + } else { + return ProgressiveAudioSource(uri, headers: headers, tag: tag); + } + } + + static AudioSource fromJson(Map json) { + switch (json['type']) { + case 'progressive': + return ProgressiveAudioSource(Uri.parse(json['uri']), + headers: json['headers']); + case "dash": + return DashAudioSource(Uri.parse(json['uri']), + headers: json['headers']); + case "hls": + return HlsAudioSource(Uri.parse(json['uri']), headers: json['headers']); + case "concatenating": + return ConcatenatingAudioSource( + children: (json['audioSources'] as List) + .map((s) => AudioSource.fromJson(s)) + .toList()); + case "clipping": + return ClippingAudioSource( + child: AudioSource.fromJson(json['audioSource']), + start: Duration(milliseconds: json['start']), + end: Duration(milliseconds: json['end'])); + default: + throw Exception("Unknown AudioSource type: " + json['type']); + } + } + + AudioSource() : _id = _uuid.v4(); + + @mustCallSuper + Future _setup(AudioPlayer player) async { + _player = player; + player._registerAudioSource(this); + } + + @mustCallSuper + void _dispose() { + _player = null; + } + + bool get _requiresHeaders; + + List get sequence; + + Map toJson(); + + @override + int get hashCode => _id.hashCode; + + @override + bool operator ==(dynamic other) => other is AudioSource && other._id == _id; +} + +/// An [AudioSource] that can appear in a sequence. +abstract class IndexedAudioSource extends AudioSource { + final Object tag; + + IndexedAudioSource(this.tag); + + @override + List get sequence => [this]; +} + +/// An abstract class representing audio sources that are loaded from a URI. +abstract class UriAudioSource extends IndexedAudioSource { + final Uri uri; + final Map headers; + final String _type; + Uri _overrideUri; + File _cacheFile; + + UriAudioSource(this.uri, {this.headers, Object tag, @required String type}) + : _type = type, + super(tag); + + @override + Future _setup(AudioPlayer player) async { + await super._setup(player); + if (uri.scheme == 'asset') { + _overrideUri = Uri.file((await _loadAsset(uri.path)).path); + } else if (headers != null) { + _overrideUri = player._proxy.addUrl(uri, headers); + } + } + + @override + void _dispose() { + if (_cacheFile?.existsSync() == true) { + _cacheFile?.deleteSync(); + } + super._dispose(); + } + + Future _loadAsset(String assetPath) async { + final file = await _getCacheFile(assetPath); + this._cacheFile = file; + if (!file.existsSync()) { + await file.create(recursive: true); + await file.writeAsBytes( + (await rootBundle.load(assetPath)).buffer.asUint8List()); + } + return file; + } + + /// Get file for caching asset media with proper extension + Future _getCacheFile(final String assetPath) async => File(p.join( + (await getTemporaryDirectory()).path, + 'just_audio_asset_cache', + '${_player._id}_$_id${p.extension(assetPath)}')); + + @override + bool get _requiresHeaders => headers != null; + + @override + Map toJson() => { + 'id': _id, + 'type': _type, + 'uri': (_overrideUri ?? uri).toString(), + 'headers': headers, + }; +} + +/// An [AudioSource] representing a regular media file such asn an MP3 or M4A +/// file. The following URI schemes are supported: +/// +/// * file: loads from a local file (provided you give your app permission to +/// access that file). +/// * asset: loads from a Flutter asset (not supported on Web). +/// * http(s): loads from an HTTP(S) resource. +/// +/// On platforms except for the web, the supplied [headers] will be passed with +/// the HTTP(S) request. +class ProgressiveAudioSource extends UriAudioSource { + ProgressiveAudioSource(Uri uri, {Map headers, Object tag}) + : super(uri, headers: headers, tag: tag, type: 'progressive'); +} + +/// An [AudioSource] representing a DASH stream. +/// +/// On platforms except for the web, the supplied [headers] will be passed with +/// the HTTP(S) request. Currently headers are not recursively applied to items +/// the HTTP(S) request. Currently headers are not applied recursively. +class DashAudioSource extends UriAudioSource { + DashAudioSource(Uri uri, {Map headers, Object tag}) + : super(uri, headers: headers, tag: tag, type: 'dash'); +} + +/// An [AudioSource] representing an HLS stream. +/// +/// On platforms except for the web, the supplied [headers] will be passed with +/// the HTTP(S) request. Currently headers are not applied recursively. +class HlsAudioSource extends UriAudioSource { + HlsAudioSource(Uri uri, {Map headers, Object tag}) + : super(uri, headers: headers, tag: tag, type: 'hls'); +} + +/// An [AudioSource] representing a concatenation of multiple audio sources to +/// be played in succession. This can be used to create playlists. Playback +/// between items will be gapless on Android, iOS and macOS, while there will +/// be a slight gap on Web. +/// +/// (Untested) Audio sources can be dynamically added, removed and reordered +/// while the audio is playing. +class ConcatenatingAudioSource extends AudioSource { + final List children; + final bool useLazyPreparation; + + ConcatenatingAudioSource({ + @required this.children, + this.useLazyPreparation = false, + }); + + @override + Future _setup(AudioPlayer player) async { + await super._setup(player); + for (var source in children) { + await source._setup(player); + } + } + + /// (Untested) Appends an [AudioSource]. + Future add(AudioSource audioSource) async { + children.add(audioSource); + if (_player != null) { + await _player + ._invokeMethod('concatenating.add', [_id, audioSource.toJson()]); + } + } + + /// (Untested) Inserts an [AudioSource] at [index]. + Future insert(int index, AudioSource audioSource) async { + children.insert(index, audioSource); + if (_player != null) { + await _player._invokeMethod( + 'concatenating.insert', [_id, index, audioSource.toJson()]); + } + } + + /// (Untested) Appends multiple [AudioSource]s. + Future addAll(List children) async { + this.children.addAll(children); + if (_player != null) { + await _player._invokeMethod('concatenating.addAll', + [_id, children.map((s) => s.toJson()).toList()]); + } + } + + /// (Untested) Insert multiple [AudioSource]s at [index]. + Future insertAll(int index, List children) async { + this.children.insertAll(index, children); + if (_player != null) { + await _player._invokeMethod('concatenating.insertAll', + [_id, index, children.map((s) => s.toJson()).toList()]); + } + } + + /// (Untested) Dynmaically remove an [AudioSource] at [index] after this + /// [ConcatenatingAudioSource] has already been loaded. + Future removeAt(int index) async { + children.removeAt(index); + if (_player != null) { + await _player._invokeMethod('concatenating.removeAt', [_id, index]); + } + } + + /// (Untested) Removes a range of [AudioSource]s from index [start] inclusive + /// to [end] exclusive. + Future removeRange(int start, int end) async { + children.removeRange(start, end); + if (_player != null) { + await _player + ._invokeMethod('concatenating.removeRange', [_id, start, end]); + } + } + + /// (Untested) Moves an [AudioSource] from [currentIndex] to [newIndex]. + Future move(int currentIndex, int newIndex) async { + children.insert(newIndex, children.removeAt(currentIndex)); + if (_player != null) { + await _player + ._invokeMethod('concatenating.move', [_id, currentIndex, newIndex]); + } + } + + /// (Untested) Removes all [AudioSources]. + Future clear() async { + children.clear(); + if (_player != null) { + await _player._invokeMethod('concatenating.clear', [_id]); + } + } + + /// The number of [AudioSource]s. + int get length => children.length; + + operator [](int index) => children[index]; + + @override + List get sequence => + children.expand((s) => s.sequence).toList(); + + @override + bool get _requiresHeaders => + children.any((source) => source._requiresHeaders); + + @override + Map toJson() => { + 'id': _id, + 'type': 'concatenating', + 'audioSources': children.map((source) => source.toJson()).toList(), + 'useLazyPreparation': useLazyPreparation, + }; +} + +/// An [AudioSource] that clips the audio of a [UriAudioSource] between a +/// certain start and end time. +class ClippingAudioSource extends IndexedAudioSource { + final UriAudioSource child; + final Duration start; + final Duration end; + + /// Creates an audio source that clips [child] to the range [start]..[end], + /// where [start] and [end] default to the beginning and end of the original + /// [child] source. + ClippingAudioSource({ + @required this.child, + this.start, + this.end, + Object tag, + }) : super(tag); + + @override + Future _setup(AudioPlayer player) async { + await super._setup(player); + await child._setup(player); + } + + @override + bool get _requiresHeaders => child._requiresHeaders; + + @override + Map toJson() => { + 'id': _id, + 'type': 'clipping', + 'audioSource': child.toJson(), + 'start': start?.inMilliseconds, + 'end': end?.inMilliseconds, + }; +} + +// An [AudioSource] that loops a nested [AudioSource] a finite number of times. +// NOTE: this can be inefficient when using a large loop count. If you wish to +// loop an infinite number of times, use [AudioPlayer.setLoopMode]. +// +// On iOS and macOS, note that [LoopingAudioSource] will provide gapless +// playback while [AudioPlayer.setLoopMode] will not. (This will be supported +// in a future release.) +class LoopingAudioSource extends AudioSource { + AudioSource child; + final int count; + + LoopingAudioSource({ + @required this.child, + this.count, + }) : super(); + + @override + List get sequence => + List.generate(count, (i) => child).expand((s) => s.sequence).toList(); + + @override + bool get _requiresHeaders => child._requiresHeaders; + + @override + Map toJson() => { + 'id': _id, + 'type': 'looping', + 'audioSource': child.toJson(), + 'count': count, + }; +} + +enum LoopMode { off, one, all } diff --git a/just_audio/lib/just_audio_web.dart b/just_audio/lib/just_audio_web.dart new file mode 100644 index 0000000..1df5735 --- /dev/null +++ b/just_audio/lib/just_audio_web.dart @@ -0,0 +1,957 @@ +import 'dart:async'; +import 'dart:html'; +import 'dart:math'; + +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; +import 'package:just_audio/just_audio.dart'; + +final Random _random = Random(); + +class JustAudioPlugin { + static void registerWith(Registrar registrar) { + final MethodChannel channel = MethodChannel( + 'com.ryanheise.just_audio.methods', + const StandardMethodCodec(), + registrar.messenger); + final JustAudioPlugin instance = JustAudioPlugin(registrar); + channel.setMethodCallHandler(instance.handleMethodCall); + } + + final Registrar registrar; + + JustAudioPlugin(this.registrar); + + Future handleMethodCall(MethodCall call) async { + switch (call.method) { + case 'init': + final String id = call.arguments[0]; + new Html5AudioPlayer(id: id, registrar: registrar); + return null; + case 'setIosCategory': + return null; + default: + throw PlatformException(code: 'Unimplemented'); + } + } +} + +abstract class JustAudioPlayer { + final String id; + final Registrar registrar; + final MethodChannel methodChannel; + final PluginEventChannel eventChannel; + final StreamController eventController = StreamController(); + ProcessingState _processingState = ProcessingState.none; + bool _playing = false; + int _index; + + JustAudioPlayer({@required this.id, @required this.registrar}) + : methodChannel = MethodChannel('com.ryanheise.just_audio.methods.$id', + const StandardMethodCodec(), registrar.messenger), + eventChannel = PluginEventChannel('com.ryanheise.just_audio.events.$id', + const StandardMethodCodec(), registrar.messenger) { + methodChannel.setMethodCallHandler(_methodHandler); + eventChannel.controller = eventController; + } + + Future _methodHandler(MethodCall call) async { + try { + final args = call.arguments; + switch (call.method) { + case 'load': + return await load(args[0]); + case 'play': + return await play(); + case 'pause': + return await pause(); + case 'setVolume': + return await setVolume(args[0]); + case 'setSpeed': + return await setSpeed(args[0]); + case 'setLoopMode': + return await setLoopMode(args[0]); + case 'setShuffleModeEnabled': + return await setShuffleModeEnabled(args[0]); + case 'setAutomaticallyWaitsToMinimizeStalling': + return null; + case 'seek': + return await seek(args[0], args[1]); + case 'dispose': + return dispose(); + case 'concatenating.add': + return await concatenatingAdd(args[0], args[1]); + case "concatenating.insert": + return await concatenatingInsert(args[0], args[1], args[2]); + case "concatenating.addAll": + return await concatenatingAddAll(args[0], args[1]); + case "concatenating.insertAll": + return await concatenatingInsertAll(args[0], args[1], args[2]); + case "concatenating.removeAt": + return await concatenatingRemoveAt(args[0], args[1]); + case "concatenating.removeRange": + return await concatenatingRemoveRange(args[0], args[1], args[2]); + case "concatenating.move": + return await concatenatingMove(args[0], args[1], args[2]); + case "concatenating.clear": + return await concatenatingClear(args[0]); + default: + throw PlatformException(code: 'Unimplemented'); + } + } catch (e, stacktrace) { + print("$stacktrace"); + rethrow; + } + } + + Future load(Map source); + + Future play(); + + Future pause(); + + Future setVolume(double volume); + + Future setSpeed(double speed); + + Future setLoopMode(int mode); + + Future setShuffleModeEnabled(bool enabled); + + Future seek(int position, int index); + + @mustCallSuper + void dispose() { + eventController.close(); + } + + Duration getCurrentPosition(); + + Duration getBufferedPosition(); + + Duration getDuration(); + + concatenatingAdd(String playerId, Map source); + + concatenatingInsert(String playerId, int index, Map source); + + concatenatingAddAll(String playerId, List sources); + + concatenatingInsertAll(String playerId, int index, List sources); + + concatenatingRemoveAt(String playerId, int index); + + concatenatingRemoveRange(String playerId, int start, int end); + + concatenatingMove(String playerId, int currentIndex, int newIndex); + + concatenatingClear(String playerId); + + broadcastPlaybackEvent() { + var updateTime = DateTime.now().millisecondsSinceEpoch; + eventController.add({ + 'processingState': _processingState.index, + 'updatePosition': getCurrentPosition()?.inMilliseconds, + 'updateTime': updateTime, + 'bufferedPosition': getBufferedPosition()?.inMilliseconds, + // TODO: Icy Metadata + 'icyMetadata': null, + 'duration': getDuration()?.inMilliseconds, + 'currentIndex': _index, + }); + } + + transition(ProcessingState processingState) { + _processingState = processingState; + broadcastPlaybackEvent(); + } +} + +class Html5AudioPlayer extends JustAudioPlayer { + AudioElement _audioElement = AudioElement(); + Completer _durationCompleter; + AudioSourcePlayer _audioSourcePlayer; + LoopMode _loopMode = LoopMode.off; + bool _shuffleModeEnabled = false; + final Map _audioSourcePlayers = {}; + + Html5AudioPlayer({@required String id, @required Registrar registrar}) + : super(id: id, registrar: registrar) { + _audioElement.addEventListener('durationchange', (event) { + _durationCompleter?.complete(); + broadcastPlaybackEvent(); + }); + _audioElement.addEventListener('error', (event) { + _durationCompleter?.completeError(_audioElement.error); + }); + _audioElement.addEventListener('ended', (event) async { + _currentAudioSourcePlayer.complete(); + }); + _audioElement.addEventListener('timeupdate', (event) { + _currentAudioSourcePlayer.timeUpdated(_audioElement.currentTime); + }); + _audioElement.addEventListener('loadstart', (event) { + transition(ProcessingState.buffering); + }); + _audioElement.addEventListener('waiting', (event) { + transition(ProcessingState.buffering); + }); + _audioElement.addEventListener('stalled', (event) { + transition(ProcessingState.buffering); + }); + _audioElement.addEventListener('canplaythrough', (event) { + transition(ProcessingState.ready); + }); + _audioElement.addEventListener('progress', (event) { + broadcastPlaybackEvent(); + }); + } + + List get order { + final sequence = _audioSourcePlayer.sequence; + List order = List(sequence.length); + if (_shuffleModeEnabled) { + order = _audioSourcePlayer.shuffleOrder; + } else { + for (var i = 0; i < order.length; i++) { + order[i] = i; + } + } + return order; + } + + List getInv(List order) { + List orderInv = List(order.length); + for (var i = 0; i < order.length; i++) { + orderInv[order[i]] = i; + } + return orderInv; + } + + onEnded() async { + if (_loopMode == LoopMode.one) { + await seek(0, null); + play(); + } else { + final order = this.order; + final orderInv = getInv(order); + if (orderInv[_index] + 1 < order.length) { + // move to next item + _index = order[orderInv[_index] + 1]; + await _currentAudioSourcePlayer.load(); + // Should always be true... + if (_playing) { + play(); + } + } else { + // reached end of playlist + if (_loopMode == LoopMode.all) { + // Loop back to the beginning + if (order.length == 1) { + await seek(0, null); + play(); + } else { + _index = order[0]; + await _currentAudioSourcePlayer.load(); + // Should always be true... + if (_playing) { + play(); + } + } + } else { + transition(ProcessingState.completed); + } + } + } + } + + // TODO: Improve efficiency. + IndexedAudioSourcePlayer get _currentAudioSourcePlayer => + _audioSourcePlayer != null && _index < _audioSourcePlayer.sequence.length + ? _audioSourcePlayer.sequence[_index] + : null; + + @override + Future load(Map source) async { + _currentAudioSourcePlayer?.pause(); + _audioSourcePlayer = getAudioSource(source); + _index = 0; + if (_shuffleModeEnabled) { + _audioSourcePlayer?.shuffle(0, _index); + } + return (await _currentAudioSourcePlayer.load()).inMilliseconds; + } + + Future loadUri(final Uri uri) async { + transition(ProcessingState.loading); + final src = uri.toString(); + if (src != _audioElement.src) { + _durationCompleter = Completer(); + _audioElement.src = src; + _audioElement.preload = 'auto'; + _audioElement.load(); + try { + await _durationCompleter.future; + } on MediaError catch (e) { + throw PlatformException( + code: "${e.code}", message: "Failed to load URL"); + } finally { + _durationCompleter = null; + } + } + transition(ProcessingState.ready); + final seconds = _audioElement.duration; + return seconds.isFinite + ? Duration(milliseconds: (seconds * 1000).toInt()) + : null; + } + + @override + Future play() async { + _playing = true; + await _currentAudioSourcePlayer.play(); + } + + @override + Future pause() async { + _playing = false; + _currentAudioSourcePlayer.pause(); + } + + @override + Future setVolume(double volume) async { + _audioElement.volume = volume; + } + + @override + Future setSpeed(double speed) async { + _audioElement.playbackRate = speed; + } + + @override + Future setLoopMode(int mode) async { + _loopMode = LoopMode.values[mode]; + } + + @override + Future setShuffleModeEnabled(bool enabled) async { + _shuffleModeEnabled = enabled; + if (enabled) { + _audioSourcePlayer?.shuffle(0, _index); + } + } + + @override + Future seek(int position, int newIndex) async { + int index = newIndex ?? _index; + if (index != _index) { + _currentAudioSourcePlayer.pause(); + _index = index; + await _currentAudioSourcePlayer.load(); + await _currentAudioSourcePlayer.seek(position); + if (_playing) { + _currentAudioSourcePlayer.play(); + } + } else { + await _currentAudioSourcePlayer.seek(position); + } + } + + ConcatenatingAudioSourcePlayer _concatenating(String playerId) => + _audioSourcePlayers[playerId] as ConcatenatingAudioSourcePlayer; + + concatenatingAdd(String playerId, Map source) { + final playlist = _concatenating(playerId); + playlist.add(getAudioSource(source)); + } + + concatenatingInsert(String playerId, int index, Map source) { + _concatenating(playerId).insert(index, getAudioSource(source)); + if (index <= _index) { + _index++; + } + } + + concatenatingAddAll(String playerId, List sources) { + _concatenating(playerId).addAll(getAudioSources(sources)); + } + + concatenatingInsertAll(String playerId, int index, List sources) { + _concatenating(playerId).insertAll(index, getAudioSources(sources)); + if (index <= _index) { + _index += sources.length; + } + } + + concatenatingRemoveAt(String playerId, int index) async { + // Pause if removing current item + if (_index == index && _playing) { + _currentAudioSourcePlayer.pause(); + } + _concatenating(playerId).removeAt(index); + if (_index == index) { + // Skip backward if there's nothing after this + if (index == _audioSourcePlayer.sequence.length) { + _index--; + } + // Resume playback at the new item (if it exists) + if (_playing && _currentAudioSourcePlayer != null) { + await _currentAudioSourcePlayer.load(); + _currentAudioSourcePlayer.play(); + } + } else if (index < _index) { + // Reflect that the current item has shifted its position + _index--; + } + } + + concatenatingRemoveRange(String playerId, int start, int end) async { + if (_index >= start && _index < end && _playing) { + // Pause if removing current item + _currentAudioSourcePlayer.pause(); + } + _concatenating(playerId).removeRange(start, end); + if (_index >= start && _index < end) { + // Skip backward if there's nothing after this + if (start >= _audioSourcePlayer.sequence.length) { + _index = start - 1; + } else { + _index = start; + } + // Resume playback at the new item (if it exists) + if (_playing && _currentAudioSourcePlayer != null) { + await _currentAudioSourcePlayer.load(); + _currentAudioSourcePlayer.play(); + } + } else if (end <= _index) { + // Reflect that the current item has shifted its position + _index -= (end - start); + } + } + + concatenatingMove(String playerId, int currentIndex, int newIndex) { + _concatenating(playerId).move(currentIndex, newIndex); + if (currentIndex == _index) { + _index = newIndex; + } else if (currentIndex < _index && newIndex >= _index) { + _index--; + } else if (currentIndex > _index && newIndex <= _index) { + _index++; + } + } + + concatenatingClear(String playerId) { + _currentAudioSourcePlayer.pause(); + _concatenating(playerId).clear(); + } + + @override + Duration getCurrentPosition() => _currentAudioSourcePlayer?.position; + + @override + Duration getBufferedPosition() => _currentAudioSourcePlayer?.bufferedPosition; + + @override + Duration getDuration() => _currentAudioSourcePlayer?.duration; + + @override + void dispose() { + _currentAudioSourcePlayer?.pause(); + _audioElement.removeAttribute('src'); + _audioElement.load(); + transition(ProcessingState.none); + super.dispose(); + } + + List getAudioSources(List json) => + json.map((s) => getAudioSource(s)).toList(); + + AudioSourcePlayer getAudioSource(Map json) { + final String id = json['id']; + var audioSourcePlayer = _audioSourcePlayers[id]; + if (audioSourcePlayer == null) { + audioSourcePlayer = decodeAudioSource(json); + _audioSourcePlayers[id] = audioSourcePlayer; + } + return audioSourcePlayer; + } + + AudioSourcePlayer decodeAudioSource(Map json) { + try { + switch (json['type']) { + case 'progressive': + return ProgressiveAudioSourcePlayer( + this, json['id'], Uri.parse(json['uri']), json['headers']); + case "dash": + return DashAudioSourcePlayer( + this, json['id'], Uri.parse(json['uri']), json['headers']); + case "hls": + return HlsAudioSourcePlayer( + this, json['id'], Uri.parse(json['uri']), json['headers']); + case "concatenating": + return ConcatenatingAudioSourcePlayer( + this, + json['id'], + getAudioSources(json['audioSources']), + json['useLazyPreparation']); + case "clipping": + return ClippingAudioSourcePlayer( + this, + json['id'], + getAudioSource(json['audioSource']), + Duration(milliseconds: json['start']), + Duration(milliseconds: json['end'])); + case "looping": + return LoopingAudioSourcePlayer(this, json['id'], + getAudioSource(json['audioSource']), json['count']); + default: + throw Exception("Unknown AudioSource type: " + json['type']); + } + } catch (e, stacktrace) { + print("$stacktrace"); + rethrow; + } + } +} + +abstract class AudioSourcePlayer { + Html5AudioPlayer html5AudioPlayer; + final String id; + + AudioSourcePlayer(this.html5AudioPlayer, this.id); + + List get sequence; + + List get shuffleOrder; + + int shuffle(int treeIndex, int currentIndex); +} + +abstract class IndexedAudioSourcePlayer extends AudioSourcePlayer { + IndexedAudioSourcePlayer(Html5AudioPlayer html5AudioPlayer, String id) + : super(html5AudioPlayer, id); + + Future load(); + + Future play(); + + Future pause(); + + Future seek(int position); + + Future complete(); + + Future timeUpdated(double seconds) async {} + + Duration get duration; + + Duration get position; + + Duration get bufferedPosition; + + AudioElement get _audioElement => html5AudioPlayer._audioElement; + + @override + int shuffle(int treeIndex, int currentIndex) => treeIndex + 1; + + @override + String toString() => "${this.runtimeType}"; +} + +abstract class UriAudioSourcePlayer extends IndexedAudioSourcePlayer { + final Uri uri; + final Map headers; + double _resumePos; + Duration _duration; + Completer _completer; + + UriAudioSourcePlayer( + Html5AudioPlayer html5AudioPlayer, String id, this.uri, this.headers) + : super(html5AudioPlayer, id); + + @override + List get sequence => [this]; + + @override + List get shuffleOrder => [0]; + + @override + Future load() async { + _resumePos = 0.0; + return _duration = await html5AudioPlayer.loadUri(uri); + } + + @override + Future play() async { + _audioElement.currentTime = _resumePos; + _audioElement.play(); + _completer = Completer(); + await _completer.future; + _completer = null; + } + + @override + Future pause() async { + _resumePos = _audioElement.currentTime; + _audioElement.pause(); + _interruptPlay(); + } + + @override + Future seek(int position) async { + _audioElement.currentTime = _resumePos = position / 1000.0; + } + + @override + Future complete() async { + _interruptPlay(); + html5AudioPlayer.onEnded(); + } + + _interruptPlay() { + if (_completer?.isCompleted == false) { + _completer.complete(); + } + } + + @override + Duration get duration { + return _duration; + //final seconds = _audioElement.duration; + //return seconds.isFinite + // ? Duration(milliseconds: (seconds * 1000).toInt()) + // : null; + } + + @override + Duration get position { + double seconds = _audioElement.currentTime; + return Duration(milliseconds: (seconds * 1000).toInt()); + } + + @override + Duration get bufferedPosition { + if (_audioElement.buffered.length > 0) { + return Duration( + milliseconds: + (_audioElement.buffered.end(_audioElement.buffered.length - 1) * + 1000) + .toInt()); + } else { + return Duration.zero; + } + } +} + +class ProgressiveAudioSourcePlayer extends UriAudioSourcePlayer { + ProgressiveAudioSourcePlayer( + Html5AudioPlayer html5AudioPlayer, String id, Uri uri, Map headers) + : super(html5AudioPlayer, id, uri, headers); +} + +class DashAudioSourcePlayer extends UriAudioSourcePlayer { + DashAudioSourcePlayer( + Html5AudioPlayer html5AudioPlayer, String id, Uri uri, Map headers) + : super(html5AudioPlayer, id, uri, headers); +} + +class HlsAudioSourcePlayer extends UriAudioSourcePlayer { + HlsAudioSourcePlayer( + Html5AudioPlayer html5AudioPlayer, String id, Uri uri, Map headers) + : super(html5AudioPlayer, id, uri, headers); +} + +class ConcatenatingAudioSourcePlayer extends AudioSourcePlayer { + static List generateShuffleOrder(int length, [int firstIndex]) { + final shuffleOrder = List(length); + for (var i = 0; i < length; i++) { + final j = _random.nextInt(i + 1); + shuffleOrder[i] = shuffleOrder[j]; + shuffleOrder[j] = i; + } + if (firstIndex != null) { + for (var i = 1; i < length; i++) { + if (shuffleOrder[i] == firstIndex) { + final v = shuffleOrder[0]; + shuffleOrder[0] = shuffleOrder[i]; + shuffleOrder[i] = v; + break; + } + } + } + return shuffleOrder; + } + + final List audioSourcePlayers; + final bool useLazyPreparation; + List _shuffleOrder; + + ConcatenatingAudioSourcePlayer(Html5AudioPlayer html5AudioPlayer, String id, + this.audioSourcePlayers, this.useLazyPreparation) + : _shuffleOrder = generateShuffleOrder(audioSourcePlayers.length), + super(html5AudioPlayer, id); + + @override + List get sequence => + audioSourcePlayers.expand((p) => p.sequence).toList(); + + @override + List get shuffleOrder { + final order = []; + var offset = order.length; + final childOrders = >[]; + for (var audioSourcePlayer in audioSourcePlayers) { + final childShuffleOrder = audioSourcePlayer.shuffleOrder; + childOrders.add(childShuffleOrder.map((i) => i + offset).toList()); + offset += childShuffleOrder.length; + } + for (var i = 0; i < childOrders.length; i++) { + order.addAll(childOrders[_shuffleOrder[i]]); + } + return order; + } + + @override + int shuffle(int treeIndex, int currentIndex) { + int currentChildIndex; + for (var i = 0; i < audioSourcePlayers.length; i++) { + final indexBefore = treeIndex; + final child = audioSourcePlayers[i]; + treeIndex = child.shuffle(treeIndex, currentIndex); + if (currentIndex >= indexBefore && currentIndex < treeIndex) { + currentChildIndex = i; + } else {} + } + // Shuffle so that the current child is first in the shuffle order + _shuffleOrder = + generateShuffleOrder(audioSourcePlayers.length, currentChildIndex); + return treeIndex; + } + + add(AudioSourcePlayer player) { + audioSourcePlayers.add(player); + _shuffleOrder.add(audioSourcePlayers.length - 1); + } + + insert(int index, AudioSourcePlayer player) { + audioSourcePlayers.insert(index, player); + for (var i = 0; i < audioSourcePlayers.length; i++) { + if (_shuffleOrder[i] >= index) { + _shuffleOrder[i]++; + } + } + _shuffleOrder.add(index); + } + + addAll(List players) { + audioSourcePlayers.addAll(players); + _shuffleOrder.addAll( + List.generate(players.length, (i) => audioSourcePlayers.length + i) + .toList() + ..shuffle()); + } + + insertAll(int index, List players) { + audioSourcePlayers.insertAll(index, players); + for (var i = 0; i < audioSourcePlayers.length; i++) { + if (_shuffleOrder[i] >= index) { + _shuffleOrder[i] += players.length; + } + } + _shuffleOrder.addAll( + List.generate(players.length, (i) => index + i).toList()..shuffle()); + } + + removeAt(int index) { + audioSourcePlayers.removeAt(index); + // 0 1 2 3 + // 3 2 0 1 + for (var i = 0; i < audioSourcePlayers.length; i++) { + if (_shuffleOrder[i] > index) { + _shuffleOrder[i]--; + } + } + _shuffleOrder.removeWhere((i) => i == index); + } + + removeRange(int start, int end) { + audioSourcePlayers.removeRange(start, end); + for (var i = 0; i < audioSourcePlayers.length; i++) { + if (_shuffleOrder[i] >= end) { + _shuffleOrder[i] -= (end - start); + } + } + _shuffleOrder.removeWhere((i) => i >= start && i < end); + } + + move(int currentIndex, int newIndex) { + audioSourcePlayers.insert( + newIndex, audioSourcePlayers.removeAt(currentIndex)); + } + + clear() { + audioSourcePlayers.clear(); + _shuffleOrder.clear(); + } +} + +class ClippingAudioSourcePlayer extends IndexedAudioSourcePlayer { + final UriAudioSourcePlayer audioSourcePlayer; + final Duration start; + final Duration end; + Completer _completer; + double _resumePos; + Duration _duration; + + ClippingAudioSourcePlayer(Html5AudioPlayer html5AudioPlayer, String id, + this.audioSourcePlayer, this.start, this.end) + : super(html5AudioPlayer, id); + + @override + List get sequence => [this]; + + @override + List get shuffleOrder => [0]; + + @override + Future load() async { + _resumePos = (start ?? Duration.zero).inMilliseconds / 1000.0; + Duration fullDuration = + await html5AudioPlayer.loadUri(audioSourcePlayer.uri); + _audioElement.currentTime = _resumePos; + _duration = Duration( + milliseconds: min((end ?? fullDuration).inMilliseconds, + fullDuration.inMilliseconds) - + (start ?? Duration.zero).inMilliseconds); + return _duration; + } + + double get remaining => end.inMilliseconds / 1000 - _audioElement.currentTime; + + @override + Future play() async { + _interruptPlay(ClipInterruptReason.simultaneous); + _audioElement.currentTime = _resumePos; + _audioElement.play(); + _completer = Completer(); + ClipInterruptReason reason; + while ((reason = await _completer.future) == ClipInterruptReason.seek) { + _completer = Completer(); + } + if (reason == ClipInterruptReason.end) { + html5AudioPlayer.onEnded(); + } + _completer = null; + } + + @override + Future pause() async { + _interruptPlay(ClipInterruptReason.pause); + _resumePos = _audioElement.currentTime; + _audioElement.pause(); + } + + @override + Future seek(int position) async { + _interruptPlay(ClipInterruptReason.seek); + _audioElement.currentTime = + _resumePos = start.inMilliseconds / 1000.0 + position / 1000.0; + } + + @override + Future complete() async { + _interruptPlay(ClipInterruptReason.end); + } + + @override + Future timeUpdated(double seconds) async { + if (end != null) { + if (seconds >= end.inMilliseconds / 1000) { + _interruptPlay(ClipInterruptReason.end); + } + } + } + + @override + Duration get duration { + return _duration; + } + + @override + Duration get position { + double seconds = _audioElement.currentTime; + var position = Duration(milliseconds: (seconds * 1000).toInt()); + if (start != null) { + position -= start; + } + if (position < Duration.zero) { + position = Duration.zero; + } + return position; + } + + @override + Duration get bufferedPosition { + if (_audioElement.buffered.length > 0) { + var seconds = + _audioElement.buffered.end(_audioElement.buffered.length - 1); + var position = Duration(milliseconds: (seconds * 1000).toInt()); + if (start != null) { + position -= start; + } + if (position < Duration.zero) { + position = Duration.zero; + } + if (duration != null && position > duration) { + position = duration; + } + return position; + } else { + return Duration.zero; + } + } + + _interruptPlay(ClipInterruptReason reason) { + if (_completer?.isCompleted == false) { + _completer.complete(reason); + } + } +} + +enum ClipInterruptReason { end, pause, seek, simultaneous } + +class LoopingAudioSourcePlayer extends AudioSourcePlayer { + final AudioSourcePlayer audioSourcePlayer; + final int count; + + LoopingAudioSourcePlayer(Html5AudioPlayer html5AudioPlayer, String id, + this.audioSourcePlayer, this.count) + : super(html5AudioPlayer, id); + + @override + List get sequence => + List.generate(count, (i) => audioSourcePlayer) + .expand((p) => p.sequence) + .toList(); + + @override + List get shuffleOrder { + final order = []; + var offset = order.length; + for (var i = 0; i < count; i++) { + final childShuffleOrder = audioSourcePlayer.shuffleOrder; + order.addAll(childShuffleOrder.map((i) => i + offset).toList()); + offset += childShuffleOrder.length; + } + return order; + } + + @override + int shuffle(int treeIndex, int currentIndex) { + for (var i = 0; i < count; i++) { + treeIndex = audioSourcePlayer.shuffle(treeIndex, currentIndex); + } + return treeIndex; + } +} diff --git a/just_audio/macos/.gitignore b/just_audio/macos/.gitignore new file mode 100644 index 0000000..aa479fd --- /dev/null +++ b/just_audio/macos/.gitignore @@ -0,0 +1,37 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/Generated.xcconfig +/Flutter/flutter_export_environment.sh \ No newline at end of file diff --git a/just_audio/macos/Assets/.gitkeep b/just_audio/macos/Assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/just_audio/macos/Classes/AudioPlayer.h b/just_audio/macos/Classes/AudioPlayer.h new file mode 100644 index 0000000..d64e13d --- /dev/null +++ b/just_audio/macos/Classes/AudioPlayer.h @@ -0,0 +1,21 @@ +#import + +@interface AudioPlayer : NSObject + +- (instancetype)initWithRegistrar:(NSObject *)registrar playerId:(NSString*)idParam configuredSession:(BOOL)configuredSession; + +@end + +enum ProcessingState { + none, + loading, + buffering, + ready, + completed +}; + +enum LoopMode { + loopOff, + loopOne, + loopAll +}; diff --git a/just_audio/macos/Classes/AudioPlayer.m b/just_audio/macos/Classes/AudioPlayer.m new file mode 100644 index 0000000..ccbfdea --- /dev/null +++ b/just_audio/macos/Classes/AudioPlayer.m @@ -0,0 +1,1138 @@ +#import "AudioPlayer.h" +#import "AudioSource.h" +#import "IndexedAudioSource.h" +#import "UriAudioSource.h" +#import "ConcatenatingAudioSource.h" +#import "LoopingAudioSource.h" +#import "ClippingAudioSource.h" +#import +#import +#include + +// TODO: Check for and report invalid state transitions. +// TODO: Apply Apple's guidance on seeking: https://developer.apple.com/library/archive/qa/qa1820/_index.html +@implementation AudioPlayer { + NSObject* _registrar; + FlutterMethodChannel *_methodChannel; + FlutterEventChannel *_eventChannel; + FlutterEventSink _eventSink; + NSString *_playerId; + AVQueuePlayer *_player; + AudioSource *_audioSource; + NSMutableArray *_indexedAudioSources; + NSMutableArray *_order; + NSMutableArray *_orderInv; + int _index; + enum ProcessingState _processingState; + enum LoopMode _loopMode; + BOOL _shuffleModeEnabled; + long long _updateTime; + int _updatePosition; + int _lastPosition; + int _bufferedPosition; + // Set when the current item hasn't been played yet so we aren't sure whether sufficient audio has been buffered. + BOOL _bufferUnconfirmed; + CMTime _seekPos; + FlutterResult _loadResult; + FlutterResult _playResult; + id _timeObserver; + BOOL _automaticallyWaitsToMinimizeStalling; + BOOL _configuredSession; + BOOL _playing; +} + +- (instancetype)initWithRegistrar:(NSObject *)registrar playerId:(NSString*)idParam configuredSession:(BOOL)configuredSession { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + _registrar = registrar; + _playerId = idParam; + _configuredSession = configuredSession; + _methodChannel = + [FlutterMethodChannel methodChannelWithName:[NSMutableString stringWithFormat:@"com.ryanheise.just_audio.methods.%@", _playerId] + binaryMessenger:[registrar messenger]]; + _eventChannel = + [FlutterEventChannel eventChannelWithName:[NSMutableString stringWithFormat:@"com.ryanheise.just_audio.events.%@", _playerId] + binaryMessenger:[registrar messenger]]; + [_eventChannel setStreamHandler:self]; + _index = 0; + _processingState = none; + _loopMode = loopOff; + _shuffleModeEnabled = NO; + _player = nil; + _audioSource = nil; + _indexedAudioSources = nil; + _order = nil; + _orderInv = nil; + _seekPos = kCMTimeInvalid; + _timeObserver = 0; + _updatePosition = 0; + _updateTime = 0; + _lastPosition = 0; + _bufferedPosition = 0; + _bufferUnconfirmed = NO; + _playing = NO; + _loadResult = nil; + _playResult = nil; + _automaticallyWaitsToMinimizeStalling = YES; + __weak __typeof__(self) weakSelf = self; + [_methodChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { + [weakSelf handleMethodCall:call result:result]; + }]; + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { + NSArray* args = (NSArray*)call.arguments; + if ([@"load" isEqualToString:call.method]) { + [self load:args[0] result:result]; + } else if ([@"play" isEqualToString:call.method]) { + [self play:result]; + } else if ([@"pause" isEqualToString:call.method]) { + [self pause]; + result(nil); + } else if ([@"setVolume" isEqualToString:call.method]) { + [self setVolume:(float)[args[0] doubleValue]]; + result(nil); + } else if ([@"setSpeed" isEqualToString:call.method]) { + [self setSpeed:(float)[args[0] doubleValue]]; + result(nil); + } else if ([@"setLoopMode" isEqualToString:call.method]) { + [self setLoopMode:[args[0] intValue]]; + result(nil); + } else if ([@"setShuffleModeEnabled" isEqualToString:call.method]) { + [self setShuffleModeEnabled:(BOOL)[args[0] boolValue]]; + result(nil); + } else if ([@"setAutomaticallyWaitsToMinimizeStalling" isEqualToString:call.method]) { + [self setAutomaticallyWaitsToMinimizeStalling:(BOOL)[args[0] boolValue]]; + result(nil); + } else if ([@"seek" isEqualToString:call.method]) { + CMTime position = args[0] == [NSNull null] ? kCMTimePositiveInfinity : CMTimeMake([args[0] intValue], 1000); + [self seek:position index:args[1] completionHandler:^(BOOL finished) { + result(nil); + }]; + result(nil); + } else if ([@"dispose" isEqualToString:call.method]) { + [self dispose]; + result(nil); + } else if ([@"concatenating.add" isEqualToString:call.method]) { + [self concatenatingAdd:(NSString*)args[0] source:(NSDictionary*)args[1]]; + result(nil); + } else if ([@"concatenating.insert" isEqualToString:call.method]) { + [self concatenatingInsert:(NSString*)args[0] index:[args[1] intValue] source:(NSDictionary*)args[2]]; + result(nil); + } else if ([@"concatenating.addAll" isEqualToString:call.method]) { + [self concatenatingAddAll:(NSString*)args[0] sources:(NSArray*)args[1]]; + result(nil); + } else if ([@"concatenating.insertAll" isEqualToString:call.method]) { + [self concatenatingInsertAll:(NSString*)args[0] index:[args[1] intValue] sources:(NSArray*)args[2]]; + result(nil); + } else if ([@"concatenating.removeAt" isEqualToString:call.method]) { + [self concatenatingRemoveAt:(NSString*)args[0] index:(int)args[1]]; + result(nil); + } else if ([@"concatenating.removeRange" isEqualToString:call.method]) { + [self concatenatingRemoveRange:(NSString*)args[0] start:[args[1] intValue] end:[args[2] intValue]]; + result(nil); + } else if ([@"concatenating.move" isEqualToString:call.method]) { + [self concatenatingMove:(NSString*)args[0] currentIndex:[args[1] intValue] newIndex:[args[2] intValue]]; + result(nil); + } else if ([@"concatenating.clear" isEqualToString:call.method]) { + [self concatenatingClear:(NSString*)args[0]]; + result(nil); + } else { + result(FlutterMethodNotImplemented); + } +} + +// Untested +- (void)concatenatingAdd:(NSString *)catId source:(NSDictionary *)source { + [self concatenatingInsertAll:catId index:-1 sources:@[source]]; +} + +// Untested +- (void)concatenatingInsert:(NSString *)catId index:(int)index source:(NSDictionary *)source { + [self concatenatingInsertAll:catId index:index sources:@[source]]; +} + +// Untested +- (void)concatenatingAddAll:(NSString *)catId sources:(NSArray *)sources { + [self concatenatingInsertAll:catId index:-1 sources:sources]; +} + +// Untested +- (void)concatenatingInsertAll:(NSString *)catId index:(int)index sources:(NSArray *)sources { + // Find all duplicates of the identified ConcatenatingAudioSource. + NSMutableArray *matches = [[NSMutableArray alloc] init]; + [_audioSource findById:catId matches:matches]; + // Add each new source to each match. + for (int i = 0; i < matches.count; i++) { + ConcatenatingAudioSource *catSource = (ConcatenatingAudioSource *)matches[i]; + int idx = index >= 0 ? index : catSource.count; + NSMutableArray *audioSources = [self decodeAudioSources:sources]; + for (int j = 0; j < audioSources.count; j++) { + AudioSource *audioSource = audioSources[j]; + [catSource insertSource:audioSource atIndex:(idx + j)]; + } + } + // Index the new audio sources. + _indexedAudioSources = [[NSMutableArray alloc] init]; + [_audioSource buildSequence:_indexedAudioSources treeIndex:0]; + for (int i = 0; i < [_indexedAudioSources count]; i++) { + IndexedAudioSource *audioSource = _indexedAudioSources[i]; + if (!audioSource.isAttached) { + audioSource.playerItem.audioSource = audioSource; + [self addItemObservers:audioSource.playerItem]; + } + } + [self updateOrder]; + if (_player.currentItem) { + _index = [self indexForItem:_player.currentItem]; + } else { + _index = 0; + } + [self enqueueFrom:_index]; + // Notify each new IndexedAudioSource that it's been attached to the player. + for (int i = 0; i < [_indexedAudioSources count]; i++) { + if (!_indexedAudioSources[i].isAttached) { + [_indexedAudioSources[i] attach:_player]; + } + } + [self broadcastPlaybackEvent]; +} + +// Untested +- (void)concatenatingRemoveAt:(NSString *)catId index:(int)index { + [self concatenatingRemoveRange:catId start:index end:(index + 1)]; +} + +// Untested +- (void)concatenatingRemoveRange:(NSString *)catId start:(int)start end:(int)end { + // Find all duplicates of the identified ConcatenatingAudioSource. + NSMutableArray *matches = [[NSMutableArray alloc] init]; + [_audioSource findById:catId matches:matches]; + // Remove range from each match. + for (int i = 0; i < matches.count; i++) { + ConcatenatingAudioSource *catSource = (ConcatenatingAudioSource *)matches[i]; + int endIndex = end >= 0 ? end : catSource.count; + [catSource removeSourcesFromIndex:start toIndex:endIndex]; + } + // Re-index the remaining audio sources. + NSArray *oldIndexedAudioSources = _indexedAudioSources; + _indexedAudioSources = [[NSMutableArray alloc] init]; + [_audioSource buildSequence:_indexedAudioSources treeIndex:0]; + for (int i = 0, j = 0; i < _indexedAudioSources.count; i++, j++) { + IndexedAudioSource *audioSource = _indexedAudioSources[i]; + while (audioSource != oldIndexedAudioSources[j]) { + [self removeItemObservers:oldIndexedAudioSources[j].playerItem]; + if (j < _index) { + _index--; + } else if (j == _index) { + // The currently playing item was removed. + } + j++; + } + } + [self updateOrder]; + if (_index >= _indexedAudioSources.count) _index = _indexedAudioSources.count - 1; + if (_index < 0) _index = 0; + [self enqueueFrom:_index]; + [self broadcastPlaybackEvent]; +} + +// Untested +- (void)concatenatingMove:(NSString *)catId currentIndex:(int)currentIndex newIndex:(int)newIndex { + // Find all duplicates of the identified ConcatenatingAudioSource. + NSMutableArray *matches = [[NSMutableArray alloc] init]; + [_audioSource findById:catId matches:matches]; + // Move range within each match. + for (int i = 0; i < matches.count; i++) { + ConcatenatingAudioSource *catSource = (ConcatenatingAudioSource *)matches[i]; + [catSource moveSourceFromIndex:currentIndex toIndex:newIndex]; + } + // Re-index the audio sources. + _indexedAudioSources = [[NSMutableArray alloc] init]; + [_audioSource buildSequence:_indexedAudioSources treeIndex:0]; + _index = [self indexForItem:_player.currentItem]; + [self broadcastPlaybackEvent]; +} + +// Untested +- (void)concatenatingClear:(NSString *)catId { + [self concatenatingRemoveRange:catId start:0 end:-1]; +} + +- (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink { + _eventSink = eventSink; + return nil; +} + +- (FlutterError*)onCancelWithArguments:(id)arguments { + _eventSink = nil; + return nil; +} + +- (void)checkForDiscontinuity { + if (!_eventSink) return; + if (!_playing || CMTIME_IS_VALID(_seekPos) || _processingState == completed) return; + int position = [self getCurrentPosition]; + if (_processingState == buffering) { + if (position > _lastPosition) { + [self leaveBuffering:@"stall ended"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } else { + long long now = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0); + long long timeSinceLastUpdate = now - _updateTime; + long long expectedPosition = _updatePosition + (long long)(timeSinceLastUpdate * _player.rate); + long long drift = position - expectedPosition; + //NSLog(@"position: %d, drift: %lld", position, drift); + // Update if we've drifted or just started observing + if (_updateTime == 0L) { + [self broadcastPlaybackEvent]; + } else if (drift < -100) { + [self enterBuffering:@"stalling"]; + NSLog(@"Drift: %lld", drift); + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } + _lastPosition = position; +} + +- (void)enterBuffering:(NSString *)reason { + NSLog(@"ENTER BUFFERING: %@", reason); + _processingState = buffering; +} + +- (void)leaveBuffering:(NSString *)reason { + NSLog(@"LEAVE BUFFERING: %@", reason); + _processingState = ready; +} + +- (void)broadcastPlaybackEvent { + if (!_eventSink) return; + _eventSink(@{ + @"processingState": @(_processingState), + @"updatePosition": @(_updatePosition), + @"updateTime": @(_updateTime), + // TODO: buffer position + @"bufferedPosition": @(_updatePosition), + // TODO: Icy Metadata + @"icyMetadata": [NSNull null], + @"duration": @([self getDuration]), + @"currentIndex": @(_index), + }); +} + +- (int)getCurrentPosition { + if (_processingState == none || _processingState == loading) { + return 0; + } else if (CMTIME_IS_VALID(_seekPos)) { + return (int)(1000 * CMTimeGetSeconds(_seekPos)); + } else if (_indexedAudioSources) { + int ms = (int)(1000 * CMTimeGetSeconds(_indexedAudioSources[_index].position)); + if (ms < 0) ms = 0; + return ms; + } else { + return 0; + } +} + +- (int)getBufferedPosition { + if (_processingState == none || _processingState == loading) { + return 0; + } else if (_indexedAudioSources) { + int ms = (int)(1000 * CMTimeGetSeconds(_indexedAudioSources[_index].bufferedPosition)); + if (ms < 0) ms = 0; + return ms; + } else { + return 0; + } +} + +- (int)getDuration { + if (_processingState == none) { + return -1; + } else if (_indexedAudioSources) { + int v = (int)(1000 * CMTimeGetSeconds(_indexedAudioSources[_index].duration)); + return v; + } else { + return 0; + } +} + +- (void)removeItemObservers:(AVPlayerItem *)playerItem { + [playerItem removeObserver:self forKeyPath:@"status"]; + [playerItem removeObserver:self forKeyPath:@"playbackBufferEmpty"]; + [playerItem removeObserver:self forKeyPath:@"playbackBufferFull"]; + //[playerItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemPlaybackStalledNotification object:playerItem]; +} + +- (void)addItemObservers:(AVPlayerItem *)playerItem { + // Get notified when the item is loaded or had an error loading + [playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; + // Get notified of the buffer state + [playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; + [playerItem addObserver:self forKeyPath:@"playbackBufferFull" options:NSKeyValueObservingOptionNew context:nil]; + [playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; + //[playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; + // Get notified when playback has reached the end + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onComplete:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; + // Get notified when playback stops due to a failure (currently unused) + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFailToComplete:) name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem]; + // Get notified when playback stalls (currently unused) + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onItemStalled:) name:AVPlayerItemPlaybackStalledNotification object:playerItem]; +} + +- (NSMutableArray *)decodeAudioSources:(NSArray *)data { + NSMutableArray *array = [[NSMutableArray alloc] init]; + for (int i = 0; i < [data count]; i++) { + AudioSource *source = [self decodeAudioSource:data[i]]; + [array addObject:source]; + } + return array; +} + +- (AudioSource *)decodeAudioSource:(NSDictionary *)data { + NSString *type = data[@"type"]; + if ([@"progressive" isEqualToString:type]) { + return [[UriAudioSource alloc] initWithId:data[@"id"] uri:data[@"uri"]]; + } else if ([@"dash" isEqualToString:type]) { + return [[UriAudioSource alloc] initWithId:data[@"id"] uri:data[@"uri"]]; + } else if ([@"hls" isEqualToString:type]) { + return [[UriAudioSource alloc] initWithId:data[@"id"] uri:data[@"uri"]]; + } else if ([@"concatenating" isEqualToString:type]) { + return [[ConcatenatingAudioSource alloc] initWithId:data[@"id"] + audioSources:[self decodeAudioSources:data[@"audioSources"]]]; + } else if ([@"clipping" isEqualToString:type]) { + return [[ClippingAudioSource alloc] initWithId:data[@"id"] + audioSource:[self decodeAudioSource:data[@"audioSource"]] + start:data[@"start"] + end:data[@"end"]]; + } else if ([@"looping" isEqualToString:type]) { + NSMutableArray *childSources = [NSMutableArray new]; + int count = [data[@"count"] intValue]; + for (int i = 0; i < count; i++) { + [childSources addObject:[self decodeAudioSource:data[@"audioSource"]]]; + } + return [[LoopingAudioSource alloc] initWithId:data[@"id"] audioSources:childSources]; + } else { + return nil; + } +} + +- (void)enqueueFrom:(int)index { + int oldIndex = _index; + _index = index; + + // Update the queue while keeping the currently playing item untouched. + + /* NSLog(@"before reorder: _player.items.count: ", _player.items.count); */ + /* [self dumpQueue]; */ + + // First, remove all _player items except for the currently playing one (if any). + IndexedPlayerItem *oldItem = _player.currentItem; + IndexedPlayerItem *existingItem = nil; + NSArray *oldPlayerItems = [NSArray arrayWithArray:_player.items]; + // In the first pass, preserve the old and new items. + for (int i = 0; i < oldPlayerItems.count; i++) { + if (oldPlayerItems[i] == _indexedAudioSources[_index].playerItem) { + // Preserve and tag new item if it is already in the queue. + existingItem = oldPlayerItems[i]; + } else if (oldPlayerItems[i] == oldItem) { + // Temporarily preserve old item, just to avoid jumping to + // intermediate queue positions unnecessarily. We only want to jump + // once to _index. + } else { + [_player removeItem:oldPlayerItems[i]]; + } + } + // In the second pass, remove the old item (if different from new item). + if (_index != oldIndex) { + [_player removeItem:oldItem]; + } + + /* NSLog(@"inter order: _player.items.count: ", _player.items.count); */ + /* [self dumpQueue]; */ + + // Regenerate queue + BOOL include = NO; + for (int i = 0; i < [_order count]; i++) { + int si = [_order[i] intValue]; + if (si == _index) include = YES; + if (include && _indexedAudioSources[si].playerItem != existingItem) { + [_player insertItem:_indexedAudioSources[si].playerItem afterItem:nil]; + } + } + + /* NSLog(@"after reorder: _player.items.count: ", _player.items.count); */ + /* [self dumpQueue]; */ + + if (_processingState != loading && oldItem != _indexedAudioSources[_index].playerItem) { + // || !_player.currentItem.playbackLikelyToKeepUp; + if (_player.currentItem.playbackBufferEmpty) { + [self enterBuffering:@"enqueueFrom playbackBufferEmpty"]; + } else { + [self leaveBuffering:@"enqueueFrom !playbackBufferEmpty"]; + } + [self updatePosition]; + } +} + +- (void)updatePosition { + _updatePosition = [self getCurrentPosition]; + _updateTime = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0); +} + +- (void)load:(NSDictionary *)source result:(FlutterResult)result { + if (!_playing) { + [_player pause]; + } + if (_processingState == loading) { + [self abortExistingConnection]; + } + _loadResult = result; + _index = 0; + [self updatePosition]; + _processingState = loading; + [self broadcastPlaybackEvent]; + // Remove previous observers + if (_indexedAudioSources) { + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [self removeItemObservers:_indexedAudioSources[i].playerItem]; + } + } + // Decode audio source + if (_audioSource && [@"clipping" isEqualToString:source[@"type"]]) { + // Check if we're clipping an audio source that was previously loaded. + UriAudioSource *child = nil; + if ([_audioSource isKindOfClass:[ClippingAudioSource class]]) { + ClippingAudioSource *clipper = (ClippingAudioSource *)_audioSource; + child = clipper.audioSource; + } else if ([_audioSource isKindOfClass:[UriAudioSource class]]) { + child = (UriAudioSource *)_audioSource; + } + if (child) { + _audioSource = [[ClippingAudioSource alloc] initWithId:source[@"id"] + audioSource:child + start:source[@"start"] + end:source[@"end"]]; + } else { + _audioSource = [self decodeAudioSource:source]; + } + } else { + _audioSource = [self decodeAudioSource:source]; + } + _indexedAudioSources = [[NSMutableArray alloc] init]; + [_audioSource buildSequence:_indexedAudioSources treeIndex:0]; + for (int i = 0; i < [_indexedAudioSources count]; i++) { + IndexedAudioSource *source = _indexedAudioSources[i]; + [self addItemObservers:source.playerItem]; + source.playerItem.audioSource = source; + } + [self updateOrder]; + // Set up an empty player + if (!_player) { + _player = [[AVQueuePlayer alloc] initWithItems:@[]]; + if (@available(macOS 10.12, iOS 10.0, *)) { + _player.automaticallyWaitsToMinimizeStalling = _automaticallyWaitsToMinimizeStalling; + // TODO: Remove these observers in dispose. + [_player addObserver:self + forKeyPath:@"timeControlStatus" + options:NSKeyValueObservingOptionNew + context:nil]; + } + [_player addObserver:self + forKeyPath:@"currentItem" + options:NSKeyValueObservingOptionNew + context:nil]; + // TODO: learn about the different ways to define weakSelf. + //__weak __typeof__(self) weakSelf = self; + //typeof(self) __weak weakSelf = self; + __unsafe_unretained typeof(self) weakSelf = self; + if (@available(macOS 10.12, iOS 10.0, *)) {} + else { + _timeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMake(200, 1000) + queue:nil + usingBlock:^(CMTime time) { + [weakSelf checkForDiscontinuity]; + } + ]; + } + } + // Initialise the AVQueuePlayer with items. + [self enqueueFrom:0]; + // Notify each IndexedAudioSource that it's been attached to the player. + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [_indexedAudioSources[i] attach:_player]; + } + + if (_player.currentItem.status == AVPlayerItemStatusReadyToPlay) { + _loadResult(@([self getDuration])); + _loadResult = nil; + } else { + // We send result after the playerItem is ready in observeValueForKeyPath. + } + [self broadcastPlaybackEvent]; +} + +- (void)updateOrder { + if (_shuffleModeEnabled) { + [_audioSource shuffle:0 currentIndex: _index]; + } + _orderInv = [NSMutableArray arrayWithCapacity:[_indexedAudioSources count]]; + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [_orderInv addObject:@(0)]; + } + if (_shuffleModeEnabled) { + _order = [_audioSource getShuffleOrder]; + } else { + NSMutableArray *order = [[NSMutableArray alloc] init]; + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [order addObject:@(i)]; + } + _order = order; + } + for (int i = 0; i < [_indexedAudioSources count]; i++) { + _orderInv[[_order[i] intValue]] = @(i); + } +} + +- (void)onItemStalled:(NSNotification *)notification { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)notification.object; + NSLog(@"onItemStalled"); +} + +- (void)onFailToComplete:(NSNotification *)notification { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)notification.object; + NSLog(@"onFailToComplete"); +} + +- (void)onComplete:(NSNotification *)notification { + NSLog(@"onComplete"); + if (_loopMode == loopOne) { + [self seek:kCMTimeZero index:@(_index) completionHandler:^(BOOL finished) { + // XXX: Not necessary? + [self play]; + }]; + } else { + IndexedPlayerItem *endedPlayerItem = (IndexedPlayerItem *)notification.object; + IndexedAudioSource *endedSource = endedPlayerItem.audioSource; + // When an item ends, seek back to its beginning. + [endedSource seek:kCMTimeZero]; + + if ([_orderInv[_index] intValue] + 1 < [_order count]) { + // account for automatic move to next item + _index = [_order[[_orderInv[_index] intValue] + 1] intValue]; + NSLog(@"advance to next: index = %d", _index); + [self broadcastPlaybackEvent]; + } else { + // reached end of playlist + if (_loopMode == loopAll) { + NSLog(@"Loop back to first item"); + // Loop back to the beginning + // TODO: Currently there will be a gap at the loop point. + // Maybe we can do something clever by temporarily adding the + // first playlist item at the end of the queue, although this + // will affect any code that assumes the queue always + // corresponds to a contiguous region of the indexed audio + // sources. + // For now we just do a seek back to the start. + if ([_order count] == 1) { + [self seek:kCMTimeZero index:[NSNull null] completionHandler:^(BOOL finished) { + // XXX: Necessary? + [self play]; + }]; + } else { + [self seek:kCMTimeZero index:_order[0] completionHandler:^(BOOL finished) { + // XXX: Necessary? + [self play]; + }]; + } + } else { + [self complete]; + } + } + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + + if ([keyPath isEqualToString:@"status"]) { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)object; + AVPlayerItemStatus status = AVPlayerItemStatusUnknown; + NSNumber *statusNumber = change[NSKeyValueChangeNewKey]; + if ([statusNumber isKindOfClass:[NSNumber class]]) { + status = statusNumber.intValue; + } + switch (status) { + case AVPlayerItemStatusReadyToPlay: { + if (playerItem != _player.currentItem) return; + // Detect buffering in different ways depending on whether we're playing + if (_playing) { + if (@available(macOS 10.12, iOS 10.0, *)) { + if (_player.timeControlStatus == AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate) { + [self enterBuffering:@"ready to play: playing, waitingToPlay"]; + } else { + [self leaveBuffering:@"ready to play: playing, !waitingToPlay"]; + } + [self updatePosition]; + } else { + // If this happens when we're playing, check whether buffer is confirmed + if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { + // Stay in bufering - XXX Test + [self enterBuffering:@"ready to play: playing, bufferUnconfirmed && !playbackBufferFull"]; + } else { + if (_player.currentItem.playbackBufferEmpty) { + // !_player.currentItem.playbackLikelyToKeepUp; + [self enterBuffering:@"ready to play: playing, playbackBufferEmpty"]; + } else { + [self leaveBuffering:@"ready to play: playing, !playbackBufferEmpty"]; + } + [self updatePosition]; + } + } + } else { + if (_player.currentItem.playbackBufferEmpty) { + [self enterBuffering:@"ready to play: !playing, playbackBufferEmpty"]; + // || !_player.currentItem.playbackLikelyToKeepUp; + } else { + [self leaveBuffering:@"ready to play: !playing, !playbackBufferEmpty"]; + } + [self updatePosition]; + } + [self broadcastPlaybackEvent]; + if (_loadResult) { + _loadResult(@([self getDuration])); + _loadResult = nil; + } + break; + } + case AVPlayerItemStatusFailed: { + NSLog(@"AVPlayerItemStatusFailed"); + [self sendErrorForItem:playerItem]; + break; + } + case AVPlayerItemStatusUnknown: + break; + } + } else if ([keyPath isEqualToString:@"playbackBufferEmpty"] || [keyPath isEqualToString:@"playbackBufferFull"]) { + // Use these values to detect buffering. + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)object; + if (playerItem != _player.currentItem) return; + // If there's a seek in progress, these values are unreliable + if (CMTIME_IS_VALID(_seekPos)) return; + // Detect buffering in different ways depending on whether we're playing + if (_playing) { + if (@available(macOS 10.12, iOS 10.0, *)) { + // We handle this with timeControlStatus instead. + } else { + if (_bufferUnconfirmed && playerItem.playbackBufferFull) { + _bufferUnconfirmed = NO; + [self leaveBuffering:@"playing, _bufferUnconfirmed && playbackBufferFull"]; + [self updatePosition]; + NSLog(@"Buffering confirmed! leaving buffering"); + [self broadcastPlaybackEvent]; + } + } + } else { + if (playerItem.playbackBufferEmpty) { + [self enterBuffering:@"!playing, playbackBufferEmpty"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } else if (!playerItem.playbackBufferEmpty || playerItem.playbackBufferFull) { + _processingState = ready; + [self leaveBuffering:@"!playing, !playbackBufferEmpty || playbackBufferFull"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } + /* } else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) { */ + } else if ([keyPath isEqualToString:@"timeControlStatus"]) { + if (@available(macOS 10.12, iOS 10.0, *)) { + AVPlayerTimeControlStatus status = AVPlayerTimeControlStatusPaused; + NSNumber *statusNumber = change[NSKeyValueChangeNewKey]; + if ([statusNumber isKindOfClass:[NSNumber class]]) { + status = statusNumber.intValue; + } + switch (status) { + case AVPlayerTimeControlStatusPaused: + //NSLog(@"AVPlayerTimeControlStatusPaused"); + break; + case AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate: + //NSLog(@"AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate"); + if (_processingState != completed) { + [self enterBuffering:@"timeControlStatus"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } else { + NSLog(@"Ignoring wait signal because we reached the end"); + } + break; + case AVPlayerTimeControlStatusPlaying: + [self leaveBuffering:@"timeControlStatus"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + break; + } + } + } else if ([keyPath isEqualToString:@"currentItem"] && _player.currentItem) { + if (_player.currentItem.status == AVPlayerItemStatusFailed) { + if ([_orderInv[_index] intValue] + 1 < [_order count]) { + // account for automatic move to next item + _index = [_order[[_orderInv[_index] intValue] + 1] intValue]; + NSLog(@"advance to next on error: index = %d", _index); + [self broadcastPlaybackEvent]; + } else { + NSLog(@"error on last item"); + } + return; + } else { + int expectedIndex = [self indexForItem:_player.currentItem]; + if (_index != expectedIndex) { + // AVQueuePlayer will sometimes skip over error items without + // notifying this observer. + NSLog(@"Queue change detected. Adjusting index from %d -> %d", _index, expectedIndex); + _index = expectedIndex; + [self broadcastPlaybackEvent]; + } + } + //NSLog(@"currentItem changed. _index=%d", _index); + _bufferUnconfirmed = YES; + // If we've skipped or transitioned to a new item and we're not + // currently in the middle of a seek + if (CMTIME_IS_INVALID(_seekPos) && _player.currentItem.status == AVPlayerItemStatusReadyToPlay) { + [self updatePosition]; + IndexedAudioSource *source = ((IndexedPlayerItem *)_player.currentItem).audioSource; + // We should already be at position zero but for + // ClippingAudioSource it might be off by some milliseconds so we + // consider anything <= 100 as close enough. + if ((int)(1000 * CMTimeGetSeconds(source.position)) > 100) { + NSLog(@"On currentItem change, seeking back to zero"); + BOOL shouldResumePlayback = NO; + AVPlayerActionAtItemEnd originalEndAction = _player.actionAtItemEnd; + if (_playing && CMTimeGetSeconds(CMTimeSubtract(source.position, source.duration)) >= 0) { + NSLog(@"Need to pause while rewinding because we're at the end"); + shouldResumePlayback = YES; + _player.actionAtItemEnd = AVPlayerActionAtItemEndPause; + [_player pause]; + } + [self enterBuffering:@"currentItem changed, seeking"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + [source seek:kCMTimeZero completionHandler:^(BOOL finished) { + [self leaveBuffering:@"currentItem changed, finished seek"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + if (shouldResumePlayback) { + _player.actionAtItemEnd = originalEndAction; + // TODO: This logic is almost duplicated in seek. See if we can reuse this code. + [_player play]; + } + }]; + } else { + // Already at zero, no need to seek. + } + } + } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)object; + if (playerItem != _player.currentItem) return; + int pos = [self getBufferedPosition]; + if (pos != _bufferedPosition) { + _bufferedPosition = pos; + [self broadcastPlaybackEvent]; + } + } +} + +- (void)sendErrorForItem:(IndexedPlayerItem *)playerItem { + FlutterError *flutterError = [FlutterError errorWithCode:[NSString stringWithFormat:@"%d", playerItem.error.code] + message:playerItem.error.localizedDescription + details:nil]; + [self sendError:flutterError playerItem:playerItem]; +} + +- (void)sendError:(FlutterError *)flutterError playerItem:(IndexedPlayerItem *)playerItem { + NSLog(@"sendError"); + if (_loadResult && playerItem == _player.currentItem) { + _loadResult(flutterError); + _loadResult = nil; + } + if (_eventSink) { + // Broadcast all errors even if they aren't on the current item. + _eventSink(flutterError); + } +} + +- (void)abortExistingConnection { + FlutterError *flutterError = [FlutterError errorWithCode:@"abort" + message:@"Connection aborted" + details:nil]; + [self sendError:flutterError playerItem:nil]; +} + +- (int)indexForItem:(IndexedPlayerItem *)playerItem { + for (int i = 0; i < _indexedAudioSources.count; i++) { + if (_indexedAudioSources[i].playerItem == playerItem) { + return i; + } + } + return -1; +} + +- (void)play { + [self play:nil]; +} + +- (void)play:(FlutterResult)result { + if (result) { + if (_playResult) { + NSLog(@"INTERRUPTING PLAY"); + _playResult(nil); + } + _playResult = result; + } + _playing = YES; +#if TARGET_OS_IPHONE + if (_configuredSession) { + [[AVAudioSession sharedInstance] setActive:YES error:nil]; + } +#endif + [_player play]; + [self updatePosition]; + if (@available(macOS 10.12, iOS 10.0, *)) {} + else { + if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { + [self enterBuffering:@"play, _bufferUnconfirmed && !playbackBufferFull"]; + [self broadcastPlaybackEvent]; + } + } +} + +- (void)pause { + _playing = NO; + [_player pause]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + if (_playResult) { + NSLog(@"PLAY FINISHED DUE TO PAUSE"); + _playResult(nil); + _playResult = nil; + } +} + +- (void)complete { + [self updatePosition]; + _processingState = completed; + [self broadcastPlaybackEvent]; + if (_playResult) { + NSLog(@"PLAY FINISHED DUE TO COMPLETE"); + _playResult(nil); + _playResult = nil; + } +} + +- (void)setVolume:(float)volume { + [_player setVolume:volume]; +} + +- (void)setSpeed:(float)speed { + if (speed == 1.0 + || (speed < 1.0 && _player.currentItem.canPlaySlowForward) + || (speed > 1.0 && _player.currentItem.canPlayFastForward)) { + _player.rate = speed; + } + [self updatePosition]; +} + +- (void)setLoopMode:(int)loopMode { + _loopMode = loopMode; + if (_player) { + switch (_loopMode) { + case loopOne: + _player.actionAtItemEnd = AVPlayerActionAtItemEndPause; // AVPlayerActionAtItemEndNone + break; + default: + _player.actionAtItemEnd = AVPlayerActionAtItemEndAdvance; + } + } +} + +- (void)setShuffleModeEnabled:(BOOL)shuffleModeEnabled { + NSLog(@"setShuffleModeEnabled: %d", shuffleModeEnabled); + _shuffleModeEnabled = shuffleModeEnabled; + if (!_audioSource) return; + + [self updateOrder]; + + [self enqueueFrom:_index]; +} + +- (void)dumpQueue { + for (int i = 0; i < _player.items.count; i++) { + IndexedPlayerItem *playerItem = _player.items[i]; + for (int j = 0; j < _indexedAudioSources.count; j++) { + IndexedAudioSource *source = _indexedAudioSources[j]; + if (source.playerItem == playerItem) { + NSLog(@"- %d", j); + break; + } + } + } +} + +- (void)setAutomaticallyWaitsToMinimizeStalling:(bool)automaticallyWaitsToMinimizeStalling { + _automaticallyWaitsToMinimizeStalling = automaticallyWaitsToMinimizeStalling; + if (@available(macOS 10.12, iOS 10.0, *)) { + if(_player) { + _player.automaticallyWaitsToMinimizeStalling = automaticallyWaitsToMinimizeStalling; + } + } +} + +- (void)seek:(CMTime)position index:(NSNumber *)newIndex completionHandler:(void (^)(BOOL))completionHandler { + int index = _index; + if (newIndex != [NSNull null]) { + index = [newIndex intValue]; + } + if (index != _index) { + // Jump to a new item + /* if (_playing && index == _index + 1) { */ + /* // Special case for jumping to the very next item */ + /* NSLog(@"seek to next item: %d -> %d", _index, index); */ + /* [_indexedAudioSources[_index] seek:kCMTimeZero]; */ + /* _index = index; */ + /* [_player advanceToNextItem]; */ + /* [self broadcastPlaybackEvent]; */ + /* } else */ + { + // Jump to a distant item + //NSLog(@"seek# jump to distant item: %d -> %d", _index, index); + if (_playing) { + [_player pause]; + } + [_indexedAudioSources[_index] seek:kCMTimeZero]; + // The "currentItem" key observer will respect that a seek is already in progress + _seekPos = position; + [self updatePosition]; + [self enqueueFrom:index]; + IndexedAudioSource *source = _indexedAudioSources[_index]; + if (abs((int)(1000 * CMTimeGetSeconds(CMTimeSubtract(source.position, position)))) > 100) { + [self enterBuffering:@"seek to index"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + [source seek:position completionHandler:^(BOOL finished) { + if (@available(macOS 10.12, iOS 10.0, *)) { + if (_playing) { + // Handled by timeControlStatus + } else { + if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { + // Stay in buffering + } else if (source.playerItem.status == AVPlayerItemStatusReadyToPlay) { + [self leaveBuffering:@"seek to index finished, (!bufferUnconfirmed || playbackBufferFull) && ready to play"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } + } else { + if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { + // Stay in buffering + } else if (source.playerItem.status == AVPlayerItemStatusReadyToPlay) { + [self leaveBuffering:@"seek to index finished, (!bufferUnconfirmed || playbackBufferFull) && ready to play"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + } + } + if (_playing) { + [_player play]; + } + _seekPos = kCMTimeInvalid; + [self broadcastPlaybackEvent]; + if (completionHandler) { + completionHandler(finished); + } + }]; + } else { + _seekPos = kCMTimeInvalid; + if (_playing) { + [_player play]; + } + } + } + } else { + // Seek within an item + if (_playing) { + [_player pause]; + } + _seekPos = position; + //NSLog(@"seek. enter buffering. pos = %d", (int)(1000*CMTimeGetSeconds(_indexedAudioSources[_index].position))); + // TODO: Move this into a separate method so it can also + // be used in skip. + [self enterBuffering:@"seek"]; + [self updatePosition]; + [self broadcastPlaybackEvent]; + [_indexedAudioSources[_index] seek:position completionHandler:^(BOOL finished) { + [self updatePosition]; + if (_playing) { + // If playing, buffering will be detected either by: + // 1. checkForDiscontinuity + // 2. timeControlStatus + [_player play]; + } else { + // If not playing, there is no reliable way to detect + // when buffering has completed, so we use + // !playbackBufferEmpty. Although this always seems to + // be full even right after a seek. + if (_player.currentItem.playbackBufferEmpty) { + [self enterBuffering:@"seek finished, playbackBufferEmpty"]; + } else { + [self leaveBuffering:@"seek finished, !playbackBufferEmpty"]; + } + [self updatePosition]; + if (_processingState != buffering) { + [self broadcastPlaybackEvent]; + } + } + _seekPos = kCMTimeInvalid; + [self broadcastPlaybackEvent]; + if (completionHandler) { + completionHandler(finished); + } + }]; + } +} + +- (void)dispose { + if (_processingState != none) { + [_player pause]; + _processingState = none; + [self broadcastPlaybackEvent]; + } + if (_timeObserver) { + [_player removeTimeObserver:_timeObserver]; + _timeObserver = 0; + } + if (_indexedAudioSources) { + for (int i = 0; i < [_indexedAudioSources count]; i++) { + [self removeItemObservers:_indexedAudioSources[i].playerItem]; + } + } + if (_player) { + [_player removeObserver:self forKeyPath:@"currentItem"]; + if (@available(macOS 10.12, iOS 10.0, *)) { + [_player removeObserver:self forKeyPath:@"timeControlStatus"]; + } + _player = nil; + } + // Untested: + // [_eventChannel setStreamHandler:nil]; + // [_methodChannel setMethodHandler:nil]; +} + +@end diff --git a/just_audio/macos/Classes/AudioSource.h b/just_audio/macos/Classes/AudioSource.h new file mode 100644 index 0000000..3dd1bf5 --- /dev/null +++ b/just_audio/macos/Classes/AudioSource.h @@ -0,0 +1,13 @@ +#import + +@interface AudioSource : NSObject + +@property (readonly, nonatomic) NSString* sourceId; + +- (instancetype)initWithId:(NSString *)sid; +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex; +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches; +- (NSArray *)getShuffleOrder; +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex; + +@end diff --git a/just_audio/macos/Classes/AudioSource.m b/just_audio/macos/Classes/AudioSource.m new file mode 100644 index 0000000..81534f1 --- /dev/null +++ b/just_audio/macos/Classes/AudioSource.m @@ -0,0 +1,37 @@ +#import "AudioSource.h" +#import + +@implementation AudioSource { + NSString *_sourceId; +} + +- (instancetype)initWithId:(NSString *)sid { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + _sourceId = sid; + return self; +} + +- (NSString *)sourceId { + return _sourceId; +} + +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex { + return 0; +} + +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches { + if ([_sourceId isEqualToString:sourceId]) { + [matches addObject:self]; + } +} + +- (NSArray *)getShuffleOrder { + return @[]; +} + +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex { + return 0; +} + +@end diff --git a/just_audio/macos/Classes/ClippingAudioSource.h b/just_audio/macos/Classes/ClippingAudioSource.h new file mode 100644 index 0000000..8122e3a --- /dev/null +++ b/just_audio/macos/Classes/ClippingAudioSource.h @@ -0,0 +1,11 @@ +#import "AudioSource.h" +#import "UriAudioSource.h" +#import + +@interface ClippingAudioSource : IndexedAudioSource + +@property (readonly, nonatomic) UriAudioSource* audioSource; + +- (instancetype)initWithId:(NSString *)sid audioSource:(UriAudioSource *)audioSource start:(NSNumber *)start end:(NSNumber *)end; + +@end diff --git a/just_audio/macos/Classes/ClippingAudioSource.m b/just_audio/macos/Classes/ClippingAudioSource.m new file mode 100644 index 0000000..2f3b174 --- /dev/null +++ b/just_audio/macos/Classes/ClippingAudioSource.m @@ -0,0 +1,79 @@ +#import "AudioSource.h" +#import "ClippingAudioSource.h" +#import "IndexedPlayerItem.h" +#import "UriAudioSource.h" +#import + +@implementation ClippingAudioSource { + UriAudioSource *_audioSource; + CMTime _start; + CMTime _end; +} + +- (instancetype)initWithId:(NSString *)sid audioSource:(UriAudioSource *)audioSource start:(NSNumber *)start end:(NSNumber *)end { + self = [super initWithId:sid]; + NSAssert(self, @"super init cannot be nil"); + _audioSource = audioSource; + _start = start == [NSNull null] ? kCMTimeZero : CMTimeMake([start intValue], 1000); + _end = end == [NSNull null] ? kCMTimeInvalid : CMTimeMake([end intValue], 1000); + return self; +} + +- (UriAudioSource *)audioSource { + return _audioSource; +} + +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches { + [super findById:sourceId matches:matches]; + [_audioSource findById:sourceId matches:matches]; +} + +- (void)attach:(AVQueuePlayer *)player { + [super attach:player]; + _audioSource.playerItem.forwardPlaybackEndTime = _end; + // XXX: Not needed since currentItem observer handles it? + [self seek:kCMTimeZero]; +} + +- (IndexedPlayerItem *)playerItem { + return _audioSource.playerItem; +} + +- (NSArray *)getShuffleOrder { + return @[@(0)]; +} + +- (void)play:(AVQueuePlayer *)player { +} + +- (void)pause:(AVQueuePlayer *)player { +} + +- (void)stop:(AVQueuePlayer *)player { +} + +- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler { + if (!completionHandler || (self.playerItem.status == AVPlayerItemStatusReadyToPlay)) { + CMTime absPosition = CMTimeAdd(_start, position); + [_audioSource.playerItem seekToTime:absPosition toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:completionHandler]; + } +} + +- (CMTime)duration { + return CMTimeSubtract(CMTIME_IS_INVALID(_end) ? self.playerItem.duration : _end, _start); +} + +- (void)setDuration:(CMTime)duration { +} + +- (CMTime)position { + return CMTimeSubtract(self.playerItem.currentTime, _start); +} + +- (CMTime)bufferedPosition { + CMTime pos = CMTimeSubtract(_audioSource.bufferedPosition, _start); + CMTime dur = [self duration]; + return CMTimeCompare(pos, dur) >= 0 ? dur : pos; +} + +@end diff --git a/just_audio/macos/Classes/ConcatenatingAudioSource.h b/just_audio/macos/Classes/ConcatenatingAudioSource.h new file mode 100644 index 0000000..68455af --- /dev/null +++ b/just_audio/macos/Classes/ConcatenatingAudioSource.h @@ -0,0 +1,13 @@ +#import "AudioSource.h" +#import + +@interface ConcatenatingAudioSource : AudioSource + +@property (readonly, nonatomic) int count; + +- (instancetype)initWithId:(NSString *)sid audioSources:(NSMutableArray *)audioSources; +- (void)insertSource:(AudioSource *)audioSource atIndex:(int)index; +- (void)removeSourcesFromIndex:(int)start toIndex:(int)end; +- (void)moveSourceFromIndex:(int)currentIndex toIndex:(int)newIndex; + +@end diff --git a/just_audio/macos/Classes/ConcatenatingAudioSource.m b/just_audio/macos/Classes/ConcatenatingAudioSource.m new file mode 100644 index 0000000..bd7b713 --- /dev/null +++ b/just_audio/macos/Classes/ConcatenatingAudioSource.m @@ -0,0 +1,109 @@ +#import "AudioSource.h" +#import "ConcatenatingAudioSource.h" +#import +#import + +@implementation ConcatenatingAudioSource { + NSMutableArray *_audioSources; + NSMutableArray *_shuffleOrder; +} + +- (instancetype)initWithId:(NSString *)sid audioSources:(NSMutableArray *)audioSources { + self = [super initWithId:sid]; + NSAssert(self, @"super init cannot be nil"); + _audioSources = audioSources; + return self; +} + +- (int)count { + return _audioSources.count; +} + +- (void)insertSource:(AudioSource *)audioSource atIndex:(int)index { + [_audioSources insertObject:audioSource atIndex:index]; +} + +- (void)removeSourcesFromIndex:(int)start toIndex:(int)end { + if (end == -1) end = _audioSources.count; + for (int i = start; i < end; i++) { + [_audioSources removeObjectAtIndex:start]; + } +} + +- (void)moveSourceFromIndex:(int)currentIndex toIndex:(int)newIndex { + AudioSource *source = _audioSources[currentIndex]; + [_audioSources removeObjectAtIndex:currentIndex]; + [_audioSources insertObject:source atIndex:newIndex]; +} + +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex { + for (int i = 0; i < [_audioSources count]; i++) { + treeIndex = [_audioSources[i] buildSequence:sequence treeIndex:treeIndex]; + } + return treeIndex; +} + +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches { + [super findById:sourceId matches:matches]; + for (int i = 0; i < [_audioSources count]; i++) { + [_audioSources[i] findById:sourceId matches:matches]; + } +} + +- (NSArray *)getShuffleOrder { + NSMutableArray *order = [NSMutableArray new]; + int offset = [order count]; + NSMutableArray *childOrders = [NSMutableArray new]; // array of array of ints + for (int i = 0; i < [_audioSources count]; i++) { + AudioSource *audioSource = _audioSources[i]; + NSArray *childShuffleOrder = [audioSource getShuffleOrder]; + NSMutableArray *offsetChildShuffleOrder = [NSMutableArray new]; + for (int j = 0; j < [childShuffleOrder count]; j++) { + [offsetChildShuffleOrder addObject:@([childShuffleOrder[j] integerValue] + offset)]; + } + [childOrders addObject:offsetChildShuffleOrder]; + offset += [childShuffleOrder count]; + } + for (int i = 0; i < [_audioSources count]; i++) { + [order addObjectsFromArray:childOrders[[_shuffleOrder[i] integerValue]]]; + } + return order; +} + +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex { + int currentChildIndex = -1; + for (int i = 0; i < [_audioSources count]; i++) { + int indexBefore = treeIndex; + AudioSource *child = _audioSources[i]; + treeIndex = [child shuffle:treeIndex currentIndex:currentIndex]; + if (currentIndex >= indexBefore && currentIndex < treeIndex) { + currentChildIndex = i; + } else {} + } + // Shuffle so that the current child is first in the shuffle order + _shuffleOrder = [NSMutableArray arrayWithCapacity:[_audioSources count]]; + for (int i = 0; i < [_audioSources count]; i++) { + [_shuffleOrder addObject:@(0)]; + } + NSLog(@"shuffle: audioSources.count=%d and shuffleOrder.count=%d", [_audioSources count], [_shuffleOrder count]); + // First generate a random shuffle + for (int i = 0; i < [_audioSources count]; i++) { + int j = arc4random_uniform(i + 1); + _shuffleOrder[i] = _shuffleOrder[j]; + _shuffleOrder[j] = @(i); + } + // Then bring currentIndex to the front + if (currentChildIndex != -1) { + for (int i = 1; i < [_audioSources count]; i++) { + if ([_shuffleOrder[i] integerValue] == currentChildIndex) { + NSNumber *v = _shuffleOrder[0]; + _shuffleOrder[0] = _shuffleOrder[i]; + _shuffleOrder[i] = v; + break; + } + } + } + return treeIndex; +} + +@end diff --git a/just_audio/macos/Classes/IndexedAudioSource.h b/just_audio/macos/Classes/IndexedAudioSource.h new file mode 100644 index 0000000..7d343d8 --- /dev/null +++ b/just_audio/macos/Classes/IndexedAudioSource.h @@ -0,0 +1,21 @@ +#import "AudioSource.h" +#import "IndexedPlayerItem.h" +#import +#import + +@interface IndexedAudioSource : AudioSource + +@property (readonly, nonatomic) IndexedPlayerItem *playerItem; +@property (readwrite, nonatomic) CMTime duration; +@property (readonly, nonatomic) CMTime position; +@property (readonly, nonatomic) CMTime bufferedPosition; +@property (readonly, nonatomic) BOOL isAttached; + +- (void)attach:(AVQueuePlayer *)player; +- (void)play:(AVQueuePlayer *)player; +- (void)pause:(AVQueuePlayer *)player; +- (void)stop:(AVQueuePlayer *)player; +- (void)seek:(CMTime)position; +- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler; + +@end diff --git a/just_audio/macos/Classes/IndexedAudioSource.m b/just_audio/macos/Classes/IndexedAudioSource.m new file mode 100644 index 0000000..316f900 --- /dev/null +++ b/just_audio/macos/Classes/IndexedAudioSource.m @@ -0,0 +1,68 @@ +#import "IndexedAudioSource.h" +#import "IndexedPlayerItem.h" +#import + +@implementation IndexedAudioSource { + BOOL _isAttached; +} + +- (instancetype)initWithId:(NSString *)sid { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + _isAttached = NO; + return self; +} + +- (IndexedPlayerItem *)playerItem { + return nil; +} + +- (BOOL)isAttached { + return _isAttached; +} + +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex { + [sequence addObject:self]; + return treeIndex + 1; +} + +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex { + return treeIndex + 1; +} + +- (void)attach:(AVQueuePlayer *)player { + _isAttached = YES; +} + +- (void)play:(AVQueuePlayer *)player { +} + +- (void)pause:(AVQueuePlayer *)player { +} + +- (void)stop:(AVQueuePlayer *)player { +} + +- (void)seek:(CMTime)position { + [self seek:position completionHandler:nil]; +} + +- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler { +} + +- (CMTime)duration { + return kCMTimeInvalid; +} + +- (void)setDuration:(CMTime)duration { +} + +- (CMTime)position { + return kCMTimeInvalid; +} + +- (CMTime)bufferedPosition { + return kCMTimeInvalid; +} + +@end diff --git a/just_audio/macos/Classes/IndexedPlayerItem.h b/just_audio/macos/Classes/IndexedPlayerItem.h new file mode 100644 index 0000000..5d4a11c --- /dev/null +++ b/just_audio/macos/Classes/IndexedPlayerItem.h @@ -0,0 +1,9 @@ +#import + +@class IndexedAudioSource; + +@interface IndexedPlayerItem : AVPlayerItem + +@property (readwrite, nonatomic) IndexedAudioSource *audioSource; + +@end diff --git a/just_audio/macos/Classes/IndexedPlayerItem.m b/just_audio/macos/Classes/IndexedPlayerItem.m new file mode 100644 index 0000000..87fafe0 --- /dev/null +++ b/just_audio/macos/Classes/IndexedPlayerItem.m @@ -0,0 +1,16 @@ +#import "IndexedPlayerItem.h" +#import "IndexedAudioSource.h" + +@implementation IndexedPlayerItem { + IndexedAudioSource *_audioSource; +} + +-(void)setAudioSource:(IndexedAudioSource *)audioSource { + _audioSource = audioSource; +} + +-(IndexedAudioSource *)audioSource { + return _audioSource; +} + +@end diff --git a/just_audio/macos/Classes/JustAudioPlugin.h b/just_audio/macos/Classes/JustAudioPlugin.h new file mode 100644 index 0000000..3f4068d --- /dev/null +++ b/just_audio/macos/Classes/JustAudioPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface JustAudioPlugin : NSObject +@end diff --git a/just_audio/macos/Classes/JustAudioPlugin.m b/just_audio/macos/Classes/JustAudioPlugin.m new file mode 100644 index 0000000..982a260 --- /dev/null +++ b/just_audio/macos/Classes/JustAudioPlugin.m @@ -0,0 +1,55 @@ +#import "JustAudioPlugin.h" +#import "AudioPlayer.h" +#import +#include + +@implementation JustAudioPlugin { + NSObject* _registrar; + BOOL _configuredSession; +} + ++ (void)registerWithRegistrar:(NSObject*)registrar { + FlutterMethodChannel* channel = [FlutterMethodChannel + methodChannelWithName:@"com.ryanheise.just_audio.methods" + binaryMessenger:[registrar messenger]]; + JustAudioPlugin* instance = [[JustAudioPlugin alloc] initWithRegistrar:registrar]; + [registrar addMethodCallDelegate:instance channel:channel]; +} + +- (instancetype)initWithRegistrar:(NSObject *)registrar { + self = [super init]; + NSAssert(self, @"super init cannot be nil"); + _registrar = registrar; + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { + if ([@"init" isEqualToString:call.method]) { + NSArray* args = (NSArray*)call.arguments; + NSString* playerId = args[0]; + /*AudioPlayer* player =*/ [[AudioPlayer alloc] initWithRegistrar:_registrar playerId:playerId configuredSession:_configuredSession]; + result(nil); + } else if ([@"setIosCategory" isEqualToString:call.method]) { +#if TARGET_OS_IPHONE + NSNumber* categoryIndex = (NSNumber*)call.arguments; + AVAudioSessionCategory category = nil; + switch (categoryIndex.integerValue) { + case 0: category = AVAudioSessionCategoryAmbient; break; + case 1: category = AVAudioSessionCategorySoloAmbient; break; + case 2: category = AVAudioSessionCategoryPlayback; break; + case 3: category = AVAudioSessionCategoryRecord; break; + case 4: category = AVAudioSessionCategoryPlayAndRecord; break; + case 5: category = AVAudioSessionCategoryMultiRoute; break; + } + if (category) { + _configuredSession = YES; + } + [[AVAudioSession sharedInstance] setCategory:category error:nil]; +#endif + result(nil); + } else { + result(FlutterMethodNotImplemented); + } +} + +@end diff --git a/just_audio/macos/Classes/LoopingAudioSource.h b/just_audio/macos/Classes/LoopingAudioSource.h new file mode 100644 index 0000000..a77636b --- /dev/null +++ b/just_audio/macos/Classes/LoopingAudioSource.h @@ -0,0 +1,8 @@ +#import "AudioSource.h" +#import + +@interface LoopingAudioSource : AudioSource + +- (instancetype)initWithId:(NSString *)sid audioSources:(NSArray *)audioSources; + +@end diff --git a/just_audio/macos/Classes/LoopingAudioSource.m b/just_audio/macos/Classes/LoopingAudioSource.m new file mode 100644 index 0000000..ba4b52b --- /dev/null +++ b/just_audio/macos/Classes/LoopingAudioSource.m @@ -0,0 +1,53 @@ +#import "AudioSource.h" +#import "LoopingAudioSource.h" +#import + +@implementation LoopingAudioSource { + // An array of duplicates + NSArray *_audioSources; // +} + +- (instancetype)initWithId:(NSString *)sid audioSources:(NSArray *)audioSources { + self = [super initWithId:sid]; + NSAssert(self, @"super init cannot be nil"); + _audioSources = audioSources; + return self; +} + +- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex { + for (int i = 0; i < [_audioSources count]; i++) { + treeIndex = [_audioSources[i] buildSequence:sequence treeIndex:treeIndex]; + } + return treeIndex; +} + +- (void)findById:(NSString *)sourceId matches:(NSMutableArray *)matches { + [super findById:sourceId matches:matches]; + for (int i = 0; i < [_audioSources count]; i++) { + [_audioSources[i] findById:sourceId matches:matches]; + } +} + +- (NSArray *)getShuffleOrder { + NSMutableArray *order = [NSMutableArray new]; + int offset = (int)[order count]; + for (int i = 0; i < [_audioSources count]; i++) { + AudioSource *audioSource = _audioSources[i]; + NSArray *childShuffleOrder = [audioSource getShuffleOrder]; + for (int j = 0; j < [childShuffleOrder count]; j++) { + [order addObject:@([childShuffleOrder[j] integerValue] + offset)]; + } + offset += [childShuffleOrder count]; + } + return order; +} + +- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex { + // TODO: This should probably shuffle the same way on all duplicates. + for (int i = 0; i < [_audioSources count]; i++) { + treeIndex = [_audioSources[i] shuffle:treeIndex currentIndex:currentIndex]; + } + return treeIndex; +} + +@end diff --git a/just_audio/macos/Classes/UriAudioSource.h b/just_audio/macos/Classes/UriAudioSource.h new file mode 100644 index 0000000..9b74125 --- /dev/null +++ b/just_audio/macos/Classes/UriAudioSource.h @@ -0,0 +1,8 @@ +#import "IndexedAudioSource.h" +#import + +@interface UriAudioSource : IndexedAudioSource + +- (instancetype)initWithId:(NSString *)sid uri:(NSString *)uri; + +@end diff --git a/just_audio/macos/Classes/UriAudioSource.m b/just_audio/macos/Classes/UriAudioSource.m new file mode 100644 index 0000000..91321d4 --- /dev/null +++ b/just_audio/macos/Classes/UriAudioSource.m @@ -0,0 +1,79 @@ +#import "UriAudioSource.h" +#import "IndexedAudioSource.h" +#import "IndexedPlayerItem.h" +#import + +@implementation UriAudioSource { + NSString *_uri; + IndexedPlayerItem *_playerItem; + /* CMTime _duration; */ +} + +- (instancetype)initWithId:(NSString *)sid uri:(NSString *)uri { + self = [super initWithId:sid]; + NSAssert(self, @"super init cannot be nil"); + _uri = uri; + if ([_uri hasPrefix:@"file://"]) { + _playerItem = [[IndexedPlayerItem alloc] initWithURL:[NSURL fileURLWithPath:[_uri substringFromIndex:7]]]; + } else { + _playerItem = [[IndexedPlayerItem alloc] initWithURL:[NSURL URLWithString:_uri]]; + } + if (@available(macOS 10.13, iOS 11.0, *)) { + // This does the best at reducing distortion on voice with speeds below 1.0 + _playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmTimeDomain; + } + /* NSKeyValueObservingOptions options = */ + /* NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew; */ + /* [_playerItem addObserver:self */ + /* forKeyPath:@"duration" */ + /* options:options */ + /* context:nil]; */ + return self; +} + +- (IndexedPlayerItem *)playerItem { + return _playerItem; +} + +- (NSArray *)getShuffleOrder { + return @[@(0)]; +} + +- (void)play:(AVQueuePlayer *)player { +} + +- (void)pause:(AVQueuePlayer *)player { +} + +- (void)stop:(AVQueuePlayer *)player { +} + +- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler { + if (!completionHandler || (_playerItem.status == AVPlayerItemStatusReadyToPlay)) { + [_playerItem seekToTime:position toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:completionHandler]; + } +} + +- (CMTime)duration { + return _playerItem.duration; +} + +- (void)setDuration:(CMTime)duration { +} + +- (CMTime)position { + return _playerItem.currentTime; +} + +- (CMTime)bufferedPosition { + NSValue *last = _playerItem.loadedTimeRanges.lastObject; + if (last) { + CMTimeRange timeRange = [last CMTimeRangeValue]; + return CMTimeAdd(timeRange.start, timeRange.duration); + } else { + return _playerItem.currentTime; + } + return kCMTimeInvalid; +} + +@end diff --git a/just_audio/macos/just_audio.podspec b/just_audio/macos/just_audio.podspec new file mode 100644 index 0000000..ff946e8 --- /dev/null +++ b/just_audio/macos/just_audio.podspec @@ -0,0 +1,21 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'just_audio' + s.version = '0.0.1' + s.summary = 'A new flutter plugin project.' + s.description = <<-DESC +A new flutter plugin project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'FlutterMacOS' + s.platform = :osx, '10.11' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } +end + diff --git a/just_audio/pubspec.lock b/just_audio/pubspec.lock new file mode 100644 index 0000000..6c8bd0b --- /dev/null +++ b/just_audio/pubspec.lock @@ -0,0 +1,250 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: "direct main" + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.2" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.3" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.14.13" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.4" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.8" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.8" + path: + dependency: "direct main" + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" + path_provider: + dependency: "direct main" + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.10" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+1" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.4+3" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.13" + rxdart: + dependency: "direct main" + description: + name: rxdart + url: "https://pub.dartlang.org" + source: hosted + version: "0.24.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.5" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.17" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + uuid: + dependency: "direct main" + description: + name: uuid + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0" +sdks: + dart: ">=2.9.0-14.0.dev <3.0.0" + flutter: ">=1.12.13+hotfix.5 <2.0.0" diff --git a/just_audio/pubspec.yaml b/just_audio/pubspec.yaml new file mode 100644 index 0000000..12616f4 --- /dev/null +++ b/just_audio/pubspec.yaml @@ -0,0 +1,37 @@ +name: just_audio +description: Flutter plugin to play audio from streams, files, assets, DASH/HLS streams and playlists. Works with audio_service to play audio in the background. +version: 0.3.1 +homepage: https://github.com/ryanheise/just_audio + +environment: + sdk: '>=2.6.0 <3.0.0' + flutter: ">=1.12.8 <2.0.0" + +dependencies: + rxdart: ^0.24.1 + path: ^1.6.4 + path_provider: ^1.6.10 + async: ^2.4.1 + uuid: ^2.2.0 + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + +flutter: + plugin: + platforms: + android: + package: com.ryanheise.just_audio + pluginClass: JustAudioPlugin + ios: + pluginClass: JustAudioPlugin + macos: + pluginClass: JustAudioPlugin + web: + pluginClass: JustAudioPlugin + fileName: just_audio_web.dart diff --git a/just_audio/test/just_audio_test.dart b/just_audio/test/just_audio_test.dart new file mode 100644 index 0000000..14c6a7a --- /dev/null +++ b/just_audio/test/just_audio_test.dart @@ -0,0 +1,21 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:just_audio/just_audio.dart'; + +void main() { + const MethodChannel channel = MethodChannel('just_audio'); + + setUp(() { + channel.setMockMethodCallHandler((MethodCall methodCall) async { + return '42'; + }); + }); + + tearDown(() { + channel.setMockMethodCallHandler(null); + }); + +// test('getPlatformVersion', () async { +// expect(await AudioPlayer.platformVersion, '42'); +// }); +} diff --git a/lib/api/deezer.dart b/lib/api/deezer.dart index 2bd3ef3..d5743bd 100644 --- a/lib/api/deezer.dart +++ b/lib/api/deezer.dart @@ -360,6 +360,18 @@ class DeezerAPI { //Return playlistId return data['results'].toString(); } - + + //Get part of discography + Future> discographyPage(String artistId, {int start = 0, int nb = 50}) async { + Map data = await callApi('album.getDiscography', params: { + 'art_id': int.parse(artistId), + 'discography_mode': 'all', + 'nb': nb, + 'start': start, + 'nb_songs': 30 + }); + + return data['results']['data'].map((a) => Album.fromPrivateJson(a)).toList(); + } } diff --git a/lib/api/definitions.dart b/lib/api/definitions.dart index 61e754f..7faced5 100644 --- a/lib/api/definitions.dart +++ b/lib/api/definitions.dart @@ -80,6 +80,7 @@ class Track { id: this.id, extras: { "playbackDetails": jsonEncode(this.playbackDetails), + "thumb": this.albumArt.thumb, "lyrics": jsonEncode(this.lyrics.toJson()), "albumId": this.album.id, "artists": jsonEncode(this.artists.map((art) => art.toJson()).toList()) @@ -102,7 +103,10 @@ class Track { artists: artists, album: album, id: mi.id, - albumArt: ImageDetails(fullUrl: mi.artUri), + albumArt: ImageDetails( + fullUrl: mi.artUri, + thumbUrl: mi.extras['thumb'] + ), duration: mi.duration, playbackDetails: null, // So it gets updated from api lyrics: Lyrics.fromJson(jsonDecode(((mi.extras??{})['lyrics'])??"{}")) @@ -116,7 +120,7 @@ class Track { title = "${json['SNG_TITLE']} ${json['VERSION']}"; } return Track( - id: json['SNG_ID'], + id: json['SNG_ID'].toString(), title: title, duration: Duration(seconds: int.parse(json['DURATION'])), albumArt: ImageDetails.fromPrivateString(json['ALB_PICTURE']), @@ -180,7 +184,7 @@ class Album { //JSON factory Album.fromPrivateJson(Map json, {Map songsJson = const {}, bool library = false}) => Album( - id: json['ALB_ID'], + id: json['ALB_ID'].toString(), title: json['ALB_TITLE'], art: ImageDetails.fromPrivateString(json['ALB_PICTURE']), artists: (json['ARTISTS']??[json]).map((dynamic art) => Artist.fromPrivateJson(art)).toList(), @@ -240,7 +244,7 @@ class Artist { Map topJson = const {}, bool library = false }) => Artist( - id: json['ART_ID'], + id: json['ART_ID'].toString(), name: json['ART_NAME'], fans: json['NB_FAN'], picture: ImageDetails.fromPrivateString(json['ART_PICTURE'], type: 'artist'), @@ -299,7 +303,7 @@ class Playlist { //JSON factory Playlist.fromPrivateJson(Map json, {Map songsJson = const {}, bool library = false}) => Playlist( - id: json['PLAYLIST_ID'], + id: json['PLAYLIST_ID'].toString(), title: json['TITLE'], trackCount: json['NB_SONG']??songsJson['total'], image: ImageDetails.fromPrivateString(json['PLAYLIST_PICTURE'], type: 'playlist'), diff --git a/lib/api/download.dart b/lib/api/download.dart index b7bf692..daec483 100644 --- a/lib/api/download.dart +++ b/lib/api/download.dart @@ -328,7 +328,8 @@ class DownloadManager { List duplicate = await db.rawQuery('SELECT * FROM downloads WHERE trackId == ?', [track.id]); if (duplicate.length != 0) return; //Save art - await imagesDatabase.getImage(track.albumArt.full, permanent: true); + //await imagesDatabase.getImage(track.albumArt.full); + imagesDatabase.saveImage(track.albumArt.full); //Save to db b.insert('tracks', track.toSQL(off: true), conflictAlgorithm: ConflictAlgorithm.replace); b.insert('albums', track.album.toSQL(), conflictAlgorithm: ConflictAlgorithm.ignore); diff --git a/lib/api/player.dart b/lib/api/player.dart index e98707a..dbf4078 100644 --- a/lib/api/player.dart +++ b/lib/api/player.dart @@ -1,9 +1,6 @@ import 'package:audio_service/audio_service.dart'; -import 'package:collection/collection.dart'; -import 'package:dio/dio.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:freezer/api/deezer.dart'; -import 'package:freezer/ui/cached_image.dart'; import 'package:just_audio/just_audio.dart'; import 'package:connectivity/connectivity.dart'; import 'package:path/path.dart' as p; @@ -23,7 +20,8 @@ class PlayerHelper { StreamSubscription _customEventSubscription; StreamSubscription _playbackStateStreamSubscription; QueueSource queueSource; - RepeatType repeatType = RepeatType.NONE; + LoopMode repeatType = LoopMode.off; + bool shuffle = false; //Find queue index by id int get queueIndex => AudioService.queue.indexWhere((mi) => mi.id == AudioService.currentMediaItem?.id??'Random string so it returns -1'); @@ -45,7 +43,6 @@ class PlayerHelper { if (event['action'] == 'queueEnd') { //If last song is played, load more queue this.queueSource = QueueSource.fromJson(event['queueSource']); - print(queueSource.toJson()); return; } }); @@ -74,20 +71,24 @@ class PlayerHelper { ); } - + Future toggleShuffle() async { + this.shuffle = !this.shuffle; + await AudioService.customAction('shuffle', this.shuffle); + } + //Repeat toggle Future changeRepeat() async { //Change to next repeat type switch (repeatType) { - case RepeatType.NONE: - repeatType = RepeatType.LIST; break; - case RepeatType.LIST: - repeatType = RepeatType.TRACK; break; + case LoopMode.one: + repeatType = LoopMode.off; break; + case LoopMode.all: + repeatType = LoopMode.one; break; default: - repeatType = RepeatType.NONE; break; + repeatType = LoopMode.all; break; } //Set repeat type - await AudioService.customAction("repeatType", RepeatType.values.indexOf(repeatType)); + await AudioService.customAction("repeatType", LoopMode.values.indexOf(repeatType)); } //Executed before exit @@ -101,7 +102,7 @@ class PlayerHelper { await startService(); await settings.updateAudioServiceQuality(); await AudioService.updateQueue(queue); - await AudioService.playFromMediaId(trackId); + await AudioService.skipToQueueItem(trackId); } //Play track from album @@ -178,277 +179,229 @@ void backgroundTaskEntrypoint() async { } class AudioPlayerTask extends BackgroundAudioTask { + AudioPlayer _player = AudioPlayer(); - AudioPlayer _audioPlayer = AudioPlayer(); - + //Queue List _queue = []; - int _queueIndex = -1; + int _queueIndex = 0; + ConcatenatingAudioSource _audioSource; - bool _playing; - bool _interrupted; AudioProcessingState _skipState; - Duration _lastPosition; + bool _interrupted; + Seeker _seeker; - ImagesDatabase imagesDB; + //Stream subscriptions + StreamSubscription _eventSub; + + //Loaded from file/frontend int mobileQuality; int wifiQuality; - - StreamSubscription _eventSub; - StreamSubscription _playerStateSub; - QueueSource queueSource; - int repeatType = 0; + Duration _lastPosition; MediaItem get mediaItem => _queue[_queueIndex]; - //Controls - final playControl = MediaControl( - androidIcon: 'drawable/ic_play_arrow', - label: 'Play', - action: MediaAction.play - ); - final pauseControl = MediaControl( - androidIcon: 'drawable/ic_pause', - label: 'Pause', - action: MediaAction.pause - ); - final stopControl = MediaControl( - androidIcon: 'drawable/ic_stop', - label: 'Stop', - action: MediaAction.stop - ); - final nextControl = MediaControl( - androidIcon: 'drawable/ic_skip_next', - label: 'Next', - action: MediaAction.skipToNext - ); - final previousControl = MediaControl( - androidIcon: 'drawable/ic_skip_previous', - label: 'Previous', - action: MediaAction.skipToPrevious - ); - @override - Future onStart(Map params) async { - _playerStateSub = _audioPlayer.playbackStateStream - .where((state) => state == AudioPlaybackState.completed) - .listen((_event) { - if (_queue.length > _queueIndex + 1) { - onSkipToNext(); - return; - } else { - //Repeat whole list (if enabled) - if (repeatType == 1) { - _skip(-_queueIndex); - return; - } - //Ask for more tracks in queue - AudioServiceBackground.sendCustomEvent({ - 'action': 'queueEnd', - 'queueSource': (queueSource??QueueSource()).toJson() - }); - if (_playing) _playing = false; - _setState(AudioProcessingState.none); - return; + Future onStart(Map params) { + + //Update track index + _player.currentIndexStream.listen((index) { + if (index != null) { + _queueIndex = index; + AudioServiceBackground.setMediaItem(mediaItem); + } + }); + //Update state on all clients on change + _eventSub = _player.playbackEventStream.listen((event) { + _broadcastState(); + }); + _player.processingStateStream.listen((state) { + switch(state) { + case ProcessingState.completed: + //Player ended, get more songs + AudioServiceBackground.sendCustomEvent({ + 'action': 'queueEnd', + 'queueSource': (queueSource??QueueSource()).toJson() + }); + break; + case ProcessingState.ready: + //Ready to play + _skipState = null; + break; + default: + break; } }); - //Read audio player events - _eventSub = _audioPlayer.playbackEventStream.listen((event) { - AudioProcessingState bufferingState = event.buffering ? AudioProcessingState.buffering : null; - switch (event.state) { - case AudioPlaybackState.paused: - case AudioPlaybackState.playing: - _setState(bufferingState ?? AudioProcessingState.ready, pos: event.position); - break; - case AudioPlaybackState.connecting: - _setState(_skipState ?? AudioProcessingState.connecting, pos: event.position); - break; - default: - break; - } - }); - - //Initialize later - //await imagesDB.init(); - + //Load queue AudioServiceBackground.setQueue(_queue); AudioServiceBackground.sendCustomEvent({'action': 'onLoad'}); } @override - Future onSkipToNext() async { - //If repeating allowed - if (repeatType == 2) { - await _skip(0); - return null; - } - _skip(1); - } + Future onSkipToQueueItem(String mediaId) async { + _lastPosition = null; - @override - Future onSkipToPrevious() => _skip(-1); + //Calculate new index + final newIndex = _queue.indexWhere((i) => i.id == mediaId); + if (newIndex == -1) return; - Future _skip(int offset) async { - int newPos = _queueIndex + offset; - //Out of bounds - if (newPos >= _queue.length || newPos < 0) return; - //First song - if (_playing == null) { - _playing = true; - } else if (_playing) { - await _audioPlayer.stop(); - } - //Update position, album art source, queue source text - _queueIndex = newPos; - //Get uri - String uri = await _getTrackUri(mediaItem); - //Modify extras - Map extras = mediaItem.extras; - extras.addAll({"qualityString": await _getQualityString(uri, mediaItem.duration)}); - _queue[_queueIndex] = mediaItem.copyWith( - artUri: await _getArtUri(mediaItem.artUri), - extras: extras - ); - //Play - AudioServiceBackground.setMediaItem(mediaItem); - _skipState = offset > 0 ? AudioProcessingState.skippingToNext:AudioProcessingState.skippingToPrevious; - //Load - await _audioPlayer.setUrl(uri); + //Update buffering state + _skipState = newIndex > _queueIndex + ? AudioProcessingState.skippingToNext + : AudioProcessingState.skippingToPrevious; + + //Skip in player + await _player.seek(Duration.zero, index: newIndex); _skipState = null; - await _saveQueue(); - (_playing??false) ? onPlay() : _setState(AudioProcessingState.ready); - } - - @override - void onPlay() async { - //Start playing preloaded queue - if (AudioServiceBackground.state.processingState == AudioProcessingState.none && _queue.length > 0) { - if (_queueIndex < 0 || _queueIndex == null) { - await this._skip(1); - } else { - await this._skip(0); - } - //Restore position from saved queue - if (_lastPosition != null) { - onSeekTo(_lastPosition); - _lastPosition = null; - } - return; - } - if (_skipState == null) { - _playing = true; - _audioPlayer.play(); - } - } - - @override - void onPause() { - if (_skipState == null && _playing) { - _playing = false; - _audioPlayer.pause(); - } - } - - @override - void onSeekTo(Duration pos) { - _audioPlayer.seek(pos); - } - - @override - void onClick(MediaButton button) { - if (_playing) onPause(); onPlay(); } @override - Future onUpdateQueue(List q) async { - this._queue = q; - AudioServiceBackground.setQueue(_queue); - await _saveQueue(); + Future onPlay() { + _player.play(); + //Restore position on play + if (_lastPosition != null) { + onSeekTo(_lastPosition); + } } @override - void onPlayFromMediaId(String mediaId) async { - int pos = this._queue.indexWhere((mi) => mi.id == mediaId); - await _skip(pos - _queueIndex); - if (_playing == null || !_playing) onPlay(); - } + Future onPause() => _player.pause(); @override - Future onFastForward() async { - await _seekRelative(fastForwardInterval); - } + Future onSeekTo(Duration pos) => _player.seek(pos); @override - void onAddQueueItemAt(MediaItem mi, int index) { - _queue.insert(index, mi); - AudioServiceBackground.setQueue(_queue); - _saveQueue(); - } + Future onFastForward() => _seekRelative(fastForwardInterval); @override - void onAddQueueItem(MediaItem mi) { - _queue.add(mi); - AudioServiceBackground.setQueue(_queue); - _saveQueue(); - } + Future onRewind() => _seekRelative(-rewindInterval); @override - Future onRewind() async { - await _seekRelative(rewindInterval); + Future onSeekForward(bool begin) async => _seekContinuously(begin, 1); + + @override + Future onSeekBackward(bool begin) async => _seekContinuously(begin, -1); + + //While seeking, jump 10s every 1s + void _seekContinuously(bool begin, int direction) { + _seeker?.stop(); + if (begin) { + _seeker = Seeker(_player, Duration(seconds: 10 * direction), Duration(seconds: 1), mediaItem)..start(); + } } + //Relative seek Future _seekRelative(Duration offset) async { - Duration newPos = _audioPlayer.playbackEvent.position + offset; + Duration newPos = _player.position + offset; + //Out of bounds check if (newPos < Duration.zero) newPos = Duration.zero; if (newPos > mediaItem.duration) newPos = mediaItem.duration; - onSeekTo(_audioPlayer.playbackEvent.position + offset); + + await _player.seek(newPos); } + //Update state on all clients + Future _broadcastState() async { + await AudioServiceBackground.setState( + controls: [ + MediaControl.skipToPrevious, + if (_player.playing) MediaControl.pause else MediaControl.play, + MediaControl.skipToNext, + //MediaControl.stop + ], + systemActions: [ + MediaAction.seekTo, + MediaAction.seekForward, + MediaAction.seekBackward + ], + processingState: _getProcessingState(), + playing: _player.playing, + position: _player.position, + bufferedPosition: _player.bufferedPosition, + speed: _player.speed + ); + } + + //just_audio state -> audio_service state. If skipping, use _skipState + AudioProcessingState _getProcessingState() { + if (_skipState != null) return _skipState; + //SRC: audio_service example + switch (_player.processingState) { + case ProcessingState.none: + return AudioProcessingState.stopped; + case ProcessingState.loading: + return AudioProcessingState.connecting; + case ProcessingState.buffering: + return AudioProcessingState.buffering; + case ProcessingState.ready: + return AudioProcessingState.ready; + case ProcessingState.completed: + return AudioProcessingState.completed; + default: + throw Exception("Invalid state: ${_player.processingState}"); + } + } + + //Replace current queue @override - Future onUpdateMediaItem(MediaItem mediaItem) async { - _queue[_queueIndex] = mediaItem; + Future onUpdateQueue(List q) async { + //just_audio + _player.stop(); + if (_audioSource != null) _audioSource.clear(); + //audio_service + this._queue = q; + AudioServiceBackground.setQueue(_queue); + //Load + await _loadQueue(); + await _player.seek(Duration.zero, index: 0); + } + + //Load queue to just_audio + Future _loadQueue() async { + List sources = []; + for(int i=0; i<_queue.length; i++) { + sources.add(await _mediaItemToAudioSource(_queue[i])); + } + + _audioSource = ConcatenatingAudioSource(children: sources); + //Load in just_audio + try { + await _player.load(_audioSource); + } catch (e) { + //Error loading tracks + } AudioServiceBackground.setMediaItem(mediaItem); } - //Audio interruptions - @override - void onAudioFocusLost(AudioInterruption interruption) { - if (_playing) _interrupted = true; - switch (interruption) { - case AudioInterruption.pause: - case AudioInterruption.temporaryPause: - case AudioInterruption.unknownPause: - if (_playing) onPause(); - break; - case AudioInterruption.temporaryDuck: - _audioPlayer.setVolume(0.5); - break; + Future _mediaItemToAudioSource(MediaItem mi) async { + String url = await _getTrackUrl(mi); + if (url.startsWith('http')) return ProgressiveAudioSource(Uri.parse(url)); + return AudioSource.uri(Uri.parse(url)); + } + + Future _getTrackUrl(MediaItem mediaItem, {int quality}) async { + //Check if offline + String _offlinePath = p.join((await getExternalStorageDirectory()).path, 'offline/'); + File f = File(p.join(_offlinePath, mediaItem.id)); + if (await f.exists()) { + return f.path; } + + //Due to current limitations of just_audio, quality fallback moved to DeezerDataSource in ExoPlayer + //This just returns fake url that contains metadata + List playbackDetails = jsonDecode(mediaItem.extras['playbackDetails']); + //Quality + ConnectivityResult conn = await Connectivity().checkConnectivity(); + quality = mobileQuality; + if (conn == ConnectivityResult.wifi) quality = wifiQuality; + + String url = 'https://dzcdn.net/?md5=${playbackDetails[0]}&mv=${playbackDetails[1]}&q=${quality.toString()}#${mediaItem.id}'; + return url; } - @override - void onAudioFocusGained(AudioInterruption interruption) { - switch (interruption) { - case AudioInterruption.temporaryPause: - if (!_playing && _interrupted) onPlay(); - break; - case AudioInterruption.temporaryDuck: - _audioPlayer.setVolume(1.0); - break; - default: - break; - } - _interrupted = false; - } - - @override - void onAudioBecomingNoisy() { - onPause(); - } - - + //Custom actions @override Future onCustomAction(String name, dynamic args) async { if (name == 'updateQuality') { @@ -457,228 +410,178 @@ class AudioPlayerTask extends BackgroundAudioTask { this.wifiQuality = args['wifiQuality']; this.mobileQuality = args['mobileQuality']; } - if (name == 'saveQueue') { - await this._saveQueue(); - } - //Load queue, called after start - if (name == 'load') { - await _loadQueue(); - } //Change queue source if (name == 'queueSource') { this.queueSource = QueueSource.fromJson(Map.from(args)); } - //Shuffle - if (name == 'shuffleQueue') { - MediaItem mi = mediaItem; - shuffle(this._queue); - _queueIndex = _queue.indexOf(mi); - AudioServiceBackground.setQueue(this._queue); - } - //Repeating + //Looping if (name == 'repeatType') { - this.repeatType = args; + _player.setLoopMode(LoopMode.values[args]); } + if (name == 'saveQueue') await this._saveQueue(); + //Load queue after some initialization in frontend + if (name == 'load') await this._loadQueueFile(); + //Shuffle + if (name == 'shuffle') await _player.setShuffleModeEnabled(args); + return true; } - Future _getArtUri(String url) async { - //Load from cache - if (url.startsWith('http')) { - //Prepare db - if (imagesDB == null) { - imagesDB = ImagesDatabase(); - await imagesDB.init(); - } - - String path = await imagesDB.getImage(url); - return 'file://$path'; + //Audio interruptions + @override + Future onAudioFocusLost(AudioInterruption interruption) { + if (_player.playing) _interrupted = true; + switch (interruption) { + case AudioInterruption.pause: + case AudioInterruption.temporaryPause: + case AudioInterruption.unknownPause: + if (_player.playing) onPause(); + break; + case AudioInterruption.temporaryDuck: + _player.setVolume(0.5); + break; } - //If file - if (url.startsWith('/')) return 'file://' + url; - return url; - } - - Future _getTrackUri(MediaItem mi, {int quality}) async { - String prefix = 'DEEZER|${mi.id}|'; - - //Check if song is available offline - String _offlinePath = p.join((await getExternalStorageDirectory()).path, 'offline/'); - File f = File(p.join(_offlinePath, mi.id)); - if (await f.exists()) return f.path; - - //Get online url - Track t = Track( - id: mi.id, - playbackDetails: jsonDecode(mi.extras['playbackDetails']) //JSON Because of audio_service bug - ); - - //Check connection - if (quality == null) { - ConnectivityResult conn = await Connectivity().checkConnectivity(); - quality = mobileQuality; - if (conn == ConnectivityResult.wifi) quality = wifiQuality; - } - String url = t.getUrl(quality); - - //Quality fallback - Dio dio = Dio(); - try { - await dio.head(url); - return prefix + url; - } catch (e) { - if (quality == 9) return _getTrackUri(mi, quality: 3); - if (quality == 3) return _getTrackUri(mi, quality: 1); - throw Exception('No available quality!'); - } - } - - - Future _getQualityString(String uri, Duration duration) async { - //Get url/path - String url = uri; - List split = uri.split('|'); - if (split.length >= 3) url = split[2]; - - int size; - String format; - String source; - - //Local file - if (url.startsWith('/')) { - //Read first 4 bytes of file, get format - File f = File(url); - Stream> reader = f.openRead(0, 4); - List magic = await reader.first; - format = _magicToFormat(magic); - size = await f.length(); - source = 'Offline'; - } - - //URL - if (url.startsWith('http')) { - Dio dio = Dio(); - Response response = await dio.head(url); - size = int.parse(response.headers['Content-Length'][0]); - //Parse format - format = response.headers['Content-Type'][0]; - if (format.trim() == 'audio/mpeg') format = 'MP3'; - if (format.trim() == 'audio/flac') format = 'FLAC'; - source = 'Stream'; - } - //Calculate - return '$format ${_bitrateString(size, duration.inSeconds)} ($source)'; - } - - String _bitrateString(int size, int duration) { - int bitrate = ((size / 125) / duration).floor(); - //Prettify - if (bitrate > 315 && bitrate < 325) return '320kbps'; - if (bitrate > 125 && bitrate < 135) return '128kbps'; - return '${bitrate}kbps'; - } - - //Magic number to string, source: https://en.wikipedia.org/wiki/List_of_file_signatures - String _magicToFormat(List magic) { - Function eq = const ListEquality().equals; - if (eq(magic.sublist(0, 4), [0x66, 0x4c, 0x61, 0x43])) return 'FLAC'; - //MP3 With ID3 - if (eq(magic.sublist(0, 3), [0x49, 0x44, 0x33])) return 'MP3'; - //MP3 - List m = magic.sublist(0, 2); - if (eq(m, [0xff, 0xfb]) ||eq(m, [0xff, 0xf3]) || eq(m, [0xff, 0xf2])) return 'MP3'; - //Unknown - return 'UNK'; } @override - void onTaskRemoved() async { + Future onAudioFocusGained(AudioInterruption interruption) { + switch (interruption) { + case AudioInterruption.temporaryPause: + if (!_player.playing && _interrupted) onPlay(); + break; + case AudioInterruption.temporaryDuck: + _player.setVolume(1.0); + break; + default: + break; + } + _interrupted = false; + } + + @override + Future onAudioBecomingNoisy() { + onPause(); + } + + @override + Future onTaskRemoved() async { await onStop(); } @override + Future onClose() async { + await onStop(); + } + Future onStop() async { - _audioPlayer.stop(); - if (_playerStateSub != null) _playerStateSub.cancel(); - if (_eventSub != null) _eventSub.cancel(); await _saveQueue(); + _player.stop(); + if (_eventSub != null) _eventSub.cancel(); - await super.onStop(); + super.onStop(); } - @override - void onClose() async { - //await _saveQueue(); - //Gets saved in onStop() - await onStop(); - } - - //Update state - void _setState(AudioProcessingState state, {Duration pos}) { - AudioServiceBackground.setState( - controls: _getControls(), - systemActions: (_playing == null) ? [] : [MediaAction.seekTo], - processingState: state ?? AudioServiceBackground.state.processingState, - playing: _playing ?? false, - position: pos ?? _audioPlayer.playbackEvent.position, - bufferedPosition: pos ?? _audioPlayer.playbackEvent.position, - speed: _audioPlayer.speed - ); - } - - List _getControls() { - if (_playing == null || !_playing) { - //Paused / not-started - return [ - previousControl, - playControl, - nextControl - ]; - } - //Playing - return [ - previousControl, - pauseControl, - nextControl - ]; - } - - //Get queue saved file path + //Get queue save file path Future _getQueuePath() async { Directory dir = await getApplicationDocumentsDirectory(); - return p.join(dir.path, 'offline.json'); + return p.join(dir.path, 'playback.json'); } //Export queue to JSON Future _saveQueue() async { - print('save'); - File f = File(await _getQueuePath()); - await f.writeAsString(jsonEncode({ + String path = await _getQueuePath(); + File f = File(path); + //Create if doesnt exist + if (! await File(path).exists()) { + f = await f.create(); + } + + Map data = { 'index': _queueIndex, 'queue': _queue.map>((mi) => mi.toJson()).toList(), - 'position': _audioPlayer.playbackEvent.position.inMilliseconds, + 'position': _player.position.inMilliseconds, 'queueSource': (queueSource??QueueSource()).toJson(), - })); + }; + await f.writeAsString(jsonEncode(data)); } - Future _loadQueue() async { + //Restore queue & playback info from path + Future _loadQueueFile() async { File f = File(await _getQueuePath()); if (await f.exists()) { Map json = jsonDecode(await f.readAsString()); this._queue = (json['queue']??[]).map((mi) => MediaItem.fromJson(mi)).toList(); - this._queueIndex = json['index'] ?? -1; + this._queueIndex = json['index'] ?? 0; this._lastPosition = Duration(milliseconds: json['position']??0); this.queueSource = QueueSource.fromJson(json['queueSource']??{}); + //Restore queue if (_queue != null) { - AudioServiceBackground.setQueue(_queue); + await AudioServiceBackground.setQueue(_queue); + await _loadQueue(); AudioServiceBackground.setMediaItem(mediaItem); - //Update state to allow play button in notification - this._setState(AudioProcessingState.none, pos: _lastPosition); } - //Send restored queue source to ui - AudioServiceBackground.sendCustomEvent({'action': 'onRestore', 'queueSource': (queueSource??QueueSource()).toJson()}); - return true; + } + //Send restored queue source to ui + AudioServiceBackground.sendCustomEvent({ + 'action': 'onRestore', + 'queueSource': (queueSource??QueueSource()).toJson() + }); + return true; + } + + @override + Future onAddQueueItemAt(MediaItem mi, int index) async { + //-1 == play next + if (index == -1) index = _queueIndex + 1; + + + _queue.insert(index, mi); + await AudioServiceBackground.setQueue(_queue); + await _audioSource.insert(index, await _mediaItemToAudioSource(mi)); + + _saveQueue(); + } + + //Add at end of queue + @override + Future onAddQueueItem(MediaItem mi) async { + _queue.add(mi); + await AudioServiceBackground.setQueue(_queue); + await _audioSource.add(await _mediaItemToAudioSource(mi)); + _saveQueue(); + } + + @override + Future onPlayFromMediaId(String mediaId) async { + //Does the same thing + await this.onSkipToQueueItem(mediaId); + } + +} + +//Seeker from audio_service example (why reinvent the wheel?) +//While holding seek button, will continuously seek +class Seeker { + final AudioPlayer player; + final Duration positionInterval; + final Duration stepInterval; + final MediaItem mediaItem; + bool _running = false; + + Seeker(this.player, this.positionInterval, this.stepInterval, this.mediaItem); + + Future start() async { + _running = true; + while (_running) { + Duration newPosition = player.position + positionInterval; + if (newPosition < Duration.zero) newPosition = Duration.zero; + if (newPosition > mediaItem.duration) newPosition = mediaItem.duration; + player.seek(newPosition); + await Future.delayed(stepInterval); } } + void stop() { + _running = false; + } } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 8b147a9..de73e8d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -27,7 +27,7 @@ void main() async { //Initialize globals settings = await Settings().loadSettings(); - await imagesDatabase.init(); + //await imagesDatabase.init(); await downloadManager.init(); runApp(FreezerApp()); @@ -44,9 +44,6 @@ class _FreezerAppState extends State { //Make update theme global updateTheme = _updateTheme; - //Precache placeholder - precacheImage(imagesDatabase.placeholderThumb, context); - super.initState(); } diff --git a/lib/ui/cached_image.dart b/lib/ui/cached_image.dart index 1dda7c5..b8daf75 100644 --- a/lib/ui/cached_image.dart +++ b/lib/ui/cached_image.dart @@ -1,209 +1,66 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:palette_generator/palette_generator.dart'; -import 'package:path/path.dart' as p; -import 'package:path_provider/path_provider.dart'; -import 'package:sqflite/sqflite.dart'; -import 'package:crypto/crypto.dart'; -import 'package:dio/dio.dart'; - -import 'dart:io'; -import 'dart:convert'; +import 'package:cached_network_image/cached_network_image.dart'; ImagesDatabase imagesDatabase = ImagesDatabase(); + class ImagesDatabase { /* - images.db: - Table: images - Fields: - id - id - name - md5 hash of url. also filename - url - url - permanent - 0/1 - if image is cached or offline + !!! Using the wrappers so i don't have to rewrite most of the code, because of migration to cached network image */ - - Database db; - String imagesPath; - - ImageProvider placeholderThumb = new AssetImage('assets/cover_thumb.jpg'); - - //Prepare database - Future init() async { - String dir = await getDatabasesPath(); - String path = p.join(dir, 'images.db'); - db = await openDatabase( - path, - version: 1, - singleInstance: false, - onCreate: (Database db, int version) async { - //Create table on db created - await db.execute('CREATE TABLE images (id INTEGER PRIMARY KEY, name TEXT, url TEXT, permanent INTEGER)'); - } - ); - //Prepare folders - imagesPath = p.join((await getApplicationDocumentsDirectory()).path, 'images/'); - Directory imagesDir = Directory(imagesPath); - await imagesDir.create(recursive: true); + void saveImage(String url) { + CachedNetworkImageProvider(url); } - String getPath(String name) { - return p.join(imagesPath, name); + Future getPaletteGenerator(String url) { + return PaletteGenerator.fromImageProvider(CachedNetworkImageProvider(url)); } - //Get image url/path, cache it - Future getImage(String url, {bool permanent = false}) async { - //Already file - if (!url.startsWith('http')) { - url = url.replaceFirst('file://', ''); - if (!permanent) return url; - //Update in db to permanent - String name = p.basenameWithoutExtension(url); - await db.rawUpdate('UPDATE images SET permanent == 1 WHERE name == ?', [name]); - } - //Filename = md5 hash - String hash = md5.convert(utf8.encode(url)).toString(); - List results = await db.rawQuery('SELECT * FROM images WHERE name == ?', [hash]); - String path = getPath(hash); - if (results.length > 0) { - //Image in database - return path; - } - //Save image - Dio dio = Dio(); - try { - await dio.download(url, path); - await db.insert('images', {'url': url, 'name': hash, 'permanent': permanent?1:0}); - return path; - } catch (e) { - return null; - } - } - - Future getPaletteGenerator(String url) async { - String path = await getImage(url); - //Get image provider - ImageProvider provider = placeholderThumb; - if (path != null) { - provider = FileImage(File(path)); - } - PaletteGenerator paletteGenerator = await PaletteGenerator.fromImageProvider(provider); - return paletteGenerator; - } - - //Get primary color from album art Future getPrimaryColor(String url) async { PaletteGenerator paletteGenerator = await getPaletteGenerator(url); return paletteGenerator.colors.first; } - //Check if is dark Future isDark(String url) async { PaletteGenerator paletteGenerator = await getPaletteGenerator(url); return paletteGenerator.colors.first.computeLuminance() > 0.5 ? false : true; } - } class CachedImage extends StatefulWidget { - final String url; final double width; final double height; final bool circular; + final bool fullThumb; - const CachedImage({Key key, this.url, this.height, this.width, this.circular = false}): super(key: key); + const CachedImage({Key key, this.url, this.height, this.width, this.circular = false, this.fullThumb = false}): super(key: key); @override _CachedImageState createState() => _CachedImageState(); } class _CachedImageState extends State { - - ImageProvider _image = imagesDatabase.placeholderThumb; - double _opacity = 0.0; - bool _disposed = false; - String _prevUrl; - - Future _getImage() async { - //Image already path - if (!widget.url.startsWith('http')) { - //Remove file://, if used in audio_service - if (widget.url.startsWith('/')) return FileImage(File(widget.url)); - return FileImage(File(widget.url.replaceFirst('file://', ''))); - } - //Load image from db - String path = await imagesDatabase.getImage(widget.url); - if (path == null) return imagesDatabase.placeholderThumb; - return FileImage(File(path)); - } - - //Load image and fade - void _load() async { - if (_prevUrl == widget.url) return; - - ImageProvider image = await _getImage(); - if (_disposed) return; - setState(() { - _image = image; - _opacity = 1.0; - }); - _prevUrl = widget.url; - } - - @override - void dispose() { - _disposed = true; - super.dispose(); - } - - @override - void initState() { - _load(); - super.initState(); - } - - @override - void didUpdateWidget(CachedImage oldWidget) { - _load(); - super.didUpdateWidget(oldWidget); - } - @override Widget build(BuildContext context) { - return Stack( - children: [ - widget.circular ? - CircleAvatar( - radius: (widget.width??widget.height), - backgroundImage: imagesDatabase.placeholderThumb, - ): - Image( - image: imagesDatabase.placeholderThumb, - height: widget.height, - width: widget.width, - ), + if (widget.circular) return ClipOval( + child: CachedImage(url: widget.url, height: widget.height, width: widget.width, circular: false) + ); - AnimatedOpacity( - duration: Duration(milliseconds: 250), - opacity: _opacity, - child: widget.circular ? - CircleAvatar( - radius: (widget.width??widget.height), - backgroundImage: _image, - ): - Image( - image: _image, - height: widget.height, - width: widget.width, - ), - ) - ], + return CachedNetworkImage( + imageUrl: widget.url, + width: widget.width, + height: widget.height, + placeholder: (context, url) { + if (widget.fullThumb) return Image.asset('assets/cover.jpg', width: widget.width, height: widget.height,); + return Image.asset('assets/cover_thumb.jpg', width: widget.width, height: widget.height); + }, + errorWidget: (context, url, error) => Image.asset('assets/cover_thumb.jpg', width: widget.width, height: widget.height), ); } - } - - diff --git a/lib/ui/details_screens.dart b/lib/ui/details_screens.dart index b08e06d..0c16fda 100644 --- a/lib/ui/details_screens.dart +++ b/lib/ui/details_screens.dart @@ -394,7 +394,19 @@ class ArtistDetails extends StatelessWidget { fontSize: 22.0 ), ), - ...List.generate(artist.albums.length, (i) { + ...List.generate(artist.albums.length > 10 ? 11 : artist.albums.length + 1, (i) { + //Show discography + if (i == 10 || i == artist.albums.length) { + return ListTile( + title: Text('Show all albums'), + onTap: () { + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => DiscographyScreen(artist: artist,)) + ); + } + ); + } + //Top albums Album a = artist.albums[i]; return AlbumTile( a, @@ -419,6 +431,103 @@ class ArtistDetails extends StatelessWidget { } } +class DiscographyScreen extends StatefulWidget { + + Artist artist; + DiscographyScreen({@required this.artist, Key key}): super(key: key); + + @override + _DiscographyScreenState createState() => _DiscographyScreenState(); +} + +class _DiscographyScreenState extends State { + + Artist artist; + bool _loading = false; + bool _error = false; + ScrollController _scrollController = ScrollController(); + + Future _load() async { + if (artist.albums.length >= artist.albumCount || _loading) return; + setState(() => _loading = true); + + //Fetch data + List data; + try { + data = await deezerAPI.discographyPage(artist.id, start: artist.albums.length); + } catch (e) { + setState(() { + _error = true; + _loading = false; + }); + return; + } + + //Save + setState(() { + artist.albums.addAll(data); + _loading = false; + }); + + } + + @override + void initState() { + artist = widget.artist; + + //Lazy loading scroll + _scrollController.addListener(() { + double off = _scrollController.position.maxScrollExtent * 0.90; + if (_scrollController.position.pixels > off) { + _load(); + } + }); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('Discography'),), + body: ListView.builder( + controller: _scrollController, + itemCount: artist.albums.length + 1, + itemBuilder: (context, i) { + //Loading + if (i == artist.albums.length) { + if (_loading) + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [CircularProgressIndicator()], + ); + //Error + if (_error) + return ErrorScreen(); + //Success + return Container(width: 0, height: 0,); + } + + Album a = artist.albums[i]; + return AlbumTile( + a, + onTap: () { + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => AlbumDetails(a)) + ); + }, + onHold: () { + MenuSheet m = MenuSheet(context); + m.defaultAlbumMenu(a); + }, + ); + }, + ), + ); + } +} + + class PlaylistDetails extends StatefulWidget { diff --git a/lib/ui/menu.dart b/lib/ui/menu.dart index dc8cd63..82f57bb 100644 --- a/lib/ui/menu.dart +++ b/lib/ui/menu.dart @@ -140,15 +140,8 @@ class MenuSheet { title: Text('Play next'), leading: Icon(Icons.playlist_play), onTap: () async { - if (playerHelper.queueIndex == -1) { - //First track - await AudioService.addQueueItem(t.toMediaItem()); - await AudioService.play(); - } else { - //Normal - await AudioService.addQueueItemAt( - t.toMediaItem(), playerHelper.queueIndex + 1); - } + //-1 = next + await AudioService.addQueueItemAt(t.toMediaItem(), -1); _close(); }); diff --git a/lib/ui/player_bar.dart b/lib/ui/player_bar.dart index 6c9d4b3..ac6eea2 100644 --- a/lib/ui/player_bar.dart +++ b/lib/ui/player_bar.dart @@ -32,7 +32,7 @@ class PlayerBar extends StatelessWidget { leading: CachedImage( width: 50, height: 50, - url: AudioService.currentMediaItem.artUri, + url: AudioService.currentMediaItem.extras['thumb'] ?? AudioService.currentMediaItem.artUri, ), title: Text( AudioService.currentMediaItem.displayTitle, diff --git a/lib/ui/player_screen.dart b/lib/ui/player_screen.dart index 9af003a..bd36530 100644 --- a/lib/ui/player_screen.dart +++ b/lib/ui/player_screen.dart @@ -6,10 +6,12 @@ import 'package:audio_service/audio_service.dart'; import 'package:flutter_screenutil/screenutil.dart'; import 'package:freezer/api/deezer.dart'; import 'package:freezer/api/player.dart'; +import 'package:freezer/settings.dart'; import 'package:freezer/ui/menu.dart'; import 'package:freezer/ui/settings_screen.dart'; import 'package:freezer/ui/tiles.dart'; import 'package:async/async.dart'; +import 'package:just_audio/just_audio.dart'; import 'package:marquee/marquee.dart'; import 'cached_image.dart'; @@ -84,9 +86,10 @@ class _PlayerScreenHorizontalState extends State { children: [ CachedImage( url: AudioService.currentMediaItem.artUri, + fullThumb: true, ), if (_lyrics) LyricsWidget( - artUri: AudioService.currentMediaItem.artUri, + artUri: AudioService.currentMediaItem.extras['thumb'], trackId: AudioService.currentMediaItem.id, lyrics: Track.fromMediaItem(AudioService.currentMediaItem).lyrics, height: ScreenUtil().setWidth(500), @@ -188,7 +191,7 @@ class _PlayerScreenHorizontalState extends State { MaterialPageRoute(builder: (context) => QualitySettings()) ), child: Text( - AudioService.currentMediaItem.extras['qualityString'], + AudioService.currentMediaItem.extras['qualityString'] ?? '', style: TextStyle(fontSize: ScreenUtil().setSp(24)), ), ), @@ -242,9 +245,10 @@ class _PlayerScreenVerticalState extends State { children: [ CachedImage( url: AudioService.currentMediaItem.artUri, + fullThumb: true, ), if (_lyrics) LyricsWidget( - artUri: AudioService.currentMediaItem.artUri, + artUri: AudioService.currentMediaItem.extras['thumb'], trackId: AudioService.currentMediaItem.id, lyrics: Track.fromMediaItem(AudioService.currentMediaItem).lyrics, height: ScreenUtil().setHeight(1050), @@ -322,7 +326,7 @@ class _PlayerScreenVerticalState extends State { MaterialPageRoute(builder: (context) => QualitySettings()) ), child: Text( - AudioService.currentMediaItem.extras['qualityString'], + AudioService.currentMediaItem.extras['qualityString'] ?? '', style: TextStyle( fontSize: ScreenUtil().setSp(32), ), @@ -574,15 +578,15 @@ class _RepeatButtonState extends State { Icon get icon { switch (playerHelper.repeatType) { - case RepeatType.NONE: + case LoopMode.off: return Icon(Icons.repeat, size: widget.size??_size); - case RepeatType.LIST: + case LoopMode.all: return Icon( Icons.repeat, color: Theme.of(context).primaryColor, size: widget.size??_size ); - case RepeatType.TRACK: + case LoopMode.one: return Icon( Icons.repeat_one, color: Theme.of(context).primaryColor, @@ -708,6 +712,18 @@ class QueueScreen extends StatefulWidget { } class _QueueScreenState extends State { + + //Get proper icon color by theme + Color get shuffleIconColor { + Color og = Theme.of(context).primaryColor; + if (og.computeLuminance() > 0.5) { + if (playerHelper.shuffle) return Theme.of(context).primaryColorLight; + return Colors.black; + } + if (playerHelper.shuffle) return Theme.of(context).primaryColorDark; + return Colors.white; + } + @override Widget build(BuildContext context) { return Scaffold( @@ -715,10 +731,13 @@ class _QueueScreenState extends State { title: Text('Queue'), actions: [ IconButton( - icon: Icon(Icons.shuffle), + icon: Icon( + Icons.shuffle, + color: shuffleIconColor + ), onPressed: () async { - await AudioService.customAction('shuffleQueue'); - setState(() => {}); + await playerHelper.toggleShuffle(); + setState(() {}); }, ) ], diff --git a/lib/ui/search.dart b/lib/ui/search.dart index 7ba12de..ae534b5 100644 --- a/lib/ui/search.dart +++ b/lib/ui/search.dart @@ -1,3 +1,4 @@ +import 'package:connectivity/connectivity.dart'; import 'package:flutter/material.dart'; import 'package:freezer/api/download.dart'; import 'package:freezer/api/player.dart'; @@ -7,7 +8,6 @@ import 'package:freezer/ui/menu.dart'; import 'tiles.dart'; import '../api/deezer.dart'; import '../api/definitions.dart'; -import '../settings.dart'; import 'error.dart'; class SearchScreen extends StatefulWidget { @@ -18,7 +18,7 @@ class SearchScreen extends StatefulWidget { class _SearchScreenState extends State { String _query; - bool _offline = settings.offlineMode; + bool _offline = false; void _submit(BuildContext context, {String query}) { if (query != null) _query = query; @@ -27,6 +27,19 @@ class _SearchScreenState extends State { ); } + @override + void initState() { + //Check for connectivity and enable offline mode + Connectivity().checkConnectivity().then((res) { + if (res == ConnectivityResult.none) setState(() { + _offline = true; + }); + }); + + + super.initState(); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -59,11 +72,7 @@ class _SearchScreenState extends State { leading: Switch( value: _offline, onChanged: (v) { - if (settings.offlineMode) { - setState(() => _offline = true); - } else { - setState(() => _offline = v); - } + setState(() => _offline = !_offline); }, ), ) diff --git a/pubspec.lock b/pubspec.lock deleted file mode 100644 index ed3238f..0000000 --- a/pubspec.lock +++ /dev/null @@ -1,826 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - url: "https://pub.dartlang.org" - source: hosted - version: "4.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - url: "https://pub.dartlang.org" - source: hosted - version: "0.39.10" - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.13" - args: - dependency: transitive - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "1.6.0" - async: - dependency: "direct main" - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.1" - audio_service: - dependency: "direct main" - description: - name: audio_service - url: "https://pub.dartlang.org" - source: hosted - version: "0.11.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - build: - dependency: transitive - description: - name: build - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - build_config: - dependency: transitive - description: - name: build_config - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.2" - build_daemon: - dependency: transitive - description: - name: build_daemon - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.4" - build_resolvers: - dependency: transitive - description: - name: build_resolvers - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.9" - build_runner: - dependency: "direct dev" - description: - name: build_runner - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - build_runner_core: - dependency: transitive - description: - name: build_runner_core - url: "https://pub.dartlang.org" - source: hosted - version: "5.2.0" - built_collection: - dependency: transitive - description: - name: built_collection - url: "https://pub.dartlang.org" - source: hosted - version: "4.3.2" - built_value: - dependency: transitive - description: - name: built_value - url: "https://pub.dartlang.org" - source: hosted - version: "7.1.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.3" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - code_builder: - dependency: transitive - description: - name: code_builder - url: "https://pub.dartlang.org" - source: hosted - version: "3.3.0" - collection: - dependency: "direct main" - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.14.12" - connectivity: - dependency: "direct main" - description: - name: connectivity - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.8+6" - connectivity_macos: - dependency: transitive - description: - name: connectivity_macos - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.0+3" - connectivity_platform_interface: - dependency: transitive - description: - name: connectivity_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.6" - convert: - dependency: transitive - description: - name: convert - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - cookie_jar: - dependency: "direct main" - description: - name: cookie_jar - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - country_pickers: - dependency: "direct main" - description: - name: country_pickers - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - crypto: - dependency: "direct main" - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.4" - csslib: - dependency: transitive - description: - name: csslib - url: "https://pub.dartlang.org" - source: hosted - version: "0.16.1" - custom_navigator: - dependency: "direct main" - description: - name: custom_navigator - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.0" - dart_style: - dependency: transitive - description: - name: dart_style - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.6" - dio: - dependency: "direct main" - description: - name: dio - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.9" - dio_cookie_manager: - dependency: "direct main" - description: - name: dio_cookie_manager - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - disk_space: - dependency: "direct main" - description: - name: disk_space - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.3" - ext_storage: - dependency: "direct main" - description: - name: ext_storage - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.3" - fading_edge_scrollview: - dependency: transitive - description: - name: fading_edge_scrollview - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.4" - file: - dependency: transitive - description: - name: file - url: "https://pub.dartlang.org" - source: hosted - version: "5.1.0" - filesize: - dependency: "direct main" - description: - name: filesize - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.4" - fixnum: - dependency: transitive - description: - name: fixnum - url: "https://pub.dartlang.org" - source: hosted - version: "0.10.11" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_cache_manager: - dependency: transitive - description: - name: flutter_cache_manager - url: "https://pub.dartlang.org" - source: hosted - version: "1.4.0" - flutter_inappwebview: - dependency: "direct main" - description: - name: flutter_inappwebview - url: "https://pub.dartlang.org" - source: hosted - version: "3.3.0+3" - flutter_isolate: - dependency: transitive - description: - name: flutter_isolate - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0+14" - flutter_local_notifications: - dependency: "direct main" - description: - name: flutter_local_notifications - url: "https://pub.dartlang.org" - source: hosted - version: "1.4.4+1" - flutter_local_notifications_platform_interface: - dependency: transitive - description: - name: flutter_local_notifications_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - flutter_material_color_picker: - dependency: "direct main" - description: - name: flutter_material_color_picker - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.5" - flutter_screenutil: - dependency: "direct main" - description: - name: flutter_screenutil - url: "https://pub.dartlang.org" - source: hosted - version: "2.3.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - fluttertoast: - dependency: "direct main" - description: - name: fluttertoast - url: "https://pub.dartlang.org" - source: hosted - version: "4.0.1" - glob: - dependency: transitive - description: - name: glob - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - graphs: - dependency: transitive - description: - name: graphs - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.0" - hex: - dependency: "direct main" - description: - name: hex - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.2" - html: - dependency: "direct main" - description: - name: html - url: "https://pub.dartlang.org" - source: hosted - version: "0.14.0+3" - http: - dependency: transitive - description: - name: http - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.1" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.0" - http_parser: - dependency: transitive - description: - name: http_parser - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.4" - image: - dependency: transitive - description: - name: image - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.12" - intl: - dependency: "direct main" - description: - name: intl - url: "https://pub.dartlang.org" - source: hosted - version: "0.16.1" - io: - dependency: transitive - description: - name: io - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.4" - js: - dependency: transitive - description: - name: js - url: "https://pub.dartlang.org" - source: hosted - version: "0.6.2" - json_annotation: - dependency: "direct main" - description: - name: json_annotation - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - json_serializable: - dependency: "direct dev" - description: - name: json_serializable - url: "https://pub.dartlang.org" - source: hosted - version: "3.3.0" - just_audio: - dependency: "direct main" - description: - path: "." - ref: HEAD - resolved-ref: "70392a52590c95bd4b1ca35c7e92d30793c7c4d3" - url: "https://notabug.org/exttex/just_audio.git" - source: git - version: "0.1.10" - language_pickers: - dependency: "direct main" - description: - name: language_pickers - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.0+1" - logging: - dependency: transitive - description: - name: logging - url: "https://pub.dartlang.org" - source: hosted - version: "0.11.4" - marquee: - dependency: "direct main" - description: - name: marquee - url: "https://pub.dartlang.org" - source: hosted - version: "1.5.2" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.6" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.8" - mime: - dependency: transitive - description: - name: mime - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.6+3" - move_to_background: - dependency: "direct main" - description: - name: move_to_background - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - node_interop: - dependency: transitive - description: - name: node_interop - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" - node_io: - dependency: transitive - description: - name: node_io - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" - package_config: - dependency: transitive - description: - name: package_config - url: "https://pub.dartlang.org" - source: hosted - version: "1.9.3" - package_info: - dependency: "direct main" - description: - name: package_info - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.1" - palette_generator: - dependency: "direct main" - description: - name: palette_generator - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.3" - path: - dependency: "direct main" - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.6.4" - path_provider: - dependency: "direct main" - description: - name: path_provider - url: "https://pub.dartlang.org" - source: hosted - version: "1.6.10" - path_provider_ex: - dependency: "direct main" - description: - name: path_provider_ex - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.1+1" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.4+3" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.9.0" - permission_handler: - dependency: "direct main" - description: - name: permission_handler - url: "https://pub.dartlang.org" - source: hosted - version: "5.0.1" - permission_handler_platform_interface: - dependency: transitive - description: - name: permission_handler_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.0" - platform: - dependency: transitive - description: - name: platform - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.1" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - pointycastle: - dependency: "direct main" - description: - name: pointycastle - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - pool: - dependency: transitive - description: - name: pool - url: "https://pub.dartlang.org" - source: hosted - version: "1.4.0" - process: - dependency: transitive - description: - name: process - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.13" - pub_semver: - dependency: transitive - description: - name: pub_semver - url: "https://pub.dartlang.org" - source: hosted - version: "1.4.4" - pubspec_parse: - dependency: transitive - description: - name: pubspec_parse - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.5" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" - random_string: - dependency: "direct main" - description: - name: random_string - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - rxdart: - dependency: transitive - description: - name: rxdart - url: "https://pub.dartlang.org" - source: hosted - version: "0.24.1" - shelf: - dependency: transitive - description: - name: shelf - url: "https://pub.dartlang.org" - source: hosted - version: "0.7.5" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.3" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_gen: - dependency: transitive - description: - name: source_gen - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.5" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.7.0" - sqflite: - dependency: "direct main" - description: - name: sqflite - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - sqflite_common: - dependency: transitive - description: - name: sqflite_common - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.9.3" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - stream_transform: - dependency: transitive - description: - name: stream_transform - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.5" - synchronized: - dependency: transitive - description: - name: synchronized - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.15" - timing: - dependency: transitive - description: - name: timing - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.1+2" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.6" - uuid: - dependency: transitive - description: - name: uuid - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.4" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.8" - watcher: - dependency: transitive - description: - name: watcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.7+15" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.0" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "3.6.1" - yaml: - dependency: transitive - description: - name: yaml - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.1" -sdks: - dart: ">=2.7.0 <3.0.0" - flutter: ">=1.15.21 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 96ebdb3..be6513f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,10 +39,10 @@ dependencies: connectivity: ^0.4.8+6 intl: ^0.16.1 filesize: ^1.0.4 - fluttertoast: ^4.0.1 + fluttertoast: ^7.0.2 palette_generator: ^0.2.3 flutter_material_color_picker: ^1.0.5 - flutter_inappwebview: ^3.3.0+3 + flutter_inappwebview: ^4.0.0 custom_navigator: ^0.3.0 language_pickers: ^0.2.0+1 country_pickers: ^1.3.0 @@ -51,16 +51,18 @@ dependencies: flutter_local_notifications: ^1.4.4+1 collection: ^1.14.12 disk_space: ^0.0.3 - audio_service: ^0.11.0 path_provider_ex: ^1.0.1 random_string: ^2.0.1 async: ^2.4.1 html: ^0.14.0+3 flutter_screenutil: ^2.3.0 marquee: ^1.5.2 + flutter_cache_manager: ^1.4.1 + cached_network_image: ^2.2.0+1 + audio_service: ^0.13.0 just_audio: - git: https://notabug.org/exttex/just_audio.git + path: ./just_audio # cupertino_icons: ^0.1.3

?6>~bdd9YA7fn!qI)FRu z=`>eb8V%3Xw%>op1b(KrBjil&p9}pP4`L2SI8(dtOfY`ah;CWiBG237q|Z2?2tRMJ z_fdva$z~0-+X?A{JA@Q(?DZZ3`cRc40 z+&#Nj=dW_Fkkv;1#zygyyOxW-{{6J%pO!#h)5Gv}AI(QhBYYYtkG{# z+suV*jFwOtGfkaDJ;n+x#lY06FUCiPEkK&A@8Qt%aF-#^88ySqZ)f6mlDh2rq|RP~LJSf4A29v#j8;8>p_v4Y1F zJ-QZ$nU^#2Rg@R;zXJ2}_?`ZZ&(QaMOD3wzX-@LKn^QgC+{x$bH@WqL)I+2Bo?Y;K zy+d(tm}hb~WH4X-Y029(w!4VNe81(*81;Wc>HXtkPMftMeJceYJsBALE9rOTlaa^1 zm*lzY?yzIu6o{iSL9J6l*FG^8cZZCzt0*wW*+qPe_p~LE{T|Q6JQaQ0(?<1S^I)&B zHE6Ffna{ni2M5O^Mhs%^Un*k~_ly5ceaTv2e24w0lwp<|1ad5U4E-1{cG^)kombz%+IWlG5X|`Y|kavitXdo{qi2x|CvN=8~>?b zIDeIO*h*RF)BL_VFUS~)-%=fn3&$bD#@8IpR-HpUxXKi`dwheHHS6~o7TgrbTdTjf zb83jwr`_A(Me_3E2tRnhlEsH!43hoLM4=Gdz{yv}U*FOn?Sxqq5 zlE{4;4*t9*VxRVSMnX3pr)vI1eR~!*=Bqm;?wrgfSS^b~WLQXlOrT%s0Qy6+_sfvJ z6rlY@{)qR|57AoNaaH*J7xcxlqexvhM$9$DxHuTnpJ(o5j>aD{$Mg_>PX+wDBg5YX z_$32}Zv=ZY!5$R~n|P;VVSsnOJ4t-8Ff#A_YGEKAQbbzEcClJAgg3BqsMEhj>1!lr&S~)OF!#M)=hbe%gJsSA*`Or8TA` zigi}o$2rE=S&>hn{2=kyEI*G`!1ov46?WijmBDsk&S0k5fqTl{GqwYj#QyeW&A1Y` zW(z`3zSTfau1ptta^gv8|IG;K$#cH#uP2A|f%wOu^YelD4Xv9k7xtIehlt)N%ky*W zNLKAxf-iQ4#%Cj35zij@d|;s8yejcoA^G!!PQNkQJA0Dw$;t@7cZN05#`jii>V*;D zK6{>U?<2UCsS)AsDZ^S^GC|d1)9ClwHxmEt^7+&Fo$Vrj-?-M(^FzAxTkhi>qKjWg zuw6+8KHgMrsqC|5N4#1i<$SdcHe$+eK5OFef4ZMJp8cFTw)(_;e8eZ^1oXFjAtQ|Z z`Yr=}qqs;V;(jgGl@ADBU;Pl;WubmtM4fcIMJZGdgeL@WJ_vu%PMv)?QW5uE0M|opWJLwbh89U1^arxwLmJH-Z6D>VNx8IR%`1^8`dus;cXYocphTl+sjPegBS2*3c zkA*lk4Y>V#yE9jro4JA2BEHI6_$uX&R6V#)R#&wG_sQUg zfIDR_o|9ALnRLt#*>9QHx1Zez>=RDwCa*?W!Z3wfqv5qy2KmU93>)dqL42m)O8mHVw7m(n0Xm<+#K2;883P$ z3&;?$Pjs=GjdQKg@-oJITmzd9m&8h%MhThpWC%?y z(K?z&7a03-o6n!7&(9CUWElueq4VkKYA3oH-77$!u;zbvhkxVooBrt5`}KV%?6W3T zS}4x{ZV$H4w7#x`zwXRJL;I{dLM~r^*V-b_I(CX!WZJzkZm((g4Q}cG4gQ||+aT+rTp`$%@}BKs?(Z7s1rNCF zB5tPBF89@UhaM)Z;h3#phcZ!SW3n)@yW+r|-V_ee&Mcv$U2h4%~UuVv{g>catLST^+na z_>wf-%PKfe-!e*lS(jG>euD5Pfo~w@1@@I#rI;I_$E~-8#6&ddADS|MPKiPWdM^X^lV=2taEgR@4! ziHp>y$Ih=$OEupTdDcVrVR9wUr!HU}xz!j}HTLV&?+HtuwOa(N?d+9Q4r|}7#`LSk z+4r{8^P*oLtcm&jY=HOa=b}%qN9xlrzHgtzUg`T9tgQmpmhgT0Cf9v_Jkba1%}MGX zG&rpS&J&UP)b>65Bz+ctslnm+NmN`tHxQr;Ve?Qul zO;IyMpZ2iBqE83sh3KP}zCP{A{nEHkxc3_oPR5izALYH&{!gWTT!NT*6Ghx+f0@Y1 z?!Q9Zp~iOyzB^d!Cni>FN!+mM)g;#@tc%b?5y!nR7HG&GVGqeuR%8$hl*(m^{kJAd z{l#jY)OB<9xj@JcOs+J!Q#+W$t;x<$1#O<27h$|V`<`=B`uetG9}uvZlT=G5PJU&%T*WeThI6b#SfaCa{ za1x4DzwifcVjr0}oIl?ZLGSt4^!>(2`lNn#R`%&i(Wl=<>eE%vMA>I@CedI2XT5}YRo4hJwetR#iopZA{? z@rFX<3;1HM;%6{FnP+?k^PSnm@5f@#e!;gQE`{)+Nb}rIzq9CfuRP~6I@=mddPqx1 zUXU(bUJ$;vDwnBcqXRiX^f_6E+-!0i?H?^9d{5u^nmb%P1lX;duDv36@f$Y_x}G3- zy`0rglAv8BiYvTJ`ro9j@n|`{b}^Jwnn`m?z;qlo`_&Dw1 z@yQz%II93onA53Nk%Qn$3F{St#ViApH$U3=A~N#z7ppvZ}>Sj;X`sEIPYQz zj3;m5cfI=iI#9V(;+xJ9A`cAKfxpQ-Fo+8g%YyT!{)Aw4oc6aJ=dr?!V-lRc?;XBY zd~|b|IN>s84q{EghXApr5GR|Dud37{b_>5pxIn38Hu~O8HYduxC}Pj){R^`p`{M(7 zpg;AKT#65&cgWgUc1ysoCNx%?-2ZK|?1)jza*X$XGhNIv#~{W${3;&!CfMh4$u|Vc z62R|u;Ae@9-w5CrJ8=AP1{8{;op2lz;)^-w8{v1N;WFzRyr*01D z6=8e|$Y!^wH96sZ3XFVFt_{O01M#QXck{sfY1Z5<{ArfrK6Z#d&4wGfKTXrW<4={b)HjPzP}s^HQ8e{JV_Bju^iuXx%o;{2|y^`oxsR&$wvp zE4Y84IpFsR8TqeGXv4?)iV1zb$zRB%vp6WE%rn%=ci&u$m*o1zrN)<839+dD) znX)@Go*n6w`GWMZS!#O_lO{M;OX*Giw4k{5mmyXN%?n2BHRj}3;`|@E6Zvmbp}fPG z?Ab>6AvTBp%pS4pZz4EXP`ilHc5E2)>1~mUJ(E6cAe?*BXxv7Xa2*tURy>*=Ibap* zjXfGUyj|t*+FVKFh~Ms$aX-I|b|rl^eqDy2o_8u%`>!uwpRrr9+p7m#?FUCPhu!LQ zB*Y8+QD+bRq3qXGCo_-Lda3MxQJt@p1pDs6cDwf?sxz4Cq&OV|DnFLWr&IaiPDjs3 zqLs4pxB7aAWW6$~_cGNZCDvXu*k(U?DRb~R!-ON|nElB7BHNM7qOr#^i+Fwo>ObaF zm)-ftg+$|pLkra|8VlAj;zGsjDmT%e->>Ae9lzKM56f_I2-9*Uv48Q`6*tB3an@y=E3h?(qxIHGMl&w=JD-$lIhV;YzL zlDy;Pyt9_`&bvySeevb%GTu|-?XL`uvmd5$i6h>Lm%O8|7q$-ZP8{)0Jn_ze$`kLz z5%0tgA7FXnnYe5!KYD=W$5Z)SDu2lU%NH_7{N=>U6P%8(iI-oIe2nw_BUA@`{39xV zi7DQmU`nvRH#pw@{<@!F z+rahK% zy}gX&a8|wZn*GtreFq7a`31{;Q7>379Zmno(EqCw?;3Yy;$4fcOI$c^dg8*xa}$3! zZbsq{7ndjgVBECCA1uBqn$6jszkTuZ`Oh!@RsOFQCjfgugumu3NO&Rtg~dP0Sup!R z&Vq#1^#8g1=NA7q|F?@@%71C`i}}A@KrwihXis0%Qk#c#xZ^ zRIze@o?H`rbexVH?vF#?t<--rb6iuMTQo~SIZNYA;y3tXj3vIwBfhZ{-+=bH8sC^Z zru6YmzT}%|;v4$&(;B4l&W^Leyz|QE1LK`{NNzoHL;v_|%W!Xr^a3r`u(o!8etq!T z{nY2*Kj#UDq0=S)64LfV)OP(kp?m1p_hp~^)2<7Lb6H^@&RYDp_K$0^`_Y z7BS+q@1f&(E_@!4__U-1SB@eSVU^xxDgUMuR0|JokX_76S{=oNQ< zD(B$134P_ag_OSqxTOAPbev~G+Mb4cWbn0;bpNrWyGHNsbI`jx0=*y7!P4{`z=WeK#vCa22#^M+AAz!Z&Ux_zU{kbcEcnRDd~1kH?O0iSn$G)wl(oEv(7B7pa|2mER8 zg~3~km9OFb#Q}-8^mzi_SM=d6@-qC3%2aZ^311e7`^xLR6X2;)A@%m4UTXh(_ahch zUtflJQmNjZef5I%&o`(qq)&vEdH+sKzJB<&W2e@=Jf&co)&Sm}njD9H4?JyVp)- zgA4C{_$izPfaX>ut&yKg)136bQ+#A0d=jTIb#J*i69CRBPU5|XnY)A5$Y;(@e>&O3 z+J^9ZnPUI_opO$o87r4rzKzipMu6xa^Bmw%PWd zkAJ>sF7}|<-r#cwasJBl$0+jLdazQ9^$f9=>g9g^QCcr7ednA4F14k8ykEo!J!|aifxKD~eLdnsd_Cd>9#0S+U4ue=apH8oIB|h9|N9RJx*+yLIDZQ_ ztvOi<{m*!J5#RO22dN*c+U40lVuK(~NXlH{&w)50@JDb$Pq|L`)892G#3x+(+RTJc z_*`Ru`fg_IYlHJ**&okwIR=`~1HTs*8|ZsUY@qM?2hQ#9P%}4>SK)m6uK7Kn@53cu z&h(4eilonnrSLtI8(Ff0#~)lq@IIRD z-v^6nJO=2pOfb;*H``(+40mdxf z{|~sF``)|Dx#ymH&bfP<{fKl&%Co@Zb=vbGol7duy_--6OHl{b;o|*>U-LQ`*r^V> zs`nGXg>_Nyr{sE<@|5enLe6ucu;-u9F{2AR&)fcBo6ke9tjPD)10&A;-`s=o&jM$( zzxjQV$+Rwq)rfl%`T5uP2si5&fPc3z-7?hOGW#g|QyzB*@cqL=>=`;&SX(Ww-Eo~| zzK+$--OT$*o9Fc(Z*TP2t4RA4dphS<5Bl4F?Vq3OJkOXsnP$%bU;j*nzCZ9#E|u00 zy&=>#o5Z_)y2~dU`DpI%G9UMuW5Wf$216_5^WtKU@+P9Z&Cp$&r1GvDeck09K|H%D zfbu?`&dVDo;jy9A0}tuE@l6{gJm_BL>%>C<9)~vsK#y&(1(hNWWp{euAl(~LVUuup zdhB)Ma2EQkX>9yLl9^-ZTl$6hfVh?&gE%5#17waW@wvM}Qdfs0^XITbN*8FMq`y?D* zEbzcVz8|4h!l60gx^Y+r99V4tINUUow=74%}Wd2K+@_ifm_LlAoN$)woub|V;8Uo?78TQLk z88^(3^2!lv&r%s*7iw9gSjOh*J?HuNd^*cAfIPpL1>G-|FV%ym=pL6vsMFgdo;nhL z-8{7qIH+$60EdKG{2Y=$D|$ZXeLK>$-4Z~W1H`)fZ2)QBNA;r%Ak9@Xc$%96NVA^k zUlc%^chBT$)&-De3DRuxcdo8)n*W<_zcYaJ@~D312aw+I8TNSrq?bzg&GVmLF=Llq z=?xKe_0#~;9Dy{Mzq5CJ)67ig_eAuRUSHy$>;TGa5p_@R0Mh(+KKLgyfHc2iT!yy= zaG$|Hk)}oyK$@>G`-K3~dmHH;_IIwXFCBMGK*U_SFHTXQKL<6hL}^o5s(+ zS`t8-I;x)u0i-!?I=`Q@D1bE6k*3Yxxw@U|T$H~v14uK0+E07{X}&qb9`AEU!#}?h z*XVa=V+^45M|EpsY+gE?&KgVidsg@$K^*Uh44^Dm^FW{B0hHzBO#3&i=kzWhJ*EyI zy~WU>0i^d9;des->3y4Ke$J8r(+8(7KKN;HVxit+ntT1=_(R5O<@G3k zCHx2d`1o)1gD>Z8KXbzWnd?o{M?UyLbHbbVuNPcn&}V$oUjISQW6)i#6VcKA=i$>` zbFzo#cD+ud;sa;2)(;J6?QSodxIcnuAg_Z%e?0l9v=*)p*8YOitFMI zM|iJ`GxZYJ#eHA;UC-LQt8=8ad7<7o?2&L7)CF-@5OK z&cBuDrT&rYn$zZSLE48F)zZs{HqS}4`KkHHD3>qDKOa3fpmV))S>jQzAI|Yv|3kPB z`0?xYHq`6*#x;-5`l}hke%mn)*uXnx*wGEAS08J3;4Or@7X@M7N|# z>t9w#>tFa8*vimLYQFvj-#ym9Z1AD+#P@yIzcl=y^)GbS^Hpj63*l=5UtbIs_s;s# zVGQWN&n8X$1*gO5+0q(lK`bl9t3a7{gASn;DXCqpSN#`w{=K<=b=3)fx+>F$24B4Q z{dLs>pS`VPebRpCJ^%Yr-hR&+{S7v)*fdczbzYaP6_~=abh#Dl(#-eGsYcYW);%cc4|JJA0+Z{o3Akmo`;%KIwn<_vh4 z=vNWK_K7r%Zh0T+oOj_7-E!}H;(GQ9w1L$~7d+NNYo^m)~_hR4=XD4XoWqy2@j?FLTdXAA9k`cb(DC`N_L0Ii&U} z^YM3okQ}q#>5RUcgI-lcN`JoX6R@=*V1`cbOr^TJ3+MJ-~OfG^Ar8>jXzIN+RufGcT(`@c`AEG zFzhS&c|Z_{xr2iXn5Vi~Sv`9I_0ap3=T-y7RJapyQEPO#tSfivMt<8yW2D){&& z;l!W+su1V(<>%i8^LsNw<>!yYXO;XsC`7s^V_?f$5>5sQr>{dYIbSUBQ}4cOsJUD| z>bBhuW_j0t#XI8o9N(KUSghCc(pf}u{axU?gwAzP^8Ur`pv6=_d4J8UwWTDsUOt761P$#Kr${692F9 zDS!Ms?mf?=-r=(F^45<+Ts&Qq)iqBKM&4JlyOx2Xz6y2WAV@ge?t??fJMKNZs&}}3 zdwG9CsLN(8@CpCj8PQgh_X}`4v%CEQJ;>D*pY$)Bk@`#FKmL9JUzripiN2lX?x8cz z=xyE5`TLAjShQXAM|-*Lc#r<*-fsJ&eY)?DeysJTZ(}F={{Pn>ouuueKiaGN{%9s- z{gmtUoW-&-LGESJI3HwFP)I}P^745PWb4l6Lt57^1U<>^7FHy z{2r%J`S~;PStUQ;7-o-?^wcP=e?9eNmNPnj7-$;A5}QEN_!v!V805p{2m)VMGt-Y?nR_~UFr1yk{eIvu$ZeDr%|Gxj5+D(~x{Va9YPqSq2ZqM+ppWM?wZX5o&Px_Nj|G#5jy{q|t z_SI+L>3?K8qtz%QJ6}<^?{%9#0Vd}4xAFt^YZ8mb-#CdQ1@-@ipFRE|0#)=2K@Ma zp#?r?VEo-D?{%ldzIhY#s8_k&PSdpRM!7C3LsRAo{igEzJ0E73$9azWq*YCH`bxA* z=$vd`Un)L7d18NfIJdcnf=2xL@i5nZ>b*Yc+(GFe?~3-mVxG^t^L)Z5?9Ecx`0t`q z&WYtcv42pwYu@G&pYYklV?#8KWV98p@g^TWJIDFVf4lMKw=9X@yu%US1!w-~eHX8@ zQc8Ww*5{Oaj;z-yuFJjl%`en+J5P6qLp*z}%Xu_uA2-P)veUw)dp?O)v~Tob z>D+$#3{JYom3WcgfhmVyB@G;8RBsu(9`Cf$ap5IxLboToRme*T6|6k+1_jz}a z$KL1pz5U-Sp$g!BR-d(T(;*wxU98=ub#aftw&L`?t+&)Sf&G;3d}xoK{jFpA3T+9! zSZneKVNZp)mwPW;BbMjObf5c3f?eg=JLWF`<)L%aySpc&;63L6U z67MjU&(-H=Hu)+4caVW-0ChUH7B?LaLtxUO(ZNsK2fT-n6H? zap}_32-DJ3Itz$&9^p!1GCcOybNYu%ygwN94;SzK)Z;zfIZJJw-`8ps?_HJGYZBh= zuZn9(zoEG%lyxd-ehcuUI@^OfJF~Q}{pyb1b~;mf2+A+lH?>W{`cJNiqiiE z<(20t3w?O-H7a8;+xIE*`3$^w31KRc#(atYsI0_y;K48DbB{)$z75iR>I^^Wm4tex z7u{oeDbl|G7hVAd-i{I z*D1N3#0gQ2`Y(Vh^dGIWC%T5>T}2=9K3Uqc;oB~zpk0*sJF_3*-jmzKkraEvaQ9ww zSG%|c?H_m(Ubg@*!e`;vp7;!EoG#(BO1|R(?+Bl{AsWa3_&GS@a_A^g&qBkXNW7~Q>WE26Wt z@apU2Nkh`uytOs_{N{Ab{yX0%&ci=E)1he$3yNVN4hlYRg{11L6u zpB*o_?>Sy4h2O7;O_IZ(mF0(|hvNBnQ4di)MZYSZ`9XKQM@6#auFfQQQsce{-j`2^ zCt6T1zu2N_xPO8sjh};YWR{)IzgPy`>E0E7{zV*1i|Wl zKW9I9rZop?ZC9{MC5po{Lv35P(bxjr2~cqx+e7zylZk*%uTpR+0xlqq{3YeeOW~`+5AJsenNfH-}l!4J7YhKX80fbi4W?2>}MJH;m%o|$9_ELsN^vp z&v|xkAA5`;ADQ8Q&S=?N-PYq~f8#EHoZ(I9+urg%vyS5ZkTdIk0_bIhgKCmrXTNGHKH z=Capw%w?`m*eg<4k1?0Mo?|XEe8OLRQ(RBE8*=b^*1_(WF0F%Ac5&YEknUyDk1>YR zjJCgZ=8rp$GlkY(c$|ZJdAc{f9(&V0j`PTyd>m)9=bX$Z)4P_TzkJgfUC{-;^8CQ{ zuF>SY>@jZp(sb`Rf|@toYim4lSqfaTfeWA0kmg<2G4FX-&pAmRF5V|xP#59G`GgDW z9Im@@Y)_en_TPGuv6Og4Xi9~$UyASeGB3YJ+u7(-Uz6VC`ldDh8gDzBJ=@MopRl8( zuov5-r}BDrwe853>Tc>a`b~+B9&?~y%mlcN@bg*4Zzu4L_KAI; z{UyHT?%hqfpGCRtGdk-`SG`Dc+@1D0d7O{_8t^s&k5C~@oSUr|YBk~>9g-=qBJ{FEPj zD3;&DZprZ}^Eby)&waYD=hvqDtab8pj`@Y-*S9BTdz!Q_t}9!hhjsJoxGmsbJ4NB> zS*{mR{~zT#e-~uHL(>D-Tb<6k^^k*Mahfzb&yA0-fX@8+2GK@~T9mOzL+9LH?8Db= zeStE*rieO*v@g*(+94WWpu39bT$fM#*!L(jX*5;>dM#^4KXyNC-H#Pf{H{0Zqtc!S z&R6fd`RctiZ@#(*bZ?eyi}lCdwnZxF?q!d9&h5r`!8bu}zVU49 zH9Rn0<+9s#u6kt4<344bcU;nIvyxq59!&G!&ghKMS;w8xfz&0{jb~lb{oKBFx!R*H z;}qT3CCMV+y7WE!^v9;1Z#ysWsju&jbuG^cCu#$4P7Az^_`M&vMw3?2i%lWBfzCb( ztzl`=G1UKY+p3|xMP0=Ab*Yh0qPXUb;)F?I(}n0|DNjE%L=H>!O5v}dZ$jVY`$**X zyAw2N@e+M9l+wK`u_jCOjG@`UBJnF<>T2wE)C%E$z z6jHdb&UwoEN3NGoQ@w5N2azZ7P!93Y;Bfnx-r?x)vf3#E4h?wv}K5-L37*|EQyj!QOR5bwl`fRX>7MKfH`SbwcNU{Ma;`3Ywj9@$#US$5OrP zX)e{1!t?GKF|J4x?{-G-rb_fk28^2Kt;@RFe?a{oS)Y&|8GFnb9XyTJI33#4p=5SG zCV4!_{^|=fUgGgCE7*P%?-a~-QVINnA~mVIVl-Pes$bkzHjMSpWU3aUGd*QEV-CVk z4yQu6dl2pkSGb^-a)evk&T4mqrW@I$sVZjMvH{;qnW9CG-?922&-?3QVNc{RR?P4C zye9bt6N2KZ~@QFEINXPUk}^K3*?ApTcuu4+)Nmu=;^D@@O@d2?ONE;Or-93Yn+ul* zR|uzryA|#ZxDvQ>xC*#RIJ6bD6|Mnp4IC4YKU^qW1YAG3NVpidVQ^}=k#O;Fsb%Y!R~)4|;ecL!VvTsd3?TqRr$oE5GCZVjAGNF$o;WbA~@gJlQj zrL9$qYqm1LBSKS#V;#HvZ0v`<(}?Dd6!7L6y36~>ZjpZu?MdG#)Kc8}i1Q`BQ+mVK zXdWm7ja7&*ylZGHt0+x<3F#=9qES;aKdpqZWU~E;FDSo^Yfhb-X*|*u`I2~%#>~}7 zhj^6qZVA#+e>gwwEMrqj?&fQi_M^S=`M4e6ujAmaNVJP*fyWL-WMk7RYnuTs6ZvK$ z-`9X+8Q#aT*h}X_wht-8dnM$`c{*n#Gu*y@X=$pSXaJl9&>)=dl|tAH2&-qxrDVgW zGsf2zQ25LWYbx0{be{Y6dxb9z?M_|Ojtqwlcs74DKaBww=%^{pz?J-vhx^Yd#r5lZ zo!tI%)VE~dn{bS=s77C&Wt%b_{%HLhlw%jlI0CfZ2wDe$MjI>2QeQ^CN~Ub2a+RS> zig)AMsO@Y=nHcJVXpOpb(VE>armsMJ@@KZMJq7vDO7DdG1^$g~7Q?W|WL*BThpE`x zgiCW7v*$;!twhhJXsW{(ce8%mxAE`~OYye4%bKh__X$McTt{x@Gc>W1$C7JxQHYd1eV=i;ZUWy(E{ zWvV^j)dlS#p1K{nvmN++%kP_4wyf=^bi^R;>VYBlXDA zj%%d#z@!|(!7cQT?yI@?nmAA0G)Lno0S=du zm!JZ!p=k5KZ+NKk(NetsjNbRtG(<*tzyCyhe;_i_`~62;CX0Ht_!{LM)pE0xmtlg| z(WKQlmU)DkC*zT>al~#EzI<&k=re#d#-g0ZJi=*w!flEX!_l0cfUt)>!cO7&4sMz3 z6X)U}remM4IhBbxv_E7x;x(iEe?;7ep*JolV_IScY8}+KcWxN`_5~%aCsB(1zt?Ri zUrD9=r<9H-@V#t+mdh7R5Pn5waO)nx7a`J*_CekP+Ld_V^lpb|`3ARq zglEFrGcAU+sH_WI@dme?mh!vG*XxM5yxbx3&5Ir0d=ut@??DOQm%72XB1FV@11~RY z)B@+p9<+JVgEp@*kv2Oe+ECb%rEzV9M>E3hL;jI0vXRybF@^19sX}FMLK_tz7l;;+ zefA8M&=zZBU&g7K-GDyYP!IZS_NX(>lY%4Cqb$FW%KLLE4AHR!_s34Z*oKiR@ z)8DXE&F!9;sp365|G4IiKE!P|QD0mw(?YIgL9S&(cf9VBdx{f~gOZKsIqrh86nV+R zvCMG;czWHhG924m1jqI*f&=#4{w9PYd0~T2W6%vG_tlIwuG^C7z*nY(MUOT|=;Sx8UMf-X_LDS#itw=cnyTaSj?3D>O( z<*|}C2d7!TWsZ_>g;pEhm4pYkmTc5OUMP>T2;0dr1=`?LrQ>&?O>?lV_1OW;ZhJh# zaYi8=BN_Y7O(ajETgpinfnSc?q)9uAx=i0Hu1z|EeouOnxUPt7+IJ>^k7g+yM~35l z1grg&iTWfRdiz{|_#v;G`?D#awY?R3iQ2>e+C`o=Bq<%u&{OU0lKclxl}=DPjv_6+ zO6-dh4zP>URJ=_LZuz$y7i9o13^2ShIF0n)IR)~(DDZw8g`+vt4-xhN!t%QN8-@pnfDrx6}>9%VXoIrZac?>F_qZbKhN z)MG;uc1&iDZ#vw%jNXwxJ54yF-5V0XBa}v-NXylzE5e87T4R;5m)JntHU)2UG5r3b zBMR^Z^0)wgitC5EK%4&#>6bu%#=;JvbzlfLAhsW?tq{2FyE$$%cwugdSD%J-3CZsD z)Heg1GKKfmiYPAy`V}RATa=dB5L=uHUL6El?ocQi&vIKAeIL;2KH&c>@TW2lVuKo2 zys{|Gc}-c{#AzLgb{U;OG$l0}qB1t4 zY$PX{gjWe*CmAu8>@-nEIA08X`xB(wvHE##BavNnP^)m+N;K|q3mnN0k`rx^9n??U zpkxkOLviM0sC^&!@#>#L?fYL8?Auw)r5$6KZX4?RQPj151FPKx*{om7YD=N-^;%Yo zzLsvT3jVRI*4BsVLcs_6p{%w9dY)vnzAvk7zKQ8<{WNWlj%4=9uz~a=SnZ?W{lm~p z`qB743g1<>v~lz;h1H(L`->EJBGRWYlfm~Rc^U@{WJ69ze5A$bTRLpbUQ9QP;@-k) zoBGi@KfKQcK7E<)0>0@BM8CcmY2!QDZTcmwRx=Q|Q#o#DwQ(WrW_2%ivkl+%dgP0C z8baaHh1!dh-ixeOL1o`A-fgCT05pgOY-F{e2z!9=dI5d(8}RP;to8!nGxScYsBH?B zXmLoWof{^uDa+6bH)qrLVnrg&uXGlvM;CG~Bz$+Ag zD|jeFsc~db8n-KI(a+WCUscv-3}w3YkS}EW5RGMf@_F#xzz$EFa)@M84sH1oX%8lQ zmZNv;NakvpgJ{Cg&!T?cXZ>l7mT=6rx}@!wB!fa&?R>oBeDFa@ z+a~GVAHWkE@Vx#5L)(TA;sDic_b~B};x|xt!~3$E@4@#C_`dOj(zbgLW+TFE_+WS& zou%B`N5qBN&H4{kwrNy!_nO#FXpJH9;=10DRqgBlrf$z{TuOENYw#z11AjCT@1X4& z_#Jh_TS}!m;$=~>n`4KeU4qZg&hwUW8noM6xSgq4xj=-i#UgavERMk(EAXg4qO(q- z^E%Wa(N_c7&X(v<1wI}Q+T6B`-OS5__OuS=wV_NT7hasVDzzN>Z`d@Vv4r+KGU2|F zME{7x+lCWl>=<0+h|t5^N;a}b=?*xuEy>E!WcSxxluw&`Bk4Oz|CvO72QeOu8${oChV<98&lX*`npt0cE+Y_pBeuMKRG z`@44NtELMX4jMyg`bZo@Y4RFFiE7ya8NM3zSps`cgK%p<>Yc{4vs>5R%^a~Rv5$`a zT5Vh~(~;a~v0AIQL7pd&RZA5HHY+K2}zKG{3XC`X)9 zEXM`dZ&Z#Hl*0ge2#U+keym_=eWdV|-zD&Z9CwSKxbcX49$`L2ypmPPZ8T1Fo0i$P z-zR)|2L3pQQ%AH`ytN1{l<{ZQrrDxrvFJ9h+g7qea1bvLPjupi4Shvk&<=Uqa~xOZ zgR4WCbp4_Ju?39OSdkk#30{N(cz2Zy)U1$!E z#&!#5bN*<`oR_8+*pxq^jAR2fWro|&Ih`liX2Bk}cb0uQ;+(zaoU&ttV3*I%`xIdh zr7Im|Q#U<8{Z-hP$g4@KJ#l#3igM9r%a2dL5nse zOCW#jcVhjs_KaiAeb7f^!lnNywhwt&!KU1kpmi8QpJ%~mPbbk_i-wo?h$1%W0{Gw) z#BXBhXGq@C7*;HJuL=F4AZZOd<@btH(yC z#j}d^Gd6`722l4h%J~G!DW~@caQ+lH%kgR5k{n+yFXcsgh{~+FMtcZEn-t|v@U=-h zR=?~~)-jTN`-`i-_PxmLbUxkJd|ra_{wvir&6S#yoew=I@$~)|``T@sr=xhkKONYjh2KnN7KM;M@eb$%BG2ci-T9%S|D%x;C%|7 zgQYo%f#NtR^}|tCUS_c^r=pJcNn@3&Jr_rZR_)g+?Vn8yt2!GZ?D;$;yy|>k#hx$H zdsTg1tlV=R?YUVyov;6(dbwH_1X>0|MuhBnMmxanxJF|I;v6o~^I2`2ypQ1)lu(eko4ozimtT0!+7mHqpd`Nkg0 z?8|F%*{JN_a9)e-#A|oDcug$ta?-8hUh@5NS+`%4=K{s&W7ov8lRPR-BwC4OxA`f1 zsz=$W+*B?qH_?I0O?04g6CH>Ka`}5IJC&QtOXU_IQ$5Q~8IS^Ui8bkG;+VO9T=+5w-(*f7?< ze?xz}Y;V5TA-C_SmVbQft$#{jONig1TMk3lkS$8OhW6aaaTv;e8M36rM{islJ-do@ z$7d7gRFVGpJY{Yb>5wndbE-u9=x@7ax%z)Kmp%eC&461A+u-bo?Y9wRTgCM*o_2a& zLu|2Q1aolP1GJ<)Uk!{+KA#oSLUFbZXKz1=biVS7^UJQeX*P@%$4c{zzGHlG=zGK!hIJa_ z(@0}{HffA+#w7Px8m%4hocs1nU#+0@hYg6eF+NARiS(g{Q9pbN%^}Ag7T15qY6K2% zLb__ulH{Q}RMchObCy3W{XRXW|HIdQsOc<*ny@a{e#H5#{TTftt^Igs;`Oin@Z{lv z8qLZpQXh$AS6zbklw|iO5DiGDZ<6kqKR=w#Eskp0spS2dgg@iGEmO0S-W|oao#^kd zcI~OB@SgfHJHUg@qs9J=UXld_2^W$FZvOP3|44By5y`z<6UF(0(&3u4b?9H}BUo)1 z>U;gtlGL-Ywjx@a&`W3+sW*Iramvt1YL^Pj(q3j>7%{czmVFgyDnN?^YNrV80v%Qz~Z&1zUDX&YVn+>zl!>Z0*{VB z`Uf@$b{cDH-3huQ|7m15DKxEy5SDBR1`KA&N7svI(v}MSrdkIu`_`jz$7sK@tXrDJ zx=o;b`Z&e0tNqYNCBYhpfozt^%+Z{}9BLKY*EAXRnZo<}$Ee@8UfSPFV^RliWX0!{ zLt9G02Q;62Ryiyo!6}Z@i?kWs(uDRh%1L@~Si%R~Mq&xj{a@ny7HY%7<-1O0j5x9_ zPQ~7)ywJz^jOvm4gZ!Kkl#TTR9i=sFbk+ft+yA`ZtDL?<79_*FiQ=5X~Ja!&>5k=^PJQAE?(Ry)O>oGEh zIm!`t9TV)vHG*R!3$drO8`{!sH?+msV%y>lGd!#K93SOjfNom*l9;|ep0)Dvy>j+t zSTxhg_>*j*y!uSitPI0*I9vo=FSt;+H-p&Q9|y6gZ7BC)rfH?|Fj`Z41m)4vx>_bQ zlHS)sRv(U}elf!{yEG=wwvFJtxOE)fKS~^T6j~lDTKB7`Ea0nUy#Itg=d%9y^0}*v z%HWn)&VsK{)=Jo#)UN5yzVQl{Ok*=a0^9cqWZ*jF(+s)^C?nY*8{i*_GBP|fJcoqR z84t|Ss~=y>dTjE04{-X+8tAWOk6^h1mrnsaG=kn=o1=`2ar8^GD?{|Q<7Z9K7jQBD$ zjQXysM)WODQP`Ie_6bE0!UkQU{nSShPX#%Y8ER{l)5t_0mFl0;`7hZbh<8{K*%*yB z^PD2Ok>+hDqRqzewMsDw|A8HQK2zODZJPCE189D4C*;sXl;!Z!eFq5d{b--mew%2H z7j>M8`dl%9IqK2ZqcLleEi|rKLh@xgbC7+}JXYg4q-Bm$#BWk6(wdOwA(B1m%<l4Y4&r&!c*>xJqf*}MN%wIbGl_Rd}Mtfj&BMrv|fSa;}F!zV3c(bA9J>yd=7dc6_Cr#P?ik3w=&4I zdhqc6qv~Ua6vCwvF2kc*VyPbn`wB*8f~ezcTarPmp}Y)a4-8GX7x>aSD(j&0)x&NW z5PLS3j|&-MZ9LgF5J^u&^K_dy z&4wl{?C`G>1X(Afh&q9RmuY;R#*DchqP!I1xD@3<<>h@QNmm@^YitI!_@DcIwM#ur zbS6D~Rno&mXL)=vO0p9(fb#*+ndp*6Z9>w)8Ns3s=Hs+Mq8{!_2OsWm>)`PcjUQy9 z4yH2_X#VDf8$Ib3!|7He(JizKy2bgS+gZ?!&I}SD4~Nq_h*0VSGsnP&xHez?`lfH6 zq7%)Y^Pri~BG8?69{kDI6^i2nQ%g|(rrs>&J(ML}lHn!JM|DwP^b#;4hN(T$Yyv+o@fHNh7xc*ZrUg^^FCjGgXSq&!T~B zvlXGA!y-vPx0DQrO$6Gg3!^6UK0rJhP%@mg>O$GR2gA`O_!&r1EehDwO^`*l5Vj9# z@$sn+$c&~r&?V90yJr!9WM4&Nwo>ER2%VP|%l3@~EkSR4(CU$GG%kAE2xiwqF7x%X zA&^6GJLYKknl9=elTISNNcbHYB-&Cm2C$^v`Opgpw;$oGAsRIZL|$*xdYFT&)NNO;Irldc?}UiyHw81kMl6z-3wB)}jf2+n z5)Dgu8)Zo)Xrr{h>|^ldj<1~5{!jjc=5~VmO;ym3+SYc?(*yZDIn9kOZ|}S&lVoR8yW38*L8s8%`lHgCoR1-+ zF3=dgRxAtQr-aRa0B!#p(CR9Ur_i_vWK!&~8!WW{%h-q3CfQEz;A0TblMbgYgDD&1 zpcmDkQBy-nTQKzpLn-~>OD`h*7oj&lRwyqiBbjal>W=!;=fTs&S0n=(q`iI7Bx6yw z7eI$h;5ZHVqMR*Jpvf-KCt8|!`4!+Z(4QBSs+Ky?=bUmFjfvZLfew+JPJ?;b4IX6| z*Y*r;xkD=Zt`xESJAfaZb>>t=T`KEv>K*}3p7hwz?$oUarhZdY3!T@d5kjY0fiKC( zBVRgso1!swR#RUeH*{`L{R(b^E=2Z~>hZ_lBOG>4NZ$a`j^Td1w= zhpzY*@k^!nwBBkj-W>o=2OwJ*@dtRC#RGr}4sM7omtxw%GnPgwv)F#D{V`?R9q`f$>Gaak(S0sAPl@en-60Vib$dznu9t?dj}?%|0Irinnx2O|UrK98{K;FdHH_{#Ae#T7^B+{Oz0o&F{#snexMeHo zWq>Y(%soMJlj}pYbCRQ_kOO7mqAXPx&W7E^_SryJW(&6W9*@2}{K6-Y4}+i&K4Fgi zMYA1$M;LjYhQiTY&F~2lp3>Zn$C%;CcX%I5oU0Uo+t;bOauMV*fM1SgQ ze53Z7&Z0Ptb!2zVcyXVCSmy^^wglSz33*(Y)=ZFX(S$r60iB4BL?`tH5f44+ME-#n zQD(>~(qT@>#0$)=PtQo}iw}pf{Ul?EZgkFLD#iP^#_NPyN;nv^S#(`W}5wE=$p7ib1=r=ueW}Ol^n8br&ezxa!8!xpT-1 zy7@5LDAf=3fer^#o7Ai%J!4?~rjq_R33(9Z>gPly{Qg^aUxS{h|9KMcnqZF&;%kF! zMbF?}(`wdw7V?yB9>DJydk!`$;c;jpb5MWk5M}=L6EiFp!^%8Uot4cnRhz7{Sp1lU z%urs=;`4Z*N)%mpJe%JaP6V+-QPifYYM0uCDylYZZKA%m+Iu9n)>f1jMXN^b+B>LG zd(_^<-V&SSm)}467 z?$@pV1#C%5UpC6qGJ54edV?fR6~%w#Iku$=KBYlyZd~!Lc(n^BGkkKRub=zxTSnu! z<6x;}%Z&XOg-6jmk4Czp1s+;Dm)EB<8LvG|1bZjCdn_Jfu?NPjW zme#`Yrl3jY)h}`~eU(`HlJcsIfjDpP0J4OJcT2SYx?5T%{{7f(is^GQG5spE4C_a^73_Z0DABr&Z;N8Edu}{i zlh5a{yGG_2{L={hQ`I|i>|GYpNY~Hu{y1+8i~xIL_czp7fW^JGSUbC&Ls&Sg(L&20 zok@{0#d~8=?`)UeR>Pmw{}m^3Lm`FHq#+GG%5_}|-9bC7s`aYX`|AUaDz2*5Q$(ZOSemST1|zwc2rLY`E}k5BB){2Hxo2rFN9=%nOlxssQV|?t*@yLWUxU%^uvIgscPAx+tUDDcnS1JXxezVq`PG5NW(3 z9AOG*XFHU*^aP@T)hka|5HyGMmx*1iRJi6493TjM`0z*kTwE}yo%Yc5kxRoJ!7*)v z=dmPE0eH#VaR1U0aLfNAfzev03kP6v);woi;68RGxaCv z-BtkGfR|4e^e&&d%^ou#hr)3_NLivby{JVB1nYvw69Btq@+OiEM^hF{&aXJJ>;fAei_9;F7mPD-_D= z^5E7Q$O}k_hz)Ni93`=jG9|+~BAbC_Zneh@U4jufss@$g5uz-J6j+EB+vO(Qg}cA7 zyn+K9b0a6*T)S}37H})B(Vj>I%`r3t7bOe9X(N|`3Pkl_EGPs445B(5Id+W-q{be& z)nqi&92Z^*E;Zir}{b;HFfl=$+|iiVro%5>*Y6ci!^#+m{V#D3%~f)Yic zCD91Mg(sKkz_*~!T}&&6pag;}l5_yh3u#O?cRXaobqiW0?toIbh}`Cdv;vh^=pF*X zT{KPqgk4jy@{_7C-_d4lIMh^ZHAMWGfZXhW83+nf$D0l@)K+|oTxJybz`*fYKA6yl z^En;YLL?G=vTNt2>n0$Rix~|B5lDhU#XcMd2_M@g86DjxbW!;r+w@XLb!BcCCP7V- z3J6_p3z1ZW(Qy6Y?5s#y;(vKWFkW(|j&EVPqcQuCgPM>KJ2e+un?v%h9a|W71|&FQ z0|;|;`n_O`z&uD^8qg1TO5h6s0!dK#zU0pd0^5#8W+qK}D=#L;_P5&iy90oszQg=R zq|}$7anlc&o&b)OR5)tu4`~YT!;aDDkJhD8iv|u)cw$wCmP=9|@f2vj%1Z4c6N~YZ zZpsR~-4_VfOOR-uh<#Wf*e5(?gY2`&Fi-uGH}GY|c5C5lcK0b+tpG2SzgdJCcPuR& zSf_27m6A3T)@V7;FCAnz$u^S) zI{NRE+xvv`TPTX)63ZNM%lX+uZ+A_0{?5Zs~6d@8a&7{4mX%S6(MDUtx*K zH1?r~KGY1ca=SokEnRb5%{CJR~)cGVo zzg$E>@)xD!_Yps%)wG^no++~LxgD>BX}HwQqo2M`pZ0!*TG_DRup#=gccCGn1_kVgo)jOT*{=Ha69)``0MnpHZvs@D3wI*xsP zjO$;1TJh9R{mihSdF0*yXRq3ja{dFMy`JM$DirZLru!B-PrANo{rD%fHhH8zJ0p+uY z6*VEXGh!CGneqy0g2Q6=R<4Yv_e)gL`pn}{Ts*-NY$0%~$9{fE+kAWN$kMi^% z{BHlFocLDbDC5uJwEs4H2H^;Vf=8PIZHt(Jr7taJ9nGo?PQ8=5g9=`>JAO@%MMbzHdyU{C*JUX+CGe!A<%~+52d+nP=Ai zM0;PeTf)4%UMMvB49Qpko2?luLV&+N`lb;Nvq)c&i=D!noRXDnqa^AZ?7qj;WaJpg zL6r-$=Rvb%NWOQ3{h`J^pPy>*4gCE&_^7W76<~zVG5+PUR@9{D?M(DM?w7$trLz=& ziAY6J0xx&loURQ^Z}0wI&&aRp-94?1^?&QMy}$|GKMLiZ z&}<+28wzK7mLi^%ge>^|&WAT}Tp9P`PZeC$y62B3LlH#UoN?Gz(RHC~ir@8RoBL}* z_`7#z{f~^~pIAMw$ZrD`s_JA)yk|5Zx}Z!XIbiO%K0lC!DK0C3h^sgym!u-j65?WF z_UYw)56yZuW9VqXr)S2qb72CQ)R=0qm>SQs>aotC%Xwb>;r+vKzkHta))>7#C~67dX^s}`m{mYH>;+<(_%)6SDQ9l zBV$7ce0E2=i>L$E%H9PPC01SUK%#>J0+qwm&JB9Hy{2Rp3oG@p5uy~Y$%PhzSbc5N z{IfS2iz+5bmKl14dZa1Jwr|EYu<)Q>t__7(QwI7u{p)IiL;}e@w_o!Q{~D)Z>ZOlrIM+;)-NrooE*gdM*L9lv?JbH~AFQNvuwfo)G8)sX5|fZ5Hq zGiHj4MxQ`H!Ui@cH=b+2* zo%O8+9PYE^{by)!jDC+?oeJ%MMsmNJ*x$Z0Q_I)<2g#Se6hFrEOu0;M(L0_IsboiJ z`;NH`^AlcG+l@>y+_!P^jB!wG?(K8A#WaNx$osLp3fr&UQw+J*T(e8GFyPq0ILThe zj{W$;p|(4#dCc&eS**j-4QkS3St(ST#WJJe?L8^fN-#uRd)nmmdGQM$wv#a9b)w47 zu;vLvL1s|%Qv=O6Q9L~#pG|7aT%J^C)WW~G+uYJ|pS8%{PB_{3BXx@zmU+B!?g3iC z&zjz!z18i#dAoyo7o{m=4wXAevVn$T(thoO8nbNyB9@P>S9yo=V1mnPN z^4Bk$BTeKbmd-`hTwxK!@m$_$;JZztt{L-96?nFm&=f5qYoOHBS z{*nx_6T9!x<@Px~XKdoxcP-Aurv6dS+o|P?Z!p6X#4j&2EiX+OGsVw>jgKD<&aRut z4CpN}KPBG?OW55Iz6@<2*EO7e|KY2?a(2}owF8Ng!Nc*jrwFT0E0%GaN-vINlI)(_ z2B(eHT4<3S9I1U1KGt@4I#Rx%Yg1ZKYs}^#U>A8gU_Si&moaCf*)6{fz9eYFZ^Vi9 zFsyv~_Cx!^)3+UDC+Vgg6s6RNM&h@<|1b2G{=e|n_8q?Uv#Ou}FK8I^@c*%N;VJol zUD-Rz|JPAE|G)0=Ra6V#jiasY{~K2epk4?u;O{3T0$^YBU$nyg({gmp z5*jnv5dzOr_wHKOI+NVldmH8&o(pT|{C?;3RrYz+Gxy)V_b&Ifb7#Ja|8?amkL%~S zUC@arEzTNu%ZrbGZK(L4(UbyStLo_+dp-cA+$BPSw3q}S?;i9c&|=I$L1xuJK& z5pvJIe)fwIP1H^LWfOJHL;toWUU1y?$8mCHbj@hQsqK&Wd&Z}XB$WBEb40USH#f{d4m4Dxg^@a|&5tNv_gSuSQrVpr z&eQpHl+N^Z|A;T^)TwxLI`V?`W|n+Mc%|?Ywzcws&~l%Ai)EXLBTJj*p7gRQd}#q~y$c#S_e(DkxC|w4_TfL;*ttu_AuRmcPpgl< z=tIw+^{Nyb3AFOP_*y5V(GZF-9=!kfOwQstq-OhCEvqNHDC>KWaLDNUMcsY!JmrS5 zqx4?AbX-U#1M2F$;>krRJ}WeL_0o|lpv7RnHRk^Dho&KvQxgha5ca@;F+JF9|lFW6as#dqQQNJ`Za@k{9`T4VE z@LSzReXI=|RuR#@@RP1Yz#Em6F?^7Xhy-8+)<-Zwfp&mgR9Ut1!pT|-HJG4~Tf zna%}~+ipqff)nZH?f065T-gYObxG|MYpL@q?_9iJjo>mr^~DZt;2bnZio~D9(qV8n zx8F8TOp%gtcV@E_u2Ih;$mz1%TTA_PluF!Xapk%nM3j$%0^7fP_Su>+@bABE18iaM z3M-8pO?a?}9#=BBZ-%3Y9vK8MJOZ;TEArsm=m+@soZ^-Ef9qQk1zV;sU}6H2!eUPe z*2pAlov%;JsUa`!MCy=9wxtDUk^vKIEOokt>&r}%f-v7pxv>|ym%j#E7GR=GzsmHd z!Sb2cyEcv`OnLsjPI715{FD3wQ4i)^td-ISUkj?7lPSptk48T$yLW;i!-uxm+86$- zn&Qrq4d*!{CimV?f(o*%aW0mKm-YO5P~8nP=HoUox2ydZYh&r+-OK3uiw$BBGbm(R zRR7huv8wdbs|O>W|A}(cbwv>7^3Fj?h&(^YP(I6zavsW) z)7PD=>YBJGPy0wS#Ik0o&%jEw0(Mp$5FFfEywEbUyK33}b~NU3Yg(FizwOVDvo&8x zGd|8|2^hw%?dJUY8)u?mxm7GWqXS7X zIhZs;(Op^^lO}ApLH=cIFpg-@XyCJvv5ja+&F?3)CH+=!wslcej@)9IUm8D5zW)7H z&bIj7=c_^eUV(1S__Zo`M+wy-+t7f4*$h9Qn~{H|!=E6%7|&C(r(&m=>!ACtig)Fu zPp7Bdd)6{zdn!FJsz_1dl39-lEtiUU$%zf`o6)rN)^)SCW^)Da#$*YzMXcC#CgHMc z`PN659N9bBMTNxu#U*1li}VrhW~RdE^K_}|pnHIj-=9e9EnWv94H2Qm*&<2`QVUOpY@+S5aQIlSnK4!3r(+x_A= ztZ0ADZ&VvPnK4u2Q2r^TaC{8bQ&i|*$5TvH{AIy@t-Cx`Jk_SIPrgK^M$P>Mwk0W6 zBt3Rb+`?d*)eZYSbuwL@e^E}@UB7Gm?Qh1PGVjHLb=Iz+MNv(l>PhDZ|Bap&gLm~m zmZjot9A*jlO?Cf%wyP%k=`21CS?71Ct;zEcXEwLgqO8e^FBgBE_L+Ico=em+k}r~` z3iGf$OBNv#sL*gKRJZxjHRIYR{az<1y+N~e!Hkr~#Nj_((NqtnrNxN$%oz`{rq-Xf z)zSGsHmb^_Ux^(>1jv1?xNrECGRYQW=2ET(hcRIjUOfEMUfi!M{ml5>za=XR6(F5P zlg7)d^e~0j{TE7|$jgCxoY(r#?>EXE(?;rH8aE2e8DCZ5WB9X7{~6n+-?K6%5^y3K zaD)-fmZ#ry?G^Lf8UOttmdWvnll1x?dU7DX26N{lo$QnKO+Kl_^$IiZN3whmGo+ zZ-Pwuku}QF)cr#ehM&P10s8uREk})`x^)y)6hS#|inl3$Gi`G>GG3ERO#GvU9sk?o z(0lT}2tpVCUs+>7<5(v-)8kF!g=5l&PM0Wp7ZYc)28W-vd5z#Xij;**hL^hvqr^~^ zcSh0{9PZ>1=1E)0$hzi_t2fs#e(8f zQo~&svTbPWBmO)uIzTeX^DH-T!G`BdkttgMMI19F0bfk;_FYw^W=a676>TA%zAv7b?>(V&gr(uJxR3=%OSVim zD|h;fiVX{_B|m@vm2xrDqp-)>y3w(qp{IJoPe&cS&bSCvTt4Mnm{S_W8NJ-ILDA?= zQwtFq{j8Ep_(*K#KMiDzeP>0ZCwi%O#;Q1AR52Dux{%V;!_04ITNk$2 zJym@(Yh4<7_mLG=QJt`N8Jrm0DO5#GZ*aU(A7lEue!)XS#GojwOJ6_WOnYY@0ejs~ zsjT{P><>;wov4?^qn(>wQ^eAAz%P#*FxGvU_lr};WloH1XofYORcCPbpVo}IuIL} z<$mH8?Mtx8mH7(j@=$sO=*NUd%n}-J{JpKBbWwZ5_XorOAx(kaA-%w|kO$yhkQ@7o z0`k&TNrwy%#}y#*17Yfx>>n^bSPEj9O}Gr9)JBnC(yeHOJS*+G@+UASnOKcu)Yy{t zmQo{dxhIol9KuY`I(%B?)utVdSMfqF)s_(QIezpIu&)%9(3zlxpn*Z;9m_F*g;YwC za0g&Py65(mz-51O6%S|h5ovi4o~2bY6y^|+;gMK4DkRB1L8g$xa|Ti;uYnPT9QClq^X*(lqEq6OQHt| zu5kb45kUgzTS$eLA{?(=NrE==OU4xyWN-)#t!x%P1p|nO6VMqv2#U)hY5A5xeZQ=}Y19>Iu zF%NQ7e3ZTNJ=JzPA$DZP?GcDAC;Aq6)Te?C;fYn0M51JqT<@8qB5xmsvjfx!;O_vf zKuMuPHxr=sXMpA0=DX(#A&y80a31dn=+AgTFTrjscp3Lsl#m`s_kj>$nBz~szM@*P z6QCu5GkD*SvPma&L6n=V!z7g!zZl#UCVf+uL#6`~L36t_kR(C1mSQA>2>Edr{ReQ7 zlVVG;m#Fv}Fu^SH8faGiz^@<|3+x5Y-Te1Iv6`*4LDyjXigK+*7zuGX*kb5r~$sTbO+Bfoy-^ zl-p)jm8x9JNusK>yN6ZUOH4|15>*J*9=##B4J%Jyfp}#-M*zV1;gSv~EjrX3?NL+J zgrjqrS)k#kU=UPUYE(4dE%(Ck7)-3B!Mbb1wga-xO)pAfNSojOrrWaTkSS~ltc&;!ntAJzYXUM zd_bSooDY8ZtYr_)WpxIa=Rz`E{#jMv-}2!&B&mLsn2v2>qtFoL6zA}CUkk9!WI zUfknEb4cS+(nm@VDYcUjG>mtq9e5UgoC2ep=ItOXH+a}vyZY)Mvps>GB6-Gl*99g1 z{ZbgEJxI%ROjwcGh+L-Q(Rc6$`885>6rZcd2w*@`GZv{dhRDN6d^}gA%K6K~EGzG^ zLEwB9+^47@J_Gu$e>fLj|5iDWyHokm?0Z)*D>+rX_3fc<>JZ5W`B zsKUEe=orBUD{@BOVrz{=cQjsM?{gU_!jycjAsYOnBh7${>#eeXdk{|upti`uoK>Cl4F}Fu!DmU)U`sw z*qlA3)W;yDbrPx`1JPWF_WL>t0et|M0$X#p;D11Mp`U&JFub^S%f6);Cn8SZ$XP)e zCb!FqeCyE_%H7+0%;0uwT%+T5FD?u}ea(=R6>%w$1XXU<;R~!H^9+TI5)^MMBp~CG z83oQFwua3wce0Of+=Bl^@10noz!X^SxdC&=LM+o25VWjx)j2F5<>z)lqzn^dB)VG> zF}gFav8=qW87Ab$i2t*j&_0lD=az1lwG>F3%TR-WoP+~MQOdy~qGr+Xgxi%Ss|P!T z=GDg#s&6XNVJYqSE7|R8(wFuY_f_^5AM^fr+=N`Zr-uoLr#z18Sk>2KdGz_?yIYsJ zkq__g)s#}J4DgQTD9JL4#eQdI0R-pT{e0~6DX8|bsyY=__=FQRL<;n%eBV{$z=d;_*F!SdK8_+`gdBt zZxhbrUFb|9AEFsT<92-aU5cz}ipw0vYVW9Y7X;WLa8hKDqPRvLgH=Qci4_E5!gITX zVp3qNQlKU!$?-1>Azmv@tFQEG{tpdp5nw=vg9xB*8V@1rxX^-aJ$fnVO(VzMz`O7|BApG76ggk>Pu&bD>B24t)kA+Xt4t?*kiwBo@O02yc|wrO1huddogQyuw7?kg=ygaL2># zM#`PpSPy~&nAkSKmLj|T%tt>(T1Min4m~$uTuLzQ?oP^fbS@3Ny>$K_TBHB0yXCVL*Bgf4H-*B5g%T>p}|v@n{nETz8fo zu<`}B9DWvxTM7|iC%ga(&5-pKxeP+Viyy2qeLcidQ^C6VQ*lJ`$XW5$5K@1 zL1bqjRV3YCr9FijyGmjf;>DY7tneJv@7_Kk1Cqp^>bqGVRUH2Ia&O-currr({HPMK0683f@<*Vg{WkZYt>C2JO;ERv~`Tr+er_Y7Dn zh6fixK!>OZU`iq3l!!GaT7Em2Y~zBXzZiTHJ|(P7H5_^vt!o**!mb&*zT!-HwTry; zX50Z4c5uvi(Va$*wFOv#C0N4S)sjZ+lD?^pB`7g$%i)({1rbtJB?I1Z(m7m)W2iiB`=ky-T{=RX$?`Fs4^;FX7r1iaUJLa;N#WO(KM8ilCaV9*tK3wdlUe$)kJ zyk@?}GJVV-LY5FtDne8T$y@f$%MM|415n(gz3QRV3zThW&{nZ|Jsdf2+5xR83QI1-lNB=W zq)nDg-S-#lN_&MrytQ5LL=?~KzkAJO`EL+obvs>^Qc+m_l#dlX3UL|-Aq3d}W9UVg z*BAbI!6ti}-ia74NM(FI^A}vF+c-m5qqAM|Sz$gIrQH|EQD1~&>r+lL^+ctzK~d&O z7fHyH95xwd#C@OF<;00k<@4F|(Ws-BAL$D7LU%lGb)LJnDQA{5^%?xa=(F(kZ9Q&% zj`jG>Jk~~CVQBtM04|B4_bqsl(qEC-25VI2E4&O#8hOq(`j{ab)jp%lm`Swu27cMR{V9n zPnI($a-sB-8b{7r-_HIWX+jXoDNUMLKNJN@l1x#Yw8*~|!@(0Q`k_LOhi`i{?v_X! zDNl(5>`h*@Uvw?)=zR2+Iin6+%2Z7 zTTFkJUuk-30J_7-^SOUcp?bmq!GJCb{!o*C_3G#0HP5cp>40ZVCwT615;rfkZeK`S zs(fl6)1PbSYQ+qF7e>e@wLjcf4o#IBIgq4}#g;OTFkk%q9lB(%jp$Acx$!(I6> zvPHEJek)*BmY_fw+^aBr8RoCr552$268kbEY(%^S{FrDv`n zfOX$CP?AV+$B2#A%O~Bl&N}63C5=+wcJjKN&$ILs;Yry3bJPP3U|SoizweI?Uz$k1 zCmX+enLd{-j_WAL(MSlptuf_$J%^fqH&`Z?z;y|oGxm^kwwsgr(3@x2ozCdB&KZ7B zV4JQBWI(Yd?$rmflW+YS^L@UoairyjK}nL`ZLjyA7=FcZut&5Q3NQASo?b#^=V=)W z={FoK;&_Q#nFBmSPmpb7xX2oG1NmtTH5BfEjc$|3KY%Lrv2q>+JRH0g-()J}yA|1& z%hC8K@#a#!kD1ezKPkt5<}65o=j~=hdJk^$x7@Fy#GgJEpw^AQsWat2E=miw;+$Dl zG1UM}74K}&VDXU%MohnDZ&GrT$P_6p_p?3slK ztnv-TT=@37;$vqf=DdGHPCE)`1D@4mIoVfdqB+^a7xF&!{vV5KoH>DC%a~^p`?;z7 zHy8}QdljV~wiq?qyP7E9yhsgnunKgzjlTP9%~$o~#TPaRDnX$}Ly7OAB5$jr)O-Vv zYj)|pQdft&UexX_)u(0J(z}hmUd{?EnUmo@?-}kH=Jx(N-_PiYCH>LFbN-uTaa{Tj zw(D7ihrDeM`t0yHk?%1T4$Sqv^M0jC+V2MMD{1?Dui3jZGWRH|E$;=B5ZP6q8o1r7o;v|8 z3cj-1Vng0)>}?dBZptkh{7yu|QKpra#xoYb5Hr(3YO*d5GlJp_;NzE&yN4JtRIllh zUmv3=tB~wFg{EKA9;LTmV%E1*%Tn27qlOQUtlILbHOMiL)4j;M1@de3JL>Cy zKkTHgqUD037ME8sVo(g3J zC@y<{t`*j9r&vc=+tnU$5MT8fPr<#WyvMI0KCAz|${Mg%+sTN|zR-Gu8#u9(XTSL= zISZE^xt=4E#hKpv<)1+?tfP{fS$r?fXd{B`srG~oRUSUx z=#8oQ&c?Thk&k9QZ9MJV`Mim{(6@XQyGV4%?`O5uCL$O>7RR1l=~SXQfR5T#ko+l3 zc1MRP;F^$BU;c8dV#3Dj)dP+3W%JQuDC~anD}-yx^ZX(Y7c3`u!93jbq0Rb4k^Qj< z)u^wK{NDJxc6Dg*e+;47SEn^W?S@-eh1vK{A(G}!F>84Z_TXJtEgNqRo5)p0*)L(rhtfOqS}& z;*)Jypkf$$^05uPTf9-IF^5}0SdRw&+j$2!8|8H}Zrv*8h3>O3PkaxZ7xJ8fN(3N8 z1S=qZd+giHx#^pYau<7Rm6@J=d!ci9f+w}u1|6;qgkb+kllYyw^I^+wm;&%lGt}qR zvhvx~&+bS$AAPLV^xK@z7t<{_IhbI2jCH_OZv$5u4mMrGCkX9*yov1viwL`D$7(%a z^+=wB23KroJDm@(^|iVT`PF&h$gkbE{coP*S8Z&*skCtNdx}%izHt8>&(}h=h#Av5 z*uvn%QvMlq-ErIV*7{W&u;r~mw$)B%`xv8c~9ed@vgbJa9$&Y ze9x}2H>EUFd-O7vN-N0YYTVbwToOHBQiBbJU)vru*!+6lsH~9WxvbiR1N)=P9!JX^ zXg$DL8SV%=GjKpF_l71Q`8Sr8CC!3mjYsk%jiA#Lf^`!XpA^}NUt9DVH%I>4clCuT zzNGEhCeROOf3qF@*?*W!Ym7j5WEHl9RWQOkSoUCEzjP0|Pv3B&jqS)=`Wp^;Lv8*; z&sS)6)EnQzZlh4|9*X_%ImnjG%$zK^+A{Z?kHb7saE|?K+Ei(Jc9P-q!?!m2|8T0=_CXZpT;aY47G6)H9Gj3c;Y6n zt&Gd-Dnf&RCnZPeO`JNl_6Na9BkrgU$iVXZ;ti|5La9?mREpr7yCdCc)o1Ywc&Qf- zbltz`aOmmofVI2M<+{~}R^=UonrEAGe)uXax9|!=A%j6e@szT}j`2w7NQLwS~ zHY=b`d3m%X0imw5e9#jxv2gJz|7Ljm-=Z2+e_` zjmjKxoL&=$FosPdYg~PK-F>d21{c1B8DW$h?B3`~_&AEr@`1Z49R_I2Lj5>hSNcFn zfzqecs38`Ax>JCf0);m)-D)Q_Zj>5~cHjW;ZT*TXGQ)~?r#Jv*WYK`u9p z!Qjp*O8;+#%~q1qpQl=cQQ>kO$rBg*>Irfb{*G~CxUq|4Ylk6pi(Vf?&kUSP5|?D! zRX#&?)y!tB~+TKvymClb{dly&9eluOOJ=6#l9>TFlA1=?{4l_ZsM=!Kt@_H!v zEaYbPsPNfEh3rmC1pdp2ELW1wbC=b&t(qEFmdM4?hpz2qSrA*8;T1RbR$vIXr?|~b zcV+$+dNA6YS5ZYbT!DA(;Kcz4cYWSAj_hSXusIF7ss?k9s`pSQ!s%H6Hg!#Pi zMApS*+C}f?U!3qPR?BW#WhWoa^UJmh`uMc<0c3y3HNV?0^u|hQhBC)yBgL*=XUkBW zXQF8&SuGFpa8|01FY;{RGvRzE-kWPE?f|J_aTMEKBM?@HF5j9syKnlu|+oHwLvN>R0S{jumxXAu_jVU9l1z(Q@z5UiZh-*=r^7yts5o}~Sb%@xR zAA`F*a=M@omJML%`%)|Wr#@vDA-`Gt&{Q&))n-GePf-1Rqd%uk_T-W)q%?iL#GqFv zV^~Qqt>hohSjr*it1AxDocxe^%Sh(u3B=LUzE+B*1m%Hp@T~YBlq0`0t)Jx*l^!CD#1px9o6z z${`~6<%7-fg$srJt@hDG#iMc3WzyiFgk|>p6UenOYpXa`Dd(#}IeY#cJ8HOoHds)* z1wA^wz5VkJlHG-_JHK+HM77mRU$k?$!c8+1=(s2c|6Z^TUi@xv)j}toB&j>%GDdi- zug%j-cHbA9_fjK>){aKdOKCOOaPtcUSFp;Gp?ZfxLoS>x8GXC=YUUQWr>tbE{hF6F zzny7yN0trkxo4w70}ub;%b7OSwl$2Q*>)0hW*=xw)Y)Ps5}Ui5c!)Cpt}i5Sspvmg zh`LeRRGTj8_b*0JbPmV+?Z`8u;cfV5tI2l@_oUI5f~~%JX%meaX)OM{*}V@Px9&(# zo=jM@?am!^dkek2J}QhF8&S^b|50xdiTijRu=U2H=?r7BJ>-w^N=W5NR3HdeVUy36 zwV52#*vlzFoxVLnrwC+iUX7?qL%*Jls5WMKt|yy_s?+;f|df%sT}!j z8SicHpbAeE8BrJjHGlgZw;R~`GvEihS$|Y=uLa5wwPZ8=q1I8JA0l%!(EOBpIq@$a zuMCbK=>H}mt4CZ0;!J$H+H$k{bL+L2h0*-ixZCWv+P7YCqxx4uLnBEL#bMTT&m2To z`EFL+?d_wHKt8LPH*f!YVVJyJJtl2)?kRS9H!6pFby(wI5yxqf+O&Y#{K5CnN{LE5-2Z9pYABd@&zrGu*ybQ|nd--^_{*#4JL+4fLxcryeYja;Dne%YP)-~1 z;rGR|y6aHip1?3V)oOc4B2EpX&~_MLy%YR_X~r;EoEwVkzrfnD&i#G1jZj(GO1_5f zD@)q`DVE!NT8!%&ZhXeQtTW)r{$+S8GsN6?_)cmED~zh07yEkUKzHhxkTrZ(g6d02 z%B**qC(Xu5whMOMm22$cMw{zB@e5qSK^7L$n7z&m@b5m4JC_~Wzk~$yV$>7x+`yxf z`+fH3yZRkR!V)vNRob#|JRjr}=vQx8=)Bp!a1Ms?x-;%1c2N zbqhPU-J84_IdV7V(0%>NOv{dH)31e{UKZ;Ny5(Ol^i$7XZb`olqFGmKv}o)5>Z7NhlE zN(MJh>90Af%`l?;@i`P2OuH2bm=u3Z;AC38xGx=y{rTA)0nmp*|BIWQbTOL>mW>IQ0h0R7~EqNZgHIm7T;L1~W2X z&eLmFTf7wbQ7soRJ~QfTA?*ecRH)o4ah{G_XS}jPGA~OuvuWU~OjjATDfd^*?AiQI z;bu21S_vbhcL3fj@M$04ox3C;__#*GjO5g|&p>AN-DtDLR1|Y$%Y)Mf{AAT6-Bsry zTbwx|LBIRpR?9J>0(oagVJ)J0P>bu_9BunMFlSE0f+@;#mvMg!KKvJoBJJ}(iq*J^ zUXm`Ol!W-xqZG0|ssoZrE#1x$NxX=>p~QJ*1ViXSdd%Yyj{QK(jT%Isa>b?tZgj-+ z|D(S9Wy@xc2l|cWdK@lEvhDM#!dCh$&OLv(Mkr8Jrgkvk=F+uKo0^>*$5MfwiqK9Q)So zYbf^9Zml-vgbo0i87p0W20J>sS zJB(g9RaN!WR^q+d=;KZTOL@q&%Unm*-S%=GMadcccQw)lKNYaMn|`@G``cr!43}G> z<+w#7iAs2AhmBtN{O@QaJ081s$qerX1%ecl7mwnfeBK+Q|Ki;`qf=geR zQh6l=Lr}ZtD-kWR+!u;V7F>?s!f!ZT!&~(2TIs{uX7kTN0@N7!C%nE{Ko#!0hpfK+1N~|Hb{3cH>%Bew*!F5?BoaqPx{uicZxx^5Mwvm$mJ^uA#wt|c!Jvo#{Y$jK49k| zAEFRtv4{F&fU*7ifxp|;cFiZ7O7o0?&{#Eu5m+`?CqeY1CquN zEsDgu8|8ypAWpYT6~z^L7gh+lq)vlNV)K8@Z4Icapph>(r&_Bz+bhRItd&XW4QFaz zd)qxl+&t79fLYk3#?KyT``#$z2~}1N-w>jz2KMjh1l%v60|7Ye1uDZ%!arR!Zbzmp zDikvMY1M)U-KNtUnl=}8@VkMdd;Lc(E+vfv{7hTpicq|POjNfx52 zzUtG;gwvt?zuSQnCmnQV;*qwh%(+jcPwM5;szg?1FW=kjTA49vCPfZE^gi)v=v>*f zDgsRX@?gNTZ{3+Z|mfx3qu zQ#j$&|9ciS9A7Tuv}YdbG9w`vpOG&}Z}4`E-}9EUNNI|o-M$YgEd|L~l@mE+9JHJW z{R`525`DgWA*Iu!baB(RpwHhsKghPGvIZkM5lplz^kr-(Ps#d>yymTLxVOZ0QaKo*-BzD3X~ z6Q>3DhuaK=wzy6}?cl`ms@LSXKZNv7iSBPHTNlOQ1CDFQ{A&Z6-9`DHYn{_)nuliM zjn$zyh5(TP@?P==p+$^5x)e#3@WWfbmfQyVZV+m)b-uTB!+-b9Vzh4azE41mM!moN zGbOyob8R4|dlGi51NhK{c{n@o*FoI|OA?gjM8+kLXl4)x;N?0~3qr+opLwaok=_Pu z_lIRRymCvjv*D~2Y6QuGf|mPcla3u%^cC$7gS!IORaN+d6Z!@izGu)={#@|Cea1|? zfH5)#R_81Dlp9n^IE?rwO{Lx2r9KUqvQY|}JI~^mIT2@CD(V69%baffnu_E~OkBMn z{Sq#e)=ErtBVm74mi+41PDuUNNr`S;0REMej$cYAzXoD>OyjbJ z_DJ!+YygS!==@(B2|SZr$vzMi4qwYQ{OI@gP-F7STb%Hc;dbu3ltaFyu}A&>{hJyM zGo}K`Q!;uQ_OFGu;XCXFb$KZMjc@Q58i(8;W96-cTrWC41Z|+gBd0PRhEG+XXkeuF zlW*g!nhJ0xjiwH6A73^u=#)`ws0H833ESGS{dZMPY0g9O^XTsH{o>scj%xuLU&*f> z@EcQsaZj_X%3-ZP#`MMZ+Mi^+PZm#ppX`)8HtO}JDn&0nW1_84|0##A0RK#)hK6LJ zuFUM_^Ta9j9gY5jGnrS0_w?)Uu)ILHSL%@gi>ol)8B#i7`m*kjmWfs+A5-oD-V?{fSniMKW6ZNu(sr@dM)d{_O3 zvu-v83rmrpOi;}h#ndC?tp=7vbSr@cp*))kKXy8?LTAtcZf4;)z0uHQ#0tg;)gDVq5eV1Ac0ZKl>l zFk7@%g&nWlLS*VOWXzR!7<9zl?r|%>C3i`Dxt};H{CCY9`>83-XDktQmEDk=Ye6q@ zDo9bScUBEq zW1wo-%3%DotP1FKWbRphkT$hZ0^+`#M0iARw=7 zkL{z5&*@Oq(^hixxAnXLu9nc#0+X0!!1mp zF0vn&Yoi-D-(KVuW%u24qgi_@v-dL@surL4i2u)Xe&L1csZhyqZ`s7XALkuD?}7kGD7-t@cq8APud9_8K2jHCUdxOG<&tE}Wx*`OrxzKuC$QiiqYlq)jy z+WAH;LL|3p{jZE}s7YM;YDnzZ4U0fh?&-iIo8jTJ(pg~@grL#L^D@iVm4aF`Z^p8b z9O>~htcudGiGx}IArA^0HQIf9nX zN5ihlGMe^{zNq%?H}8I%)Ag=Z4QxZE_>~ z5;}sW=kDR^b-jOlbhKA(gOKkaU9N77@&-fgXlH_LdkA3fk&)Kv6H-N+ef}!%o2uop){xh6OPXPbQKzXW> z&DWHvCuJo`+X>Eexdtb{%D=aa{j3ESPHRDqug{l0lULhV^^@B6v6=>}=j`a@Xo9Xb$33s3BfTzsXVxGA& z_4*P%5PiPj19-bXOCVC8qt4jI`r!=aaF?bv`0b|8_Tkw z?B)9|n>PBW8=j+?b)qD zvL=Zzac35+D5n*Xq3;)BpxkzO^n$1FUf*?_!S;95`6(wleOLRKSrE3w82^u}BNw6@ zbF9$r=Jh7=xeh_}&AyJ*&#ji@PcT2d|a>7kn)fF%)Y z6kS8HSsy14`5e?4?qgCZw}O>82?xK;%R{BIf(_0eR-VD!D7dFcBn9if{>dyqA(oeQ zgIdFNbdZgo_Nv3;uhbvSAwMF4MVnk^Fz(P_QSqbJYAe0W?UaP%47%P z$BP-kQkkZ_nH24Jsu}M?ID`}_%=7qNw0IQf0IbvF^F^liU^$6hFp8Q|@58`!Tz6dX z4!I%D2+e~v$8o8ulD&*3ZcFPt&J-SCkjC!;QL;Wb><-QV_RHTdj;q>l+^B#4&#o1_ zExV0N>$_E`7WtJi1+JhSc*zd)zFYi-?M-TwPOfb%LbL=!xhjZ&;e0&FkroEHV1pzC zD2bfzL-c*HhbkBXZ%P)z=bbg6PdK1;BZwq|7q<{yLknnR$RQB#P^ms?{nbGrkmagVeqM4K%6;bmW~LU15#2*JaA zOls)R&4h1XBil*wkya`;+)LGJ=U?U6Nw z;FcxJMq{J{E=TtBa-{H?6KT@|cnLCzoF|?7fPB;a1736Y!Wkd<^AH_J#IbcM?Nwc_ z@yLQx2(_!wJN^PB*MBDM3m%a-2Q0_iN19IL= zXl~o-&iI-ho)8fSKYB`%3B{3QP=@%jfU5ruaj}i|VyO_*q}&f)DpSTU8CbTv>EMGu z^dl~vqYIeO)Q_)dKoS2==8jE%9(wyjpbEi>WQ)oFef~f;k!*+3!JCp4vvBT3FQJ3M zrvx;j4Ab94=J_%V^UTSdP67P914ojC>h1w5 zH{2W5pk(b!=v1A8&LLSiR7x+-l#0W z2y_jwGY;GPF@?~SB^O8n>0qmO0~reoZG34LJ|hco)S;X70NN7vJLle zoHvKzIrZqpAf}5u1Ztp~L^io(Q;NOkmLo77E^n_-#`_S@#G!Sn=$)!O&@6A<3EEz< z5+hx>F-~N|EqckrfxOeac_Gk2#X=yO+IJg{c+djf9R_F5@FtR_N{O}z#x(eJPV?CB z%Hbnjiz zQ!wQAW@@7sg_bS&^4Q$A8JF{Vw*b_t|3jZRm|fEtcJfB0-{SQXlq|OdVfA!kS{zhL z4E>W+Px!*OV_##o;L8!C{c&!=XS4>n8FPAunm=>0l_W1f?%QFWtYB0`@EP?nyFeGo^3D zmz|@^WIb?^f{&NI7kUkXuL%>5DuSxd{&aPGFl!jAscbB56=rb(HlIvsnr^bpuCzfZ z9iL~v5V&4e7yGVcld#}N%Wz_<-Kj&DP zS2s{mfYk`ZeHXEEXV)d)@z2QwQ~w4WgOK@?yvrdr_#HU9G9116b*(~3XW?`S>An(W zbhOasj;c(iqBh}F3A)SG^7^0dy2%lujr!z(VMw5-b%mPY(eH9paSlZoxVSU9>T;qz z`Y5Ts>|kc8n1OY(!&b`3kCL`kV8ANU1{=1RRzx+;X9yqh0zP=Hhd?e4s?xWfuqn2| z%r_0w68nB-9xsFzeHpAwVn5n!g(GZ!3_lA7zV4`W z0O!ARkBD|HJtmc+1=5?6S-hb8=S}euU>A7tJDQ`jW0F0Tp|qP?QNQ%RcZE|Hhrj|F zM1XHe*d14mU|*6#1r37GpnD^K=)jqXWlJQ@;ap0>Is}4!17y9i>^)PYtOHWvKJ-V4 z2%s+7Mu@a(-SkS6*M{D_5@l?|S9R-OJL+%@JVbIQ~D{yEt0gxmej~yjK_Tc0cHVhRmQT6pFlkj6s=U z#iQqCk)n%Ew)b2QRZS}z{R|(XWh=7k{Pqu`vg%Ce2Jb$!;(No=EgD|UY-RE0R*wb7 z`d>`Is3uGFT5ua|=kNgc(%v2z)L{VwcBTvyHjnTj@|@Uy6e7Ogd&ew2JzBRpqetyF_ zP{McNUZEo_eolTZx{XzB;MVN@hsgU^8J?;-sIZ?rS4w|j-tIQP@q#|#`3LS1LCgbLq6F?xON!jjiUN|OD zY$(4PJ+$^eOxulvf8P;cP4n&g!|mP@@{!oVYMUV~D;#frfKsg}yZ0l3IO6%FbNek2 zeXUoXU3Yg!G3a*{?g0?}4v5aO>a?5l0DFIj;Y@&NEy(s|k|T{^acNxV5^&}tXNXNA zjO+kL$3wP%+yZ-t!2+9LGN*iCv@vA+Z+__LEMv%MA!Iu+A!Kxikfuo-Ns2a(UVj6` zNEQRrl5mtgd48O@L|{B&V{*AfJS0c`6%%b=||EJC5v~Otx>kk30UzN;uoLc?|&iJOt^>8x{)JwdA z(R)Bzx(kiDPpSK07IxwKB4d(lU6k4|`T{JfJH05OWxglaeFg3tukLIaWHO;B6?NV5 z&;Xu4iXlg$g)EL~t#_oa8P)eKR8 zzU>>uISP-VlXTE7&-6w;M*y?(6UCWW^4+8d2b0W{{0WF@JpFk+vnQPE&~fKQ-S!LQ znsUC5sy)kA%GdJ^{VA+=EGnbt4qE*~Z1(4F>tK1&*VDD2wAOv>z54iG2d=Icl<;Hj zoeX)B@`#)KU+zxpWbAfJdZUNWkL?0nw~da429f(G+*N~odKcFC*O{~M4okV?k}BJp zySWf}guS9vCIDRVQO12f^Ae`G|X-dWX0=E2X9xNpTzM!&+n*)K)Wx@fUD&*QzZ8K z_||9c!LJC>%A|tS25Wc1FHEP+(LNNI+x{r=)Fc+)L3M`IqVTF|8^jqSFWpU#C_#~> zu*pT|-?x^YCM3Tio!sIxs8@Je{{N81@B7c2@3*3ljU0;GX#w!ywf&eOneKm1s#s$ub zeoM065L&9fUsxkJgzDtbV2U75V=b|$O|y~l_52~OK;5|zr?3kx*lp@z&n@updlgH) z>uy1T=Xbb%SclT>3990qb}gjMr_XsF?X_IHlMCrI9xfo*{vPkkdhRNL-WceQ8eM9CR#CeT=!l1i5z*|yJry)fkz zpH=0au#n=0TKQ0xWI9QQcW?SN>2hkNx}%mHVyO|`PduB&AnrW@9B7(FM#8XSIhRzY z^X&dEx$$5vij9O+d=btesI^F!4(|#%YY|`lXhjaWjpRmMq(%l+WLxe(itk}Y+EcIM zS-+CmWCr=*_8(5<{MpuE*LwS@ZwBIH{;B?ZP$0dchIm!qG~tsk&nU*pB)EmUxzA0% z;h)shISF@8h`kuLw+=DD@LCaDg91K)g2D0UYHH@&T!LYFb0te?;rw++^r ztQZP8r{C_WSo)50PXU(O#_AsYIRKZ)vVgZ#=|0u3sG8Hau8G2-nI8>&5Bi=&?es$}lN9Hc; z6jhR&na@Y(G8%ke@Y<~Toc+lWp=duQdn$ct-FN1g1-go<;4C6e>GaM4Rf7RAyIB7^ z+l|utIhJtBfQL#o|js{9)7WwRYh6wn~6K2(CICt!&e z*j#d6BA#%IEcfdUMNa29_yf4h1u(3`z+6+zq-#w22fD1;*bp@#6GGs_bEep((ypzkHwyab6SDZ= z&v-&L#mMD4>vh=`j)6vq{tr+^JecgFHy89V7sF5wLIn`$h)n`G!Cz5VRjV9# znf~Plawsh>Mt5C~2D#Ll5=$C#WI-_|;wbcqSR^mCqtw{APK}qv)zEatNqAWe#7Kz( zeGH#u$Y`BKNBzjIyUBKleqF#Dl-p9)t|>-IwjrM#A&T>Wu6_7Xxz*4Z%mcx_l0JO9 z&LHZ^fxCYJ+gfPSXL8i3dCw{7!-WuOC-p zsT%IsVj#^#lf4pm?k4WsqeDqI&+#8U>T4R&&4;Gfbhayb`sYBhykkiVmUQfL+i9)m zbzJ!n&<)XnFZza4BUD2D^5E?GiQ@q;{@t~e=L*9)qaAD@T1rp`1AK7* zH7&VEmqr1R;Fyyt6;=vo1cY-I{mmu5cFco8)bY;hY1c)wZ(~jNF;tD9er zO|syb!UICdzR^beL~_1kK6ltpzZH_iNQzcM?3p27Uku5K5JBdd0Ir&H-Ezl%^ah1i zDz#O}auS4#>=_^R=_!3b3y;mOvFf`xxijPq7l*^Y5LLM0CnKoaM&mrz3Ol3j^o!bw zy#+H~#L#<$jo&Tv<6aQ<$TKCHS;XyC9OH(%OQ|R1#XTki$@@s=lnQ~`)Sq5MIKURIfM#L!OvdjLlB=j^(LXr+jh1cp3m@l z>9sJZ@ffe(_fy9RNLwC|4!^-f`tZ;D#K=aW@xdWQsE`D`Ny%WM*!%~yIDtxGs0B8* zQYIKcv(){sDL0fUrk4oC$=o}t;yz0#{I>hPdbYeFCbqaoq15%Wq-jV3GXfXQPGS^gwq4kf(PKkGIe*y zYtQj8f>&?o%f;c!l0MvcR%+Esi(SQ}9A_7_UU${8mMq_!3V%8kik-H}ftBpSzFe4T zgs`T@mnM?N7{9`0W{lwQxYKf-F>cQE?_}uPAIV4s=$n8UjeudxP6IJ`G}$D6P!@)3 zG2TYUkC^Zh^jI-Xe0Uzl2`)nxG}@@(QoYH^*%t!$GOCtZmOw-~Ce3Tl6{j`W?Q;RJ zuQhOnxj>b;7u#hlEnFXF;bnKB$@if`H&25KN$-9VF2xGXTv+ig!ymGw;UwiIp-IXX zqGV6Hf|fgVq}a}ve3bGyp{NN)@D7bJpn&#CF^(=;G*o9$=% zbvtJ27*rV9H@cGzIY-t1Xy=J`Zb%a!**>2fZO?Y*e{HIcYU^GX=50=ga;Nh$)K#M! zzoC#1WbO(5#y^0DM5Y#7Dr&tU+C@_2x6unjArRm;a+%JiLyiOAFMt<$=94u77lOZ! z1-tWOzf0r-)hD$haK^pz%-bnU-roxl>; zbFJ*)HveE$nC-dZDJNHtt=$o6_#;GR}hbK8UQHAypf?xNf7%Hp5->RxC>$GhUJID zIqhPsA=fwb<^^opL%EQHhX6LLob+qp+evLzsGI&6t#lXZdN1i(?3X~Js(^8}%E6!h zFJsT9%)PQpcM;U+8K(pmg_oDY{@_b6cH67A1;#AoTS@Rcv=ptf&p; zMDTgzsS9@~ceMwHv{8M_YB!hrHSihl1fvCL0t zi>|lbqOw2G$nWe7r%3feUz~q2O(gx7GJr7L91n&NDn{m_$$}1QOG%gk`ArL#L{-^7 z?DMVmE7NU$9yMZ|@-e6E9=|4GB5!+k)kGb&G685Ygx}*3#vWKWK3eD89+4Y5%ZF@o zRf8VWY=o@k)PrpmIv5YR&1Il6k4QMXE%K%o2EISpM@CYIH|g-lYyF1D@qR})aaEI- zy}lTmiW^DCtAzAwK>0bIkcQ`B?9d0>HfLm&N84ZQTzg)vklrQsGwvc(19zy(tG*RPDdu{-t=c^jDn1qGh910*NsV@y2dx`y5uN;77urlF%q!O+R zX}DFT#1G`%cP`ci`+BYB6kx4dP_0x*?N#1#ReUlZG6JzZ7})YN`^5<8_7FKpqI)U- zpz5X#IR-Rk(|5s9bx{=ssr=RXHjuLRETOTlJf;8HNPMn4>xK>$23vB*5ValA7v#dW ztTaP-Nav%a0nG>}x(Z49W~oA6z8P!!j+Nx>33{o_0T-J2A40Bcx_kB}6&hgO`i|n^wd&ZDWMl7d(yLI)NS8bRbcKD5gkX67z2i!mt4F zdh+tD?>I{#=^1y&9D`I}{Lh3*_}Gg@g0u(JIdv^N{v?!R+Zja&dRV{n74RLMji}+w z==|4AQDCEOI+pjIBO&gnAvA|BJY+C{4@dES`J`B#G3ZbY+1+53>m?O3<=GZlkn2#e z015F=-2Q{FP!0s|gZOR&#J8)`AR9{~9~Pi&8(q9=YFg1cWS~ul#f-~=G?()0x4f)` zE%sQ-QsSvEw?eK)(2y9gPtp0b{W_{d8;;f6=(h~{Kvd0>cTOVkV}BZPoyaR630C&L zH7Km~C$3Uwh5c@1kn|npTJZRq=~NC*m|T^DxJ}Uq^{6UKyGb9#Z0C_TiZdFhM!+<) zOLV@%wV!k@6%U}um!Nn_ zy-mVI^j!eu-yGG&5^v^qINMv1dU2soZ;mu3j4s;sA)?Qe%4#{uNU;IhT)<*Q+A^B*8*af#Jr%ZgBO0@rafK1ZEkohTV`1GgXovZY01*LTgf~I`VY#<;2Tn9wZ8`}P7smF+a+*{_>Tp@Cbxvc ziXDpLpOI@RausSa9x+>I-*qFcd1zd zeN2(jSgE8aTTb~41yK_KO2d4<#5r@}9_5&4{!S&rWdrMbV-(llGJeG!e{3nJFF(8f z1|1Qb=O55rPp%z`eiJ;j`7fz8i|*CJ4JMIbWiugN*J;8>r}Lq$mE{drMJ0_-cZ-D4 zhV`r8%t{Po(85QKhR!9f%FF+*vC4~=il_7!7Zu@y8e zPW`pN*%*21K3|A?<8K?G5a{JJW)?GJ!v)xKx_~`TQzaP$dLQj%-!F^uZ)MWcblMwg z<{!NA-d?4Ityjm)PIL5qwFtnpb=hK9rM7%nQ@)XvpBaB4V@@0q5LD_-=8S~zp%2Sy zFo0fYfq&#e9kI0M_r|A`_tZvTf-mm2IXf|h! zC@HDVi2Int^zbXM(N}|Z$sY01Xw{B^`voIj5=0vIhmgW&$q%8znvW}#uL|o#h}(jg zgnY|mW8^r-e}T$^eOp%c`Gf^D4=W{E$3;{hD`!ZUmX`Z43H&p$jB0H7YoTk@X_CO& zl;aW6P#qA_@cYjirpCz7_=D9nO>(k9GnMwZl+Q?Zk(=Y+dfM_2PGF|_-1fZki8!I= z4?1I+VZ*c4`1#Ijv`%PuU)= zua@$yCj8ea!SeI|p)eBhC$_sbUhiLa&?V`5X|Hu~FsD0&7`)3|MR;It4v|P&`f{xxd6sSvSW5O5Cs-1d@c`b%@w$WQ|ro)H=JEyM)0 zX|Bm_zaTDHL?x%<0Uq}Hi<JObK6X#_XuEUGY(}NSU-e5A^Ca=^~MyF~+q1IbHn~nkulfW7@MP)j`T#0tJ5+ z3WKfuWkBaWp(Y^=M{#csI;rftz^}D^EhQE17#8;&_LZ_FROIK>Q;$xCMbBISxf^6? zT^ea*zE#U?-F;fk<*)OmYT-clR;o4##dK)0#y7{N$-tB=h|zJ+uC6!=D>RDd6a4+F z_EL7Pn3y(hc&eQua7}PUR2?mRN;mc>NXieu(`o`DayGdsL^P5WdYuoa^&Iw=^c?sP zp(T*gy8|Wh?+YBfASc4hua0i7WQNM6%}vcHA@bU^5qahjomUU|m9p)G0{6D_c*lOP za6Y((>2W(E3)fReWCy9g@@;rc5V*eIqTq;0mxOaJe9_GjVKK_@e+G7_;;Zwox?0nB z-L|fE*oeV4sZgpw{qWL4FD%ln1e4HxsxdC2GHEHTFC;MR+IKt8dP7gtabb1@w|c-N zQ~JRz!j@@wNgrw|z2*_I{1a_ll)c!u@ppxXN^7p;b8ytc*BO80$qz3HceQ-IEP`ysBj zpJTW;*TSbR(I?{YoXg^+u?+va0jogtXpdFksJd*iwsuR*Pif_nf95)dow6+>kwa7C z%3d`;u_f&<)PG0{3u@j^%1kI{cKfNlurIq;qW){gn6>4hvlOS0`eoe1vt9ODkAp`V zp)(S7zjie43%AIqx0KW|3+^E+9U4AnW-KPCcm+)naV2T9&tiCN&WVA1VVsg_4E2!l zzjxJmd1rp5*WD^yQeqj&ezusuE^yfLPAF!FH~(&_OPsB_x4v{l_S0XG$o+HmuLq^u zpk$#2kWZN?>S19970pXY$Ltpo1&IaA&zyDr{OnY`e$_v5j(pS#w?6IG*9>xUs+6>W zXgFp2lDh-zLLNDA;f);~ll40UqW{Uk6x(m`QL;mg$_GihBX55`C6a%SX=)9Ay62Z> zT*tsYJyD;>&pY0LQ6+eI?cHX&gw_$FUw7(+NVX zQTK+|n3E75J5|Czd5wcKrOoViim-V?*{{QWju+~in4|jk(EpFcAb~io;94Kn6mifI`(WvS&*45jwv$wT;Jg53LbmXui z^UkHPrmZzT^lr~Y4O2c`(>^|ycQIj(cfqyF*g#AS|9q>_*3O&`8m-M$0Pq8jl^Cm{x^$F7U_@hlbQ4|5J_sY<%;OmXe*l+u^0AoX&srr*c>Ih~@j+pw#<)~H@ac^U~=Cl@#V5w<1TaJVq#YCrw2)O71t|yQ+Bo(oFg)MF(0NO0)jPP zYH*J8hl29`4;7TBwvNO_O!pdV%dJa#42%q)E(K^CR2)4?e3f44fQ-tGs|N|-_jAMR z-n6|^&#G$|J?>KRr#@@G&S;=(Wo4^gIQ_Ervw3>Ytt)+W`JbQci$5Fj=G*jlU>Q&c z_SXejRPSn4oQh(Kda+9Jye|KIm>w)t;J;Nd1vb1F5o`+5c5Ay?vblauwFH7=_ULhF zcqtFyY&m4|VtVjux>+hA2UF%+mOrrHn3BjWGm)ur=$D~up}44MKLT;%IghrT8g^;q z@$Rmk{zlE$0ITI1E5 z70;pW;{O7R<6pV4*Ibj?bLZnzEmEvJ3bS3A+O*{U?I7_EG#8 zFueTtz)T0=teoq&E8dyfDR0FW?^Lo9VtFL&amGB_kDJfG>h(+XMk^P?8{ z`*_!mj6B(GJUlWk>~K%PXWZ0w=m+b7anX-e3wc`1Z1N5V05S7E43QL@ddS37cq-B% zs3j;Q!e6&Wu`SbRc#5$~F&C^&VRBTq-8$E8A@@ErdWLKjuTWc66-cN%?Ed9d(JkUE zuBGv66@FLnkKx|u9fPNVzxjkJCj>OJ;-;8P3YV@j2$II?NOEn9JI`V|Vrk7y8Q-Z! zWGAIIOxT$|$|=JK|M%*@O1|AddE_ECUcv8kFpX z1RZb|T12@4XDn1tKedudUvV+ekF)KQPS^CLqfjW(kn1d=*92?x?!J%;P?&k(v;ui; z8{e?nV_3=CpxF8?K7GZ&XpIj4Q&#vmvo+v73)={41+ zGcCZXCe8AE&AGnF=aA-Ma{g|0UNyh^Q3}_2Ll6HVOOi%`MR3|!a^Pk zv>op4Jht{m!nAdDbzWY=v*inQTRzRmyPZ+~rJ?Z<10ETxeNEo!y1`vdL29OdDRD&p z4=~vwnAZ)DvEE0uRgcGheu=!Iah1F~h296Zlt(Ij(E~(7ifgXw)10Mz-|S#VU_S@X z9$H-*K&Lk^x-uNQSzjS_Qi^)KMXWO?&&xMOyqRB;B9X7;V(Vi^{#j(&QcW==WjBdk zrL-1eg}-ww4Hs65+uLg6Xpf_WNrw8^hf#IK`|*Hrw^56=S6wMVtFXP-1{TvZl&1sx zEq}V)hU-ATbpK|T57fbQ32&Vo5gb{v9e!5(n8k<=Sp^>}S?pp&$+RA`NcBSOHN&R) z?C#^2%)u58=faA?j^oghnXPS)z+|qendKYeYUsF;nYK={mklrpv?!RI$CHRDfPJT+pSxXF8T=o>Sx+ z749^1m#Y$hpp!FO>0>o$;R0*?mp^8zQm@}+U+}9tarWS7K|9_%HeMI&E_dwvP%yN( z&_eR&hqJVbiT9IjL3bXRPw3RQ0eUsAy3uUg9zX9a`zVCoT^LzG(3~5o&55E_~&dU8pm6)KOkP!Kp@j zCtuS(BDA65uJ+NV^wk-?6xlutkPJ=xfX;79$sVTgh7>6&eDfs=(eTKRNPjCv&aE_d zk)^AA_gJd9BW$+VwBlBaOH#vd%#lZsV_JWwpmmD&->+1X-wY#tsxTo8VUNl}(4WXr zEn%509yT6^(!%$AGk2J1WTy58rEK(=`BI6^W|M zRvP@X#SeDUHGVG_xS@1=)Y;TnXN@roV)`G_$l`NXiM4N&L-k^5b;?ChRW&nHvO#j| zOb|vrikRd8P{+O`m}dn#$xW0_1|3X02`&wehpp6SbYj$Jf zDZnUycJrmz_jcReLoLv#b{e}c;4r(+W!6Kg>}7^;=BUP)ov{7*nZVeY)7V+**xCNr zp{~f|lwT1A-|G{UH^ryeqNJm@3KE2#bcm(=T)o~rn6xQS8*NsRFle)%`m*S|y3J6k zXi?0db!jSJ(KmJL=+wtWQG-@asi`xog_@wG03l5Mp8B+25$`+glx!gdgP=Uji#_!z zy@E>_-Y>L6_3zF8|51zjEazv05B4AW`O>zvMwqXxAMQVN2Q>w> zwe~K}2(MPUS%I3W|KE+e|Nm4cyF8CCu~|=*dj6f?raM*Sc}$6QUh4Db-}tS=QaPVT zl~`G0>UY&A_40V%YDZ<$DKG^+#k|;6pU}(UeH9Omw}>~7H;XroH;FfnpJznnk$skq zG_JO~Vo_1F|6JRgZ|whw!7n^%gD#mdaCqs!2@82WyY?~kb+AA~$E{P9F%8v-wkh-+ zUE@sQ4W76+LPO@+?qQirt|TUSY4ay==dJ$1n(Wc?Vh3Bt-*CVEGMfW`(*L3DJp-C( zyRBgr5vdVT5b4rX1f+LDFVgHtjX(gAUIao(RI1VfC>E4Sd6o8N^cp$F8Pw2i!?^y7K5x+v5m7BXzdJo_b&VaF$CMC3 zS#NU2#gLjLclWkkLU?h*FL~tW#*%;j+3SNy)OapF*pIs~@1UXtFCOlBJpEeW+Q*TP z7X)v&{b)#GeP=g1oA;2=DIzNWI=kHa;Y0nxlKIAu8wK`jB?}F;R)1y(ZUBKXB$5G} z&-WGD8O5M}CTn%)3+pMvPLj9qA&Fn+G9_&KePmo8UHII;;cQkGL98phUb7`r!D$B9=C}NHyNx1cmlZnxo>_7mfmk{Inu56?7nS0l4Uf;&& zg{p6_9xPkzYWIB2EX~SW5{imz#^K_1jkKYpy}X8DeODMs>G1QQ;ODR|5Hx-5SK_;= zP9Wvj$g5o5Xxj1mW!3velTsc81j1HU`ejHZJ9p#Qm1;+Aw}k=M60%>=#A(OZ`3Zrp zX;TKn*fA$&rXgA1G$Tf-0;Dt}xp{8(1@E=w$3MY6(TUq53m!@v-|trVXZwHpB7Ub# zikv}{9#)cB(X^FYku$|`(hHB6Z~t~&wJWn?_fAmK$~WI|npo29x6dI87%mx0l5fAD z-v{&P9-4Z?0m^i_9@s}Z`_8bYnRk*%?IqkBW_CBhRz-_3fqCTecoBft&Qe8eeHSh# zLOclnx!?ZnUEOkZ1B~l&kRv|hnF*szM=__G$7f>a&%!>r2b0~22s6eQ)tA&(Cj!_n ztK#o0Ki>*)|4cFsT#f%WZ{a#F#4g0bK(D=a!L>zDpC6SEzc@1LexSfx^~ye8-hh!y zw$+WHc{mFxf5+PDvRv*@|NT!RG663PTQ>BV-p>}g)b!nkQX=2EzU?#)bTsJu$oONg zrbs5U&-H?fpsB6HJ%v&=+)$Tx2@j(2a0dug`oPU8=e4g`TrF`cU&;-BOV~Q*{k`a$ z_n3I?s(*2(xV#^Wx8>$2i3oRn_u$s9*sN<+d-SJ5g>WG>66fJQ_$?n0U}R+whVpdQ z*36{qetYLNR>MaiMu3>HQ>MiruzMozZ@>!XY(HyZntk<>D8h)}@e(mKks;cMzVLGS z<%ha^FQZ90e}pq|&diW>k-9;kxmL+r6t3Ndx$Z(auTM5&ju{&V&pfi$M;EQmo=cpA z*TpTX2n1+WYiz%np{wI7zq-p$t!pO;*B408#1cev!cjO0APt0NR~1W(>SfxyiYg32 z8#b5ZW0;qSCMXGYBrPO!0H=YiIfFL$vqB|YX?Tk2g2Ob_BSJ0^vphiX6MhPIFBM+O z4;s0H1dzqCDjCQq63Ura{2L(<#g7~=VcS)~0#FEhyH?mG86D_}t~w1$&_qvJ8?Smv z`kM54>EHPfsF7nWsrf8e2z&)Bdm1Z{a4rE;L6Tp3hVs5d+F3-8a4B+cnKZA2v)DsiX+?}<%41{pwGYZkmdX9 zS^+VECvZlAR4uH+cM0>>@0h)-^H1Qe*qZAC8!pHw2%xtcREBE3P<03@oyX;)MA!c6X7P$MM#Z3G<5(M z#-~LtsSRyiQJXJ-54e!e%`g&^mP>z~hLAZXSco;3<3m_}k!ZG*uhbxpNQ_5f2$hyO zA}Q*6Jee&igI-qqf=2vnZhFr1^j}Wk{B6DWRRK}q+IrfZ8aJ*G^6(*du!;s(gs%H+ zCyGUhK$~H!$BQCcW~#x9Sg@*Se@?}d7tNzVp?%1zna8RHQP~+HB*CSP9q$?)&ops= zIATm~W@kU$xns05hm~(dbu*y>N%a6&?C{U=_z zaM>T?YUjtMayd;J%I8IV0#3i=vAnKu7d#6z-?4#>@e*(sn%5!8&+zw zKlST9@Uj92`C!y0fTuwKf?4?TeVQznyJ`?@dX!KK#dnJ<+);LUw9%04X}}XgATOe8 zEUu$xXT3&CdXsE#9tA@z_BPp1!ts^4jD)WxR(rn?$i{=+FVmhX^7dd-+LE(d{c4fH z$RBek*>`GfbOcQd8arZ5jXjZp&K>O(5I;QE}|9Uc|#^I6hiPToC!r0ayZMQ zgTVmPTA71y4xpfh(;7NH;9iCr>-dN4?BmugP?MK#-^VVKSMH`35WnAHl)$6Xu%ft?*S}&pMFlxr8K6%A|Bj^36#Yo^mb>ZP8PJedm z=)Q{BPR?Om%CYAo(@cB!DjYdztzL#3RP^&V=K*!B=aA#3AdAqp@@lm#<$-``QqPN8Ky6pNdeNVLp zWF^F6+lrPBDV3dgxEF;pseOrEkC>a~+nGOR?xMJka5|3Ft0$$VSQ! zR8OrGqI2^_nipuJ&J3u2NJQ9ED}aZd*8Vt@Ld>m@0;b-p;P_Vw2Kx{ZVgCDGmP>C&U_O6a*9*zIdm&HnfL-Y)K_9wt2)7k%vCxT(0- z5Tyle@*?>X7X$j$iQ8d&l=LUQ!yj_D0{%1wb{`L$=h7o#NbFbV z3{bF&h;LKq$dB5yTg8Al=s^lJssmH6w!7RdoYlN<<>*=#$8}|p6)8)-_$;XX6p-4yh`Ek?K(}Hs zDf~&m3}yZ5^M>e}Zb@i?Pw?Z}y@=xI1&ccuUpN0&4&# zK6ou&rJ1^lmQY&KG>@{|a4LB@nJI@Eg@FS5%LuAL{f%FWtHt|76~kiq#1*}9a@t%4 zpcB&E!0&2c)p33cZtLX7?qO@|1_GU3Nj`8*wK;O^5JXlY)xC7cuT8Gz!5~n|dyHAu z$CHEFhn4RVl6i>>1&0pGPJD{Kf5wVevWSy?-ZctEjRl+2f)^@dV!ce<`_R6_ggFdx z4xZW%n}Bqe(kJl#+7klO2z%_X)zUv^LZ;K@d@#YW*r z8#h#hX1F9_J94$%75G=Efk1ZN^K<7n5>CH4E}Rm$VHcNw1`;L?^;!CkuMRZK%b%(e zwm5iwSG=E$;CL^S2^df_Z9{-if3G^?5|R*W46!Amt#B0jQ(f8<4yf{BxHN=3jbMX~ z$8!&o)n{;%RbG*t1AOzu`r-rTTUMVl+8fD5pag^)WgPol6?UAesBFc-%wx!SZ-9CUjlxnYpgkmD`%JTeEmV~G$Hfz4{FiWV5jww zIE9Xq273P+3fk(;(BRYc!9xL=cx5@45erUMni8bPh{!|?)?7uhb|)XW-NZA%X6~W7 zz~VIoX)rr^)rnfc5+zWzh?K6e8Faa?d%H|RUz6ZM?Q&F?SzYK1O|~N;ADCVS(O(HL zXJ$a`x93t{JOUf{b3spF2QCuv-bbctz?A^l}VcS zkpt)Y%SJt!n-#$atMQvnzR2r)+K}$K3$ekN>SIZA2)PC)%KT!0vQ+p0^L;s7O}7np z%)0E-4_jeDDdXOO@FB*l#mJCXBMULge8q*wJj-+a7fzDJf zpbbwbA+KINHN}r3X04IrN`zE%f5RQ{fxvyNIqD>rnP-5f9Q**Qx8AeU{T@9T=D5%zQL&m?5Wa$5>ft$~ zURL%+=h?YzzB~G{b*Gapj29v#LY(+F-}8uVg|&RC5lX4@j8<%=%?@7~XmGu_*~yDR z`M2E}$S&~DA+!Q>lpU_+xVm;`MyUAr-zny9S}D_?Q&!(yE001n9``S7WDGy`P+H!~ z%c;AyI8`L7P7)-g;?U~-#KSKI$eHUkr2K%c*;jA(P{P2K5H(rX!%(DZ<=&==Cwg~& z$usoe=nwKSd9QqhfPNP0*Vk&s#hX?M3#8V90CM_~i!yCZnVKnSD5q)1?$m_ee$K!d z_B!uB_{jLIaoe~;r0=wapmW6N-0N57Tg8NaYcEH~*(905(#+uB`KO5L8Z(n z?c)<#NTQq(lGiH;m8TFYuYPNL5|=>w;^Z9PHbWlYK#%`O_|bi2wL20}i=-T43{SM3 z)o0V)APcBJU7vfm`<490uA0^JshmX3^=G`1+x(;;s*dz}tlb4Fnj@dyNpsfHgHf!F z``OCAI4?r5Phi9!b-ta&Wcm{*15q@`aI9!e=;UOM!8^I@*X$7sS5i4A5tNQ&P8iW5h z*XqxntBVT$b5g4x3J>1b7ue1GVWv^78LyY+P*-yupma9rt(UVabvPv6wUDoq!Q|UW z%WE2Taq<6o&CyH*uG4H;iuv1$cF^`2@~lJXM@bc7DnW2#IN1C&jRBJRNGva)US>Z#}2l1Ia0f)Zh^kZPliwf@& zVP~@kO#1y*>uHD2yx#6}R6wb_h^F;%I+lkq>LV5UBLh9APuD+RUVZ}C6gi!FsJ{qV@nP63k=mTaj@>Jv9gmca`p+T8h=}kKP{Jml49P z&{jYxJLMKYnGXXo8PMiE-ux>AQQst2wgw=l8T&FIC7QndoK&rTxeaG`eGJjt1X!AE zR%HRqOO&aM`ADKLLMhBjoQJ?S)PI^71>Rj5EX_I_JOF5Ne&UmJz$(PK8)k?sgbzpv zd-|{-^4C`Cy2@?BUn3tB{3=2W^l&z0S!@mNpF|e+b*hEWM4;+Q+NLA<`LwVr&6)fv z{G|p;+7hpkH4yg9s1<_A@oZO@GzfpkU$Tw>2+l*6B;1Z@hbk z^BOoS)jWM)g;q%tXf-m>JFfK-OPVM`@b#`dNcOhPVVZott0qavQPO(^>K}vV&-ztB zQ;uY2efo|=4GVt@i=2`y)oX4$9_AYYIbfanh!`LM!n#}jcdL!MMc6kylo?N>`9VuU zDK%wr_Sj5*`h(^f4uW_=*4pPbAPB2H@xw{r%Ieu$NXyv!rUR_qm zyKNsbu1Q~obysG~?9=SclxbrVr2Yr9^NXZ2K24y|SpKCuO4?<7+@IoMxwD|Ys9jppef z+0g`9kup#QRbDct7UZKoKwc#CN^=rw9(_;^U0%Hw|;+5 z_Vk)wGlyBpE}HsZ$8u1Iqe|b%ahZkQ>BRQSTENrL(CUNdl7#rG%X*Ry^)pRm@z*CC zBB$z4)qN-uID-#IUv#&3edgJ>oh5N>s8fn?xvBlN7?Pie>v2;qVNV#6{}mbR9rsx* zpbzG#C*`2&+q$8tXnbj21=7&xQ087jhNBQzVCQP{i+?)S7PWf&$+sb z17-7O$g0YpG;fY#-YjVK!rf#0x1smr@+Sj!6N3PkNdLWYPo>Mc0yBZA=Q zwq#hqk636|^bU}9IvOQ3EW0xIgP{=Eav+w#l1%n^eO#w8GH3COiq^sX05P;2C(aw? zY)`nUikl6bn}uZ6*SH=B3+~ow8IH@H9j=WDTG-FDm&A?5?vG?U4&#dT#a!;;N6Kyw zpb3&W8;;hAW}=WEN$QYNZS+=BK;ko1>IcI0cC|g{Hih z`XS5L9&S1o3$1WHfVT?JsLHh7?>KF~J8QGy16cPN$mHCd4E_V(Kw0|GSm=8QDI{B= zf_%g#HRO|~QCncPx-d79fTRZ0ESPcf-nPIrDijMX&sNp&htqYNJ~aBnX&ed91z+Pd z)q^L3uW*`}3OS&jN#_{zJHy|B8PZLik|x0t>H5pbMh09K#>(A3!zND?N3qw-Bdztv zlDJUHK7w`WGg@QGR^1oM6KC{1L^Dx5V41q)8QpCWE7VgTz@*-`AR&1Rd$v4G)xbZ= z^700PNkF^%u5?x`zaX`)WJZ=jC%g=-ny%5$&(?iKI{UX!MYpwd!f(-3xO{nqpZaFY>U3`(S0{j(L&qt;%qDZtRNjzUZW=V57Q4TCv7sX`g1WEjlK>X);mY3YB zf#vUJH06_nQSv@~bqF_6KvH&oO25BOB>VwbRw*%7z@a-(`c0PR*W`4te7ezcA`yFe zSnp}FE9$xrkA;y3{{||Kdi}T=Q~5*{lnvISJi<+w06*#W-#s&_$-93%@Co*Rx%txf znI!n;KZE+$zvSN{zTK+Q2y3k=l>M+_O7au1oP~CYpldfXn5Qmr#@It(qr3R8LAM(L z@II`m4@X_5n}Aif8kpWqX9blz3k$)y==AJzKpBSu8JVE_Ca6&4E?z|gu{|3X`SfRY`cVH$?qt0Y{ zER%GivA{^Tn{?_wP=Hk~Pbm^qNXqOM2dmY6bmQmhcE|er&`la|-v~$+2aDB3xd{>y z|CJpGd~<(nJY;H>1BT3V`!a)9qN%jJhQKfl08f`=WGG>85(Y{u50_)IVtX7g7Hs-G99(M7{i9BtXxHYf@*MKeIa< zE8(N?pO^wpn*LjEdhK9>|Bpdi@h>0##R>!I_pu^>19j)Gv^+xj{ZHzZXZa=nQ^-7o zxlmL*{aZ3ry8naiRM`ZpKwfY1|4Tc1gZ}NsU;TRFbAwa6Gie8WPASY-=&zB?-@<#{ z!ufG`M6&m;G0j{;ABoLMlxMRqzAd$Rsw_!$Ea5h^dRPs`u92~m0RzosqG1oxKUOyVe6z9dMpnH010)YO9s|46snN)VHx@GTx z)h)E0?m@RTgOf>Pc|6g`llznf@|jjv0^JZ&hyoBm+IwgqlS6>-y><5av{hJ7Md1?O zFopv$>J+LLeOmECv{mE}0!t}PL+IdikCMGIq-^`ngF0%{aw`%yg$mm#uGB-aza{wH zCmXPxx?ia^SqNqfy4>#(o?Ijo@mplC+kV)@Lo}d&j5EVj%||9ZGuM}XjSA8}FrGVG z#z0|GV_Q&gMcTTY`r{>)?jz$){W0o|0Un|((|x`C-6p@o@H~{%dfJh@gM0v-IlZK0IWXI#X6GF+xw{X{ z$XOpv6fNv_2di*~{yqBd`KrqZzhq|YWtURiXYPEPrl`O#JYihzjq7&|j1i%|mH|gm%;r=AS8R0DLYt9i!0kzKrx&^kEBE^QACL+bA3sRYt7o_OY zD+8sdMMvm5Lh=n`K6q*8ijwuxDmfQ;J%;_?L*5$tzDM5@aj)?zH)LcbjF?R6V2qQU z*iNWRj-M#@=DTy8FeN_~TZV|Z$2g;4ResEyVtW|x zLhAlo*LL-}{3V8B5%+hofZj{-vDzIX;`g4t4GecgCB!;&@T=xBu3fG-u?!Elav2^o zR5s73jQb3799~!3duM0_-yz-zmn@3R!9V;E)85dTFZUiI-lN@GDCIKQO06>mrC+hk zH}5GM%a3@64#Jx4*0tn+i8*0LrB3wnJ%~YOei9|3!NXd@B$Wpxtqq?f$=iC3twG68 zh1Y_)F@}l*8I{lM*m`tpX)yN!ccV6vkmiXJ^vXQJ4B_$Cb_zpllKEOr}9Qz;>bb)wEB)Q1KC@?<7NUm%JTEaD!>k&pH)2d!Az-}Ff)lLtVsBQS?8~uKs zA8vI%v^;0?Qh?XHqkvDdMkmkWkJ>kNYI6>hhefwm&h3lR2gtRuHZf{?BQG8ZV{Fa^ z3qi!h+@v4WGI_jEqcI*}OS=a)SckLs| zQ;a)x0AfKVh)a0YpC~$H-{#C{d9bYr9G5m>idT_m2b}UI5q5eg{=mX0~+n6xp!7U}AN0EQgD|New;bv(yg+F)7&!^4`d)Imn^yBDrToOf{z7YwVk zF9QIEXFl_>=5Kx2Ra7=`6|OO;PoN(bc@J@er)WH-PhcFTO466CE;<)?aIJGFYd+6@ zY=EXE$}L-FP<`nn=yF6_^FwNBT9802%dm6=!a<$Q_U*wJyxVU;Yng~RXyW~=G`xEe zom!Ac@w16&;-hP^q3`e)i{`>LCqNgG9rgF0#rs@ACmg){d1Xno@!H09yF|ljJcX4Y zKmXv#IQmFkCK)WviNVrD!&~W@E=v{DUA%s)xGn1ay;rXd20!y$0={h8df{@=luA~4 z6V88`Q|n0fSLM>-K{eXSbEBz-Zz}%Y==7A;)YMpY^H#dAkMYqJ?H_-BKw!wwL!qdP zX!Ht^f}p4lK*p3;HWRAGErYkJ4!by8VG(KqBv>^rE#@hv2528UA8)SDbV*n9~cZh6PB-zwsYGZ%evXx$j zUSGUvcLjPA^Wx}T_*J|wy`;vBi6R48C^x<~;U^PRNdORlW(WixU&W{&Nrlfv!3>|> z3OB7~BP(HOqNnMR(NMi-w6Kp}H%Kn6fR+Ja+4%xC^n33QKN-nD46rSMpQKEB*2>>tfEixOShHtzL^jhfkjb+c#W4J36ap`R zLU@T_%>r4ef0NY7@M2hCZncPx5>|_LxM*^;7mm~p(KzCy9*7fw8Hyg$+Fd?Ox+~f4 z5H75`AeHNaKhHg@E%x>*G%8c11}SNi405^Qo74 zsi%Q{1!@J_-G6Kp9rzYsh@ZYFIjR$T_Z%=8e|f?&9YDT~>5|I1-2Bcv4DZ;^7tVtR zU1X*X*?z*Tl}iBDdiNNJ*?OS7R!u02hR6oJvMZX!NMtLCpbiW`-R6Vd zv|}W(wtBWCh&0ljB7U+%fp!4u$@crO*4gOHi=L4%<7f0lwq`+{6ffn4i>-Oot4hSW zhJV3_(U*?5Cx-)dDWV})y}9h1Ho2U80@fPyoI)S)JWC|x?^roW46T!^ zl<-ulaeHnz;h763W)~@rG5H*ek^&3$5?bxk4fJcEOCHqZu?BDp>2U8|!*C2z=rPVf z&FGy2L#-ppIpOvr(iMRPJU2#DfQ7Xc7L<62JZKcY_?+^En|f&1Umvt7)FzBXwx@X% zHq+OqqTGNJvp|7OpdB;T?An`C(X0fr*)x_pD?Weiv9kdmszwQ+YNk?8 z!7)wclv_2g6^Qr_^^jZuVxx^KB(MpPK*V3?vt4S-Q&+{d%|RTl@!>IDp@9hi*k}}T zvkkP1i3&M-q)syABi90et8ERTfvJGGg*L0uBW1qkv8cI?w(%qUNAT72r`Q3^-+AU@tbjGTI7Pn3RWpaG_$ zo6=$z@+*pufKgK?J>esl17O`ze7hJkB3?A~Xi=T?34lAq*rgb-hhnos=CAN+SHf2(XGe`2@eH-q;m|TyFy%VkC)ps<~Tyz# zGppX%8|Ar!DOL~327or&a0eLIkfVEiXlxtD2|hwSqy*rJ#~i4uF1NXc1bzf09OK~t z*h=aDqwBi=7a)YUPa@jS&UjWy1O?z<^kscYQw($=&$ejl#L?5$eqFR(oea6M_Bk?D z{<&L~dieg>{QUfm*xMUbM{WB1qRN{;QOb*RJgOoKlZ`AP-1u%`768j3ORcFo5Uu$Xj z7BaWQK73JaF>>F1n`yAOQXqkau2LnUF+q;D<2x5HB>zICJP$d%X_;k^#**f{TeBj4 zeY@%SCC3s2zxoGdZOk3hV4_`9Uy}wjr?S_^`4jI4g-1IP1F_%ftQ`)|*2txLcV~X8 z8@11#~~dt6#->=^5KgiAzq6KA?CWFQdd2FPa|H z9GgQ&>S)08{OnLj{PuiarL?P+hYQ)g)=MmzEH-V z?%?;!jbf^l-udU}hw>U&53Zn*9lQ6T2GMyPw|4U;mEJm&j2-CLON~C(!6+;T?rBjQ zUY;U^I+1<;4^wN^@8|CEOhnc5hI5avHOxf1aY7sguEdkNqGGbGA@Y={n38~MT3Ofi z4uJw0_9#<{?v?PgX6_}mw27sMUpF2$%v|s9C3R1k2NRT0q?dyaQqgqe zMrome8=;T*f8f-uax4y4FtSSqkJO~&J{Q~0ZDn+NC@72s7p(0STig>R;TCHO3Ckfy zujSVx?v}G0)Qi-0v#cn)*=_rmvZ|cuRJSp|L36aHsF#YL%v^9lSeaU^4RWlShe>Is znCI@_k=7b$tZt%A8icwT=XrShl7r#eHVi@V8PS6s?T1c%AG(iTqO{hpfo1j9=OZ5K z%g$5Rx7WjXRG*4^q>$cj$9bMXr`3)vpWa%%<#+V$jVeq-nWD1ll+QZ=i(4sex$sCI zMl>%~Q#(GZ@L`4stt(J#ZoW9pt!KrOzOudXH9|e5cX^{jU4eaW&N)qG_L+ZyRRPX# zBX@;SMrAfI>9CZh9@r9hR*x2Z23^X*qyNnRPEHCb;WOf~sLD)+an#BARo8pGUSCdi zEG}R#4W>Smiz)?VO&$9k88%V^te^aB0-k7VkT^7?~kYQ{I<;kH?@9_E`J8_Q9J7Czv*J5oB4cxJqG91w%pdZ>BX&V@Bb^ud8TSd zqDJ$OzA-8Xo^y9qibIWug=hPsmv!)Y+2T68K-K4UIV=^WRdtq0@TcvXmTqVGr=1RnZ`Ox?D+?@@?;N$)~Xu`X71r`4TiJCxOZv;hHe1laNVC({QPjh=WS89v{)q4@Fa#B=yweVSgsQ zM5eiV@@MZ#F2>oKJT{nRi18N-FVo@x`AM8p!?<;dv-R?PPzlW|SF%g&dR8+tv>@)! zx$k>r{ZEHpu-}c9pQISddK@O>g|7i3bw#Wx7aYSCUxR9HB|l+OOG~J<^F>%?DgCkf zv^T!0g3-zBC=chBY#)Mu%69Q3GS%B@D;yhRPZ2%-ggO3c@0$T5_9*|vmDK3R1xAyR z$qDsu6uXjaeu{3rbn`TKIAKw$=E!z53#b(vEPa~hoUo;-ff){%RO?7pSXx@z z^Pu>KDKAZCJ&MWM4&K{p$@3)L=0En%K5manc+ByFHVz~E!sNE)qM(af4PVlQVwd3z z#Rkd%@8>F`sf$wj>xq&ye&4Er2NeJ52S@HzhNW}$mOHAvJg*i%M*{?O<%p>Iz3|< z+HF&b)crX&S&rLWMbX_Pv!b0pFDm?OSem8)953{PB>~`IG#O%T&|T z~3*72j!Hi2Q3+ zTHZg)yM><;Sj$RFH7LckeCyh7rAbfHU?#c2yQT7gy85B@r)$O6Qk9A3T&(MdmzQ-X z0}ASAf;G*>hCfE@K*i@7tn>1j!=W4db3IX~%DE)vgPFYzKk6HL;;YuZ4PN6<0HFu| zKdzp-D*2hk0xCd4mNsK^c=@h@%w6HZNtv6140B$Au@e4sM8>YwrDmz1y6Lp~p!REO zV_OvJ9!vn5`c;k0;Tg+r|D8khRvkQ`QYxaJ9Pa0}u73AvZjmjqcmBcpq~{sN)6QgS zi)`{Yv6Jh&uf!K?@!xvMddLDDKOQ?Pl+hIX*KX>nunP5W4}>935Bn+FRwoN{&s`B( zvvT9V#%xPBIl7qFRi?ViWOXugWzep=2+s%)sLfOx9D1)OwUNUy%ItnkYc!qi zWr7Z?>#)RCw=vUOF?Ws^_L^vq{RXdS%@!dl*Z4HJ7LxLwysz%nG&_L25Yt7kUYtrH zz8GnVxxMOfaPe4uBd=7ia?(n$`z(4~u<2dlS@XCT9eYO_Y7Po0z5JACS9d*gc)iZR z%#dXdMxWdmeyX;9H`x{)l&_FzX4EcjGK2kP4@Desb+6(@(&5#`%}XXKWLWMk4PqW* zP(Eik=VLRtD)8wc&7r&cc$}=8FiDvQw?8we!sAbEe&c7PYXrhrd^7|~_>NWly7){S ziV4F145tmA6M+hE^}U$vEONk>n`Q>~j~26^d_nzqV^YU_I8XrdpI=GrpxIXl*l0v3 ze0ozN8q2(`cd8T+H0djdWxkU5&cnq2nXgj-$z zG%9jK!RpB=(E$R0BE+u@Yt62mB*i%2-M)!{3i~ZK zxL+%**e__@vFOL8P2WdLJ11VsY_l&k38u1b|7F22I}$NKd4TPpJh05&uDDETa(fh) z)u3tdGRyYsyB!k;mRgfXQEP%t!vjq_Yt46FSQhU3$5iY|=%BCdcJ?O+aP6-Dq!H_I zs?l6b`(x*8%G`|9ZuW??RvA1Gy8XsgszlE^7FYOur0~ou>(Sxyo@J{R8J=TM!MnA6 zVvk~qU~?gUQo@E53vm-q_wQ_pj7x>l$Qpaft=gC`buYF|-0hmKeyY@E z6rG=Jhvz4opB6AQo9gtl`WsAhJgmkI%d}NXK0bt*K5nBhZU9=g$t&;HHz&8=@q@Ig zoHYWs1U&bRr@pF5JaA{|BGi%P%i=EmI$~s~wxIUUEhdbh>eG$45)pT86%ZE`CxYmgHe zlgC}~silARQ?cHly8R|i={9?&d*^p-w#cyQ8ZgipLUdsYjMx{SJbJ0ImhDD8R zRy!AXe7I%LYjT4aQr|J=`0=7cddYJ~YN* zT5UL4!3^k;SDoY11vPVo)@ihjYtp#bydluq@`Z1{m>zqNsLf5Gk*-b?-*B%u*novD ztl;UH=7ESD?z{9jLzcUtqX$5xvU89H_}T#O-6GHYzT)sXEl>NKVan!sv739>6H}VQ zS+e=(#--x_G)#ycW`KJ>H9rkl@Sf8?epz{y; zT?;|9S!+caj&tR6C$fVq>jq-j)8lxc;3fAP@ZN#Kd1>+a93Sb~{Sd~ZoAa6j;$ou`>!8;iW z1wsCeDUdzSm~r`L$abLk=~s?YwQu(AuWFH2Lo)2I?&^uZ?cW&gmy$SLxNmLARR2C| zVOTQfYAQO+hXKc#iWZ;lCt}>FjTS48O*}*2l;PK$X%_Z<+v*<`hm6CZBUT%qn_j|q z?4C}+Jq>KPy^!De5gcAeN&OBCT}NxAyjHuYtkT-2LwCf)X;B|PD9{6a&*c>B*2Sf zJLW7AG!8pQ4*12`>}AmD(aU{gxMa6;v;NuVBoYs`jW~WvMxgiGKG>b35 zc}Zu-hvd^Y6?*ggqPx{A?*J{Ln>L<1kBuHf_~ReOo4wA_sVfMMaUED5$_4tWww^w&%}fjGa8E_rC?Jow4>q*C)IUpn_zXOC*g z>Q0;<$FXs0Zxyheb+I9=_4uB6MH&_vH|&-Xju#<}-uxEBfcG^Zvgm%(WY9ua7wQ*Xdp>%#(e7?Pe9gXw?ca z)}C2=;U;*`p_PXTp9j8dy_`r6yx|^o;GcP@PnU1<faVao>LhwS^xaXZiJ_E-n^d*15)TzXWzzJKG$+k9F$h{>B$P0AepI%j|N-JC@M z9UYPn5Y9cOX4#&7DG)`(OAOg>efw6W$X9(v*4u>nw0rbU$*cU6AD9ttc^{&Ar7nIz z=IP^px{wZK;herGYLR`Pc)<}tz2CRx3M@7AWGMGS9zfnnJ&}}h2>LZ)YicvBM3?hy zPT@f(=r*qo-{K5{8}Vqrrj~tVLHdG{n`$!9u@Rn1Y!6Ze;dt2xuyxgoo?R$;V@KoEd>^$1Y%JjdYHphT+Vb6(7H0`vBvGYvW>r+TGsIQ>Sg+u#1x1zz@-^6X`Da9?6}&_jT+>Z7n)qTR zP!ZLxouUERpu3PzB`A^PAmnaNRJiNmuE$i(xwt6S3~4Yo4L_Jg@0BC6`1!Qo&Eofv z^LLi(uc1HMZE{GDT^gCbwm9_k9Y@eA+m(=04MvA5`CvckmBAG6ED-H=Y*3XklGV}8 zzrubb@v>aP;g_=mdK}cFX#+E^*n|Ss02ccJvdlYK&66p8{V7`ZLcb zUx|L6+}Ql~U^CJ?!b>+7QOQH|v*J#aWAvR6MY)0=$i98u*DC)PFrABQ+TE?>=ql%} zgrlP~U5+@lty=u@8A0t0pJ(j?c})j;fFeFwqY3wf~HqV z#tFYYMeICM+~ZYAoQhK1q2zgD%~Tcz_leY({Zomt$hoHivYkG`&ZszUs-8el#Qhio{utzl!=6|8FzLn_9jra3S11B0o=wYHmH%oq%h=xL-d_KfT%Kr#HKe@oPr->Eqn) z)AZAa-+6xeICtl1&rcuHzm&KCWj&r9#5>K%a9%aYwFk}M-`?L3z47j!8Esh4OsciG zw#B_n24dFo(Vr{7QW$ms_(VDXn|117J6yEG?<)$mwgrAf@~1uDmFqHp{D5@7J?-^# z&c{{hoVRFoW4JiC-x66kAc(_HE9{S>-UiCN^lEQ`&3Kh_35>x5k*xFM)1H6C{R3>L zk!%|Snk!@RwlUnp#=Kz_vukP&*uRHCQ)^G3E3B`H%n@9!ohVl*JCa4`M;8N4sPT8!&a*_ z9fSJiZT%hLbdYUw)K1$xSSG~dCze2)6G%(Zq4^0c4~_|Ve}=}#Bvm-o%|!{%`9tW>0} z;__|1;|*j9RhhThAc)#%Ua38UGCj5H= z5yUkY_yk;&{sTUok%8?>yER5yt_>98&Z-=Bc%_VcYmg=?mgXxthYCBco5%zIEjVLa zZ?(SKo-5B`9q664g!|*x+h0h${#qDzG1fHI3N6g$*Tx55WB#Hg`+JMxF{?W6)koQV zS34}%9cwN@tR@b_4vV36XSu!sz2vj7NXot$Hq$nrjS}1Yg8DqGr2^x9c?*2Ad6v|3 z6<=s6kB5xu7*}{}@m=V5U2c?dL}DKNmM*t#X*R!MMw=Bd7eIHHNgX8r|5*sx$KH_R zU)G^-@2%;yyHlmVwS=Du(`4 zskl(mYPQ4wzuKxnTb)(hC%D|HLs`|h4<)wR#jAGo7N2Uf_&3=0#TG?%v*YGR^zn7n@V8#G2mTUrg{JSfL?1QV!ge0f6#lw<3la@P?Vha5`)E6k1WinQ^QSNIYqowCB3j1gf!v`>ahBI#r9$NuE7HnZyjhP|6!{$85z#HE9OW#@MH?Fefd<^0xy#jos z->v4R@B4IsY+KYWwB4nk33-7!h8jN1=i!gFW65>V?x?Z=K^ovvm^cZc!&F>D!WF~ z;L*(Y|Dv9A%-~vz%tIR2w&V-xxQFSWN*7h>_)eyMusvT$^QcOL_hZ1TN)c@bn>xn8 z=NS|7&9~5p)0A)Lr=5Nc#|iSeMCi1uk#I6;vn}*><^GanwwB|5TGe%hjFT41_5Fid zB0rtrSNkK9!egwN$gs7!106H0Z4lZ5|EW>$`1kD0Pj^=O|-u zSm*wb9dZqYK8=*YpjXzPQN~y~#>lji27jGRJ{@44jL}NsA)E6lMM_^}`_Q&)-xxk4 zA$4?!Z^QUmGLL&_4`ka@-kJ&JUM2UXdhM6<+=`YNs(kuMTH>am_QU^|>tn<1N8FIO z3hlp1wSOntzjLVlEc5Vt!|lI7w*Mxt{V7j(3UyWu>4sM)+kci$sQKZc_WAaKARcvS zmu9itxYwWQTQi2N61!v@Bl28*RVL=QV3pTcKamz43h)>;c+q zw9EE#3^zx^K8cMz!)@P%w(pW{rw_!sw)xsVTD3i*X!O(a>r=!1+D{Afg^_M({|WaB z`|i)0DqHYzu$mgfbp{MJW#v0H(uDg0Xx80)WAEVP4Y3o@ybZcF~xwc zvYj7+Ea=PWc<-oo)GB{20N;l`UCDhr&<@Y1!x${$YHv!R9knCcvE)4RS#lov+^0i6 zRkcIUwer32g&-e}r7{LtZx{A?(q|cp&wcZPvdy|`vyL%bCqJZYIZoRJAGVNwMeXn& zZDrRT+H~5ufa9NXMfds*?R(hQXM$p1AICwxxCQZ^umybXEc`9T;r@C2 zLVt;=bqcxeptV@sUsA?Ckn3`Ts9(=Ap5Qr%Tk;dAhma5Fkm!>~YCC%?(%Jkt+Cb6` zS)y-$zlL@->79R~O>3)ADpXWZK{iu1>SLWs*Et1`WuXRFSj4cWA9D}Q?u^pyG;sNDfy`~CVk4Sse> zQ#OAQeC;nJ*zXZ1rY2j<;bZgpwAk?TKx(SBJa+EqUxfWQ*YoOBtK3gb8PQ&FZdbHy z?-ia;<4Br6#rdEWPHCpi`Z?zt479BXz5(Bv`&`b8nTQoj4J#i+U*)-$NoK%i%=k_8 zfAWBHhMK;4sNGZ8Zt@86N#wpvZ%B{_8So(eJ|0{Yf;_;7X;A}qaPT#uf%c?fHHUk9 z`TU~L@N6*4}ebZd0dsg?Bjs9UgV*CHAx`mp@MdSC zk}30+`s7-3a@gPIdBI`1ZiHN47?NvD@w})qn~&X!7;^#o3HT5HZu}ple5;(vQodET zfwZGhcRH?CLf8)430t9|nE@&oRM z`_mTJH#px<*{?mJ=KRIrz`xVAAb>r{WmTib|ay|jh3i@Q#EYZvtGBWmrTVVaO> z3TqFyofuwwU|h`kd#+P_Qq`vopJ|_?tNDeCxUQlfa7%q_5{pl853~24^VwUxvtD%+{i9AOo&vq>F?1?=4M_w(>UnKi%i=FLUZw187a<7m)&z9cd zPAd9Suh6fx|bS>!6JFcup$Ab-Ommct;=S{3}t{j7dLwEl{5B<@>KN zjuacYFUpa6skO-Xq)?AM3vwPl|LXYr`TSe??2vmtKI`XLcZup=e`yJ%&stX@pO?se z)!rE{#=zXeRb;e)$B8_BUdE^aqs^Lxc<`(DllJEPhvZtxHI{%c?D75@kN5vT-Zwj= z)ESTx?Ez;F$|x!K<}v^AxX1qz@IS2hUo7`q!Z$ze*%iiX#fsm1jt|erh3WUxj>x(0 zC32m{5UcEv;qBvu4^*p}X$$%eKWmwzo8F#@3wbU}t`S{j(Z`}}wA2PWit>Wx>w61x z;f6OyGe@ZTaqjD2KF;M%q74|zlkPnOotl&=vW47FlC9Jetz$x>b$jIc^uu&!s#&b&Fct;v7LU^6)&9*B6?cWs+CR<^C%AZ(Ns@dq0(&CP+DP zUSgvsr%uZ0X6~znoUXOb)juv&{bMfjvVYL_f9&{h|EN;(sgQmi;-(S(Lyi@w)6ls# zwuI}VdqZ+R>UvAp+g!bPlRQs9Ma?;}+^I^QlPFKsZ~SGP1YZm5d?ABtuUA`9bB9|| z&Uw8JcH_8~d^CwXsWx|T9qd|tHeb88#Hy`dpC7Ez>=I*rUaMN4r;I}BHu)V8xrPgW zBWkp{jh909wdr2X*AB`^nAY~nif6X%fm{mn`ksIMsFVTc^{dppKF1a2LHxXVR=^vZ z#;QHdJnyw>aCrY|k@7V;*S~(SaGn}6NQz48IOpgo?}k9O9PcW*M>D9(V!jl{;8&F(KmDeP+v!JS^W0M+ z^kR$pRKq`3$yw1iq`z#V%3iphKBl4NcE#p3yvFn`vz$kB=b7=FfRW?t4uL5!^)t2YEro?v2b&>eKBiAVV zhp}{gT8RP0`?JU z%fng8gKE`okzR!HX_s5hIYJ%0Nwi8?al8s)oYIr+C}#!vi7{%I{3b&b=?#6J&3>aL z*30yPRcd@nhgqkir`yMblI>$S|EGgDQIVE%(3ATxw%uWaFBbQx!p=-D#yHQlj`HGk zp8Kx~d-I3pMn>F|C!I&VxMAd;aOwj3%ypXb>AsA6^xMq^+eSOVbNh4O^Wv?-xOuQh zu2qcB0gqLtrHq(%=6jx9;@J~@!Jm5P@f=s!OKUOh*x|I(RN7dj{MMIasy(#_BVPJb zOn>2U`U!>fW4-j;JNo6|TG{8%Fm26nTD_3=LN6`Xw%%cyNyBMMkS12+y&qQzT})<& z-U*q%*kXRZD?ESuUG;qI+0O?G&nwSTdeY;OiShc!MkV6>!ZkfFoJqf=hq{?yrn8{NjiT@<$e6! zvt@@k;pmk?x#u7K|4ptH&xu7HIq?U*_HO z%l4sn&n?>x=aKD~&Li6g&Li9VM#z@$-h)lzyL;Z1{#l+h7ni5Gp5heB8;i16E4oFh z#2V|XYbBpw`2Oe1`F!mApC|ad^8L@R!}GDAm(L5&NcTcXbBXl}u8|=QDbdUA!Ww@V z@zU3ip#K}*9?1arcpGW>?P+(Bp0-Cv<_$C|Sf^k$AooKOA03Gg$TRT9FI>)vN7cC{ zA%2PL89A4*CN%tw7&+!{dO9r3U%E!_0LHZgy_$8n=kw<4uW9-cJ7|8y3YxF>3iDa_ z4EKtG$BoQycw;!{=7#c_hkLlj$$VVb3>dHW{zZOk&WpK(FCXWh>V5f`XL1Ab#IkwL z=?7RoTpMU#V1>9Yl38zsU?0MA?aM2N`=NOY-&l5z{ipK}scu3w)p4fpB(L^jt?+3Sx^Ihn}i`gsOH|IEcFJEpH52%+t( z7oX|xS+x4}ntR{uUvvBSPQP~dn$!0@c4z;c8@_k?&MgD|s~3Fl^uVfEe>_~*-?!<` z)Azo(rvGj{ySx6|{rxSI`#;;arvKTxy3=pYyQqKul<%ERhFABWsjcgO4ZO4N{(gT@ zH07Uv?4Ew>u_yYix*zu6bMI59pY8i>Kc6KR;n}9A`hOBm_Ad+@{h3R~pM3Gfd;61* zKXsbV;)|a;{n`4bPG`QUpInH0=DT+b?kDIcUku;dpLuxVN%A6diGGs&B`@m1?wr z)$_H~QmYDaeu+ijcC%F_&&$9kvF@55HJdFx%k{)fR<&G{*yjf2+|cdwOOwm2XqxXH zK}>$9nQAn{1wK4ra3Xl3X_bJD%e*yuCzR6XTxtfLKQRokzJd z!g9|*wl)G70c6|{Utvxd{uk#%kZwld9sO{g-zw&rcAaZ*EBGAokeG$EGdO<}03J%J zHIoc{5uIn5nx#)g-)-FJ&&he)Ny4xv#gq29P&Pk%hd8EB`W$@ST3d&{kJjf+*5V5d zQ_I#?R~F7KZgaQ6hd~T)2Mx^*q~=*%hc)GTyya}`8$4E{zAwdgvOb=F7%iH)ruP$F zzsuI;{KPWQ@{l_nv{a6ur4qDMd;l$(iocDP&-!T56%COB4NLfa2A=tDX1~ts`ZX11 zdA7Vj7v!}$Sa_dM@0VoDLy3nZPq{ypZR6Zb#R&QB}e)?Z7|J&&Qc%PcP_3`kc zvv{~7&u=5tfrjc4G*p9zXFh<2roWMf4=EZ(tNKkJ|7hQe#Vz?Lcv8lBmvi#dqwzPK zYw)Esor~tgRg&g|`be7FJerg9ay|YK&tvD~@V~C~m!^$znCnF2qI`3a@V)~< zyh_2Sf-wcR$haF20If3)^w$2GSP1Q3VDn%?OD#}#W%Pd#|5e`@f1r@!&o9jB*P0zNs|A3Ob* z)9G6K^f$kI&*_#`ubsXGW6n2w-s}ICW}SYrJl6j&eV;kK{+Z*aKjQr5^uK9S`@jFj zJ^laE(s%j?`OnBP>3jK4_n+MKV1MTN#*>*(R-b&j)k*x=6CwqP$8l#__zX zF4NsPKN#<_jJTAa9X6L+lp)U@^V?G1TKettxfWf7@@nKaU-r4hX&JM~y)a>!W*Or9 zJLVU~_gH}p_X>dy#xL>5ZTeLI30@m1`F&U?$}tAxCC^8dh?}h%YoGkCVMP4Ks?K?P zZQ)1H^40+4_kdv=vgMo ztcv|I%|3{CDer8UCbs9VlzXa{T0*WpzF~iq`yhR1t2o!k^HqG$GgeoolJ+E#vJKeZ zS+M_O$F<}u_3V<$63R_1V|&`S!+u_>$}ra3<(Gc0{7PdoZ0S-t-#*%$Z&MG8AjeA+ zt8Ejp<)!G4<%s=)scWo)jAsP0OJ1rvAn8Bb=C+@6oY?-FcV?4qqwMAQpYwEry1{mP zW7rbs5$Y5PZ0>*yF?1AHajK;sJfKOH-?Dww*i(Ca<>25$8rzUfW-OpTD!wYj=8{JQrDL z_f2SbNR2hJ-QZWD-Q}{qD>!$H_TFvltJse@rYxafk1=Ilh1rrV_w(R~=u_UfvqJ6} z*Y!me=BjKt&r+78x$nB&_4ZwDm-|w#DCm&fOY*iodq{_Fk$mIx@de(E(4X<=(4V(D z|KHP}uJ`$AN_VpJtcZ_?p%FYJ|2$o}#rc@z-95Ix4gNL#c(Fep&TMiQ;{7P8EAQCz z(B_G<%`3e&^ZX0@O;YunOrhPMwm*(`*Id|=pNMu(EcM#`{SRn!v1)TcSAv;qEw-7u z!ZtqnK0oTAbM}v)y2EW8qkO5+1z&2F{7yXQ^_^&PGxcWtHBtv|k>|5@{kjTsTejTa z{vQqLNwdQ|}1g-;2^C-f)Dry`F}nfLi_8_(&xwYZ+Y8B~5-q~N#Rhc>1*yJ6qlC)+mine^9E z%3r$={@RH5t!Dya%Uc1l=*@sw^XGt=I}jK;^Akcla$F0{Q69tl4Xf0C!za1lkl(Hg z2%*Wnc^qr9`DW0}wFCNcPYCgSjy*x(mGE)3+AS9PC%F>QdFJ3wMdKRMXn8b_CtVt8On5YE z8{iu(<~j_||IGKg}KjCgnZnT2t zLaW$>?9BD@tia`p_Srt#YtKQuu4o^xXkSj+g~wy*r^G!zcU-4rKHcN>{ZsA!t@qqH z5CyI$uCndAHK(^;2YtBs&i=Jm+5J6rkOA6BTMHa=i4PoC?P8oe3UU~wdF={w4VAJ$ zyTZ8&H?;9E>`@UHX=>fs&vz0y){b2Wm@)w zi7IUk(nbxWMfz~OQnoK-b@xDy@B!CbX_U`11I)*>JcY9%%zMFzyfU4tQ%9YlCEy9l z7=<`YXv1ZkMj8IIX!H{ye>u-zsolnX8gpn1E1%(7eRj$y#01r_xdA*Ii+3v$2i#i3 zpZ{Wdd5RKSEzaeHZf~=Ki5uY8^E+2!x~8|-Uz0xnZCpRu%e|=HIVaFRZ)fl985n}A(!(WTrrAA!t2V-9PtlqpWe7RD&#_Lax7Q04|aZ~1j~iSx7isB>iOeCMV5#ZE@ktj7NgJM(gJCld%r z-#TB;Hh6W=57)v8rw|8dBAvIPBYQ6{b@p65&!bcN;v4e*v(!SJr5-2OpflbcYF)*( z^vTH+a|2=)jAx9E#WLE~>EsXBT4Ey8$8VNU{zZBK{`-9n^g9yJo2(-JkCr?`4w^hY z^`P+mhW3qc4^`ZoUzYzbFoWlQyzfU>gC>64=M~5M)*i>NnZo-HDcAG@xHlkw;?-&m zJt}pv-D)*kt)E4b1KeLGE;)Q+gVv7w_<*=1cS7ce?W~4A(2k7ep7Ydhm+_#M_zu5G z;TD@kXw&C;E+@jWHq2lIG#iQpK1m4 zm=!RZETOl^J!(PY*XWPdEOq8klYBM~t24^#dlNd(9A%yR&DUT182o-d;~o&s``?Ci zT+h{vU-bC%pidq>OJBIh05X>6`x32I5!x|Iol7t0x%7CeT&HH6O4VMOGT-x%l$-b6 zthdyE*=TBi)mb_M+NpfH-qHhhPVIHo^uumW*W}(;?(cn1@EyizAu7|{SE%~d zDde#{KViIPGEY$E;Xa2zj`vY{UnbXFgGjqn#$vA$r4xWRAx#!E<9c{1#y0-H`21rsdpS zDSZI&;bY!_+*f(~ChTJP1b?QTk#md*`Q0Ebk+zGKz32MfJ={}+F}a|d zh5ytl7FWsdtz_p9|3_D0Ux0tVO4Z>{aDR4QQ|AlV&$#ETy{^c4CH#C|<9I-uX&@Fb z-mr`1zJ?XfgTVs`N4COk*fhp}u3`J7o_+oNR&gvSI`iIH=oQZ5^Q7<6cgi)gYmsg@ z&!)!b+1#7Rxk`TXUQc(p*Wq1jAZ>*qi*KNv>mY~SnVmA84P`pqjrTuEWM7#sLrEoyU`jflGPinaALU|PX0#j6{0SaAG)sA zoS+K}huYP0cDq!&qvvV2zl_j-Q^p~29^R?<-#yQJe;vEU2iI};`Rb7QS9oWQ<+*su z$NSDC&x`oe)}QD3|MNgVY{j+yivjVyF9bvm*Ozdu$MtPoU&ixCaQz$7T=c+jtm^Gs zra$xxDQjs{pc94h@>AY<$)WM`j6AcEk@~{_mn(c9f%^@wS9{<}WgmaDw_t;~KIXNt zNuDK-4Shp%_<2B{5h=9IJKIIOG!`^3!sVTL(;fN0I)>~=`LE@;4{$y7s?y=Nx2aR3 z(Z5DJhzjNi$B1nt$Q?{vZTICCQh3@T_2&=Ob=R3Di zm*+mMuA%!_e)t?mNS)>I@6(rOExhk}IFvhtiU=3gcU=?5tP?z@|Zk;i~tAB$F;jyVuBk)Tv3-ObEBDTz9F&C4MUe>xM%Fh|Kc(+)|Eh3_2~)j{-P53|6?ZT zY%nLdd%iHu;u$}-jsJ1jjeCB_-86BZ>~MGEp5L771mqdS?e|Z!xCbdq?mtOdmz@kKf0<7yRS5)Q-yk;#lr9DBZbJ z@saBr)SZIfP#;9D(-pzaBT?u9zr$LP^$y57l*mY(?Yd%$wX<=GwQKGaYuTJOw1skO z>oH)LIY)X5b$^2Ut5MhWsxHc_9`dToKt>pI3?-`?B`eCzlw(b$l2zryZ08yGR>M;rMc zl{}Nq@uHMt4aNq3o3H`Cei*W4zmRjCxQ{{aq&!1K7GnVueVlFB-!#>V@*ZOhZTcSE z>$vAyeM1i84DPFN-+;0^fpd&8aldovREy&a|HpAJaE><|XNYs0+0JJiR{*IO-GG$$ zP0z2ls3W0Vdk@#Ve-3`X@gC37EO&mT`pSv-l#C(6y37QZa;^s7t8$*55XK%!dkC;z z@_P^XyhrK)UkBZB=;3X`&|qDSg+{rtCxLyzwGaZ zgr1$F?Ab>87e(peb{6_|7xcf*XY2OQ^!n-^)la)sAKk5ZutV`+r{cjb#er*X@q% zE37ky^69&?-tIZ5mv;2yu%iuABt0W(;CdC;ncjZaqv6cEN*9vU8Pz_tYdhPM^4hcP zvUZDhCuDlIfpe-y-#z<3#G)4BhaA`UAC>XL=Vjcm(ixO-!%F8G88@tSUR2}7Tku!u zubI#%`f3e;^wVO1^wAoV+;;$SrCrZjB9D3rAW_xz3w zZHbxQC*Sj2Q3GVe{?Lj0Dj5Sza2sL!4cIC^t4VUKM>^EI8~4???*gR!_ss0|>NVQt^rsrpH zyb7fr>3JIReptmB4?%8m>jwBnh!c~GWsJdjgi6?#FYp^TDSlgZS8wsD_WuuJi%u`L zXg-A4qSK2lntKpibb7G`@D%U{h2IO@RQTPgPA|3qz9!Y_#TLMmsZKAp0KPKS>BSbn zSEM?<*aCP{s?&=tfG2=gDSR<-UEzy>M-{#>)#=3+z~iY-FSY#8d ztm+)wwcp*f0{PSI3*K`*M?QGZqbP^Z8gOsG4s9o0D0eQ>ijvO0owxK@+i&i%n3nMc zZH|$=%bq=pYxbF*s>`4|$!5Fhvg{J?EJ&LbH@&#yfwN+cmCn~>%(2p$Dr1h7&U3z) zgK>XN?grbGz8>TU$k@M;F*@K}75f|LuR7w8DEch<8$y3>RPzB1YCeFmh6$WwGIgH5 zBkdk-fgCetK5NlWs%QUAm$^F{Y>Rpx#n=%}JnHVoeIwt)FQXsM`?3JEv z`i_iCRyvi6FW(|xARmt9(zZ~q0mIZev&uD7+{4-_?N1c<_53eB>NW1exUb{>R_Z+N z`JZvsdJ+gDH4moF1#s4tRdHk$S z!PYH!&Z2+X2wqZVd#`b`RwMBJfV5>?Bc|=*cK{mZdp50daw}+DZa1KgWwGoM zj(-8O-SYU|+Vd0eyIICDE1fcpam-5R7RC1^;Jco>!KSR}vrxyPSud_Nl>ZV_{!1Mo z_uCG|Gjo1yv7JWl)3y=6+1@?VmA=MKKtuW*uJk!(U6IX?nY$r>Q$wNOthcBKVYK5Y z_a~@0=Oao7jO-0|gVKRIr2|!<%dZ1E?)^Ft#eK}D17X}7N)I?!RiorxkFl^WhqP(0 zKN-b)`>K@=@c$iYYZ%k$tc(6F^l%UKuVk#VlJlHW4}K2cjPj2t`{9>+HF#A;TLd2>3f_fN z9`EXuKU=T-*($^HaT!0*7md&sWWAVxdsk(=GxL!2PpL;cXZA=RmG)#W@H*+g_DCJ- z2K02O$I~HYXR4H)X_|euF40fSqh0%yuSvP>r9aDgB8&$OY0na+voa11-_g>}5`HO;W*n|6e-0uRM%RKN$iBp!l zC4`LzY`}fzRgUCoK{uq&a}IroCcW6Kpcmw?j5}d-M^Q%LVZ<7arTz>2yjI3iE1hjh zPp+b#Ndwjj%}eV_@%}+#sj+x;~V70ak4({jeT|WIRQD2?FVH1 zWhB@-=kMRRU-1PaPu9IOY{>ypg%b?n0ksKMkcJU)4{$RX^S7>!*fsi!JHBVne=Z zW`P%*B)!~w&2ujQrfB^RXq7x*>^1WR%Sd?bX8v)Kr?=S6L;UpG%ozM1k-u8sD*x~J z_35hy5_;N>%l|%^H?VcOch*;%a@AcAee-9pzxV3*cYm>Irtbf*m4w(PzY%_={LWj} z;ap0iTsO0Oxh7WvzwJuB*52{^!DIaYOrBAlD#Woy-P^waxBTek`YO8v@0;{4_~)&l z#rqa;c4AAO{~OXMy#H^X%kSpv^1myOjgH(oFgkM8zzVg##=XLefA6iYtw8#f^81`T zbL5?g7HE(BAI}K?tJQik?Q99 zn8o?LfH15Q?wd?@gO&}}gAEbqp36T0n$qBNtwrC_indzCsr6RS6jnIV?P}%}i~TbQ zzhe0VWzGu^-r&eGQifHOY_V>ileVIW=SxyS84re1)2va6R;whn(fUKO#4*;)cZyT( zmPk(F_b=Vv2R2x`-t87AORTCm|L5%@gh(w`ak9-id0W(ZddXsk|2xk$oI9^-w}Q!O zco(v&kSB<=)#+~e9~j^IoN(6Naic@LBpCy}Ef#6#`Lg1quxgOLBykbw*kl!f-s#Ju zPJ8o0hj=JqSe%b0?FQ!?5<$!4|2QS4!nbX)_}_+=%R`R2;yQ-hj=~ezI{6XGr>T40gJYf zGU9$^#w9m4MbO3tmPkytc#hb)e7(i>JGLLczk`jk|Sa;ugqf=y1Z(#Fb zbLS%6>Rb4IYXfC*&X?aEo(wu$Eq;6Uky#<g6EvaC_Ov$HCV}<@K~rs` zaGtzkp+kJtnDtfwI$C4~QTHY*kb_<#eviq$DjTfTvja{PG)}ziMyb!7gRm}Wk$egu z55Ip!KGneolkwZKGAEu`EcLQ{19i_{yT=xSL$ z+PSZJk)(@sYx)+;fz7GsnIXlm$xDizeYbivk#6#7b=?NoV)*t-hS3#4$7TNlPI^gW zz6$*sbrtAYc*`i~hfUY{=y^oa!*4Vd==rBlMV&u>a-ol&&61u1Ey+)YoF6Q|(MQWe zl9mD;sg-5Uk8Zo(M@PG)qd>#+x0N`Lu9)wmp;gjAf2u&k+sy&zE4SR>qhZroG_)mx z&g)H|_`j@udwg6~wf{b6Cdp(P+LJbI#}eSQRH(J!07XkJGKGTW>7=AD?A0k&L@!>a z3X1-!Owzm>8apXTpOg$xC1R0MiXs9ADNkD{PyrEso|)+(rA4jRD80%hzx7>votcwq zD0=VjkNr8XefDGRwfA0Y?e*}rp@rK3eF3i>W&dX6+v;P!cB~%Kj&tJ2<@YVV{3uv> zZEzP?=6|=q--f0kZ8)-|B7eu{XCE~tcYVXmqYYjE=Mt{_iwnx~+v+cqb~ssYTomSK zydi6PV>8dpf27{S6(`HMLbyDg^QE#L9jTN{4FbJKSH~b(k@y*Cj+OG)Gp+swmkmrvixUn zxG0Z%Gl_P!bGs^%)F$MicC1}dm9M&KF7NpU*W2QtU08!ElGHZjqc(l_`ce5m-9&Xt z`!H^3o1GZiwimuzmT$UYuCHz1=eGIV^_lNg?t>Dzo&EJu z`I+Cnl;H;c{|lc4Tvs|(lppW`>;Pkf>I2Mv@%7{KuYBixh9BeufSqBXt+c078*s)N z!oSpaw6k-}aru_xui!Srj+gRMn;VF}Xeq>F@cW0uIVtPgX0%^8`1*hjF6`N^Zc-e3 z8-6|BF`;Ygu)o-Kp)%*Q_@?G(|7@!E?#eP}iQ42Yifv-Qn&qOa4*TK+*+Ovr!pO-&hsZGyV zxUb8y(VW=ukAMu6P#enQ>N4`s$_#)uPxWths&Yyzc}A!B8K~VH$e9x>I3VW z!RLdi4t7pddBp2LJ?BEEZ^2%uv)?@2z-1>5f&`VbTCTfIeYFF+?BysMdbtVMRV{|! zj!l)-z{Pmh#JLd1%dX3Ysq8@F85&!H_Zca+A?yfie>WXO&;Nt<`xmhO-x4abd}1r* zxtM4_t>*$eC*+w=Z7yviTnWuWpXIt*t^?A>xu(RBho8KO1UI{{A3B7FTAYRbU5v^+ z4RD}#t~FHnbh-bg0lneH`57huE4$B~G$WIpG@0-x+D9~9pBwbbmU08WJY`XQ?*q-A zgFp7kR3C6{Nvz!+;y;e+I)Unns`Uo|%bRGd0oSwvec#3Taoi4qwWEC+ArE}jp)8AI zv95QkI5z8gj?eHBj=!_Tt^8HW@q7~*Y6-_RH*B>McmUmn%8A-fYL)oAf$SIdKk$)I zS=Z=ryo8im34Ava#rH;1zvDP1adlPzWm7$sXVCnl@?l#CJ#4fOwnC;FL-TyBf)CG- zJBTt}OF`zhKgicx_J{boZhsYDyZ2jsUBADEuCQBze#-q)=6zJAMRTjhY0ZVz`nOd2 z%Q>7$su+z0;RMGIsJra|;1F0^(+@s;<<%eV4=k-l%vv|Fl-kYL(f#n*!X~!C)h@*fFaIwM8_m|?OVL$G|wrZvP*D%a~ z#zfzLls_c*Cf!#Zh3AjEki&dU%KNHu^js;H)#od#uTU1|iY51$Cp9H?l*!zA3-e#< zxsvPoa!%_g^ZJuD&luC+c*ZsTL3+l$5q;7P$-PPURdOGodrR(vbYCO)Wpp2r`*OOk z^~$l&&tW~Npm(s#nl5cP(T}sbYtgFu}{e3Fhm|D+sD%7XfU-%nkJf=S4yahgp z1F>g#&O!bMIc3wt6wSE~KF!BaQ@)Pwe~_<{ z{)hNl+y5|Mi*x2tdbX&3#7uY`XWZ6BIoJZjhTOlWB1X%0+V9?`G|R*uvWS|yc+5|g z#_bB$!DLzOej|Ei&RDvx-$?YaZ7guMl5hoc>~85}uPV-ohA6FL37KbwIrL_KaX)#I z_LC=Fz=j8;)-K!r}dfE zS8c5>TQGKI6I{Xx27ykSSM0x|uP&*b56x7DKkJ1ToM z<+n}3wTjrl-+8}Ym|f0(vRjD$#a^A>51+L=qK`S)tG|MBXwNT;>iB%+L<^KBQPvj* zg2{zB_`9=5|Lrf6P-ZALa71W;C1|VRZ)=*{x;^<=7H!>uE5Q!=>pZ(08lNkUF+PMd zPU-lZ@B8<>WBjWUeeNlXGTBp>(fGt^zo%!SxpRN@l?R+Y-B;d6k5OJQkva-jPV!)7 zYk!t4%L!J1`&140j_}ffj(`XE1#DN)PWRRLkJgV+QpatwFy}|7SRWnhN5@xW?YQKc zfsUzP7{EAo7_otl>e#?LTvoldmw0b*LfqQqMu@*!lqA|V-RZ>B?QXr=^kJf}C)KO= z51*&wd}PnFj2z@EvDi|UKVz>w1!w-29_NOAgNI^?_8iBGpt8IEK6oe?zmVwiRwt(B z!_IAHjA)T4^hwzFLn;@V`lW$U)W;~@!`H>AuOtR+)t(!5$?$7tEzYDRqcxSGK9s_P||b%0a%<_7#2FvoB^#ucIR* zCU%9yRq=Sd?eN9APxEng(!PQZc!|9kAzt&{6#HUgpL^grLn-)O-QdDUm=z-$ozh=k z(tSV8+aKaO|KXQ(`G1xxa2NO6>>kkfx!!1x+pFNqb&Uf%cGz+SR0sRJ1z&agKE!4R zU*8FvEcUZMP1^htl~XPLx^pjS+alao(fV<+SL)b7 z<$C{m_QShh(msk2i=>k96?;l;0>09(%G*RoVk~QjF2Z`YOUmizSg4zM&io$sp!EF_ zjGwicV6ljJpv~QeTG06h$Bu~Se+T|k5&g#BdZdHG2`d6FIT1Z<{lp$oT_oBXj|7R_ypZc&>QTt zkZ3)_=y(hLzFGS65Nr+@zw|jF=3WPVyHR3}D2`(doByt{men+R`UrKrXR`;p#!tMY z&lI)2UeT8C41xW}=vtwM#;m|??K-<=6D>t-AfDOxIo5nVW%VG_#R2s)qcpRVQaa=@e$!~K{4Ks%0yfp!^f?g8FGM;iLr@Gxo*iS`q z%$PlVced1arkk2{6!7l$M8LgePJPJ+A%}MP<&T=^Zx!9Js+&jm zv7!%;z4-pHzcxH{zWn?9!2OFa7Gs@V{o>%ktyI3>mjdd1;0 zPt$&-;n2lJ7JWPHMz;Hl)irNMIEEX+e>wSn_U09TM^p`{65+WUWfRZCacp0 zFR(`10ytO5zbN-wdhh-3**YISn|QmsiniH^E7h0ialQSwJb}G>os0E8BV#*JVjE+x z=%sn~jTZ}XNVvWTuUp-2lHT7+--Fmws+*lA)!-fn-HB*7`ycsthOPE#Vc2g_*>AXJ z^bI!)vs)*R3GfZ6Dp^0#^`|ZT5@Bm^avmVH<9G z<3s!6I%?YrU;eXSEbiG8QD#EVPn3HGzQr}&kM)CKoMWF#)L!sAC*wP0nyiz8q&tU%QxCP!@=|$Zc2S9zmM1Zq4^F=zCFm7 zLB0w3XNSr6rsR7Z`J%`-Cf_IdRJ6nO=lvb>M)lhHGvrsuZ{>Hw_Q$Hs-DHPzHz}2C z7}J=&$qw)p|2B+CF)#Ln)O9NLi+ww>Z}L`#sW%3{dZ9Q5w{bh-`MapDZQeRh|J+Jz z%L6X}*Sj>X$7Mbu1|<7G?s7LUebtfs$qO3i;pe4{a2{OL4x5?prm^(|CCE znDJBao#wDn3mS9HBcbeGp4<5))UIhiG}Y(MHPu>5|24~0=^vPCg{)hi%|7P&^_|6e zUYQ2&Z{&IY>PMc)1`N#Cv zIi+*lqW<>z`b%@!tZB$@?Q3>>dB5p)6M(7R?P85FCpNQQP!s&VQJW?yb@y>8%_Ct< z=Sh2h$9s3TTgSM;u^rh5z1OBIq&;Ix+jA8Bn+xzqdFLLZEksW~#IddtjqcF3Y2%Q! ziTQz>9|?Vv#wvOz%`_R4TWO6lj1%^|UX53JSeq=zS1BUi{i zIgWh-VJte`tuzPBj9yPit3q73aE96#f=`Gjjc=lh{rQjOHf=26^KHHuSzhePE&9AL zuX(LH*l>l7!dxi+OY=A2&4tyJcNFutSHaIWtqZLjZ*v9v4J!WA$bKg-a@ZfT9m^Hu zAXKlG$#VRg2`J~QpmV6dO;%G*P3&Z!Icj1<|EM1***`Nqf0+L7wb9>C zJ3*@vzSI#baRTTA=tYA@0NqV%&_Vy64%su-6>nePB;`**d!k)K_KJ;rHBNu#UszM_ z#rl=dG=E6@(8+qw@LiHgp%1h9tc=@fH@p7!fo3dij*Mx4=QPS4`khV^iwzAI- zuf0dD2~Dm!8EZn5+iN2>tmeO$!;g<|94+9D{pp;CJCHGYkdVnMSrX4_uMNTv*R*Cc_5fCa^fY1Qzgp6g7GTe()um zra83EjT-Z^pFo?eb*^2Hvb8TNz%8KmxOOO$P1%iO%=jK^{~k?0*?U|Mp3gk5;dzS8 zZ_NAMLR;>r*6|3?j@w6Pvd~RU(Rh6rxa_AN<3;*WNxNUbI!bNuujhkO*LYbw_4*_0 zXJR;9Yhhe7bzD@2nVz@n3+rN;&}>AF0-z3w*g^4-e9w;~1J|Qt){}Ykst%4)S+B-vBFG`!OcU zqH(Dq9ySCTsW>ix(-#FsSIBrk&bnIsEMM_H<8e95STgzBq-}_^8cd~lZw@82jNs!H zarhXYpk;!K7(Y&_fnC8KqIptd(2i3gXoJQLC2c~xW74LxeQkPIaO5M@CicNBJQ(zr zJ$_-y^V+A*QTUQ9;>-2Y<{uA(FW-=QPx`>U)<^3k^;*yPk}R(C9==rg_R+1+X@5b$ zmynOoIsJM4{xH2CLDxSDKEa3NwYQpT86}I-ip|A6ZZdq(y>@vn-Yfh-O3Nz48O-rb zF8s(uQXOth3VcwJzlVP+OZEl>@)LvLl1{soamW&BP3QULa2!nU8{%R13f~5ux?nm5 zee;7@+b-w5*x_}U|CN7O_UrMo1lw`X7xil@d~>V9PzT`)C}MZyYNEs&sIIqCaoV%! z-Q|`l#8)@e;(VX#cnfm9acq;k1-4O?kM{5I;ymni%)2uuSIBsVZRl=fvhNYh!^E@%UtuVgA3^U>(}(S;5i`^`4zz= zqKdMSJoq0C=Cr(qkFxnJwszaD)~iw7T!q#&V$xN@Zc(&~J>(RaF11u|4ch zOUEkj=^t+$y|zJa^gUTSKm!%l;Y=s-675V|Kwj|$X)F6R^o@62N#FM_>*4-;_yHJ| zDIMSSOV4RJ&42CD|KMza=LP61g2`+?|LWp1J+%9CQs)Hl(diDJe|W!0-tW_J%ht=Y zC4R;L7jvqH%O~aAVfHJieUy2$H|9!i59oWe z{QR%zAH0V=arYPWoIrnhU4-9!k&U5^6~o}jG=a-Rfy@1S^xg`;VZ5GM#~;N*#*wE4 z-%Y{yu;4rJ9Qc0HG1l-m15Yv~)M z6_obgVyc18q5OB#)tWBxEk3AK7imF@VjP}>cJS<{2p?q8T^sCrk25i}m&Ck9m^_(yaKkM$+YtBXg z0zV7CwJM|e*JIWD^zNbbKkKQK)c?fpB2T4x)T{FUOdBl0!A(*}gkioIJbReOOla8C zm|wkkSbp`1cd=#`^G@>dtA>wXjsN$c$eEg4e}2ClWDLf{rt!^aU;2Q}&jtrIZ=cq@ zJ&zyp_V*1Atv5J~EM_LP?Wtc69%}0>o)-WoSIC*mI1gtuj~Mp+I0GNPw7an1^7#np zUz~?{I2`f*wYm#sDIF_e0{$N>_@(=s$?KRUL!a3$Q|M#FSg#-$jW{|_-V_}5Vy%08 zgDqE#hqI(O>Je4t@Q_uLoI=;pe~BZ3E5u z7nYNByP<@JDe+0+e)>K@V_hTXA~pVV5udz6{Ox9S-3u^JhSc5jYkfw={ZQIgbxNYi zwJD{-vj@-?D}ghs2G{laO>icB4sRpglh5?%JI*cMmhV`{x}sVpomM>ze@~}F(R!D% zdw47mx7Vm(8wDPZrvwfb@U#tn$1~Y)ahVJAuwUNGa3I`Ht}DRd2Lgu?yhmvK@cuW4 zdH1QwrrJdim_?1;x!NZiDuL5SO5imA*BYl7PI`UGPNA}GN)6%jVarQ-8yOy(eQ-Jf zv_E)srOzbGn6_Nw+%9=AudcT>th{*&xLjLagiC|K#e>P2KA8Mw7?>o6fk`Pm@I3lt zQ{8%VaSecuPgUP$=4Y+gW;f()c7uJi@AeT78mIS8hnrNZagK2a@bud&V{bzrpjUuB z4d>9nS0hc=_w2hFC3%c+syDC#rg~Ahdwv< z&ddRqx4EoEdD#BD9$ZpIxJ(eZcr@7CoQK9GgR(k6>t)41bp8|YwXAe3hKgb8!(LJ* z^kb#y2zu-5f0Ze&1Mg98nU>#h48;p+T)i?%;ck2Y-0vJ5EW+J~x3Hbi`{V-lk&S!s z@d`fHqwuqibFVAe1_^PHIL2jv7VCJl5xU0NdioFlU!&A({{OG$_zdSeA^R5iA@%=04kgy{Svt!480+J$qw!dfg%175C}KEX315ISp>I!ZgYWO`VZjT`k!yKJhnY~uUeP|?Xa_^hxeE(pVjN;TJYW;eTXuMzP*6HvFwh%cVOPqJMgPD z=_WUdZ;2^6tPd;`r#hc!SnE1prgmZeJxg#IN&S10u9r!jAD22=Z!X2W2ghHX0k4BqCU)v1mg%k`+wwb3oE`JK$k-nl62Wj_mjuy}SW!3?pl{ol4f zqrde)=I58|C5eVZd`z0N(A!)V5SgCR{wDa`oNx^`Qz7C{qUM#^RqRW@lYOfo1_t~L zLDm@Ia_aJHaON>x%htai)iS9LdbgVB^VL4N6#Rj=Q@cX!k0Z`DVC`J?dWOmC62Ead z!3jRC$}$?Z@HLeLjCgHZnEwsr1A-5TE!+1D#{y+sK$(ycz+MyM^ujY5#^0cKfG5@) zZ*RN=`$M9O=PcqU#mpX-2Zz#f-a|0q7{rJ*LNKZI!DO+(1pNj~*2uXJ-~kwPh-|JD z2G|!aen#^u^MIT7I&SCFa^7&}2rciu6!HUEPoOKu@iwV#7s_6*eEk3nzQO%m%rsvO z_yWp1lYMjP7%giA4p)j?=Vp2aJn(KB^NB;{WXm;78UBCZI2|ls(dY81BA$&CJPXmc z10pj6{~nYxbx&@}JU!tH;thLkzUUb(!&Y9rw0#Z-=i@CKTG{7 zhu=BS7;*Ls%Cf(+r3^*mc&7XZ8PI}fv@R;1FPHbfe|k{XqlNijzXyFqnr|XshV5W2 z@tn5Zq%7>~A*Yk}^q3P&d_Px3`D08gbkp8CFFTvpd*WB3DK{oO+HarMxHeJv zMq9zI6FLns2mB-QVEw)E=^|asx>Si~w*Azx%R9%?oEt-Q#8}we0Y1>vLtk_}jP-1D z$FY`GtBd#^mfh-FOmos4mcE|NdKX&%uwL}WZ=rfeFdeE6TCg?6|1`EJ$Ff>+UZcl^ zU>G8}Y808nT7al;7LJS z%vGICbA#uC52qln541;BzmWYJ_5V0a^Fz3Y-Z0Aqs89d#G-SR>j%R%3(^}{4I=Ws@ z{RR)7B)TZ6^uDe4+MfPi*vCCJc&OHvax5pmM9QH(`?V0!)Ucm8Ps&?F*Qk^?jmn!g zOnI+RdES4&8EdN7C@uS*sha6}52c##73nJI^r!3OJd$v{DuuXFM{5}I)5tlXOxt2SY(@6$FmZ1 z2Qiu=c9+C-MjJcaU!9l9owp^6iI{OZLN2zWp$i z-c0nj-VcwX_f@nfR{8eCa8%ciHic4}Hh7HpMr|tq-s-way)XU(dkoP5e72g>Yx!&N zO(wcAJF(}U z4hua{Y3p<1v#CtjbbJN0Rdh3t%VhYYkUSrk@1Ljd(6iTN;!Gt5UkV&o`c0xgYcj<1 z3T|O92VdH2d@v1)Iw7YCnw{)t0Jjd*N@`@aFf(LKVUmm=@b0okH-*H|6I1C4O)B~Nb{sIlwvNY^RpHSL9$WjR`W3jrmCpO^(@F!>L9}++^T2!33LEL$p((wQci8JWIAXa(?RHOIm%DA(Q}sz zzmi_Qzj7bjbRQM(=9}gx46N+l`elv<6AxJfrqG#@QL}7j^CO`Tz9Og zJgzY??0|me{o#fWL!7+#_mdl2-xRixKxo)FCDA&w`}cnxER%M%V zFwy9md^SWhYa+$AgP;|0HbreBx*{#`f!^Bsg1q*bC$zm;CtV@;_hJp7Am>A%>06)h zotr`b4f_z`E6OGQg5bA~W7m1-HbJ7_fj7Yfd|h_BtRt*>c^YrR3Du%?6gduBBhmPs zLfbdEo=p94M^T;{j3e$4E*{hH2%$c0yJr{9saX9%qLHe;3PfwvL3uY`h<^Xf}UX%=Qx00 zC*p!=-UxHePPzIV88C08?*wzmf1_(P%x%_pCYU$6;HenqwDtt!X!}~`hb-#52Xnt1 zy0neKWY^fBTF*3$!Le`k`GvpT|Gi7M`yK2v7>h)T*TbOjK8-5%mMQ!l@WBwgV15rg zQylcbFu2gB$8bn&MB%}#)sIBLkC`#g_D6*+eFmBR!V{jo8tig20i~MCEXD(l!$_=V zBhOWBKe5FND1P*Nyu*Kyc$2$fS5a3B?`nwt zYS^XEmHs@aLp^h)_(s=HDTTR6BbV_ZM zYH7pr)8I$$)MsLWn9#oIq7EnIq5II*l*oQ*jj8dS`$MMqagLQa)aJ?(n=9CQ-8!a+ z|M6_D9v65Z-pWXvC5sHS#%Fi+S*7i+^jQ$KLwK){kB0yA<9ZI8d>$ibN;G!Ug?76` zsY~FWuEwX!RA?{s)o3o%s5ih5u?^H-g6sR`eMa(zB<~Z)$onYriXGN3Bwx^HhvnrB ziXGMtDI4Y9%lqdR7dBX+55Yg(WEr`eY_njKg+6+AS%^E+aB_;}Y+k>Y!8R+=%Kb+F z-*2qC#5U_Ts{c;Vr$lF?oHIBE>hk>R!NJ$yXCNXnBdjBb9@k^{8CmOx!v&OiF=+AR z8*U}x)7Z=#)SrsnxYQf&`1Bj@8M}&Swx32h^j|pGmc8p68SO(XxGEb=t|VBmWIw>b zXY>PW{B7b_VYbAVMcp;Fwh;{yjj8F(6pg8@`Br)?_I>OvlW*_gegn5du@tSDO=Cl` z<}%Dfi}F{+(9cv3=bz9eEQQCJO1)MKe6(Qyq028XkyUzg6yJEBrZ7*N-OIJSRO2(f zyIADNfA`rwV}0EHxRxh$J+AF4{!{eO(vNGI8U95X@l214etZJ_wiU~TSq_(3StItc z(=%GnO3z~z{;8Dvy~p)j{)nerAzp(v4rG-9U6Peog=MokVlX z=Q{&&fj}deLT6#`uZi8_f~JeMJrbGRcMHqerqDZ#5#s)8{A_kTy?MxU4B0!1an_4_ z7WR$LJU&zh2Dq^AaSwlVyjvyn3ib#gNsGyHd#=VtZvFb{&YGaxb`&)y4ijHv3`4|{&1 zAKOFlI|#nW= z_pJcVZr^Y(wBDfk(vY=OyL%Bme_Ebv=y@(ZUrf)J*!rCcHfAIA{!)5>8NI*U_r8|i zUqSCbL+|7A-muKvi_u)aqOmffD|3^h?d~Kqm9;5v9pxPrRXKYSeH-1#F_ouS?e08U zyGE<#+!-JH<(r4?UD;9L#J~*kyYq9C_=Wf;mSf&)>ht_Je&xwn+TEG}Vp?mx1oYYK zFMO}uP5EaAz;A4FwH}f_6U17`Ynm-~__i7orF<(!^)TL{9PBNj*d})t^i30xakS@t zSf~B@cy;{Hh-W7SKs(iE?SPtD7O!`1mNxE`HUg%H=-sTOUQ_+;WM7`V9%lj;+G%Za z&lwrY=R+3||5caoRE^FgBg5nLQTWirx<&9pxgRstgh7Fg6>HChMAig7h8d|2wueXC zp9mlx{rr3|eqkfkmw(A*{R8gzVJag%vM9&NEcbL>FLWx1$9>vVGv}l(&CQ@a2Qi8m zHmJwe^Ac^xInw{7aw_N_tcgD}F&=YspzkW|7y6Cl!W?h~zPV$b^3KCgQPMa}k0Y%5IvN?l)phIfKT-r1tz_ zaB${&g3>G9k;u{f4nX)LKt6WS>6oP?f7UVg>_`UmUCRv!-FpV>728>p;; zERWg<{RYE&d4FJfCOc`?%B&HepM!lJ{C-Y5L7y2;`EC!N|G>8Gu-%uPLwh3E2RUi1 z)$#DfYa{A9MdmNs_jav5uZC_U%F7V^m==w7>iblF7gOm>!>AdN-Zs5B!qGGMX;Au1dE7Fapj2Msw7q3|GXTJ=+J{MO1gJ z3Nm{~WWYWB(`$P)?MCgNHm%3a+^+dC=u6zbe5HfOfZln}@auf%8Hg`Mbm=F1T>LY|>fnFy9&z{j zj@RRY`ccm``o4XHo*Opepr$pQ2_Ga?)c*|4OVGLKFZM6-Z>#tADD354+HcfkvZvP4 zni#9kRb1c9;}7{?+t=^t=Q#yi58~H6TL#8O$OUznMW#=SO$1DBJU(xvCxozz# zj?p(m<|W21q@E$#V^t1i1w|f-@)VT^AD^Bb5xyah_x*^WCXBOw>w+epqdv>AWZxzF zF*C_@GJ%GysZ!Z-RJPv^3I9Te{VhY=?bg!xe~0;2Pp|5g{_!fy_%z+pK8-B;_u9vB z_WL7#e?8&SG|}~GV7;rrSItDt!dJ1WrURW}l_H=h&C>S`!rgP9ydr z!`%kl;cGD1#BfLKSgd7b<{kZ5!vHtL2Ah>AjzNXM4SNIDwH;LcWazCkj&F3MJSSi6 zFEdk4$m$!SyW#!w1Nvt=>#aBE^tkQC-j)3|twkTF@%x}Yb^ohPtXyaXjILwi#IE#t2rmv<`2DY%$daU7qX$ zLrt}PeMWzK)14lF!Tqkvux&sV_G?p#hORf%!6||lILl&vbHWS6_d+?dgg;S2=Xm|Q zNcyH^?G9U+{wattNwj?d_w53|k)0{y8}i1N=h7?vez=tWbD9q(R;GOjTwW%)JR*7= zY`2WPGKTniGS&%gM^oWz^M|}PXT&dtd=F(Z{lQF%&qKYuBPB17lQ({uKF$**7>1>t zn3n;6J83NZ?R=Hmc?-4k)$)ISuk+UNH~9>7eja0vH6OYuh`(35ms|n67AkkJuSf^| zh}W}CJg$4S{#O=z3G1`c`Z<_!@^geY94%vuGndhn|19Vof}c;cH{40|4t4|;(bW##;kn8RxModr)}rfW zRBk-3%dDfa=g}T()HidPS5h4xru=2~O2hhY#8@$xT=?T=9VwJ(GDY^QZB8XPvLu@uVQ z;GP5B6M9E$&p};QCXZ*p;}jV$(6Fp;%-8v_pJ4gA){pLB887HpUQ2Dgr-9Cgt;kjx z>t4GZyy%cRBJ8_K*P)+5*Fp9Reva*sCq!bp&K&Onnf%jtXuh6fN`i-!vuo2Q_d1K< zvY+yyugD9VfArTG&FAQOy$2$E1bpeRTxX(RA>u)kl{(`2)%XOnN}yWxR8w;mb}{51rRcb5ohXfvrnnv(Ql3 zcM3FGO3&}}lW#yaFTh@DV#uF5x0qHH6m z#}Ms?O_85I@%o7~GA>K&EoUv6^HIgN_Pm~b4l*jbE(U&ic%8~{9XNNvy(zvR*!G|B zi}eGkj?d6PeP1@!t4mC^|5{VM`z2HDrIey{Bc&OX9=^s@t0^^6x{*?x(p*ZjC{3YM zLn%mU85r*ZQb;zS7RV6FeOB`lE=?u7_T`j=vB&OTv^&{BvPX>XHLU&On;xs-yz4gp`5*6=K?1&~;IV>Y=9wJw1BA8vinH)aH72 zahS&uoVRqyxsd1xLyipFUEXWt`{6$t>J3Wg{K-%!P|DIhbQ(PQD)4wlT=-t-07h>{ z${_|E&Jyn6ws#lCB}8Kqo%={AxVOVRaqwft-H!|&+P$DSFXo86a>dtrK%erwfPY)h zHWso<6SSw5-d|3A`DBStd&nve!;?J$ZYQPd2uWV04j(40++O|LY$UlVH#xr1U9Hw1 zxQ}SBDY1?2gJbq&chWaJKScLC==um z`)Rtrh`!ITR^?_8EeikOqpcM01&9TSIf1z_NyTze*5TMl^Jk+wh3=8xIG)Ci`gF;o z+HUH@WpUW;gg<;C$Jx$#YrFALtwV>hj1lqtB>^=7asud(oHYOU{WF9PMjoucGniJ1 zIiMd7i##h_kW&)>5Qj`_RqhAN^%{iyKQMHhltol_MRJZ)%=19KtCEskx7ZV+@?P_lpbpQ5IzkKt-;2!ojKSSt$GXNd6jm*zPVof>lF~236 zn$I+;-A+}H$PPr7IXjch81tcL6UKitEcP`>bNDfi7hnf7yyl{h9*>9qd37>BiaKo# zGq3;nW?38c8c5$+29^-HBI<3x{UVkDM%W(~>U@gh2^H#;u?TQ!~JMN>V z7Y{%l3Vj#4)>562F%i#|Yc)FivA%@3KffAMw$BG2mkoVjk9U28Wu_YoxYIgudq4D8 zKx1(ERBtO{98un9ytWVzquaAE>kzyjH`T$_BZlJNbdmi5{~-J0y&|q@mY)(Inix?s zHp}(cV2{~A|ICPX1NEo5GmZ$TE+Kgg20RAa_Nu`_z4#Y$@~dgB%K$G3p3^;f0-psS&l_V=F8n>sPwcpV)Q1+FUSnpc&jQgrf=sm|xp}iXAu}-*dH|8>8y+M`z#Cs(si2wTapgDa$F^Gp7lWBlqsyHr~d*P^0PC#YdPGwC_Xxll!`fCJhZ{71??d4r3Fwp*b zs6O61>a$PKTGj%2tn~f!B5&~e&toIoek4!-pqy%$|L3 zaAw~!?Q>`l{15g)%D+80^h_0d1J)zZAWXv`uHrEJgMTk#TTwN1k9ZVzQC`_Z?|~)( zz4xbwG~a`D7BpWu^Z0Xf-g&T&Jy@5+ep;v}esn!&OFch=9*)on9=y&Lc%gr{()U*b z#dbub9ee&ix8r6dG|2n3<2!&y;QjaF+GFg+9|Y?!U_C!Z+4ldUZ20u+HQ&GN$^VP8 zVLKN;M%h#T7iFJFWgju#zwBxML)r(nkJE(CjtZTPZ_}90F7hX-rFyPS7QgC~=*s@F z;@W>cweR2@-}40UWJ%V2%~zDH7amg&{N;ak4ar%#vqW_m%YAR~3 zx{=bW^gM8hsh+0mb#$$v^zg-09;GTuhd*7E(*U;LQ|$k+9lBPKYak}ZAAjzx1@Zh! z*6*B8d}NcGf{Z||$(2>7`;EgXmJu8=l$s{jxpdu%@ON}S333qemj(I9Zeu8I>HoIV z=TjDAefQ6`t}M4H)jgWem?-}|*py4&w(25}P?Kn)GMgPf|2JTNTP%B-F~MB!5cL?9xV<(6QI8lznFQDl6Kd6?I!xZ#=9q8sLH#K5}oer+q<4!Un1=e zsNx#@w%i}EO86eC_f_`s)8LeI8`f|o-$pPES!_Snh;Pd`tN|6mmtxPZrT5Sgtx;X>SAVW`3IAQ=Mc(^=%0;G1QHoRA zf1#=NQF@Tlc1pdJZl%;G&lyT-N-0W7N=qo!Q`+{rp;l1x+xd7gSMHRyooZ;^(+gDh z0qE9UpqdU$kl4e1-MXeACA#jVWDyRg3>}X#s+x1wrN8;Z^I^n@YtB7CH36SDx#z!< z7>KH--1FfWy{GF`#EfgAyu1GJ{8wTFLu2hO$XoGlT1MuN`GuT8SOQBg&m2GPU@XY~ z6+Xh3gO8#zt!7?ZFQ-0LBo;U|Qr4qVR!vD+&` zWxX=CVb8aQ{$JyZ+w$KJdVcs>EOC#*qGug*z{4A@D#!1Kc+Y_EW@ch)-1718E*zS!d zz74u6alxIhD;*~e?<3X*S54A#qC*eDUu(OYB^=*tJdxEf&SV4fUyIll0FL)iUaT<@ z>c>B%?cbB{5&HfEl$C&wh34EEYGW<{6)1C{fMOnn<{C9yL%51OO-rrugsy`@pgMZ=J z05`DjADkt9TgpT%D)3`vGTyZ^-eol2;;S_KACecbFUx$mQBCiyGeUX&=k&<%%@iX`gEh&d^rNwM^ymMsuQ35|wt`;+$?*Dd#`ueE{;hRQ( zhrJy1JI|56^(yw4&-6$$!4P!AnaCe+&Xo}?S?3F96OzAH{Cjz8=#L-N>*9wWEUt@w zpIMWnUx2y4Ur$iKq9y$*h0UA`Oy!T+lzy-nW2y4NqHT<4qgJl%mWQl~30nV(7eo1ILPzZx_+GKgu^tzWLXce&2t!aqX|*9PBaTmOdlX?`f>U zk5if6w2%V-?upKK^!`X>HSf=bHAys z%uY1m$8wz;Om-6=zc70O_;I_NZBHwR7d?yl;Va=MpgojagE)ryz!~fN1BY9APkWfs zeo8eoW^*X5p!7C1#G*2-D9XGt8=^96=($FogY+Ds=ZHKj$ie8jR-Pg6vgz5D=Od8G z(DP(@9splW&r{_2Fg@?JALAG}dsSaHU`=$03MJYi4I8})GiV)|VYTEeTKh*BS{6{c zms!?2(fg*De^lazHF$`-sPF*qoU)jH9%=s(tGu@JZ9q)zMCYRw%-57f_E-bM33o=<09m-ckQr>XQD zrMjb1_ot=q$x=7`cm}2J%cTD&untf+wHIa7XSL79`uq&u?{(XP@l-CDfKAc5g0ENY zzod@s>q4|Yg=kO1nWMJ-F6R3ykCi@~4%*|~{Xf<9{~7N~=4HXoCZ_e@t7QKVB=74F zBzCau5ja;v1eaF>)7w% zyYCTRMOQK&yos?dX+zLHKlh8DN_@lfGucv_n{|_7nSlSj$G_I3(k^Uy4i% z##^a@kJEI~$7wb83ZmbU7c@NLwi8~ouTrZVE7j$u*j{5H`*X!y2k&);wDCldk&dG0 zu}a5;$6gFt1T^tR$p>4?5cpbZJ7Q^oZ{&5_LVVKJ1JGRxS*>oBrTr{Hr|}4{uTAdh z1>Hs3$8Og2%3mJPds~~;=HNZz6TnB{$x3a4uLi^(r}j?WVE4EUN#a3m)c31w>%>fd zFbX@-F1K}Q%3*&{s)cB)7PlsWcP)+uJM#qMmoLbUV*L~+JB4VuO5$N#m$x{`2l-+} zqQyBp@uDoAaUW9UL?@MVITfmf^)eCbeihMcRvI!1&6D%kP(NZcCVM|#^oazW#s;dx z>f7wX-)950waVG-hGLuDNG$c1)kp1)r`%}CUXF1@TwUm_u$`Bc%6YzGE)@8m!g}#t zwD)XwEeCN`XXmO?n_ZTRr8mQ$>T9U`W44oTsBUzofH#VEv0p0WF`_G-h&7vaWr81l z=?}jOe{leF<@xXh1L~ts{DJ!UEW^}lbsCmxo#IeBKX_%pUjSu5n!h%!D>K<%x37ttRKC2a5BkhUmy9de>lR{(7(dWR}-hnnP78bpSpUswly~K!p1E zH#x88^&q9sURck^k3)b#iv8hKo0&{C;Z$`%t*tiY%%wmd#o12`uYHEq?A#;m!v5P# z&ovUm0K8Ab?3A-E+~7c#z&@df&sz7Pi4N=`R~9@EbS)4=4n8_^qTBAT z_o%j}ISzI;;rNiYR{H*d9udYV?8%C#4dCsvRBw99N~d$i$+RvkAll$r$B3tM0lSgl zeR~e$Kz*cbAY+)7H{^ae9_!ybIg9Chj#qjX(|buZroFA9TI;f5T@Q^Zvs#>M1t!0v zeXK%t!)6`6mBKCb4e-G;e5QEg=h<}e*x73x6}^-8%a&YOVu7O)@8rDkgufVXO#cEM z34&80UOcY>DaebnS8)B>J`8$bXxjx36n&a|wyja0&1^_yS@Y;z8O6SVHbm(mi-cRhT)CFT6VO1sy}9&1H6u>IL{zTYts=d8Evhujmi1mvNA#~kE5Mf^mYX76NQlzIRAXw+0q(c*rM zF|D;czwveO(u&X)OM$f{SQ7b?x=2XGSwIx=s&_Ig$nbSMc3;w zqqYYMW9GG4x8=suO||>yGosjPpt)C8i!v~!Y$(KLg`h6uM4wL!9|o`nc3bSv@Ko-M(ixg#Nb~s zto_wx|HM4w7M6)&ZwX4iw{)C&*l1jWZyawZ)*&Wts z&ky~}_Ydm+s`**sLBnlEi-W#a#o!kr&HdOb?HiE32BoiurLVvX=r}wh`3^FFv>`VG z{yeCiO;jeUz*$|p1sbc|q^W!V`7uNvK2PFKN&bz-zlL8)%JJ_cN(*QT^&_2lx zwINrTA=)DYpR{VG*4c06x_xmC*!QcUzQZvS4Aq|7xWm)iZ*?&z%00S@VDL%$b}nS_ zyjNuVu?HEn)&OUw@6hXiSUu5?^K5@TL;9G|J}L|uBgFrN9=LtKmRWmzj5qGU^GQCO zsfc5&Z{T~J7kqVxr$fJr?M}*+L$pJSgFe;r^F_`w&eJA-*`PC6$7^SW$QR1!dl~UG z@NWiw1GbNf|IzlJkP(y-9f9v*rYC$bM4Mx)hMozq?mc|aZFJAyq2=VIaUj?ahpl6w z8q!zLWc@oly?(9JA7YwlHsM@dwoLf&GLaYjeuu~@O!3cE0%xqZfGzO$zwRS^gb&7) zlgHc|Py1>u{0(L}W?^B@Rlm=idu&H>&SAd6F7(fG9)WQL%zhzx4#BTaO4Ad=;y_Ab zUQ^p%;&yG|{TwkHY7-l{O@OP{F02t#XpJcMw@c3EH~ZREQPQpoX;-(eT^!TyKFr+> zGIuu|HFx);P4vCi-f-01MW1ezG4kv#lyU;Y@wlaD$Og~f4tE`uk3Ncw5VY_^6*R9? z%ZV;Y#d7SwHjTZk+dY?cT&TY>y@r2&het>0{SW=sGCQrGhW;*=JYyst)b01_wJIcQ z74&rd{q4Q)*lX1+Dz7}D9E0{!?;HiXSfS*nImQCU^QFPTXIajbb^`u2^r$sf!5>j3 z|LyyHXGRGPOT7QaeZ@6zqLu{`oHYH?7hXDGsTMvjN5A%jV*@xNXJ2$m$MGJoUgq=G zf%`NJ!iDqJmtDwZz4O*J_vv{VN$PVGFXoPS<^p@rDjj0Qx1G>Mv^<3t{EeA|4Bsm-#~Of$H`ku?YI8U za(edrXK|cN_KQ4M`gt9{hu&e6Ym5dw7h{gMPhh#)e7%mKeFU2c_Z9tLjh6FY|M+uHyj|%Li?)?AHiqE_O^a<$Qwj#YDekR&`O&9CUe9;v1-Fr#r>FCz{6g z?qi*9MDAI4h4t)v`p3tgbVExujn8^fd|uJw9P#v|=o$X;-!6G}N}drbajUh#-JR%R zU3JXcw4od?PernY^=SgpRtG*xt7v}QF)^k22fK~!vk>PBdO7K2Q9r&dp>^U>PA}Fm zDGTL{Pd4Z5#4Bu5aZ7o*^TUaan%|)E{4oCcb`4*^)_XrN$yEC(?W5F3X}8>Or?idI zPD*J?O_XL)nn5W_scMp`O67(HT>E;;fzR3T>TfP|P=T-Y_xaB7X^xaxv_?eNvyB6M z3YU#u=~#&8GzqeYh8*bfOX#1uG)7hSW*(!Mf2x^fRp|z| zc4-l2p-h8o!CyMT4Yp?5Z(=u>3qP9gmg*o;yWX~n{#7upPRaAWlIN`!eE!lrqx5h> z`(S&&v9F4*bVkzn7ssCGNVrYLzR5TCD~61H*FQP-#WD8JyWm7qy=&8$Q`$>uAEj3* z?WDAw(u0(`D78_FQJO_*Iwi|4`bo1e-jIJqwT)hgd9n^SyS>Ph`TdLnFAQ0OaQ-ts z`m&38Y}!s1`-4UMgGuB59Q{9@aRdBbjPd44dT0Ce%_2U1Gs~xM7BY%DX38k)m>m&W z%fK+>yT4@oUM+dvUGm)Le=70Dm{_TOl86)bb&s;Wjm!t*m!) z$GwAxwzBM?nfXfMA*aGOHexxpnDC30b~hpq%@LFKR>*0=OCi=(FZ*d<#5UX&T8@+5 zcCTJ9t`U8sRVLf0WqT7%ZVk0#e93-;J^g$5C!u9Z(0Ldsdk$nRp8N;pe@o}f`^&^0 zvz6sPbDc)B#kr00M2({SXNqs_v7txlXg$gZ^e9t${4C!Z#Q4Z@ga{veI+#c7q7J6w zbL~dwfZ&1>zlyJyJnt=e4%sVNFY{rmhiNR7n2YrM(TxY_6+UKiUpv94sQAfE!= z?b%Z|`EYNAZ@tm@){&2=7+cnra25Wt5i4 z^*Ty(CB-RCqhwRsf4r$)r}QADzT=1J=<59>0s8Cefd&(M>6Q8Cr(Qh(8aI-9!1d@d zT2t63@TGFTF!+=J@D?S>Ao3)15B&(KwKin z=dX*Nt4f|#$+NddV1GF90sF(zw1HkXcFO*+-8Wvn|HJ(OayE~SJ^$XKjBz+R_KlxF zX4>rjko|b-bKrdw5ciVS6-pUO+vGkiX#=I}DP2p+rc_I*hSK2=75)07uB}R+QGqXo z>=E^Wj)>n|JP+zs)IZ`Yw%Y66meHE8upxh>_Qfb4zJrG@6L}TZoQRcj$BR!S(DjGs zK62nw_e%SH^3f@@pY3btaS<;Pcz0Y<^UGeGj#@Q>%V2z?wACjgJyqKHIc_8E2i!(l zBTL#ip4+JXA2<8jhIf0yUm8IE=cj&&aJkd<^gA#ANeP{+{slTW?xS;;YCQJv%&=OV z;8GvmN^8UrI+vc`E_oh8=O!97t&?bRcE>dyuQSREdtXJe+3|2#sYb%NOg2M!=ixEV zB{v8jclq#m_5To$m7M7-3%vC4v_{rB5!f+wJQBL&p20&iB1ErJdUw33-lp^_rTvul zNqU{qgOs*W%1~NFsh-khl%|X?%I9@#Vv)~b4C#LVJs4LlpW6!goGIfDo|ndb<4>?J zcDud8^EQ}`99ubJ)A-wc1sPrUPxKiwN4l zI5T3sBxjy={0=_c_Zp99-=Z~T&a`meJ5ybKmG*u7f{sa&PmgbOD(U$S=w(c7a2o9x z>-Sft8=ZFs2iu>5U$8Gf%V)B^nN6%G2U#$5$buXjVx41JcR8rz29%wq@l&CEO3lr8 z(>{88pjn@tE`e;5{YkD~)^!z&9s24iR_C2s`?Q+9b8`CJIx*7gHM2^vi{%w#iOCQp@54ml{K8(`)R37~p zFa4lJj}Mc2#dx|gn(&~@Xe*4#}e(YR2((<$9aZM5hc zbRwRo^3nf<+3GF}s=Q6#``Rl8Dm_^{J=eyyU#;NHkGu`ov(M^#bPSWkHf`7axouib zw`7~PGb>5?>AO90ooD|LF7wJG+*=~?PwW$QzL=C#CguG7$HlxcOXr#FE9*af z-xE^SWGQP-Nm>2AymO?iDZa9P@B6+?%9MQH#zVFvbSy3q~UQ*Uie0k$i)^uN4KlFW1N?FsTtoo9&Hv96{OIb5~ zW!>WYe!Y}6L&{oIQdXNU?;MhoZq1<_?=rtt^;`l z=G{X-*0_kZb-HSCV^lu$**rfds0X;Nh>pHul-B=$`p0rcHZPMsWh8iKqStC^jY+n+ zbHCT(w$pd;7dTg_q&8^VyG*_>e9?ePws0K4W!Icf8i~XgR>aU@?2PofRN(U%K`D|^o+h;VsWzjv_h?obFbfa4#_?nV{ap^Fd;3zQ z4p*A$0HrjI+bl{%kf=1Jcj>;C-b1dWqPNnxfbPo>y|)^%oT@QCM00XHHp~h5#-neA z7;MueHrV@(w?4DSc+UfE%f4m3u@1h^SO?--pAYozjT3v=rW0cTU9Zh|7i=-YTIa6I z_3(-J(P7GqF4w-8JbdwRrBZMOvV}+qu2elXJgyAhUDUhuaAkj{$K6l30vUWbv&L}* zS6(l{72p(b1@cPMF5-%r$rvW#3iZzj;f#s!B^+!#Fa%HH{~De=@T1}JBv_(Tc`UqH zQDLh0ZZlLL5zM>j{$WbX2$w8MPhX@aTjf5vLX>0hLH~{T$6IJz>hnQwp0mtk zv&8npIr~ai>-p)iPS``o+P=GJ@1dgIqKk41ujwfNj~olByMTizDHDBu(`BX_ zy@hHQoCR(&Umsn|xDS1IT06^5EW{^)e}y{aZ9pE#cPcr)IBWtDONVvj^TrvC;JX6} zbEUhiM*m+*XDZ*G^hxf27t0E-9nJn+**4MB1H!(RXiC#Qns%?P0pGtcYl$CIz=}4U zOIk($wChK#Taj;-n2>UY&+_B1{YcZoObgbe+zC3)DtsdH74MsVq-k@_+cdCT{o2W$ zRClM_NHDl|a)Ud^cV2Y+L@k3{TVXo^DSugwwmVoxb@=<>;g`36;N7$!j33h+e-HIz zZJ5LG;5d-^I-)I5&V?tYa%;k~2dYod*9+wNe7Vk+t8u)(o+reU0xvBKLl~oS=+x71m?I5u7_j zZLOCEneSQRd#8%~y3WO!=A}O>o||~@E~a;T?OixS$Y+dsw8lN2gKY|6$@V&Oj*j|} z|6Iz?{tSJ3KS9yapEI)4#>3(yXsQR|GXPdx!#@}BcAQD6IFgcy*m)sw8wu*ek)>t7h@fBD_+E1 zPwzb>?eM>wPV`A!&Kv^7=Rx)v>O&isusux_u{>?quPh;ERKoCI(^}C)pcMG z&c90P>wV8q9v(4F6Z)*cU_H}r#_Ih@)b*714Gs=Y zhhJh!%Ov3*WlfM+fp62^K0?YbXB~=6{&P}KndpJzJ}2?t5i^tVF{W)(y=VOY1j>x* zvveb-#`wQ`G;59M8}2i;Z&l^lxF{W8y|1yy#TnYeR})`BJZX7ijl=r$d`7W_eW&&v zr}2(RqVS0$U*IvoIY!@U4Q_??D)Z!5h^#k2ykym-4!92V9EGy>Ge!YBO zTKYYvzh5Wc7t{Bf?8@9t(efPPN#B$V=Adiec=F2ZO;MG@JZl`&nr#@fG8-d&Z(~{N3Nb&zC(!ZV$7W^|#;4$|^y+_Jf z&;&cG=@zW7z&GSSOZ)5RHeOF{3`-jgt1o|q{;g3(|1KySW9{X?mhFtXwVf4Yg^=sh z{al|tvn4*nD|~*=HvJI$=>H?`ZNTHIs{P@8W+urb8Pby`r7;cdNjpG@5vCfUmWb05 z+7zlz+O)LTi&Lyx{a2Y{y|-e)nWXt>ZQ994(=@bn3Kh9tt`o<<5)YW85bmVc2b+bztJmwuxYR z;=Y{z`R9D-&yd}u=2*m)wvp1lgtRob3vosg6J>I*mwAvr=t>`^^v~QU$LU5&(@68q zOMFC1NPo-?(Qf+*#6Ez3P(Gs?vPVjCdQyzv7ZC2=nBdq6{&-?!N~bf9>ajmED`72A-~LG7=CLge&Mslk5;yDV8NcwO>fu;~ zJ?y&{`am^!rzgyy`i)aN4wf!5FIDCJH|h$@n3IR7FR1gh@}>5XDO;_i>I=t%BHAll zvNf-%MDG26q5sO+z>-&q=y2+hA_w+;V)KCQztA^5G(G;6t$Lgtfc|_;6`cVg!S+&m2>|t zsUrv+@p*!Ey^gVKPSZYK+aP^P%d=x4W5<8WD^6@co}`0UR%gD)bl8CXh#HGEm;*w_ zPs8(_)TX35UqnCufIjOo&c+cfAPXa*5-WaPa6x; zOMx3egHrl^Uz6#}ReJcUTI!@X64{D)mxX?5DppvcG+{Da^tIHt{Wg5ICSZr7_n7cS zQq6O6V1my%)h%NR0oDaxIX4RQ1?IY~1FV~f^H2ESjIJB7G2VQpr~3Zis%`L90pAT; zd==Zthp66bRoocV>*MiD+SjYTr&$I*#IjB7k7tayy{TL3)1V!Yxo=RsWmPE2>&mNm zk{L6l-vG&ztX4j22v@AqCioYY?S+94k`wK9co@G*FWW}6G@q3W5N?q00PXq{k6gEC zbE#_cUsRj%ZpwX<&vElOe})}7_50BslJ-N}n%N#k`t#6|qU;cT%Zti+UC*`zt20fM zrcvx?e_m7I6Ux|SaZD$zm+0VD^U*x%%L_Cw?)&Mth8P zSD6n?Dl?_ZY*S^92^j+}rpXwuZR-1JdjGGQ)DcEm>)mxxS<>fCw;fY;-b!hkiVoOI z3FkRsx&aSQMafA)2*XT%dQT+iT7%3aThA>emCgZDY(iYZV|&!etq#1%L`Dds?h ziaB5?m|=XX3`rOMi|T8b`@Y`>JSym0Vrqv8T;vyz+l3s9UBYsn>TA7%FUl%cWnHhz zdXEO&kFs90Vas}<{y#V$w9e`pm6IS?{$!#Z$k(9q&EhhD%W<{;LFs$M<5?#y;uaw7 zOb1uH>i4VqYgIWHsBy*mN6gijc=b;#-=Y4%X9M&}iVjJA?s}e6D>D_*6vy*@6FATn zBj7TH%P`h;s-7`b&+CeJ^s_uewxvd;DNtz$32A5|ocIB4kC`Y2){=j!?~-rSzhBIKUnhQ%6H*S8@5 z6*B$;;NeRyF@^DX_IFBWT0|euI%6|B?cA|hr|N)jSZ8b+R2x2`zO5G=8d0ckxtun;M_>)SfVp$sS4bMCCs3?tdE)8Hv+ecOX zu05(q#$;P9Wq))%M{^o&9o~9?<0@mHclP7OXU8jPKJ)&(S;0k)pKRCf)w}iT-7`q* z(8r24M%&%(UP0~tF11_6aBj|APIauMe178957X5}*U`Tb|Nf>t!*Y+qhVpaywkr7U zyEg~F4~X0z)i^1wL23Vbk4$@oE1fYZU69h9Qt2*sr8`qLiD#sAmP$9nmG0Q2baj;O zm`Vq^{}x48IPu<|P~YMN!v_`rkG@oacAGSJ|5NpK8e}Px;2NDIixkSI>ShhTrE@-~ zUm)17Q}Y4w9_c#qfa@LXR)?rf>vcH?u9P~66L!~{Xi3kdIRjc}tMYq*d~Z;Dcc^^u zKfi^_98+anrpkaG=Tds_lrx9QIgN6ZezsH2?NrW~DyNFlkDNZYeYc?=*YoG;IqrJ? zEW>nV=AJVIC+5=zC;aC7T=JxRO1DAfgMBz%Cr+zpqKzv-A0MW=c|9l`#J*g^aeFKw zX=e8r+&w-%6jk|Or2H?sVl~4@(YFw!j&MOcd}hSsyw2gT0C;ZZ_;~FG_P?<@(_T$H zKk-C@?HXF`0A15qW+vy@<@e^!=r_<_1YKaCSYowr9LVDQ%9gs=9Q&XWG_UwK*0s?@ zr`5io!@T&OoUSP5ZhPrKwt(>8(t9M|-CjMAmAZ^XAE~;)g8)|Tr80Jb79Y;K+y5(S z-=EKppIA>k>dCX?6Sxa=`Iq#JK1<(AagP5gal{_R5y%7hhU0IA=@NqJzeDGIOcMq% z3l((fbUpey;fw#FRCIrweow!qiDPt)(vA@OlO`ViizbqE#pr6JD@d0)s)=XmI!xEY zbnT!kN!J#-*3;EO*BZKNUZHWKYyBxIo638Xu0iZHbVcYolGVm9#`6OCC5jst>OPn zu&fw<3#Y66ER$7q0Q{)9<-k6d9N1mv364M4!*-#NPw!Q2zfhfNppNHRuc3b;P1Waz z8D4-%w@P2+O8;~CAyIPWpCd2Tmy`d(=c1%J@C$o~d}EoZ>Cc#7<2BO{I#Tk<%I?I^ za?3^CA0O|NhX)-b}xzcFEY3I17PaGDipA8S8pcY>OoJ(ueG-nMdtmB_F)# znxotw#Hy^WpJQ&+U;UG}y45^v{3flH&o&p`BXxJB4F9OzqW^;V`HOBo%5e;_cdUr~ zg3D;4_Wd?uW?5#FCyFAFBc-|-HaL%7DSlylac(DMKBrvd{eXh!OqGw}ug(o|9xzVn za2|kho_YDOt@H(XtTi>(MH8}%p$VA->$)YeFA)8i2RehsFV=0>6ON3v^w=-Z9N4^x z<^kabQ}kR+xTxA@`B~37I-=t#2?xxp23?*h8tQx#GLbi2-=*GgztkJ1bm2*5opPlO ztFnTwvW~mHM^#xtRaWDqvVQMM+o;N_ah3IJ*Y|a*tQu8T)1cW)>1X zq|=(ngRfWGgJH{1kdl5OKbewi0`%eq+r=2lha9tk*(_yaiWp%O$*LJXl-!ZBGGEC zB%ZvHd9PHa`kqueLhBi^ZHwmiX1$}WW{eQvsbZoAi_X0^sEhc6cf2GHxZctlQkgbt z!vtNP%+cl%)!ykoaYFKHk<3DmC~BC(=VTeTOr_3|nG-$;PRYqbAXl$Y&ovyojA&}+ z2h5D_F*(lT7J^ZnaDrEGeEA}e`qkubr3N1{jKf!Ev`D)L`$t5bl@_Y8`mOYRK=TD93i@Yjr1%adAR=A}|S4_}gnk`jILt?U5_g-ymr`5PXsgrC-_kw^JT1#- ze~{x zJ+fbUT4xqAe6%fAF6H*G!ABTkvAX(;*hfU$oR~u8LM}W(J5U`4^g#5(+;7Z1na91K z4DsB--1sn+GlS-A1?6p~a?p>eWVb!wf!|gdgJ7GTUrl{7dhK5)t?d2%Z7i35l-{#k zG}LWFXXJr$LG!82#F?zqx6iA-tyW`(_~<^-eq1Q}V+>~jG)6f8{pJU;+Sz!o+N4m>LrJoDZGo;3=d z7b^I?N%N|S(gx)jfBK8m*NP7VrE##;|LW4@f_g@{So z5$Z5gLAj54iLcv2Yv541w5bB#DN*N&h}&2?>(;c7_<(~`X|LMYPV06L+X;J1+s!SZ zgjEinn&5v=fz%cHx<{QWM&zDzg~Ev#GsvAWhsq=JTp9BykJjwd)b43hZcPh)uRTi` zR*~{|U`UzPcI4N^O&MJ@_x%S=uwX1{e}m>I<|b%v%v+0iI%j>~pw>6OyVv*)jMMwM zZBAO>dGtvnZMoZp3wGPUea^h5{j9Qa9R9QZzl9~spa_;9Rj_PvV5#=+nF^M`BMvM9 z$3lW3V0ru9k`BRm<68sur%+#DuE9CzTuMjlW5oe=maY1N*a)SNleu8|_B3`bpO0|= zJmYoopEyTRIR1Yq4ew#_r4#D0%Vxu7Az{n?XIX~$ z_W3y1^vvzaMrb{iT}6D(+(Z_8W~@F*`}Q)#C7PdcjrkO3%p>QH`Ht~in#p60aX}xE zrxh@W$Lyar-)AZ`snaJPrRYk*58`dC> zBIWxbjq^NpZr|*j#j0_6N|SR0c;Q9NhlsSy+Kd zpH*2~c#mz)JW0=9`h7+N&D5NsmzB<#TJ)}gee4piL$LC0B)V~JPnLZ!Y^1RZwOO%E z&{JH_WA~gU*P@4L!om-xGCT)TMArwU-td&DW<{d#NwCYxM~wE-gb6xwlZsK7q$@?& z19Ux1*Acpo()9veBXo_?<@e;SGd={k>t{OhH1yzUo*C6W(_nwFDVUh{8O5`=Fs+!A zecVAXY;nmxw(XZV_H&xV-$KgSB))x{dG^oN65`0*MDWdY(EwZ>eJ?(|MZ}owr4k^c2P^4>*Bk0IBpB_e)#>I%>0`q2O;jrp9HM*5451 zg#@#%nmpj16MA)V2G1TN3>otYae2waGy7Dc`#au)_!#p3O}Z~t_p>j_V?PJDAAV0B z^p9owI_PZ5d-yQOQ}^+A7qg6)$L!LAj7D|PIPv&_uLtjNW9&uyQkplHdP>v4FRXtI zdV}!9W~7AFx92UU7lhgX~c4YGyu|IViW9a*Jv;LY=Pfma`-+qg@e?>#kaeF37%~nWbfwVG za#c6SZ>#2w?w+Ze^`y7ZVUQ%mYSnS zgyK<%K9Ofn{S1?>RCbq7@|K991bs}o$E*YoTDe2%hoamjSGm7Z<$hC0T(K1Nk|AiX zzKzeD1a!6t&RgqSsr*)ZM|tZ+9e?8eB00fF{ntKO)?Lthq3@8fg0E;Xx-D*t{zMk^ z7kJVsNew>r*YcT zr^@>`r#wTJ7XS|^o|q^vL~VJK_@bny0Uw<}TJ%{ce{P!IY&Tt=w1+{H+Z==4CCgg+_wmZ*4&9P^E8X&T<#GJszmK0d{1V{}x{lHHG+jsNdiW)YOWg2W zuKIt~BzRsx{eL@{Y8rF_Q>7?t6T#IDPt<>nDs#3|rl2w-FWQUop8Xw0(ic-dw)&(U z!ibTu9r<$?y#rh$(08Eqw6#9LuslU&^@>&#^LGc$V@*saK5(`7uWEibmGm$iQO*mX z3H%z3&4WCbaK`wTH>FQ)mX)eAm_ph~LPu}#_`dqXfbVEG%V6)lYy4!B%dWu)^)QS> zhU8l(kKONRjGVo2mUz3pa1rf=t#8>2%UpT&$$8gO-it?6DsUGq1I_+3J;^K9(uR6ri@WuvBk@}hy_a#Q=sWY`ZfD=jvh_>ml z7SBYidl`GIg5Y1ra+nS?Pb5d6gK_l*9js5g`|?z#2K>=*xBV=^J7f}`3Ew^9A6{nW z=|@e%rSl8)Wo8lGe-gS53V*@wqUrL4jdS(}-h*$>)X|t5N_OC*XM*YclIji<^LQTZ z2cQ|@r>~^C&Gc~`o*Q8kH9z_D)GOY|FEg<`>owrG?%Gd}`HW?jS#!&4-L=<_y~!~V zZ-!68BH)C)*hkDfqNVew>;@{=7wtU`9xkx9!}LYljwAi>r0?sU z7VNs==L~k6?5mIM)w=Da@GU^F{Og zl+tD@2!AyFK@(0J@xF$}8@#5I9_KU6-vD1xo?^=5UMrxd%V^Cxdm?-X>$E49&+TD4 zek$d6uV>(r^3tR|!sjD$ZTs0b{*YSNIoz1{=6Gd*&-|s&lUT6Fe&ejv0pRk~9*4E% zE^qAYcqR7YQ@_>386sv65ixqMeVVj!E|9*>ho&pN*pI$0VOpm6Fei;#oBk%hnd9;t+ill#PP-!#j$Q?~->EVy9JocL z%-5sNRLdr{{b_1@g_0XLsw=EuhBG?G0aV77sy$wjvrht@0ezwT^Vl4%qqfbvLFz>_ zo(Mx`+)sF;*p@!`agG?te9wcJ?R$yFlsNg@#E0YT6n+obzFyhBhiIPGS0_0Jn=qcR z^7UrIRlhOs^T=2Ry5gm=UxaVQnHKGl`VG=omRdg^Zu?%liM|g)XEu&@46+}wDuN5f zcKUhjx&V`UEqApj8Wi^^|Ill>b8@H50y)-07#F1Zm>U1T^7-dp*5Q5ub}OO1_G!__ zwsJ%Zr#1cCeAd?hTupl>a5nbNAZ)SpUeFPCL$nxvv5L%m?6(WeYQpsnu0gqw%b$t$ z+2vZF?GF#K+;E=K$TM?TAhZ`CcGJ8NY*yB!;VZm9;5GX|pCMgon+YDo=@XxucrbQ-G!gl>T{kxkZv&d^SLo(ibZ-#3nG>Z;6d;S5AUb( zFNXe_hW^%=#dck&*bWXC+XnHr^{H+faanMV!+u7oFEi_S;Sxo%6 z#E<%7m;<@-4Tie;+==Icm|;UUtP#CrV19&QzcI)3Q@(sX2w5ksu|ArIhnQ}nJ+stj zq)Ih$qZu%8M)#cQ^hu}kIy6y>J;4thQfjvk{&^x16Y{DMY$apE=EeS0x{k^(@W<28 zNk$t$>*D+?U;i1^S)MU`@O?~q1MxKUiZAs`U1I37SNjmhz1#jWja7+QMrA)^ep(ar zJ@Hh!#8_qm7Y0HLuzzQgCl^o_=~l;d{ZbmUi%rBlE=F5);G!8cKWA{>1n{m9-V&m( z1Nt*2aB(NCxmRg@IO9zXc*}TK(YRo|G1eG+jCU|Xr5B-XqQ( zZ_w(;W{S-4HA(g<54kSl4|~JCCeD3C>Y(KfwGdt;ScaZAiH?|mzWLE6{&(}^%QQbe zP4naJ>O_5rCFYBwzGY^9=-1}Qs7~N@*cBnhCF~3}+GpRzy6el??g=zfXcAo%W*xM> z^1N-Ygw53o9(XrS@Cwl$TSsk9Y0YK`G@Sl~1>Mv-y_oiB*^UaP5tg%U8S1H-RL>=@ zda`N^s$KQi^sa{LDI#1SRCNWUe9D6DLk-m%r22H=X_|)t+S7}S=S=K*e%jkB5jTwR zE@X;%`r{`12B0|td$QE5L>e(@UuqP@``%!|4=2VZKs+$u-NC%fUf3qEjG;);Q-l8) zKd~iz!1gQJO470LSs>}heBt<;Ol2aJ4&Qw$PE^xOrL&}DA9*hQ(@*U|yu=iAPfr+> zFaMnKyKLy6_CKYG`=8Xr13%Qn({ye4Va|Vn^n=lBvtQGQjEyUluZfT@b@bk=;GVDS z16UU>+HO03>p-{5xU@1h_Y@)hJ~?Z^J8^cO%ubWOLu!3QJAp?Dg=8Jzb+K+eQa^`f zhXpRZ^@%!QyB(E2>Hfy?)+N1+`kb~SzS!ipzoO**XgmB5JO0QyPOicI&mivwvX9bl z7i4wNv8Fsf-h+A8&M~Or_oJS^->K%_^eMM$sf8)ciS^_5_knalm%l;S1bP%dbU&4u znj-yxFpi;LQ+q7S0X9oI3aVi}Ek4#>F41oJ@jE~PKD zGUMn6!4HLu=Q3zN{a)$ogVt*45%qrf7U{!07VHK8TFQD4Dad5{?DyUX8$Hlq3q?M? zhnz)cIxE$OaV#f1Fhz|o{N!$?GX2oc<#yc2dQBWNGTN$ryUf_|-H*<7z(SQ^jbd=_!IreeL&JH*&w+a_g0 zS-3Ht)gspk)`K;q-^HqsEZ1L}Ff9dN_^9y5+fDd#hP{Q;2FL#Ban**4&;}vPu3|m% zB)5ZOj7r(02Knz(w5Ko}BG;KHs{(cus;sZ?$?4wWtes=CYaLm{kc8an`z-qzlzL<_ zxwb!`c#^A>&aeZY^0+K>FWMKAXPz>C?VyAcd}b;b6*G(mS>G6V1@M4h2rf^-Vz zy3f$Fu6OyTFwWzj;!z*OsD%@ zwc)WN1u}0r^I`4g3-n!A_ak&4Q1@eW?^pK$rX}Tl1>M&XO@jL%-Pfr55ZxQ!#L8ABB z{+0O75ab)g14I6CCyg)0)$&JQ1KpwD(q)&wx67`W-DTf#MVB>N+Qs%Tpw~Q8TSq#f zcX&^i?X$XUKh2l?;&v-=8|8sMQ*yrz`pZwe#L?<5``Ml@``E!Q`-P2Nwz(GZEW7RF zT9;i%{O$<-*3j=M`b`uyjoptn!{-HPqqvMcxq{{_=)vXm3z>EEfb_-v(E;gu`@=k^ z_uDtnFUnj(zbJDt{TlRp9sLIB_u2u(C){r@7(g7u{q~3W`+oa_{C&TDHRs!Je}K!` zZ(l{f*!SK~zpzn#A3x8q=MG38;8)P^Z5Om#SW`O!a!%9^s55&-4^EEp>3)XXcIj@} zhwFDsf80&S^O%MTEl^BEC}e@dz!f5yGT_ zfDj=fdWLCtJWd;pzg&m_gg|@0IzoVlC=Zd1;uPEvLJvc{)rUFuhtpM^*pAYpI6WM#c}I* z>ON2*zdfU#E7bF^)N@ch|6DzX)bmf(bAx*Rv3hP&&yT6+7WMoC^&C~t|D~QcsORsf z=gsQ*Tk3hMdj1dfoK(+WSI_&@^S$c%e)W7nJ>Pag+}fw^cT~x5gX+1e63@x(E9&`? zemU^vv-Or41hT!yxgQLFmKdJdo*VQTA%SV87WYKXnV@o#%A&ee`a9k(N1C zt4;Wm{{;1?i0GEnG@pF&|AI`M=hP1%SB}H)$sXG*&doKP`K4;4{Y(q=wUv+W#{mx~ zEzTm0L>6su>={6pe~!}(F})U{cDK+~A#!$31xr(z@s&dIBm^g)mdvWYR#q6WQ)x6| zmxwz3%q!>8K#seD$70C#t&MZte_>r6g7;GF1+x8U#|=DoGQN>dN7_Ah(3J-K)WXSW zs9eYXu}bl2HEU>Jp?si8eaa^fXi}MOHPe+Sdz+TPIqyXM?^b1R)8b}cRMw9)K9%Ma z^<}mzjgQh~RbSRm>Py9W`m$kCnknZ=6PuJK|2%0nO-l2RzPF~?JPB@NeR3X18|FlI z%cSq8CVdwMjhB$V4P`9#Uc2dErEedsmo<{s${ZqC1LpZISi(mp(nFUTI@HaGHSGEh z`T5a4IVYg|nHP@B`gDwCE+6Fm3nzRkNuC;V!zQeGqs!b<+RN{{u!cgtwvXlHy|zw! zxlYgJ#HSc^UqSDx=$YtP`t7!p)xGu_;&E58u5-8Dbg^7FjVolFI48c7hv<%a^)2N3 z<}tRJ9P7+zHLF&*VxJ+#~C-)F-$8=~>bPO=sqi7e*gP;+&U`qsAvz+dC5sm7@ZxQHI z=qkmTHZ^M{P3L3%ka$+oqqKK0jT&bfmFZW)aY)BwfpbDdquxn0Ds0a{qZ03t2`eAw z@MT_3?`w1_qiDexdIP0GxZUW`Y^Qk@#oE<-bbCe@gXRZDV8)p=k z3HtS?(lz)Eq|%qtFX%7uL&RrUnkSwfrE$50Z4!q@JmCk4$4_N2SIhMtIbZo4^E&Hb zX{)KZ=8Xe`jeI^TVVI|2m}K7E_p7{99R1vI-2N8unxePd^wnhg zYcjpX{44e6-Nr9i_FhAMuciLX_N)H;WWNCi^b_#mzD6F*1~_j|Zf$a3QyIh)b@$b2 z@0G5;=BvK`Z~FN~)?uJMu`)NNUtpgBj_<~yX-6-4ywt1rmVS=jFQ&0Z8_`y@a~-uW zD&&~>jHKnX3-!HU`B7cNa<@q4U!1yzv`nF%WPN7P4mZ+woyO&oIO|Phe2`5OzBpRF zF#X;u9{bZ}A%Yv>ra3{J)&0VrQ$ujWZymvnex3Bk44Hl|rGKwVA5!VBQ0XtH->J~y zWF2<=Cd|Y7uhS3CdhAc%EBi$n@Y9CRg`1!KiAuOR=L(mqzCaJRg7$l-KOV6n{Y%2t zv!V0-peD}zrzXbe8llUi>nL4E=z5s02k1I{n4tcECj8&b$@~y&*E7tz8!XS^Gf$4U zOSF=Cm+c96zs&6m%lIDfNvrQTH@*k#jz{Tt!`;%RoYo{_9A*lWpzk0fFSZ?B7){D& zE6Zif4wmsrUtxP$Z@`gHOxCq~s%QKpWT)&CpT_Yu8b^QXF54TGaj`Tm<0hsRDjW8M#z75@+W$B+#o_rbOEb|1FR|7r4BH5p~Pk2GQ z;+;PRKTXRr->39Mi$aen{XH7zIyHwud*m4lt-=`Mz%9!V&e#t9=qma?g`OV~V*5QI z2`ewb=AKw8;W0X`IwN8GRT=Q1V9>lQp!OFlS=W9gvqryss$YY=J`tOQ+9kqPRKxtl z*-OuEzliiD0S78GeswYTk@~kCbokW3vJCZQcR(!b>!dW0*~0dDY25+V*>v{eGEXF3 z=1Em+B0M`R5*Ihf_N5!>9<*}Hu!QFzkMEkyUe+O|{2P<(Hv;luwv!ZVSpUv>|2MQd zw8uvOS$DzTS{NkFKM3=%URkq5W2#aY?wNe4@81KM3D;j=hYK z`Y@nJuA=uTz0XEoE{ocGsVW0$-$!{bA4h!0HVbV=8t4{4&SLb+alC}!Q6r>ooJZ+~ z0bkC6uOwCHMby3^>tjeCWe-)#SQ%gKQTB4sRj2PM^}b!bpQ7?rv79`TDOS&#f~TS0 zqrF(`UYs4d`U%-O!-Kw^q5YftrF8VA&GxeNMMTSDKDft$=IhWH_j?)JCKeD}9;f$> zv{qP${sLN;Myjpwf=JtkC~XnFn@aDB@h%W)n@{g9z`H;s6EH;Im9XcDN!`)s&yK6u zdeUFF&p6D!!Q}Zvt6jk{zGWQCf*EoTgq@C0w6cG4+(X}16ExRi{rs*1@s7pv^ceei zAX<^q8pPN7IA(Ps8&vl-@N=ZzL0=yC6*$YLenKy%=4s-yPHCAVUy{6KEA7)QDi7`h zl+U?e<$7PD-h1X^UvDMc*p?L`Dm&E2dX~`XL3#azC)QViPr(?(vm4a?pdsbkcz66= zx$iOhzR&e-lS-d*y&EY6ttT=*g2ksUTtw~udNw(`)9$CM&gis5bg^%PP?G1%89Y~a z+DYPH8tC3zBYmdt|DZS-sBzKqB56J`>!4{6U8DKqX(j*hB7WfNDV^3Ad!&5g5YZ6F zrXR2avAeJrr!jv$`n}nwln=8bm&!7IMw|2zuD97zmpEbT#$7Z&+nD~YinrNDw9O8t z+U%N0n_U;fJ#<-@rSE6kN#e`n+gV2kF+O3#&-(f?c}@x+n24!eFe7e(FMu5H3s^_G z)ZHy08Uggel+p>)RrGA{YW4DZG#?QdU*x>lFx^~J)=rv|I#>j532G% z#^vv}(H7_YD>zZdZab*T4^sJ{MNv-BRZfj6XNfAuDWk?!MvW??M(OAGDVczXnVFg$ zG+)AX3)Kx;sJ16}cK2t(W$tu&lx~$u zXSmX3Xgyz`@W6-8jt@;y>%WB7`qel$k4j%O>#2PksC|>`?pI|NyUGOqnq2pwN~gKf zY0@5gJNoDJ`AdEoIlddxuW}u?Ny;7G?W7OEcV#cfqCNuo zs@|5ZP-%jkK9yOTlycTXby`O1szT1y&oP)W-;WS%@82L{tHs(m7Lk;3-Iy+;@%HO| zkmF|NCv)*e@(5QIMBw*Amh~#bP11KM}}KXC5ZYjey#5An)W_vn{3&dYJYRXYko2eTuw zgyjn*?DCLi|Eg&5*cd(UqTf}qRtwMTL#_4(y1sbD0_%ZLBCp;n&-6m?JHRwGpF?we zi9Y+Dq#X0@a(viN^T+(+q^4-R;6KKxo&6&r$WM)g`I(Cn7VB8hxX5-9Egedgt$A-^ z+HB~dL}@>x%TM(;*5b?uYc*k`j3Cnzi7ezoky^DMMB~||mAQMQGgP{kTJW6xBNgg- zm3ppH&r$Wfl-kn7?+#`Gm-SA0wBDu^K^D@_F<2Zq9Ol-kN;Ut1Ta)s<1oJ#Ju`ZHX z$Ws1A!RHe$_+Y+F^-Fu|7tV|qy?~hLhRJ8{^&z!xi2j-?%ybjWovE!{U!U#7332GQ zdc_AgzGf=aI;i?A!3Z>iah;h*bfc!XvaL7lyy0Jr=O*T*-jl6YZJh6F;|XQ&{m>an zj|2D1Iu!1w`k#8Y?5ihqnB^>&GY^uq*Xs%P)hpv4^s|ipQW;B;*U^D9<0l;b7fsob zc^z2}&6_=EFqh@Lh0YOO9NSE1SyvCu*@a`Ex6mKx##RxG(60uTBM`koeH!1DqamF> zeOLAA+qAy#bhQEX-p+OQOvGZK{!QCgrImS%6rqjeG@>b{Z=^Jys}(3LcVI5tZNV>Z#|bOrZoqKdBdcR{iuV+>s&WDISOijnB(D(M_E zFUj#2E?_+;z-|S6idTa6GlY!E^Xv^;W;k+y*UzKF2jKfK3qCq9j2MKw%mDQ#7>*N8 zgiJ0x<|o>GP@T*78wY5v#4YgGRHh01!}4T252t9TQW|hM_;KJO8?F{7&p`elwz9s3lW!ftC`{LuL4skm zn9!jSCc$YKxbJQowy6_Ydk-^#sk@azJqzEApMr>JCq#qt+0j;4%)7v zT(OhZwA4*<;$rEpn1vT8dk{_TRh0o+qlo<}<9;^tT5X9)-$&RRM<>OtyKU$AL@c3M zyheLi7V$3SU+!62JHt^mh9TMqVh6LV+Yy!fK!A1UB4#i~cv@$iNfR%np>NK7?xH$} zweAtr8Hjb;-~IdeN$EFQo=;&Mo%pES@2FgV?)RmH|K4fbUYsw-jcFGeJ9pmD9!=bF zxh4+L#N13*7j<+(@9sQs#5tNr#dQQ9vtts>E_T7}LKn<@sxO!?EovTP4m)rJ3_X#9 z*#P^d0-r-L6A7OCjvUB651cvdh6mm~v|AHP-jnlj*Fy85Wv@Itgg-k+zT})AI%j*( zsjG_g*f=9A5bahl)Wc^S90QB+*Qp|T-shunyl?0DL=1!ffL&X-$7cVRY||@gSm;bb zuJdb^HXH^05P{DB+zQ&O^F>QKKb)%W7JEjZ=U+$byFT8{ex@4Y&_C|BM|gi6vV&1t z!(r%wCbPhmzMz)TseK+3XPHtqUJkiXT*`%vOYY{_jGgMtPfN=8IG?~g={-Pu3)SIm zM*bUF7c5WtNDan%&Ut?YuhrdB#)q?`>U~+9`4otiXZ_fGK>$|T1 z6x&W755jhG(b(TumV9HHbt?Uv#Bq1)~I$>)4)@(x+j^>1%E?eW9f$;zetr z<<`nu0F!oxNui9_C+&AN8t;y~ZK3+A#YNfUlx8E&6R3SvA!$qLHBt#-?6iZ`J82GH zYc3@oJ*fB$%#WI|f(5~-U~YdF{0r=0^P_EP*cVG!tdOvXNm$7Fu|m!d$XzMVlOYKU z?*uGvl=FjaZMANPY~@XVUfqM_=F1`6}VGpdsy((T`KBC2obE zkxiXiCVXW{20Y&Qhd!EVTtf8ea8I^qF8HfBjZ2^15+l49#(g*Y;G@0WsxcQ>Vz}Gx z3Ac^Z&@*(0Dj)|V8t)#&OVjt-;0aN$FM>DxdQ&=$d8=%uvCadxYniRo zu7csXdHhR6gTtmY7B@jB_eX(uyY0M4+jHHr z@F5hZb^ssgM8}SNM$7D20)1)fR}}ny(%wgVX#~2`)VD|fP2)2G#5sWM!f#L?sjQ8n zbp(7b(SF=Nl>1pK7iTu7E+gJH#B{xRs1JL@ay}23r%RtBMB7&8izMqL!B>+OZ8fE@ zf=+^MGw}Od58cB?#Ca~z+f0vo_R?=1aNL9rYjfryng`6=60KiDH0t{9@ssF3;2rFf zXXt3d)qJil_li55^K|g4+qBG*uSi-Quz?-3uNq_8o2@f??Y@FJ)HcW;<@rorsLkvx zlr-%9LdH^pK1T1yA(uh9}BD ziHs-iWIfa&87ncQ@E~+I)O#-bL#a&N7g@HLj;OMORCbTI+U)ht;qnV2ZRVj+!m3pH zo|=@;X_Mi~7omJV_;|u9Ah-ooKFAS|zgPCh8-lG!u1=>vODSK^RdYYvFIAal~Kdzp2_U5)caZLebsy|^YGLc(r|DW`Ay(fYF`)DCE7@P;MQ2&?g|lJ3sGLkal<{Ph}>h1hKE__)~n`$ z6NiZ9*R&oc>i~>yA3u4zUlUEcG;w67CK|iJAH6jmv!>!P`zGQszxA8{9lizL;akN! ze5-ngZ-)9dLF-ORQ^s*`n~85=z2!MQLYNJ@l<~mthd+|AbkS;8aeR&4BL>ZjhG?rD zrgt@>)v7S*eKc>0KbC?9UML7(ck5sc2$9{nBKTK*2-YTn^n-8*~>Ip2hgcMCt{ zj@;?(^3=aWc@6LIE&TtYuHZk(GZCkJSmo9CF`oh7Ma*BAQWhh1*rS#aj#x8kjoeuZ zdR{D_S)OX9Atn06Ohfk%_&iU4hW8HOT#rbV61`R0Bz7>5yfm_dW1Np}Bi>?C3})CQ zNgJT#1b-NTOojQ(6*v#p9J$jS+t2ky%szxA?aQ)Jjt%-%xxRs83aXWF0@{NIRo+NE z4jRIC{1I?`WWX>aJNS%z@mwBz&+`U-hQ?{s0bP2(~`$!R0>K48%M zP~UVBN=)N2==~{ruj|hHR+(NTr;XNWWgd~FZ8tGZ#=TFn4$?o1`&{9=uX5cRuKS?) z=W(KIT=#XZ`;hB?p6kBeb>HB+54-LgUH6b7aIA5~LsxN3U81`b4-KB`IMJ8E@IJdD ziFLP?{gGA>t*0luZOFMbU-!#-O2%Fwc4py!5WX}##DBFDKTtySH2A=R$oI4U&_d#? z_tCh7P4F9@P--sQ=aF&mlxY*l~Hjn7h*k_fhB# zqg?RcJ{1eZL%*owJE()`H%T|FPV>3LFww|jAGf($*%YFu?8;%QZ`_?F zz9tQS9Kq1tc1`SVJ0b=~{8YbRBR)!mO^?>e_jm^$8ZwAs$Xhg=tL*18Y33*DfyJXxC{M}7!te&8I z3R&j}=aI?d@O9yv+nc2|Vl!VA85(i=e<$&AL2a}Dy(AmRUt2xz|@7Hs7_gm2+@;fpT4o!f+rw{?8G(lgdOSpUnH>gRRqH@2H- z>vZPr_A|co6a3)g^tje*dqay%!hLD4F6SltK8ozOhv)X%N7nY*+nU==UwE4I`LUoa zE5f^NKm159=wSa~Z(#lb=2|P;Uh!UG;!JEcttaM5Y6IftbS-?jLk}ZNG+|^2dWA2S zJf1L1sC+@|r{rMVELpIXWxWN^8;DM|wRpnP)^5*w5C;tV=iD7cCsKR0_H4drGf@}j z3+&xBZ7a2B8~j38h&PV9z0y{*RuenTa$Wi+_A?zDNkgy9#$2Md`;*&D_^9xkJ5A^f z0+wjAFk5Zn(TC(7oML++$TnyG-F>FiZzC`KQU$7evN#|2yY7Ro`x@6hbV2;AH@-6S zuj=f#XI%MNBOIhh;2)#kKF()7GzZL19>+NtN9ND(wt-s^2jh4t{Cg0diFLz2JM;qP zVqYj%atN&d!90%%+#*t)k{+P_yC}l3y4e?(=kWoS^JtI9vyegQ@Cl0;KYD`T*#ckT zEK|^k=LF2S&oR`!Q;vHIFuI%9tdX;p`eJ>@A;T?f zrh1dxEUmed>t&lo;DQurd&F#$x=!J6#4Wx`)~AxdX7W364=<66|pwP0mmzIHaF0*%U9#q3*8&lM$~DI zk8h_o@IE2yB;I_|+K0YiAaa-OiME+~>@FMSiufn2E3f;6dF9tq>B?Jgr8ab0v!a(+ zQ|(mRh<=K21>&JDPhSby(=e4ClfIc)r;^%S6z?+qVg>tZW4{uFQ;K4pX4``M*ymjd z<@F7B*dM3-PTH~Y@!Fv|m&m!1Tx24K5#R_JR2lpC{BM?H=Pihvo@l$77g=n2BR|P> z*RC7$MOIk1%=z2vrvH}L03Wkv^feEyf2?bqTf>GeT6gAk{3dVEUwNMJW`1)rEA{JF z5H9}Y!hCUK+81s&Pa}3I<@vQ*3y=qLA1C^?8n&kM9bYsW&8MPhhq+_Hy;*H|2lZ`D z+81fFYbN@(It{-#Lv?ewZ-vISCj2F1UqSvtoFh>?r^3Hegm6pj3GQbh^|K&E_ym2t zblsST`Z$~Vc#mejjy^tEz4o;N=7(v%B+DwXd zCuELoYZKUU}3SGiD(X2kmNWgo9w#sv0b*ABC-`$BUXvTUKYmj5)8vQJL zru6Uk8mYN;%BG+8oAgDU&_&v9KMma)_(7%p+Ry%Z<(}=)uZ7+Tmmg9#`uIJvC3gl= z4t-m+IffX0J@z5!J0K2e3UdC{EW`CQOS%qw=rLut6@dJX)+F{M|AL{cjKRJqi+Gjb zI}Ud$JwfPG5{|(<8e=`aAwCb$W0JNiAi6GSY`2|wz#igh3QFVV63Va9cbp@EUeUr! ztozq!nWy#vpAXoDL~p?k1!%s>Z_sX*~jFr1hlGg5>I5T(C+x75+@P(XSG~|bWhho{)<>psVwBlm@gq+C%!=X^pdn)(mvWTAy0B+JU zfPY<=)Q5BKWnC$rLy*gF2JK8Z`HQZz1$@7a_d?#o`T40CupyQ@rYH~odEnzmQ|l*B z=^jXVnAAPcCTvAkWh$c5ry26X9so8&kjZPY!>qr{I^mIidp)hQ4aRQvY30#-((rX9 z%stf2o6DBtOpNNSitJ|^X0%y|ucGleP27G#)9uGP&$YSy5wA6j z%?e&`ICq6!iot&6AIt*(0QZ3IT3W00OLOlNcz-@SpjX?+PnKRDw}J%oGen0YE*aC| z(H>JI@3pk}N=qdFoA#U)=@jiTzUUsiJ=Sh^9_%oWMt_#hA6{h^=)X4!ch(Mq4uF1Q zYP$vBsAmXveXu`srQ0<=KHsCSG`;%o;LB}(Kx`iYtXZt_c#OjAx7K*t+aL*&S=ZzY}+Islvzg-iLZax=xiior$hL1)QHZU>iJJS=Q z{YyySE0{x5J75>h^mHZfX?%vad)l)zv@#mQ={Upi@Y>4ZfvQm4g3TA(Fh%-C{P8}! zAhypGsb1TcgxuwuR)EHtX*l?U)4E^IH-;EDi_pJYu;B--2wSvs?5|yZOmHr5vRxSD z$EnQwI&wZ;Ci`(QXUO^To{qQo-QvLJS%MAp#-aCKe$fFt5T|`QdDlcN0N+JYPc~>2 z+YRiy59g>!<^xXENtt#P;j?+@OSD(XlzOr{^xSB_BD$&v_^B~kOtiCEM(d`Gc#Z83 zRYAT7KbW$v`|A#{9EtUN309DiCoh|A_6L+7ix}^x8BJ>&DKJ{ic|yhsG3NI1{_IV` zZZwi1f^2>R&6oS%t+D+LblrS$4$ zuGb@viG4xZdIrKN%{QDXgPnyoyl{4acq9!xMkK1266Or$hfT$Z6L+1S zVGHnr>ltT;M_tcL^$#l1Kdhb~s?E)d2j)wgQ0afCk7H@9qIo%3o6`%&oLEo! zyU;H1E||N-N7TWG4wZxbq!E5fhr2oMN)y!$zpK8rJ=sP6)$nWf{Ds&9X$^q?G)ni_ z{hu)y&hW*8Uqk&aW!r_g8P=t57{FgMQ*%)s^OUSl(31Wze8#Hsi8gtD=B!)OOKHs^ zwy00*G7rv9rC}G;^d)V(P_y}LJ$&6Bd$a&sNxBz}0ArAOFNp6DHKBKfD%?Ph@LfSz7=?bGDN-k87bm z>n9(-*wplP=upgmn)b8}NeQi5!XMv=gp^-Y z!G4bz?(2w#U8IQ+Ht(MJ4E57Sqnc6$wvcf#h_%)_nbx+t|Te!aCJhITHp zVv!ldS4PsCXdbQ)(|t5mT@+4LQ@^TN-}0t*Q^sSyDJ?Yd{B+t|Hc^|_(>%|oIhyKC zr8mTi?QLQkd}QPNG2w?!!h%-wwmY_RO#0Gx_;G<;1AYLAm!W*?XrEj|aE(&Eu}Cq; zWoe=37}d2YS!}n@jhheB7-9ZL;xp_}(W>+xY5sQ}y&%ziW6NONtgiSodcCa;;pvQpX`+Gr0;mX8yIdgA=ALzy|O5h{ua$~8i#b)oMCq?ILxv>zxfe?J*aeQ3(dEq7W;sp^}17Q zNtZD1NqY!Amq4Eky3omOR;#y#?NMpYZ-*TFGRl*nXUNSGG*>|b;oBUx3D{(@PFne> zbvdoaopVy@Z&pFyY?)cYJixC_lz)M$7xiErYxSvgVtOh)dq-RPo{B`;L(i?3ZZeVH zPxZj3HE<+swS4+=dVdVQjBC5--MzaK={94N*`~`j3F8?2O>>-vMxNiR(@pqI(j3vZ z!JmAlr$jRk!tc1T#HtQ`#;PY=uhSf_4z0FAG{5hnwax8inYOGiL*>B-J&#?C;m+}K z;16;s&1t~>o5n(p?*$rQ4c8sZ1cu|LFNyV#$`tfS{B{+M&ti;^F2|=+drZuKIX+>G&sGa(#2BCZd3+kJkSCR{Hr83wJaPJMvEJ`V zHQ$5riOMr2r#@$V0E<(IBTnlGcmp^xpUT8~$2taX^@rQ+K%~zGtpM9dPcja_n(3)q zB`>!LewwL|oubpsKS=cup1$p(6x(1SW}&9<$riVbpTwF5ZSI^wZ)ICM*lF#_BAtiQ zL}*ER4|OtaOXbuSR=1gcsk^t`tN(WfdScy0w~P^e zZgm%3JN9>)kH~}da)`<-7oCgd#Y}~^%VebcsXHf5wQAtC?H>06-j)>@hZEW0Q=Ocz1T?HvxKW2h$qt?6p ztTA|zey82=-NzIgSrCh(&;+(1$l3L zRug`@d~~JOQ#q8kg|0@r96zCmksw&-pwE`E9i)$ce{`4Sk5HerfvgzqVEr(}Z$MnB zt#lb{`-tWz{z8|&iNVYMplw12p%Q)woiwl~z&iR~o7)eejEMlhqB_-$v_fBCy3_xs zO8+{`?Zk<on`M4zL|^^CWw4*nl_D!dRop*mLXPxPunjapJhbst(=NzW1v#GdN#W-^*R! z-=n_&0X`4Z_X^kdi`DmM==-UB`Mt{Z{UY@pG3k%0?}qF9H1++*e7-wiAHFab15ne$ zY*P_XX&zxa@&P+}o-|&S26V|L`W_NQTT+^%2J9HXgG%|v9F^|ti1(#;a9;SG0bK$) zK44SI^2Y%?UMkPeo}@W|z0aWb>p1gOYc#b{e#iN}uFCBJoG33~2zfQW7piYsJXLm% zJXyuh$=7gZctGm@hf^x%w9+{uS}LBW=0+-MZ_dlfBFZVh&p4cg{T%9nT<2t~tn1cs z;55v$xOt3Vz~70t%c$?4R^K6qLmHfMBh7>A`^Vv{gub&6tuXef)oF`x^dD5r73dc| zr_#14KMf8nexcrfg#BR*@cW;ucT4b2_4_HT3DxH+dbhO{a{5$ySf#y&<95>fYU-nE z-}ltFt5i7}x2*-b3iBTVed3!mM%8kR?pOIPqkPfw1NPwC%#XWNx>=MiMQxwwJHRps z_;YjCC(?adrJII!_?&ewzs*m`ZzX_>`gX`Q=U1t``Sksef<-&*LA`1Y#B$@0cnC+l zxqSgL?}uH_m>&-~&&i~H$eWuh`&{YZuQTa-MjVB$=akcJZ}#T;5mWc@#pLmIzs#`I zQXGfj{_p_f(9YSexkvo*Qq`}cXKC)xT`&_RrSUwZ;_{y<6rpo zqx{WOb$kZ)9lC7icU7C#@jmb@>)h+0--&n2a6FU!Hs(SAah;V+z~kHh^1X-~jy=PL zH;!p<#p6F#b#6Q>*Y!u@a^E^kX|Yz_bN6AD_ESi!)+g5OOX_{}tXx|kRAt1@Q^wa- z+7)MWYaC_#Qoa8uy>HOox*zOS-xt$&LwoCf(4)S8h`#&O_n_lKOrreXk>YAEIx&VUIrv#z#J_30#NhGC!q>_$M{7iLMQF`RUy$ zdUuqrhv*ulYcpM|=$c1YJ*7GH2~BLJYZYB#x@zbur)%^UO`N9dX}X@J>j+(k>DotE zoUTE-#9I0mC7O<|b#yh+RY#Xj*VxB%X9@vzrqGlpeVwDP;dW`4&GF6=Ls0p$^Q&_x z(5v$l44}_cf&D~JDL;>Le39-7mFBas2_ss5>^yi7=`MEWj8O5uX#IGK*(cE>@NGhS z=_6VppC^6;&p1o;6mi_`$_uDo$X^OCU_WHv7^ZUI8%PVtUr&H_+batx-KFrmUMzL1 z3Ip<2D`G$1l>z!b3o%OZu2}l7gs%m}OvSk<an26w_}p^xSmFwy0j{NkK-fOM5)xOgzny;8o1@_Xn?J_gIxoBJ zXWrw>{GuU{xwfi^aSU{$ZZQ^Qo^Du*{yaZ^VFAH6%l5zRTD4^skJctiCXh)1$80>K^C3!xzbW_(Z=WApP>d z57c~=IX%}Vz+B8M$#~Q=>r|E&yPqrJR|~c=cgQgog_*sVEy$$d|4%d{9>ILJWAH~Z7sSN-3Q{uOUU;HD9`!_S!wM zF5SMbwv-;&t?9dxqO@nvChgq$wov82gYvJ@&cCidpwest{YUG%LbO{d)is8~|5&Yjr|q^uKj(uVCtBQZ2rtskQfY6Zv?byuw$;9XexbV& zpx+Dm{F2thMZU}}`U3FhnI!vNO{FoeQ&fH$%gQC}$A7o|i>g58>8hoi?x57aKLK4B zpQ7PCD$fV0&H{Dzf2DdikKes$H;Hp$_CH_A*-2|rQ3hXD_Y;m?bu-~#`i;@Gl&*Su z-b74QfG&Rp;r@>i-lpr&O)fotDhIap(6xY$jF;`3W&DJ#x;$3{&AG+MohNMyftN{? zO`Iu-Rul39uOVeLzxayuiS6huqddr7G<`ACMp`^)lP}ah3|YrnnNRjBEXp`uNB0j$ zeAM1Lw0X5Aj;)?_K22@js;TzF-yP+LpF2q-wq!Px=K28MD_W}fuuzY^s`LP#g$bio z`9CJwF}g>dPg4In^hA0HZA!|%G${w2*(m zb|etm!+uo^O5Z5glSZtBJ0bRhlqX<;D!U%-HvvrV{K^te2QB7xFB7-fXFB0vQ$JiD0hP5Ps7P z$YzP=n(FY-y}%QtI{S&kT_JyHu%P|3qbVV)f^CB*3v#8a$|n*r$Y(OM{~mi*+^D(!Vhi!-O#jTX(5 z%HJT~IknZP59R;m&Rm@zU>OYb>xr+JJCH3bm20wAmG=ad5#lqjfeD={cl-b7DvS2M zqQevOGDna8_D=V_yoq)HWc&Lk(iDHiB_qR`Zt5m(|75}u2@C*M%heFJr`e$x$woQ zcfc1N(XA$MMn2(;?mKfhBdX3`CC+GKobkBo!|F*mWAHpUdahgv z`97!eETBAL&5@7gaK$0@{R5NguR#5gwLCYcpqmZ3>k--~p%aUEe$aownsCPC0X;W=4ypT8RPLpauk$`i z{Sr~wez%zg2F{RE=`(la*1=S@&g2}rp6%m9ce-V?Qm+l`r%*`W5${&ty$=3}tYE#- z$?I?O^O0qmc$BVFbnT-n{@q&_`HYv|xaQPLZ!A3JTjIO^OO3ZT7OtPV{-rmahKfdwitMMP={Y!7mJ|&F!55=fB{n8s3((@&!ibnT5id48qsv>$@!l}mJ`15$t zX!6mb(E+;p>FT9xke^4t>;2Y;Py4!C59cjzJw1^)&ErgaFe9RXV z@1d4o99mSpsCJQmv~t{d@TE7NJGq`(Kb94Plup-%wpDr_^Bn${)4s2c{_u})Sg)c_ z-#+=$8{a#bwaX$S}fDc7WY$&KdSn3l)v6XU++_2 z+v#f!wSUp0rHhJ2ucf;MbS>tm#z$v9Bt{=QJ@e7R(bSuNeB+*1hhG+RVvCQyEHwE) z|9Vl>dZKi8_=FbqEolnt*B*W|J{m5JEf$Y`Wa+iy-S573@nIUX&X6%$;4>D9(bH%1 z7KI+HAqc$mM%PH*U*h60wP*visQ)C|7@sFb?;J-fcbvp%#|<(1$FnsL#;bjlBQ|0z zI!fPKPKwe0^Oz70%#({s7UBEmlX>+2_LGgLHw9jLW6Mdcy76@UqM{|lOs+K+6)rjQ zvbH{ax@OjA)@yS=6U|@prN-({6ppt14J|7>EgoB}8vQQ#_^$Ciru}7=C>nk02WVOI z>570DO};7TU`^?+{#lmeG)DH~?^oO+M|;1N4#4i6QS zSzJEJYFaPgL^j0oNLb$g7RZbzuc4*ZW)OPz>Nvfyw+org&_|r_E$umCE0da|?UFHR z^s^vUfuHYssiXy6T|COxf<~iUDTK30nI3xRPS^X*TxFq|YiJ1q)~3B=9A<*`BF~!p z+T4D`^ZsC~Az3?UT-9`3*?^4){XuldulW0eIKEBI_xZzr=KHt4fXSRWz$C!=cKOY{dO4MM}@b7!Pq*s2e`-f3mc zp!+tr%43BDzCoUs2PJu|wzVQ_Y5>D%$oaL9Pk|94;(@ zpA%$6=d^Hc2LkMCTCMd&&!~YmEIiuF(s)HL3YbbTntcwTKb({C=w|ARo^Y5)u5y5G zg0;xZ%M$djdb!T+Q0D~b=q%_1e@>PswNq2%c90rCO}(cXOQTxYov%+-Ww4;KJO6y~*6B;#UX0y&Gj8OT^VU;;E%v3Y6 zcBasF)X+|9$V|DC5H@q!Fy^C_{$K1W1k56k@i^&v$fb&Cown9JLdSwP0t) z5j){4SkEo+{KYPhQyxQ|FfpRH5L-!S(Q%#zg;$B|!9Lju_DL#8))sC9r{VK>lg|n^ z(T0u`0ml)(RhO!QDMCUb6B-uYrj0wQGFO)Z)D|1GnMB%5ByDbNX9XiNT5*UmpKJbB z(s^_nZP4!i{sbRi$8s$$8<%J~BpH30%}B`V@^a+q=lvSam7d^BsJ6I~FseIYE3#$_ zSoctyhGjZ2PFSxC{nHzTZ$0r_;;OuMk8s$t2)MYdP{YZwM~TZJ zM#6~h+0$PQ=-M^-+37zX-U}m&gcm&Q7G#ChmsuT*1MD})u^V(-bq?*8ZJk)h2rN1Y z{R5f=oq^ashon4@O&{lD1P#*pj6n1C-5L&Ct;Y>j$cltbo^9=G5#~Sl8y9`#*F)K~ zpcC4@wHsLzePB&^?vOImQ8p6FJ!bw+PE}^+stPOXv{iX^cZTBt-Wep6SwjznKZKQ1 zby8QwSS_Jj!uqPu`~=gLfa%^KV7VFP-V-!zy)=U54z(hE9+jWHU5or$z)}z*Sk$4} zfK&35^sJ!q)kR$5MkJi*s`Rt%NJskeTC=VSL0=fFHl*Hy%pZdW)tDYkZ`O^V{w(fUV5%sy;T^Yu^ebct^@ESv5I}=Kr5TK zzVvi6)U#*+C!1MW3YeFC49~x5)>o;vAR$`x2v4Ocj*D3}FLoZ4e~Y2DZQsrV3cUFwXuwq zyN)9kPeY4fO9h>jq(X{L>Q79qM`mP+h@V8%&{|6enPJP%v0RD&m^5+Q+nrYZxupwQ zwQ-uwbK2V6n(!$x^IQctM?m^hV%oWgcoR_dRRr2XcLqvsJg3?+d%DqaWe`?-bVcYJiS;p6qGPoJQ?P_Uq-56QhcIq_h&FX6MJi|$zyB%u2gv$k} zP10n)y84uudhV3y=~x6>odJqhcd+JD;+-8D*9fZ5v!U0&???>Sma$uG_S#Y>kMo?a zQ{w#{r^Nd@2t9X0s<%TEW;udQ=wQMq9BF2u-uwsNoYxo$#N`J7z;1cv5NHz}$<@yXU*iyb9I`UEl|x zZEXwKBL(spv0Q=^Bv~+FB0p9h`-lh6gFI=4zeG~~#Q%zyfWKAQyxc>X$M*q_Q#OnS z`_|Vu=_;>y)mfnB(MB`S9zNTWjxD&|hh4n6c(ub^KS%JG7Q0L?6USUakHI))>FR3j zR|lt8*4Q;iOhHv8(_W!gaaOLgd1;#6gGO)IZI&|fP_U0Y!7(c7So-ZU8C5Nq7mUt4w`^j3-&Z@E{=4Li%OY`X7hjvwA0+UpUJ%l4y z$2daeQ!6x_6xWxk{`@TWv{mRR5Y;tdhKkn>Uh zspW;s3zc1)_J$T%UWIS>$@vRP{%a-QrsV&n$odnE}jxswhMkWN9OpU zR>sxF89Ghq8VhLdJ5Gu3v|#gG&gjFVtvrm9`O`8hS6is5!dCFAt3HEqn<^#bqUALMt~H9-&0@<*lgM&kXs3dwIo z{2~yYI}Sd_pOt(@n;y7=fAkKRD_L)87X_Hnh|h7z^`a}VE5^G7?pat5Y{;U5y7+;dWNccAQdf>S8Jhy+`J!sIqG1E%ZuHw!$n?hQ_$)}4VT z&sdf<*k+e8jxuZ|HU+uJu?*M?R*PAjei+r;&Ux%1WjrHSx1VV*zl%1wHKup5_UR%r)H}H0Hm}%Ykk;1oKU@4e_y`<&vC4l2p8Dh?cpvb&>xK z-pe1JmSk6lKIVVqi}-o`Iy(cBV+ zm&0OvluBbs?N*nLFbC-^3C+5C0f z%rd5icym_pT6IuAH87i-$Qi>VtqU5fP-b4ep6K;}0e(?P^D3o~&Sx{1tn3$@6hCZF znJlllIMXX#Z*%fhb`%UYc%_N9xUxO`H2=$XlcMKk9UpAKqp@|yV&eO;0o@<5wK=2@ zuPbA6Kzo!j94R>!!Z{~Ga;;#4llKA6<%OS>5jwvtjjnCsM6y?41RcGe+sdgqJBK)T;`mf9&o{L9(b>02NRpki>t%xPLsw0 zGvziek2@wAYr%f@5YK2|CzIHCVT-4l*R+2br|wMEc(u&Y(xo_iR%jzoh^#hYorh>t zQdh3^hNPSH`|0P8JQ+SHnYV?Pveu=+7M`>KqYwwdplNRe|B9(vYtK4N_FT5D#by{0 zT^?W|-qU>&!M&$`qjWv;`8P@vQHg&W^k{0(x_S=XU%>{CR(*6z*t)t=s|k`a-K1}t z?`ivTc~0;MH!j?$O``NQ?Q<=~*2%%46waj-o;xx&OkkW8h7FJwMqdVbGlgtFG9t{H zk8n(ww4^eJ7n7FaLkFc4-%*e}od5b_Y*mN0(RCY}*8tXrmIToH(HUD_%kgvC#*DuN zYj8S0UrGog{$a^@pfK@pn)^|JoL@IJQb!@c+UwuF6 zRUF85JzvbJe7PLyFXKbzr}5z zZ^P>G$5k6N?f+!rV2&{xKrYQW`}7)ZkVvID_===M9l4aac1P0_ky^1(qO#M=C&W0P z0aV`zz0Zf%b%V7y0>&?& z%i%`Hc6%aXX@e}a%L{eFOW?O*ShL8!^pT^S+#B?q zz^^zhtdlKv!&-b&+}42t_vK^M`3*wz0l!{Zl`-Af*V0vf9*m#81q~xR{?Wbt>&aD! z3Hbjtd^Rz{CdjtS&P(MFo)p)e)%n%@$ogxcPDFe;q9!LtK<)cyYwJk-;aN-ZyPYQ0 zT${PL#D=%)rZF`s0dgK~bhl?_jyxC6f{PAKpA4R>Vk7KX@ahV@^ctB;}ab(0pM;K655} zEB^&PZHA6N1iX3&;%bN&0?!UY+VxHJ42Gp=N7!`|d{-1$1kbj7gJS-}&Py-+t^(|n z=bc*>zp+rtG>-TCxOnakKRKh&(S6_az(WFqz96=1R&$t)W=ad@4Atn;o|Od`mJd5n zf->?Qhg$E?ctP4=!5KRxp9Nj|`^tMZpi4Ve9%}tv2Dik2kx}-mVJg!Se!h){6`Xxn%>Q#;}AUC@!uP(mR zswcbG%eyK#WPLbzNMb!FTMcWu>BECnK<9XCSxA3r&+-%t77p~>UJPql{%VJALSrkk zG`2E(DmYDP+!n+7lTdF~xP;<1j6{MNTAEFB#gMzQYmXm#DcsV<`WowsXgThTXOLj* z^3*|lxYC{&#O`~tjUhY+=NWwZFo7T5Tfvd1Ui;O-tS}nGR2yng2C)c`@Nv&5|H)Pc zY9<8%##Cun1@-Rn*}9Oymk%wl+gCY|aJ;92!(mcmAMjrl9OnnS%w-5aBw)=|VIpe~ z?mr>Eb$)prc$Q}EX7whGPhCUKCG3*A8d=E7zlV;UhI;Jk*U%V4H5tv+0F0yy_$Z8ylTJ6YWW0rml9|&A{w@@FZ^1PvkRMvFCMjKWPV{6Ic+#0-gnOI;9bN+8u0ZixYLT4{yp{cj{{b(-4SHm^K()I zg*j70acM{>EicRgyVNs3$0poW&g3=hMJ(N0%1L?$P2W&X_UrdX$ca>bxrU2VX4dfT{Y74Gzmv?0G-mjZ z#Pc{LW!AnR<@pTnACkuUc1l*D^ERwY%jZ0%cps6^>V9O^`H+xM?&Zj{lhVXSO{XqF zpQh<#b?Z#`axdEx4wp!yUB_FUDfgv)z<<#GR-#9^=$$KNnecU;u5-<({dx4IRD$)@ zha_Vd3ndbv^CvH%U=dhu>Ao#R@?4FGlYs8|!QXT0oeL#h;tKHK)|d$ID!~iI?&;a% zgQTYgfI$sZee5MCUs&)b(W-dD%z^c@}2dgxxVdAq!~>2?hOxE7jfsuB_|& zFL31;<;pN--Dyl~sH^V)9S_<_B5)>vd#vkZt2+7k%tJGtaOft2W|{_?DOu}#O|qgx zlF8?+e@)5;o09PCEQ|vS)UEW&lqUn_k7Xx@WZW9(t?)bBCC>ubWl z=i)n4^rYYVopR3!wokg`zRrNY76DB+N#J1$?*pIC2h}?XomMD)P?GVfs@NLcc7iV# zN*|WIT;Ay)T2zASnJZuMqZmJgtzCo@mO-3QcfA6fc$sn{nNcg8@YDP*Z$&0^@Xy4~=uE;_hc6$S zhx-VQ?>&YZa)OJ6=Oo}>@_NwO2KPNV#*j0ez{iCjrx=Fg&%xIGTr!&Wg-N}SJkge4 zmsUW_rL-TZ%RsOS++X0ONPSKUYu#n)(h7XCUaWyhf!5 zWT}})*Qz;+)Q}pDP@^#D;i57*R=O4_xCSWDF#A?RiV4njnH~ASn+SzO~EX8-YxoZ#-=6dZ`k95!zKJc z-mUuax~666@vgDl_1w?R#FjuwI1IlNhkCML87+_JQYN zJ@`G1eu7`}cO%3Y;%qz-e&^ta@Fu(z-Kabr`d5ed;0AmEe}%un$MJt~3+{l@OSl^| zjDeA{B{OME26G*A6ElsO!Q8{V*}0P0-CcfRp5ABIe)q!Nc+ARNU4R+0aGWkMf%Dl_ z-#vHt3@E`9eD+jGbGb-(-s8wk4v~_??<()!*7*?DXKR~q2Gfl@Z5Qx_B)d&m?U@7f z;Bk+cQws-rC!bz#2Roy}nQnHKLuy#L%AI$UJ{Mg`C?}o+%0O8Waa81FD_%#e8C^iv ziFLp!tP7C6l1iv^MFo*_n~+q2^USWq9|QV2jGt9IMFW-}`@Gd{5D82h*uj z%?vZvMxm(O>E6~khe77-9CTq?`4270LJlfm!pTa_A;$Tm`OYTnAjL z(rYP~UN4WG677_$ot>3 zCY!A2!WSNF!QDs*7wMqxKdH>k?p1Rt9~wv2Lt-zgYLKwIS5@UWP5SW-^zKU9qhpX- zMN>y0^$1Nx`RnWZx;O}9_43F{TK*M4m^oGm_E;#EFCl*;ee${Tq_ii6J~<8f;q*xu zQjgNqsUkCIcUJhehoLY(!jqfBQD{Q*p`J@a@=ZM*LuxMT`HAKa)8{H-X7@>&|5|DN zFFnU-p3Ep#P?6b$$;<)%)R5;_NGhMZnLq?+4J=IW`H0r|NNI6Z&);djLBVM3*)fD8 z+P*!-yQuUgt3I4bEF2c3x7_tlR~3c(JFSO=uOq%N!Jh~#5sU(?hcL#NoRLh~b(C7T zQ!h^3h1^Bfr!VI1lE+v}<>BF=ss?W-I3A9?+YCA>h}`#B*-#~5C-y}W#rskZkzAwK z!yTn-AQCiQSvxRZq8-Q{Es@omsI4G*ys`QBPH$C_ntOt-g`dD$NM_0>l4;u+inmDm z&l%FvI_Sr;W|DdqQYAF?6p;^_dJ9qPJ)J;PgqBOa*k|^W zkx&UEyQVagT{dK5=^ei44%Tt;?0EvuL(M))3GtTmo6D#KtV;)bo!S>Kd1NkL3w}cW zjfZ#Za&npm^yundnJZ7g(|dBSZ(uyHhFL!gw0&oW36|S_8q4ve-5aBDG|GmgMJLrjVw690a6@X=eN87^KhS85-BIE}9 z>2rwRf>;Z>;BOF@Ls$=i@Of7^U*}cE&PwrT#qgK*O8x=tUs3Gj1dNP)M4Z>_8T2&J z1JsX3xuC&dg~Fo?K!&gGCFjGcP3Q~?ya+Umgf@pmNI(du0WE}{C&6ZD_yVC@;rT=e zDeycI!gEl*3W6aCBQNO(1RlbkujNobC_Dw>NeDYX1APZ|njrlXg#TWJ(Xx^9xe9oS zdGpg6)7IGWcjO+mj!WXwlv~Sa4}tK4oifbLx?i=ku%hC;Uz*7q00cIAhm7UEbH;N6 zR)oeU^NoekotXpu2EH}THl#h}SP)dX@5~(?ye)S|aCYwOP^DeH2??8EX3U0}vED0l z7zwBP)PCL-ojGrKuzLXieVBxTk}k zd7oF7FrsURxgXB83FEv}%7m4Dq;6di(O%9j?3;d?$tgKvb3bC86?&h_^cNu0C6cv% zce;EASS;20y}#MpvdUy5B7RYf*H!XRQnS4CE%3Z_H^KdR|0cO-9AmkThit zxq|9{O!R+OHmp@>Tq?*p=%^mKKWcBhADj8*xJFI&&JBINVG`%}$QUmva}5cChiI%5 z!S*l)?@=9+xs?UAaX8+O%+{62ygQxssjF2!7Q8IXl0Nl|;fU40g7y{(_CD4J^r+*( zD~|6p8CsQDpbHXSB4LeZU{vMOSvhJtH`pp(gdK>9m|XgN_`1uqY=vcw0_R zaDL9T5TSZu-?T83J@ZI`yFf7GN3yS{r6>C)ht*pkl`Z#uZjZd4{@KIQ8>tnrX3izE zOxV*4^jA%;!Jz~v8>H!X{n)pteppz} zErcBJC$OxL)oXUC=}N;2CA})JUAB)T|7Rf4$r`GYwK1KX(UAc2flVt=bmmI7bNrY z>xjzNK59wW$?TG%D~6^EG;XqbCOc$*<3uwGqyvwhA2x7C&T^HUjeng74Ii?Qy|+JZ zYuD)gAk%Z&if|rxT)e+S&B1zEZw^BVIxbo}n*3_69_)V>36;>;GZ+ZN9~%eV6>9BwaXvSFpY*j3G=_BE)* zHE;(L#Su^LSuWF(&iSBsuS!$Oy7_&)-hEg?jYlLD22RZtrm>Zs-`J`-E4PgT$p|AO^gZx_W|x}o4_4Z51Zm_!QZd-%Om#L{Av3||mgIfn zvB6^$>KZDunG_0TTEb)pXyj#eHYjzHl{)dXj)6k)TomeQfI>LbOx}uQYX|mPftm?h z?HS+==Z(Gk$c6 zc*sxEux)Q@y&Omm)OOA^L`AT1%7z>!;-{o;9QN9AxjM?QG^&K4JMb+}y7 zJDM_fV-dkE?;(N57OCbfQ1g$yTB`32BO~JBNDCir^`4JV;P(9p-3dV>JQi*Bh4NbR z7T){znP6Atxo@*NLyx3?CL!C~_LP9xjm#&+gqAA*+xDA-kjvWES&DVpH#hyzf(5l> zQqd&%HyhQG8o+^>;T`rkfV;=43&~|otyv&7qk?LFWEj@LEE|V6Ma1*{we`3P=V4zH z)e8x9|11vl0@N`tGKc3%<`QC44cu{k2v&rLt-mPv8FO-2PGNJrl2V&> zN=ju`DJd5GMGWf)EBvcV4O*XQtebnP?bsIzYB(KTr6b}Geb;lJHxHa=Z34Yn=Um5; zdq}B#iZ5z?!@V59F#IGZ*q5m#*DkP!F@W~xH;@w>vTqD_nU`Q17SvS5`LtDsTJ;EU&YeE} zilBbe(bgh-sMUZEwmK`-RR<+29!0IvcWc6H^+{pv7Q@!VXVo|#F#t>U&vV7OdEQyHvelK^G`B^BR zzE5_O&SvQK?DmdT|_SDY~>mYAz zL)M~T1-F;39E<2p&f{WQ8^HMIv@M0TV>^z6wIdGJj_n+9hdBu{fkzU~HcH5+ukII5 zQyZe^3^J#MVNPr{yY$uM#>25*!hwjmt`9huJZz?E$hxNrle+)xMrP)fEBO>^Hw=&2 z4Vu>DBI;l{0^{!{{&l1W1xA6cs!qXZyAh+aaq@Y!yt8Psq(F-c`Ye17ub!zI+>)iX z!3_2G#>M=K(U{u`zJtlV(y9W_fi)ZGYQ7buC&j&RECc?K!3F*>+Dbi)8M)CCz|atF z)5wv&rS}mXc3ezp%}9;jPesC)dl3rxqk2)pvs^rv$5;7XJlFwHHzK0Gd_JMrI76|@ zM+2S1ExgXfgo*yW-nETKyv~onk~Bj~zONx`&k@j<8*%I|dmO8*nRkI@i?ZhDEDFi? zFW$t`wGM~Sn8YygossZSH?kIna21!1H_N)fMqzHDbv8;%ah^Xz3oDiIX|H@n8Ep9e9|P~t zuc=jYI^GBt5nh#({iQ)lq2Wn5ZQ;#V~|;$GpR|HGcj11jyG6c@|iX^ zSAsTqw{s+e-@|6DG}1UKj4VF88Kit$XTIwAZZ3CA9SpwsS{=?ERvN%3e4Tq~X$@RjE!RH%HJJ$eEEYPPVfw zz&(5RC~9ZnYGO^^0a^g_-1K2VCr4!I>7Kt!YSWLa4y@P)G1SDMPinm_C79(r61(mD zX7W~te3NdiWN--N z>>u@uclOBGGw8g!N0uH1r$)iKaK^kLIE~cDVua*=O*nsY<8GaGLldEVE9jPEb>tbD z9kN$r4;02)o+r8eFlX13n_Nq=Jyy<1);hA^hsM~$Q)8t!N!$D~o&BP=XF$g9QDppj z3aJv#N^0(4GcwCF5@j_s|C+1);@BSKtFDtd`c{{W?E>ZK`5_!V0zMB~JHVeW6z-?e zmQ!NjM-hlFk&=at(n1c=2YQeKaOBQN6fzljhafFOu|g#B zTTt^ZgE|}02z^1GJ%0)D;p zw}Sf|et&2gCS;@QhWveSS$^Oz7hi`Cp}X;3^iMn!(#vUS0lFPInJLUx)Q1kiVznJ? zS1kOs3kj?DzulRS^wvh9su zKMcRe%a>$7eX(knv6Df>*VtA>*8f@1Gi)X|Vy>^43BT>-55n&+n|C ziG+$gl=Wuk1B@;QU3i3^KkAW*Rcq9mJ{9>*Wt&yemL8>)yxTz9Sk{AtbA%?-9Oz|9 z`3m^u${&KhX2d94O5tCkP>;d$%!&u#cT@R;@OunkkPx@4QzFzy-k1Aw zrk~`b_vOA2O_n4rfW9oCC;J8l3C~mfj{=^b-XF}9&uPu$3Z4Trcl3QV&F!PPLkiXu zOTTy~Qc!Gdca3aIFDI#8~n~+vl@PHSaTozs@5!n-=sBo5ie7=ydKWDHDbnmP`G z{8!6MdHe@q=@WNS>5c4E z#=nn_|4y|s{{3Q7q@}opp7ohj6T)Oxl)$X;Ron@`tre@`cYDQh_+3!3GKb8GM-p)U0>)0v02j>b?Ncw#*tr2LLu}sHIWy4^ z+}F7>Q3JmZfOoL3b6(=p7jN1LHnDGjZ!gkYvVGzKdeT|GM%~F6kZ@zeLg>?p3ewlF zD(;2fw<=1rZNjOF!SaC=YLj+iGe|1Z*Sy;~j?unHD8IAo)Bi+ar*ln`F>isSyH@}H z*0hbLfjy8(eKFd8 z2W1s8h&v%SF_v3I&dFoB1&~{FI-0wUoT$d0l|arF%gu(|9kJXD$jyu8iXf*VIXVjD zOlU`W5MjyCi2R5U=iCTS89z9ZFqhGO+d34tf zVn_Cip56ieV>6RTC@GSAic`=SO{d-N+A4Eb* z1=&fo38o5pFOj2iMouvF@(G6C3tS{87%)F67vJrXIkD$GnTscT2(AH6lC~C5&GGJg z|F>~DKxOxPNyhk+g7NP?1K9k)J8{UE|DlKAUiBVJwUQCE(uUsZVl`JyS1Jbd(Hd87 zjQ4L5d5q;=hg|B9gR$9^-pqZE;FjqWF9_g*uk&A8t2;k#n9_73jO^px21|E*nb@e=#%=PnultqNc6?H;OK z2@O{%G>qL&zNA8^z`}6pr!bkrf2u)fvq=6ETa0axz7|49HRu5dJ0ZLd;QB z1x*R*Q zo>MSKPQe^`;0&SmpwgpbHQ!T7pBoxMUG2?7Te!bV_FVeKv~IG$y=vy_ zq4(Bnw7v(!19gg_&djdp{6uuGLywouST=aC!NNLm$#Wv zSwsDheboT*n3`iPc>sT;i{;d=JdV^j)J5LX$D!eLHVAw(0Og_|#7G#GB&!cO$x0=j+B)r&vbF(dmTOSGgHDGOB z&y_1Z*H)7goPP0ZDT=WIFlr|%SSQ}b9cpFjK}U6^HXn=O`Kf=8e-;Ot$ng8HGkq{O z-jkx-xQB9ME~kchUEke(=F?d1Py18-3pfMRo*F(7E8W-6*9B%h>4=EpUgjb~`7pOn zyp7N^5I6{HIuRNVWmZVv31R4jBc=Kpi=uwAx>JWdEhV~7q?B!spIH~9Vj6Ja&$Pc! z?_C=!o!oEouYuCq=89O^c!2a$$fbKdvC`2{`XnvAXYUiS(o`s2O-twRT@@>h2ds}l z=`+ob#mZCw`7ni?x_4!)RO(ChFQ=sw_dXOW?dUW6AD|pl8J0BvF;;%M&*bN!{ElWm zR`xBFErGH*%}ZishXCthidDb2G*)^5An$?F8=HS0E87E*cT>oV^>@WecS7kRTH0EF zd#v;gC|y8HPu0(lmHq{=&V|y%=DD%57XWfLh5WpJR;;ufAZI{n_nG2YnHwOT6!P!& zg|X5H0n!1bKb>*J%I*co0t)%J`hgj?2ug3Ir5o#SiIvXkBXabQ_ou*)Tht03M6u>f`Mh4=@ES3&%5h|3_ZSIXakxCG)& z5Z?-MImFjOyaM8p5dR)x3uzDHMA9C_y?;aK8i;>_SZa%%zciHB%BO(omK4zX^XU5p z--*TTqj@b|LqO9c=cLN-F?|q;zF~#}U>Mh}V#ph`HF7NmBh5-^5dJXi(;5;wR2dYf7PZKDf zu4Yaz`Ks1jvd2CK=4b@!;FGPWirj)Ds~St+#-#77hS8XhrzZ!|cqEMT8mKPq6YKlm zFRm&Y^gievjgrYT@-!N+3tSJpOg&vqIkB-w_V9OyU!pXB0W>F4I(K`Jc~4k|A~%2y zBe#XY@76)y^G>@CC0QGVOCEJ+vL0oc#)2>8NtIaioyeWX6ETO(DEsHoPrs^hVo;5@ zl^Wv*)%f?28f5qLpHRa9HFQwpb)`nipc-`wjrS^V!_89ii)nuh9H-=obRYrCPT>=lbR#1QgTlEG=UkWAYbjfs#qWM^cp3dr%^Kc$eE%1 z4KoxdAT~CHsSs{~Q1L24hh77n1MxnH&p@z32txid2v0o+el_GR5Qal>8AH41=`s zHS#~ZkpCeap>q&SP(JAlqTk3HRm4Wu|L#40az>?-qUTP%;){Lqxs!Y&JA6` z3wqVuRbi8Ip3^J7+g;@!sJF83B&}x%%JtPye|a`T>;Jo1zSmRRQ2z?h{mQ@{IUn~d z*d_hqcRkg9qKo>)qdgu!*k#lP?h|pJu2?g8zLkL&xklz1xfPcKe0t|UgTK!nPj6NE zd)&&sUNUP>^=gM=S)?f?IOMb1>&ZUp01o;FRsv_Tq;tbTM>h6a+&S*+c#s zdgaC#$sOr(*2yhi2QB7J)?2S_A~%E4m{vNj^yI_m42}m`ptse-e0~8T6WcK5-`pV$u}qVL&<3Rti2EWTKsa$3AC?qN?#p)$mj7# z`|0l|+(N?j{m5rkN|A6yzcM%I-N(~g!Je!_XvtPI=o^jlNTph;=t#BqupmK`_$Kkk z^W^4cZYo+&?ndXpTJ~Od^j6v6y9o06xIQg4fU~us!FN;pMc-cRzAyV?sKC7_dsxt& zJt0_@-4VP0P})!4IhjiD#(o>Y9QmHfihYyA^7DRi1&lcvfqwCUZdaX#zFYOr$mBXt zOeQz>q!bSuaz^28ap4g$3?kh%cwOWycqG7{`Qd-r7MVR{J~xT!=YPw#_;b&IZE<)LqW4ea_R^s} zP0wgv6RX22Ybh2U=ppw>{tEE(HX}6nEVoZQ+fDf0B>wl@z*%m;_{yHk`_k0?TYb3+ z`f}%>IjrG`W+HFiG1(Q+G6z#luh3yWC%^<{ybhu=(-u|fN2!tv6?e-9=?^=rLoq;BWW<> z(`FMsJ>{q^JO;ir`C{A^R1XxV*A`}%>Dw;g_o9* z8Ccg%>XxLbtePfs>>blS@!h@AF**u7fAd%*vUnrdzYtiVcrWe8>Nrk2Q&)tnPdHNP zsRqli0SmWyBzga&Ph7hf1r|WvnVU$Ryy)rv3(wb9a+xr$34A^uw?5d)m_2DYPj8)g zL{)>#I_rqwu)E*v%u^f2G3`ig4d}09@*Z@*-I>Q4#y%u0WG4q660T*(I@osAFf8Gl zeri@#BVmlh?o721sat&hwGNd5>@mwf&NUid=sg z?|PZ^!CfC)7YEUq`2QQ7%YaTRrE|MNr*#mW7h9urRsfxelulEO&h2NvXayUE(wP~h zv%$#47sbz3bL0&_S*poh=N|D=pFSql$68e&=R?1TjR4P~!;#4I>j}QzJ;5Qm;S_me z;aBeykoh$U=GWi9kKVJ^##YTfF}q8iPx5`0jCvG!Z3Fo}5-S|qBim6%uv|btnRL+W z9`PT2)~C#MExg-L=zXov3}e>H)r+U^rYDf;w+BtPBQN4{`7 zLCOr1c)U{jYz)gO$rP*IB$4kf$`I}t#37~5LwzljbBlnIY)eDSN46euNyDqqhkG{= z9xdGyz(2LmO25I( z1Xx9rH;IkyjL_Im)`cC-V0V5O)u*1sa{9%~S-g=8wW_KBZLz%?AN% zLyIm^Xo%1>BRtW+8f0M&1eI_x5WR;79;?&PY1A3Xw~=bV8tcUR3eLtIlE`;ON+ipy zCmm-0(sVPG+iRpzv*k3A#Au7Vdean33(BZ0Ms+SNky0qstG&sy%$&TpmCelq7+eGG zwBma3Pb4RO|7;$oihU`qR}=#B9lqyZ0#Dipo=q?kX@~d(gzsM@{qWJ7Nh;tWGOtNH z0&7uR+M9M&i0Im0(eM$uVKlH-$ZsVWXA_ww^c!L`h`gcDBhH}j4_rsf2G6C6uOpFa zpkWeib75d8zN8qw#6kElZvdRW!nhb8_*mI*wQ?P_F%R&63+)77AnjxX2JVgZh~Lw}Z#a zRAl-M-S>EpF~(Jy6A|&*i0(JXjs<>%4n-n=hIsY!gfEZnSH7q8CnIO|8)H5~eZMRZ z>qhp9b^ZLGtbVOB>w3la`m2?jdOhOgeG>uCM8KCzzkD_;l6}#SHH3jEe^&z5t zin`R`EmZmCw;|)hM1Ot+Bh|2- zwB$xo*}4{}vl-yYdt_j3WwD%UQ=d4k$F&bA9j26}yY%rAIej8; zi^=y#M}a)WLvV!#(@QWK$lgP;Y&q`VJ6IoF>e9p{_wK%ym~^(ny1e??%kPn@gr1KE z`-#d;Xp=n+3Ef_uds}Cz3YmxJq6-(jGl{hjf2Z(AY0sFL?}>yRdr9rLp|%^KUZ+t12CQc&)-B!{Ze)($ z^D}zodw!qd_3(F?{_4@UnA9O>AG>IsrvcZafa^~b*FJjkPRbvK@>xJnr-$_9XV1e{ z@-Fg&0C_)!BwvYmkwX3+ARmVEJ8AieSou6}F;MeZ4iZ{Cx4)Vp8&7Kuj@*dDbR`UI@O69v4cT$)ffO*9FXmANU%cRf9mnX{Tvvhby z=oCEUmfi(VnU&nsA~dIX3A~ZQe**AxDLf1CMdaHk-kJ1E4i75)pAjsx&JJD-6PODg zr~7dz*V553dH-N72tGnnWQ6|Xk@wItq2?StkcqT5k%HzWkd)lQ+?megot`qmVB{>YuUHPMRWjLF#GhK}h|Drv3=24PhqV z;@T+j-i=aO=^Ba03)(bD{vK)>Hp8skue`nfriZ-UZe1?V_Zzxip*R+j+gUV4Zd(13 zrpOJfidb1GP0jrkcc<1z>)#!Noe_?5@XfwG{^-|az-sC)F1|4Udq9N0=665iGK4dp zLufn%4}>_-GeqAgU&{l}gJ78o_-quP4N^D7Qj=)vR`N9rrR;Lbaw%n#$rnf{#3cGH zlEDyf@A>WW7FwQ9Zi~^HdB1{qbPrf{z-{1e>ATI*6eEo2LVoUtu>DYzD@Xg=$=upa{vF^ zA@~1b&AqJMfC9B=2-LF6pmr!wZw-OE>oTY<3e<)nP|nMs)+$g>4S~8oa5;~0rykbi zqg_#Jty?VJj{>i*B|KhTe>rR%!0sOeI|E=>Q`q|ySk0ha^70q>%PmbCT#mT%Duw0?dd68Y#Egx-6G`hRPr8$=*JG zL|vpJ#zShi^5hk; zQ}8M*^kaLrCa8&7*S%6pjI+-|8){198++t7jGT_*e@VgO?o<3Mu+x8#BdOH-hwKS4{*zNqIhvkSah zi;VjgkOFSc|9S7GTO9F!*}HLg5lZ?v5(z#{XdJai{{JpznR=qk@%YVU?Bl)sn$pYV z>pGx$-k||I&%>doja;68OwoY6b5drED>kW08i}labIg*wf$o)bi{JG&Nk(+ltn}GW zI-YVYSN#88@c(t4I@;@yw36;U^ok>;Cdq_IzutpdsmK?DHUV@Bh2E<`M|FFz$n23< zpZ6;e+5zFO5Gp+gS)tF2@D|l!8l}&_)mL)A?yvuj&j0Aw271JAB4nhy#U;JRTGh&K zRgd^(fDu;5-upLl!;6N`@+jl-q@%j9iSA@1%_d`%q(~PjB_mv07(b}QL`#ULm>ZpC z&qc>=2hhGM5Q)584FTrdpCKeXMf!7dfcO@~pN;As!~fIXyT>32zwEe_ND)ak0jIXc6XSTOa_prYCaeJ8Li~@FeO{D1~$W0dV zJNQm8ztP_MRws6s;x$1|7wnqgXxLu6m-)w9W0CE z0%eeFkgIuTe<7@q^>alc#JTzj@kE*2)mI25$>?`c=+3CU^$`5_eAt)|SP0kvco%ST zrPoKxXWyQY?~aW+-+H#ac4x*Hv@G^_{O9|^G*Maf3>f_)r@T&uy}#Jz*uB2m`I1p- zyxYWWuA4>Q!a{r5bDiog=lU>bp4{;zA%!cb?u>W*`|17~?j`KZ$EY;iV;5SZFQ~TB z-F)BS+!JflWMAw)Ny_9dE+eiOA=WjUg)$v3p_3*4GuYFtA@~H40={0Gigtx6l z>`RMTn|5{c;Ob}3s^t;m`yZ64n|IQuLWUeni+MP0aPwd{cb)pWzT@3r_H$AGyFsN- z=s$N>t%#VQILIZ@uh=U!%{z<6E1R@2%{xh#cLcPzruT3TB^rJEtxp2y_0i|Uedj;c zb@=DEE8Zqe-!7+RP1-44r?s~Z33_f~6m&oG$)%2)eqF{*q;K5xmyDYfdd(94X*ggl z`pG)LqkzY1x{sUr=WBP4`kdPR)sDWV_l;aqcoP}%?n(K`PmE8djS}9uRBP0_N01Ax zw`{){$AXJ;|g?RU3y6dM-` z-=d6ibCK7p!uBbBo}vCic!00mxPvr3QjPrv>a(z#)>X<5X`i^V&EF4(ZVOyJ%38+l z2=w2x;lHgH{QmpG)~oO8y5^L%4BVkqceeILsIMp=;q&W}@awt0lDIGUN6^Ww#{_@g zvR!zC7SG<=!|b#*dc6(J`$B8gdDXUXUzx{T@R#9@t)%JRJH7MH7)kwIhFqhBTz6iG z^~owxnrLXBEoeVsdbdw_vv}nIWo>IeVOrUz&w`qZsVneMvPr?14lr!heze?|K2{Q=2cGyR)YC?|dXMqXzYzFpLgyni}Q zzmhP_MRSsGj?<)p8g)KQIJ?>2y8Ar+5`&!6%$X_NcaD6MK0PVp(tWv(b+bIu;gdDv zQs9%v6|YTGG!Lr2DNfNOgI1dBg!YYZ(5p)?Y3|nC1pE4*jZ}W)RzxX>*G6%5>fFSf zyE0Z}91!2nN39(tyrEqtyb<&J3>loKxX z@z3l!sTlLk@j>*SZoojoktOIm#ehYCTlZj{2YfZ~pE3Vy0rLR%kG$7MT72(XnTfK@ zkDD&sF(eb-b#toyyOXj7Z>H&+r)JAGvtEw9QYU?zxb4dQC&_&gDpgYiugbs*A>1f@ zg^)g@Lkx)D_xH3c;hvjMJ@k9l-n(hqTYqXBH9J;%_r<+oy2&m&KAyZl$LaZ2&tA7<*Zh_{Eb3SBts29`wYHqfF5s39bE!2$g!A!_d8!-z`D|AlE99YefK8QWq|p z$Yl)Rx~9p0t!k8bzh7JHKRfxx5yBhm!fgYyp>x%Kw-|CEdW4J(9 zDCzs5>6MG~80Q-s!!_?_4s7<;N&;*clpPW9zS{)U3%w(j)eC*fi(X5k@9+yp{lsJa zGYW7GU>G0@&NHt)hTkDq{fouKbZKSCa{w!-L^<_u42F@qcM~`ju&L;cX*j4m~6x0^- z+AGX=d$xM#6SiLQuUzH6oao9!zAa;!*EW@8-e`5RU3F*cGi@V%^TruBJ!{5h4Wlq? zT;-cJ{_Qpjv&I#Y8Dc+Zbk-Oup?%_3-Q}G#28naV0N^87^o!0P8tA>U(c>9qqqj)1kCf_R1)$}zOyf0l_x3w<2&|kDr2~YW*=cF;aahz#*BlT)udE_poFem6Q zNUx1!XWO(Gc|K#O`8k`s{j}D|R*Fo2mXTf)_OAABL4WbyDR#c~CC?yV_&E=4jS-F6 zLY|vEVXoN5;oDfgstZaV-$Nd6&-I?~UFRg^7t~>#V28Siw%G@gdoTmrjoq=*)IrZo zgrDV<+HH)otE0d0eJ({42kHO~J-3nuOK$YAk^N)4_uQBF{KWaz>?UF*+j8qc@3b@EwXos{21y(_1@TQkDdVD#2QgJ9it zu+HBehdUWn-7zpbYVPukJ2Plqgq`Ig)@t}|ENwyuFWgr$o1WR|r0>2>^LbM}SttUFWwsp9f*4Op# zxZhO37jnz{#P#2YT8pA*d`uep9WqkaPtDcIHq&>+uvxPf{$>x_h}PV;9f8;7$%GH}|yKC^OM}Nb6?NV|(jnSQRa-$*5Jios9YvtY)ESkv_*mBGgi|ejS}OdZ!}#|C3Mnvx{U)Csx5AFTK0D5LsEui2IlAX~^@TmR(YoBY)9-8dos@+S(IgZb zi#g*bM%qg_4Ot$E9U4-&#G{?jJGqu6JK5ffev_}QHQ9Z= zT^d)rbL^~N&@UCwSCdooNM6gNNy_2eX!)r+Ip4BZ9gX_qCXv%oQG82_Iz4?D|K{n- ztf^o6`rYe>}-yN2c~e}uIB)=s%!I-Z68NLmJxfhzh8k9@PTWuT1IN%g($mOsg?{a5?L$CWL8 z2rs75FH;~dE-E?Y)Vm|t{U`ImM=z5on(*d=6#fV^VvPZw_Fkz=SL_bxR!xj$|+e? zTJ$yJW*g@gn2 zJ-|&IQIa#eq+@-Dai}I-!^QP&p0-`a4~*vzwhN#d2^8T5|QzFB>LZigxG`f?MX(uL!fWB92RKngs_A3J6_q;)(OQzOYxw7}}r7=%@s3bHDT9Em5bG0|z(DHYRDvNbV}x z!^B8p!|Jpevfk5L=_%g+;@SR$zJVttA}pPodi1zPC_TR~Ow@bD`Q~kTr=l~5o?mmW z|5>H-g|w@`2-`SGgLRpVGlo4fPLpD!U-hMPnHGK5(>mM3O(CjN%`*O*Zf|ox&^qI1 zE}_r9u#K{-!X62Co#-QPCj6=6VNVj5>`9j6`8IEz{`+`;)TTwO&3TZ5!O$sE_-|_t7_{M!*-- zyELNDbD9XAi&Hi!dFHJ>t;d=ecKNOyz4}{3g+enjtN(8gm-)X#KFd8MlJ@PilYL($ zysJ1-LwiX+~%Ow~Rk|eBE~cdz&9> zz#ONUk@cizsO0Mv1BB;^`nB~x8yP|G10CMNVgBO6qnl)7`Zm+IdiL2j&cxGuk`qbG z6zYZg_J?nQ3m>Y%9x*M>ks#}ek58y zGFa>XL|cEssROM;ej-h0-o{=T>kuRG4_GVgMOe9n-k(myZ_|cX+}+Usw+9Rgp=~TD zWG|_NHyn6cbsp+#{uz5QU-P7pV+?Zq_RLV|{(T!E4&-$o;IZ4-Jie}>FV?e>##m#& zhw0ZZTHKrlK3VuG0caQ%il)ehW|Z^wGtO>#eAl@Zl@$HEGYWHmN zygQ4a&V{cCE0cDg#F`X4{*)01TFcHT&T2{CxhIw$Xf^)CX4G+QbltHYb3&T`owhr} zH3Yu4zvgbE8Y`{jMzt|c^PUjqiwSx+m&JUh{YQ_-|1NuC945%{;KN?rNT1}Bqfc&} zWsHHh7~RJeHaE=08|gWhv?Y{FrRlE6n>Src*3C*0^1fRL)9Y(AcUhMAnxsVT0h<3% z%|^`tNO~=xPs*ihn%yzGc#Uh8PxgMVEN6_kO(~q|pzF%nx6yT_&PbmYRy5`Qx}^B? z-#xZw@4C`>-)(DVaanYI@BC4GBc*ZFlKNTlZ0h$&EWP%`(kMTBKV|JsnemY&QL~ta zkD;M2+s`D+VBTTl zEc)e~z8dn|D@&s^su5hv)q)Lw-B#yb$@#y-LBHYJe3A^U)5K^#F;Y)J*X#5v?CF@3 zNXr{--JVAjp2HZD)nD)%-fOeGk=en+gK;lsURi9U@3Y_CmfXl~R5j9fEz|hF+oHD7 zyYgzeuGeV~wEljIe+#|=HXeSPi>-BMMNuC?pSN2Z6VW_7Cc0^09JgYz zoP6J8b(kwzEq6u6DGrj;E8%45Q+L#7{A=FDd`9hQ>N8{~4z%t%^%o-{@4borQW+sv zAUx8@^1UDV&Jpu{uk_GPZ@y^=-wlY2+tifej^z&td3IhjPt9q1-1EzU)_YHlM;^Jz z^HT#MYJ^`aXV2<{X=1Umj?^^#wx%Ykx#73knlbw}xKqhN)Z0D4@bF}VJ04py%htzHeR5UjrU zC&lRxeO6bAvDV^UC&@x@52Tj=uDjS;?h(QAVX%DvNz&AgHa+nMAqG9xov=H*jNMPJ z&_rc%FUel^K1)RS&rWh=zq^|Aw94sMT}E=kv#_ykaYi{jJ=dg6W}{ZoK)>;Pp!MmK z#c!~A0zRrG%*~5mva-M99m%OAtC5zPmVQtpX?gK9=OQgnpQfc(HPUi33Eey1J>rFa zmu10cy|fW)gkc(LSy&w{&6c058|8mq(%65tT9c~z+O4d+Jp;4O&x(!w@Q;NrP0+Ix zamFxVbr&w4<3G@vb8^q?gv6GyzNOR*$R2`yeSc$|k$V{a`e74vult!iK~&TW(^Ve( zCek<~_vbI5Ntr@>%z;+bNz3d0wak4DeI8b57H3^1oM-ocuUT2wXY&GMi4pBng7v3b zv6;?)^b1E-%?)YJ=5Xv^xYN5hr3O3cxTr?CksHtLBcsb*_i4!Zo7~C=qW8;NYBSSM zWrmGksLFWbtmlTo-%$$IJ&~Zw<)_I2xu(FaD2m5E{2sYt(oh%HOOe9&R3ot?H^}0L zG;{Hh%_Kf+pZuyF!neT5$VqeW%sAktPb6IKn&=BFTwXdin(p7%VWs}Y`BlGHMJzbg zFFd}PoL+?-WG%It-RKu2KJAo7HYh{cQk#}_Dor*!WB17gvAa($ydJBy(JUu!^lrC# z9yeO3jVIXm#v^4{A~Z$ZMfJ}bfWACn_JD4EdBRD0Z20LwtK|e~ zx*BaT1AQ)szK@<=Mq@}N$H}-*ziYBGd##2wMZt#!m9Y(|O6{h`evg_4G`VAoN^n68v z=2rLQT9iLC>r|$4!0Fv#%F|&3DwXFl&wP0@y)s%CbK>}bU2LqbjnR!GznW_QA-pGf za7ziPBM)Ojd7L~+o+9<+Ir1WTiM&EyBd?P;NeS7C^auZs|F)BN$h%}W`G|Z%J|oTK zOY#-@h8!Z_lOyB@a)O*DKa;cM9BC!zNe2d%oD1h7(76V3gSnwxG`9|AvCVo0^Y=BX zQ3t<25!J$z2J!}Zi)!(2juzoqAvu~Q$0d^EZIYu&ax_Yg z<&tBWLkZv$+1XsytP}H9dD5w7fX(dB*&X2$D1U_g_7fqlH&r& zalYhOC^;5Lj`@;f3&x#R2(e?H)w#Iq+V<$AAw3?*n!Lb^_i8`~$EB&`Re+U%8o-?Zn)h8U?E^WARmwi$N^*nG=OwKD&PjdOu%)3X@F}1Qvj0y ziGYcKc))l-9AGS9G+-nk7H}ot3c%%np@7q+^vy=~hdtLkjXl%T*e^Z(1KS(boe9Lv z0_OO6M}WDJ^c9dqdw4h@Ps+%k!&lPJSKeSf95vB;SjMNjICcHeL4)fLUzSvVnDF&S zDKAG-csYM}>@x^IgYa_*$8y@kv0Ms2G8S}%pF#LJgwfhZMl(h~h+4+ds0<2o*;qnO5i;-Sd5@>BJSG0*K9A>gc*@Qbj}W;_ z9+m21yanLRmxmKFobp0eE*n%2&tCtAY>?}H=y`uA^eCI>9wEi?Cx@Y`6t1U!P&Pks zBogZhsSbri2Z?fBMr{bch^!2DDX}k2o9{U-tKE6RjkqiYbyZw{n6uR%mTT(|Uk7iH_h!(DY_SGgY7 zje%?-|ex#4hb(pA+9-*>SPdHh8SP46nmwhTbKMMepIU=>lS?|UIj%v_H3_;V z^+6vbDGObckJEnOLf?R$^+)ZHA(W=3G7FAgfxh{-hK9qpK}X-(LRY`K4_wOHjjo8g zmt0)!#v`Qer6UTm-W3-0f~z0$>Preav`uV8RDCR0yx@qpUWI;GTjx^nPyHaTd&V`7 zwkyI5g!~qw&wuP9t_M#=c8`*6V5;8>ZATE z>gPt(&jLkvvKWBgFi`)x~zVlI%Z{RlsM+AXYJCE zU4QvuV9Pq!MoouD8aHMI#y59KZ^;depXm}mm)kpkOkQAoRF`;R7ygtk>6^O58@j|7 zcCoh*4lSU3h@a4Q)NpX&qvmzgX=-Mj_KEzbkrn+eyD`eDW>-CGIrEV0R0@W8dzoO zsF@7hVq$Vpw=sIo5=O5#Gd-Itn0%y#(TR=4i>sJD3#-KPi19UId>wEU_+J4YGK}6o z*-;Zs^IgW$Cof}qGM2M=4zL30yTtefV1l@N1*0e5)ls7at_6++j;Ue#ch@leWF^yo z5I6>S|J_XgntK@i+&wIQ=0RrXu?JZ`Cmv+_l@BrflOJOG^$)Rh^FyLs9kWOMFyl{o zgr(1Tgwboo_$J^BnD{O{%HmP$J8ImB*KJ_&jlky+pYRx?*FVPiTOMP2G9G7q+Q%8) z{W#0N{z=BK+QjIuJk9uaJk83pMU0;jP`d7c! zQL_W_^{+Gf^KUS|O>Z!|dJBuIwutpcG3drOJ8HH7uYRkeW-IWPw^+LSEk-Z?hghC% zjQ`*^u|MwYsCk9Tzr)f~nmTGWBVOIa=&D^TKYkbEcYVX+2ftzbyMSvEUr0IyKCQg7 zW(BP;MW;X?)rZjw2Q#|uvQEK{=Ygwfe*>m^ltVgeoYelIjIJ8S_!kdj@^zOp`tHja zT{)c5S6{>Ei$^ee)<{NIs~DY+WASt2SU$G#oi%3KuP1cY*r?s{EZ=kSjDK|k==*Q# z6xwkwa1OO+F{A5soi$msU+Ea#T_VzrjDEt%=+(D%)@W(Jzm26=FJX2aT*C5i0iHqI z)7)8;Ld#=jd@C%BzQw}m7c7jPVq^6EOBsEXy|X5Rwx^xxy7kvif^gOs}8I>h;`QW|tz@Q*)5&&t>V6xvc&c1D~Pw4@~=0 zR37;0ya60Z$5|eeKLJep`wT6U*8JL@} zQ-9DP^0~$ImU&F?1z3qHin9l#_ZesbJ5$UR%8T}wI zT`wpWF}tD{F?zEYKemYRw=81vCq(+GMa zkv|!jt{>{e_!=?Y1x(j7TTD!DkBO!40;cnIjG4(zH?w-mF|&Gl*39bZbu+7{_sp!G zj+t3K4XI%DG^&Etlg-ZR={-BEk27{wA17{S^&z{1)kpLltUk8f#q4Xoi_y2%F#5P! zR!-2NLbX}kGCy%hMH?Hvr`-WY>bl=c$pGVjq#H{rQ`-X+3)ek;1TvkR|C`i(hOj_-@6%jA#gRY5qKkTHSk-&Yp8t> zh<@ln_(N*PGiVRG4+L(Y`MrSlp!=m4(H_(u;2m^71-y&yr+|0U{laF{JMaqNy}*Sp zq2B4f5qLlF7T|+)p9g%1mh)xQ7qt`k7~Piwp8(zge1`5Tfm>*Pe`EHU|HkO+#dzJ{ z7{B@z7SDQx={Y9GU9T|xD_&*s>Q`C5JH+_bSD8I7kxu^3=oC}>Rx!Ti@67(F*O>lw zuZe!*HD+H%gE(#)n0<>I7`jzT`Gf$M-{fd3B61MdYM1$+uv1+3hT`2$!5tOm~7&h%x7 zbiEia-p=?}Y#05oNUz<_^l#eE^lugETSU5IhuB^_m_5lm7`;xUuM_FV#JFn*v)?V! z`JId&vy;(_#rWc#th}p5`iyrNJ^39*U-%BASBrF~NIxdVUBHouPiPYTYZK$wit(H# z#=k<0S2r>K29X}Ui`9c_m)JjcvG#I`aoaA|j+;gL8IgWMq>p-6oJZbe?d}xgws%?k zJ}Ac5zRUW_F_9km9^+TP$I>Uf$LLy-zV$uP-;3$%-)H^p*!yC+-)H^s*Z0Nsgh)U4 zJ{yNoyBU4hZn55XvvHLn#1Raxgil#q^(oVzBgPkh z%JSVJ#^UdKTRvrWD)%ya&R#}exR=p)i}5{sS-I4oF?#W5qW;eq{dO_F;xp!F zNBxu0jsFzaW&dRLTPMaTrv6&}IpbURx#+h(XLh{xIkWqpBK?!k**w1cbEfBz7~lUn z^Y0R8+=sUh(^FZ;JY#vbVXZC3ii0jh>j9x9qYY#B~=&u-E^|jc~zh?B+ zUo(2c*G$hLG2Qhwv+LB?%#I-k*}PPEkl9mvklC~AAk))wkm(uq4U-@74WrNahUv-r zhVd^J$i;V7U}wbVVy(k;}F(4w4M&J zd6j&}=GDmWnElD$G5hPjWA^O*j@fDcp4ngjJ*x-T_u{xYCa%YRVElE!e^WNrk{^-& znyl7&9Qz@}t4}b#^gnYe8yY@ZO_zYFG)z`?3p1XFgm9)1{@%~iu&M|8yWM1^bg8T~ zFQ%udo6er}che)WXVvPJ9|yN#)g{^~<@uJ zbhop+%{|pgPi4tN_%*WXd+)2g_qU$P z(t8{IckS3yzYT@Ir~co)-(G58y2QFAq5Gfi{-k@q>b)I<`dzTsoIsNsavu=Eu^d88@ABe}lezBFl>q&7+EGyMAd3p&CTv$?*x zU3Bylc%#5un@)NERx9uhQ0TeAw+7`sme57-IK^}>AgUFAl+aI~`Jz?YwcR}7mJ%`dCyZ0k$zS25576%(L1sfV*Lky{x zVUs9}T%#bb$lx;9%EQ+xNS%BO7h3*O`kFY&IP-AIA&RR>G+dvp2l~Pu=qX+4a3aIt zX;fY4!(@y>@3!^S-#3kw%(h+#2pAdcNoJ8_HO_RR7wO z-T$2*>wP@djq%k*l+e%qjkV6d!^7W+AjiVjDafVS(|f)D?}mFH+y58!+0%NjC!aZa zv}B!$el|v#LK4ROxA}H2S195Cu8n$MxBO4SJMVM@)uf+jsJ7b7y5$CY(!>gbQ>WKC zbrZ|Xy3&bSQ>nAkZqV3u6$YZpmgp;R+D(@7>$+32@mrJz3wqB-uv~*YAZE~2%oVdm zChRvmCrAOW3ra*@P~j`C#blkBw%ln*t1K%s*sqJrCYqeobgjC>0lO-@6) z&TKBxl`i2cErx0vs>q-ZVDi>S5I(-3Fh4VOZg#FFFJzGgdHHGC1?hQn=Vs;>hAib= zZZq(sD+BlqcDvQ?V|F-o&PvD3(SgSIQ1H7Xbcy)WF8LTa+XVy!GU z@(!D>lv=}EE1kAVCtt!iM&Dk^&!9(=ZZx0+u!^C@;z`Ag)SfJ;GuRU>l@%ohdy&wE zX3pekhDAl1{M5ObMY;3mre)?A72c%HEGkHytIhF}$V8*H!Z5KyXE!WaVzo?}m|1Pr z3Ii8I*lDmhOje77c?gHS6nrMj#M>+;fl_1>ijz=UIz4I1G`_%Stu(VXC^7IxgWZro z&>`%CalFaF=g!Z`>FXy==Sy`cvB|l7=IBa(nbod$&_D?Wv=Aso&XpCkq~5d%LI*>j zFBz>)UO1fxO01+Bg=PuNgpqp6gz4d(R;SKfrV?6Sn(T#{86-!W zPO@_|GPRjFAUP*fQ&?1xosmiMvu94o$2GfAEk%}FLDRZmLdZKi62 z*};!3Loeh_Xr!^cN}D^2w_420;}|FJOC#ylD#TS~cB{o1=Z#T67DsXnx-tw@45D%a znQPFSbiB%tP@ce>btP~x4wK%%Tg&+L41rb8>+DX<0TazM3?EZwwO62*I;>_Zoe)!5 zsxJX~S@e~qPOF`yVN#lyXD>AxFhF%ksIXb7L(ExjH;i--)9$`Uyij@ z=S24>8I^RpHv6NM~rR_aYwe@c2rd`2o?T4~^sj4G^v zCf=y4GVnT{)=xZ~h}mE%cN%F8>YS7ajwIfJGFbGEZVI{x3HmUI4OIrTDqL%o$zdu% zo0cr+rz9tf?%hFxTHwviYBBIAA3T-{oq}Zn&lY!a>%k>TGMC0<-0>=Pb!uvyG)vub z!P$tC0Rrl7nFJ(z%a<5GZ5nSC^armJYKgV1%;B{%ggObH@g*whD&9l&nk;%lHE*+; zEY7YXV;$&bcJMKtE(KQ$rS8F2ChgW_mGqZv2)X~gR3(~W*>9h;o!gPz?kfe@RS6^$0BYFcyoXJK9Qh+X4%_jEwg_`(e z!sf%dnT4qtsfDR}cCq%~VoSe*AsX0a2x!U=KAm$_oorQGl#!X9mw|O}L1t=xdRCDJ{klu9>cS|LymuCf zF1EHVxG6Wi7i|Jl@N}&2i}ExgH8@M&tXTog+s&9R{kltfYFb`?A+{7j6MOG-U6|*? z8({l_UUYL$`Y1y;Z`2FV{M>^1TCHFpwiUUB=uw$H`vo$vb zTGuP5w{#e|MXB>Mvh#|%PXb<%^qlO>+``_JLcEt$TBp>b^uiL7&+_Hgi|Y->zuOS(O>AC{7S*4r(G+R(Gt;vR=n1-u3j6IVD$L6(LLZ0Aq^p-p zFo3SxS+Zp19!fcbuB3uVTy)a(3SE5C493~Zq#2Aoh|dki)}zn&G6y*Fp2lSWlLobw z)7!A@ZPE_L6QZh%7NxgII~Y$d`Svtvn<{kWhKV*yIf;+Io;WL)7?!K180f-Z628tx zPl4*pMU0lzd*XGrN(*)kl}?c|37ZI=g`N@Ana%Xvt${BpDy_!m#8^~rwwCD34&rd? zr%x{`GMh?DZMGt(*-=E#anUO(m3HCM3zH}}IK3jOIAW+alvYBUm0l9)jkl;w=Wwcg zX3(=;5OW&o^$y-)GnAUjOr<<*<;$%0pjnBMw;SwMUN{TNWUF-MN<)uA{>z6&Mx8}( zHrORs6wS+dyTMs$w;1%qX|PwAEU@W+#z&1>#_KG+p}N!{oOWaN+9g_|(-#FH35`R9 z5WTKjWHBr&VyB(`Jf)~de~g|aH0jC2l1h_VUt)C%SE9TZnl1Vz@pc0}C2EMbCnXA3 zt?U+^c_MA&>gtIJ3G}}URaatSN=mGDXHkX0;Xv<9K$jo^6kkQqQ;N$>P9weM<|`6C zwazZrvTKZ?G6!Wu+Zs&e(khj3p@mCzmE}gKq^U{K&7?>GcA!V$0%noPQe|CYAQZ6+ z7| zI*U{6J?I>jmL1csPzOwkQ<~a=&HmhA{U+y*C;&9q4SrNnd5&d%1lBtvt#*qa4lZj;F zOmZu^6@oL#_4p?^*>FB=xpoHuT#rs44IuX+L{td}fd3Q@#g@_<4I7)k<+Ab}Z> zMOXw(CmHEvzLU&1ld4SmUh1*J>=7$EdMn$Y8x0TxLR!rgkN%0 z(mQAzR#<3qF89}wLx)9)$;mGhZYOg%tv2CivI%?%HbfS9L9AVwHp=C_?a#*-V8ARa zjIu4P8vc*#GQARIu_qW&m)M@=i)bhmfPRJ#_X8Uz-qz#1xpNp`+GEm~UBv z`n2$=`Ez+;JO{`H@?zft`E0EIHFj%-&~FM1LW3c5rbgPD;_{ua+dxbfvx#~Zw#e3F zYzQ~I(gwBJ{Vi`dEUh%bonaRQchBzDBeqgvhCMc7R}*_8u_qDxBx0XT>{Ez+DzRTn z?8(GF4M{W^>4{0ip(c(*;y_>$aZDzTDa0|AIIbm*Wa5~HB$|wL%9#j`M6e`+2R_P? z2(Co1C4w&rd`VOf_>#bv1imEjC4nyqeDHIQB=AiF-=svMR}(#s=;M=!9^P;Y(N87% zYl$B2a2k?mGSZQ&9=Ym~s~)-Pk*glL>XEA+x$2RtK8fl9A9B?rS3PpoBUe3g)l=_^ zT=mFRk6gW#?`yfl$+LA;x(uCDS75EQml{Z-S`s0B21LYMIe2LD4O0_GjT{$mTXxrS z^O6!nR-Pucu;AufT*rTmeN|LkP4FiY+yVr*1b5fq?(S~E10;j%K(G+poxvq|u%JUA zxC~BkcXyZp=FhihA9nX?ANuw=)pfhh?dtB^U8kyk5`Klx3+uSS@VV~QbKsTn>b9n2 z!`Vy6`Qp=34CJ%l_Guo?Df9sZ|LD1al>j?AS4?>JJfgu_UVB_-;}U~SW~bdtw7*m` z4PJf4SQyVt_Ef(qum;G(yM>(H+r2b2?6c=8*gS;KJD{mj#X~Yfvmigc%xcR|Cz;Vdvu2po zC&o3h(j)x-QIr>Ft+SxreJ9!j-$nw$`G;JjAvs|@Zi-F$o>n9hq`eO(2znnn zk?M1UBXNEs{if9VcA>Pv(?f{x6`ctg@}`?OG5pIrE9Tw>gh;v-yjTA(q@EA#mhwu! za}$-M-tz* z$c0UhI=TZQ1SKCuN!FKS136q0E%4g~I0TNH6G+yo=!%RK~dpoJPD8_=4u(d|%shDRZ|;J@%)%=8>1 z;?X^!Zg7PAAhdkwBzw@`03+qgKQLb;^f(|e;d>+dAhaR{%l{_(g0OjxxK8`Tav>S& zgS;j$OjRH)jFuR8A+uo`;{Ilb?lZC;tr_xfs!fI-Vk>c}C~iD4a$j02%H9P;OFS{M z#P1h&A=c=F2(?m17%Mct@uV0DX)5sZe{Fv6!nZx5i9HC4hl8Kx5upe>MYXE)Xrap? z1c*~1N>UG{2Vsa1Su5r@XK$`?6WtK$5jgRbX%uy=dc;UCh~BK7MZJ&?EG^;gxo#M( zgh|vP=0PG-My;fHuzj6HnYlL@(f`V9NFTu7LgQuDr#YdWs87Cqu5viYy;eO;%g`jO zaqFEznopk)u!VmUo#KW1qGN}3!wS!lwLuFZ{oEm8h>P4C{p!oZ%gF8@YOn~0TAy}z zH1Tfeo~?Qo6hD=aqIO~iVHLOsA_bi{aEhB}=ngbGzk6>I{=tSUiHJNkw~&f-`-#L%swbMYX(XG%a?(@(r^)jkeD|&V?&M7bb@9vN6jNb4p1>H22#t zap42eu1BX7yxQqYO78bZ&~1AEJ~`v$oQkpq<^z_ypK>QxKPVM+BfemQzvq9PIO+Yu z(d)T9$rgoU>LUxGoawP9(g?pBN(ry`$y($~(MxKs=-mj&RoF>?atuJj)Fc2*9b$shx^(> ziS}oJ5blxtSMHT$`)y`&3pn9wl=R9xsK)wV2dwpiQ(Hg{0b`98y9#9#X>P9@*RESaB*=5+h_yC}Aor$-}EAJY}r>9nBIF{+- z4vw2{5c{>9HEacrWoPqKOKv6ZD(2ESLsK<;)woMuQW$f=Sk08qHLF_oKXH@99|?Xk zXGv&M{3J`6sYz!IGiUx(k>02q@wQK_6ON)f%+;@S{9`_1f zrs~E8*s`YX~4WMdXLkwk_8rc>1lM!MvWkl#1Ki>?# z{}?e@T|ARB8UJCzV+Qk3`8jdf|K;fE7`pizXXXL?Z@&RQa z1~Q*^o{0_XY+Cupyu#+OKyQH`xNBOCnaT088jvV_h^W|24v zK8mAW=o?AXDshh0R6}AOp!A}IHNM-yi+-L72^lX^5M?8Cbo!SjT58n9$Aoa>o*tpHuc(EHEL{dfWZfcXXSt+$y5DncYe5n?d{#;ZFpe+X_p zK|O9gwHBT)Sv}4L^#-97-v*`BR~ZddgHJWN+jV#A8HL#C4ycFt73uP=>8<`BTvXUB^}A&jr{ktlq-%ap|i| z{|-afMWi`W-9ifw!P*d9e$Dej<@yB_-UW83O-&&|0HSnymUfyhtviFaJeOCbNLuO_{%h=H>DnV>-{ z4uF0^_Z?>-D87Hmnt$)6%71>9t1JflhLehg3Fe>FrbEkjdL%_LpgMhaoa~)PUqgGh zb?xL1&fm+gbt1Wj!Ckw%4)w@dRvHEB6xbfey?kEcx` zdWC1G3l)keCHmfgjcE~~YTkVxl_SMNdBmhcioxC|y!c?uzr=`wE}=js(#zvC2+99&Kw~%u1g(W2*tJ5A%1k9C58P4YZU1Ra&7>Za%M; zdZ{)wrW8@Oq)`l7!%gheWyX<9L)fmttGGpZ&X(liUF99`H%S!cWX$D+yJv|*d04bQ z`uZ7PP5XCVSd(%Rm(9;6H~};-JH7@1y{g)Bpq841BpWGVQZ46UO^e=KC}`H~F`1 z@tlwSwVwdUzTlPg_kdzU@56Qj*&V_xceJF`H}1U$`dDGRK87_pe^(1 z{dQN(N=}hkgWRjy%yO6=+B1f0Ix~jF>61)JbBkM99!?L%Mh zdD?;q+GM472+nN*kQJs0#UitEIX9)kZzpe_0}xsbG!&3{5qDjlA6Hw`ht;VVvf!8< z`}aLdQlh}OyRigqbJ9B+KLA&-td)Y-LP*d?CA|~52H7c#1~kgGanS?zzYUGINls4q z6`6sik{{iJ6Ti;NzYZv;JZ*W@O3*!D8`_xz01p}H4K9&b;AwjuF?H#y04sB=U^KZl z5(WS)Y$%HwH#K0-`c->!oB(N`Hj?%ss<*rEZ0WCQcDnsChlB39Q$(>T@4kOBzxXap zqr7AAX862Ou|2j}F)LS|ww2-g3Q>ahQ@)%GrmnOtV;wS?ql?qd# z6*?L?dkk7(0KXh(<$kXI^nyj3@wHqJJ}8eeC2=nZRs|mz$hgDIuYKA)=(gy1}depk?az)5tXRDL9=4m_)rR>CMf z*YP|t7>_kGw&vP{6G`QrLlcNyZy6*Y4Vjxt_;~m{<6#mm00t}J=5xl`u*~y0S~ta) z)K(OuHYyK>3z>h5AEre^^Ug6L8b;3vr%#tK`1N^KIS&NE!vEt%?&4XCh-Intki^ zLh}WxSLKA2786BTYGrwvTD$iz&O?*cS(oyoxs-DA9JB0PBLkCUVGb6N_~2ZnCI%*l zKW6E5#UliY_NC>T`}&Q5{lUu=!ZHTE8HlvHHWQ=zmcC$zbYPYu<*m7=MciAS2j#Z8 z>U}~&f|R$KdEde&3fOq?-Ne3G->g#TFC<@d2kE4lg;&>!B~#E-RFn4N>~dx(di2@R z{pO)m{z6Kn(V=T7L%?oO{^5^laLSt1*B?y)Rl9E&zmj}Y^63vUOesg%NWGV$6P;&8 zV%g~pT%<~rXhl=7hm6PO9+W35A;oHN>*d_ctrb{ht+EC#aD`H%V05I>r)IG; z-ihT|VRg-rEE?s-#?hw=Q--&g$y-S~=Jms>OR^4fH99Iwrk%c+jXcRLNZt4ux36W6 z@%&>}zOP-YO}aSUC5^@G&7eOj3G|GU|C9cAx(l)~EwJF(d*)gY=y@t1THDnrdG6K9 z-*dj@|GjpY`Gooi%+(7UtBtJpqTDTZ5yT9L^xPl)@N!FJ9;Q8nbALT7_dB}YiwtK* zfINbfzz7%0N6_L{{Mwnq2YIy&<%e|q`F)nST6LDm=E_-#c7~tjaZJq89 z1l@Cg;bOlQK=1C4*QoE6A7;0pB2a;0*-hHu@0W`QqTIh)hER-zV-sJ@PXdx3KrXd# zInJKzzV?0Cw{WiGdb5y-#;3rwWBa-vflYxo-8B(}L^~TqtG8Y1|E~Y_F44HSc(u@O zEakKYNz%XUpQZfC!0vXOs2enmhcG-kyBoYc{fy#-jy0TOm#?rO7c#>C&Bt%R zdv+I%gpf&$ia_*#@O^f&vHxsstD>RI>EV9T1q__KhQr~$`8Czm)h5kG)img(`c=gJ z^DRrxbCr$3?-!WtFh%tlWDO(V9I{q62Sg|{UQ9rUl&pt{2=%H>(0Eq z!HJ3B8~-i|U?5k<{UP8S8Yo8ndg@(I7<>h}%}@O}%#FSK{ALrh@D4fpbTJE}%_@hZ zopkhOF3Zj0(l_J{n{HrX7HH==Pi$Hl+qx{^Rx?lU7GL*AQR850=(aX(Q{Y zgUTDR@16$T!Zz5T6Rk4e)oRNQs!pi{~ zq)ID^Z7jM35DfD3{_JrbDCv<7YO@LSxNZ*K%Xu1$yBr_qV-ggye3jY* z2{h61@aP6T=Gmq${oql~ov0Jy&BCGhTq07P;(nZz#Wpy0<#581F1*7XvhQ+|l+X@==WT0=>MX9Dn42=# zmCyO1ivG*z3iNE6-f%q{SM4gte1PD}c}qo(BX#su{FgzZhvC4wkSLm9dqG)>p*==l? ztSVI?x!-v6S9~aYdgEe8*kg0d>nUU}i%cJaYr2GsQ?tvn!kDbi1V08GDL&PS(44w{ zW+GC#$8IXmeiH*tc{~k^oE2Wx3L*{uIW}Vgh4y^#&x8aLA2G2{Xw`Z1-bxO%7ryAo zcI|U;>FFhjE9I$NL(stz<62D9fs(AOpCb#2d0(t`r}78TDuLhB8jB^DKI^q@K_cl%Yy$k#PT3Ot5f+=BgMGjJSf3S+tW$q%!vwQ~+6-X7w>Mv7k1TA5N6 z>kTXd_N-zR;Rz)$4<&ccc6nD@e@j`Qy6aC6x)(Z;wyV&r-ceNVHgSzaRY}m{E=GU* zru3295hxZ~GjnwRkA*qmgY<~H2VRK-$+S@Tp(w>3vUK-NdQn$u203fo>9KsZ&qx#n zYtD-%&5x&G#|lu_W?|rHE5%Qe@z$Y->QZ+$%yy`%B@m2q%E8K~6j$IEu3o8a8wlN} z?fmV4qc3~^^$S?e<2>|^kjh>A*(lgSQ`b3fKKNd7nDS%>A}d?*vR33DFiHruK5#d8 z!c~+RVKSMG;UA>y{y8N9-~S`#9ot57apV3PW=Lw;`7A)Q9Y?h7^mZl%<9SrzIffe; zUidUo@Ur1H4qFgEIFL8-x1H+#QD!{5?5Qa&?>4)FX5IO*qIvM$U&D$t2%gT{!^rHu zhxVc_V;|C=SbaGd&+O_z{4oke*fhlq%C>n+{|s0T?(6yYgGmsl9P~(sbbtnImK@=b!9E?lM>a2+>0pu^pRLY8EMwolV5Tz`EDgA(M4 zxI0^?@Qwo>1{&8B<9}-P=}IPdYbH)zY2px#T?L_4WAJ5I#gc;d4}PX1A7=>MFf3;aj)psD5@Zp6*?txjL*9P}W0}X(UN@S}^Mq60$xkK}KBB7a zSZ7)ePUXft%{d;AB9r2=DZUXHuk)BnJksEq^^XMd?X`|@nmiZ4=i~UZ=VgzzFAoE7 z=5nChg`|S-mCO%o@Ty73U5UN;ZVhcZzrNlTt_4yZN)7T^NZ~bo-}Es0a$;Y)AQ%0> z1IpBdGC2CpTtz|IrROlluc(W(eRAe`r{ff*Po4>TZW)hL&J}X!zEM{RKX@T(y|WO- zJ36>H57?(TSjdozKsK_v&WCLLf=93e@Lk2f_h`JB{kGTx;?Y@caqcC-FS zznJp4g4FfImI zdu*w3qOP>Np=;l-Y7~J9R{juaVCBqoPRO&C_`L2EKQNFJy6n?^*Zk(W@aU7Q_>nr; z68=a=)j|He>6^`mZ)x682=&{ih~-KvM->=fAJtxychnr@0kdga=o@i~soh(h_#B-Q z3#?L5vz7(s7jka+3S#f-Mr*u~EI{^cx?60-&uSoIHyPQJ?}_kjvg>-KbY~Z|`aR)q z?zI1D?oLuBV+WlW>U8af-jspxXZ0j^jm}FHDUQ_YjPDv@fxAM=13o80o!iUk@BV(Q zkpK?#P>7ERb&p909)^wGz2BB?uU?2mt&BO8pxQhY9UxhwY#PiS#lF=OiXU|RH)Znl z==jgeBxpPoK5GSnCumLHI^vlc1+N!A6*qpH)jIdZe5Nu9EY_CLM-Dpd*rpeez1(G@ zfV%KMN7YN9%Lbfm=B+2e$<^WHv4#d5L1B|$s!0>N4rwCq3|iOsyUCu1f7am9$OV-b zOU7PK2r+{lYo0zkI^r)qHPGCye}C**Uf(JKmy$b6jPDl(DYOM%&oDkfW~P@(u0x4# zZwX+dd5#GN{;O8?894Q|HtF3q)6}yyf3Avacfwy^lT&mZcdEX-sAst*qDQ-+ zzeSQl&c_k{JFQO`>;A6vd+;l@7$z|u)1-#%L7cQ>D##>|jl^h{+a0DjSUI%?QIKYI zK3x3~+Cc#0Irk5s8pt3|-N#~wkWVd)=rTqEY9xsN*fKzKS|xL%p%nv9A~Aa=na53c zGbC862cV$iRSK=dG)vf>hhzbbkWIHl(s5NYb9p=6Ua;vzl*XUlJ=bc*u+02&J6f|( z+CGzTAxGadQqA(oK-_^o&kpylYaFO*YWj;cx_cw>n&LE#=3S`}>KWwl()xW}-^-LJ z5QK9-Y#VqMFbTr-zPyc!{?h7v#=;FM&Z^-Cm1m8j4w04Db;70m%3YoVIBzVcrW?sm z-J{BYVY%+PpR^4DVx8#Fbr+~cCU9;H0C^j6w{=6OqykvL(%~wS~TwCAK4eHW1V8RPYRKI$%k34^Sy274}L+q|$EXh3naNL|+U=J@(;&5LE9e??%YeA*P;@H@OaQzO4I_$&Oa ztim|6rN5*+P;+78e$S@h;1!-B3+iBNg(tdDG*JxmZ`v;U5DCpYjFt-0vkksETTtb8 zi?oJso4W@`U%Afi-47>mK0eFLSJAN_@w6Kjh|huCE8f&*oDE1Bh(n56W;$`V zPf@E|Z4WI+{`|P?U#1=?1gF|Iz&Qr1)DD%(y{^nGl!GM(6-omu!hx*3y$d{u9mQypYQ#Sm7E@xa3|szn(V zFI;&@uDE8y;*=C|28zek;2(@31LQ~4*_J)N{6;Pbs#BKa%`aOr4^_=q)bV$BR7?9- zN0Q$jwwfQ(rGZst@OLZwE@zOwr|k6g-O2T;Lom`k4gY=G7rgnAV~*eO+P3@DI{@)f z)Natx;xEa1-!ohBZNjGvrt==f%P1h{et%W{5$cw#+atp(kr;Z zRzm)fDBct5ZX3yUjSsMmcyln1w8X*|Dk1Cp!Nl*?ZRY*>6JmDoqgA-#^XHrUY#R0> z=QGRT@E0w0;Mw~f5?I(~EF8B4*lCb2$_+QnogU_s#0d%Jho*R?%Xg_f#{uBQhjlW* z*rU@NuwY+M{d{+@;uFYmH!1YdwsSt1I_d>g9Zqv_KC>*ex16^W*g=8i*J>Y(`V!^5 z3w(3xO8*2>zJK^SRCkq!Hzy^jK64%$54MQmq9kir3W6P)VV6{z1WJA=C<1XyGI|1^k9khwt4P#TbCD$MSxKyl@ceumn(Ov=^Z?6St*UI~S1bSmA9JFnPCGydq zw{Kr!Z(V{?-6hu9t{V-yiDxZS#|?oA10x-8^ThAXlk=&SGzIpe#M<%x2D&}Zw@M6$ z1ek;0H>d9n;=^->>LNBl5s%_3IqRAO&;V7Eb*K-;4bAKgUNJbr?r~(_I@TvGEa*N4 zA`9#&v&8b4CIvluWtO|_sU~$7ZHLYJMjE2sUuFjg&nH+Lfz5huPUZeAWRM-bJAaCK zs3}LQJmm)>z&!-uoUcyGO|X%!FLiU%J`{|1jaS>-V$P0P4n6nAD9i*G;-U8PyNbckQH)E*Gf1pEV@{4@+*4zH94ORxm&rDP z1-ne|_8&bW9XSYZZ8gu_%)RR@&sdHy;cgaTFnIL|hE z0LDTJ);HzKLx0xd0Ebzh)ns|puc^@NisC)Ct_Z0&SEN`1DO!aEM| zw3qz0z1x7(0~wf2;Gc-ntP!VR(rZ_`kzI2F@rQ7%H|_G7ClrGGvgUK(o*<1R z35faLdhM~X!-OK@QTf=t-{?T`d09&%9)xEbv{sSlgRLMx7(wRDGQMC9CNDot7%eaA zgrGZrtjjzze4${Jf|JESznxlR+$GE{ye4dhEBQfmV*MNfzXDB#qcaZca$$fF1ys{s33yco+afFqJIf5vfF0DVu zuAG}@p9$qMA6)SkA3mcnJ?%SPj{g~Wuds}FCKo)C1kz_u5IZP$f#T888PrJF(NIKP z&WTbF+KRb9^%@3W6`A|TmsSSb@Vt~bK%tOkN2OcRr-f@V2L#kD^d_IMP4|>*rBkt= z2t;j$IdGsXw6C7pKmSa1BUs8*5*%`;RhMU3oe}ooG$cT0XdK2_I&XWz_(UEqU-AS08Bp1`p~S}w@>(Of`fzJnMd5>Xyx3nvkpZndPQ zJ6`l$4}{|$@flY^a^9{faCCD2hAgbOX4?Ezc$}ze-05Vdg3+w)_m2dMO$t$SCc*%o zNarvS^H0ysgN`5TR(TcIxI!eZJ!n~-n++^L)<9E{`J%PE`10vs-oX1+p@I#WH20@= zg40q7F{Pm4+w0RIh?Q$s&fx<5JR%^%U@gabttJZ;;#bj4lX9=xbk!lh7UlcL$MUkk zEY<1U@N*QLe;oex7pShe0%PqC?cQqq87Fg;|JrEhyxxHN{LgcJdbg(4T0tFr_c@fj z_)uax`m)d<0JP6`u;2`Ju?voEu1Kf^Bg5`jm!NcbFZa&pF+oTMdnS6s$H(jFb<$Yp zf!I$|U{du*IMLar2{6qYKmC{j@8uiJdHh*o5zhs-|9;WZ`HZuKNjm^^xc%SXBuSrVBLD@c?$!bOQEW6y*_`XwA4Z5sc!xW@7oKpx+L*4*tw$c+dp_f0iDp< zWt^hJ(2FJ;Nb6?sDhAt2a#e9SSQBjdC(veY>pbd7Kb_PW<91!Xccz>|{n=K0y2Efr z(sUw)8$?|MTROXXDL4--H=B2`4cynwD4;Epyj$gpPrrP?TK9X3I!K^vx{al{ZB~wP zNB-!4`zc1H1kOSVcAgG;zVCmz>W>VuW)6WlzygLW6f!a}DMj3$I*ykbHMoB?HZY`uyyyJ5XI` zAItFi=PvddKN}T%UOXY!NA!e9N?4S`P zd&F6|f_0j)mmBS*QFus5D>lZrRAi6=BV&b@UbaFBxv8C=tr@eO1@1`vKD+ak3!F<1 z2cNUO8HNG=adq}T@M;BH(~zk@HrqUF*LC4#v!9VB>`hU|Ts3Jlz5d|hQG}X%j=&cu8%bp>v^gc?$AKPel>zLr(u3k z_VF3_yG>6VGI00Vi2!iMwX5rsW$d@=xxEaHyc`f0MW1#s?mFyU9Pf+EOWJC_ezrB_ zi>Ru{Dyx8<&9{-!@v)CH`pjb!qeI!e;__-`7T#{s3KnO)OtG9k3iGr91{1Ua-U@E{ z*{S59_v!r;v4I_ZS^5WGh?g6$Rm?;}^N59416xRl+5xL=5hyim#G>XAeldBt(X*%T z;#R())KmpDA&Jt_mz$~&8|7LBPjlcI;ln34e>1ITu?s zdx6nq=PW2~)S@%O?+$!zFrVu`>d6zAAKk=(shEx{eNUjd+y36V5G#kJirsuJasK9_8U-QssTmaQ$zt z8vC>^)^4H8w_tQNX#Dtz72MA8RV>`gQ1$B+?OLARMrM-hwdX!uaMpN2%pr30aUG2= zEc*HBkgkZ3=j}gC)gO(y(R3-qIo`Yo#(Y1_C${jXl$!faQk3WWu}pst3TNZ6Aj*(7 z_LxrDGXWUVCbHc;5*n7VC}R|2CldeAmGXO8tLf+@gZDGdX5~h?6$4QFN_2p*aC~J0 zamAOjXgbn)bQVGvxAcyZe_7nTPV;&>tF||hq}(6 zE&O5v-m5De%oXPNTp7h=f%)!wZjVB~(YQ~GBzpm$bqO*AuK5g})Y#eO`iUtcz+Y$b zRPB8|ldEk{u^O*<&1%z^)OW?~dHAtnbjy}c=oIYje*+qY$x1&(&wa1XjkW3M5T;u= zRT)-M`L-%dU&YNPEA~gG+UA6%g~wYgTb`KBEy=khzg?IpWkb4LcT$Y~qOVuUhBv%=P58imqSl0zCRo6)cOMHMS)WrYS=yHCW# z9s1pTl2wjQ8^-@aUlx|IIb74cLy0hRRgpyB5s}!7Bt>P?rYfRWM*a`_>#OZ(q56p>u;@X9a=1(K(om{ zmadQ&J&nWtJ~sSy=QwuD`)HF(mL?(tDEWnY!PM2jV&)Rxyz9t69T8flZ0Drv)5^yM zA(2y!(4N@Z>fK_D)1E?1PN!$(T~7UN0?puW0g04|OQ9+%A1&W@^1r69G=xo|-n5qp zFPy4PcE)pe`7;I`>mARoq=$8vr!K|SbxmU>W@m~y{6X^3Fx7vzt^5U+g_D?sfFCbN z_XHVni*03d>=*iFT$Yo*^kOk6cw2PGM<6_ue)y+;qr1Ok^0UNeiJN7Gp%6(x z_^L%XQL{OLv(GLOX9J1dZx0=AtnaWbGN(JZPop|TQi9WuPA8O9!{0se+UwDwoo#mb zTRv>`$O038IQSOw5)!%3WUNadIv;sZMa9}q{3bqE7f&wnWwhH_{YB3@my>!KG0p_X znEn&Y;o?6gs2+djXpG6@5U?}MG}Y4E64cezNsJ)UQ|_L@*P5XW`q8Km>$J(`) zu}YDj4n_!tm2radn0OQF)bv(q>nsDL3+X@9`+prEDETYyTmslxoQjLFGc-%xW=>b{ zpwqlNu7R@gh_@U{FqRSBudttVBkzw}{u$G-65zwR>ojYnsB#*aA88etsiOa-1)hl57+#yOwh?T;w$)vxSUz>`P{@Xg) zKIfDyRlmD3gh(%V)24^r+Ph& zy+gg++vazFWzuePsPCC!VYlxn@GHWlp>4s1!zG`XtxYGUi)gFPrfk8m&-rU)mAby= z{pZzHa92yw#)2ZiZUr|nW^e7re$7n!7+m|U<$AJ+X}?{CstpTiHsSD3U3t-^|525| zsZ@|)y+T!+@g6&;XS<2;4}mhls8#bJ6*hL3FYmwl8{UWyvfkKg0*m#vqaAXJo$A+} zi5cW^*YS((XFgBnd}=P&xVPsLZGFd(rJtE#@kXG0G_G>?a3~F<8=3Wvp$)g36|n!M z1OP2^Kf~EJt}UjgtIMKeU;XtVsom*JkA7dl+jUK$C?zm~uS`hjU&^*F)8pp}&1`|N zvhdv4Z%7UnoumDgt7SCPjOv;>0)77Z;?@c_BR9i$PRdThd<3WS55`U`PAup`Qxa?p zADl|WhtuD>s}n@|9?*|}R5@3FIjK~hNfW8M1;r-@H$JWx^b!RP%;metFrqZQt*Ot`bneq>VHO?*hC&tPx zCB`0Fku|^hgp%hC^e1xiC$ocGf=fUJm^t!n%aw-=k69C2#AzF=IZa=rSQz^?Q;yxSmN_tI4(vU9(+?*`{k_#N#|zkKRWEA!W9!?u>$~1+wNI4RR1vVaE!)B ztZEDg%usHqnQoxLK@?hqVnr|6d-0#D@FWDihj8?z?a@PGl6^HErcCMDCpE=mj@_!5$M_(!#E+8i zy?l`NgQPhY4@8wp^;{OgVEK; zv3$pL+n)k|B>3ijC?zwhCnE}f=pUFW63{mVjFdD$Kc4-aXuRoeZr=teFK{i{eGiVlVdHfnoEzOC zwCZo8rP2D&{{pdLQF#J zu-Es~6NLAlL+h8LlDjj$464ggCx_GJX7f=!`cUN(T5?_2?G^} zBSYRx<0%%RSI#uXMxXBUX9aOIFht1OQ1%2Yd#H+5(~td9hCEO+JM4I$QZT0a zIl!%D^>mDDWI~>g^~*;p6F-3&H}A5O{q%Eoi}ziln~nm!>t0cyFiM-|GaD|mNtF-_ zLw=IeUsH3D0L6Eu!!3FE8GhKZbcFxr!h0mMthvMk;-!omC zzd8Nhm{lceD;>kX_sg$&n))d>Coi-`@5+qNQ?2iMLb=Mh4T?TFt?h=~Da5;YR+iLB zHK)cD**U+BJy|5sIz2xV=4AJ^D!z99$KSvJ48o80^9CzOhRS@39d~XqV1*FuHZfV1 zfHZ0&wl9KDUZvmoe*CxsH1diOdbq{>d7qeoi{?6C@~9v)c#GB8XwCuCIfjNVm4Uqr z7?*U)yV93>(e_rb4Pl5KVtqfny{3LTqnSt-%%9c~RwTiWo0jHHnU8F1;Q_nM|K=^& z?>i;SaI!*k?J%8=i5jKO9sJhzel6$q_oG}1cDf{wj0|&mZoqpPP*^E~W_R@#Cwf1p znH%k}Ct{ha0TzE*u<0#c*=rZFdXLbmD$nl_{iuGT4K4nQ3|W@C(#lQKtyaOj0$>qW z68Lb6vEOx6U!V8;J0v%?PHpDgk!L#m5>sUlNbgG`E5L&WSmF7QI5bIU3AldhjQdz@ zHKqM{km+_U?_A{%AZdwZapS3cWK(VPV)jnZ$+7(fa?X+Ulv>5rx8lQV%l8=;-6=L+ zrR)M1U*KCAVN?(OkeU3~&}^Vv;kDn-P&4n(7SK39yL8AnKAT%xy|qGns;Rd$J)szd zBP^n|&>Ctx=T~dBtZ#qlqt$lGd%^N+BW4Ut?Wk$`YoX!I(62eZ7OPLm8K13(0DJHD ztiQNQW)tVb8<|DZnSk!Kv?Vvd?dANoREn2kbfslUn2XSQ1fK%A=uQOAnPX>WKoBG= zdOxsd<(9;5r^TqWX;WOXFD}TzCF1Q+RL6zn58Pvs@A^=Yg{OIbGh->l-%W&jhv(h548tk4PrXetK!3F=R5nY{}P-S0{_(A)JgzSi_S z$%her&K47;VUhn_^Gm#gu1k}isA+wwa>kydOe4qqU)78XNts8EdFIC&uTAWzKEocU z#y?$B>U~N`O#gTc#CQ@4(hz9dZ5NBdICMV4Cd>AV*mX8t4^*xX8;Qy5&vL|gJUv8P zDh^m(qH4`%L8Wf>OzW{ts@-I6vLym(@9d20FK3sEkTG!jaPB#sT<}o0=aT(PZ9PN_ zGh9AvW8O52db(_H{Ac{H?5y8UUa5>v)Ko+7*HWB#UH#sciPj6g68k zCaukV+8qhGLNKRhQe&!P37g!UTPVOO;7pya_R+yU+01Z;;;)tmQDH@+N8?9I4GOY5 z^|Cc|Osro^)3<6_7OV0TrQ?=PxI1(gW-BtK#yz!nfWW8#|H#Y_uo(2K=9u0hTUUTtr z-L-J58?RhU3Og*TNlB=Sh5B9Vu^x z*FqTzYL_-Ytl!eaZq~;CSMa85iz!RYIZ&Ny)5Jza&#%}Ma~xQRhY(#qBsTj9*uShE z{2s%OdYqT;ML(yhgq}Qf;RxP;pW!+rqf4e3q};uyGsXe=93$iKP6DcVuNckO#(W8VB{WT@GJUC8?@r2cdg z?w0fx#30U_Uv_U%$gsxYroQ3kQnz=s>_!Cds~JLjovjbgAx|HfuIobbNL3qi_x>~= zCLWr-=L#KaAaoUT_@13bVe{H&|s&oNCA_E$bCTTn2HO|a(X4T1DtDP^9zUFLAMwiZjGNDtA zx1up<15fr4-u0dHpglBP< zeN)MMw&G9H8lyL@o?o(V->p{1i-l!WJ#N_LHTixe2%D4t=J{5hewYrsjVfrnapL;$~HeT-8AOzk2Pf}^Xb|%j;Up2vGeKM7me{} zDf8-nVjNOSAS=rv=i{+A87s+TxupMVKVLUqZJuM?D%fc6YTvc=aeB^_73JWl1=s5~ z-6Zs*l4^~V`Re?iTDN0IL-)#mDu%6IzpIwxi(X56)$+eN*OMbbZ!e0D_Biv^z0)H> zcf(e{j`s28IoGvXH(SHjhX0po;Qx!vmNGcY^Hq%^WgwNuT8$*7UynyyjWFf!J058@ zyp+CK?*IJ>JcKr7eQJ?en0)y5&lB1=jUtMR5V5KzTE8m$uWk*dYp{l8 zDpf4rE04zdH$HydK3|<9 zb%^|pRAfU2E_Us%J#PckW>Qft^(3m&O}do=4LHP|z0Q|+K9OvHUwgR5@ zK6B`2bDixq-S7=UAe54l)8S@NWdx!4{22tp#uZw-_v1;q|7>j)ADbc;qQ?3;;z^+lAoN!r2}lck2v~|Yi>j&T{`kr*&Q$=1BL#I ziZt!?=qqH~0S-fT?M8xL=*qqJS?*Y(WkR5@A%Nx;Ljhn*!rI%2fx=x4TA(ZPhKeLgxi;g<7Z^H zP^+TNWm12Ix9NRncr1;+xc4w`E*+hGh`rGk4`_o>HhA}@SQC47Ij@-05F5Ul5N(|o zj>|t+0Udi&a;(6V#^~`B^_Q5B=Ee2DEk<{RzI%7uk`4m>{0*B``VAG(6xD%(KdYRd z7OM8i&1@xNtG(nM5I?K(m@2IN)-WtM5GBw3B3pr zMT#_~NCyRhP$Ni_Di8=YfdmMFlqY!3xu0{MbANr`501Z`J$u$(>stRc$uP5LdWN5_ zn_=cG>5qj()Wbu|m2sDwCNPLfv!^eA6=UgXY`On~X+4lF&{3<$ ztnK^F7HiYXY&evf_!ZQzYCO5{Cy>LDSl1hc}`tqGK$D8`$09c9NAuhJ6rQ*k~m_dzM zAiZYQO|4bLa%l7RoC+c4ju#dD9!x0@7J(PhgkjcUN;&2CV9n#}nDHm#%eq|}&RxBP zdl2pGDuP@YVj4V}Tv$mV5pV+^ienem{uJeS9ByZG<+{8f)PEPE3z%=ZTz_AIC?T}o zJSDY)UiTds&W0IPit}1))*hqVlRB8|3!pQg8J`zQcl}})jLF%1M{NPv*$h|jzS~vtaYbmal^G=qURM%u zT5rG+`h3zI3lN2FMNcraFf|B8IvpRX{RYpkJqDBo#3PcxX-vO`^YUHR5{QHAO73AH6@YOGPL`()8333m@ug5Lu42ZeB`U--Smxz~$mWau^^>!G- z^ymuA0Ah6=Tf~N~Y4YKnxmO$GK-YTFoD#H*?xYNobEAPhguH+}O`oU1*0_H}yj-BH ze9Xzw)Tr?iZVU(yzq%orp1_Avd7P$I9IHz9`(ijZf44O1rke;X1R@2QkH;x8&Z)u# zAWjeuYI}f&KhJ%@40icC7N6(Li&B|P;3eusWa*O!Q49WfJXSbxFE!@yZDp-zt-oAvLaBbdvrM@tm|Ts08AJ%nr_d# z!`rOsm#}cLl_5yUO#lXf2t%~eNs(Y%`tZj!U4++E^Q-1pt>T2qyH1mO3lN&>JeP>EI2tTP(B;RJ=Jiru2V0lhuS341`=uk&*W^28R1>sL@1EW>dHEJN zvWf_F-bDfy^?NY`MGby#mx|YfO@9kEE_ipBtm#c@cY1FzD~_h^8H2 zzWx)hz_Q%d7BQ6SDECJ=2-80t0loY*T_1@r=6g$%2qZ4hTbqO_W9Ju~BH+?do(9O+ z`Fkd3$L+(v)bkrle{Femp~e{Dsbcy(@lwkR$hrBn9VUj=Fwf155m$rMo$SMvq^=L} z$wTGq7O3fuR!7ohM{P#|)2~{Fe&xQMbKMgt8hhJ`=#k=(6Dgh+csB1c;Di}*X;zI4 zn8}m|syzO&J|oHVqGBE-VvexI4(0_at+yaKluz3l8w`Q%_@e=lqEpy3@<}OILD1ls z3$P{E;l;trrbP#7>UQ@6Tn3V7z!B_lV>#gIc4)3u!q{y_p2M*P6*?!@s9z~c(*)M% zh$1+7_pP1j8pD(wDO_;Rm{;ZQR8V)2s8nJzt{#nln&C!dVVCLv5I}N`3XI=otoxAyxXhbQP7nHb94s=1!5CzXxu6#1T(XXW;72z%j2KOotq*ztk1E1e}PV zozDr~{_4=_6OKc(@h~w>n=I{dGOAae?bc;H%+Uydr71agM9x3O3%uw%bPSt5H59(j z{=xYa56S!D?z%+qTm4p?OLO~1ga4mzAJ49N>w;OBl?Y2SX&TSNKQ0FCvWU^uJ)1-n z;2kl|rmb?7&P0|a?~|SH17lrJ{C_CK!3EWTXU$M&+rTOP4~`r+Sa>uJzndyKJ0I`Y z3{MLSb}s*H2TV*j2}q47uPreR!)xiz;GpakF+%{y;o#|Kdkiy0(d61-vqKda+lpCi z<*A?y#K>1SJjL-Hj66728*4+#S{G-Zt@F=kEfq%08l>7|P6LAz{JYj-GkWG=15a{Q zZyj}s=(h84Pp|zvQBZ@{1UR4KDotry%aKWe$lbGTG;W(|21%n9i2Za@+sUC3iO$Dg zX`-4~8o7Pa88}_KtPvLabE-3EjIc#`O;J~+s_fQ>8Y^0^-H|<7($xqLe(L2m___;B zQ}bJPvr7%GaWtDa4@~Y7JVfr0XDJ@ySGziRL?qkLgf7?qPA9wz*ftG!5Uw$sy>xmv zgk>N+B>@;tY$M1(lOk7-#es6Q9I^0a**2wWR;ycRH&t+$Et2E0AuZ`T(VQt=9In;( zPXn3)@iy{wk)j-^_F=X0!6FC323`AygH^$0@x*>0e|F$92nfY(m8 zv*S$F8Na$gyQfn+4vt*rBf!DP8O@M5l_!?&onWp^wOx@91JErc4ac)>do7E);96(d z_ZGdy38x($in29=l7cV#zUjg_Z?toj(*Od*Sik!Ho-^Mc1ha&6UuJA&lr7^8_UQc_ z@KCPBFNk{s#|G2CN(DQ0FBduNCy{ZBWQH((KmT~+Cd z+=<3Ktm!(*TYFgC?uN0JBk#nm)wkl2;cke=5w+A$a~7yq!Q6wlkE(pytkc?`pXqwo z7nw?_?ahW_qU?hr9!}GkPW3rs=9;K-qAYOxJT!G7Tgu(PPFK}|zRTSe18WQuT^wdF z6%PV&z0QQ`fS%~V6c5Z&qZi^gcv*J!STY$YhARm!CkGYRjz?5Sn4V!pREbx^S9(Un zbMb6vdIH7HJ!mT`@v+nD?X}1{?ECp^$dfBj>9ya(13u+%n`!pkduy|(CUol(Re4vI zp7nJ*#TBYjImh5qJytaLX#!k{bfI*u#Ntf4@0`qQ>R(n?v>1p#&{8ca?cbu#>KPEK zmCqIy7kf0e4@L_=N7%1A5c=Nb)r}cs!~2k3*d_W+=-{lzSp$QqSQgwml^Sc$^{aA4 zt!25v=Qxb2czFPQRH*2uU!63^x3MFP3rFd}yLHLeuw*SYZL(F+r1dZK5eVCkRjoW^ z$4W-ck!@di6$NL(3FrjB@rHjOFG4y4K7q{WqB$$uD2M^CF9wVX@X*SdQ>g8)&b?(I zDt`{@v2sQr2|8Yo2@i}!{tJcT<;BmTND6xKC7U=8kPlxBOSYQu!v1b@)HHsvdtg<` zqtt;Scq@S#5(nVA{UO3Fi?|9=hWsy&$<^ptoWHUgETRL41C6xLN+mKh-H* zZuh=lbYx`j*Azo7jD(xp?xOmi=-xPtpa!VEWMkjdI+TWo za8i;e=GEP?A051Y3Zf<%AgoR(yTg1m(ur$n` z>X+S7S7{pCIrz(?s>pmw8C^FpHX|f_>Ou4#tp@=H@cNgrp=4ZoE0zrQT8`?T?CpxWezDRl` zVNCk#Sd>3-V>aJW%R^)F%5&w`{#csSUQ+Kb*!ie`2h9Sf#1INgmp1Sy%OMt%xFGgKi)S^)#4eO4kJQ^>7Ci`t@t z6AEH1@!*%e$a-f8c9sS6#wKh|g$!{=2$^@d>=88+)ek!(gn7c1cb09={xJCi&Sp20 z4Z57V@KuFFsdahy-#HZVNF?ZJAkOr%f(v&In&+ znVqRzUEhx2omeM^Ud5%?N7LK(NVQOS_J_K+;Z}nMhYiEE;1@mnc(8)}8>fJU6HqEN?p#+jgfTI&PP$ZeYwys{F^KG z6jq4Ykb^zA1NwVi-O|Zw>yasJIrwaAamZXz4Hb|JYLLFYHIJOpz$_dn2{~nV@8d6q zMm;;|fFz9|@1)R#!#1E4{b?1m%HlH<`wK_N%6b5kSe>A1NWvMMN0Dxs=LNzdfx$P8 zC-ZRgPfxoCS3$r!140*yU9Y2D`|^D6v_E~XA;Mod0EACS6aE${RSJbdX^W1+o_$vi zLxdb@FHduG19vRwjL)RFpZty~W_3f%cSbBW^CItNtQ>RB?1Ot8pq+@^KQrk_UYdH1 zT(y_G>ym@D-ZFRu9w^YPe>M3obMlU`#Opb-yXZ;I-8 zD;=_i)l+!JQ%?Bxry;}dcf0v=1h+_p#_!~1!?Te1@C}8B8sgEM(r5Cs+G4>P!6iAh z_F1jKoU~9=$+Hhj>1;!)F$X`qZeb3sze#l0M36%jOy2P*8=?@#JS$6wq+f>!W2FFp zJNH|d4U8uDOVz8tC0qm?J6p@QDYoc9%af@V8(5DUZnD32)k2FZN6ry8w-A&3L|qzVh3?n=itwNn;iKgveXf7}6Z6#>bO{E|o* zuIYh~{eamFO}mBU#&1yMb8$5Fv>5#m9$} zZWDA?UduxBwA!Z!Hz^OPo^|Qwd+?x?DS}x2(2sJKze?5T!5f0edAp0m;Z7QI#cMGm z4I}2s;kEUQvc)SMB_nc$tPt#ws&h^h;mN+d9$W9p!=VBwgDrWQmN&2IO*AJ~x@G|; zAy2d6;BUKz)zb4wMyghcm$t)fPnAp4`cw^Qy0eO9@ z&3Oc*NN~L< zWPNhP$FI z{ROCoh4a{N9&~Y&D7xBuOr2rN6abCN=~H!0{zkfl@?7=EQMC}%(9mZ`=*|FKVY_<9 zQ`&hK5W^X3RI=QVgJ&Tz7)9ZJ3(~3 z@cN*yQXW=NQFL+1!fHD(UFEtm)YyZ2T`6KYC+KCkxEqI?3QSoqwGmkS-Ok-eW<(_| z^gCTR`59%e@ZWDUF98s?%X?<;^c4*$}sgbXpkaMxcBybu2y?CuRM%)6Z1Oh ziGSs~j0P-FlfPnyMpZu_V-rNdi_tmy+_3ih;$V*I-8a0;%Hbt0OF|Ik@M>A;VD3FB zP_S!qxSs_0jAmIG`#ZfVWdjadYUn3S=E^kzfBD7sscPXsewEDVV%XDtzh2em98)2f z_vvrnJori)`$qT)gZXs22Mt;kr`@YcM|a4^Gux&Grm&;57%OW(utm6*dA$fKlf?K2 zaT8w4LMzwDw8!3QRl+;P+16MH2Xnzm$DHnY@H3(Ka3^Vu0QOM4TT3Hn{ZM*)xjIfI z4a(#5Ttx3AKHNFv=OXXn2#ljcprbiID`|Kd)ky2Ds`%hIGaAO9h*N|b5@3{n<#W!kBa=_)gnm_@RE7M zS@MIm7a(wmt$o25uYFeAm>cmn#!kI6G`2T8yxDx61rc#^_0%9DrvcCk{wiY;MBFcu zMaJPY_!`gjl9!)&Rl@OM$m+9`-zkqG7UpyR|{8G^)+H z4K@~)pd{Hid^fKSZM&q#`hJUeGdRw9aSKzOGSnfW%C>N~y?0XDd_&DL0-Rv~CAa;D z`1dnAHv4q}OeK^e0Qg-7X|pa6x{X?j>6MlY(oni`rvz|}N`1MomHUmrDY?4^c+r~` z&a;V+G~xa*5_+@t=d*QMtbTk*rL!GUWF7E(QC7SdngZDHX$s@{wJR{&1vBZQ3TgX^ zIJ*#XE2)DV)pTfE_9ebeml|E{s2*xDV=t)1mx=4i3N`)ID4VIWVJpAP%}byRIEz7y z7ihGKWVio3k{{+e)lqjgR10T;FAqhA>Zqgqz99jDk@^h_PXQP8EjLtDKgbD-#)>faKZ@ z)L6d^^3(*2=+RIbi6BrYXt4a;<4(q!j2YLwDMtauDB`iHJ*JIk+QGS)0>yFU-kS*e zMfLGRsfUspQ*&rN4W)1%<0Y=}zSRh#$W^G1LWg&#3>Ye@+-Y$e zp2eW|B{!<}ZT5Z5`nC|%h~%OIrfn_KL#!;qEHmN=WKt|Q(&?twnzmr7n4SW=h~f>; z%W`a$$)o1e8kCWJ`-WFwP&7zJIhNBvC-at@gmUp40fs?0+3dy)FPLhOdcMgW2&ZhC z1plI&n5|AuCKJpcNWoUWmTv~c0l66@(3-e#?_s9>;8PfFeSEc0Xhu8aPLNV-!h+#+ z<{1R{5>pPi7BG#ElF!dmf-*>r%tz_o8*zU!@VCy;7 zjnAZa6a1f<{Ez4VX}vyaLC=rBIeiNDFo>fyX2BT2hspTo;S@9Y9Blw@tZXJa=`n+R zFf-YLH+*Z5`?C2)LN!iA$1U(1KG(qmH_m)L;mpd??6#k`42&&v4MHCE2io=>##@8v6Ho_@{2QTx%s@B(d?UL-`TtIG@xiJ8CEKRcn_yD)ss9gnioxEc z(>tk0+UF+zFAp~3{`CLKYd6|_-L^sV`Zp3H|Hh*VlJfr$Kj%S8=YOQCV#Ystd?7%t z|E2L?g3TPXludc7J0|k$-+2sP`(Kng58*n`sedPa&V!UyF6Kv%qCkBA&Vw%@3?rtuv|y4bGMMAL^*)^BF91<7zGZuR1W5d88Acv2spB2lPK$as68Y zglgQ_mDApuo{J-4L?9VL3e~?X(6pv5+Xo~HP3071hLraB7`yN5hQt>tNL%H znM%f|{7-fJ0Qvq8HU6jk#zeTzVK9UI&c!iI3YE}#QTwMfTH~sPn={TsMROjie_8my z0yK|nSo)VV^kkDbjc7@s8b7a|MuH?569#1M+l6Z zR7yzV_@@P1!*g+j!2E*fY)ugY|CENR(Wj+qCD~YNp<>LH?DB!)x|GsnE1<0&qgeRI zO=UB>dm=-Ic`2y9YnUsZ<&T|S6UMJ>Tx#UG#qz-^j~XDaX9WX&=<%Oy3iJEL(_*1TK>UHDxps0^xch?y70erM50; zwG|i%?EC=I%q8w$nM~g7d~+r47;}M5=kl@$vaag2Rv+H!|fG3bbi0UnuCiT0Zcfhv>`$l4`Iax3FtZ zK9KZfDVG{KiX){rE$V`DBOTh*k2f^4Bq|?R|7O8JF+E0rwEOua5FYggb2~et6kZzs zyipUW-|u``j>DRs4%lC{J`w9T9zSC~04ccLx6X_id`3xOlzn^?Xd_GjevcGWeR=r0 zTO-|cg)ggNmY5iMjd(9y50~&j`Z0lGtDN)s7GYU0yR>|{3S8# zkZPl$&gDYR8;@nv-hiIH8h>0I_v|%WHR!}Q-cItZYsFJp6NlIUx3^6kpDcTVdAVH_ zQG9Dgv^Xjj{!ZC3Nm)x!9{Qcg)`%|Pe)mtavmXv_6$X@btSeNGkhFj=C13SA4AV_1 zJt|9v;&NHNGxyE4`VyC}X?--rIzB z+dXY|7T0{wdC04?#5;~7om+o7=BjB=)QFk5P)AMtoWMeSfROV%eeJ$7Osl6dTH}Ct zV?y${Nw3+AFze70&UA3qSu6bNvW#V3Rw&ny_6U++^;UO6P|hLXbwFIi_1b*~t-YKV zCnIJL$BEb0`3?|TQLnKaS?#4~_CLgr&uFYfwy@l%j|t5skA?6W@0>m^0PbTG@ur?i zkBM?aR;yT=y?eVr-S9;0yOL@BmV}>Us(UGzmeGu4lJ=r@epxw?gHLu-%5-?7s6?VhVG&w0J?1io6>sS`Q2UCxi2i_lF zJ+qs12}F84P!R-**i8D#wj>YQ9Edo-=0CV^XIc5VTic4#v{AIGMVHTMoabs3W$0(^ zk5r~#D@667*OLtx)dGrQf$Xb$kAsR@zLk}I@YEj@A|?s1O9L&FFT_XmYP zIAab;3ym~XD6ArVldokTJW?Gp9SVJ=O~Z`8ZPt_4T)`@v{noUNR2#@hRa_`ElLqD@ z+mSi=9Tr9^66t(Rxn+V{#@ZEM#PFzjFT!~^XN!7J!r6Z| z)ate~Jbdq*$>heg#atWR(3wP3 z8V3mCOn;j8;gnaIFm*D1iTD{&U1(TR*heBD4HwpL@y4V0=+d@r51xkb10On>?D6(~ zo7&E$AJWGtiU4!OO}#yOe68juo!vAV^ZEP87G5SHe7SCVk}#b?TLgJ!kQjJL^HWAO z!!f1#5$yV4Xg4pD;fDUn0EJjp-Wf&ZvxyWOBy>CL+AYa!%9zhiHvnlz#rv_mP39-` z8(pR9omB`Lpa`$KQ^zkRI>SmohK2Q1^rslK7sVOyI8=E?p?9Zl;y)XLE<3=tQ zN=s12X7Doh>bmroDBLv?=6SMoWPdi|CVcsjv~(a5rRoNqivUMW&p1WY;6pqk@1F9f z80wX$gOlXrR<%n-AUs;9ToXQ}-HPl>_g`piDVfuybn79@4nXsK0RE`xL#{1)c4B%4 zepk~VQYAL)WG;Eqh#)iZFlivYEJNe<;hCUxseigdy2;1e*S79_aLF1TM7C#`k9x}R zMWswKZe9QFQR;8j@oLgVel~r{a7}Jv%Z)bO$tdu;xi~gkPZFlV-}xHnR(h=usppYS zOgSWHPXN{Os=Pe3We)`r5^?UO4Wa60R3l^p-`sIlOYd|BN{lXKdyTF?UEgq=Q-WFY2On?_}cqO97-q zm_nR&?-aOQ6&NjRxhh6G?sTP1pP;u$nq4{Re_eNW#f zdL-j}zd(!Rv=ynF$V;;In$*SgVMV#r2SVV-a~%Oom){f84ueo@AZ~u*4KMmWH9Zap zSliA7&r=zj>X(UEkBCRrE|rM-X3ILPC5gER;Yq0^nazeY0=#i+zvq=|wbdpg`@ z=OayM_|c|TfdQUp3xLW50TNC%%sDTCY1BT1F>F!6x&?}!%G;#Z3S$KvO-Tj}P`U+K zzIs}p%y2P{VA9mswuyRhRvKHq84_Nn`vlGjl}e((qA{MwOP%E14U!u#NdL}AA>MNv z0GW3*vu+7Y5bvqg}@+BW%8wk0_viP+JxA7M*i+w9M4XaTD*Evz~7gy;?HPIc3K~B z?z*v-6BZ!Uin4F!Cl^i_7J6j-ngYtn0L3o2XC4>)9ac#g&&@_6S* zSh8A|6KzuCX1w!bELm6XilhYa+d6gk5Q^e0bpJW2$2Wf24NGR?(E?hhn;qJ3C-sxZ z+uIUep6Oid9zc1VvLW2Ca(HT_>-iS*8J7=;r~7igjj$z^j^2U4+lx6Gzo7eK=i30D zVepnm3wRxRD98Ead{A2b`R;rM|8OPeuPc0Zp?O<87vI<~FSM}m&koDn-|G*_`fd^* zIA6hGZBEX?MtTiSOTTnWoXf)Pt$u~{?{K#Gn=OG%?w_Mw7Np?)N1*TQ@g?kj4tVzJ z$E->Lt$`oi_nqQPZu&VCaY%TuHiO#&<6LCGE)}U9Gm+#CZ2hBYehv>9j67IB!TOI9 zG{t*c=qDWetTS&>PX(=QLmw^6V1VDwNt!8ObjrXk3$+`5k51X*w_BBNk$~!$W6@&xMU9qI3U4fH0aIgZ-LC3GKkQ!C2fW&pW z6Q}s*&$x@Za=4qrJOS#x^Q4{zHbCY&-R+_kog9rv;=Rav+(iynKX)t{f-0EkagHJM zF9ys%*x8)3OZdC(lmM22SJwV+FPyVGVf;%l?VR8O^nBK|4d(=P|DxU;LR>gcP=_E4 zDJ&m++Ix+NyrjsrxQdZ5wzbVuw`963_^y4uU%Bn^)47m|9msFg^#?AZXhBn^HG5GNheSpx(7t0s|i7GeL;RKhut$k%_l44-pR zANxz^uP9Cbf<60-6#o~d%-^9|=etu|AZX94Qkiln&$-L(q(TB-C(yBCY{?_o;wuNP z-54i@OT3?w;XT+T575j-O2WX*LKQBOL$0C$=e2Y8;%$xqnqJm_KpVUC_B;=7S+*FG z67elr3nwWNS???iU+|E7OL5{va>`XSu$|2v)^Rm|MK!^A(Cp+DOyFu`*w7h&@$Ngkb^7yt+!{x=;nZ5xwwO=j60*W6dGNda z%tS?-C%rbU+&b?zjggi~FqMvIOo`AkKSL^5K_TYe&8Be)^B=~RJSE0|@alfw*JQl7 z6WHEvX^!0?Jv4rqV4|_Zu4d84M%>^1$pY#-5>qp%%(>TCsG!PJDU-;l`$ugkg!VQj zNqrfQ$3&u+5ldSU*+^eZ=b&}#z_nLSA_Q- zCW|Uo?MRR#jV+Czc~<^tL=EZn*&R7nm7M@kr{iB^vUtE8if?wP?x(*ZFKHaAC5dmQMlt+5iM4oBH0mP>Cy{x(40NLoACHQM*P^3mU z1NQNk-Y!os_tJ}_pOAJ}6@0K0Lw8{UektGNRlg*IJ-;&~zXneqh?ogEwoiRpFZ7;n zp)ugnv*yTMn{rRZp_0C}*NffIL^z}gm{tzBqgS6r6`Ci!9B-Oev2P?NCIf`G%YF3T zh=sIVoNlfKzH3?D#EQ^!*s9%pPJya44lJ;v;d(uVVdD7S`+Trh8&rOa^U`BXE)KF|4Hd|vEDCZ+?eviqWZnDlT1A|$bcd=I!${~#2?$-m)dJ0(u8*rl*#BqcY7}L`_{J{68 zOCVvU%*GRo4#fKNVPX$)nZ+ z^PjX#-!U@al1dgC%>QAR5b|!;&2l?+Kk`bcxhk1KnO;gtU^~QRJgEWB=+S4uev~1c zBFp0DaoS{G(dzrt;ozMMXj51y){lW{9YjvezTNJX4Vq#DO{GG%4(0thjVhf_ag%{vfI&t7C`si9sQ?b{FbCG=(_i~Ls z=h}U755n_PDVX^RO-JgfIf#FyAl~Yim7Qt^v4?$f&|2Cmai@{`9Qd=rOngh^*ZbEQ zGKPy0Ne{S1w{E?V?Ao4=&cM7Wu1)W}IOMd*VZ%TCK}h9xg!7*#`CO-JkKW7g3+3}M z(cSZ(hy!rMc8E?BbMu-6!C%#HVm~IoS7W2rFDJ5rwion5OiJ&lm=`fs3jd_9G)c28 z*Z#CuDo_g7)e5sxSLomHmCBbxHU>7Z+T34{Hr-6~pNAdadV+Mec*IjP2Y$raWT;O+ z(j}y5VC37)Y<0hbIRiuy>!_N0=hX~n#Be2@t8|#hy|b!{Ov@L0@(xB4SVO)&=&q1W^aXo$LJ!FvJQCii zS@-@ZY@J}9K-F0JVeXzY>rCzqIW~-3Qph%&yH3*FV?Ks8cJuB1&itImi4@C@OXef9 z)J6&~o_l2rhqRbJxTWx#9FkSh`zw)e+A3*N{+XW>lM}0C*kZwyR@U^I>}_IJ{))CVmQRvPtcjBK&w0NNF|HjR z9eyLD$sF|Ge-GvFjyImDek;&pbkC03;jRWC{y1@TlC`rhvBW+#m$Ztkl9IPeSR*6g z>CLwH>Q6qYKFP7Ryz%jQw{N(raJ4VvAFi#Jc21%>hq@nI|mjB@9(qeJ9;wf0V6>s+o}0*v|FSSvvQgD zFNmkLy56OfuwP!hns3o=ptUvONd;f?Vz0wRjce}to=^rbU6~Fz!PQc`KyPgx zFLGGRF!N0%Q-c_RRpmY|)9!fgiE7GJ1pp!riYy1yA5WNltW8ttw6cFpZz%aVx~X;c ziQZF;!{rHDqQDKx)l9X~KKH|AW8w_!eel;8tvSHDDrkhQ=UD8)vVw3=v0;?YDFtef zMXhE%?S0YHfk9=}F>aw!^=3Jl;+z zwupp;I+Q-=j)?j-36%#l6?@?90uL?v>ky3IK*}^{{l}l`<|fU1T%!yVIf;h1 zG5?e7M8{PRcU(1m)x#CHFUI~9gqQncElUYF76m-)hnB5jmOzOoPNYaa)kxHYf$fuT#SJWg+r=&<*d4iJ>};5`f5fr4T|;|Lxk&L>aX@ z-{EFH_`*Tj@F-jw{0M5E=>qjt@ZnYn%Yj6HR3<*yrkWP?6mn4(07~M2U!|ZOGI%yx zfi0n(z4*ECi>RagqZ%jQNN(RT;K=4Ag-x-A3Uz|n&iiggp7P7Z*q7N4a(|r2gh>I! zGiH|v8vS*|eUHAn(bu+Ga`F>CG##P00dCG}wa}(=Z)y~SYS<>*2laz2JF@;#rb_$Nld2c*)0RZkb3OV21rOo2%;k0ki|85jO-g>Idh|YL_-LF(k=h?{3`M3%WU zHUIRo)Jp`@yjX`!e_Zz3O9lC;C%LZDY#Pr$2Ujl|%tHpeT9pW<@*R*IwS~hPRNO9a@1iTydNEcInGBYJ0 z{6lVTjdVkv3Nu&E&2R_1C4s1}X6M(TE|9>MyAd;i5gYpR4UzH3t8i&r+QKj?h!3-v zdWgl4-hIZx!{T4&68N3R$q3It);Sc}o96mQUyNXz<{b{gLB3*LroxyZkHtd^TJyf3 zk(;$SgEvh87oOdM_qc|xeQEikB9=ZsD&NFdKB&7Z3li?Mu{(Uc^@zm-BB(1ou_!f` zsb6bUx^gq;d6i9SmPSS5c;mw-zHgr3-bo!-@g46Zd~q&(++CcAPXf4^fhSt_BYTRp zgj)@i*Y9&q#eYk~#CZP_BrN^Ft_{cA@I-oJ+&)Mz_aGGrnpx2Y!s( z;dUcjK_%+nGa35EB_Oh|sTKam2k5GN|6w6n^S*fZ*TR=r~ zc7A@Vjk{=dCs%$-_p?Tq!(yS6GkD{wDW(uAWJa4X4tNY1? zAkA?Kr+|PnfGdbGk7`)6|-V!tb&79(6!Z5ly)>hP1SpT%l60Yo_B*+ zNvO2<2DEc(W0Bi^&JDS||AmrlgG^E=jh&|B#uHk`5N+kq@X^x&>f-sPjHb&*`SuxK zUv!#MMXM-wB97H$H-1hVy(5TcjQjVRrJ8bVnc~BsVI}N};j}wgIvxA@J0(p5^}L53 zPhH}V*{R?8D0STM&;Kf8c*ZtTT(xLli@)0Mhv@M|ssd$fcdZpMVuhv_Yr&ny`ZvP6?XqX!&Hok6$};aoV57D@vNqt|n8Dw~^UAO78yyViJ^ea-aQh z>s3eVN7c`k15oKUne{Jkd*a$Z_vc7uG_G3MEdS1S_-teUQwg2w9z1jBE@ZEx{2pTg z)6oq1u^*Sxqm)Ojy^*~^2|`VVmAx}wO{<@uLn}O6Psy?c&ss*;Tzs!)I%fV^A($rW zel*T{^vNqavCSoDWi`K9nrc*J-a=FIKAbgNO1GAOU3%KjS(w@Gexh>VdsFfI`kOa; zq#P~nlxaUT9(;XuqunM?(QoL+O!5s_clFl;m{(?Wjd%)+T%)ehd+CN>JSKMZ{XL)R zew>7~HYTOC%`GzTDV}T{kEq#1Jk`pc$u$e#`-vp(CwNWCy?H9tZ9Z$aEIgNeCo(+q zX8D;B6qW8jR9^Br>@n40w=Q-2{AxorX8ozJ*qmsk;+I^_cW*2+QdoIAa(&Pv_f@f* zgRmmgzQ?z}C|teB+c=4k31oehvRje(CsTmFojcL!$V%WwU_4@9?L9@+8?C8`pxTVE zH-VnY+Lg&l`SdMIfBuPs#C?5-GV7DaVpg*;>D-?AI#7 zqB5*iK|}Ll;A!>T&wY{| z&&xyCG{oi~Y_2fLyd=>BJ>I5!pchBo%)f;$8}~o|(sr)@xwQ@cCl-zX{ibbPF`RAA zf#4caiNHT8w_$=lEX4%ue7VG(+U~K5rmNf4;fQx8&*J*-AH9cKXq2fS6`1YpbhayR zwX3IRD{u9w1GClU^!mNZt*5saQ2oq4SraBo_qP(ghui*XV%Ia{L1W;mU2(II3I199 z`u9I&IG7S8Eex%qNW8BdB%ZV0Jn{LSQxl%w-j3)XUG`Qz%1W45k$W1WL83I#GFFU6 zJQrH8cgy!(s2RM^4EyN7hXMmPfgqqa6AQQVEn-2sD0c8%ZYXKo7mS~eHz)4AY{{3+ z=X3M?Bqq}*Uw>=~v42n>QR=1}4Kg@eO~F~D+7_v{#+LWW$rA~@)W)uky54M1>OM9| zoWTh7%@Z;h3uPya_dK)w;Ix3+CU-)S9q<>>uy1k9T}Y$v4g7Jj;+A9xxr_5bwTiLB$CdQ!AHJB>FzOSy2oQ;~r zaZTQnVo-Uu5mahBPry0EOZT<1*|+JY)%6yG z+%L&I0|!6|GfHih^p;rsy~*&q;BPwzcCarCl)wP%s<{n`|DyB-zM(%)Rf}aKx4D{E z%^QDo zl-GEHM-@nrm#8Ti+z3-A+>9$S!B0 zeFr8pGEZwi!QoA~#uMllBcjD0Fq5xi?)p&Kw%6I@KWSE8YY`vN@MXHe^b;&v724Hi zvsjs?`opfVmG5D-=(T+Ngyryr^|1LA4hCscw!@JXU-}Q-_b{ZWfst zE>Y;6Cc@DUgg7(ce}{apN%y}ThyAch&RE3m3T!|OtZa(TsH9`>)akJ{*5J4Cr|Sf1 zmsxqEBXdxEO}YrWO`mlC%P|x02*b3HSq)#kvQ%yC#oH+IFR!Q!nB|+C1N5#+iG}&W z^zzEUNB$@Z`5fwdEtouKCkf+JC`~qEMk708buU4gvr$}3mEYEVn1Ro5USoXz{}}rx z(LMB0jLd}5-ToM=N}U=jv~Xd5426eq)Wm9yI%Ks-iM*d8}5E2!oCO zlh)KhEWF8DWezLF_Wg}|t+#=K=L)PL5T*Vj_S7L>j4@9}+UiN^sXPjY&{993)D41l z7+h>>?^I95J3RcfxCWJZV>+3YNkB*!w*e^_TTc(TUn zTN?P<_`{e#TIf9#x{o{vdXQq~`$B8fNb+h|Xr}&rz9_b;Eu+Z%oK|d|TWnr=N}LY- zWh4@z0VxnFry>3e@$ZX!Q|CKTPJVHr_XNFz22|?km+F*MP?eWsRi?(dv!Akm_qrp@ zFKMueX_|o-=;Zs?6TNBi^1MCviu)FLdqd0AG1JO;`bw;7^Qbxo`bw;GOF-XH;2*;} zecAN`=b^7M(D!z<<#JZuUa{9Px>W8kw=a0uG9)J(tXPZ!hRFhu=<>K)oT zJ4GW}&PI3w({)c^SRd-?-F^Om-5J*3ZQCHagI|cA`qSyvmRkHrlSMa1x&vdp5mdVw z?g;y7T_>ZM3*c?VbMMP<_q%_oXf&GBphoa+&jFn^KitGrL zfy>?)9{|6mk0_YyuMGV2^=KFQJlKvcsq?K}N2g<}#-2Sv^{8?1eJ42xJQySl1n2gb z{Mi0q;IqUkO#&8je59;J4hOk37SH9{ofLRjUGJ~DM>A@-*?39K)X>!%S|Sa~UgfFH z*jwarq|5k`PXjG}J!VC2o5F5Ly6_W%y~e>Fr!)}c=3vgyvT|2&g$c1~@L_BT!q%HE zjxFBi0An`|m}ag!-=?V7CnM&-Mi22mS(38Q_a?+|#MG{1G>m3oHA(cqAEqX=yH2DY z7N-e;6UM>A&fVfB9Rbm$sE0Y)@i>&XTGi9D>lkzymM9^7G&u9;mlDfOw;wyzLV z(RP3Hm1HxO4f_o|uZ<~pi&poF8(pDO?4lSZ&Vn592kp)w?GFJvkfOy-1)C{T_-lu?!I=oycre z)D)PgwT>K;yWLlU6Q9~6X_A>x2xY@_1|3J!cI`Gh$5yYtwgzk+i<}U<$u(168$kHB z(;u=scWFOj@^gMJPERN#rXDLb9y&Ks3*m|60H{PZkEofBo~ z+U=OI%^}f`k-_~JbUF1b8Q_z=!yn2PrZE7zKHmmr1uyv|5@{*0Nt0E97&0SxIi}Qz zgS@Ax9;YAXF2`FAgC&)*81jV}hc;;oAs>tO%uhFhLuV4gNYU*7m)*G=$H_Dy2av4^ zfu#6A=hImVY9BXWsH(E9|H8#!T3m6hsI<>(DM{0_e#6j*guh*n~2PUxPf zfn{Z!19p|z#5b)8Qwh@OV&TokQOCe?o)a&au zN(YHI4GxOK^nQ)s4bPk3fBma5&i)R%Mh?o|Hf_4E!YF2LG+iwGwMQB$zjmkw6xTnA zSDh7O7=`^uQ`FvDQkxcdpXW>H2AX<3-v=I6ujg$n3T#)Rc+`JC!YfVDcw2NwJxqzk zOMi+==nFg*9RE`9EI3KgSN$dUF)5w1Ejr`U!uzH881Fz+pC=vfH+yHjos9QSjlF*a z+ZVsjNQPx46IH?hk2{6*O8Zf1DOVbmm6E8^6oWo1Br9!2B_~yCG4h+gJC+!)$JWa> z?2F3V$_wX`(xz8p{Kgeo@&H18geMlpMLty*xpRPpE~-q7LGT*-%OZa^Dsm|j_2_J_ zK%-bhsr$8I;`w|w%QW&z`P-TEvS(dCj?cT&)>z^dK$)ljzn3nUU3p=DN>nQ7RHfcu z^38*!1WMh{b?mH4{Zovc!iz+VU44~Q1=~6J#dJbqwrOirC%z1{($TvYux|(d$)#NIvCYPy4r?UJdW-R}2=}K~yR1&I^jBAJVDt|(in{^er zN~#D|G2&(#y$bFx3|_%i#ynS0nfFrXUff&~r61+c$Cd(#n$)8!#wMIsNwglWy>dOw z_MkCv@s`i99%kM6JpUp+m$0Qcabsk{F2BjnKkm`jyW$^0 zOX+gqgrpi+0u)nV3zcX6Fmlmlw7B&w`M6xxia%d+?*6AevGuE6P}&lUw$Mu9$k8dr zc8o87I*5gkit@JD?O3#&JOgt*#b%UAlc2?lqmuNDV(NJTt|04#x*|EL@B zm_J3nr{Q%2)|ooGK6JKeIgV>=TZkzADPGa4mQR(4AvKcjeJ{2E^RUdP=&gX-nOkaE ziT2brR)hBoK@5LBwKabIX(81QJxVW;l{}A#me|5mMLG3>@_^R8B5* z5h>FDyUk<_$1M~sA~b?GH>LXS^x1UE%%8QjR-Vj(Z@-cB5ar)N_Zk zv35ubGGyRAL?lRGf*{Eo6gEfTp8tsoat;adx~L$3_Xl?L{-{4pHDhwj`X4!2#fx1j zEX!iT)mp#Ta|_3&nR{GA%DfJ(*woc4icQ9LvDB&#r+dH22U)G!Jr>_LjAE%pY2}L{ zOuxwN&@Cm|hLv-)6fu+#uMr#WGKzaFEhgTLt@?Y_q1n{|ipT0Bo@x3<1+gyCtH$KW zdC&juGDXi{cXkEPm<5JEdYBB0wia^C0+$#PPmY~`zt9G1(HTJpeALLB+SG8mvf)3l zthifCMgF&p2->A1#2h95OBowGA>!Xk5%X0B^T{zVMkPH5YhFM2!TDrO?Dx!z%6e3a z%i^<0S;t+jvHJH>IcJibzrbRn>~~(I;rK85W0Vn-a`Eq_lz%U!jM4>WUK%U5N-6ub zyUnfxt3RhLHDSqcIuvTD$=D-`t)WK{e`M}r70?z~xbb^1mtYg!0;`D#_XBn@Bu4xv z?WrvkYSkVwL=1-14*xN8?J)!WPW=FH^%WR#*#ywd+eqz)E=4O!yH;$0|F{5a5Tu^9 zywo(lyfn%Ahxq+3ZBYe)s7U_Pc@J&ZiNXC>pOLb^bS&mMoPR(5`2JrsNUc$n<)sF% zUU?aLy1s&5G2Hc`8lGK!Ep?91lS(d-3YYFlt#8C$E`v7@uR9(19fi%IY-|xbErtU> z{{+nE3e>8{PCf%zPW9H0mnhFRo^QSX-1EP!u`?en%C=7ZDl=;DE1w|1AZaZYVP)IC z@q$bFMV`5klQrRy(NUD}{1JJD!~PHL<7K!XS$Ap3Y_^TZZl7|#rKB}}eZcb-vW4UG zSKBVrUqBrru#VsEnO<_i^@oY}za>gOgmFne^Z9i=9r*GnGhRQ*RP}$j^{eQGtWSES zRH}qqM5rS_+jze50J`L}8T{ed&Ze#peMK{j=h<)c&DxeqAau8taEd-5I;md-^rg%N zSMT?g*^SEo941|%ZdN^8oFPRby-6V?_IfLzGzY{PF%tM54mTAr{%H<^|M=S|s-8Kd z;sx@-*=WQ>PhK|uWX?z&QIoIN#rDtsu9?>}tO%DLxAJ`{gl;e93%1VAIKUY^A!f%A z_U}nNB@Zi4#w+yI3G;8%tGkY-z7J#3L1r6mu63mI$kVPinieW`pO?o8ZJNQC!|Z7m zeP9o!gnbq(JkD~AH#t7j3`jJKx5QYddmL%k&;YI#lG#b^6NRQ=vvFd0i1UZ(XknRI z%eT;*9ma0o+FYY+MA`5w^rEsEv;Dy-##Z6aJfJ&EM__p0VZ+-&>?#^E;`%bp?75l7 z*@(2gys3Px!|cm@i*4^(c9t^au2gGa;5VdM5ziOv8?nIZofTYY9SJym>e`PN3Yvt@c~)grKVLEi=nQg;BXk` zcnSX|qnSd+*!QSWtg{H)#^|6slD_g<8g!#K)?vJT3{@tMx5sAJ9~>WV$(%2Dn5Qo% zmSZo>Qj@k$9~g!Z!e+KAPh3Jal-^9E+6TgqEhM_pk6C+O5vn~3YtO?#YDa3f#IXVn z0xbSLra1k;%mHgi{b4ds=ZyEfk=Z2qed531z=V1y-|yGGQ(u2xa|IS0#@1I~9yMZT z0#}4-Oq`X(yM`};CZ4Gsi%c~bs&oAxrqs4K8Vs?!AaOr3MIa|`soh;Oo(*Z83GAb? ztHZ&+5|;ElQCoep|3gb{d+&Hf(GmFLAn!QgrMwjN=q1;F3uim@3On=X=4)fk@;U zlPY_u)DV}b3L_A>Y@Mar|DtvjdAexF_;+NS&132R!`ni+c81n!-4Of9Y^e3-08KqCt!9i z8>z~537DNnc1dSHwUY-9pSf^9di%^I{peHf@5+2z?yfDhsz;`JE`Oc32w`4pQF-9) z=i=rE%+Abx%^I-e%Dv>W*E1vZPfq~F(PTD7DT))JuY}>2V zEG8rVq{+I`7gwU+*8{;{3d(5YS{pE$F%C-?@TiVSV zXL(OgHlG#W+DmUT0_0C-@{!8;reu3bg|{i&8kKFP6z|!@vk?uG;&)f9#caLB^7s~c z_p`F?a_3Io_Z(4PGyU2bF1*cqBHq=1V6yv;s-j#Qe1rW}3wc*8O7(FImg}UDb&o5$ zm=EOltao@;yKOZ^g9w=mSbspM(DR>Cg8%=tmGgcF~VL z^y8zp2bA@=JOooWr({oW|S2})8@OK|j9zII{KcW9U^nd?ZAXT+%fy}Hr@DEvS-ExPCOS2~}{ea8zCoMb7W#yBW z^|%)E1e)1<5$^_A>#znJ4UlKm?vsoY-q(nqMcn*fgO{Pd0y&G3)ob~%@{1mHHJIO(bGUq1gq6Z3(Xj)nuO2YC znt54FndcWnXj7gaM8JeN_;HIXEZ3R&S_Vv7DR1?tXJ;eI#O3CLUJLfd3|UuBRsE;C z0-3w`ID|#hmSMlwW~16-6+`NgWGd>w+FGQtJn+g-^%-8gf|~SPC&tu>vVPiDs~FDM z)72Zob>$JOX!cwrhHCtMT>(@R&Ef`NG{hLKeoT4m05EC&|Afo6akvm3L%`!=!sD^mh!+;;05+<)!mA(owAa6%`1&TR*dt%x&aYooF1iEHJQK%= z*-(TFz8$yIrk&@$$#dpQs{hR6j~U~RQiqe7yhCeLtLoQE!y?a-*&)tkwi^ei50k58 z9H#zS)hD`)WQsr9OaB{T$f--QlOhj>+M@&3#QBV2zF^ok2b&4zKz|3t?##pDZ03mg z0LEg3j0KtB?~(cX-iZg4ZcrDUMLed+<_p%5%ES?Y($_I{g&i+%4tpgc$h ze%~&2F};8w5SB%t!vusS$f?gLc)e2TO~`E3&^ z`a#h#;7?a>?Nn~%(-RLGmf~iDZ}N$I<*hU7K;mP&)zi12Q&_1}C@*(*eaKHYWp*GA zrROi$JFB0L@12bEB>l5xyoa=ixqO~G4C|lTsni{gbG2M!JYzkpQ&C%(#wN9oknI>p zwv~p9-wwx98GSZ^TJxt;YfGe73}?27lBkO$5Im_psB1_tj0yI@3Tg=<&-5t0@&YlF zm}hdfVbgFY_R^*5gIL`mcKuvSERyc9qP8>LElhX2j&_9TR({*vb=27?EDlC^m?)Rz z;)d5nfy?gsG=e{uNHF0-6enZ1_NSBl^pD0#W-XLQJFcG87)D8Vw!s{lc`*l6J5s}} z&Nxi&Y;*08k=*jXC3z_keC^$zMzDPnf(e083iSFjk^PIOCXhX;`S*`2x1UVv9oXw^ zA&SXKa<--RDRq0H+1--dK1JQhy1f`3nvo3;Ojxv2qlcRwl*9NiA>d zoV8m=Mc$TT*BS5WV5N@5!YCHX4<5x}9*0SoFmXpQp;wu9(4R8>tzr7RoDsSY7>pex zEOt`bME{S|@AtTtnV>y{mI=5mj^g$w;I=<;O+q8&w6v`hT#h6!-x?NajAt;o*(mY+ zoiT>zf5q^;nDOj)jVMpxBAs}yO~iMU@wG6%{e<7U{3}eqjz%#Z?&3NWFAY<$^DsFG zWB8BYuSuuOujhf^X$k!P5ok&pr-|qZ6FuO$FK_*vlQl6R;*o${tWwo=GC4+ofP={D1%B2b6v| z0(&Wl?I!}N4$_ZrcS&gwPx_cr;={_bcv3G|Z`-c6n24DFcJ24LCahQGZPk`<9rYhe z$|SFLYuK0eZ@#>5(yxBbN?yCQPuH!#edhJp%KsVfKixcuV3P}o)PG)z_Man3`pr~# zZIJ!vWdm>Wd5ZT6tQ^(lot(2>LWj|H{_z~UyW7g{a&Umc* z_1P9>b`ti+kvT=L^!f5O#XtJD@pu}P_`*7a0M~v(V>5ur2r1b+KbccQdHSUnT7|T5D+P})a zCsg3-UhTlu=_^B_wDIz@T_G*ck({>?e(9jAyZVr3awOP8xxeQ&Y_b`Mq#BeTH^zOI zA#Q(A?T{hgV5qj&K5nUbgHZn&y}8res%&daIFAqh@_k40 z?hA5l>-Ty}wF;ASV5`x2&>0EMV0uf`CY!SjCw^CbfjEg3#_I?CM(r+>_qaHH^#OG# z;yFmZuX$F_$}VSPXiCDm+vMXz^^0;t<)v7zR_cOyK-;uz1V^b&6%X1LMOK>v*KEKN z9VxbYGr3IIgreQ7Mv`Q=*H_?oV8)DfB9s^Hk7*8{>6e;Eu?o)y+|X@O=ueq~YoyCI z;IC=JJc?8B{+kO`zm3$z#S;zdOj??v6)7fh`08eLEaG`p%W?Q}w%t(lTHg)JUptk$ z)BE3eit2`%bp%NCuJEck+EPh^k%$F4p3l>HYi|A+UVVS_{@;`y3! zFs^;q*s5%CI&dr1G&a{alKr?Q;r&#Wsh5!(akIhuuTYA|bdI8&b6x=YNqBOly1i>+ zUoXInXz$k>Dc5_&lLbacV_uE-67}d9b*EwED$h0=8$)|Ur=u^g*Sl2NcBfJFsJ)F} zufZe5Pkt+DV=q56cjJAI>CVQQ;a=}W;(&UjS8k{F{Iq8HBc-m8-di*LPo;hVejMwq z8F^l*TZ7%nU&qRPrz4!#=PgmT6&OXcdZMv*jGMpl$vcy3jy2Yd)OhDSd1tczGhOZN zbG9)8%Cmkl+%>~}ypfs&8FXN?M5kjkFYH}3vAKfr=58Esj#@U2w;UdCxn?-*vk2aQ zjh5SS=BTUY7_p{iWK^kt9iHH}M~q@nJ=s_r;fLyfi}ix&Ta@~rGMF3%H!x_5g18as z$=jyX9BHf>B5(!1T}Y#^j_!^Wj>ia%QTiLagGy^g-tk(WEOSh+IWkr=^tMuWBW3b7 z^I+Dw_brT%e=kV;aI3|amr~!j?#eiQQnsb!ecdzN)SGvAwWHWIw(?)jM%S3Ikj>!`V04Yu1>Jt5bvc2zOnZ=Nt0uT(;eb zJA5pmi)j34#wI+At7FxT@h@6!irg4jHvSrX)xAFA=~T8A(`y!t7P$PLo$L_efK8!1 z@JeL4+A%Y()L)IhsPRg%&c$`cC>IMqBrg63JI2^z1a5?`!VL$-*rrC$Z+R!8$4Nx* zz_Lz##QV9JzLuzdi>qZ-Ez#DmU8-zLo2G1AJgvXb^}gqL4E3FcDC+Z1>DTD@AGk+PP%x^?9%Vg$mWZoRjyh&#M9gk;5 zGe3{}kzBYA)FO*7#xv98@1^uxO#77i&++m9c{!e7(bmM{))fWu<5f=0@OsZz^ik?x z+8TLvM9nP*&)fzv6gV&>x8VuDai}J5szG#kgQ2T&q{MTDPhCfx5K}`loC9(d(d<)O zk!6hAAwB^=IsBTPdtWqquc6+vQ}|=@E8G(t*qJ1Dc?Ndi43|25adnc|L*Z<6d~5Fd zm+FtKGP(AzK3fnwsWEZA6xWGx2rTwT>o@E5qnE!;xNphXM%XxL8t>=&a z<$Au2uc1Ysz|^tD5%_OlJ>NnP4qaJ2lb%!fKr_z&e4k6?!)r_)2hUc)7Usov+=<yUI(CWhU2`Lf44{3yxfs3I+e{ujw~aNKbu7t@^Xzk^)I}d zQI=!GS$Eu=Yei{3mqK6`l;&}%ol0#eE#gvq)xwU_QZB`L|1^}AacMgCd!n?QOEai6 z9i@wnJ8}A5*}T@V%=m%WMPlfR$ZsayYEI7ELX6;u{IpVk3kDH(9?81jh+~` z>uGc=Lc-z+G!#1qoNdm%&V%@7;(a6>h;m7qR`z6#vbl6E>q0E6j zX^VgQuClp2*VxWAC}a6kt;*(QImRy01aCuoJWVTl?LB34VK!-K*=y8AZqLG@jMw&2 zUWT!i@_H!G!Fh)$FP-yxDKCxlj#HkU^8%D-ZMu|gnv|_w%GM@j zYn3CiMUKd39+AyFAT#pi+za+;%X;MCYnB4HN`YIXz-?0Cb}8^QDR74rcsc~WcLKf8 z=M2#U60=FmLH%LmWhM5H+{FHolh{A<6Z=OVm&W8>#H9{igs0L{E{z+1`*3Ok;x99{ z$j%fe{stC*L!oPrQojJ=|IrAE+-Jc@<>P+b38E_9C!s zaoYQ<;M>DeW3~rAgahm-=Iq`eT*)W0Cq}X8kd<`Y>^M?57>l%6p|&n59-& zrB+xZ#WqQ?T~bUsHEuAaKjx73GCkfO%SiOcvJ?HWtVDk-H_;!Q&#@mMwJN%^EFvTtG{~wMs%18| zK&#^I$=w#w={+30Wk|CBCcRN+xLqUe=W_-hBENqzx$P~YhkoaYE=;e?l(%XDuPn+f z5-rA#8Sjfd`bA>X z%kZ8V@9TBJ7Axg07TwhDu9<5&7p${W?!9`u-TFr<(kX8_>c!p#UT0A5ee|Xew7cyy z`8FD4~--M%nkh6oY5~IG5v!lc{tkl1c zTS_)4Qoidc6@$(;b>~@xh}3Xtg1R+08`Y7SFdWK;1Id_y)aw4T%tj$&cw)Hd+#44# zP7D;I0c12_jDD_iV&G_x4-n%5NqIM8TWq6w#Cb5%%U9aWr=X;^Mw@RPT(OqFqS!p1 zUB}sLjLkFU=N0qDi#BqRhl}E}e~62)y9ZZP8Jk%K`Qt?m{KP~2M7}N_z33S(a&u8G zv~Ij;6BpgbMOjpoGhXx@7v0N6IaHKAUi3T{E$5EL_0Ll2PrS=dM?H^oWKDTaoaD^#Ww_E0o4rUsA zW?=7M8Ar+U?bt>&jBQj!o$@R7mSo#T9*H*=AXsjtKm}iVd~7;;Z|JY;2t~`oh?Ykv zTGlX^H$u^}$1H8dH>P7Ofc0}od!H@seU7yES<>F;N_(Hr_C8PA`y$=m_iB$Gmp0uZ zZMs?7bepv4Y0{=!Vbh~t6T(_C1b>{&9qT(;^j7+v9kb{exbKF{^OQhy`7#+lQ= zPzt(lnIajQGz|=ONZzGO-lfT*)-IW6lS8dl4z(6J)S7vyohnD#=v*k++oRoiNDiPD zIe?lavu%>uX_DDi$!xo1cKU%G0_nl6SL#S#1zP9 zl^OD(F#dC_`4q;#k|G6lr5EnR9`n$$MC)Ha*cHmh{(EK=RftZq}KUuR;!P7=RQ zd$dRTa2Bb8=Kqxs7aigoxUXlk#zCyIujj|Ok)vy04r|)E+E)~(eQCP(mBq9#D?!hq z+Lx7}X;JSjD^Amv#k{wyI8SYHLc38#H1j;Ezdt z&5G%(L+6WwHF{iMqkPGqpszO8>!@C3CyYcFE8dW>-|56b$@t*o|8{X^4uRM&s>(#8QoWp$}^AJ zq~~YK@z%4<`oS6v;`t|>O|4$w>=d#b z5YKs-dhR|m&}*m6Kp7lF+(W1j{x4?$08GOfCbyVHT|#zoc1MQLCm<{}AUveq*(K=Z zO3$gpRb7kx-0OxGH|Na~!|4*Y<-yHS) zncHnClQ+g3YW+m<8QMjL%nJHbUyD48PR{dLeJ#=hhYq*!tnt=j*%ph*#5*V<1+!`@GJycCPI zkF@WC6Yl6&{GVxD3qoa9*pEf;8S=Qi^xuFcroQ6eJNh;MUQxhIM@Ee>MsNg z`~2^Y?)1Ma3gCda4=@aU>qjfUD`4pK?;E|tzfTnKQGqh*#f#@X-d&}|;x7A6^)>%1 zqfhu>;f?7^$JG=5*GBL4za|Pm7b~%MMZ=CQ`{$@89!?M*PKW}S zDBbqM(PxH?8Mf|wvCceuC*$EW!UN2|)8Q^qVBZ;ivHXEMe)I)k=vEK=W22AxV|+5{ z`ZB26_P<8g54(5josS3@j`73E^qnf^P<3+KKp+xlk z{_fE`{oM|nWeVs0F1{%dYxhw7asU3&-TwXXJ&4{T-{AiGK2iTpe|+?Qf1KL&MxPmf zji)LntA2E2)T$4E@mAm3E2#FZC-#2SxAros{lmY!Ke})2E~Qzqx%2l`Np)q^%qe6gA#xLZQuHQH^We7!7%9DHYwIVieYdYFuWKD?0VxsEH2sOVEkyo zF#mC?;-1U@`Qx`gM8)tIsfv!v@o)9_MAv(Jmj3d5Q8TvWPWboxcSghGzuofKt7gp} z`;PA2`3&7zRbz@jkHvDie=hs}?mhXUhZ|CtOpSF6<{lQ>JG*z~i$4D5g7v?TwaeT` zw|%Esk3aD611Dp#5!}mC`#!Ut39npt{kLNsx!g~$J#N-h`h(Y9_r=-=GdvU1@C259 z{wdL2W_WxV@a(=J9Eo*|;9fcHuUPOjEPwR&SbHwlGcKcF?|oR(8;cFLLlzX+_geLM zrrLiM>yR0q3JacRyuTRctdDh$u;XZCiTyRI=P=b14y;~&O*iWA(%AQa>gn(wiQaSe z6-Oq#WY%A1|EzmoK1qn^`bjVB*?$SwuXfTi61mZ5&bxo_-AMpSbmOL8C3+qFNoK3Czo@=b^TAcLcS~Z?5BITe}_wpO$ zhb__zL@6~c${<8wkCCoJt(*fhoHot%y_w!y9W&jlj+M|W`M%#_l5YAbA0k8&@l~<$ z1Xt)-p1h`;bPMes?M08sb)?Fw1WFwi#fL-T{SOuhB}>r&w>ZkgH*rT8#pM3yYoof`Yh^sN`7|S z>bdH;%8I}%!Os%!(c|d-x5FEUfL+sJ19T6(lMUSqu-G^=pgX>(ChGZdVE@9QQP0l< z+l_~dFIV3Ueb^KAJnMfOry_rh6M#Q<<5cF)=}+Cy-Jw^Ufp>#{r)mT5%HdlDNUkTd z>{HsfRqD9afbQRkDR~UeLnb&u53-q+c2QNn{(N84hFpA4!D#dE3d zeTk=YErmDn2Y@Ef^AJetr0;+shY?rh7J3*R2mD71ehfPD)laa}DksS!|A3VBzz%ss zobKH64_*oElQ+=Z5XQSmA$>fCN^)KFp&S`bPk`N%(SmN&md3E_Cn84BExYH+^I|wD zdJri091Oi85whQ6WNTdQ4#Gj=lRtQ5X<{`wdJ*DDWr?K6wHM+G5PsX0IsQ+p8 zd{O<=>P-?ag>Xd;JgMG9ub)zHqIXZIH+iZ~#32seXn5O921Ggt!Mci4wbzZHa zz}nIm?GINA_6q=pt8?}n5a1H=Ka0dA!Z`TEC87xxic2atjDEaYft!8`LLE|l@b`%} z$pUVfl*w)uzcvuV@Ktkz9jyCNqB;G|^z=7o`TMN$_t~{Zr*TQ_>M|}JsAYFzXu1|h zcFS4qk20%kwQ6g%DrJC;7I4e%H-al?^#l z0(*lWC%SV?=KNQV#Vj<`PvLm*gZylPHdig!Nxy67s&jVc(8ayDkm#Zf7rB*znV#U@ z#KTs#59WL|o;T`$damGjad}e?IL^36BTv$AF8w}5zfSsnf_?`R@4LYJFD8m}EDD@A zaJyg1`x)>Ir~Ym*0HW(T8%&7!1_PqVyvfBlFmEtE3eB6rbTJGUsL_p!p*$Xbnpnb7 zb-mL=#~cK=yyiB$$n~P#v-TvU`|i~H$X+dn5vLd3s=;ZaZEA-Wbob%kv*k?%THE>*Cwe|f^jqe}m|9cJKwym(olJ2&fa;SN(<|D3VPx70bwfp+WQKfZ&{?hkoUEaKH76+xA#%a zK<&L$^B=Ug;k#ebzr_Q#H}k8s*O&g^Wus?AVCbm)PFHM7YpT8Y}<8j$TCdW)}I(a=_LLr}s>uv<2;p_n7U>~-V?4k-Mf4gFukvzuE za}}ssCWk+=pVlRg878y^@xyb21-WN zYFGFBVkg)gsBr~ffXalOFlZ>s*jhj<@aG0iH)Ydw&{W3C;*}r=({iCf%kO2-@}>-0 zUL$B(WYY2+5`_zj@g$p?a-_H~CA}GxWXxSWg&*`s#UkDs6tb-_@u8q(2~%>nNl8A0 z^GX&ar%f4vk`H|?i;{n+=#P>cDg-6(s{kblvQU}L5GVc32iddDcW>c*ez!r0%(Ls| z6{eYMSiC~Wjg_X{$V#^~aJ-UHx1GfA=JBQi%W06EURz3C->9#F|G9!*)+jWbx}qrCuS zgEyW@Hw!%nNNvFj5Dw3tdJ^EK{QA<#={$T03eSyddF43O5&4xZQzJtJrD@JosebKb zb9teyMNibKwM&rPHg)+ts=86H74JhmQm|g$1eS@#5_!l-qE(#qUJ2yY3G-;umL1bjA_Q_!db4s;>h%?Co19<%aspX-vGvx3U5H8gUCuD7B zSLuA{U~&XmS<+M{fac}2>bG2F=7(*2ir%-)&GcUwW2ijsPq z$|!nOy69yYMZG9mkX`i5bkUrQq8=1I+?!SOqls40{k=v}6hjCgtUp8VuZX>$2Lndv zgBAJPV;|%pm1 zhgZP)?j9s`y_=H*F(bHASL#=aFGN%uwd&p_s?Y_mOjmlrM01eHku%Ls@IX=THAl(a z<|w()7$p~3qvT>5B^)f!4Dn(TGdvdZCODo+jlrC7_h#p(HsoK${DJ&I;@1m#_cY6o zTwXnF0Q^F5`P&1{_bpM*1qyAmQsecqa#Mz!Ye+3ay(bZZ(1uo0-Zl3K0m{N+yx{zE z%F}pQXLMHx4D~(}4{J^@Em-sd@#FQECJ4lDU@Qjc;odldc}B+iH{vF_TiM05F6ryzmxT85xH*blx}t{-5& zG2XW^$W?7i`pPTw`-i^je3kbNo=|xOE_A}2;AAayE2vo(`_z%TlExBNwLcGVr#X^U zpeJ}v_d!NdD{=6x#w$>h2z!QFucRk&k!tSnK>1kLTqh><2bh0yFy2GU=i8JS2!g{r zP0K-9X^3o78nn9^E%3;yk<=b-3wj9~>5k&wU_A$rQ9JY&hk;T7$gO)c7uTuA!8PB6lQeeN#Q%&*CQ2ZpxaLgOCT`9%q zY1My#XaK}YqS+S`uNncQXo>5x$&p_gDJ-#eW92~1>1&p#b!(PZsC>)2mA@Nrj*jd6 zdqOXx`*t~Uzr~-?N~yR@j@*TMSet+YT_vgI(9T`Sg+}1Q*{*pueM@czOmg@FD7MH% zWa<>rrj)utv`k|&rQD}9>OUE83CmfS9>fUcpbi2{VLtKoPkTQRIC@oNAiLMB`oWB< z@1?3ITU{$KgiU6(Ayj*>o##1^5Pgk$$@uheztAp5wPzr)H^Lb1Bdy^+$`pG{1qC6L z!)`2nvdQOd)%QaGbY~)O)gXa9xa;H#1b*-Zfry;2fy1Zvo#-I1M!Iez5?Qm)9j_Gn z=1fjas&;Uo1n!<8&1PO{sXpJz=-R20tpBdDB+JC%WMsmeX=nnOFD}B1afWcpd~pU| zoFh7|pC{%9tG`E1lI*(9pFJN~@1wP;V(&Zrq(GCrQm)eO&VcytB_!6O z<4lOJFgezQS2-*30~<>gXLd(|%hQHFYX)~W>fan^0W>3H);g7q`=7O#jbFBBf$(7R zOq15uv(@^eUr(j_v1b=%(rb8gh6XD!!Mvvu?B20v_s>fcjLQq=L4di$v>ZqY!RRL8 zG>dQzB4w{j8@hH>TeHtYR2oGD8z~4j0)wGR5bQ~RdZ?cTE=Us%Mu=9uu(p4~$>Gn0 z@TBGO>z7;7tAIDDTv$icN@^n?SQ9WIx<0YeGMC`fT)|Kn6+;HMVY6+flYU0EeV@Qg zxao34qd~^PMt!garpAjNmdp$)0okbkPYnYJS)2xxfP~sW^MtM$pR+ugbSlT4V|GAU zU~-&=aOJ$jTUjiZCPf6hA8Ecbim-3&S)#>^YW8z-_?L%dR~}0)x7d~X`IObqV8eeZ zbzin;H6e$;0c~fL$+HOrdjgEG;K-7v|^Fe|Fc` z%y?2RrFSBo*e2V?( z_m?pX-XPGea9;D)%b1mU9KrQ8a#ZocuypV;VJwSZ%I|r6!Im1gG4ihZ0(LkN;!_U4 zXyfgu#Ban1E77hrIB*=Q*m#*R2VXDrz1n0Up57~f`6jMc^EKYdkt^)X)h-k8!VD}8 z7T>h1aSe5YCzta0FmNhLH515z9_5kE053UcbFR>I3RHV$$8Rjj?l?^_N0lo8%|A*+ z*I&ORqw86NHF6E|Tw4-2>!tEh;);`oZEZkuR|;~=krRestsO`ioNh?m8J5Jo+EfN1 zfp`n)SYq)BPFn9HeniSp0;q})vMx0@mjna+?ou%fkUJCOb4V}uG;#EcF9Uepr3`TJ z8~-V=Sz{&!^kwz>F{ z{>RJXmk6fWP}Fz4a0kzzK4AR!2lB=u23Z9D6{DH=+l#5?<&tJd{XZ6GH*C;WZ$ZOx z6O1AQ40i??k(43}Q1SuFYQzRwO0&y~?=xE~L$n4d+Un9@9Klf^SIoD`>pMu`9Qv4q z8uLre7tCH|Hl;}uu^~#-DND2*VdK^6)-LHQYAT8ar#+M9?tz1glgdF)3(#cbo{%|qx!lhC2dwP*L*3Cc} ze3S7uinnif_rE@~>?;@73j0dhzR&g*BR=wMS7-uVZ@{%Mu1t}HBh+wlXfiSc6UyC! zs&^Ar@21Ju&|6(C`tgfQh4prm(!z*D%=$x+*nQ22>s6z_u<^)Qd zu3BEb&$5yb2V@vY2#y5e@N@I}x=*Q;sQpj+-a-yb)t~*cW*YN1+YGA(@8N=$cgl3r z?cy09i}9;za4|B}8c}|#QC^dk$&qcr>x8NDDuWf1lMUWWUTGvqQ4jm~=->H_)+rYm zdzHy^I4W~8pFfRkQ%0!O3br_ZaRK~REPX(Xtr|%^tRC0@^ofx%o66mJ0Si*6P1y~> zG>;%vWB&HYHu;C`$@YHML)pEbUd8*v^Gb*$=Z!IGTKtvsHH%H-)B3+n6&a+LI3uax z#H`TQFO3$`^iQMHK~higFZt1EIQ*#H%BxzQwisKl34FV13@qQL_Rrjp^TaC|&Vlyh z()7=SuON9@-}b#``@^%^w{!a2w%m4O&ui!ZAK|B9w1FQQSv;3!<7eh*#?PfROtWzD=Gi7LUMT!B zTzt9zL#5d7W{Wxfcp3M1IuY=^fLfFzEZ&znwLJJIuo2~r^TYw;8qxC_(Q{$-isy+N z(eoP7^BU3f8tysHgtE(CEu*qurr=dsXPw~n_2T1Dfa zksQ7i-Yy26-e=g#&ga+3z4YA~jEdx0G~KAjgbat5FUk9kv)M2;uz#kdFLX~9{4!Gn z8l5QuM=vq(gSfE~&bpAv7SEjfAF~CH)5a#J&acs=SYYKp znZ)@|IO*68PHmyngf4QFW1%Z&``gtchX3{iZ59q!N2|)D$ev&q%@5z#u5oEs7Y4R2 z8>3AKO|}QmDULZBoSdf#meL5aa(IK+B;ddvy;f3p79W(O@YpWiD&Kn@6raJNfL-L? z(WX1GFV*op_V5WB#SORA;+Xui4!Le;@^SwjQJt9Fwd-BLv$m3LFJdEd?|U$KklGSD z?ohrHI!+bCaOB^kO$xjVo2hbfa*QP}qRoRPZIKfTMOeSBG7hc58Hg=-kNSiBA}xB8JCbBm3W?iX%x$F0+{4f12p=glwId|(T4iHZTs^G+ zWDru_V*XclKo7?lR7S#K1bzUiEA?&X2v0d0%;oj8E)0GfFEx0RG&Sl&3M>Qoj2u(# zTm%tEy4;p?_~r9rmsSqLbk7z_cVe)_<8o*pNW(2K%(jfezBe^8K{WEnIaVXs2NYIx z=!K;CHR^A9g~Hk{^OiD8jA>ixb(8+Hv&6P}Cq7-r@VTO)N~$%gHL^R5;wxyvNzE30 z_tzn?ywT7Nc+sN!MWd(=UtgCaES-o3z^PKak!{Pr5q-voBt)x@!AA5ln>7(^a>_BP z)7d)D-lG5YY_2BIBS(JCDSdoyet!8`*7Gw(!Xa1jvB)-~!WDl2d6zq32KYT_72<6U z8@m&RzAp^Xh1z(n+NpNXw?47cu$7kuSvJ6XxW2Zq538@XjXn%E7z4vTRm>Fb7B<3% zeNY%1^`Cf6^&ese(oc?jZfDGq?dT*vl+}0fc53wFW8LX$-s`_sSF%>EgZSh zIPwY{t@#gd{*IE|98Cxy3`&yywh%MxNJ3_8t9WF=h~UkoVS4?=h<8J z*=7;tX)s_TJwrZ~kp>H*P338;!6CTHHKtq`IIBG-!5$Mm=WI<12h?;k4C_Z3DuXhD zS9?CMaUfxcXd{b^3t&bVbuyJ=>~US#1fJ$p8$CGKKm)hRXa~#Nt>f(SruOhQIdTb1 zjBG0?M2zyG(Pm$ft~yLFqjU>yv;ZRqDpwCDe`PkpEhg8S-T9k<4&%90JS)(*@iS+O zNG@2^sxKL33IZpqN40z}wd!9VVeYLtxfdccNhExn%_m;9x=^ckYSna6K+<(Mk_kF# zdX84*NVN9rqQ~5s$XNJE1jK$0<2`YAFSb+%@L!2vDcLxt^K>VR?Q_%}>GNBYXtpxv z|D!bj?~%jz3nV+W*22K9Wfy3RUD}nQN%r7b>h9v0z22$r(psGu8J(~!;Ba7cz7*KE zd_InHsjn38mGAurs#uKO7m(efT?s!yszZ)!7nQq3Ko>6(vmTTqdBTe52^`j1I7Opy zgV3t6F`5`+Hvw{*Teb=K@R^I}#Uq5_4#SYm>`twsu(*rX(9pv$xtS$@Hk|eMIcgax zw|29i4M;SVuMLY&VWlm!g4ViCY9;n%X$n_sT&Ws25nwtorGVfszQ_t^hS=MRqJFDtF5%| zl)&U1`@P16tc)76M4>OK1~+`$w+$C--q@K0LxU6E?;#-=0c@Z47OOiu6#PU=UzL;jDY?Ty!ywz2 ztp~IB|HqNSGNppW^psj?2lBI1NOU+GoAe?N54b2M^A`OQzH`k>r51Zz^b(IDxbB>& zKQUZ*!%ifZ#Pn?LYP`nwro(-E5Ai!D^2t7%rF{@5@vL=Q=+#Rck^dl~*^{?rz*ZRk$P796|< zN>3`Nk>RkTub=5>pi7dGEhb}0LLXtY``0Vx~> zAu1p9!}z@gk~?^#aC|@vM-S0$*+r%z0vKnKnE9lt8BvgDtH*Lmw~A(8tI5vt3fdz9Q)3D@Y$dmsZKFkBdE} zBA%aMe%9x^h@&Rk;7c#`;LH*aW1e~kM5ht2EQ2u{r<(RC3$#Y$|NCBa8ZsvE?q!v* z0Yh^ae9@|VhM5!ot-LPRpFSowQj~Hij;0O3O*k$Q)izNm- zx!eZ@CRl<|%*-$j%ur~({;t@s_gu<`WYoN3BkSZW9e>bAU*@^e&MWAOEN%G_=0_ek zcUe3MkDMZ6#7l`MFA+RhtW7I1J#s8aupe_9`|p)#BD6Rd^3VkaLvkudNKS$%a+isT z0&4(j)7*^~^5qCzwIPa_A_c}nNFZvmC|NCNZGy9d@J#w3A#q$2L{$c&xuR#Ywy=eYnug&RH1f+iO%PCv#h)T&_e?M?S`5uRlsgXD{3U&QP7d^aPTkOQCAWo;7uQ?2jLujpT)6Qs^ z7De~1f~-=(oeXU&rRx7UMbH&jvY4Y(Ry(z+qBS&(=7RUD)uc#9-VXjS`H;HYsh&`m zlZs&hz8a@8lDUk(&k&viTO`^LZJ|LwqUhbs`htFqPVG*j-vlPtGG}11lax#%Sv@~! zbp?*l4Yfk_JUAc)J^CGkgz(tc6aQj5Rv!R*QOI#VzuYu@?x-u!4o)5CE zy~US`{SoIpyWZ}>rUH%pKuBSKAM*@Qip0mS7?$=xv}pu zVNo8GAl?yF=BlNdZ0rHz6Iu{p+E6aT&M>NQlH_P|B`;Q&xM=FkH+aWrIe2&S9{;xF zXfCE!y3`I@254u}N`nhkx@lAiE7aDnyg$%gB=p5QfR9K@8O>XX=d%X}Y0%f@^9Ci2 zR$JW0n}f~%_T;sieE@X1EOg~1hxXeEfxbKP4F1n$^-;Z3%1Qy>N8icZ|0?2q!TzIA zUgm(;;R$8rvFcT4!nSCT30nXz08VoYm?T84q%HyZ2h;ix zCk6*6#SfN?H4+Fqr7tX}@;|MWjA7Hy`B5*x3*vZI@I2_gL4r&j{b3wH-V`tE46P8!9>|LOHa+pwcvJp1HrI_)1#!zwo!E zRNF;tI{7b$5jU4rV%|*4K7VV(#O1;dJ4~uwqgC@!Z+=|tFf2+m2@y8`Y(&$g5x~}v z%wE_S3x?>svZ zAqQCkTT-)K#tFij9Gk7hI;M!jvSJ5N7-+uR_f#VePo|5DPCyl@=zFO0>jM-Vl~J$| z1#<@|_(|p|$@j%6Nso0(vLNG>WMS4RN%XQYql0sWVaX+SNL#GajG`q2`G&HM1Cl?7 z2K|_!dK0cvv)!m^kK9%w3|OSiAY{3l6gpafO%X}0TU;cf2-3)(*#av>%y7H4MPUj|Ic@`uIk^J$Lf*90cOjD;(O7VCG4?-s=>2z&X$5tuc2o@qr`RWXv5%aN zrM?33Z@4dx7g3(EbQHnGv6+2JKV7*SujbvpX@-MkUtu8R-iF+UsVpgHz(9*_}z36jpR-bQ2<^R|WF_XAC zW%(2J(f#ub%bo=DcFXXSX!He&Y>&2W>2K_f?|&y}g(gsu4qm=dWEh!?$8$cH()H zk!t!d63nn;NC}`hFA1v%Z+)B%739M&dQ;|ue3h0ai(ywCc)rC;hMt$I2>|~KsNEzdvL^Tnl}crdk;1+LDx{v7&-FV zAj4PM@Ozt{A5-gHcrwFyay6c~@ubdpGSl*ntIyx6R(o*OV7zOz-ZkN!7gw{4ch}&Z zgeT3!6(39a+tro=HMTnudOxpHtuKtdCxzZ~qvULLJH4lcwOy_Dh2Dp!ZHv5BtuIll z5g@I~_YL}6=ey;IJgmNq{#2JHY}oegGPc&AlEnEz%x}DX^X-#j(7|8Q1;O(_lGssd z5w?Ru6Dff%IgG3>39e$P&kJ*L`Y11AkF>)ug$5gO>>ujRO zq~Z+W9X|`X&DzuY3^Bq7#2n#qSfc0estLR+izB{J&rmTJeIgK2c{+L{W_b>xt+KEk-#mlTnsxoydg*QU7t@A3A0RS z31*i4>Jdg*bc#R=OdYBHnMk?R1;gG_6SHbhbg8e_;0C4<>oX{MlF>$MOG4pKjP@9R z^2V5xhu5eYV6Q8&(qINHw9>2>wKB_cwI<72Q2d(fM$P-}HgUGqtbN@&u3N6j-&!C1 zJn^!jA9!ZzZ=5iQA!1F~jYeC*=Pqp0NxUolGB`5JUyf7(^l;vptVcAbt&eBQk~ z+iGd3$6^Whs`qUvQV#%u;;YN=RFA|y_LAcCAhojr#_dj)J&La( ze+Ntq6~ygjpQ}n)7g4lP-Ug}SUiAUjDhf8|?@$lN5?)flP;0YqcK#80<8CK2rQ&PJ z-zRT8>@?oB<{we(%1%<9J!tY;uA|v^9mz3I88p1gP~1c9me(>C zv5RK==lSfQ^{_SZ0(1=FWtv1?>v&4Us#vfCF+ACrwO`5>xE;$dM8G=4_ zIV}6)=sTc5=tsP!iRlg%sjWf}W!zS1p@+Hq8~I$XgQk;5>B`}ZB^;d3J@i;c=`tEVlD+THi|2DOk+0T>=ldAK3W(2#Ex&CcToTa{! zs3#R2H_P6Otpc^~a!HjgNB@wgvX$LJ5PZ2YgD^|;_{dBC+VDgO>ST_;ojJ4mdE zTh(|{DaYr}!YLq3j%=#O$CL8}`Ve!!|LV`B5^KdQqQ=@2d8lt~^Z1b~KRD^!-mVYw zA}cYjfIA?hEE6H&nOHwvIOtS7B7%kgsCi1bX&(H2)cyP&#NH7} zY?Wyhc4}Uz=@J)3&vC-HFUIy8eaA5aQ`0aIhNVC|+7=APi&*bwUR$ z4aE9ms@1h{f6;r{{bc}lD3SgHb`XABwo{k^XnEUVp{28Gv(wfxFb_Q8_-Z^*jc$y_ zA>5-@NBUCZR>$e6kp=61;}d@-q@_+Sh{bB3qU9vs5P3 zDTGh}XvO9+wC_f}p{p0Kc=g;%g5rO%%&NBY%6e*7AI%)Db0kqOG6!Nm8hT`2jyRcB z;m$-|Ct*Mfz1U|0X|fm~t^ehu=U2GE;N#2*H5p9L?LuS7R3+r_xjoe1RsW`Tf-cJ^ zoJSf^UO(Fs){@dtZW@dr>`w=n0)!rX{YvoZJM49w+!n#LUK?M(<( z`6ZZR=Ok|DRLr$!Dz5#Y?Q@$@Sd~^&tI5<-lhYY#jEzKRFPm=onh!>Ggn9;H@XHZ6 zghOW4dJJ_da{p06=ihtT!je{&NRxgw6QE2@DbN-CHbXM9Ur3x;6%}Zqt*5D|fGZl? zZ$%e!-}_Mie1IGJtPi+_TIltGTj6?wo4Bd0Ciq()*Am)wdesNHVNFu}(q?k7lEt|| z?EE6FqJ+3;q{T%$4+%~oy3a2nK2n+m4~e(2Luo$3ca>P~C>Qj@MYM2(mR%IQh*_wl zQ*v5K>62$N`OQT4Y=ePBO>CiF&0Uw}&(%zeHp8GYb!dh`h5c>cuok@2T!BuGW=tzg zNnUfY;jxV~hFDSa;tn%OHkaCjs~sX|A64p$sRw=xAt_sbR(qHVOUDh*kJkqetAW5$ zpL5}*aXXKBG^$Y@#_`5KF&m>}{94qfRZ2!0KjbTDRCnmNC3~^KHizA(v`Hb3Uh7uQ zj--O;8@4N2DVWtNwN_)ewh&fk3&Ft|>kxuiuc67YpZza&r%8=Jxg?JL71^UKgnIV%R(;{WdJU)G z`F6Rg+w$K{2n{~YW}g2QchRMJ?nsJ_g7P%6>2vGH7IU%T89t=!kB-EYS^g^x1CqLWjnj7nI&ZSqiwRGn;?`CMN9(CW`SSQ^nzM05N(d?_! zTD|FqjpAX0wzvRB02f`)!i7W^*Tg=QqW9$YQuFzT4Z9*eZjQYtX$?hMYf0z>IlqIR z%xIRfytDWm@x+D!_K}Z)H5alYH4>k zTWQ>Hm&Bn6W_qj z#+@#kvH&>S;^xuK`+b$9T9kHa&845q+eq5f$w*CJOV4`f*-3uZ%+DI-XQk4)v35dO zmG9cVHkJa@#`5}Lo2@3)i6bB7OK6$A;AhVpo-$RMty~aR4kzKlylF67b)1GQG!~t1 z1@R87LtqfH@lL~^ANvHIsrfEKH&n`TIg4-CWYUdg9cYQ27O07E*){`p5T>(7}Y>c>u7D?|>}57j)ik9$L-$t_2I z%en+S16wgkr^fYAkCYxMwa>pth*532w_G{~AcHGv826q9T4EKtcL(xw5K8NAvq?D3 z*r;##u-AxA>yCXgSjjwa+A0cV(e)}D8+?v9ZMOR0yWp)=AErog27_jnW8AOr$R>4U z7k!o?pV@XPX8%f8YfA?Ab_M^OVXUNynTQwDR&rbel@DhV;@YY_HS%Lyoy-JBz$mRP z>G1>FU+wH;5%N1wA99q;voW~(hJPA*f-|&PoJJqCvd&k#vTujjGMZ;uh!`wyI(Fw_ z(67oR806@w9~+E;l5F%lu?LXPZopIU5orzh-onc5!>^AH>;95k@%C_&6 zX4`iPv+X;cZ2JyWEj|m%f|S;fk)zs^(BPE|Y2Xz_r9Dwsg?+as4b|#~N;u1ujehWJ zXWoX{4IBEc#`3){@>k^Y@{B(pS7C=Q zy*FA_n%`=edaSY}`L4+|Q|3%G>HPTLdyT_4-nCWZN2;;*_w(A{8|15SZf!H9FBi{h zm*6j>(VWXpd!Kc>H1Mp;;$H(BUix&YuesHdLFHH(NB+&bOcKZ7@w7sS%=&ztQX3WJ;(Xr1=}%N`3*X|){y~ftN!tOeL!tB z$>PpH^qS+mPV-GMVeXJuBP~aAu^&^ox0TVFMOd_To+E8ZNkibwhTyh=A&?{Qh_jg9 zG=%}s0*!8qDxlvZ5eEn7gON&J{bQUoOCVrQdIL!r&Xb#qBx;(TY1wYh4|3!eh&`0v zTQDNn&v)yC-t9Gx(|Oe+YAj=X)Ol){7DplPEE&z4NhXJ&<`FrD#vs%QQLXj18`gxh z#l>vbqeuT{w(Az{X18aoE4j(6<{q)1+MLIF+s4gVW(ws@G54#7`^cSsB<4*1^wmC} z7G!?f-)AHFv#otTEBvz04uY&{dw}to@5?@Wlt0_m=d+@IKg&RyAy6Oc7Nf>c?uww? zm2eRnSJg#{JG*gm1L>PB8=)nfIAH@LlesyqM`^tIrOkjA6&zAiewSxKEHUNZyuX&M zx|UM)`aci!4t(CQwby~eE&ijS)N*;vO1lV$u+f%w4H@|kt)Tgg^(|P%(-JyYUegL1 zgkPvKTq@$#&M`LQY_H)Vz|(fMGjSO|dW(0h;8UOXHdR-Rc%~_(9IUOzYn00|-{bAJ zw|n_?;J+}@$5`Qp+qwvwNDHt7)ED&_dur9YHH~%g{8++a->PYfbrVzTor!0daIC>; zORepuHr{U1LiZTI>#Xf3`h*Y8i=nQCtxsMwinbfSuNuEwjo;Ue-(4A1MPGOVkw~aV zi{D|-n)B6aH*Rkew}aGbPjZA-&Edsf{cA5f>%K_8nJG5<%Xj>nlMWG01Rq}dj=+|e zkNImg65O2gR67m;kS0y5Q4)5GXVFUZW`j^#%|x|wA{Ke$Xk}M94p$|(D#4WxS3X=7 z;Hm&uE-VH;bUPh?DqV>`NWyzzqQh_llEW}#L+?N*^8PAdQrH~=Aw9K>>|bXQBR~SH zce)a{N*1#~KMd?!P_J$cwY#DXF09#&h;OjQ>mTgzOM?9@xY|}Y>wzq zv>L%y^|9ic0uDGQLIqghQ7L^YfrnnQ$rin%h3aBtoQ$l6@5w_zh1s)o96M<9x)Yy1 z%iFPp)9V528fdkcibO0w3A+vYy0#(Eb?V2G4?r`0Noq`H4WZH@?!e-6sa;n3P9ODJqkDKrkTUICIiC zFMJ>9#SO;C>U=k{OVN|J-x5W)iW%R_J+9_gr3Oji(&eu4%EPL?T1}B!T@-0o56j^< zA=O$-;M}p@ZW9U1h#5MWo+9%~U)DeGO_TLY5;)@)uVfF0#0_@%b>u|Htpo?$go*_> zHrvyq>dAe*Mi#@q)yCg2t92*Nv>W{x=Sy_+#(>3%;Za<%H-oR>&!?B|6DW9+*R1S9 z9@CSZq3cfTypk}SA3*$w9n95WKx`RoR74Cb} zV1)|awJ|n11Q8r>34!`ODnlxzby@@9CcBK0pZrL@A6%3?7_a0i)H^)Mz41!6mM6EX zm0q>UlkDhY5A5sz-|avk1s+fPMWaUvKZaB0SFl&^Kk5*{k4RcCzJw(8Qd3e3Zz2R0 z?_A5BIUR->>h@ z7~kB|^Ls^0*6@z6G`H)LQ!@JWgS{Dj@|aJT@>AghU0q`JpPw>Szry+MntwakdlXY_ zd9ECZN_>>0yk0VPzZ;z8^|XcwVvW{Anh*zISReWk$oAJK?5Ph(7_rgr8lIBe<<+$C z;BEFAPdN#bNI747%d5R|nb;UwO4pjtt@JBCVlhY<Z1Iuq~p^(@tJ&kO)34UFP$qZTj$FAV^^h8M31#zNE0v(B)#X|<{d50ll zv=+AQ8e-tDlR2M2)kW^za+KW}umOG2bpll#3cywB8juh*eQx%7U>2H)gveg|PIi-*0$N=_Vpmpp4v|R>g zM_%MpCX>8yH3@i?TI{z!O3%W3l&aVVIZ@9nC||TD@sw#wnFN@|dII@JDiU{Lk1n_;$w#4Ywwvo~>TqDU9La+fg4YTLEjc4cgPSNB*sWa5F6?0(#{jN; z!vBZ}I()a)qcivekJjQze}I_Q_&{W8zy}}fvOajnmL6WaZ0X_ksx3XdHrvv}>oHt6 z6qVN($q~?zW_4{*3Ffh%^9+iH)*9;BYHmC$ zUgW2Jp|lbs zZLH9cyrwR6&JLl>+>Wo7In^5WV1olRtG{YsyL>mtz;1Ar&veNl&g${>JG@P(Es~-W zMdbxA<734usUA}L-0>=}5iigyPSfxs5%09pUOvqw(!+P}cFfH72!%qbcuAe|dc-${ zMl}WLYB&&V=oQcO;O+!k2Y(}3yoggMVKO6RFW4zMh6qsF0}SwBZI*=n*o-YFwZ2Pj z`8-~IlAEdS;UAI9veVNLd{3YxSu9AnU#}zDsz;2llAM*#W8rBHuh^#{ZjHS?Dzy`J z`<#?yjX->QG^qpqCtox41fgHOk$JvZo9-r}X|oH}=2dQ5Jxs%&nMmngw+ad1rBz?; zeDQDoCG@3gR|NvhwCEdlm_t9j9M~aVTJDOrrUKiS2ci>Sj!t~(5D6hcj~m@uRryJ^ z0A@g$zp5OKSCt>aDyIB%z);RGl+Oso4+XZb*hi`cp&>fkt?t)mxz*-2e2|BgFv``n zap^V!Lg1!aa6UXiGs8ai8~^r@#qaZ7^?@CW%Ay{@b)Fw+^WBx&(vd!O=|~1}qz3?w z#9F*=BsVz{AB8$Rfx`>-Q1@FJ^&kDEH!E^Y-}A_Q^1q_>X-*v5pmG2Gzw~CMc|Em! zfXm~k&so^csdR~;J{Opco-`A(iOYWU-OTe%$z&hez5TjDJLO82F)sMbFLDzq)T#%& z)Vc=`#j73^Y+Uu==f*E{cLu&iZuNoiy%=pSa|`c+lyU=~#dbxdNunp$SrAmF`P8#1 zT6aH!oqk$kh0T!W9hH(AZqKG3IH15p*7Vg_7lR17ya;gOYD2OEY7kOhB+a$XjU6OXf6Gr7LsfAG7Sq8T)zNNPO!4S##W z$`8w#?GQ4EYWk}vX&78M>6j<>o&y?MamS(yv`SL&;%xjCCPb9tZr}eZf0*Q0G>G6O zi0h3d9USk(W&bN5&1=h`F_N{-5HmADEE9bXIAreGQF=Z=eCBLw2L6fh<`L1WGsfF3 zo#uGEP-xb%4;+pruQBjaL2sk}^OG5o8LUzFrTR_$9}XMG`J!4p`td)DBhAeEj7LnL z9%K4E^k)-_yAWBu+8eFwaYm&c^?3IlM~jDGqUFRal8{e#2;YKgZ(K5_(;k7_Y4E)x z)|zI7U_j?0R<)yJA2}S$jcz#+Je|At>IowWHO(Cval-nYFS`Hk5b zigSgq_e_Q8SCj6s09b}Majk-S)QKBVFwQ5ETQa-XbxFKp?3#BK z4ih%%iC4@X?zxnDRZg`9w~Fm??1#I7{x{7s!9PZhE?Fut1$RA0l}DgzrCCT07v%`| z#wKs^ae*x_v%yQpQt7S^LRXi;MFLk4WeC{@pI~QTryT0SN~;1gfDO6?djg$E^MpIy z9!6{ypG)RDp$CM2%mz-cHqkc_!*{$qAj9|9*#|nT#>-)i&)|Bm#q~RS1Z%_+NGMqo z;J6xIfI^*8dITYQKXZY;T}*=A1_{`!R&O@n2cM%AZ`&JUTw|l2155Ns`cqp> z_@l0#XjPB%lpelkmhfox-gs5a=w*y`nOcFj*JCCew~1YiKz!jm!y1vytqDx@Dc8gD znhpIU)>nTspno$9`UlPT!IvVbC1*3GK-dJ%No88wc?L~>dV2fB{)3jiwZ_Yi%w3ZH z^h@Tbj=H*{Rb9^ReU8N*8nSSVqt5@`eDBd3`tN+JzOy}hVKmVGH`*sHla{Z4X&2fH zEd@xM74sX?pXs-@vwfrpg=$}9D?ceSljw@37-DsMTs>T=P6!S+qHbg&foAALD3wzF z0Xs#shSj8hppFg>i7b&KjZc)nuv%)^T|7RH{dwql-rDhWO8%>&Rerm=gLh|OFyaY` zH%8)As8gC`6WG4H-*^d`@gLrG2xcQ{23`7(U(OK42Y5tEE%UCztN(r38Wim|;ffu< zl*C*rB|OI2?cZ>bKNGl^i2xhIqns5Dnp22t?MFzhQ@#iH>*8KGrW5M^{(@CJH`1=z zm1amuYP3=BdCrOmLZe^eV_uC^RjO3~oAHYDUt6bC#uKv*Tdo|5FnOL>l_fnwh1UdR zx4mF=FfGip;@M`dPp|$P^CAaWa$+d_bc^Ah&cQ;)XtO=VhXcEVNQg131yXBmW`T@g z9H&|Ty<_sbh~cPri(Wx8Hh4C3x;@Cu!;9vK-8v~LTk=0Z*ia^Gm?D;@C4Z~_*-Pe- zeW$pmT=JPC7C3e5|1{qQx2RpT#y}fiIeyvrcMN`UfhT69f#sl0yzTRn&D>d%{HgS8 zwQgNaIY%!1nV7AlY%w$0g83~HGX%3CBPHfbzXkL2e3;=ECheVSC)5EU6}$I4mU~EA zgL_CUy#Cym%f!turswA$#-dgEseTsjr^|oyb|yY1Y!)qIBTc^dZ7R}Ws;!3m43K2$ z*F3LhqoM3YYm_ac;>Fm_cLufw7qXohZCqrQ2;P(uVX|8EA8hUq9j8nZFKqsDg#1Pf zkkOKF9cPjm5=li@q~!aMtis<;kL+i)4*?tYZ{NtqPX1pV;yC#{yZ-L88AhT3?KAri zIBceqgXwX!@mY8ri7*T>xr@m`t@gqn#f=arS?0KU{K*Zi@Y<9K@}`T|xtE5$26&L-6YoCw~DPD zmx^=3p5%1csi)d4J2i*v*^gHA5C6pb7DiaBU<<7U&lktP)cyJa@si33Da}@Aw;&4^ z@Wne9T^Oyqe3ZN?pPodeHum;TF9xZKyEkza)7)*;fh-5FVemI+2QRnb;N>#$O2 z9}FC?al<}A|JhFM`AquDo9f1os)P_}oTWQ9TSDd{-cWHz=`AY~&ErXWL>RS8eNuGd zbdGhiDZhJ{eQUICg3Ep!z9~|LvDNzBXUyqY(yB_m(b*nthEuI8qao8o!T;Um9RyFZS{6rn{e5 z=I>Fi);2Lo_+$Z?SbKrV0`rjM$kTqxq;Z5gM}Z#a$&bGkOFHZaLY)OOh#qN+L8iFN z9It)c@w{(3%;RRW-Dbva`Ykkm`NRTTs}Pijqcs)sxvESLH(g1Kh5_eekz)+Th9?D? z_Yke@`?b1B-l(S{T5!KQht#pU`(53;c(d2O%ZmT_hQpSoVH2Me{N+NfP zXb7t9(cXck_AM@s29%>S#nZ&E2r?|gzSS~bLZ<m}g&#eOv#|w!>@WDR$LTR}3khI2QJH}%i<57r0_YB^#n}p4~ zNf3`ypt)2{a>Eo_HOVry@7v{I!->)qx{EZJt5uf2Q$`t)Se86#iEiwSs~u5gl9$bP z@}`PW>2aO9!#j&6$LAgs3i>2XM0;z}zw<{iqW}LD%T<|T*&5en;)s`{jKwk0Cs%$v z4tWqW%Se2tYi{6z}4C= z7gzZPo<7!CeQDLNeZt}gIF2GyIhgQ1?vtk-k&HUKcRAKPWZYAaI-*tn0{da~sHsu^ zjo=XBz{CM?ts9uX;9(_#ehw|K^OXh9Onb11C(0-KF9?i&?c1aN!uBIRXeszA1^ug+ zOl%1{@!i+W{eL!cxY^`#;U6;=YF{>AUMy;Ix5cdF3UqQtEw+9w3R?IB zF`}-cQO|Vyk+pU1QQ>V$QFNSJYj%5A-sQ9hM{BuSz2wLlK0_j$Iykc0aE`2&EJaYj zSM&u}L>u`s5ydA8fC9<$kKU|hK*$4u)s6;_zI z|LAjndHwa*v-aEHr`aPaof(x@s>h0B_8nXzl*(84FMdBUlsq$ z0&m{m*!-}iL)g2tC)o+{evS#}%ER$y`(dprPl94NY?lERF~rXoi*58yj*0CRol)x7 zHUKpvXkE)_Ig=FJ27wk}fbdX~frr9OJPa2_84nH`+QaKIu}~_SD@GJ1(2bVP|Y#(*K?ERba<#rY1s^Vf**ksQtiX1bDtX}0#^#=i~9QoY;U#=L>*LP%x% z@;+1k>GIu=-4$$2iyI)m;ReT2scJh@#>(b)*=x3$)=GX>Sj`*9ClbfvRh& zB;g`_66ZhGoJ8U!z_F&sx{`*PS2pX)WnDR~E01;Mwyxf>nOE;wS3Sm6v}S3%rh=c< zOcX!0;-^adG>V@(@pG;CX%;^>i=R2-=Qi&8;nl|Gu z$#?6GyT9?>!^YiCzI)8Li}BrNXM>U%xzK#3! z>HFEZe>i$u$hi{6wtb<+L|VJ6-Di?o@v zU;ocngnmDiMN24a7JQ)uhrkL!)L))C9&5HNb?%K(}d&zp@mStufqz*n%Y7nIxCX zNDyk>)^^)2-FA1~pD0uTtz@EQ0=k%h%bTvE^<~DP8bBdI%>1A4bMDJbK&iXGzkbM^ zd+#~Vd3(-tp7WgNB?HQBdd3<9iX#Kc*Y%H!4JeKbD76_-M(G)A4JghGD2aa(AD0+V zoEcDp8BliW8G{BCR|b^d>K~g7D6R}B^%+p^(=*l^P}~_%8ugE|0mYpGWqt;fZ|WK6 z8&EtMP$udhTMQ^36H2_@B*E=R4UDQTh5BqcN3N8|0zv=-c3r%hiI(zgKFZ5io|Nus zhbaX8J^(Z}ta^OA*{(<07*k(LjpDn`czdBi^sAZVMcV@w#k1vPP`vs71nVb3@kWah zg5v4!{0&cug5rs2E4m}Zcy%FnKq%+XA~7jnt4aCnS#&Q$7wG))u#!84Ug7Puzq{_@ zD1f1&bjX_y6{bT4=}^8nRVOaOz&u}aZoI7X#JBk=V2;@a_i#iGLgNHsSXpF~O&u@w zU}PV=6_fv}tjxE`?-Y!K8;{I$y)7d`ewy7h3u>HZ`TAFw_{f!e4*RaZdk}7-zUzql5Y^ zSGk527S#qfoJ~uC-spyhInft=x`q>j*dVqX0tk+$q6TR~5btOsy{TaxKg@=QXCt3y zqu_r#8wfV_*%RXNCL;fsIU%Xyc%=i#%ov@TLQlY4;T7)-Su=H>^S(Y`POOAW8K;XF z7+2enZ#lM;+8qF6;zuj%wG#^MO7~yMG~O z39dfqD1lOPQDz5|GwmEy#H>1bEgR)vF5%Fi$wHA&eu?A7r=!SlM6_>iUF za`z6gHYW;VdHtBs4VXYd8K?0qP8GBG4R!~KiL47IM*Z9npI%KH!9*&@l+s-~GwS|VZv-H@IJ&xO64iLO$qptViNb^=b z(sCsj= zSo~}hKbyqQR`K(^_<33Uyd{1<6hClsO+Oy-;}t)p;wK<}>c!7O@gs|$u=v?1em04p zt>Wi-@$<6yc}x6!D1ICcQJ?tnil0(PCX-_rIDPLt@~;cyqY2@EhL2A@nT?O{WaDG_ zsq^FGErfQrv|N{okHZ^ve3Zhfja|*(?j#DXqh;kr)@B6OWTEA~gp^;^k@6WUPXOaE(Q|}&u{b1 zrEt!Keo8z>=6AGDp+Cm*nBUg@r9TQ@b`1UB3J>?1qmwCHroO8Qud?90_Ko`Y8i%r- zHv`$NwL#>ht%sc|iuk&H`*g5b@SL9o&jxeZ&;IVdz<19DzUTjK_L`@+2!3IXL#uKj zXuDhk+2buGrV>_#H{D0`?!(qDPT!>u371LMn`!h0w??yE#dhV}j*$fIQ|~+O+oJ1J z8Gw>MWk6QE%n{A4*&M0x0!o*TfTAntKteC{%M9m zmo|O}F!@tR8t?^8qO}h}2TTOc&qx@Jz-n$POI-X@eaF@$ zDZB+a>}Y}oR0=<4GdK)}U>9%e5xMGbJW7GbJXOyvwh6Ze6Q z7Nnz-jC`+}sbhLdkOgPlj-ktRhouEeeW%Jd@HslE1)WgUz)elMsRThug=2hW&@R7- zIN6TmRnT+25PhBZI8QhqtF_UZO&QEvHYHUr?t6|W{P|4d=Ifu9muq2VtL~wNKHq9% zn)OEN%gAr2d>)V1d!32*Cv(v;3h|{j`Pr1mmrl8<%tN`*5NGvM^`#6GlPvuLIEpa+ zv2WR&Yege13ho(^B*wpr@;vj z;1cx&d=e2KJ(WXEKI!uNd!_I+A(u6xw1sD5|9^5keTv|da>g!2zJq%>nH>@paT6;+ z+waPc)_N<{y>&qKMAWR$m7{k=_!oZh?&w4`FD% zv3k*M>b?}2OLLoqaA>A6>q;8B@deWA3HXH7c0(EqJHl3C09fVN)%qb#U7Av2j%vMS z+`_GE%@!UKlV8GxLp6G5cC}*m)8a_OR zZw$8$4Kk@&YXJ!DJf}b%3S5QjXe?t`n52V7WQDAZMIsWZ%ZQW>bc-fcSu$d-s{+JEF`MwoO0Nvh}| z3UA5qS6%OIO#9|yXuqvxn14-~z*?1V2&V(y`S6&GWsg4OY1)8Uc)nh^Kr`oMUykl> zoH8ypGuG=FPp&aD{;P0D=ke`ZLvTBLXsqfH+%F6VcN-i7p`ux=hIYqu(MiHJ!HwDD>i4}vm?GLZHhgVAY$C{b^f zIO4EMxVXgGtP);P;tH$8A2Ld~xr8m9S)xdk7*Nd;%Q8xMxP&9CM5!q8tW_eAQGzYF z6lYe6siMSMtHecmiAoe$w?43b}|IMas0%(N5v(#xalA<3@{O z{2L0<_o?FhU2e{xSQ%73U{P+sn@|4=>7SSWmC(N;`ZqNi&TFOF1+zp`TO33C1YNq+ z00JtkThiT!$eg3azRzn(#76EyM4EA3W%%1!N`J@n)6vD^GQ{eKBDfUkfzu}Dyb0bP z(Yl%fD2M->?w7ZzWE4;?xq-Jm4rz_BEkGYBjLU$;&5_|WW9RsIo5@uKyuo-Is4Nzz zx_%RIwGDoXM9@#_wFvvU{!u$`+@1W(JPT^~)35L$v-}!pmshC5JaeeSJOp71U=&@z zL+xrv+|Xf~9ubW(xgFtQkY92zl(n1DSzkA>myLdSQ>ON^!^nVl363A|9Yx0v^~!dA$2lS@z{Eg}M3Y!~CfQ=_(R7URWgh=f(!FyJ=bFhKJFv&Vo0Xj;CJ&eya8BVFh_#nB(Z^Sgwl zPa$nciy1XHWY9AL$|`3Ii1c-$PNc68l+jmD@yH6iR-*ai6r3h5ylm93%(_@bJ3f9W7 zM!jqt<+@rAnXQ#*?KS#^Ki_MMSk>b zQe?_lYXA4gin0PQ&bjty-uV9R19@DEk%`yEIB0-!`dIqV3OK`pZbyR+^ z__U+{lRGs#%0#UmWdfgSG-Z>K4v0__oUSzDOo*ryn~ijV5n)0^wc2K+ z3r$s9qhSaZVfH)RX148j)JbBr8ad>Iu0q@yxKZy>wD!g^qHvH4z7R1BE*YH-z1D<& zr3HPa4t-7SjT620);ETou}(^6ma8$#z29nwz=>;!wykm7cDKHf)B5Ho&OM!O zqbQ93Yfx&w)uh9tvYS+Cg5F?()`Mg=QYR;Ug-;k^I4;q()6cBZm*9>0!WW_xUOtN3 z0@E@thmqJdVq6O$Z$vG>44bvg7KH$$#CK|^YebO(vt>i8%rckg(b^lq=yV4BXEXa+ zgv?8<3jRtI7aE#<4<0XYX zS8int*Jq#b!F3DHs`h?Xw?@1U2DU{pf&CnzKEKbNuUqxyTT9Egqz*J;iq*SI9r^+z zLSwAR@Hs2;z5A^m=Cbl^BSOh7G{O=7`2GwMDc=q{W)p^dPUiF*_`vBkn-~7QU@x1n zOC}H6EJBxj$DTp$4re@MZiw_w_@D)wYGhCk8mq%A8@pG`A|-Q0mGTY0X}8;?)$a>1 ztfP^8F}TEW|^sFy}wMnC#Ily zwDLWNE%i^LKeCH^(R812n4{$>m$GB?7Wi3>><&$+rY+!d>xKLQTd~|=6`>5xuWP&t zb>{I6h}qr)!(ebcay9K#P?XZvicP@fC)g9Km3RSxFV1``zsD84+9E0t5Jbl2gPOr5 zS?BV|Qq;y~G@?&pW*%wLXGZUpc-wBiH4!QDO_Z<5L=t$7aK!_=gcbF!=xlpAQ4UGz z{+MI&v_u_y;(-%FCoFJ+%Mgvh)+nuhSOi95bQB`W9E(6gMyABi5`wg_bk4DhTJ|8U zBXAm&R{t};52l4xWhJ-xt>t1IAbSezWv%LmY(i=otzZVK^jX~9J<^hKAQ!LG^0N-i z{=F*+KgS!*mhU9Ya0u{H=y0A;oz10Jo*fWPGH)?8j~3?Ys)RA`bT`V3SMHe$wi`DkKo^KkmS z_6Tjqer@C7@fedn@KDAT4rV><#YqvND&wpqKqx??iau!@f>`*jHR|42(kVT;4NdgD zBt7NYfvCby9q{!VT-3jt6w9MkI@WOUP9kdr35C>`=;1y>bEsz61gqJi-%@OrO{Dnq zc!A~7CI|Cj7&7=Rgw2V3J&I#+Is@Jxv#^r~dj$iz+XB)$UgzS(EV)>)cn&t{=n&E+ z5C~{Qdj}%}cfu(yDs|oN94UM?!_l@O{;JkF9}LeK1P$_UgQjh>%innv^(lAc@_0|x zYAPbT)z{?$B}S{xrG8wOShQ3O(r80-d$iWcn%leOujpB3SXqSr_UH`#?a^9ICFRY4 z=&`a_8W7KBLp?L3k`^-UN=Fk$%fcuWv?+H zIL zsYHE14B7~3X&b!>{wt-9>Txy^RnZZ_RTV@NJArTrJBJ*CehS^3qQurFbD4c%oOuW^ zP6R@oyOOtVrQ6Nn|T;cTy91 z6K*6zb6A_CuFcsvil`ErElrR44@=6x7@Ms)z_;3Rc=vsNWru!FS|P4I)RXCE+USx$ zz~OX~0WcnBKsGVHRInuu1KKdQ0>n@FvXCVdX!7ccI|oIH>t$VQ3Et2eIZR(cG|U|c zrkl%XG)fZBEj2swtufHE=0g;5x86cRgcc43_eUYIa}y`U)RbQR79zsk)_p$sK-Kd= zRe2{eG!G=(M41B77HU_j9ww8AJX>tF^xq z(##gs@$5{|IF0M}ztr3ldn1RVS`kQeNQ(Rb2g&y#WgL>0=Nls){*Yd$S3`RwnFePx zlrMGsnG*d;Zu$UUwY`xS4^KnOSq~<#x={^Jdl$T6zEi&c=?MAc+KLX zy)ZquFxfha{T24{5Qn=UhubLTRb;M9PXoNP+*y%myo>7=SrHvWS?HZ=m%?nr%ZRC)1w`<=^jpqPl!DBj5+A8@ugtCiP+!C$du|nN= zX{!TsektZ$yGS{cv-BqRLVd3zy5iXt;I(|OKpAJ_bL#7?kV5bg(zuY0VvQL0VB+OM zn_)TsvO|y`DSU0N(J%waqiZL0ii@wJXz8CaNLoXkiDE-PG&ow578DNwb8_XbiiUZ0 zX}PO0@z#$lwwI?jatL96zCf5!saIA?E2`6B4vjgUwV8xy?T;+lFY-d_)_I$VEy!S^ zTNw<90zq7BLZqppPhFxr#zZ4lblPW4^;8S~Gr8xV>OY@LCMMo#mTJ$58V(U63_xxm{oLCE~{gsbJTt0$O`aeXFqAUa{8;Kw#!NitJO$6DJV<5;Ec}vl` z4l&qkCt&GdM5CTe1fjJxb*_aZFaNzU|0SAJ`coY4!|i?cUS+UQVk2nf3_+DTig`P5 zOC79z!N>&Ij8KS{SQ_0p4O0k?0y;)O@7(&$6~rV^t)98`T#;^eATaV&!o1Cm>EKl5 z`9c%#LJO0K5S+2_WM`W77*pTS4>-B0DOsyCG|`x?CW8nEKZ9&t5AeMCt%qFUYD`w< zaCHd@aK6@McJ2)KgoY}&mV1I>t4QA~dNEh@qA05uze?_h%;W#b_;@oROOZ;*UP1)D z{{!V+c(-2|t%F>7VQ0War&QVdWA%6}2{Dtbg*E3yA((894Q>OAvHvJX#u}rxp=rbu zz9Z2>l(mgpYLN4YI+%VlQ#`}Y1aUlH>lLxP{$Z?T6a#+#bu5ho#`>Zy$!h7Ff+zC| z+mnw?Ao9-SRbv@ZT>`v%()#w#$#L|pH8#AhGUsn=t|@^ZO?5PtvEIpl-D!wxRs`!B z5)=R4T)G>_@EM|ol?AX?r0^|#*Kc5x2dw7De;Y1cDoWy5gJF0~48tP63LUMjD@hxd z$xHOh6Cz2b3$0XUxgo!JL5#mP3nJ-RgqXxAqUwddV*59v|;PIe6t{ztUd63m-A^1}t z7~oFTI(0=7n6Ev6veAYL#@YPsXyBnT2&DYI%f?1)H_CoG zNH)(<4=V2t`gSjpe)Jp)(MUB9mR6HBn|h{zdjnh+O;k8cjH>zttc_4 z|E16Y{~38=)b&elL*Us8d#@UJre&u8Oz1e8So|=C!2a-~7>KUTOtod27kCc97ef9P zOgpZ%>Kf9)eErhaM#GxiH~L)6+i6;xF(u+Lz?^j3K7(FSF5f9#-YbPe*zvlcg{XD` zHIm0|)_CGY=X|>@d1S=PD;g;0pGUm3t)!QmN4$hzpX4t_=3GuN+ik`MoW(jWJx0r> z@fZuZ%>wSnb8M;kSs>o0H`SSMDlemruQc;b>x~E(lKH0lyY$ALmFH>J@*m{ef+rij zKT(gw-h&q;`BaZHG(8d6IIzg)v^t{_DZI|&(=sG7!S9*i_X>Vm z*3gik*#2uBEdY=gnrU+AxP2Eu7=UB}h>9EY1ta(ez>K}&9D|D{)=bAP!~{DdR^y0f zZU3$b^*ZYwJ`<`k>rSG?JO>J3Ptdvf^_&7(PEmn>{Nh{|H`Xl1rG(aD& zQEc3)J3g(SS6MCko&Cc7REEDGkAilhs`Jhe)OXg41A9hC`x;HKZ=Xu1*HA}0iG)Mj zO$d)@|63AF42f*lL+EsEXi>b~u;5XiWt<}LQ$r=%1B-Q4gLu1v3mR{0fDg@(({HE` zF>bUY=c(st4b=(dg?!?}s&kADFbSg&W4nrcC&xOyEGxOoo~-1rVs+eUc*eL3V#Bsw z-tl7Je3$l-m=ep2C3ErkHiB0Lye@i+FfIq#rmWP95J+fz;`9RaunNaDxR5-H(Zt+Z?8b(V(&@x~^MwN+lgWAOG!xPh zOwQw1S3IFsn1YV?lYi2)ndKfm&3CT(T2%!ruGLjCM^d0wY|&g#sJ+Tjd(_bqt#J0I z)ru{}z5Ro#;|Y-Cd>!V2)%*V>tIwKL(mH+%Apvpc@2oxmrcL-;t(f6bh9f9by)y}7_i5W;FWI+uhuau01XkINve)l%@>V=c(^ryyyDF2D> z%R+N1LwU=*sT)SvKOIlpvL_8wMX#P``4lmBYqdXMBRZUZgYx|DKanT&YDTca&#?dd zv1N~zntV=uhj(**w;A?m)3vbDJJGa9yIxfFM(V42{`=nG7k#NI=h&ys{tJKlV^*A_ z3&%eY?enEmF2JA6@a0l&PxmlXOuj}41eb>aS8iKUf&>GD~wDYwIvzPVg* zsBAryVKd1jnN~^NT=if&=oW{=%h^!TU}$|*aXD2S3Rw--CTTg!pj{nW{`b@xnvB2* z`#2g1+axg%iNfAA+&$BPf02D-;=hFUg8ot-qfG#?yk#$FRTO#PUM?1{)JZ3~QTsHR5k7j7Z@_iC%$^2A75 zE{vR#ziL0(pPGTgMiTLp>0HsMJqQJaNIGUa{nSTxXfmgc2KJ((KY)peWFeJt|I{eP#m3}`hU zs(Zgl-B-_ilgf`dA;0Ng37_(l_cR~!Q)6lP0+fDHDYMCO0tNTr^R=46Tqx1hddsxR zvlk0*l9j1q-)`S2j#5Q)J71@$&{ZkZ^eptgUVmSKJHuLUO=?V+I;eDeZjonb^9K-g z?L)Qan-FThM(y&9IUpbPf0tX-v-E(!QEyRC^B(0UoBU^O4!1;`clP3XZ+?nJp}MrV z7DrrCwVgV`g+xV-(lY? zV`9?A=j!%3``|3fmq6^it#Bc?t_iqA#?H_7m!$^w@LuK4_y*5{-IJdW;%#8do|;)Zy6sPL!HzKcEbymDg?3beWbN zjh-}}#zmSQ;JDiL(sW20h}zJ3IhZ(E$j)P-$aQrsFSLB+6`MUaVL#7rkJ6Kd^j{rT z4y64t_0Z%&srIB)+mFMW|BQ;*H~Eu$rP||C?LlD#uZv0>Ao7?yFCBF1tjjo@nlo(V zX)Q}^BmbJ?Z?KUEBLyZob-Urvf(U1h6n+7P1uFz67=}eU>`fBspp{n&-vdS`2cxHy z(HUp~-vK$S(?Eq3Uc)LYsDE51%Wfiz#N;(mcX1f<_zwAo$Lx~AErM$*iF8LDw(U4P zg3Lm?EsH~$|24ID@}PP~Qt~0w`k~|eNKh@9^r9?8I9>d@x_9ycbwJuQXiPFL_lao( zA{6gXy zH^8;{hnM~jr=JS=_t5kcA;7!Sc=wsp@5=p@>3==vb4>rSZ)H#ai#eY@{kA!o)8CYn zHT`$wWKKUFiF2~2UM|*H+N5$A+L=si(SWxJ#%1Q9Mc%fHQ4*?)bLM6a z=izHQ2*G(h`Tz*}V4z$YIYf-X-Sa!6uDQ`h;rlczso z#a(ameI)Y4H|{<7zB82T?~u|xJzXiZKK0M3oA^5CcEr;~g7DaYjV!4`_VJ?oK*;)} zm*e%3&7?}2Dn4;-HzQAFS(#zVYtAxwDgEtzNNl)HuFO7sy2 z#MCv)jW)T6vMbxgF>s8s9c%TAOE0Ek4e5|`Ub@bK5gyD5c~Fec>=~X!)Z@>JW1ubc z9vp^j0;#F-(BbqI)ZIjN_Y1Y!HL2a79lvst-u}GpIn1NVH*pYoNBZ8<;9YjaZ+o&< zsQK?w^MorJMy=Ask7z^TLZYTT-|omMIQcZy;JeQCXY;R1EPpnox=T?g#)Mgo7LQ?3NwxI~(4&&jasr)!|JXzYQ*US_%!9r(MR)NZ7qODL?Hsc}9fe#%KI%Id~QsTwf#<%o@G{L6FWLP3g zDG#?pJcjc0vvuNhH39q7_y>1q^cPj#d7JK5@25QQhLiDg=DSjT$$;^dyE9aIrwVT@ z@CLzR7x?-d*q?whNbvzWF5Nr;J8ifX)s)gSokea|%F?>kVUea(h*y=yE3Yy%dK<8v zc($1_*0v`Ml4t9(Jj8gC!ao9qVyEo+bP7`fMqzk;@ens*w;ZeZPNkM*oJVIk;*Ktz z`DR&5WS>xK3xJ{yfekB;qc5}EQP<(lJ}Q3!Qhx}~^) zF*MV-yj{xWXTfob4j{8L%ux3u7CcmHzRC< zuNz(&G=~`Gri||!@jVYCSMD(U_rFzOeV6flNS(=+Bwuo{fBsspJJEO>eC`)qB1ZjU zK)HUy4Wd&N(Q_z{wl>N4>oyvH1t~*Zzl6O<8>A7!-7A$? zCr`5RJLfn6d_aT0>s?rXm!I)&BfX1u)Pw!(*u?1;3F$v@`VlwMk8-(TrDz<_K*whO z7MzH0-JE_NC-08HWJ*8PhxAi5NE<>gkGigwpA(aG{&iiDpFb4O1?swbe#T`Tj^OIL z`TXn>&t7$1BR}Wo>&K^c3;5Y9o~Nqo7V>k6crH=bE#~J6@m#8|Tf)yZ;<-#+*Tm2D z;<-XyC-d_H@m#5{YvJc5;yIwMTfxsQ;<-j$*UHaf@m#B}3-fcAcn+%TI{En#@m#O2 zTg%UX5YO|~bzPH%$K0P(3#a-^tE~_NKdiPw417nV3y_{8(uGLR5NR*c*NJoy(pQW0 zRHQExX^v%gu}JfdnkUli4DaKcInA5=2O?dG^j}0efb>C;u0i?*k*-C0r$`5p-XhZV zNdI1>=Og`#n-K|ONrC8Xl%Cq+Ed|11?y8$Pc(z-!3$+ZjH#Lpkr>?~1(B4F_N`zvV zguFAvL!!KjVRLkqZ&YOlel`7>k6{1ue_+O6;IQ>@Gl}KHH6s2)wH}NiTwn!b2vqXR zQH>+H26pSuoAB(io;Tt--+B(?*=s$^ zcrLM?7vj0XdalQFjrAPBbG`LkisuE^vlq`xtY;6NTdZdXp2ODjhcoE8%X)qb&yQHo zFXQ{%4uvAj9+1Q_$E)` z8t0gx!u&z6GCYvab;>c1}im%XrEWIqvmFE=+hU#o0X`fN&%gZ}bq26eU7U!q@_wN;8#fz}qd zM86Je3yM@x`f>1B@MkhN9df4Y>HMa9WU>n_?T}NricJ2q(5A^}$EqMpi4Q6>7Kz1< zR%WuJm7aK|U`HzjJ6b8&(MrLNRtk2sQm~`K7Ew2H)UEz>b3$`f*JdnkzGyT#(pHlr zZ8bU4R+A%bH968&lOt_4Inq{>BW*P~(pHlrZ8bU4)?SkgC}rSDD+Nzl$vo+HohOZ< z<3(mam?y=g(5fCSwsQ8ayRlo7=;U7`MefbDw0sSWLxHwfqoAPa&8QeYV()U-%}sZq zxvUZ*tk?O9KW^iC5F!wGNJuGs6c7eVH}^AAsNI6deHn+Y03Es*?5L?!NsuMfX-G#4 zn2stfSVsTn3`d@B<;@?iPUu z(2YD7AZZz>nf^LNnZAIUPbfWS5wV$g+}IoFLWy!z8q@0-=nQzTWrM%o zSR$Vuu0z62iL%ZmUVmq;_j;iQG21a>!H5MAoZFCIzjcZ($)Y_6o8iCWrs7c%6+rmd zx-nxOM%6WB&O_uU!$O)Vnpa@de=XI2T_>(L!ME!#{q*vBdRhLrwn&QHl{VUu(T35~ zrr9Ifaq<%}V}1IeF-6ZHP~kW6VZ2tiU|iioDf}{CV-o$>>l-JvL<=s^Di?lQGk8$e ze*z5%kcG(lPjvplDQe?dR(!&9DPr>IG8`@FV0(+wv0D9DhqPCfz1K^72#v1A7kR9c zUc319bO6Se8)*edPX(OrMX_!tG`y>!vQNygXcqVWqG-T7J4o%z=>11$S?S1KmDMn6 zj|b=Ja;LQV9w_u5plpeC-yBY#hhNHOkB8>5k94Ztw+}K(E5r}vT2Q2lrZ6S9mkEoQ*qEcE-fihIsT%f<*DX4~Co&3|} zo-aTn;Vi#bhCEV76YJHx(oKa4SGlp`zs$GB1k6kH`Gr!)Cp1hu$I_F(Us??}vs!Q} zZOs#vo{x8q;Y?$t4#fRQYN(>6KuJr>FY5n5N$0ZDXldp_r6(u#BPHz)&ECN+8-mQL zxslzOw+*!st!bXKV+=o3(YQBH-!WEvf$G^cJI3*Yoia2R(eFhz+YU@pDxZIJ0OLjW z9TJ*!#HI$PvMSI0EP^krOZ-(3$ejR&wRq*Q;Q&}4&sY7XKyj@34HFa_jKwZhh8$AI z39PbUB|QFhyhG`>mO>~TFE40o@!BrJV8gv3ji^iN*aZ!>T*@uXmDh~nJCptI`p-zp z80w@ySRpAAZr5spTCg5W%0+^0al<>|#W{TAfg`7DJ8f3(nf^0!q4_KiDE{0~N{P8x zRe6;|UB^U*O6uOUcvI(H$8blN5eZr#ACUy%9Id|dEcAs&OC9h@rG=GJUC{`wVOPsi z^;kyOd(gt4vN^bQu4{OY!O21_6g_#5~#Tl zpCmrIhELXoI&IyHylc*~B{;MeywT|{_83TvD!(qeWE%{t)V;o;0L^E1D^r2~t%K9ZTIF*DDvGryQ8 z8H|35Bi@lPAar<4xv6oKiFf3i?-pkkbZ#Ria?$BK3bk9ju{Ydz+3My76Woz{;^8u}I)1 zM~+JT*V(k%xsg6=S}mL-bUw`KAg3QeS`ruloei}MEVOpJQ)L!JyWORBZRLbp?b^l( zkJ{DE3CfJETdVW>-IBt`{yy|4I(-yQCp_=>!x#dV3I$gkn45tWS-|4cOkhP909GV`g}a64zMa7K?eJNV zl9aeJ3>rwM+fuuZI<_jkD@%j=*wvPujfTrA-eNk)^%o{)ngoZMxy>Bp%B(>yOcZ8h zORe9DrC}T>Jgj_i-Wuj6621)ZU-?wvnJ5{0LEQ3< z?987&qRyNk#^?!q5)FvAZ8a!Pn>g8pCMR0Is*9V)sBOk^?^kSu?~H0KubfRsH!Q~A zr#lZ5iGY8yrxS-bg}X}6ygK+%EV@hZ<`5}V1`|uZie{EzXr#zI0K@QX>@h5uUNjEY zZAZ=2t7fX#AeC*;o2foC^`e0Vr7vIE~0q{QXhm-s(d>BElqH-5<5FfsQCia}kLb;!&b zwM{h$a$AX+Dy7sFsJGIqwv}BX&h1(bO)kHwxI|a!s?DDXG9P|AA-OASPDm42M#O*?m_n3BGqu=EEi|i9TIk3zX&dCan8IA)NOalPGF%?; z2^9k+#0rU9zF`j6U+v~_ee+5&Ql67EQXElXjdL3a+y0}c`*a6DEV$BgXje8{Qm?0U zNAO;g@Ugxs`%-E$wvbzV`*2I-?^R>KIKC+kBEl7)M&0ZRP)unsvFYn(BWtWiKJXRM z$a_xk(LR5AR$VyU`S&zG%)lmSYqsfPzpF%}JWBUsAkGtfjOM5y{o)X9L6IW515l44 zyfK&TSgJFnS18nfMlR~aamrC>6*4=?RiK_PAxQiKUX0UFOUHmHEbb;vpIFyyzIsx=7n_K7)4Qu}_J=eN~MSe;YX! zzg-*vIBcX8h608*%dIsy)YXtbscW8R{)aClV)eeXzc;GPKZ;PBarJm~%fp;J9bbLO zAX}?nHd7{1TWu1x)o&Sh+BBL^Km7XHw2&)!?y@zgdxP^5+doJPYp)QbL(3c*j>ffG zWsSX8*++~7Oa%l_IP*in6SgO&K%$r$7q{cUtt&JMalxm>pLA*yME9?^hrTN!W;PPj zrrqmM+qv5hq1*9xvsdkAuiDLCwVS$OjTtUEpv51F6ML8cTdncsxI;6D~&xE@$7_x3Qz5G`h4E*)aGVQsc*M` zz?jLHF^|Xp7xPFpTT@9BIq+AWNHtDVS*Z)jX?#C@K9`@!oX@l|pCgQnE*$^!W<9>` zv*!41Fz}l-6QkO9MOf7Ly~dzP@?sh-d0c9V##(JkcRdDeUe<_x{;@%{+-z(}eL-|; zMEJY&=vOXK4;noR1v2#2@|kqb*L=$TE@34^#78dIs)#-0`^IjE)=;4Ir0}?0U7xg?4HS)IZX_*__U%(&O5vu8N~P?`ZZkOj*9 zZkt-*RZk;6w0yH6z))6sZ1Q!=(|n4PzfL6k=^`YdTx?Rl9W~8H@|MTl)iLVz@f<;ZHx7%W_k_(z~Mdt&7sMf!?%xF{jPEK51fTR1G_)A zbW|0M%=_@sE%@6ARNq%#O3z^EAdUw9K2#`Q zUECM-JS58Rzh3Ea)Px386Lozs%8(lC+f9{<=a~imm^8Cjlf8~R57gkyx%T3O_<5ds zSlp`ywoI+2v3Ha&&zDvs9F{er;bCm$%e}tt$SHl0{)$1m4Ys-F7-iYZt?)X=)vwdX z?6?@S_r#d}K4Z-OMIW=w@sh%jWzv`p^O((5Pb=?Y%;1>Uq4c<=dEGQtF{ntI_0gE! zih;X`2CbL=!KVaXthz|)DOBQvq1Sle4)DOin!;0j0N}*AYPA@@*`Yz&JtoFSvwMw0@&P2>r7xS6dcvQww|q%_!hzu z?Scjt^em!XSiGvo8|`{ayz)dhyZDIgQeV<7-U=E-{a%kA?xHZ=@cM_Y;C-M#?0j|+$59;4VHD##_4Fna zkKy!<2KLTpHbb(Adyd2Yx=>s72xfR5W+`#g*GwN_7v&;Yhd2RJ_O|ChdZ0J* zf0G>Ju?zU4Z61KuTg61}VGND^i2b$PhcOexnw*gyj7c*N`VY_+<6tduX+}(%e!#z< zFMy;OgV0tbTA;hK$`=ixzE%Vir!F@*^LiznD|K8Zjx=s9ygdjZdvE%vE>XF&)96=p ztrOkGG~U_SYrQ;Xs5LZA)oMzTFWHO}m*DD?Md*&hYYut`40zf>MnAKLg!OXj7tI<{ zO=hWcGki+BYDx&rw5DLH(JcFxmF=yIKC{MJttLptQ-yk2+(I)8qwko$Q@Z^(5CM*d zhO9{^EOj*`ZoS%^^e@>(KB3e+A}gHRxe^6dZdM)1Q-_om4|Jxg99kz(yUMq(yb}^! zX*ye#sa<%>Du{cb1Kn11iDdyM1QL@9&BH5)&NObT%j$Fi)o3Gw9HNiXQ?P8?P?9!7 zJ&0Ugml?U{(7_`J1+VBtmVeD;r9eZBoNfgpqm9>Y@!C6aAXmEhfWA$?hsbB|;`6Cb zL>d!cod|8U4DV+8=g=D?7}|{Z)wCTPGwnU}^PLkBvhAU9#Kx*s4&meM)8bp7li&F{ z^SeH0{`}9GzuDyN~vv}s?fsrXONm+nQ@@&`i%KTUI=xD`EGx5znzUK2$Zl<=TM7(ml|k5vun^PkF|^q!!=k30c-$ZS+M#%7xBjg(hp!}~`Ao;F4q z$_-@${Hxmls40yQ$2&U3V}`sy$g|wAM7r5YCk#nzf`GdnR|Y4f2|3#Bu!<03J3G$%LwEUqury-^oJy+RWp*R?|&k_vF9tqUezcMYdG z;yir+!cA8ZQA>EX+z$A51_fV2`{eI)g%w<(?^H(rK+PPRnbQTceTzd|kAB47%*m~P zoKcx19`l|gWs6IPX_WijNvzptbRXlNZ#TK<=-y8iF{0Op35Gj%i?+nxyDLllElN{zrZ69VZT` z`@6Fo@wuQwyF{Z;1s#=2kMow$yQw@LFZDH*(N;Kq;d@K!#lxu1e?ofD;nj@`V9Wcl z)B&*{ETE&M!oO?KYd@iSp!!I^nD3yI6YvdDkjuf09MOU{U$==*_0OGEJ?)z7Ik+cR zT^-Si3B`L@DZ$gGQ0|=mwC3`v6>T{0M{Di&@>%X^&@Md~Tk2-S3*_0$p{w1uY)hvL zi_mG`k40`jpq}7EaLCQ}bfOO*FI%Y|Fm?A($!^TlET-ZBA`bS z4rFlGk~R+Okg)K?-@=+aQW(yib$FQlHlBTqlCyZPe}GOx+Jjrgyn7<2AcU9ij=UoO zK<$+tdk(d=#TYFR@;f882+ud{v}t^gz-jfi_(5Dy=?;zBvSubN;@d*+L(9ooNj2%Pm)5es%{~6ZXxOr6 zQ?;4>n_g*TyT-p~+40mjvb*1Cb?YLGQS4FAMbmc*LQ~mwm@Xppa8Nt|QPz z?=U&KlgN?7CM?@P^yN!v+^B~TQUjh(D`;0Qr5CpnJ#u;DZRY+Kf_oQ7D-FC&p2DOm z69*#fI{UXGexOI!p!AsDGtN1mD8~wz9(}(pp7&MkzXe*zqkY$HKe<1}Z1eu3aB(92 z>4nq%O6+p&_Clq{!M9I`iU&@=#y!oK6huYzy`siUGka=Y>e`I)I^x@nJ&anex(>wy zhd9>^>Y05Aa>a7?RwF41NE(OzCvk1)@-FRF&q$Bah!FbZ7ZV8OjH7uWgt@q9I2(06 zta-e}M{qM>|5$nR>>}v{onoAn?isU4D!X*|B563L#N0~H*-&bc)YLm$IH7Key^SyM zN6Hrku)`yI#IZ@C{{qsem3poDt$0{HbNYx>d(hrL!~a_7111{qsp3o`aFTD|BI%xv zvTOIhv_s8($X=$bn@rC##J~G@~FF%cZLZCqOSGD2h{=l3FX~k8UtFp+GN_= z7fC-l5F5UXeqLK7{h$5x`%3I%JpP3qUtJ_EIYN!5*UfLz%cgxFEs|cQHy_ZyR}NA7 z1tsQG;=`dW^s%4D?d5(NF8bHB2mZic@QE=CeNekgKfaCL!&>6C z9Nk=xpxWE;wzv&tEF)!>bf=D=uYH9^`+j&OPK+KjZkjfi*hSiWr0`#C;(7zlN}`TG z>a42A*9~%DjnD0F&9hqD%DQ&KYec?q&85Z@>CvVl_HU{9Oz?wD&;~_|c(-nIcp7!U>4JK?3m|sKXXV@-Jjp3W7n`u$Wg)Snt%{P?zlEc|;y zQz{8RU7>e<`wU|oW7kZLR(sgRFtM)H1={R!H(t6fzb{i^9 zpMG9~_bRUyleErDSYeqoFNQ#!t*4{4?1c~l@kZS}4-t{V#QGfg2hv7MVK@L2I!K80 z3a5$Kk2-;$a2Kd{0!Ni?tQjcZXG$l)0wn(34k)32$TZgG55IMeu;Bg;UW|v7jIebw z{IuCQ5)(`S7Yo~qIJ`%fiZnj_`hs?he1phctJRR(Qd&uK2__2T8Q@Wt5bA`5slt5`(Y|p0iBl^?n3L8 zeXt}9YF$tQEhi3NQgGmlx*jC-&z<8qO$WB=siG|YgIzap0VT%A+i1XTpAH9Dv-qgu zhl_=iv^;~8ht=1b%i!E)$_j5q^DcJiVCQ?3D)7|{DAU5L(U&Uc6!@0B*QLJ3-W{sk zsfTGDPSsZPJ;xe-_&j_Thf4|J>a3J`FSw5gSVQ{YGgI_9$hGn^(2IyK zl(sjhSF}Q5hxRU*rgB>Agp!Wdg+5Nl4S&Dd#c#4&`s%0=Eq#SvFt!MDgD}hj*du9! zgU0;{Xl(kAOVf|5oYcPM(4Gj0cQff7k_KKQpe@(oJo^bk0@W-SSF=!xzF-RpSA>^G zb)y&hj|S{dE;aS8!d_hHbJSlpI3{Mhz%9IgX>M?H0j9DQkXdc?ZWWtx%`%s!Ra)^h zZ+9!(*bEyiuuUGz@_uD7clm5>R=zeSZs)_{0oaVt>})_Z3hA+3xjEW~g)n@l-^Ki^ zp2%(Eco@4Fkf92t3_7IMaGFTe#-ntfRb$F-yY#2s(b};NWeBEI6_6O+?upKIFP{uA zSI@9=DdZaSf^*aBVd;{Zbe<272m@H^WIZSdCTknpm`joM$hTHx$Kme5CDg?7v7r^b zDkdmraY3b5blca>OH6vOo5dzK7iqJ+%5YkWU?WT3gMg^p*cP7KYLl-t2Z$E)N;jP) zBG*x-ojm$2MK(Dvc@;f#%+i)p+csTOxLykM7$t=P`Fw4Rzc+eITAJRguJt~TRkdf? zjp{JBoH#49CE@qRF$k|ZK`qe?+$k5hBSqXUi?FGE9KWW0iSPjz_Hy)>_8Q~yQGVn= ztPh9~thw;A*P^wv7rF-m#=EuNF3wtNIFnnUwJ$KB{DD6$G#)qc<6`6S*J7+{qLo1O zR_vriPCUy}%*Q@)%7~k$rEjG?`gY+al2788u_E_#(u84j%i5~#Y)i`$BMsK%` z%~_}SV-u04hrQ1T9@PtXFH@{7Z59m$mdHSUnssDtgRvi3`}U4Gt@Jo%gg!t}MV8JVx*Dt(r6Os$So+gJ<-}2?=L${O zffe$AP&bqB(Poj!uZ{T5qnG@%(6TH7Be2SyT3{Sa@O=MVmKzkQe5{4TK8`rz*5M(n zU&YVW!&>9d9sbv)nXjt_tJN2j=W;5m)zcWu{U1;R59z#`i}=6At9BT5t*oRrl*DK9 z`RCcuwk)fMfd0#zG_W}N*r<`}j9o;_u%4npJN2khdh9?A5sY5U4u`B=TTF?S==ME?KMQRgKzJs;|WzXnGQuOXr!P#AfQG)mFzfYui;Eoni+$a z=;+$@OA2(CQi;Mdf3YW^^HS9(W3n{#&2}#jgI;bN~Xt)b}41%c1`x98~{z0kz ziCjMXUFJ_l3DMGxOiQEFq02|q{yF$dg+}l9z-#oX{lmMZ|A_BT zV9o+@^>9DrJ1dI!<`O}offId1xCYI!O?vDQO(W0BNonS5f?!bRwu*^yJS$aWe+Uv~ zvD2u|R0nwi66z42D)NoEmQv(<)Sbv~9S?Bf(^R~R(W#;rgh#9Gb+jRxv|H^}4nfxK zURtNV5OsXSgl(UHP#su$nQxzZTph6Rn-+cSs3Z19o_|P-FSGv-#KTgB22c5A`?#0Y4oudxK5|h>A3~F*8d`a7uRd$&nazs z&KY}$eqvJWsN^4<0;RVB^>FiFQm!t0S{+RO8?LbS`G?g*nCr>ClJfUPi>6DPPTK9K z@NIH$^YLVDHu>p-8M*LEU`%Xke&%lMXWb}`mjQ+EqH5p}Ey*U|u#$*sPkvSR1mtH}WF`ypLqBoe2H)u-oCyna&n})Hjs(oDKa6Y0$;X#oI-)$y&vSO*jCy$T@#f=M%js5q zIlX|Tv=oa|UrML-g<33?O~7bsc6Lb_zNCi zIHB3#yh?bdUBS#$iTV?FBu#9m6khict%KbV_&Jx3H9n^r@i)2@O8z0< zU6#7I+WHM1|B2-{vNgjSgT8%SAF&dShY*YMA@@mXRbYb$F(@~9X`20gp*Q`t99AY@ z3VS~i>qv7vpawKgmH(yChe?TE>dd}%=9u^)y*$Wq6&|}@yB*Hoy_)BVc#gQF@u4g2*C+YLr>n(TZ@`15TN#`=-CUqdDDl71= zeR{zp5v2+ac{T%{(oHO)GnlwTOgCH&r|yC!Pj-g6!NeTS0ZY62shX>U?(=54-pusP z)R#Xk(^t$)<01MqgRGs()cqQvpH^w~?`Kjj>kq7SYRVy2S;uMGlP*d8>KJzc0wzs4 zCZfitOVZ074T-;;Muvy1416J@KqnE2(|H6-R)&D)Q5$Ds*+mwR4A z>PLXE+)2Hs0ZT2Q(T*L>HGG~o9n*`6O+NBF1dQ8A0HQNpnzj%X`C{)=c1J@{Tj`pY zNL$Ug8()Ro|pLV6WJi=0%R51w8}*+%na~a!7KB&xss@Bq9@g#i~AT zX85g$c;~28;-2zqSM!>r?oyzEyIf#_YGH?Djt1;0>5_Sg;}($b@+T(-WLLV$GcWP> z@vLzO-v}Qz1Iqod61kBLbhOHRn0J>Ba5aClU`_ahN0z@+p9j+NfMZ@FY-JdrtsHJQ z%bPsS+mi!yY~}fC;RO>*=JNVrWS?UddK!*IA#a%g^D%Za0&OQmBt01@;^8ip3UXxeF}e;a3AEoYKB2wJl*OmCYnLoOtzBox;?Ow%XoFVF)Doj8~yz#9mcU$%CWEX z=jU~jzHLEUkbLN;*l2SHYh)JEV3oDtp~sjk;9pdr$tXY+lWPX)-u(L7?)3$1#KZi zrulY67YleFr7{(lX^Z7TQ?>GJL+2#^Z~OppEW`i`g8Uw++MpMTTs{ zd^{0;9G*pNLm>|JwU8`(W014JV8`bqFtfCBOKyE#$HZp=D_7TbM3-`=HS_8^FmpNY z!wsCe4h-7I`!HiUsUCG5m=&G(wPLp)r3V*O!Pg~q9hezixUH@OGmQ%i>N+qfx@QG( zif|*9#N_9~Z20}wY!YVGbzp9D&pZkr8U72Ez)a@C1ZZ_Ud^?_EIZ~)Zik?U@fGE6T zWCg`&j4Yw(jgdPkQeos)@-d9uK;a}K)vp|!_Dj38tL^i;4(AsMrrKe_uaoX*!1U76 zo~#B66-UD(jJzZG@3-H6d;hL+k3RCquo?%V1W&9fkOM!lU22b{?nL|&lG#$>i^k4z zTR4V(pXSIOST3^R8IcPl&-*mVbGda!WH4bQVxula5~)A3xL&UhSAJ=qvR#R%Wb~4k z%j{x(d$9g|vE4$CYm?>s#K(rxva3}vlSGFV2BW7;nc~LS`E;G}76SnTC6GJcxs#oN{YDpq;PVHq zT46SGl^qUkZHYsfa1pF-uA#ELNuL5ZR5yKP4At*~EOJW$@FkDa&?RU;O?@sX%K4w1 zjGjI}?>ch=S@+2gqd{4{zZIC%050xi?5u=Apu(UMIY?gR0GMV0)J5{1Wx-16JFE*M~+`n>ro4*9Wzq*1xt#_guGFTg+_d<-BOU{2Wu z(mgxBqa#e?08dq|oXW*t#*q0Q6S){UXP}P}zAZC`8V`A-HjH#3T#A!^{H;EIt+PSch82Xb1OZ;9hF+t|V4z4y=uFjBa zac$^8moAjOr#UOJ^ioUoYNqZe86>%|#N;U?Gepd>iexu^H%B^TWT5)9DS-mr_Dm^d z>zPt2108mDlgSslGFW-vbsSmmrYFp`9sD{bf0UkX4&a#MvPaG#5l3o*3e;V@IT$l^ zA2Z2z=sR|kY|^2u5T^ePSjJO$r%4WR?0OS3Cw|DJ*@~emlu5zPlwW?K<9F_BGpWt#R<^R>cr)0s6 zmg%0uVKkp$^ngbzlk8X?^TzH|cKyeYWlW~nj8Ey^}IJG8fKnS%ItayHG|A6qWrnY~rwJppP zLzZZT%kKF&lBczpTdkbcN>kUjO_oEvHk&8q;4(zw8}{cA05D&$Y_( z6O83V8Oxbs3sj_Z^Sk!h}}m^Gg(-7RpM8 zm1~UB12{IRrOui|asF#W1$dJ8`M}&FTo$xI9Ni;4wbpI_AsmIHU7~FGuf}oPxWj400F~ID+t1S-w|UC znG9>l5L!d<%?qCytH>3g3Bk+ZIzJ{p`-I-tfiy?|(+f}RCI8ODKbkQO7}Bh=3aXGo zXu>1H73kejlK4TpewJOKp_x*P4IQ=hkO)V+dbU?ODQ-(2KhJz0t%E!Rl?k8W zg)ku66!}U`AEN>C{Sgh2&Le#T^6e2FkeK<^4W4bC1P|7A`5~&cS#1m-y#-a|wkq$y zPvlE{kjj{-I=(2BXcgU!6_v2mMw_6#@*IA2I)7ES(fo7oo>aX_jN<#u*SNhyukP`~y|y1;UNXv0=pEi}_FqPMzCY!&jPjqp(~t5U?Rxq7 zpZ25tZlnAay_fGkUmv0`Y&a1gBo)`;lFvf(W&iG-jD$NtOy7ZY$(P|?C`hT+>M9!V zN@dEQIW=j+5aq5Tet4)Y9j=o?VXwobo3`Z$mpGqiHtt}SRai+EKPFJ)@(pyK|2^7o{J2N^b6ES=>+L^yqL21FT7Me7>~4*P_qtx- z?PmX|mA7O0?9-ONBd-1vADyneJFfgkr!Ain2hX!T%aeV&jfE7HrdT911)7YrXJ?L+ zGf(LcjuxBzvq5W6v5uNvG0{|aY{ZC(Whp^5g2E}*x7&U|dBrL=&KJLG#@uhC(RM2Y zgnt1_$H1615lA@?MobJ<8q20~&xb$@FqX$ZJlXqrr~E+UE!JAs!e61v zGa2Af24lzaL5yDtN`6_6JR^^Pc9%66w$>d(ct+7=-Q_8h%N+jtW!IETWe(3&xy&vl zdDrA{9=lwdErvGZ?7RbWTDCPuXJmUWlQF?749tv58W?;%1ztx6iH$jUGxIgh#8QQ8 zFc)IQEmUzN!UigzLEl$C$MR!lmd{Z*52)cI&rrGaC1^AeNB~J;Gm^r)Lv>PMb$)S} z)v48|RrX^u;365(7Q~cQ!o_k5{2eaO%#jxZMp~@;2-UR^N?JT-nNzEd$FIJh{Wq*r zga+jtOgh;BPvxq-?Re&U(exa2Nvb=B^8+2C>soNar0fZ-&cVYXkG1UvN3_rqNm8w* z0cU^M%9-TRn0-)QV^Kyxz1#7dSFnn@FR|9#eYuBHy2z<}N|Wb8x#kP0t?g63qN_|= z@r9h@-V4a7QK<(Si3|Yp!3)o25~Up4hE?U_7MJ4{tU9*|Mm|j?`_4ond*#AIjJ6&< zbTVEZWb_XsU}=sPe$=-=ld=Ex9pLA|Lpsjgg!8Ky&ZV~CcQ82+%F+2w(mRYcR=?BR`q^XrzhMkL)I>ZzPhOo3dE6M`i%}NVQ68<%-W0)=r2gJ;1S2U6q5D#?0Z&E-!4!>CR ztScGn`p_?RZuWkpcW^&HKutLeaE~0&#Antj$yd3|?yQGAt=GSt>ffc;uhsSft3OGr z@fx+pYjb0l;hyznMGXCNFm4#B73wnMFSHwi|mC zZJuUV>1k&-!%OA0{X`h&AnO+#fl?A8+TfuNsio8wK|=!eJ-qmnDTaKHeHZOrK8Yuv z$Qgg6xcpv!o?V9Vk5uh9O)DB%QXkTOld0?gUP-RmmS5@++h$H z3+b?c1PeSE;VN7effXFQ$lH**9v;InlZz3-uOp9te#@28aq&NE4*n zq3#myxchyc3_{S(*uNX*F7K;^u}r9N<&%L?0@>B(!0U1@7+A^U`P5h`D1Md%k8gZB zk>7;b!U4LzIT-szPFkgjzQ*P zZro1A^Oh?9z#JC~%z|6w=~P>E zrXBNl{SU_+GN0yn|8Jnlr>(p{fWG~y2?miYbEA>DnfEWjH$%+b4aTASqM?rF?G(u=- z==D`<&>&hNnQIHDFpJl8(0GuiVmBkmsK$y%lEij1-h0kt1!7bvsoV}9kS)%D*sqa+ zCZQJ_?+?Xre~SB-E+ye=REm~^*`V~u7>uCQF0VqKN<;t8T|I~1lPs5=AQMmYvMY5o zma=9y;i`}^F@_7md9g{&Ef@J_yBZ)2AET8}?(WF@z1w5N+7rw^ zV#bj6%E}N3Qtcp2rm0(8zi1^fN)h2j{C-C^pD8RYPBLSZH5`=YC9YmqP!g1uJtwCCb8AZy z=GRzr@bi>8t_)0OVM9`_U-r4o!UwsO5(d{;nLNVLd{7VGhR!OaNarJPzk-6QM_mSa z(3Ic~h`Yk&6t2wUJeSK_0+w=F{bDkFF$#%G-K%NvIH^!!c4P>Wn2RTWI-b+oswCGP z4DgtjpMdmT0TP+9oTMLAa(A&KbhMY_goP~IbclaUonU|4pbz=nwll=nEDcY$UvPqqgz)+S>*r3 zuksuXLf$uz%?4-NJai2j8!fabU2mL>Djo1g!_~+5AQQ$vJdkY3UPEQ09v2JTcF0Kp zs(^nPgbJBZ!EZs^V7rEq^mz8$>v~G|=<)cl+prJ(I<#a#oTQsrvJpz58_R!V@FDFd zr?E^0y;1`>pEZ0?P_P&4S$MEGY^WS~0nTv_`l=l#|D}PbDo?V?@|#ggg<;in^1nCG zIUGwZIoGNTJAvlXF47DKz6to+)<6i%#s~McFs;ZINs3q^X3z{nkul@g- zz5g$qrgy#k8GRO~?=X${hPu$ukIW`-XH>|On%2(&YDJH4kZO65YWa2h5h}OryZ0qD zJ#3}~!7D+jK$n%KhF_-N~gHa?L;ers|hA9)SQm+y&3)*L*N z(om+#r)nC!);F~Em!5k38>oN!|?N_`vCVi$e>i+j&tFdi$@bEHRX_i*pBb$ zzLBoI@ISM*S%cImwBxo{w`|BjdB$7f7XMerx@LM$5f0MWmJYnghbUmWT@kqOD0n;sS|_*x`M^7X!)y z+^QEt7Hto4O%MpLId;=^+^13Xpy5>K-|w^iJ~A}1DtByE?cbs2F8(itZ14lcKzpB>;4%bP{K%x!~(kHGNPJU~77h#Oj;jGVXMVmZ* zzHD7#4p?3RfyXN3yY~w)Rm{?%z$St@c*INwboKkvpYr`Y%9@9S#+ zpZ_WSf7j^0`u)8><@<+?@29KZm;RLR=NaFpsoy94l<%F!_j_Mc`@i|8^#2{B|LXVm zp6YweegY&3OF_A%hrL5D`CoeGgE__bJ^X7&zr*Z{R$0|uurzYXpFv;yUcl8`-bJ>7 zZ^K`fit(LS4W}g&*~7+ck&~6hK8z8AD>eLHrAmTVsK1U_$q;_i)nBLj>r#I+)Zc9N zH&gx1Az8>OeZG*3j-FK+ote&d51pJR6-8Gmc{4}(%hF(>&5v1VU;o$19{EvOegqbu z$tEwdBM)>R5{5?$U7(lYmR+duYA)iGD(zCav$2p)P$DVfGN;*-08i9(o$>h=*Z@@0 z7)-GUNvx3COrLGMAK%6vYU53K64`kQdzab+Z2UY{j4WMcDVS+t4GBZ#rB-=7j8|2( zI-SgP)YGp%A^12Rg1rR6E`;EX?*7?&`)&J~J?S(%o{H|4t1W^-e%J*#x10`{e#2%%#>kvl`UqMy&S6$-+?BCF)&qHivY6m z?hfH>gsj#QU2IXB|D`zw&Bj@ix|ze>H;NULBBh4WDUR*YZ|1`2Vb>k*YUOf(8!Bg@ zrxECn$wiieGK=s}-2Hp;J#v?4A5@`;R#~ldY|%P9LTW^~IkZgx^?;Mhti)EW(w?>h z7c{gsBzvrFO&9EX`bObw7+9zf`Axa!HhrFfmQaadysYvJo4mrZnJZXs5e^l+`Vsbf zlK+6P3);mkimF*ko!;(jh7b;AFyXI=kj1u2Wxsj?q?&4$3y&z@{{3VWCS0CN@XO*6 z)@_WoI8({nVvK6|)~M>zZKJR(R^B%~N}+yU{DSp-W~Gv#x4uvcLSaA_$NMg!Z~&C| z`CR;D9~7o=j>^H8^#y>#LNlyw`~Brs-hUh|R6DW1l{Uuxc>kw3>ND(ep&2!R#g?i5pL#fTrl~t|g;7_ciRub6p`R;F zp0?tszgp_=eD$}GtwaG3(HC;E#~!^pW;x2_c>fnCqtVTrI3BeA4^Ps$LIw~skng|Y zZb7g1C4YMx=Zg)A9b;fI;Z_#k(@e}?MS8{X*1%6F{IIQhrZVv*9Syi*OCh9_nO3Q( zt;t^s!-Dw~76?&@_|9+;m?SQ`$8=eX4yiJ~EDX6jtDcCSG z`kNfzuF{wOk8Q4^^+)Gn*{!9(z;4{kxx08D#=2D5*iws<^^6L|X3le0m_h=svcovw zP*I#k`A9doYhO^m2*{>k(I_ZL&L}3~j;!v<;-J;D1 zpu~$Vv4az4`FDHnqBHPjjyC+~xH80JTuM-E;d1L!_IPHZ#vGYyNTKK!3K9p^M-@7# zLJ~*$lEz2|UBSWz48i0%3wIYe&j8E@%6V8!gYHu5(5G}aP(z*!6^`Pt6Vn`?N{j|O z*B&a&5f%W^p3oJhJ{=@dK7oH^gi;R_1OPtG@Dp(eD5kJjeIdIIgg{%6=X5A<;52A^0ibc1O7%! zG!$037sjWR&F-KuL@T2F6^f|uJ$JcR*m>V%5S`pB9K5fPvYt4k;tX*`HjofBbT;l@ z6yfx`KLL*qN`hpJ5Lj&2_oBB5n zMY=>1>0p&xZReUmn4=8t{3H;%M+0^7Tjo;wsaZ^{tBzJV(RXed^dJMb|44Gg6V5iAB zNE9>Ejh*)|#IxI(v9AF1x$I=c20h(Uza3TZte`X{yA{6Rgp^2DV{tZxES_YSiXGA7 zOmPJaz+h;_>=_s;2CXj{N}$C`|NOg?-(>uJrbW~8(DujU5Ug^VY~k=#3Kuf;ympxb z9KftdpH*E&ej~P-fC1=!|Jr-#4YIeDXXuz`L588dF-*4vy|Mua#n3Bh7EW`{teVC2 zOJ{6jr_(PleS`E%VqU8l^TKu7-N;bog_sw6p;B3yl@=E15HgclAX?6~&ze<*i;L8Pbh8>L=2oN_b>yIK zk0)|H+q4lbVchF}wHljRP1NH6^jE2CUStvhWbur{=`M_BQ$2D8P6tnxIu#-ry%J9< z5sw9lCmyZ6`hNrwpAM#i5>`vCLNVZJC4kFNMR5g{=o5%82a`|c%Slk=GWMRFp^wD8 z_RNp)YG<#Oli$&0@FEJj@^=HRgla{>DEwA|y1NYx&W9k>qU z3F^VvP${hFlNP${hEr9?_=;kIBB(8?b8K62xYDd|Z-6ST4H(@}{1Fzgw@kFr=Y%c?R(?u{e&lrJ^sc_zBwQb6ImR%8 zrOw8kv20vricw5zN1Pl91e)ZxOwZ%DXpQn)s8zAiS^y0!xdtou%=YbuIkp;@~)mcp4vHy^x}6&qDTkr~(nOps_TMP^WT#2Ox;|-Gp2dSAcLeTzS9X)-TBOe$K70 z8fB>Ob~G0OVWHI7Sjt4IcFuD|Tn*CG2RJ5?cjQthtmmF2Rtghsd=}YxYJS$ZgZ$}< zWVCH8Als1OREZswhVTCv!#OSq6_4UzarOwIVjvOR#}cjt@({|R#jeON*cO=Z0Z^Wt zgG^&T@!F^d6E4^R#Z@?zkJ!&^QY1M zUtVW>OQ6V4w_=ZkbKSczVX!s2*aCe~M*LCR#JMqoE`0?>7EcvWJrY08zbP0meVUzU zzsl}E0J7{JVHl8nBpdw&Vi7MmBAA9p>_92D)F}l~zD=dUpsB5@alP1I$Di+XJO6uK zKR^2J;XclfH2dIzP&VM5iss42etY-)zpoko%%`jG_1CbzYvb#SdH=`P*h=eFR67XH z=t*DaVRsnq4?kV|uKw#^ zRpD>$Km1un{rsQ%;}75dihjQH$&>7S=dZs%_4$t8|5vd8zv+AYUs2)z{wIw8D?0o$ zp6n0&`3C&wtMGsMyZ*s{ay!ERc(?h`WBtcct7sckJZjnTG(1gsaZy(^iuquwl)pcT z9Ku?)Fjd+65Ifpm>9R083QIMGs{Q?w%*$AGaM5T$eh$s)^IVk+%V#R`lVqo{v8O)* z+W&7y$;0YD5U6vOpN#U88f0m+?h4Qi-%x&}QNF!YE&o#Y@>)I^yTwQZ^F4^3is=dR z-AF>;4bbzC+5+OA0NzUFD~xparY*1^(CNBTKQACeL|tX?EmX z+*=Tr;RfrA&w`j&sXRtiSp%h&xFca^@@)HrDfty*QOm4qkOl1w78h>py^5`n$OtcR-#j2+h+U|vo~c~G;`If@8Stb^ z184vNWZBqfe24e9qV39y@QozmC(5utos4em5znvgX#F4qpHFRNA|r@XGVL01lFzkm z5XFrd$oBir6<66!p0jhK7#(|M5-4xxlhC*D;v_Py$Ux&mG?!no2?)fN3^Y}a2E1yP zvr06^4&3MZ$V4`E^WYNOmeeQrxsKozyU&FIiQw)Fb|10Z7O}f0*q!?D zVfJt{yL${R?izh`%b7wx*9*9^!Go9R7=tdish5G5=&1xhgV@fqx`T~TpQ5;hu=a0I zYy03h)G&IFc0?LXv2gEpTdC}N;pHia=#Ep*RwHuP$~ zhkqr3I%vL@_YEf;SZe-;ub;%%ynh%+Z{Z3}DPOTr;e>0MW*>u%YZBwIu{?n?@u2BV zg+#eD#rA>x+FxSZW1zBY@L~n`OWr?&uFQAx{z-I|a5wKSpexJGyg!$&5`V?}FQuy_ z`1U-yO1^{l52h>YUA#Yqu2Por{wVIstVo4gexR!X@NI;yY`60M&v1jNcpx5?;Xq)7 zIF><9+xf(ONN+y0f(wDzkcJKyv@wt=u}q~-X2>7jO5#%@zji6~naJhWctJ?JnXV9N z*U(i0T+M*1R}u+*7C>Ji2EBTXg_(B%F-XOh#*$PU2mb}c+dJ@3BGoFbOl4`2OH$Fg z(+R)Mz{*ssiq&!$V*hyf# zTFmR`U~VmFZ<@~f`jnaKN#}Q%p?tB}o?7$C6wHAbLC7#WUAlfS1eLk5>P_`N6<@r6 z5i`I|cVjHR!FUCeg6s(p&hiLGE_dKd7=McMtxXbV%p|F~T$>=DZ)6h$&H5=xX3q&y zf;M6qltG8#)Im7i^$o*mK-|I66)b$8vMUGRnea+e#sBV!D4LMs3ZT@e?V-Uw^1p5P zR6D`KV<+@mp}qHHxzMiKt6IoU*1IN=6VAftj=1Ll8RoXh4@}|Q!6lf?ASZG;SC2Wu zgH%(6n%vLkQpAm9K%IjiP)2X~7Bd*&c{o&<7qZw*0#=bHB~#SH912`F$pNg~ELnk# z@8(NZ!V`ua&=*o8mu%eV-!1JD&X+NJ6+Q+f=^K=6JP&|+#2!UH>YahAoD(y;7@Qe& z6OxQZ;rBjbqA z{{sL!EV2`qbEfY0!<9xrjCY?i$L1a_rvzK>Am$h6eIG&@eurJ`oFk-oJIi=KZn8;x zvqHS@i-9oV;gPQ%SBK6yy#D|`>4L=%L%H)iDmk&?b+I#pUw0KQYMUN(o*RvFA4ESF z>&=)pO-hoEDfxE9s~X+(!GX;35;Xr(i@SmMy^?~A{w`3O{m-NS*#06Z4bLf_O`-jb z41R}OY;4MH6{9Kqx~Je_5oVUB%F|#b_+CpvKyt-UQ<2z}TJz;(X|KD5)fILP#08&D zi?y@k5IWS!_f|rOM%-Hge}nC2bS4U5DwSi(ogg5MB|Vt@q)Y!mFBFrU=&R?omrUHEInYW!+g&Zt?u?EH_MiL zrHMAm8y+Ed1T0{wqouqK>!&foVep`(bS7=&04U*E0M`b)xASuCiIC>)oP*w zA7i?_Eq4y0{rAAkjJi%@wpY<>8-%CA&8j$fa{GyYnx@yJg%>>g^qLYj&%* z*V1jmt?KPmy0zS;-j1c)MD5#=ber@`_4a(aO}}U{Rb`^vl=$(77k;L4O&sl(MH*cb_(@Ktj$2m`&k$f+Y5obwNz%2O)9qsN-Z=HMK)I{-y9saalXD_CUr>>`3Lw`T1PSguCT7dJZl&>4sZ%}R-u z9rD&Guu+uYbaKBSS%e^WYGpS{#K0W18kbwcQ=y(h#wFZA7Rfiso4=Ib6eKT(W6F$i zERXE<$O?`r89$=LsPd7iDe)BPWqvlt;AL;b`ObPqoPQYbGl_GhPMiTG&ij&RqG&u0 zCd-vs42PSos!)<7S6QCt$jf++%Z{w>%|teJbNKtVCn6b-S(&!}kTAQJpS1Me;s2~-9eyVDXLk60 zy~BUT4*wxBuEWaBsWD7_NAl^}!z>k`VLun3Bb)|M1g^rViQPwF^Q9WQy1XCoG~CPJ zky3spJhOEK-Gc~PVd)M}h7Ql4l1>lLl`1?P)}IMat`5&Egy-vo_yIGIVUx+8M3d>b zo85Bk_RY4Kx%FM*>A@BK4BRO{7u+E_xH$-JK{s#{tTFU;Lq7m&@iBn5C;v=DATTTzqO)5Z{KNp|`9Ybd$K*PEL^jT62Kx6v>P?N|2dMN2<0(4Zz z(Dyh4*P|4)A7nNEoK{SLm)q)Y@r(^Whxu&|px^ z?W@C37kns{Qisnb{m=R>>UwEbrg^5>q00_RV5jv0djL{b{(MhLp@ce>GeSY^R^d!@L~%KWtL%J1qJwDT;qg_I;EtC@18 z@nWMD4XjL_qR0ZZbM(nC)lV+A^w~jfpS0Q%SeeEu5H3|!eMG#A^jfv`>N-_$D6~o} zy=Qi;xLjm2I?e?ia&`hB^8ufnAtmuH-7ZTM7l8uH-`Z|LL-h#RDi!R zp90_<0C)p>D$j9^MZnK8aTqk-9@v?Kn?itARRPGM4y;5~Cd~mQRr|d(qUG>y>#dYK96pm8BW0k6UERVqj5Nv|r+$iCq*8uw1Ko&Ub9<#)m?%7}j>K*1)=+h} zR_qj` zZhqYzsII>D>SMSW@oDs{+vZxTedQSf!cz6YaVC-^S(QVB5y3>{WoIV-qjo( zsfdMhv^N?)Y9cL^6sAMiWoN5waq z0yAjyBrqi^{+J4jLwe0Y@r^F&J?WqrGE+ba7hkd$mWg;L1lI;!_y6eX$$$7QcMptm6`WV!xs&7)X}{Qi0GQpC|zrE>BVYCng;jT z5kxr3#;iLViW5W7lYt;s4qO0zO2ZyK{G*}3p@NKk4u6r@&-q`Y&i}qa=npPCb-o?d z`1ZuJ5CW_z*WFAh?sqa2by{KdOY;VsK&p&+zV34?L;lNFQq_<=TS}$T{Eo8%6@!}G z&Ajg+D=w8oybVp>&QxAp54YUzfK75Yd)^U)O<}K<7FmAn&OykJr*nbj&x_G4e%*6} zNK*Etqok}2R`jbF!S#c|D7boZ!oERNM-2}Pw67lYD1rCSPmU9E|8+hIxxQ<#)*a|6 zT(ILYI`qIKT%^0-k5`}<-ur}!jy5j@4bjjIGn7{sgMN1}7J^1g!Uyq)e=nA?u=fKN zvtijXs5cEU12n{}#j1wrWc9==i3F8&|6^>UCLLA9`{_|K8AJTd-aqQ_EmAl42AvUg z9M!3#L!*w1?cG^WdkdRd3HE-lpvc_}u;1JJ!GboF!mQzKw)G`E&Ke$P&Dz2kZUoO9 z0xpw1E{sDW@qcnYx2kq=Ht_9kiZX zbQwyX3fiXwPXn6W0Bt}VXx7+8w1l=woZ;FZF<1KOhwSA$S@YKnJfk6dUniQ+HKM8N zr?`2Q3c+F989{JFXDAVkp}aGoe-J$XD+a;bGlSqm9fD6a2xbk?Rtd#+1=}nf4UfD# zZYROrw;NMlr@5zFK+A_quX{4@e;K!y8pHW$8q+A8YQ}1j@kDbS z(kIFV6Is{qs##r1-H%6P&FJa#|r1U9@#rNw^cd&jtOB8W;5=fi7229#PNDcjL&UTTp-SxxR;hGbJ?3b3bO)FI4cN)-#$_ z-)rsW(!f^OD2E#pP2E+CGqWmjuQC`+>7-p+5v?ZSr4Cm-DT%^J9eNum6 z*tdYeu;k2OaOp5yuEDUV-!M#7VfZfTj9_rJ(Xj_s)Ct!_iAr0QV=Ja!wob`8)#c>1IRUqq*D;bG3gcdFdAQ zfV1xw`-74S9VK%#l+3lzxdH8O`me;Bj-|Xm3!O$*Geo&@qYP86@jG~FkGEl;x6{h6 zdy8X-HK4wU9Vz@eG|Lx53DPmzD!UT3zANy|VaFh`p((JK6FXCDKA(=K@fRjw=z@g) zQp5I}S=X<(oKe@W(7T?mb^Y3Y!!SyP;r)a&g5gdbh7}qNhs^zj;rU;x^3R#UFjt4+ zIt_+dX6C*AKTshEGQ1xZP8drzO%&&Uqm(8{4Nh!Vjq{BI$XMCSM+eX94nZi@Q^>dB;?El8b5R?NUe9e$2bV z`%ljUII>ycxel>QwXN9|y_m!i*E4Z@J9|AwJ0zq`}zMII>sK#R#8_cXS z%Hb>R$Cst_vI;xxNh*?3#l2>Hd=)*O%KI-v>m+>4g@-4on`>x&?OnkMydQH0iX92O z_&bih^Zga$$xI_#3j}E^D4NA|L_SpNP)eJas{AI-KVGi304g%v`(^6a2GmLSc-@nD z{~BgIp9#YtC8JLX8oRz);p|Nf(L{VzwQ_{lqf$6#Ht&C39Wc)T$_wRPVXhFI^ajnnD4Yo!Puxf38np3} zkx;M9WGvFo5}IVoTXkbEyKa5gXv{OGQh6Qg#?u4)?1t1%otSA?jlM1AU8JVo_rIu4UN2%+@y%=>&ueyuP?UNQ*le z-F>Ya-F>4Q-MR9phrsn1(vZL-b7JxJ)wR9i%lBs-3}&?-ux$_K3JG~N^ zYNcvko$^7f_hoQqFmIXLvgRr@vsbK)Nz4gN?2L z55gmp(6|#8u-}nOi&8Pf2myy(Iy;G!<~+7sFb2k}9>MY}eXXL(sB75Z1X5#HP(qfz z{ihBNlLTUCHxp)L%2>ub0u>|`0J)*t8&FUo@E5{s!3*px0wXjb#p|?gx!PUf%H(|$ zng6XmZdY8>JDvXm%7wp7VaFk<-eo|7wDUq3>9jLUBxs5bWfW^MsW?EaywHu)VH*Z6 zvgR>d)WvOR#Nr|p&*_E|E|wWqs~Kdqs%~fyfdcWc*~C%g-4}6RDGn#U#V6hI@l--Q zK8DX@_=v~Go2YKQXH~mD;#@kpnG#O0kp7Yh&eVS-aG870CBF0yz%RM>~5^sW4LWfUTRWqE4ku&)o3%Bu0Y>u)oz4 zh&+Jv9!KNNIjVOs8qv3+D8>Ai$oH0x644SlL-}Y9nI2~t6-&p09mufLHwW_8s|@?m z$F#wk(rJwNjcOa)5>GYaE9P_`@xGUYir6I~4G|euI;cVF)OWL4gJp@Q?o@J*PSGp1 zV|kk~E27>xnhI;N`S7oytwKsZk!SFH;VO9pmUGj%2p5aN6B0eZrXoZ1JW!Zs%o>vw z3Qf2(!q1tB7iXe`0X-P0_P}rHhO*39l$Fi?xhRwNgMdo(2Md_;0MBLzMiHmhkS2Q< zM&oD2y|WmYpCt4?D|&F3cwsb-yQuP9_%9sEO^6sIq~DXGeTzrvCeNcZe-6GIf0xw4 z`v>7H*^7G#Oxkb3_ZHeqN@Y7oSYz!4#nOIh4?#G{eONe)-*KfFY65*o>`KJ~HJ^i0 z;(rGR`CLvD{B^Oix`p=doVvG3he?%rN5g9F-irz+s8gJ#V|XqMlyWFLPNzrqKyj1U z4%!99K&vC`C!EI#896bxaI)@jHs6fn`nPxs2*~@np}@h+FC;SKXIr z>w#RL|Bei8ml#YG>re1IW<~=m*f*E~tEk*_ltMH}m?sm%;buysdjM(ZN|70iG*KSu zTUW}ACr>Al=c2YaUCBkd5{UZIvGe(omWUU@E;%MO6RDZi1$eb3P}W_VyG?}w4|#f9 ze5300C}Zu9kK02VZw-h;==5~FJs`U93O5u=#yff}`Gy_)57TK2W9BI)Blajzl5aJX zE9&)w)N2s#3A1<*guPw>E4pH@VB(JQRaI;};2!qqwTsLqnIn7j~eOt@rO1GUOo`0(+Qu%p{ManD(0N(ymAf?ZI*T zqk3*1u@fZp|Cq?x`C8upzDaWhV^t>AN28H{Xxni!Z6jt{(J>teJuuTj5jxsE<&mlA zuff=;v`?7@D3i*pASQS4z7LRE&|4jNr~?+ZZPH?!G?QfNK$S(BX_Jy<4tHPLg+x$3 zghf!nF_!b`2D#Q&P-~YuJnxchw%nT4g=;eqtLHb!)32Gvr~y+lW7Z2=kyg@*BsD7c zOv8kT1bLA)tfqc-Do@P=R@4P8U;b z;|A4RV+8ZoQ1(_ZP$DMU)=ZX?8cUh4#%M8wIU${qJdLEDtcW4vUUtR~NR8YfbjuKi zT1hkm0ni^6&ZTSv+JXgbK3YK`Dx4S$USOIqx@Pp|v~;O{{y}XEWqoWz8xuF3CQiMv zuB79-!rU#`apo%+;^LAy-SeBBkcY`d7WW&x?-5)~3U2q@7MRV!;?N+4Bv>FYBEuo+ zuqQ=)!z>MxK0&t$+``5{y!?*w7?I&a;!&uCm&W)5<>JAFmD5U2-o0((tvGsrqouHYW43kv8AQ~ z>hDzR|I~AJ_}|E&54bl$x0*S$>9I@`XWVEGw<%YIXGb28*fpc#!We z)Z_6zP}*xez8?7>7P6R{(=Bo-EEi5dfkjS=T&(tADrKF&TH#p-r6lAN2oQcU7ld4^ zW5L}u8SrcW<(;?UuPtM#a1;Dmg*)!P3w|v^jpyb@i}mKa?^+_3TAcC0;vzI8?{zvveK@eU*Y zPo?~Aqg|u@H^_Uf$1b? z3#;7%MUAlYz5&EplEnJQ#rCuKbte$%K2gAptoL$TqesL>v*hl{S#?3-?NY|oALu5z z+q-jD^zsB&F^wI@Iox;%W*3G7lkl9w8mU93QBa49g-|Q!ggfz+uUWWr!w_$0&dOW8 zont8A$4Z;jWZ5}(7{Bg)Jc?|D-bo!h&>#lmJPfAz4?A|_Ee3(W(7^nT16)hMQV+`n zx+hDipyxVx-(P6oZct!3MSgfS{5w2MXbp?3)>HQS&?MIDN6h``HL9zo@Eq>+)vi&i zE$&yfxSJk6X*zwinQFBWu0Pe%!R253QSJT`R_&&KRg32Vky)p!bCp_WVZZ9cw;*u1 zaM6~ZM!7Q$vtqA=;vG_pl95JAvjbN+ie(24Bi@U7Uu;X%0@wCYXv*Q!B|h}6p?Y4XHuj>Lu}?mRZ`}C7vqLf3)+(dRzObP zDAn4e85G|xFx?`}Ksh-XbYht*5mIQQ{s}btAb@TPl(1L*7V0Kcd;f%! zQ4mHk32dO`wG!$P*0Pm)f!a%l@=S{g8V0(naFw`s$q!&xd7l?){FtvS^WTV)-VA9E76Dw0%?b%F zeYeixQf`7K8Es$_=zN{E2b9Ak+QD*iEsPcrr)q^fR7h!%!zVbx6=kIUU;-Q3g$eqk z&yJt;?Gx1Pv=!F)8DC?Qrr6nBFSD_U?pmT?|^p`V*dJ1R_+J#6c;SQ7Yzq0m>)$D4&ew9l@{68)fKWBEAn<#76ynB1d~K zH1Y*oaa`G%BcoJ}s+_`bjiP=Sukm6m0K9ly`0JQ4DIL#Ha)|3|Ol}#kZE+IK#WP|W z_YFkyj1j9e2ji2A+rIfY|J*@=GWqTq2W_?TzFU4|+0Sz8DSh4Tyni-lq*(x-3G)MZ zByCSuppII{^lMeO*3I|TXb8wAYi?2X>yfH{eb+eE*A;QoEfNCFaSSRtRwIl;wRBTA z4cj0JJa==l;0Jih$6|-M{Agp44#=KkXxh|!U{;5e%b-@N1v>*h!CnCA_Si1dHSO2N zl7v~QFW%C+m~FC{Ewb}T({>t~wu3ZnTuzv#P21W31H4gr&wVngyojrD$Y5$LUgNm2 zEWr1Jm-dX;sLRWj-T*7zAXLvAc;7v!GLMJq_pxe#MJfVn z8DtwyENnAvXbu7vHpmW7Rd1O=PLsR?BRm%Dm_wZ8Hzqcn5Hs@qD2t$f+&mT(^jyO~ zPI-I``o>kL93^s(<`_pEZgCSO|FWl3oJ|TTjxnlJoSjwB%_)uoTHZg0tu-`F0{}NU z$I+|g@DE*N!1YlP?TOlygGChgJyw4<;*H+=3p0yfnHxpv>=5p*$^v;y=Cc@PVu2^5OKMIcP>(D;!aT4@9ZL($KF z^9dVw=zK*T_T6*}YQ?Zh)nrI;1(9^q_ej1xko0jPWFAQR1iNye2W~(-NoMzadO+-A zR~ZGIUd<<>w^m)M?Adncva>%p6@09vqU{YcMO z&tGH7IF3hI3?6k6@u-YeokuZ?A>7h8lURy_@dXXWMBa~aUjvIcX|#JU@1s~=P?>l9 zWb)7Oq~KsAzraZ$_c7jg2dUj@(k{!su@-*awQMc3mP(`LNmexM37I(G0fdG`df{xT z0Ytmu?@`cd3wD5F5*vN(W{0TcjaGf;PSsEJoRQ7g(~D`;=CvAjQP^9tzA03a<}igf zBWr9$+ZQ6M4vw9%5DlW{gb`2?esZ-<_l1=GaOpdhMJSI;jlq?!Y%>cR=88;LE8MV_y~Lyg7h=KpRU?oKPDZ2Q zvn=rjLDKv5ZqynYfOPl_H-<1}z!F=*642~0a+N$)*X&$EMy$osudkxzDqWh0(ZKAWD}D=LiA|b{A$FyS7+yD_U?QwnCAgsn%D*2C zp9`e~dA3!aXp>R?$MY)N1~hue+J%@2ETcGlFKTQ?jl;*UeI7%*QY=1x?NW>`s>S1T zDv2uGx1niCgPbIp8;cqD86q}dIIi^YN(&jU-pTus8wQHa(y^={2HHv3Aft%59$*QH zc*XH+FC}Y(rM&-qyjYO{fIH~$-69Rv%rDU@M2p8P?GLw6q&O`t0E&Eb%&Kp|RE$3e zeSWdq(uRB_ux(c>vz7`0(Ok-}{k4Two=i=6dm}uWLHh6Jfe8tgtKq_L+UR)`&`HD4njZ)r{n4O}-smfK0TSv%0m%;W=WyOQZDvo4Ad z2G+7eXa-#}zxJ&JJ>`aUF#Ja(yot6E6V;e_nSqH!+&$=Z(u?T5O42pQD7Sy~`g%@0 zy{=1$r`LfwswH&7sp<9Noc`0RJeA~vVvS ze(gHwpsE&D>Ou0H%Iqr`>?BONI=8@ zoV?N@kZSh|`8u<$9f=Bak+e%10MD~kHe0TE0E6K`7Fl$eadcj+y$U-og%4YJ zdy%z;AEX|aZtVTM^zYO3^S$|5{W>qLou=m?T-NVnOmm;dnA=Af$Cw3Bd_kkdI%bSm zYBB%BQ_P&J*m**1zQngGDA^ifywFA|UMs689jgsxZp^r*9wf)~x7+z=g>n9w*`NGw z^H`JK)pnC$$=w~v4wc$DkefD?Cwe=~9tRGoT|P_YL(v0LFp}uo&2I`qIWjP#JaBY_ z)--1moyE$N-P%*8#7Y8r^nZCkE_31-8%=z0^WE1 z<$c%hI92`g`>MZN{>RBi{>O{^p1*ZR@yt^D=%vZsOxQFhL$TAm#1`vmi1`a{^SHdr zxFwzoK~L7b5y|!pKYbn+K6A}mktCo6poa~1en*QK+9!5Rj*teUz3Y_>9<*!LM6&C6v2Qwq69~-q*uYeTFt~)J{Om$KWD97Y5D^h-26d z+PwmkV^6~`4Odg01pgp*oW-xpVs$p1-$$Lw5i)4w{mmGn6$Hd6<+tg)llLvba1Wi! zc>jNM;|=fr$v*M@JJ-abo;{|XPsWB3d7UYRy*Rw<+aIGYQBP)bO?~+u8{0f1Xq(4- z+;DbR7cNKmkxN;h1B)LQyN2@XM&%N|@4Eo;t@rs$(2qlu4(38kI@Wm`@6Q~LJ0MFy zs~paH7(bl6m@*uFUO@QQzx@=mSuEnbU5kVZ#jXT??Or^D?W*AY|BE>)b}TZBp(e2l zbkUbtjyk7uLjhFs!b!v|!uUtAYcRj=H#rQ(i{fF7MRV)l7@8O4sAwK_vL~9WPWC`^ z_g$vFE{5h2Ij2Cg7M~@D*=!%v9J>eWfo;x%t8lqf%cL`d_f=vXjE=>;4+CQ8bEo5O z-d}$LGl%MATfiu_9cQpOmffHc3z0284WCTc>J@ljV^VB&xAOkQ@zqUaH5{SpCb63@ zwCeC__+RNN?q^*AcUPZK?JIp>K^HPlu#pgh{}eke;MXNzK{LdAVV|>ZI%}ey+MCI4 z-qhN|r{VD$_`w&%j%a1xT&>Q35qFr+>awx_XFA7PY2}Vk~NRjqJ;!Hocogt>;Df_Njx6!hIvPLu;wSbBH4583wf( zp5G!{w_eDo_|}oV9oAoVVXQ%|>T2cT{g;i5XI(8Fti`iNs&ncy^#M1M`EJ0Yy_8+h zl^r|HzUw&cG`sBrHE?NmpVLf>GsdRcNS1fu2ZN*GSrY03xGNfd<3erFUJ^SqVf?dc z&~C}-W6%QPDmLmj2E;Y&>J}RR8^eze)2iAkcDi8vSye|b=(DOSMv+ew$lIJ4~sLFu&2X-}wz^e?KpsK7!F*<->yJ7^!4S|7M zJc7)=^Lc+F?rSW=WRX9j#<&cVMINIo3zYkct`gzuW4cPZgZCe#tK?gF|8Ban-p$fg zdY7dv;QcStRjR=IF(86iKR{gw*FA~(b@2SDo%gj|hHyaX@MUy(LuCg2AA4^CA61b& zj?YXc$s`PU6Bt6cBx*zghy+0xh!A291Of>ppmK>Eii-l_4FM!DFd4$*@e~g{R(EyR zWA(ePpsR=%Br&{2j#??S>N<@S%1XN`DU>jZ9^kh0ZCeVh?l;c6z1k~K3TfCs zm(HT&WJ=}HA1CA~g{fj=7ftU4_Z_rMJ*hC7{$+XN)Qeg`H@rhgkQ^hEK zg~hbYMp9uZ{jpiDfT`jkyRJeBE#o2;meC*Oas^Bk|DdhlefjrN#N~@2_&HFfKh;Az z`sova>O?M8-Q-f0s7{|Ns?$DHoq8tdm!hr`A{BiIBd3OVb_7-<-w2h-xAxF5`OH2M zF!{(aX2~4y4;Y;JfcFOJ&AU#0G`xNwh}U`K^=G=%&R@7G6tC~>uI2R-Ew8s?I+`W5 z`O-~SAs_;S4gFmq>>)YW;-vE$_+G0NJJxYN0-3d~n{)|#H7JcBC~ZfXRoPKLu8*Ii zz_+DFI3?CLTb;Ak3DFl^X1eHn1LfmUO05r z0dsYh&aVe`#`9|4<;v7eyIg(QRWssG-4MxgRR}=Ia&_y^ zl%|tzXnVOjoJ2`F=!Q^3{Yz3S%T*B_U2=`)E~Y=;ljSO=igz(OL3|G_^Bk!#o&I=H zu7IgxvcAHtw9Lz-!XWzNRk;GDif0luIuiyEnnPmP0L|}?$EKnrHtYG5URN3OQv~ex zK^ICJ`}NnrZZi~in}zH~UYb>V_7c@^GX?h_=~p(1Txff~fSi${! z`Za-+8!O(RFE^VG^cFJebLfw!{!Kf!vX?Xy z#{N5aCM^7Sn=|42MB3+3y&~L&4i?JJBu!?-Rp>wmV&_vp;}ohS#WiFF4Fy9e0@9Uqq!=9t|H@Q&(rr^n_kkpE@aaI=>NY{Kx=lzCcO>YT)kOJ|_}UPz zfFA>7X2n$Tt!TY`ee-eJt8U4XeD$6VmalO?v?*WLS*0K_;U92lZ`cmUOZtC!gyaV%C{jZRQjOAx zk;ov88v&u}?1U~xagbHdR7HXm!Ly6RR8O4>W~%p2waHWiBs94$5iZ(+jCF&;SOYbT z1?cw_S8Ej#@A>a3#=TEPFq~WCC|c*kKP(kqYTv4$G)O+A_)okRl?T38hjPpJZ4RYH zLS}wz$b=q7UXHw^45dMwAFm(EuTE0JG|4Yn)t(F|qjqCfd6xUAe!F7m&>riRR61I!h>&v%O8Eqi~dl>y; zl?Aqid?dnty)*3J#ES1E8I<##UIsn%T?9;fGKO~Qj!xGogIr37*2^+zIC+B0wZb@u zc^cF?*YHOePhBE0((DVVrPw^uvNo@NhWN)xW;v>olKiKmn*$5R>?rH!YQ!b?wG>*6T|N`j*%Y5Wr+kOaetB7L@Gz+aLa2DHZ?01pkeymYFKK_Yt!^ z8jmem-f)R;9Ssg>*UDO>^{#l=q)x#{P0AGfiVArv~60I~QOez}=DpSFjDJ^aCdf_DkyK@$NGybBr6A?z8xjT6d1BEwNH zUp1i6j%XLn#6t{-%(YfH7gilqxw*+$5&|stTEv66~WfVFev^ z#97T)+%RY)CNJBYic(#0U+*K(6j?OKS}2dKqa)VZJZ)~K;HQOu%u4P0Fd8pWou>md zUGGV5ra{S{az$B8Um`pgHHGn@2fDypl*xj}s^X3Stuce#c#@esJVadwaKpqcEhvcO~pJs#NNG`ee=qUfZa>+AtIKJ4rw@VyoM@Pb-QLZxNIJm*Zv zUxxX&Dfzgw6fZ^5{5v3jIpz;j@^POg9+e=>bM}G~Q?bMdr39K_i|doG6uefIyj#C32J!Xap+`P)cAM zESAVqN}$1!7%!Drq_#0mDS`GsqL;jBvPh*?zLJmTK4PtukJOri`Grb88peumm}CeF z4pWp8X#XQ_kV-sEa9D^Xij@+0-6hT=Fdim2+=cmfEBR=NC}vCfh{GbxAEe~tIg6O8 zKtLQOV2SBU3A~sVO;U+RR65L2O5mNOc#=4BFJ?T`h`}Kp)ul=qG)xjdk;~jh%akx4 z^#2z4WlA};M-nmGnmkn}HBjDuEBupHT1k;&U~i;Ls9ti8ZIGlyriBP#j4CxDLTRz@ z5=9}+bj^a23NBSxg7iS;Glfcz6!Abal^%=92uw!WEmvrQhRLGKKu2JSGntHHCxKtB zl)xJ#-yE9VoeUvluT`?qvelP`*(Id*!k@5lWMiu;VotT|(XGnE{}?D{)h1;0h9hy%n`F*yg&bDha) zB+=dFm#JFY_l*68j=^h&)^?kz>Nq%Pcxuh*v}O$Y$_Gt21{-kzp1$Pw0|lHTO%wj2()Fzbl2z!&V@oAi9Ep>(H)yz!0a*z1#h{VZz`RR53<~(JjhZqI%78U zV6Ew1=TLV|6px2AqquY49t%j+l(#h6H7Z$2bgR5UkQ5ST)asS-kHo zCpFJtVLl$VN9e}tOoQ@dgX=iQmSJlv#&GfP8Xc=sZBA$U-tt3CPAwp8^=%_z9%`9g zagq=AP)M)|E6{7ws);|xjc~NEw@A+tt~AoZOXk9Rn)EG zPT&L#b$~571a}g7hdXtU;7+DrL&z2WAn{Br2|p>9>qT=@1out!E0vT>5qIm$F*J9q z;I`2(*-+$JeYwswcevp0LccOdx#8kseYtKlx3A#tNxue=a(%@-eYum0DS}ULiqIR% z36t=F2McH6>eFi7jft@5_?1i#8?!6VguGuX>9)Tmjy!o$nD(BOwt=SMVWRhCDXoO2 zMPu4#DQy-_iyMR*ovlDhyMd;~VOoZimO#_uF|DtZ)=b=6@;YFe zT}u0rrdct~Af+9mX&o``tfb8DqG<`3c3evPADYHs+UHW*Gc?VHY1^f=^)xLJ(_WO) z9)UDrQYVSB6H@IMRp*{73w;%EKw8f~HR(M^${m3M|zU60- zY8XmD!vl$wLox+-C;BBDX7z{;;(;#A`nNCZdEj$NO?~FF$^+Y_wDp%&9(Ykod*rgp z0~@8ZdoQazz)ESkmsK9PPf8nnS>=HVQrdNwRUQ~FrNv)Xc_39vyVR`mfK5s})vWTs zl_r|Dzggu0uax#tv&sWUq_o$YRUW96(w=NqdEhN6ZB4Vv1J6lm57D$vm{u;OO{Hm_ zF>Q&ImPOMro}G7wls1s2b-}c;Qd;+Bv5%AO) z!c(=#Q>gm|@JbxBetnakSDtH>`roATO1YFawMpfbB~n^elgcYIq_lxeDzA){(z-XP zyfQ>ei)m7MB}Ga*->CA6RZ9D|5os4sF-N-ny^$boCqc$ApuW4NLz{G4bC$MNYKnkv zqY2&a{#jXfY|^@8Cs(2sO}e$F51p0Cf_oVK>PhBjviPV`H;4ec8 z@d?WH7aIKjjQbgn5B`EaF^KWxp=P)igS^~98Z(FJD0w_jz5n&mjy`5=qoeZDi5`8AYhvLcq?=KO8rZb)`P9;S%;Q zEJ2mHliB}9g0f@UK}@6A4S;#af$pRCXV=A(yn9{cu?|XXuzSqhcWKAcD~UPyD6)lH zz<7q@sP1>IGA?o6iV>v}9AB~b;LE777-lDlI|#q;ayh0tqsEZDJ6w+O&JpnK8%pZ` zVjux~CIF8iaaWnRQR$VA%ZvwIbJ7o`?{yqxJU5~(4!)qneFd3cvJR>u;`<2$QCfhm zi27qQHwtQ&`!guetB=g$EV` z`krNWF_MCu!ht@E6gidBE8nCfB4zho7e8;}& z8ok8%DwKn2U$cF1s}hTW$VYL_@H^Qx0tOa2Bfal)SW0h`0aZ73@CTlEAUNw&2D?eQch?kk7;y=_v;$<$C4!xsrhqx>WPru7g zkYiZ7BNDTLZ7~4DGR9L)55r-f{}K5zO{9Uo+?7#WEOh)|w@`Ntw2|Z)$0RdT?!v=B z$6Y{HYIk7eTGIX8x%5Nc4S%Hj`VG+}!=^^p3|jK|ALtDFCR%@nW6@n}S;M~6S;Rc2UHCI5QT zcbnEq2Ez&UR)gGOymkymu!n0(r)oW-V04Tza|f96=Lo_uVvl1-$Y^0?Z5Xj5FO$%k zcC1oIpXp2v9yR4fu7CWCVttdjwNbOTF={jjWD!Gn-VMUdz%B|Mzf=kSJwpQgmR7UW zg~+t47ndDk7jT zNSvKZBr_p)B)*?q+#&@>n?T;8iX{<7VeHEK(FsEgE-|theQxh~0Z zi^i}BsNl8ZrUB0a_|=R>B!=YKlxxUg4$@R|+QWE*fLF0J8>1**l!}kbRNO#_o$d!3 zp7NX%C_v6G#+K&O@`+@l4qj1wyQa(jUSwtTeCQQ##^jo1=i3ACs zeve2n>ZyiP3@Iia!l=`JHL!3d5$CDs$X)HJ`6pqW!q6Bds~Fx%Fsu*2P+r+FKyW~K z>{osW;wL5kt>35|mM7ptaLvv*t~rZK1g*9iwA%ByFJ}j!HqGoB;jY2QF-v=8(e*RY zag^;!le6%xxu3>y2YvCNS>r2e=ecv_bsbPj9S3OeVaIu<9Cv;A<(KI+( zK`zao3y9fV!yj=bYI}GyG%^-4__g-58m9b@l9DeKAurVxLy_e{a30jcIcAXI+@cTx zn}nTM4YPHRaZlPYb{xJeAycE|&p{1#)i$_68VIODsWG|G`})_UfN_nP&qp)6{$nf{ z@O>&j#=@^edQS+%Jaj0;x4%{ZvDXKXJ4=C~u+eDH8hjmf@v?*C!|lCnl;gv#J$5CM z_>Rxg8m<)OWAPoEOlw+wCOOdj z!br@GFyMMBvnz?KgN;Y}UUy?W^Hi14bFbkrvumP}t0mi!_?;LnyAQym3ZqUnpoI1=A0a>U#wHA;TAt8l_aHHERsDm8Z;xJsXQs(;(X%vQo6J5`hIZ zDNLn$KPVUzs(NlLS4EBr;yS_!i887b8jOOX(%T0U$!m|aY$ftsZ7)-D`ci9@Q@Ax?%eA=zqDAX{lFb%X4X zY&9u5e5LM?9g>+Q#fGoc1F|h4E5(Jc)DyDfLsse#zEUs9wuY?KF?^-#AUh#cr938J zg6ua`@nu$dj`ZFHYQ;wKR7z_1jT2IP3lpHN9f_M@auoPCrU%Xs{3nGT;?oHsxbxJ> zkRnZn6oBMiPBr*^m4jV;VboqY+J}m ziQy}yKz65)Gplo}Gwb?*nRPwPtQ2|uX?=bLE<*bGHZFL+^~L!XbK)X4h%-)_s!RT5Q1$0qWe5zd>va ztFc}=plYlSOZvR5XM;#6u<|Qxff{z0rryysbwi+roqZrk`yB(Te2De>t9pf=kME0! zo`0&>(KCFcaz=yU5=u)9R=xng-Bl*+bC!i)g$n;&K^v^#<|_Ax*Y=C{2lcn`DD7|H z``Cf~|5@$-m#y`G5UDY1UG<-^Mwyl0AU(EfCy%Z6<)@LUG0y0y5@wt6%`s&BWxzD# zA+=keKebF&70eXq4|k!!Kg|2n-)WCxk>P%cA$LVqzB9A|yF#u*wb|C!wKmzn7VxE3 ze4`KzXvurv_!JzVFirbXc%qUsO?oR_gAv!V><0ci+#;h9+;~J^&0O{fA1gi&os&@{ zB*&JJ?05ZLAv@G(%H3#K^BK0o+n_oJ^P_VLKaK1=kMU4oCw(i+CJ!g$z6Uq2F+7`U z6;~NmFnKDNVct{wG_)8ILr&$ad?KNRm78QnV&D|XBxaQ8kPkI20#BUs@m38a3^XUO zsVUQ@dY{ISJV2P$slAMBS85Gwm!Ofy)a#Hwz{FDt6B8;}07YohcWX#8WbM-khgYIC z_;EOmZE5F^1yb{rNug#`6rrX%Ph@PL z)`GDjwosf;z+*HrZIIDWPV}VZqDFC}xF(>7_Ef?`fe?BGLl~?=z*0;(i#Ia~&;XYN zQY}RzA@E6dY^(?x8xXRwAHL9_+k&siKv_N>gvG#t15@~Tca@oom(MoX`-x?xEG%R+ zL$}OpTmCvqCWJ}^kRQo~Ui%lJ=|Eav9hL~UsI6lurhGg?V2}t?&4daXra-CIKO}Gc zxL1Q@A~w-g;j2iPo~uW;FPQ4Z2Y9ZQ?ZcxrNsAVGNKv#H!tKFxhfTGInL9CiwY*|y z$~y%#76WQPU&bS9UR(`H?@wzr7>zQ8W$T>Uz~MCOhch&@%&H9-&b=tO7+}K`;6of& zGuIWy!@UA;Lz~e0wJI7Z0d2QN$QUi!h&H z%VUjU2{NSSn)o}vCV(L1UP;5>+&N^=C01qaDby@UO!-laIUl2CK(a82yM84$3l{Ib z&#usqSN2OEzm-3pkUuucA8X~0+W4in?89u!E@~>?9W2F2sSpG-Mm_)dtTlZ?Ip3dlhU!zfW}-~wTFC`n zuGJ6!@wql);goA5zoaK*_)HslzBD7%Uq{r?1WdClX;91E=x1%7N@prLzRxv_mox|B zQMim?bZb6FJb-s4jV5OOKk$sqNKcKEeMxjbk%uzG(Fo`<THW?-~zIE0FWqR!k$ZS7;+Vxe{cFe99%q9g|!A<8}X&YLSpr5-)4}W zK?(8x&kxG@&aR3`UoOQOGrfB8%^{U0zX_ZPTbQ7eNkY7W!DB5ebG^bM%*6`>T-ZF>@R$)VmYN(+=HRs{F! z9u2s^8WnCxOHsE3nr+bZplwj-W?$DfJHx2IaKM?2A~1bV!2OGsv372cX5-p#bQBY^p66%8guNqbvI*C}QLq zoki%dkcIkeXWqm$`Gy9r??k=LqPPt9_WzXJFd;f7L%# zPWCc*E@I<{Y$yGmJe51v8ZjKW%V}oH@AMO=Lt>-I9T4w8$G0Z#Xd5$H_@wnwzU6b- zupsPx>4*PR#(VLH5si1nKZDL2WB3@ZK^;j2zyEx!nI3QBNH%EB9P`Y4NyH3eYK37o ze5_%ZJegt0!iy|}#?u<6Ijv=yzIy%czs^6tkN#igpZt$n=b!&nwaGs#zft(-)(;|* z-+AB2_AIWoRuq_QmQGm-ma?yZs9~coRV91G2t}n$%?2IDkWbT~zu}6s=*mQmu zS{9Gog+b{V&ua$BlIAgtKAv_!*zhv^b=0!M1oLR5U!nJ=owU0fumtS7?iSq!Vku`` z;`jSX;NwCW2_gGhdZlkJZf8hUYk_zA2c#xIE%IQz6EmBHYi%LA^4Ps)9}ri5yV5q- zj4u`Y1?x^BV+%*n1-xSXF&(ex5uUWSJ6MttU4>B_A@hKZLoS(;d4jPCbz$1+3ZwARI5LDjs)kd9# z{KM3)@h9mG2jc#c;Ft&_9wa=)(wf_O4*a z)j0mX1g$+V*Mi2%Q_bi}fY$4Mh{5uM=c)BN8qE6+d53~tpuF#^Tfb+otEu@1%!YLI zx#I6Jr&l^IFy+k!1;%;1|I;kaSmozf>0D+=eW%F zVsU?G{D{+xfGdzyu|Yq zd5MQaYMW)2BegA~Uv?i$U~UO?N^_v;gT{Y~yX?K4KxfATK)d2SrGvf)ADLEN(+Knm z`VLUMg=6Dw+>8L1w9DQ>AL;$2WNBD)*!bUkuQ~2rbt!Dud(Ey7uLQl<+=JlSp7)x+ zI;7rzz8#T%`=>)>wO9$1PPJninwuWLK>T@}42YOY$ zuDk~LE_tjHW4!a5`SLV;4N!gs(AMhHP&aR<%=kb+aCci62T^;dr=ixG6cyX z0PPVR@d+OExMDnw$#QVs)=_$T8%60zayw9(5+kEDD@H7=C19)F zi-b~fdr-Pf8QMGKp>66Sp;X_6pyXscKX!=>rS)$~{ytsWfl@DJB>TuCxj;r~W*2!R zpLRFJGZpz=$VlFO6@uj3KTFXv+Jocom63cy9?3m+3C9oZGLG~G;WzCB#|c-#Z6hQc zSJ~TvW05knv*n?^PR6l|g5wA7rc|aPn&Prp zon;)+b(^V}(^axwO!@7EdL^(0jgrV%niv_Loh3Y{v1 z=TA171z&PEB{3D>+Q>ASaTU{K@t>qHGPZW$xK+XN6&c4Vw#aDo^XnA;t?hw-Kw-7x zvba0UL~zXX33@Xqe||;ke|zA6qrm?`>Ay9? z{!8$;S=#~sW<@0$B&$SIB830*AEo}c2Y#Lcf3gh!aEA!{FTvl|p&jru6!^JH|09I| z^B<)Cw+H@T75VpxBLCte?7swmTYNj6O|Zo7OFauWIre6S|jI zGFvM>mzb@4EPFOSftlV;s+E)}w^k;&FGLijshqVO9n?STKO0)M{@|3yoL{g>dcXb=3a z6!>1H{}IC9`FpAVvF(5_D)7%M{f~{X{}TKa?SVf^5!+*BvE5S(-+Nwq12ZNzf=$G0 zzoRJq5OWnMbtWhs*G_@wVc6=i@Sj%T|4xSgyg9=DOYoiTfq$1m|0&A& zM+pD@-%9d*E+U;6JVOKSKELKQHy))DHOD6!<%p{+lA~ z|MQx7N7oAfLk0fdl>SEu|NZBr{u|o?|B3=XM%LV(H%8ch3BI#E@H;7*V^0}=w+P|C z|E$!1Lp$LAsPzAwGX92E;VW0jLkWC#|f8Qw`8e` z4b&R66U?&cZ2Rc7)@Ri8HDjqZbdT)RG@p?eOlBvZ|bKjZWWZ2tn? z6Z-~%cyEga#3_Rw#7y7hpbBnng?9of42%RPGM=0A%&9FIS?oBCD-}$v7+@=3YS7pv zs6e5B-Vie74q^zo>MHC%o(<(6(Cr=7{&90e<9lX19p5&IJn3-_&1Nd&h`#BO52Zw> z=&-X?d`ttSfzDE(k~u|ky96>tM>v_<>`|E(79Yqq)X_s8;ympThn|}Q)#ljD5Q7_$ zOJP#I;RHwM&A3KVN9($Fxen zI|L2=@&ab|qwck6K8|QmUqUik}p-Yk3(DTD#Q#;xIw?n9a(B)$}u1&YOZgP z$8wxS=xeH&kz0uw`M@yt4N&b>^@tjjQy)mh4ZI!{6!uAjgjep ze~EB?T+IJ(k9T5KL9{pCN!6xS;++(23XcErWXS!2_-8f#T}4Fm=>x1$OzrV|B6FcX zB|8&`y#qxU-8;?`-|qnVzez*jSMcoSJR%O&QO^eTn&{c{OXjddO**Y*6Ez6ZaNd zfOpE4Ef}7F8^m2e`B{u1jjefHBL{y*uCj8+xG$LUod)9TVl#pyu_N-%d$E!*Q4&`j zL0n-}Rf}(MD0y|cLNBib^tr{z$&5@{kXggr)h2Ej3215|VMa1GN&-tW6+0_FrhcbY zo{(t9o$UCQDZh>SyU-Bt---j!-{k_3bBZLXREiD^>4`d}LPJ%rQK9N})#l_hKL$!M z^QAUvAE4OyUzKhch=^KRXUc2GuiPze9G4f^r?)X@5P+OK{*Esp&GlFE)a2y2tmYS>A{>p@}3 zRszlDsAvR*p8CoiwDcV1wdV%``~TO}{r|ei_W!R%xSqe{4%~NL<9Z%mS?z^b6 z-j_J>k50J?Wjz2^FwyJQt3+R=gEK;f^I!1GesF!z4qNBsXW7)+`P}obsPP}yh8)iT zb>hKSbi)}ROlvi)#oyP-p))u|JwvxV%fP;I{*!Y-6xvx!=o(6iTHV9mwGe7}(cWrX*C{G;msxTbA= z>+W@xc~FDSOpALBuG{~@zJmbCGN=3BG5T)SuGbjbBg>3Oa;rh+Pe`@rja*};!SpdK z`lTx3#_F7ia#a{FN%T109cU&VqBnS&vrT^JhN|GnDkiFx-j|J(?)#myIxZ0;a?RIJ-X5we5S?S7|m2+6p<^ z3ddvo{)ci43cabTNRgenfToxn3hMpZMhx0UdIQvl(xH*>R?Z!21CDMrG5=YG-4E1wYkZ86mZ)W!fN-d zt9t82%4#5tCtLXUo_GUaXx;ooCHw&`dn~Z|m05TL(u%+K!WUKjXGKK&?_n>}`wtM6 zZYkuZm4w_(cER$%-k}YdfiY=s3hw_Z&9M9yhlPa8Sc4H3a_KdWP?VZnFqvNEki)6f zsrIXk*PpUV7q5S4K)n8UR%+t)lbDZ&kUq`w(HU9%+vj!bPxzn;%nA+h1#i|;Fm7$D@fV(dPStPDN$)I|k}(lP4c`{&I;Ixd>?Fl4x^VmZjpvhgMMv}$%L zN(#ZA4qznF5ZwN6wC%rURN5!>oC@@`7kV34bJQIL_$;s4@!6#EUtLITAW;~G6okp#+;`?{+D5nI{8e4%I`&T){Ig=?rSf#!$DuA#~i?X2%SwE<#2GU4#q|a}m-vKMyM{-~`rPOcRT z%JKuG)-tw4){;A*&fO~%=$YC^qJu#%T*k_cpsW^;hf>^=wT)Cpyb0JGs;zyCRn2|H z)ocRB1U0oz)6^}bDJyo$!b0z8=N2nXbky$zVoEjVncDrpi(B;jf#Y;PP=6KsfqS;7 z`~O8@&(Gx2{YhyntcLCtHb2`3ZxEMS9p{(b%HL(-txs$!jCM7foHy}_*y}=nC+M-S zCluk9*lIG#`kH>oalYgr23;vX#5`Ro9cgLK_q6aneq0CdW(D3L8D0#+>m$RPYz_mk zE(l;q`?B$E!i&|zv$PN1H;++UfgFo_CBRF?z@keKUT3s#GjHK-Xe3bJpKNt2mX~N> zw$xTLMg?}*cRCFH9(_#LpH!tkooRoRerPN^gF6$x{T`9FZ;!nFfcSrc8vk!$Wbyxm z!1H>dPtZ%^;2417Z?u+4M){Js4A1Q|Ku^q7w8Y>`F5j)8?k|bHSVpwAF{YI}}Sm^z1Wcp%c=c204I6|*84k0?D=Non`Z*r}U@{e-n z2+NGzF_1Toqa~?E7(OQJC^t>UcXEOExrbCicOSG2x?>8TXU^nWxID8jo;wOt!^|D! zj-#T%RS5;HZjZ)26ci12RG=pMB~*+wQuD%squdoL>B*dlWx9*zYyB}pgI&|l(SrN7J;i4xf8mI)9FD=g5xQD z$+f%xoZA2S5#4u8jcC_D^#ovwz#D<0oqy@^|3^jr@H? zBY#mjn!Rwr2y$L?{~`>8nKFI;BV_AtRfO`-!9saJD0v)e|Ng#4A{XfG4Seb0$LoXn zdU;GD`Trl4#{qlz&^tZbeCNZd9_E5TDq~P`Y z+Q@f?&-^CDd&dfY-|Pw0FN8J3CQV}TK0zpLn5$v&b<{+PfvHH$XqYh^<6dJ2RyG;~ zS()1p+?uRt2NFM55sMlNK0{iRYR$sYImW@)$O1cefcrYonr2F{eH5{c3dP@6-qZt?r0gkEe-B>ZCYCztQ?6wO)_tD9HsU&T$RGuMQCeBEov~xK3daQl*0^4)_#FZ zPE3^g-yiUR0+NcIdB1uO->L5CbQG7k=&kd7}=?+sas4Nz;?~i0Q-=NDu!Iq zl6`5)+{KT$V`HS2P3#P{<+wIlo~Lbjw$w6Sl+LG~KnroNnzDTHB6n<@)V^7Zd0Xw9 zwe9;2YWrj_47=I6*nY|UWwiZGnJF12wpWIc@jP$P8Uy07Ob-HQw3>(p+INt|nIVB! z+!t^UOvwfS`|LE~X8HDz)e6*V>?8?aQy-~b6z-785HCsgTtcHM_D0q8NMmQ+QMI$y zOmSjmwe5ij-qUrgQ{~@`$n1aDwd1@i_!i@?*&6D-WiY6(VDO>d?3fgRDet9Ot=<33 zx~lu1SwXiKy8HI=3);H>S*zavOmB_8naceS*1*R&?EF$Q>>umdMAz^Vr!|v=CpCVA z4w{hI*EM{qGhRw`e_?{8F0SF@HAzMwRf;bL|K;kr^J#nVkuL<|ZZ?6=2BpM_Q5au2 z8^0M3J_YAmVO;E7jVrwDFFMsMWCez6jh;#URbvC<1=uB@(L-D{R3bj3N$4}$vnD%9 z=QEmQ5!{c*kuRIzewKdO#oZ*_b2j7IVIrtZVmx?UNYLT-dv^`NXd>yA9zRoFj*reI zjht#`%2&dtYeWv?S%U8S=d!pYeuoBiy{qlG85H#i(QTlPDBEaMktT{Vw>rrt+GP|w zQxr=XPn=0YkuS9NFSJxOoA9M_q0kP0dcv^eyN2gD$BKV6&BuBEEcgrg$l+BqDjbG{KOYc<@XVJ#9Ny-n6C zG&}0p8-P!lax}tm4PWlG11I=S2b}-l<5H%Q6lRCb)jZkR5%?c!U@Ur)GRYZ(DeOu> zV$U~-He00d=Mw?^naX(XLVXB$bjRIv6fp30FpnO;Tg#(^$o-HAI;!C#Bi$Pfz(Mmd z?;3rkcX8?s_y|{BW1WVR`$Ch0C?^jgoSZ6@Fzz4g`48og)aC@r8uzVhA)I`Rd%p#_ zs=I_+Px4fs%E__F$=QS(Q+ydRKb@UMOaElh$Fa66&h!|}JjJ-5DoVfV%XfJ1V_+)o zL$0qEN=#f0H;CCa+34O=hgR#3dZzq3$P3_4W=9OP5YM<{@KVV9q%hIQG0d(cp(u-1 ztL64PzZQQY7?e0IuvY9Q>**f0yKBT$XAC5`4}h}5c5satFa0#)`wGYDEKCDIfy>X0 zC@^3nN_N1?ILPtkaR^I>k(c%8fZ(3hd!U#y$IqtF!iL71x6=6Xo9>R~YM2iSqN`zq zq80%8J8qnjz+m7Y!L?HzD-v=Z2FNZ}A*rg;VRkrboVST<5z0AO{?B2lv|2|UAt~2F z$XgO``~o&pN!&rM&QZgZ7n+E4v8FZRg9Yn-NTAV+84ucEgZ#Rm@f;^#riU2Me)1JH zm+^c~zRXJ)&qw4dx`gp;Ctop8mq?Peu`J_xk$hPo?MYnDYvQ<3^wm7GqY)->GC{1F zAVyyt+GIjTkh5q;MQ`jNOM{{s8Lsy7Jn?>pw`>>v4CsXu#>|u zsM?o!(wDIzI1wd>cq@_9n*E5)+k1M*{YbF9c#W0b3rVYTH<{WL!mjCazYI!yn!gaNZSk{=Y0j`{r$ht=l)xoxcQ+1s+*Ef5m^zzIkL} z>-(*5?rvkhwXj6B|C|_^{bxy_{d%kCxz879s4`1)o=a`n`%1R#6X&-DlfsXa#i^~H->zJu-hWNFrt@3f{r?i>Y$G$YEo*qzbxlZ+k=&;fG=yDFj)f%wq~Qqi>}tS4tNrQ@T8p)C5=^ZfwA!!kp!M>2txa$Q2d(z2 zJ7|4D+kTOz{cs1Z$?`$#?+jOQ&^jk1@awd|j~RjwT1SMec4nNW+RFw7=itLu_llkd zSioEG{-0QrNwF$o2{j03=cz3Z^9tisQ-E=N5;4@Ya%lWd9$x2{^ie`7E5_RdwtW9{f` z+OGucf9A^8`I`A=Yi+&-#ebM9&mYfTHja;Rtv32+vZHjI89b~{j?oNjKclP$$V*il zwTra1&#F_=Y?&^vby-$^l?_;-I|inOiRaW!yg|@xKIF{y_?^?a8r~4d5xIJf7#4)W z!A$)+tDU6tGv&3hZEoN+?cAhvV`e~PS$+J^vEl7G-<+e$zdIsWUsuk#+VwSP{O5#U z-*C|_-^<>P4cnDGGc{I9A^EY8pM?4OO1_2Uvl(qGlM_a3_+Yz1iodeGukZG@32#&D zvMXr4l#NDW3Kg-~3Lks#-BD`m-KE%j{S;rEC}k|iA<)%QJ7B$*gENg@D#Y=j2*00lS(F%p6$elTA>J0fuLVnFuv1KFdziyl;GuC@;GX#@K5 z@hDX?P^v7Phw<*BxOm0UeVT5)qoME2A+U*4TW0UaGJJw=&OGm+b7mAbifh6l*9P%g z9kR(C4y8#f!FC`W93^)5`~BW~#~~%uE^B-lm6^QLqUDHbT8_xI1c}XQTCo`r zz(En4itpOrhO6f|H_+e>X`0{-(*nh2ac0=~W#T<*{KugY$b%2>X|Fser7gHt*bI#4 zulOWWrp<_|`w}Z33wi-X%8LOqcFQn1 z*I=Gmn^%s(ypNolQOm@A}Dz0D+ zUkgQvrm&2(T5X)Y4Qr8^h-Phuv}01B4$JM@Kpi<27%qdtS(jl6^j^Y$&cQ!E1D|iH z9%BRT)>`2GXNtk#{@fb4UI+5S1JgA8@Cltlge5S#JB&85tQnH(uY>tU_@Q%9j_=H- zTpWtqfYhBZ%dBL6>RDx7nSoZ8pf?Q`m?hE&+DCdpncZ6hwebp_JQeDNxq(fn6toH>V4{wm} z$e{IUQ-yh{b-dF?BI4RPXFYV*bBNEc=Zjab90H#&ySTD5e8Z~bZ#WKF z?n8!#ueqZh|H>|WPJKhMmoL7E8E0w6F+Tq+Y!`<*&MgP+^f-6E;heY^+5tp5py`<* z{ZK;#SCxKT0TQw_*8%s(=+_-tt+Uv?Y{9zNq}T;2;3oXJA2AF_Qm z2_rxP|M+61-|2_kWnKfbbq`mER*l@ThHp9Nao%~>eaz7C9anaOFRQ=Jd4hAEzOC#y zS9UTg=Va&N(=Zr=X3bVd<|J~u)57Q5xSWgJ9zF*~$jjx|dn%o`I}R@IKqyyD20d4)*Bz7XflDl9+U;TErm#Fk>osLf1wZU$^sOZxH@v_33*ZW!`0G$DZZOc3~5~ zl1=#+2@(63T|9h}tA+vQnvhr*mNSp$T_>*1}V-CLaE;ulfF0olFyXBm#gQ#fIg>$AOM%+ z<#TMD^CU1RKmRPpTc54BR!jeY)D0_~yLqmUcrK6!<= zxhu`S#hY@DxKA<}*3w*NMgoK;*0in9B{?&Im9My%0J@%eu=Be#$>k`n*p+6rHSu^Yd|6(G+;WS z>K%wkR_&Z*G!$2_yAo|Mn5);d;2-XX>UF=;-+ubX6hr<*(LYA|$3Xv}4ZgK{orV61 zqkrP*pAPhomHvsQ70mdDUUhii?v8{S0yq@H((3w{wCPOX5-(-W&15@NXD%^7w{Gtb ztMyph-Bd(_WS$Czr+Al=$_*2Z26uDfnrJTr#h4xMb;iD28Z$SOH$TC~x>hGHGB{)1 zEoSGpykYt*WsGhkwLhFFk5S#Ftht$7@ewx0wQ7k0lvEfTP+>qC6pRJ+N60x{07>2) z7zbEF(kuD0IzGRSw^#6GM_j9oiwyjb3O3risUIvTWk)=Rn5|W=)v=2VY$wz0$P?5b6Wa z(ktC70i_-V1rM41&LiHRT7W5>b!1n3q<`+%sJsVZ4WBM?BCK39`OLBO6KGZpG`pi4 z_WHAYJR-3HC?MPMv@8Bio1+NTfCQ}7wb}$|M{`5g`{H@?dRLR#`8794A{}jX0v!ko zY7<%aRe5`J#+iJUl!`|$T)_lQ@dEX81|9hKlM#=RfQOKC76t%`YZ+VMz2z3vF>UFG z_?cHgLCz_@xRu(ECC`+puB>2?8UV; zIs3>uSAiZPL!PZU(!LaJ3dZ@?yZ>~S?G!V1AutTYpqye7Mb znEr_iu~_r1OvQA}_~fac!(sDb@9jT@OHHwb*|8nZ3qS;I25y@?8N|_KZVy+F{MV79 zfGQQDaGI+i_;w|o8*9X;-^#4aw#P|t_H!R#uCE*O0cJ%7XF((4H)x!bZ^a1y&^HdV znQddQD7C-gi|cS6_H70%feI7?L)|a%YZN^|pgIe;TCdB@<_kMki zZ>88qp!k?;YBJ5ZZ{uuY4LbOg?K7|me9k_8J2D*S+~@1K?kuj-LUtIjB!3^5vyaVcN?~rp(}W*eSY_UdEBd)-6)&P_#tbkVww1a;yRZJ3=dv z9`8hZZLZOGlSHiyg3$>W(^3YtefvQe(kL>d*k~`v26a*V^j9oKYQ#5E`rgv0 z?pTV}Lk)ucnD`A=qzE2tpq+>AJb@j-M!XHuAX#xVm42zsQHqEuMya2tz3(@uBstCP zXSS`=lxs97d~kmQ<>GrA!p`Li+#&#$zQIzRfeo~8g$?2Rw$&hWJ~F9jR4G$`Nv0)J zvAcy}N$DAl1^?WlP@)D4qNYhkHTOYZw$#GgmnhD!UsA|Ye1dnqMP@2&O<jLePN9FGBOBPFGVr zQ~o)A4s6y+Q0YJ&PEru=tCtP#g}_M!aRHP$HB5((OoW|ekzHFaRh zH;__RrksNh@eia#g0LixDR+|`hACf#ITa+Q3sZhG@N{V(S5qgZyxE9GXQtdw zKI}|+KPVzjB^A0c<+UdCHdsOMPZIL{OnGl~(`xFcl})wGzY=ntO-1;Uu^1!4k0 z>uIKZG-5u;)$}Ce`4C0v*5gS3dhc5oVF0(Dgdg60@X1vd6!_oAJTZn;eFg|dK%8Sd zt|+<|0EJ;O;e;dDM6EXyCgx+ zyBF#da@B>jUw)^>yZ#qHJv$KJMPE76eb}LqE_nY&K#;yw!xA}WO957y1XZFuSP&J9 zzoFmGQj~?8KShw@Lni9WGZX$!5`TlEzM}vM1!K;U_8of|0S6(ij^FG-wij>5rND1w z9_vdR!cyY(a$;waNJ$ZAM*PoS95Pb7t>j`G{w~%!!B?&cVj%n!KxND$UO~T zryn#{iBph=nr~!_T+L6jHdk{B;~5D_4F^RBI#n$(ZOSxenAqN>ww7APgF=_t5l7