├── .gitignore ├── LICENSE ├── README.md ├── app ├── Mediapiper.podspec ├── build.gradle.kts ├── rules.pro └── src │ ├── androidMain │ ├── AndroidManifest.xml │ ├── kotlin │ │ └── me │ │ │ └── xx2bab │ │ │ └── mediapiper │ │ │ ├── App.android.kt │ │ │ ├── Platform.android.kt │ │ │ ├── llm │ │ │ └── LLMOperator.android.kt │ │ │ └── theme │ │ │ └── Theme.android.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ └── strings.xml │ ├── commonMain │ ├── composeResources │ │ ├── font │ │ │ └── IndieFlower-Regular.ttf │ │ └── values │ │ │ └── strings.xml │ └── kotlin │ │ └── me.xx2bab.mediapiper │ │ ├── App.kt │ │ ├── Platform.kt │ │ ├── Startup.kt │ │ ├── llm │ │ ├── AiRoute.kt │ │ ├── ChatMessage.kt │ │ ├── ChatScreen.kt │ │ ├── ChatUiState.kt │ │ ├── ChatViewModel.kt │ │ ├── LLMOperator.kt │ │ └── LoadingScreen.kt │ │ └── theme │ │ ├── Color.kt │ │ └── Theme.kt │ └── iosMain │ └── kotlin │ ├── main.kt │ └── me.xx2bab.mediapiper │ ├── Platform.ios.kt │ ├── llm │ └── LLMOperator.ios.kt │ └── theme │ └── Theme.ios.kt ├── build.gradle.kts ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── iosApp ├── .gitignore ├── Podfile ├── Podfile.lock ├── Pods │ ├── Local Podspecs │ │ └── Mediapiper.podspec.json │ ├── Manifest.lock │ ├── MediaPipeTasksGenAI │ │ ├── LICENSE │ │ └── frameworks │ │ │ └── MediaPipeTasksGenAI.xcframework │ │ │ ├── Info.plist │ │ │ ├── ios-arm64 │ │ │ └── MediaPipeTasksGenAI.framework │ │ │ │ ├── Headers │ │ │ │ └── MediaPipeTasksGenAI.h │ │ │ │ ├── MediaPipeTasksGenAI │ │ │ │ └── Modules │ │ │ │ ├── MediaPipeTasksGenAI.swiftmodule │ │ │ │ ├── arm64.swiftdoc │ │ │ │ └── arm64.swiftinterface │ │ │ │ └── module.modulemap │ │ │ └── ios-arm64_x86_64-simulator │ │ │ └── MediaPipeTasksGenAI.framework │ │ │ ├── Headers │ │ │ └── MediaPipeTasksGenAI.h │ │ │ ├── MediaPipeTasksGenAI │ │ │ └── Modules │ │ │ ├── MediaPipeTasksGenAI.swiftmodule │ │ │ ├── arm64.swiftdoc │ │ │ ├── arm64.swiftinterface │ │ │ ├── x86_64.swiftdoc │ │ │ └── x86_64.swiftinterface │ │ │ └── module.modulemap │ ├── MediaPipeTasksGenAIC │ │ ├── LICENSE │ │ └── frameworks │ │ │ ├── MediaPipeTasksGenAIC.xcframework │ │ │ ├── Info.plist │ │ │ ├── ios-arm64 │ │ │ │ └── MediaPipeTasksGenAIC.framework │ │ │ │ │ ├── Headers │ │ │ │ │ ├── MediaPipeTasksGenAIC.h │ │ │ │ │ └── llm_inference_engine.h │ │ │ │ │ ├── MediaPipeTasksGenAIC │ │ │ │ │ └── Modules │ │ │ │ │ └── module.modulemap │ │ │ └── ios-arm64_x86_64-simulator │ │ │ │ └── MediaPipeTasksGenAIC.framework │ │ │ │ ├── Headers │ │ │ │ ├── MediaPipeTasksGenAIC.h │ │ │ │ └── llm_inference_engine.h │ │ │ │ ├── MediaPipeTasksGenAIC │ │ │ │ └── Modules │ │ │ │ └── module.modulemap │ │ │ └── genai_libraries │ │ │ ├── libMediaPipeTasksGenAIC_device.a │ │ │ └── libMediaPipeTasksGenAIC_simulator.a │ ├── Pods.xcodeproj │ │ ├── project.pbxproj │ │ └── xcuserdata │ │ │ └── 2bab.xcuserdatad │ │ │ └── xcschemes │ │ │ ├── MediaPipeTasksGenAI.xcscheme │ │ │ ├── MediaPipeTasksGenAIC.xcscheme │ │ │ ├── Mediapiper.xcscheme │ │ │ ├── Pods-iosApp.xcscheme │ │ │ └── xcschememanagement.plist │ └── Target Support Files │ │ ├── MediaPipeTasksGenAI │ │ ├── MediaPipeTasksGenAI-xcframeworks-input-files.xcfilelist │ │ ├── MediaPipeTasksGenAI-xcframeworks-output-files.xcfilelist │ │ ├── MediaPipeTasksGenAI-xcframeworks.sh │ │ ├── MediaPipeTasksGenAI.debug.xcconfig │ │ └── MediaPipeTasksGenAI.release.xcconfig │ │ ├── MediaPipeTasksGenAIC │ │ ├── MediaPipeTasksGenAIC-xcframeworks-input-files.xcfilelist │ │ ├── MediaPipeTasksGenAIC-xcframeworks-output-files.xcfilelist │ │ ├── MediaPipeTasksGenAIC-xcframeworks.sh │ │ ├── MediaPipeTasksGenAIC.debug.xcconfig │ │ └── MediaPipeTasksGenAIC.release.xcconfig │ │ ├── Mediapiper │ │ ├── Mediapiper-copy-dsyms-input-files.xcfilelist │ │ ├── Mediapiper-copy-dsyms-output-files.xcfilelist │ │ ├── Mediapiper-copy-dsyms.sh │ │ ├── Mediapiper.debug.xcconfig │ │ └── Mediapiper.release.xcconfig │ │ └── Pods-iosApp │ │ ├── Pods-iosApp-Info.plist │ │ ├── Pods-iosApp-acknowledgements.markdown │ │ ├── Pods-iosApp-acknowledgements.plist │ │ ├── Pods-iosApp-dummy.m │ │ ├── Pods-iosApp-frameworks-Debug-input-files.xcfilelist │ │ ├── Pods-iosApp-frameworks-Debug-output-files.xcfilelist │ │ ├── Pods-iosApp-frameworks-Release-input-files.xcfilelist │ │ ├── Pods-iosApp-frameworks-Release-output-files.xcfilelist │ │ ├── Pods-iosApp-frameworks.sh │ │ ├── Pods-iosApp-resources-Debug-input-files.xcfilelist │ │ ├── Pods-iosApp-resources-Debug-output-files.xcfilelist │ │ ├── Pods-iosApp-resources-Release-input-files.xcfilelist │ │ ├── Pods-iosApp-resources-Release-output-files.xcfilelist │ │ ├── Pods-iosApp-resources.sh │ │ ├── Pods-iosApp-umbrella.h │ │ ├── Pods-iosApp.debug.xcconfig │ │ ├── Pods-iosApp.modulemap │ │ └── Pods-iosApp.release.xcconfig ├── iosApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── iosApp.xcscheme ├── iosApp.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── iosApp │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── MediapipeLLMInferenceDelegate.swift │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ └── iosApp.swift ├── media ├── llm-inference-intro.png └── object-detection-intro.png └── settings.gradle.kts /.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle files 2 | .gradle/ 3 | build/ 4 | 5 | # Local configuration file (sdk path, etc) 6 | local.properties 7 | 8 | # Log/OS Files 9 | *.log 10 | 11 | # Android Studio generated files and folders 12 | captures/ 13 | .externalNativeBuild/ 14 | .cxx/ 15 | *.apk 16 | output.json 17 | 18 | # IntelliJ 19 | *.iml 20 | .idea/ 21 | misc.xml 22 | deploymentTargetDropDown.xml 23 | render.experimental.xml 24 | 25 | # Keystore files 26 | *.jks 27 | *.keystore 28 | 29 | # Google Services (e.g. APIs or Firebase) 30 | google-services.json 31 | 32 | # Android Profiling 33 | *.hprof 34 | 35 | 36 | .kotlin 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MediaPiper 2 | 3 | MediaPipe samples on Kotlin Multiplatform (Android and iOS). 4 | 5 | ![](./media/llm-inference-intro.png) 6 | ![](./media/object-detection-intro.png) 7 | 8 | Migration and Feature List: 9 | 10 | | Feature | Package | Additional Setup or information | Original Android Sample URL | 11 | |:--------------:|:---:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------:| 12 | | llm inference | me.xx2bab.mediapiper.llm | Refer to below section to set up Gemma models. | https://github.com/google-ai-edge/mediapipe-samples/tree/main/examples/llm_inference/android | 13 | |object detection | me.xx2bab.mediapiper.objectdetection | Please visit the [/object-detection](https://github.com/2BAB/MediaPiper/tree/object-detection) branch to get the Object Detection KMP demo, models are embedded in both projects already. (We could not merge it to main at this moment due to its framework conflict with LLM, [more information](https://github.com/google-ai-edge/mediapipe/issues/5302#issuecomment-2071660494)) | https://github.com/google-ai-edge/mediapipe-samples/tree/main/examples/object_detection/android-jetpack-compose | 14 | 15 | ## LLM Model Setup 16 | 17 | 1. Download 2 models, [gemma-1.1-2b-it-gpu-int4](https://www.kaggle.com/models/google/gemma/tfLite/gemma-1.1-2b-it-gpu-int4) and [gemma-1.1-2b-it-cpu-int4](https://www.kaggle.com/models/google/gemma/tfLite/gemma-1.1-2b-it-cpu-int4), from Kaggle respectively. 18 | 2. Execute below command to push models to Android device respectively (must be physical device) ```adb push /the/path/to/gemma-2b-it-gpu-int8.bin data/local/tmp/llm/``` 19 | 3. Move models to iOS project respectively by dragging the model to the "iosApp" target and select "create folder reference". 20 | 21 | ## Running on Android 22 | 23 | 1. Open the project via Android Studio, create a ```local.properties```, put the android sdk path and cocoapods executable path. 24 | 25 | ``` 26 | sdk.dir=/Users/xxxx/Library/Android/sdk 27 | kotlin.apple.cocoapods.bin=/opt/homebrew/lib/ruby/gems/3.3.0/bin/pod 28 | ``` 29 | 30 | 2. Get it run via the Android Studio Run button. 31 | 32 | ## Running on iOS 33 | 34 | 1. Generate a dummy Framework 35 | 36 | ```shell 37 | # cd to the root dir of this project and run below command 38 | ./gradlew :app:generateDummyFramework 39 | ``` 40 | 41 | 2. Install the pod 42 | ```shell 43 | # cd to /iosApp and run below command 44 | pod install 45 | ``` 46 | 47 | 3. Open the `/iosApp` project (`iosApp.xcworkspace`) via XCode, run it via the XCode Run button or Android Studio Run button with the KMP Plugin support. 48 | 49 | Once you modified the code, just reproduce step 3 and that's it! 50 | -------------------------------------------------------------------------------- /app/Mediapiper.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'Mediapiper' 3 | spec.version = '1.0.1' 4 | spec.homepage = 'https://github.com/2BAB/Mediapiper' 5 | spec.source = { :http=> ''} 6 | spec.authors = '' 7 | spec.license = '' 8 | spec.summary = 'Mediapiper' 9 | spec.vendored_frameworks = 'build/cocoapods/framework/app.framework' 10 | spec.libraries = 'c++' 11 | spec.ios.deployment_target = '15' 12 | spec.dependency 'MediaPipeTasksGenAI', '0.10.14' 13 | spec.dependency 'MediaPipeTasksGenAIC', '0.10.14' 14 | 15 | if !Dir.exist?('build/cocoapods/framework/app.framework') || Dir.empty?('build/cocoapods/framework/app.framework') 16 | raise " 17 | 18 | Kotlin framework 'app' doesn't exist yet, so a proper Xcode project can't be generated. 19 | 'pod install' should be executed after running ':generateDummyFramework' Gradle task: 20 | 21 | ./gradlew :app:generateDummyFramework 22 | 23 | Alternatively, proper pod installation is performed during Gradle sync in the IDE (if Podfile location is set)" 24 | end 25 | 26 | spec.xcconfig = { 27 | 'ENABLE_USER_SCRIPT_SANDBOXING' => 'NO', 28 | } 29 | 30 | spec.pod_target_xcconfig = { 31 | 'KOTLIN_PROJECT_PATH' => ':app', 32 | 'PRODUCT_MODULE_NAME' => 'app', 33 | } 34 | 35 | spec.script_phases = [ 36 | { 37 | :name => 'Build Mediapiper', 38 | :execution_position => :before_compile, 39 | :shell_path => '/bin/sh', 40 | :script => <<-SCRIPT 41 | if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then 42 | echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\"" 43 | exit 0 44 | fi 45 | set -ev 46 | REPO_ROOT="$PODS_TARGET_SRCROOT" 47 | "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \ 48 | -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \ 49 | -Pkotlin.native.cocoapods.archs="$ARCHS" \ 50 | -Pkotlin.native.cocoapods.configuration="$CONFIGURATION" 51 | SCRIPT 52 | } 53 | ] 54 | spec.resources = ['build/compose/cocoapods/compose-resources'] 55 | end -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.android.build.api.dsl.ManagedVirtualDevice 2 | import org.jetbrains.compose.ExperimentalComposeLibrary 3 | import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi 4 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 5 | import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree 6 | import org.jetbrains.kotlin.konan.target.KonanTarget 7 | 8 | plugins { 9 | alias(libs.plugins.multiplatform) // 2. 10 | alias(libs.plugins.cocoapods) 11 | alias(libs.plugins.compose.compiler) 12 | alias(libs.plugins.compose) 13 | alias(libs.plugins.android.application) 14 | alias(libs.plugins.buildConfig) 15 | alias(libs.plugins.kotlinx.serialization) 16 | } 17 | 18 | kotlin { 19 | androidTarget { 20 | compilations.all { 21 | compileTaskProvider { 22 | compilerOptions { 23 | jvmTarget.set(JvmTarget.JVM_1_8) 24 | freeCompilerArgs.add("-Xjdk-release=${JavaVersion.VERSION_1_8}") 25 | // freeCompilerArgs.add("-XXLanguage:+ExplicitBackingFields") 26 | } 27 | } 28 | } 29 | // https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-test.html 30 | @OptIn(ExperimentalKotlinGradlePluginApi::class) 31 | instrumentedTestVariant { 32 | sourceSetTree.set(KotlinSourceSetTree.test) 33 | dependencies { 34 | debugImplementation(libs.androidx.testManifest) 35 | implementation(libs.androidx.junit4) 36 | } 37 | } 38 | } 39 | 40 | listOf( 41 | iosX64(), 42 | iosArm64(), 43 | iosSimulatorArm64() 44 | ).forEach { 45 | it.binaries.framework { 46 | baseName = "Mediapiper" 47 | isStatic = true 48 | } 49 | it.binaries.all { 50 | linkerOpts("-L/usr/lib/swift") 51 | linkerOpts("-rpath", "/usr/lib/swift") 52 | val aicPathSuffix = when (this.target.konanTarget) { 53 | KonanTarget.IOS_ARM64 -> "ios-arm64" 54 | KonanTarget.IOS_X64, KonanTarget.IOS_SIMULATOR_ARM64 -> "ios-arm64_x86_64-simulator" 55 | else -> null 56 | } 57 | aicPathSuffix?.let { p -> 58 | listOf( 59 | "MediaPipeTasksGenAIC", 60 | "MediaPipeTasksGenAI" 61 | ).forEach { f -> 62 | linkerOpts("-framework", f, "-F../iosApp/Pods/$f/frameworks/$f.xcframework/$p") 63 | } 64 | val swiftPathSuffix = when (this.target.konanTarget) { 65 | KonanTarget.IOS_ARM64 -> "iphoneos" 66 | KonanTarget.IOS_X64, KonanTarget.IOS_SIMULATOR_ARM64 -> "iphonesimulator" 67 | else -> null 68 | } 69 | swiftPathSuffix?.let { sp -> 70 | val swiftPathPrefix = 71 | "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib" 72 | linkerOpts("-L$swiftPathPrefix/swift/$sp") 73 | linkerOpts("-rpath", "$swiftPathPrefix/swift-5.0/$sp") 74 | } 75 | } 76 | } 77 | } 78 | 79 | cocoapods { 80 | name = "Mediapiper" 81 | 82 | version = "1.0.1" 83 | ios.deploymentTarget = "15" 84 | 85 | summary = "Mediapiper" 86 | homepage = "https://github.com/2BAB/Mediapiper" 87 | 88 | pod("MediaPipeTasksGenAIC") { 89 | version = "0.10.14" 90 | extraOpts += listOf("-compiler-option", "-fmodules") 91 | } 92 | pod("MediaPipeTasksGenAI") { 93 | version = "0.10.14" 94 | extraOpts += listOf("-compiler-option", "-fmodules") 95 | } 96 | 97 | } 98 | 99 | sourceSets { 100 | all { 101 | languageSettings { 102 | optIn("org.jetbrains.compose.resources.ExperimentalResourceApi") 103 | } 104 | } 105 | commonMain.dependencies { 106 | implementation(compose.runtime) 107 | implementation(compose.foundation) 108 | implementation(compose.material3) 109 | implementation(compose.components.resources) 110 | implementation(compose.components.uiToolingPreview) 111 | implementation(libs.voyager.navigator) 112 | implementation(libs.voyager.screenmodel) 113 | implementation(libs.voyager.transitions) 114 | implementation(libs.coil) 115 | implementation(libs.coil.network.ktor) 116 | implementation(libs.napier) 117 | implementation(libs.kotlinx.coroutines.core) 118 | implementation(libs.koin.core) 119 | implementation(libs.koin.compose) 120 | implementation(libs.ktor.client.serialization.kotlinx.json) 121 | } 122 | 123 | commonTest.dependencies { 124 | implementation(kotlin("test")) 125 | @OptIn(ExperimentalComposeLibrary::class) 126 | implementation(compose.uiTest) 127 | implementation(libs.kotlinx.coroutines.test) 128 | } 129 | 130 | androidMain.dependencies { 131 | implementation(compose.uiTooling) 132 | implementation(libs.androidx.activityCompose) 133 | implementation(libs.androidx.lifecycle.runtime.ktx) 134 | implementation(libs.androidx.lifecycle.runtime.compose) 135 | implementation(libs.kotlinx.coroutines.android) 136 | implementation(libs.ktor.client.okhttp) 137 | implementation(libs.koin.android) 138 | implementation(libs.kstore) 139 | implementation(libs.kstore.file) 140 | implementation(libs.mediapipe.genai.android) 141 | } 142 | 143 | iosMain.dependencies { 144 | implementation(libs.ktor.client.darwin) 145 | implementation(libs.kstore) 146 | implementation(libs.kstore.file) 147 | } 148 | } 149 | } 150 | 151 | android { 152 | namespace = "me.xx2bab.mediapiper" 153 | compileSdk = 34 154 | 155 | defaultConfig { 156 | minSdk = 24 157 | targetSdk = 34 158 | 159 | applicationId = "me.xx2bab.mediapiper" 160 | versionCode = 1 161 | versionName = "1.0.0" 162 | 163 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 164 | } 165 | sourceSets["main"].apply { 166 | manifest.srcFile("src/androidMain/AndroidManifest.xml") 167 | res.srcDirs("src/androidMain/res") 168 | } 169 | // https://developer.android.com/studio/test/gradle-managed-devices 170 | @Suppress("UnstableApiUsage") 171 | testOptions { 172 | managedDevices.devices { 173 | maybeCreate("pixel5").apply { 174 | device = "Pixel 5" 175 | apiLevel = 34 176 | systemImageSource = "aosp" 177 | } 178 | } 179 | } 180 | compileOptions { 181 | sourceCompatibility = JavaVersion.VERSION_1_8 182 | targetCompatibility = JavaVersion.VERSION_1_8 183 | } 184 | buildFeatures { 185 | compose = true 186 | } 187 | } 188 | 189 | buildConfig { 190 | // BuildConfig configuration here. 191 | // https://github.com/gmazzo/gradle-buildconfig-plugin#usage-in-kts 192 | useKotlinOutput { topLevelConstants = true } 193 | packageName("me.xx2bab.mediapiper") 194 | } 195 | -------------------------------------------------------------------------------- /app/rules.pro: -------------------------------------------------------------------------------- 1 | -dontwarn okhttp3.** 2 | -dontwarn org.slf4j.** 3 | -keep class kotlin.** 4 | -keep class kotlinx.** 5 | -keep class io.ktor.** 6 | # Keep `Companion` object fields of serializable classes. 7 | # This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects. 8 | -if @kotlinx.serialization.Serializable class ** 9 | -keepclassmembers class <1> { 10 | static <1>$Companion Companion; 11 | } 12 | 13 | # Keep `serializer()` on companion objects (both default and named) of serializable classes. 14 | -if @kotlinx.serialization.Serializable class ** { 15 | static **$* *; 16 | } 17 | -keepclassmembers class <2>$<3> { 18 | kotlinx.serialization.KSerializer serializer(...); 19 | } 20 | 21 | # Keep `INSTANCE.serializer()` of serializable objects. 22 | -if @kotlinx.serialization.Serializable class ** { 23 | public static ** INSTANCE; 24 | } 25 | -keepclassmembers class <1> { 26 | public static <1> INSTANCE; 27 | kotlinx.serialization.KSerializer serializer(...); 28 | } 29 | 30 | # @Serializable and @Polymorphic are used at runtime for polymorphic serialization. 31 | -keepattributes RuntimeVisibleAnnotations,AnnotationDefault 32 | 33 | # Don't print notes about potential mistakes or omissions in the configuration for kotlinx-serialization classes 34 | # See also https://github.com/Kotlin/kotlinx.serialization/issues/1900 35 | -dontnote kotlinx.serialization.** 36 | 37 | # Serialization core uses `java.lang.ClassValue` for caching inside these specified classes. 38 | # If there is no `java.lang.ClassValue` (for example, in Android), then R8/ProGuard will print a warning. 39 | # However, since in this case they will not be used, we can disable these warnings 40 | -dontwarn kotlinx.serialization.internal.ClassValueReferences 41 | -------------------------------------------------------------------------------- /app/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/androidMain/kotlin/me/xx2bab/mediapiper/App.android.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper 2 | 3 | import android.app.Application 4 | import android.os.Bundle 5 | import androidx.activity.ComponentActivity 6 | import androidx.activity.compose.setContent 7 | import androidx.activity.enableEdgeToEdge 8 | import androidx.compose.runtime.CompositionLocalProvider 9 | import androidx.lifecycle.compose.LocalLifecycleOwner 10 | import me.xx2bab.mediapiper.llm.LLMOperatorFactory 11 | import org.koin.android.ext.koin.androidContext 12 | import org.koin.dsl.module 13 | 14 | 15 | 16 | class AndroidApp : Application() { 17 | companion object { 18 | lateinit var INSTANCE: AndroidApp 19 | } 20 | 21 | override fun onCreate() { 22 | super.onCreate() 23 | Startup.run { koinApp -> 24 | koinApp.apply { 25 | modules(androidModule) 26 | androidContext(this@AndroidApp) 27 | } 28 | } 29 | INSTANCE = this 30 | } 31 | } 32 | 33 | val androidModule = module { 34 | single { LLMOperatorFactory(androidContext()) } 35 | } 36 | 37 | class AppActivity : ComponentActivity() { 38 | override fun onCreate(savedInstanceState: Bundle?) { 39 | super.onCreate(savedInstanceState) 40 | enableEdgeToEdge() 41 | setContent { 42 | CompositionLocalProvider( 43 | LocalLifecycleOwner provides this 44 | ) { 45 | App() 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/androidMain/kotlin/me/xx2bab/mediapiper/Platform.android.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") 2 | 3 | package me.xx2bab.mediapiper 4 | 5 | import java.util.UUID 6 | 7 | actual fun randomUUID(): String = UUID.randomUUID().toString() -------------------------------------------------------------------------------- /app/src/androidMain/kotlin/me/xx2bab/mediapiper/llm/LLMOperator.android.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.llm 2 | 3 | import android.content.Context 4 | import com.google.mediapipe.tasks.genai.llminference.LlmInference 5 | import kotlinx.coroutines.channels.BufferOverflow 6 | import kotlinx.coroutines.flow.Flow 7 | import kotlinx.coroutines.flow.MutableSharedFlow 8 | import kotlinx.coroutines.flow.asSharedFlow 9 | import me.xx2bab.mediapiper.llm.LLMOperator 10 | import me.xx2bab.mediapiper.llm.MODEL_EXTENSION 11 | import me.xx2bab.mediapiper.llm.MODEL_NAME 12 | import java.io.File 13 | import java.util.concurrent.atomic.AtomicBoolean 14 | 15 | const val ANDROID_MODEL_FOLDER = "data/local/tmp/llm/" 16 | 17 | actual class LLMOperatorFactory(private val context: Context){ 18 | actual fun create(): LLMOperator = LLMInferenceAndroidImpl(context) 19 | } 20 | 21 | class LLMInferenceAndroidImpl(private val context: Context): LLMOperator { 22 | 23 | private lateinit var llmInference: LlmInference 24 | private val initialized = AtomicBoolean(false) 25 | private val partialResultsFlow = MutableSharedFlow>( 26 | extraBufferCapacity = 1, 27 | onBufferOverflow = BufferOverflow.DROP_OLDEST 28 | ) 29 | 30 | override suspend fun initModel(): String? { 31 | if (initialized.get()) { 32 | return null 33 | } 34 | return try { 35 | val modelPath = "$ANDROID_MODEL_FOLDER$MODEL_NAME.$MODEL_EXTENSION" 36 | if (File(modelPath).exists().not()) { 37 | return "Model not found at path: $modelPath" 38 | } 39 | loadModel(modelPath) 40 | initialized.set(true) 41 | null 42 | } catch (e: Exception) { 43 | e.message 44 | } 45 | } 46 | private fun loadModel(modelPath: String) { 47 | val options = LlmInference.LlmInferenceOptions.builder() 48 | .setModelPath(modelPath) 49 | .setMaxTokens(1024) 50 | .setResultListener { partialResult, done -> 51 | // This API design is weird... 52 | // We need to define the result listener in LlmInferenceOptions, 53 | // and later use it with LlmInference#generateResponseAsync(...) 54 | partialResultsFlow.tryEmit(partialResult to done) 55 | } 56 | .build() 57 | 58 | llmInference = LlmInference.createFromOptions(context, options) 59 | } 60 | 61 | override fun sizeInTokens(text: String): Int = llmInference.sizeInTokens(text) 62 | 63 | override suspend fun generateResponse(inputText: String): String { 64 | if (initialized.get().not()) { 65 | throw IllegalStateException("LLMInference is not initialized properly") 66 | } 67 | return llmInference.generateResponse(inputText) 68 | } 69 | 70 | override suspend fun generateResponseAsync(inputText: String): Flow> { 71 | if (initialized.get().not()) { 72 | throw IllegalStateException("LLMInference is not initialized properly") 73 | } 74 | llmInference.generateResponseAsync(inputText) 75 | return partialResultsFlow.asSharedFlow() 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /app/src/androidMain/kotlin/me/xx2bab/mediapiper/theme/Theme.android.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.theme 2 | 3 | import android.app.Activity 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.runtime.LaunchedEffect 6 | import androidx.compose.ui.platform.LocalView 7 | import androidx.core.view.WindowInsetsControllerCompat 8 | 9 | @Composable 10 | internal actual fun SystemAppearance(isLight: Boolean) { 11 | val view = LocalView.current 12 | LaunchedEffect(isLight) { 13 | val window = (view.context as Activity).window 14 | WindowInsetsControllerCompat(window, window.decorView).apply { 15 | isAppearanceLightStatusBars = isLight 16 | isAppearanceLightNavigationBars = isLight 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/androidMain/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/androidMain/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/app/src/androidMain/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/app/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/androidMain/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/app/src/androidMain/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/app/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/androidMain/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/app/src/androidMain/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/app/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/app/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/app/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/app/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/app/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/androidMain/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Mediapiper 3 | -------------------------------------------------------------------------------- /app/src/commonMain/composeResources/font/IndieFlower-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/app/src/commonMain/composeResources/font/IndieFlower-Regular.ttf -------------------------------------------------------------------------------- /app/src/commonMain/composeResources/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Mediapiper 3 | Back 4 | Loading model 5 | Message 6 | Send 7 | User 8 | Model 9 | Responses generated by user-provided model 10 | -------------------------------------------------------------------------------- /app/src/commonMain/kotlin/me.xx2bab.mediapiper/App.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper 2 | 3 | import androidx.compose.runtime.Composable 4 | import cafe.adriel.voyager.navigator.Navigator 5 | import cafe.adriel.voyager.transitions.FadeTransition 6 | import me.xx2bab.mediapiper.llm.AiRoute 7 | import me.xx2bab.mediapiper.theme.AppTheme 8 | 9 | @Composable 10 | internal fun App() = AppTheme { 11 | Navigator(AiRoute()) { navigator -> 12 | FadeTransition(navigator) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/commonMain/kotlin/me.xx2bab.mediapiper/Platform.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") 2 | 3 | package me.xx2bab.mediapiper 4 | 5 | expect fun randomUUID(): String -------------------------------------------------------------------------------- /app/src/commonMain/kotlin/me.xx2bab.mediapiper/Startup.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper 2 | 3 | import me.xx2bab.mediapiper.llm.LLMOperator 4 | import me.xx2bab.mediapiper.llm.LLMOperatorFactory 5 | import io.github.aakira.napier.DebugAntilog 6 | import io.github.aakira.napier.Napier 7 | import org.koin.core.KoinApplication 8 | import org.koin.core.context.startKoin 9 | import org.koin.dsl.module 10 | 11 | // 3. 12 | object Startup { 13 | fun run(platformSpecifiedKoinInitBlock: (koin: KoinApplication) -> Unit) { 14 | Napier.base(DebugAntilog()) 15 | startKoin { 16 | modules(sharedModule) 17 | platformSpecifiedKoinInitBlock(this) 18 | } 19 | } 20 | } 21 | 22 | val sharedModule = module { 23 | single { get().create() } 24 | } -------------------------------------------------------------------------------- /app/src/commonMain/kotlin/me.xx2bab.mediapiper/llm/AiRoute.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.llm 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Box 5 | import androidx.compose.foundation.layout.Column 6 | import androidx.compose.foundation.layout.Row 7 | import androidx.compose.foundation.layout.fillMaxSize 8 | import androidx.compose.foundation.layout.padding 9 | import androidx.compose.material.icons.Icons 10 | import androidx.compose.material.icons.automirrored.filled.ArrowBack 11 | import androidx.compose.material3.ExperimentalMaterial3Api 12 | import androidx.compose.material3.Icon 13 | import androidx.compose.material3.IconButton 14 | import androidx.compose.material3.Text 15 | import androidx.compose.material3.TopAppBar 16 | import androidx.compose.runtime.Composable 17 | import androidx.compose.runtime.getValue 18 | import androidx.compose.runtime.setValue 19 | import androidx.compose.runtime.mutableStateOf 20 | import androidx.compose.runtime.saveable.rememberSaveable 21 | import androidx.compose.ui.Modifier 22 | import androidx.compose.ui.graphics.Color 23 | import androidx.compose.ui.unit.dp 24 | import androidx.compose.ui.unit.sp 25 | import cafe.adriel.voyager.core.model.rememberScreenModel 26 | import cafe.adriel.voyager.core.screen.Screen 27 | import cafe.adriel.voyager.navigator.LocalNavigator 28 | import cafe.adriel.voyager.navigator.currentOrThrow 29 | import org.jetbrains.compose.ui.tooling.preview.Preview 30 | import org.koin.compose.koinInject 31 | 32 | // 6. 33 | class AiRoute : Screen { 34 | 35 | @Composable 36 | override fun Content() { 37 | AiScreen() 38 | } 39 | 40 | @OptIn(ExperimentalMaterial3Api::class) 41 | @Composable 42 | fun AiScreen(llmOperator: LLMOperator = koinInject()) { 43 | val chatViewModel = rememberScreenModel { ChatViewModel(llmOperator) } 44 | var showLoading by rememberSaveable { mutableStateOf(true) } 45 | Column { 46 | TopAppBar( 47 | title = { 48 | Row { 49 | Text("AI Samples") 50 | Text("($MODEL_NAME)", fontSize = 12.sp, modifier = Modifier.padding(start = 8.dp)) 51 | } 52 | }, 53 | // navigationIcon = { 54 | // val navigator = LocalNavigator.currentOrThrow 55 | // IconButton(onClick = { navigator.pop() }) { 56 | // Icon(Icons.AutoMirrored.Filled.ArrowBack, null) 57 | // } 58 | // }, 59 | ) 60 | Box( 61 | modifier = Modifier.fillMaxSize() 62 | .background(Color.White) 63 | ) { 64 | if (showLoading) { 65 | LoadingScreen(llmOperator, onModelLoaded = { 66 | showLoading = false 67 | }) 68 | } else { 69 | ChatRoute(chatViewModel) 70 | } 71 | } 72 | } 73 | } 74 | } 75 | 76 | 77 | @Preview 78 | @Composable 79 | fun SimpleComposablePreview() { 80 | AiRoute() 81 | } 82 | 83 | -------------------------------------------------------------------------------- /app/src/commonMain/kotlin/me.xx2bab.mediapiper/llm/ChatMessage.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.llm 2 | 3 | import me.xx2bab.mediapiper.randomUUID 4 | 5 | /** 6 | * Used to represent a ChatMessage 7 | */ 8 | data class ChatMessage( 9 | val id: String = randomUUID(), 10 | val message: String = "", 11 | val author: String, 12 | val isLoading: Boolean = false 13 | ) { 14 | val isFromUser: Boolean 15 | get() = author == USER_PREFIX 16 | } -------------------------------------------------------------------------------- /app/src/commonMain/kotlin/me.xx2bab.mediapiper/llm/ChatScreen.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.llm 2 | 3 | import androidx.compose.foundation.layout.Arrangement 4 | import androidx.compose.foundation.layout.BoxWithConstraints 5 | import androidx.compose.foundation.layout.Column 6 | import androidx.compose.foundation.layout.Row 7 | import androidx.compose.foundation.layout.Spacer 8 | import androidx.compose.foundation.layout.fillMaxSize 9 | import androidx.compose.foundation.layout.fillMaxWidth 10 | import androidx.compose.foundation.layout.padding 11 | import androidx.compose.foundation.layout.width 12 | import androidx.compose.foundation.layout.widthIn 13 | import androidx.compose.foundation.lazy.LazyColumn 14 | import androidx.compose.foundation.lazy.items 15 | import androidx.compose.foundation.shape.RoundedCornerShape 16 | import androidx.compose.foundation.text.KeyboardOptions 17 | import androidx.compose.foundation.text.selection.SelectionContainer 18 | import androidx.compose.material.icons.Icons 19 | import androidx.compose.material.icons.automirrored.filled.Send 20 | import androidx.compose.material3.Card 21 | import androidx.compose.material3.CardDefaults 22 | import androidx.compose.material3.CircularProgressIndicator 23 | import androidx.compose.material3.Icon 24 | import androidx.compose.material3.IconButton 25 | import androidx.compose.material3.LocalTextStyle 26 | import androidx.compose.material3.MaterialTheme 27 | import androidx.compose.material3.Text 28 | import androidx.compose.material3.TextField 29 | import androidx.compose.runtime.Composable 30 | import androidx.compose.runtime.getValue 31 | import androidx.compose.runtime.mutableStateOf 32 | import androidx.compose.runtime.saveable.rememberSaveable 33 | import androidx.compose.runtime.setValue 34 | import androidx.compose.ui.Alignment 35 | import androidx.compose.ui.Modifier 36 | import androidx.compose.ui.text.input.KeyboardCapitalization 37 | import androidx.compose.ui.unit.dp 38 | import androidx.lifecycle.compose.collectAsStateWithLifecycle 39 | import org.jetbrains.compose.resources.stringResource 40 | import mediapiper.app.generated.resources.Res 41 | import mediapiper.app.generated.resources.action_send 42 | import mediapiper.app.generated.resources.chat_label 43 | import mediapiper.app.generated.resources.model_label 44 | import mediapiper.app.generated.resources.user_label 45 | 46 | // 10. 47 | @Composable 48 | internal fun ChatRoute( 49 | chatViewModel: ChatViewModel 50 | ) { 51 | val uiState by chatViewModel.uiState.collectAsStateWithLifecycle() 52 | val textInputEnabled by chatViewModel.isTextInputEnabled.collectAsStateWithLifecycle() 53 | ChatScreen( 54 | uiState, 55 | textInputEnabled 56 | ) { message -> 57 | chatViewModel.sendMessage(message) 58 | } 59 | } 60 | 61 | @Composable 62 | fun ChatScreen( 63 | uiState: UiState, 64 | textInputEnabled: Boolean = true, 65 | onSendMessage: (String) -> Unit 66 | ) { 67 | var userMessage by rememberSaveable { mutableStateOf("") } 68 | 69 | Column( 70 | modifier = Modifier 71 | .fillMaxSize(), 72 | verticalArrangement = Arrangement.Bottom 73 | ) { 74 | LazyColumn( 75 | modifier = Modifier 76 | .weight(1f) 77 | .fillMaxWidth() 78 | .padding(horizontal = 8.dp), 79 | reverseLayout = true 80 | ) { 81 | items(uiState.messages) { chat -> 82 | ChatItem(chat) 83 | } 84 | } 85 | 86 | Row( 87 | modifier = Modifier 88 | .fillMaxWidth() 89 | .padding(vertical = 16.dp, horizontal = 4.dp), 90 | verticalAlignment = Alignment.CenterVertically 91 | ) { 92 | 93 | Column { } 94 | 95 | Spacer(modifier = Modifier.width(8.dp)) 96 | 97 | TextField( 98 | value = userMessage, 99 | onValueChange = { userMessage = it }, 100 | keyboardOptions = KeyboardOptions( 101 | capitalization = KeyboardCapitalization.Sentences, 102 | ), 103 | label = { 104 | Text(stringResource(Res.string.chat_label)) 105 | }, 106 | modifier = Modifier 107 | .weight(0.85f), 108 | enabled = textInputEnabled, 109 | textStyle = LocalTextStyle.current.copy( 110 | color = MaterialTheme.colorScheme.onSecondaryContainer 111 | ) 112 | ) 113 | 114 | IconButton( 115 | onClick = { 116 | if (userMessage.isNotBlank()) { 117 | onSendMessage(userMessage) 118 | userMessage = "" 119 | } 120 | }, 121 | modifier = Modifier 122 | .padding(start = 16.dp) 123 | .align(Alignment.CenterVertically) 124 | .fillMaxWidth() 125 | .weight(0.15f), 126 | enabled = textInputEnabled 127 | ) { 128 | Icon( 129 | Icons.AutoMirrored.Default.Send, 130 | contentDescription = stringResource(Res.string.action_send), 131 | modifier = Modifier 132 | ) 133 | } 134 | } 135 | } 136 | } 137 | 138 | @Composable 139 | fun ChatItem( 140 | chatMessage: ChatMessage 141 | ) { 142 | val backgroundColor = if (chatMessage.isFromUser) { 143 | MaterialTheme.colorScheme.tertiaryContainer 144 | } else { 145 | MaterialTheme.colorScheme.secondaryContainer 146 | } 147 | 148 | val bubbleShape = if (chatMessage.isFromUser) { 149 | RoundedCornerShape(20.dp, 4.dp, 20.dp, 20.dp) 150 | } else { 151 | RoundedCornerShape(4.dp, 20.dp, 20.dp, 20.dp) 152 | } 153 | 154 | val horizontalAlignment = if (chatMessage.isFromUser) { 155 | Alignment.End 156 | } else { 157 | Alignment.Start 158 | } 159 | 160 | Column( 161 | horizontalAlignment = horizontalAlignment, 162 | modifier = Modifier 163 | .padding(horizontal = 8.dp, vertical = 4.dp) 164 | .fillMaxWidth() 165 | ) { 166 | val author = if (chatMessage.isFromUser) { 167 | stringResource(Res.string.user_label) 168 | } else { 169 | stringResource(Res.string.model_label) 170 | } 171 | Text( 172 | text = author, 173 | style = MaterialTheme.typography.bodySmall, 174 | modifier = Modifier.padding(bottom = 4.dp) 175 | ) 176 | Row { 177 | BoxWithConstraints { 178 | Card( 179 | colors = CardDefaults.cardColors(containerColor = backgroundColor), 180 | shape = bubbleShape, 181 | modifier = Modifier.widthIn(0.dp, maxWidth * 0.9f) 182 | ) { 183 | if (chatMessage.isLoading) { 184 | CircularProgressIndicator( 185 | modifier = Modifier.padding(16.dp) 186 | ) 187 | } else { 188 | SelectionContainer { 189 | Text( 190 | text = chatMessage.message, 191 | modifier = Modifier.padding(16.dp) 192 | ) 193 | } 194 | } 195 | } 196 | } 197 | } 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /app/src/commonMain/kotlin/me.xx2bab.mediapiper/llm/ChatUiState.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.llm 2 | 3 | import androidx.compose.runtime.toMutableStateList 4 | 5 | const val USER_PREFIX = "user" 6 | const val MODEL_PREFIX = "model" 7 | 8 | interface UiState { 9 | val messages: List 10 | val fullPrompt: String 11 | 12 | /** 13 | * Creates a new loading message. 14 | * Returns the id of that message. 15 | */ 16 | fun createLoadingMessage(): String 17 | 18 | /** 19 | * Appends the specified text to the message with the specified ID. 20 | * @param done - indicates whether the model has finished generating the message. 21 | */ 22 | fun appendMessage(id: String, text: String, done: Boolean = false) 23 | 24 | /** 25 | * Creates a new message with the specified text and author. 26 | * Return the id of that message. 27 | */ 28 | fun addMessage(text: String, author: String): String 29 | } 30 | 31 | /** 32 | * A sample implementation of [UiState] that can be used with any model. 33 | */ 34 | class ChatUiState( 35 | messages: List = emptyList() 36 | ) : UiState { 37 | private val _messages: MutableList = messages.toMutableStateList() 38 | override val messages: List = _messages.reversed() 39 | 40 | // Prompt the model with the current chat history 41 | override val fullPrompt: String 42 | get() = _messages.joinToString(separator = "\n") { it.message } 43 | 44 | override fun createLoadingMessage(): String { 45 | val chatMessage = ChatMessage(author = MODEL_PREFIX, isLoading = true) 46 | _messages.add(chatMessage) 47 | return chatMessage.id 48 | } 49 | 50 | fun appendFirstMessage(id: String, text: String) { 51 | appendMessage(id, text, false) 52 | } 53 | 54 | override fun appendMessage(id: String, text: String, done: Boolean) { 55 | val index = _messages.indexOfFirst { it.id == id } 56 | if (index != -1) { 57 | val newText = _messages[index].message + text 58 | _messages[index] = _messages[index].copy(message = newText, isLoading = false) 59 | } 60 | } 61 | 62 | override fun addMessage(text: String, author: String): String { 63 | val chatMessage = ChatMessage( 64 | message = text, 65 | author = author 66 | ) 67 | _messages.add(chatMessage) 68 | return chatMessage.id 69 | } 70 | } 71 | 72 | /** 73 | * An implementation of [UiState] to be used with the Gemma model. 74 | */ 75 | class GemmaUiState( 76 | messages: List = emptyList() 77 | ) : UiState { 78 | private val START_TURN = "" 79 | private val END_TURN = "" 80 | 81 | private val _messages: MutableList = messages.toMutableStateList() 82 | override val messages: List 83 | get() = _messages 84 | .map { 85 | // Remove the prefix and suffix before showing a message in the UI 86 | it.copy( 87 | message = it.message.replace(START_TURN + it.author + "\n", "") 88 | .replace(END_TURN, "") 89 | ) 90 | }.reversed() 91 | 92 | // Only using the last 4 messages to keep input + output short 93 | override val fullPrompt: String 94 | get() = _messages.takeLast(4).joinToString(separator = "\n") { it.message } 95 | 96 | override fun createLoadingMessage(): String { 97 | val chatMessage = ChatMessage(author = MODEL_PREFIX, isLoading = true) 98 | _messages.add(chatMessage) 99 | return chatMessage.id 100 | } 101 | 102 | fun appendFirstMessage(id: String, text: String) { 103 | appendMessage(id, "$START_TURN$MODEL_PREFIX\n$text", false) 104 | } 105 | 106 | override fun appendMessage(id: String, text: String, done: Boolean) { 107 | val index = _messages.indexOfFirst { it.id == id } 108 | if (index != -1) { 109 | val newText = if (done) { 110 | // Append the Suffix when model is done generating the response 111 | _messages[index].message + text + END_TURN 112 | } else { 113 | // Append the text 114 | _messages[index].message + text 115 | } 116 | _messages[index] = _messages[index].copy(message = newText, isLoading = false) 117 | } 118 | } 119 | 120 | override fun addMessage(text: String, author: String): String { 121 | val chatMessage = ChatMessage( 122 | message = "$START_TURN$author\n$text$END_TURN", 123 | author = author 124 | ) 125 | _messages.add(chatMessage) 126 | return chatMessage.id 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /app/src/commonMain/kotlin/me.xx2bab.mediapiper/llm/ChatViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.llm 2 | 3 | import cafe.adriel.voyager.core.model.ScreenModel 4 | import kotlinx.coroutines.Dispatchers 5 | import kotlinx.coroutines.IO 6 | import kotlinx.coroutines.MainScope 7 | import kotlinx.coroutines.cancel 8 | import kotlinx.coroutines.flow.MutableStateFlow 9 | import kotlinx.coroutines.flow.StateFlow 10 | import kotlinx.coroutines.flow.asStateFlow 11 | import kotlinx.coroutines.flow.collectIndexed 12 | import kotlinx.coroutines.launch 13 | 14 | // 9. 15 | class ChatViewModel( 16 | private val llmOperator: LLMOperator 17 | ) : ScreenModel { 18 | private val coroutineScope = MainScope() 19 | 20 | // `GemmaUiState()` is optimized for the Gemma model. 21 | // Replace `GemmaUiState` with `ChatUiState()` if you're using a different model 22 | private val _uiState: MutableStateFlow = MutableStateFlow(GemmaUiState()) 23 | val uiState: StateFlow = 24 | _uiState.asStateFlow() 25 | 26 | private val _textInputEnabled: MutableStateFlow = 27 | MutableStateFlow(true) 28 | val isTextInputEnabled: StateFlow = 29 | _textInputEnabled.asStateFlow() 30 | 31 | fun sendMessage(userMessage: String) { 32 | coroutineScope.launch(Dispatchers.IO) { 33 | _uiState.value.addMessage(userMessage, USER_PREFIX) 34 | var currentMessageId: String? = _uiState.value.createLoadingMessage() 35 | setInputEnabled(false) 36 | try { 37 | val fullPrompt = _uiState.value.fullPrompt 38 | llmOperator.generateResponseAsync(fullPrompt) 39 | .collectIndexed { index, (partialResult, done) -> 40 | currentMessageId?.let { 41 | if (index == 0) { 42 | _uiState.value.appendFirstMessage(it, partialResult) 43 | } else { 44 | _uiState.value.appendMessage(it, partialResult, done) 45 | } 46 | if (done) { 47 | currentMessageId = null 48 | // Re-enable text input 49 | setInputEnabled(true) 50 | } 51 | } 52 | } 53 | } catch (e: Exception) { 54 | _uiState.value.addMessage(e.message ?: "Unknown Error", MODEL_PREFIX) 55 | setInputEnabled(true) 56 | } 57 | } 58 | } 59 | 60 | private fun setInputEnabled(isEnabled: Boolean) { 61 | _textInputEnabled.value = isEnabled 62 | } 63 | 64 | 65 | override fun onDispose() { 66 | super.onDispose() 67 | coroutineScope.cancel() 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/commonMain/kotlin/me.xx2bab.mediapiper/llm/LLMOperator.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.llm 2 | 3 | import kotlinx.coroutines.flow.Flow 4 | 5 | // We suppose the extension is always .bin , 6 | // so we don't pass it to the program. 7 | //const val MODEL_NAME = "gemma-2b-it-gpu-int4" 8 | const val MODEL_NAME = "gemma-2b-it-cpu-int4" 9 | 10 | const val MODEL_EXTENSION = "bin" 11 | 12 | expect class LLMOperatorFactory { 13 | fun create(): LLMOperator 14 | } 15 | 16 | // 8. 17 | interface LLMOperator { 18 | 19 | /** 20 | * To load the model into current context. 21 | * @return 1. null if it went well 2. an error message in string 22 | */ 23 | suspend fun initModel(): String? 24 | 25 | /** 26 | * To calculate the token size of a string. 27 | */ 28 | fun sizeInTokens(text: String): Int 29 | 30 | /** 31 | * To generate response for give inputText in synchronous way. 32 | */ 33 | suspend fun generateResponse(inputText: String): String 34 | 35 | /** 36 | * To generate response for give inputText in asynchronous way. 37 | * @return A flow with partial response in String and completion flag in Boolean. 38 | */ 39 | suspend fun generateResponseAsync(inputText: String): Flow> 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/commonMain/kotlin/me.xx2bab.mediapiper/llm/LoadingScreen.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.llm 2 | 3 | import androidx.compose.foundation.layout.Arrangement 4 | import androidx.compose.foundation.layout.Box 5 | import androidx.compose.foundation.layout.Column 6 | import androidx.compose.foundation.layout.fillMaxSize 7 | import androidx.compose.foundation.layout.padding 8 | import androidx.compose.material3.CircularProgressIndicator 9 | import androidx.compose.material3.MaterialTheme 10 | import androidx.compose.material3.Text 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.runtime.LaunchedEffect 13 | import androidx.compose.runtime.getValue 14 | import androidx.compose.runtime.mutableStateOf 15 | import androidx.compose.runtime.remember 16 | import androidx.compose.runtime.setValue 17 | import androidx.compose.ui.Alignment 18 | import androidx.compose.ui.Modifier 19 | import androidx.compose.ui.text.style.TextAlign 20 | import androidx.compose.ui.unit.dp 21 | import io.github.aakira.napier.Napier 22 | import kotlinx.coroutines.Dispatchers 23 | import kotlinx.coroutines.IO 24 | import kotlinx.coroutines.withContext 25 | import org.jetbrains.compose.resources.stringResource 26 | import mediapiper.app.generated.resources.Res 27 | import mediapiper.app.generated.resources.loading_model 28 | 29 | @Composable 30 | internal fun LoadingScreen( 31 | llmOperator: LLMOperator, 32 | onModelLoaded: () -> Unit = { } 33 | ) { 34 | var errorMessage by remember { mutableStateOf("") } 35 | 36 | Box(modifier = Modifier.fillMaxSize(), 37 | contentAlignment = Alignment.Center) { 38 | if (errorMessage != "") { 39 | ErrorMessage(errorMessage) 40 | } else { 41 | LoadingIndicator() 42 | } 43 | } 44 | 45 | LaunchedEffect(Unit) { 46 | // Create the LlmInference in a separate thread 47 | withContext(Dispatchers.IO) { 48 | val res = llmOperator.initModel() 49 | if (res == null) { 50 | withContext(Dispatchers.Main) { 51 | onModelLoaded() 52 | } 53 | Napier.i("model is loaded") 54 | } else { 55 | errorMessage = "Model loaded Error: $res" 56 | Napier.e("model failed to load: $res") 57 | } 58 | } 59 | } 60 | } 61 | 62 | @Composable 63 | fun LoadingIndicator() { 64 | Column( 65 | horizontalAlignment = Alignment.CenterHorizontally, 66 | verticalArrangement = Arrangement.Center 67 | ) { 68 | Text( 69 | text = stringResource(Res.string.loading_model), 70 | style = MaterialTheme.typography.titleMedium, 71 | modifier = Modifier 72 | .padding(bottom = 8.dp) 73 | ) 74 | CircularProgressIndicator() 75 | } 76 | } 77 | 78 | @Composable 79 | fun ErrorMessage( 80 | errorMessage: String 81 | ) { 82 | Box( 83 | contentAlignment = Alignment.Center 84 | ) { 85 | Text( 86 | text = errorMessage, 87 | color = MaterialTheme.colorScheme.error, 88 | textAlign = TextAlign.Center 89 | ) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/commonMain/kotlin/me.xx2bab.mediapiper/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | //generated by https://m3.material.io/theme-builder#/custom 6 | //Color palette was taken here: https://colorhunt.co/palettes/popular 7 | 8 | val primaryLight = Color(0xFF66558F) 9 | val onPrimaryLight = Color(0xFFFFFFFF) 10 | val primaryContainerLight = Color(0xFFE9DDFF) 11 | val onPrimaryContainerLight = Color(0xFF210F47) 12 | val secondaryLight = Color(0xFF66558E) 13 | val onSecondaryLight = Color(0xFFFFFFFF) 14 | val secondaryContainerLight = Color(0xFFE9DDFF) 15 | val onSecondaryContainerLight = Color(0xFF210F47) 16 | val tertiaryLight = Color(0xFF8B4A61) 17 | val onTertiaryLight = Color(0xFFFFFFFF) 18 | val tertiaryContainerLight = Color(0xFFFFD9E3) 19 | val onTertiaryContainerLight = Color(0xFF3A071E) 20 | val errorLight = Color(0xFFBA1A1A) 21 | val onErrorLight = Color(0xFFFFFFFF) 22 | val errorContainerLight = Color(0xFFFFDAD6) 23 | val onErrorContainerLight = Color(0xFF410002) 24 | val backgroundLight = Color(0xFFFEF7FF) 25 | val onBackgroundLight = Color(0xFF1D1B20) 26 | val surfaceLight = Color(0xFFFEF7FF) 27 | val onSurfaceLight = Color(0xFF1D1B20) 28 | val surfaceVariantLight = Color(0xFFE7E0EB) 29 | val onSurfaceVariantLight = Color(0xFF49454E) 30 | val outlineLight = Color(0xFF7A757F) 31 | val outlineVariantLight = Color(0xFFCAC4CF) 32 | val scrimLight = Color(0xFF000000) 33 | val inverseSurfaceLight = Color(0xFF322F35) 34 | val inverseOnSurfaceLight = Color(0xFFF5EFF7) 35 | val inversePrimaryLight = Color(0xFFD0BCFE) 36 | val surfaceDimLight = Color(0xFFDED8E0) 37 | val surfaceBrightLight = Color(0xFFFEF7FF) 38 | val surfaceContainerLowestLight = Color(0xFFFFFFFF) 39 | val surfaceContainerLowLight = Color(0xFFF8F2FA) 40 | val surfaceContainerLight = Color(0xFFF2ECF4) 41 | val surfaceContainerHighLight = Color(0xFFECE6EE) 42 | val surfaceContainerHighestLight = Color(0xFFE6E0E9) 43 | 44 | val primaryLightMediumContrast = Color(0xFF493971) 45 | val onPrimaryLightMediumContrast = Color(0xFFFFFFFF) 46 | val primaryContainerLightMediumContrast = Color(0xFF7C6BA6) 47 | val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF) 48 | val secondaryLightMediumContrast = Color(0xFF4A3971) 49 | val onSecondaryLightMediumContrast = Color(0xFFFFFFFF) 50 | val secondaryContainerLightMediumContrast = Color(0xFF7D6BA6) 51 | val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF) 52 | val tertiaryLightMediumContrast = Color(0xFF6B2F45) 53 | val onTertiaryLightMediumContrast = Color(0xFFFFFFFF) 54 | val tertiaryContainerLightMediumContrast = Color(0xFFA55F77) 55 | val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF) 56 | val errorLightMediumContrast = Color(0xFF8C0009) 57 | val onErrorLightMediumContrast = Color(0xFFFFFFFF) 58 | val errorContainerLightMediumContrast = Color(0xFFDA342E) 59 | val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF) 60 | val backgroundLightMediumContrast = Color(0xFFFEF7FF) 61 | val onBackgroundLightMediumContrast = Color(0xFF1D1B20) 62 | val surfaceLightMediumContrast = Color(0xFFFEF7FF) 63 | val onSurfaceLightMediumContrast = Color(0xFF1D1B20) 64 | val surfaceVariantLightMediumContrast = Color(0xFFE7E0EB) 65 | val onSurfaceVariantLightMediumContrast = Color(0xFF45414A) 66 | val outlineLightMediumContrast = Color(0xFF615D67) 67 | val outlineVariantLightMediumContrast = Color(0xFF7D7983) 68 | val scrimLightMediumContrast = Color(0xFF000000) 69 | val inverseSurfaceLightMediumContrast = Color(0xFF322F35) 70 | val inverseOnSurfaceLightMediumContrast = Color(0xFFF5EFF7) 71 | val inversePrimaryLightMediumContrast = Color(0xFFD0BCFE) 72 | val surfaceDimLightMediumContrast = Color(0xFFDED8E0) 73 | val surfaceBrightLightMediumContrast = Color(0xFFFEF7FF) 74 | val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF) 75 | val surfaceContainerLowLightMediumContrast = Color(0xFFF8F2FA) 76 | val surfaceContainerLightMediumContrast = Color(0xFFF2ECF4) 77 | val surfaceContainerHighLightMediumContrast = Color(0xFFECE6EE) 78 | val surfaceContainerHighestLightMediumContrast = Color(0xFFE6E0E9) 79 | 80 | val primaryLightHighContrast = Color(0xFF28174E) 81 | val onPrimaryLightHighContrast = Color(0xFFFFFFFF) 82 | val primaryContainerLightHighContrast = Color(0xFF493971) 83 | val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF) 84 | val secondaryLightHighContrast = Color(0xFF28174E) 85 | val onSecondaryLightHighContrast = Color(0xFFFFFFFF) 86 | val secondaryContainerLightHighContrast = Color(0xFF4A3971) 87 | val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF) 88 | val tertiaryLightHighContrast = Color(0xFF420E25) 89 | val onTertiaryLightHighContrast = Color(0xFFFFFFFF) 90 | val tertiaryContainerLightHighContrast = Color(0xFF6B2F45) 91 | val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF) 92 | val errorLightHighContrast = Color(0xFF4E0002) 93 | val onErrorLightHighContrast = Color(0xFFFFFFFF) 94 | val errorContainerLightHighContrast = Color(0xFF8C0009) 95 | val onErrorContainerLightHighContrast = Color(0xFFFFFFFF) 96 | val backgroundLightHighContrast = Color(0xFFFEF7FF) 97 | val onBackgroundLightHighContrast = Color(0xFF1D1B20) 98 | val surfaceLightHighContrast = Color(0xFFFEF7FF) 99 | val onSurfaceLightHighContrast = Color(0xFF000000) 100 | val surfaceVariantLightHighContrast = Color(0xFFE7E0EB) 101 | val onSurfaceVariantLightHighContrast = Color(0xFF25232B) 102 | val outlineLightHighContrast = Color(0xFF45414A) 103 | val outlineVariantLightHighContrast = Color(0xFF45414A) 104 | val scrimLightHighContrast = Color(0xFF000000) 105 | val inverseSurfaceLightHighContrast = Color(0xFF322F35) 106 | val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF) 107 | val inversePrimaryLightHighContrast = Color(0xFFF2E8FF) 108 | val surfaceDimLightHighContrast = Color(0xFFDED8E0) 109 | val surfaceBrightLightHighContrast = Color(0xFFFEF7FF) 110 | val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF) 111 | val surfaceContainerLowLightHighContrast = Color(0xFFF8F2FA) 112 | val surfaceContainerLightHighContrast = Color(0xFFF2ECF4) 113 | val surfaceContainerHighLightHighContrast = Color(0xFFECE6EE) 114 | val surfaceContainerHighestLightHighContrast = Color(0xFFE6E0E9) 115 | 116 | val primaryDark = Color(0xFFD0BCFE) 117 | val onPrimaryDark = Color(0xFF36265D) 118 | val primaryContainerDark = Color(0xFF4D3D75) 119 | val onPrimaryContainerDark = Color(0xFFE9DDFF) 120 | val secondaryDark = Color(0xFFD0BCFE) 121 | val onSecondaryDark = Color(0xFF37265D) 122 | val secondaryContainerDark = Color(0xFF4E3D75) 123 | val onSecondaryContainerDark = Color(0xFFE9DDFF) 124 | val tertiaryDark = Color(0xFFFFB0C9) 125 | val onTertiaryDark = Color(0xFF541D33) 126 | val tertiaryContainerDark = Color(0xFF6F3349) 127 | val onTertiaryContainerDark = Color(0xFFFFD9E3) 128 | val errorDark = Color(0xFFFFB4AB) 129 | val onErrorDark = Color(0xFF690005) 130 | val errorContainerDark = Color(0xFF93000A) 131 | val onErrorContainerDark = Color(0xFFFFDAD6) 132 | val backgroundDark = Color(0xFF141218) 133 | val onBackgroundDark = Color(0xFFE6E0E9) 134 | val surfaceDark = Color(0xFF141218) 135 | val onSurfaceDark = Color(0xFFE6E0E9) 136 | val surfaceVariantDark = Color(0xFF49454E) 137 | val onSurfaceVariantDark = Color(0xFFCAC4CF) 138 | val outlineDark = Color(0xFF948F99) 139 | val outlineVariantDark = Color(0xFF49454E) 140 | val scrimDark = Color(0xFF000000) 141 | val inverseSurfaceDark = Color(0xFFE6E0E9) 142 | val inverseOnSurfaceDark = Color(0xFF322F35) 143 | val inversePrimaryDark = Color(0xFF66558F) 144 | val surfaceDimDark = Color(0xFF141218) 145 | val surfaceBrightDark = Color(0xFF3B383E) 146 | val surfaceContainerLowestDark = Color(0xFF0F0D13) 147 | val surfaceContainerLowDark = Color(0xFF1D1B20) 148 | val surfaceContainerDark = Color(0xFF211F24) 149 | val surfaceContainerHighDark = Color(0xFF2B292F) 150 | val surfaceContainerHighestDark = Color(0xFF36343A) 151 | 152 | val primaryDarkMediumContrast = Color(0xFFD4C1FF) 153 | val onPrimaryDarkMediumContrast = Color(0xFF1C0941) 154 | val primaryContainerDarkMediumContrast = Color(0xFF9987C5) 155 | val onPrimaryContainerDarkMediumContrast = Color(0xFF000000) 156 | val secondaryDarkMediumContrast = Color(0xFFD4C1FF) 157 | val onSecondaryDarkMediumContrast = Color(0xFF1C0841) 158 | val secondaryContainerDarkMediumContrast = Color(0xFF9987C4) 159 | val onSecondaryContainerDarkMediumContrast = Color(0xFF000000) 160 | val tertiaryDarkMediumContrast = Color(0xFFFFB7CD) 161 | val onTertiaryDarkMediumContrast = Color(0xFF330218) 162 | val tertiaryContainerDarkMediumContrast = Color(0xFFC57B94) 163 | val onTertiaryContainerDarkMediumContrast = Color(0xFF000000) 164 | val errorDarkMediumContrast = Color(0xFFFFBAB1) 165 | val onErrorDarkMediumContrast = Color(0xFF370001) 166 | val errorContainerDarkMediumContrast = Color(0xFFFF5449) 167 | val onErrorContainerDarkMediumContrast = Color(0xFF000000) 168 | val backgroundDarkMediumContrast = Color(0xFF141218) 169 | val onBackgroundDarkMediumContrast = Color(0xFFE6E0E9) 170 | val surfaceDarkMediumContrast = Color(0xFF141218) 171 | val onSurfaceDarkMediumContrast = Color(0xFFFFF9FF) 172 | val surfaceVariantDarkMediumContrast = Color(0xFF49454E) 173 | val onSurfaceVariantDarkMediumContrast = Color(0xFFCFC8D4) 174 | val outlineDarkMediumContrast = Color(0xFFA6A1AB) 175 | val outlineVariantDarkMediumContrast = Color(0xFF86818B) 176 | val scrimDarkMediumContrast = Color(0xFF000000) 177 | val inverseSurfaceDarkMediumContrast = Color(0xFFE6E0E9) 178 | val inverseOnSurfaceDarkMediumContrast = Color(0xFF2B292F) 179 | val inversePrimaryDarkMediumContrast = Color(0xFF4F3E76) 180 | val surfaceDimDarkMediumContrast = Color(0xFF141218) 181 | val surfaceBrightDarkMediumContrast = Color(0xFF3B383E) 182 | val surfaceContainerLowestDarkMediumContrast = Color(0xFF0F0D13) 183 | val surfaceContainerLowDarkMediumContrast = Color(0xFF1D1B20) 184 | val surfaceContainerDarkMediumContrast = Color(0xFF211F24) 185 | val surfaceContainerHighDarkMediumContrast = Color(0xFF2B292F) 186 | val surfaceContainerHighestDarkMediumContrast = Color(0xFF36343A) 187 | 188 | val primaryDarkHighContrast = Color(0xFFFFF9FF) 189 | val onPrimaryDarkHighContrast = Color(0xFF000000) 190 | val primaryContainerDarkHighContrast = Color(0xFFD4C1FF) 191 | val onPrimaryContainerDarkHighContrast = Color(0xFF000000) 192 | val secondaryDarkHighContrast = Color(0xFFFFF9FF) 193 | val onSecondaryDarkHighContrast = Color(0xFF000000) 194 | val secondaryContainerDarkHighContrast = Color(0xFFD4C1FF) 195 | val onSecondaryContainerDarkHighContrast = Color(0xFF000000) 196 | val tertiaryDarkHighContrast = Color(0xFFFFF9F9) 197 | val onTertiaryDarkHighContrast = Color(0xFF000000) 198 | val tertiaryContainerDarkHighContrast = Color(0xFFFFB7CD) 199 | val onTertiaryContainerDarkHighContrast = Color(0xFF000000) 200 | val errorDarkHighContrast = Color(0xFFFFF9F9) 201 | val onErrorDarkHighContrast = Color(0xFF000000) 202 | val errorContainerDarkHighContrast = Color(0xFFFFBAB1) 203 | val onErrorContainerDarkHighContrast = Color(0xFF000000) 204 | val backgroundDarkHighContrast = Color(0xFF141218) 205 | val onBackgroundDarkHighContrast = Color(0xFFE6E0E9) 206 | val surfaceDarkHighContrast = Color(0xFF141218) 207 | val onSurfaceDarkHighContrast = Color(0xFFFFFFFF) 208 | val surfaceVariantDarkHighContrast = Color(0xFF49454E) 209 | val onSurfaceVariantDarkHighContrast = Color(0xFFFFF9FF) 210 | val outlineDarkHighContrast = Color(0xFFCFC8D4) 211 | val outlineVariantDarkHighContrast = Color(0xFFCFC8D4) 212 | val scrimDarkHighContrast = Color(0xFF000000) 213 | val inverseSurfaceDarkHighContrast = Color(0xFFE6E0E9) 214 | val inverseOnSurfaceDarkHighContrast = Color(0xFF000000) 215 | val inversePrimaryDarkHighContrast = Color(0xFF302056) 216 | val surfaceDimDarkHighContrast = Color(0xFF141218) 217 | val surfaceBrightDarkHighContrast = Color(0xFF3B383E) 218 | val surfaceContainerLowestDarkHighContrast = Color(0xFF0F0D13) 219 | val surfaceContainerLowDarkHighContrast = Color(0xFF1D1B20) 220 | val surfaceContainerDarkHighContrast = Color(0xFF211F24) 221 | val surfaceContainerHighDarkHighContrast = Color(0xFF2B292F) 222 | val surfaceContainerHighestDarkHighContrast = Color(0xFF36343A) 223 | 224 | 225 | internal val seed = Color(0xFF2C3639) 226 | fun parseColor(string: String): Color { 227 | if (string.isEmpty() || string[0] != '#' || string.length > 7) { 228 | return Color.Unspecified 229 | } 230 | val hex = string.substring(1, string.length - 1) 231 | return if (hex.length > 6) { 232 | Color(hex.toLong(16)) 233 | } else { 234 | Color(hex.toLong(16) or 0xFF000000) 235 | } 236 | } -------------------------------------------------------------------------------- /app/src/commonMain/kotlin/me.xx2bab.mediapiper/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.theme 2 | 3 | import androidx.compose.foundation.isSystemInDarkTheme 4 | import androidx.compose.material3.MaterialTheme 5 | import androidx.compose.material3.darkColorScheme 6 | import androidx.compose.material3.lightColorScheme 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.runtime.CompositionLocalProvider 9 | import androidx.compose.runtime.compositionLocalOf 10 | import androidx.compose.runtime.getValue 11 | import androidx.compose.runtime.mutableStateOf 12 | import androidx.compose.runtime.remember 13 | import androidx.compose.ui.graphics.Color 14 | 15 | val Purple80 = Color(0xFFD0BCFF) 16 | val PurpleGrey80 = Color(0xFFCCC2DC) 17 | val Pink80 = Color(0xFFEFB8C8) 18 | 19 | val Purple40 = Color(0xFF6650a4) 20 | val PurpleGrey40 = Color(0xFF625b71) 21 | val Pink40 = Color(0xFF7D5260) 22 | 23 | 24 | private val lightScheme = lightColorScheme( 25 | primary = primaryLight, 26 | onPrimary = onPrimaryLight, 27 | primaryContainer = primaryContainerLight, 28 | onPrimaryContainer = onPrimaryContainerLight, 29 | secondary = secondaryLight, 30 | onSecondary = onSecondaryLight, 31 | secondaryContainer = secondaryContainerLight, 32 | onSecondaryContainer = onSecondaryContainerLight, 33 | tertiary = tertiaryLight, 34 | onTertiary = onTertiaryLight, 35 | tertiaryContainer = tertiaryContainerLight, 36 | onTertiaryContainer = onTertiaryContainerLight, 37 | error = errorLight, 38 | onError = onErrorLight, 39 | errorContainer = errorContainerLight, 40 | onErrorContainer = onErrorContainerLight, 41 | background = backgroundLight, 42 | onBackground = onBackgroundLight, 43 | surface = surfaceLight, 44 | onSurface = onSurfaceLight, 45 | surfaceVariant = surfaceVariantLight, 46 | onSurfaceVariant = onSurfaceVariantLight, 47 | outline = outlineLight, 48 | outlineVariant = outlineVariantLight, 49 | scrim = scrimLight, 50 | inverseSurface = inverseSurfaceLight, 51 | inverseOnSurface = inverseOnSurfaceLight, 52 | inversePrimary = inversePrimaryLight, 53 | surfaceDim = surfaceDimLight, 54 | surfaceBright = surfaceBrightLight, 55 | surfaceContainerLowest = surfaceContainerLowestLight, 56 | surfaceContainerLow = surfaceContainerLowLight, 57 | surfaceContainer = surfaceContainerLight, 58 | surfaceContainerHigh = surfaceContainerHighLight, 59 | surfaceContainerHighest = surfaceContainerHighestLight, 60 | ) 61 | 62 | private val darkScheme = darkColorScheme( 63 | primary = primaryDark, 64 | onPrimary = onPrimaryDark, 65 | primaryContainer = primaryContainerDark, 66 | onPrimaryContainer = onPrimaryContainerDark, 67 | secondary = secondaryDark, 68 | onSecondary = onSecondaryDark, 69 | secondaryContainer = secondaryContainerDark, 70 | onSecondaryContainer = onSecondaryContainerDark, 71 | tertiary = tertiaryDark, 72 | onTertiary = onTertiaryDark, 73 | tertiaryContainer = tertiaryContainerDark, 74 | onTertiaryContainer = onTertiaryContainerDark, 75 | error = errorDark, 76 | onError = onErrorDark, 77 | errorContainer = errorContainerDark, 78 | onErrorContainer = onErrorContainerDark, 79 | background = backgroundDark, 80 | onBackground = onBackgroundDark, 81 | surface = surfaceDark, 82 | onSurface = onSurfaceDark, 83 | surfaceVariant = surfaceVariantDark, 84 | onSurfaceVariant = onSurfaceVariantDark, 85 | outline = outlineDark, 86 | outlineVariant = outlineVariantDark, 87 | scrim = scrimDark, 88 | inverseSurface = inverseSurfaceDark, 89 | inverseOnSurface = inverseOnSurfaceDark, 90 | inversePrimary = inversePrimaryDark, 91 | surfaceDim = surfaceDimDark, 92 | surfaceBright = surfaceBrightDark, 93 | surfaceContainerLowest = surfaceContainerLowestDark, 94 | surfaceContainerLow = surfaceContainerLowDark, 95 | surfaceContainer = surfaceContainerDark, 96 | surfaceContainerHigh = surfaceContainerHighDark, 97 | surfaceContainerHighest = surfaceContainerHighestDark, 98 | ) 99 | 100 | internal val LocalThemeIsDark = compositionLocalOf { mutableStateOf(true) } 101 | 102 | @Composable 103 | internal fun AppTheme( 104 | content: @Composable () -> Unit 105 | ) { 106 | val systemIsDark = isSystemInDarkTheme() 107 | val isDarkState = remember { mutableStateOf(systemIsDark) } 108 | CompositionLocalProvider( 109 | LocalThemeIsDark provides isDarkState 110 | ) { 111 | val isDark by isDarkState 112 | SystemAppearance(!isDark) 113 | MaterialTheme( 114 | colorScheme = if (isDark) darkScheme else lightScheme, 115 | content = content 116 | ) 117 | } 118 | } 119 | 120 | @Composable 121 | internal expect fun SystemAppearance(isLight: Boolean) 122 | -------------------------------------------------------------------------------- /app/src/iosMain/kotlin/main.kt: -------------------------------------------------------------------------------- 1 | import androidx.compose.ui.window.ComposeUIViewController 2 | import me.xx2bab.mediapiper.App 3 | import me.xx2bab.mediapiper.Startup 4 | import me.xx2bab.mediapiper.llm.LLMOperatorFactory 5 | import me.xx2bab.mediapiper.llm.LLMOperatorSwift 6 | import org.koin.dsl.module 7 | import platform.UIKit.UIViewController 8 | 9 | fun MainViewController(): UIViewController = ComposeUIViewController { App() } 10 | 11 | fun onStartup(llmInferenceDelegate: LLMOperatorSwift) { 12 | Startup.run { koinApp -> 13 | koinApp.apply { 14 | modules(module { 15 | single { LLMOperatorFactory(llmInferenceDelegate) } 16 | }) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/iosMain/kotlin/me.xx2bab.mediapiper/Platform.ios.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") 2 | 3 | package me.xx2bab.mediapiper 4 | 5 | import platform.Foundation.NSUUID 6 | 7 | 8 | actual fun randomUUID(): String = NSUUID().UUIDString() -------------------------------------------------------------------------------- /app/src/iosMain/kotlin/me.xx2bab.mediapiper/llm/LLMOperator.ios.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.llm 2 | 3 | import kotlinx.atomicfu.atomic 4 | import kotlinx.coroutines.channels.BufferOverflow 5 | import kotlinx.coroutines.flow.Flow 6 | import kotlinx.coroutines.flow.MutableSharedFlow 7 | import kotlinx.coroutines.flow.asSharedFlow 8 | 9 | actual class LLMOperatorFactory(private val llmInferenceDelegate: LLMOperatorSwift) { 10 | actual fun create(): LLMOperator = LLMOperatorIOSImpl(llmInferenceDelegate) 11 | } 12 | 13 | //// FIXME: MPPLLMInference throws NPE during initialization stage without detailed stacktrace 14 | //@OptIn(ExperimentalForeignApi::class) 15 | //class LLMOperatorIOSImpl: LLMOperator { 16 | // 17 | // private val inference: MPPLLMInference 18 | // 19 | // init { 20 | // val modelPath = NSBundle.mainBundle.pathForResource("gemma-2b-it-gpu-int4", "bin") 21 | // 22 | // val options = MPPLLMInferenceOptions(modelPath!!) 23 | // options.setModelPath(modelPath!!) 24 | // options.setMaxTokens(2048) 25 | // options.setTopk(40) 26 | // options.setTemperature(0.8f) 27 | // options.setRandomSeed(102) 28 | // 29 | // inference = MPPLLMInference(options, null) // NPE throws here!! 30 | // } 31 | // 32 | // override fun sizeInTokens(text: String): Int { 33 | // return 0 34 | // } 35 | // 36 | // override fun generateResponse(inputText: String): String { 37 | // return inference.generateResponseWithInputText(inputText, null)!! 38 | // } 39 | // 40 | // override fun generateResponseAsync(inputText: String, ...) { 41 | // // inference.generateResponseAsyncWithInputText(...) 42 | // } 43 | // 44 | //} 45 | 46 | 47 | class LLMOperatorIOSImpl(private val delegate: LLMOperatorSwift) : LLMOperator { 48 | 49 | private val initialized = atomic(false) 50 | 51 | override suspend fun initModel(): String? { 52 | if (initialized.value) { 53 | return null 54 | } 55 | return try { 56 | delegate.loadModel(MODEL_NAME) 57 | initialized.value = true 58 | null 59 | } catch (e: Exception) { 60 | e.message 61 | } 62 | } 63 | 64 | override fun sizeInTokens(text: String): Int = -1 // TODO 65 | 66 | override suspend fun generateResponse(inputText: String): String { 67 | if (initialized.value.not()) { 68 | throw IllegalStateException("LLMInference is not initialized properly") 69 | } 70 | return delegate.generateResponse(inputText) 71 | } 72 | 73 | override suspend fun generateResponseAsync(inputText: String): Flow> { 74 | if (initialized.value.not()) { 75 | throw IllegalStateException("LLMInference is not initialized properly") 76 | } 77 | val partialResultsFlow = MutableSharedFlow>( 78 | extraBufferCapacity = 1, 79 | onBufferOverflow = BufferOverflow.DROP_OLDEST 80 | ) 81 | delegate.generateResponseAsync(inputText, { partialResponse -> 82 | partialResultsFlow.tryEmit(partialResponse to false) 83 | }, { completion -> 84 | partialResultsFlow.tryEmit(completion to true) 85 | }) 86 | return partialResultsFlow.asSharedFlow() 87 | } 88 | 89 | } 90 | 91 | interface LLMOperatorSwift { 92 | suspend fun loadModel(modelName: String) 93 | fun sizeInTokens(text: String): Int 94 | suspend fun generateResponse(inputText: String): String 95 | suspend fun generateResponseAsync( 96 | inputText: String, 97 | progress: (partialResponse: String) -> Unit, 98 | completion: (completeResponse: String) -> Unit 99 | ) 100 | } -------------------------------------------------------------------------------- /app/src/iosMain/kotlin/me.xx2bab.mediapiper/theme/Theme.ios.kt: -------------------------------------------------------------------------------- 1 | package me.xx2bab.mediapiper.theme 2 | 3 | import androidx.compose.runtime.Composable 4 | import androidx.compose.runtime.LaunchedEffect 5 | import platform.UIKit.UIApplication 6 | import platform.UIKit.UIStatusBarStyleDarkContent 7 | import platform.UIKit.UIStatusBarStyleLightContent 8 | import platform.UIKit.setStatusBarStyle 9 | 10 | @Composable 11 | internal actual fun SystemAppearance(isLight: Boolean) { 12 | LaunchedEffect(isLight) { 13 | UIApplication.sharedApplication.setStatusBarStyle( 14 | if (isLight) UIStatusBarStyleDarkContent else UIStatusBarStyleLightContent 15 | ) 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.multiplatform).apply(false) 3 | alias(libs.plugins.cocoapods).apply(false) 4 | alias(libs.plugins.compose).apply(false) 5 | alias(libs.plugins.android.application).apply(false) 6 | alias(libs.plugins.buildConfig).apply(false) 7 | alias(libs.plugins.kotlinx.serialization).apply(false) 8 | alias(libs.plugins.kotlinx.atomicfu).apply(true) 9 | } 10 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Gradle 2 | org.gradle.jvmargs=-Xmx4G -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx4G" 3 | org.gradle.caching=true 4 | org.gradle.configuration-cache=true 5 | org.gradle.daemon=true 6 | org.gradle.parallel=true 7 | 8 | # Kotlin 9 | kotlin.code.style=official 10 | kotlin.js.compiler=ir 11 | kotlin.mpp.androidGradlePluginCompatibility.nowarn=true 12 | 13 | # Android 14 | android.useAndroidX=true 15 | android.nonTransitiveRClass=true 16 | 17 | # Compose 18 | org.jetbrains.compose.experimental.uikit.enabled=true 19 | org.jetbrains.compose.experimental.jscanvas.enabled=true 20 | org.jetbrains.compose.experimental.wasm.enabled=true 21 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | 3 | appdirs = "1.2.2" 4 | kotlin = "2.0.10" 5 | compose = "1.6.11" 6 | agp = "8.5.2" 7 | androidx-activityCompose = "1.9.1" 8 | androidx-uiTest = "1.6.8" 9 | androidx-lifecycle = "2.8.4" 10 | voyager = "1.1.0-beta02" 11 | napier = "2.7.1" 12 | buildConfig = "5.4.0" 13 | kotlinx-coroutines = "1.9.0-RC.2" 14 | ktor = "3.0.0-beta-2" 15 | koin = "3.5.6" 16 | coil = "3.0.0-alpha10" 17 | kstore = "0.8.0" 18 | 19 | [libraries] 20 | 21 | androidx-activityCompose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" } 22 | androidx-testManifest = { module = "androidx.compose.ui:ui-test-manifest", version.ref = "androidx-uiTest" } 23 | androidx-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "androidx-uiTest" } 24 | androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" } 25 | androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref= "androidx-lifecycle" } 26 | appdirs = { module = "net.harawata:appdirs", version.ref = "appdirs" } 27 | voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.ref = "voyager" } 28 | voyager-screenmodel = { module = "cafe.adriel.voyager:voyager-screenmodel", version.ref = "voyager" } 29 | voyager-transitions = { module = "cafe.adriel.voyager:voyager-transitions", version.ref = "voyager" } 30 | napier = { module = "io.github.aakira:napier", version.ref = "napier" } 31 | kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } 32 | kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" } 33 | kotlinx-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" } 34 | kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" } 35 | ktor-client-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" } 36 | ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } 37 | ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" } 38 | ktor-client-auth = { module = "io.ktor:ktor-client-auth", version.ref = "ktor" } 39 | ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" } 40 | ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" } 41 | ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" } 42 | ktor-client-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" } 43 | koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" } 44 | koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" } 45 | koin-compose = { module = "io.insert-koin:koin-compose", version = "1.1.5" } 46 | coil = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" } 47 | coil-network-ktor = { module = "io.coil-kt.coil3:coil-network-ktor", version = "3.0.0-alpha08" } 48 | kstore = { module = "io.github.xxfast:kstore", version.ref = "kstore" } 49 | kstore-file = { module = "io.github.xxfast:kstore-file", version.ref = "kstore" } 50 | kstore-storage = { module = "io.github.xxfast:kstore-storage", version.ref = "kstore" } 51 | 52 | mediapipe-genai-android = { module = "com.google.mediapipe:tasks-genai", version = "0.10.14" } 53 | 54 | [plugins] 55 | 56 | multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } 57 | cocoapods = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref = "kotlin" } 58 | compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } 59 | compose = { id = "org.jetbrains.compose", version.ref = "compose" } 60 | android-application = { id = "com.android.application", version.ref = "agp" } 61 | buildConfig = { id = "com.github.gmazzo.buildconfig", version.ref = "buildConfig" } 62 | kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } 63 | kotlinx-atomicfu = { id = "org.jetbrains.kotlin.plugin.atomicfu", version.ref = "kotlin" } 64 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | 2 | #!/usr/bin/env sh 3 | 4 | # 5 | # Copyright 2015 the original author or authors. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | ############################################################################## 21 | ## 22 | ## Gradle start up script for UN*X 23 | ## 24 | ############################################################################## 25 | 26 | # Attempt to set APP_HOME 27 | # Resolve links: ${'$'}0 may be a link 28 | PRG="$0" 29 | # Need this for relative symlinks. 30 | while [ -h "$PRG" ] ; do 31 | ls=`ls -ld "$PRG"` 32 | link=`expr "$ls" : '.*-> \(.*\)${'$'}'` 33 | if expr "$link" : '/.*' > /dev/null; then 34 | PRG="$link" 35 | else 36 | PRG=`dirname "$PRG"`"/$link" 37 | fi 38 | done 39 | SAVED="`pwd`" 40 | cd "`dirname \"$PRG\"`/" >/dev/null 41 | APP_HOME="`pwd -P`" 42 | cd "$SAVED" >/dev/null 43 | 44 | APP_NAME="Gradle" 45 | APP_BASE_NAME=`basename "$0"` 46 | 47 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 48 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 49 | 50 | # Use the maximum available, or set MAX_FD != -1 to use that value. 51 | MAX_FD="maximum" 52 | 53 | warn () { 54 | echo "${'$'}*" 55 | } 56 | 57 | die () { 58 | echo 59 | echo "${'$'}*" 60 | echo 61 | exit 1 62 | } 63 | 64 | # OS specific support (must be 'true' or 'false'). 65 | cygwin=false 66 | msys=false 67 | darwin=false 68 | nonstop=false 69 | case "`uname`" in 70 | CYGWIN* ) 71 | cygwin=true 72 | ;; 73 | Darwin* ) 74 | darwin=true 75 | ;; 76 | MSYS* | MINGW* ) 77 | msys=true 78 | ;; 79 | NONSTOP* ) 80 | nonstop=true 81 | ;; 82 | esac 83 | 84 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 85 | 86 | 87 | # Determine the Java command to use to start the JVM. 88 | if [ -n "$JAVA_HOME" ] ; then 89 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 90 | # IBM's JDK on AIX uses strange locations for the executables 91 | JAVACMD="$JAVA_HOME/jre/sh/java" 92 | else 93 | JAVACMD="$JAVA_HOME/bin/java" 94 | fi 95 | if [ ! -x "$JAVACMD" ] ; then 96 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 97 | 98 | Please set the JAVA_HOME variable in your environment to match the 99 | location of your Java installation." 100 | fi 101 | else 102 | JAVACMD="java" 103 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 104 | 105 | Please set the JAVA_HOME variable in your environment to match the 106 | location of your Java installation." 107 | fi 108 | 109 | # Increase the maximum file descriptors if we can. 110 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 111 | MAX_FD_LIMIT=`ulimit -H -n` 112 | if [ $? -eq 0 ] ; then 113 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 114 | MAX_FD="$MAX_FD_LIMIT" 115 | fi 116 | ulimit -n $MAX_FD 117 | if [ $? -ne 0 ] ; then 118 | warn "Could not set maximum file descriptor limit: $MAX_FD" 119 | fi 120 | else 121 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 122 | fi 123 | fi 124 | 125 | # For Darwin, add options to specify how the application appears in the dock 126 | if $darwin; then 127 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 128 | fi 129 | 130 | # For Cygwin or MSYS, switch paths to Windows format before running java 131 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 132 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 133 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 134 | 135 | JAVACMD=`cygpath --unix "$JAVACMD"` 136 | 137 | # We build the pattern for arguments to be converted via cygpath 138 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 139 | SEP="" 140 | for dir in $ROOTDIRSRAW ; do 141 | ROOTDIRS="$ROOTDIRS$SEP$dir" 142 | SEP="|" 143 | done 144 | OURCYGPATTERN="(^($ROOTDIRS))" 145 | # Add a user-defined pattern to the cygpath arguments 146 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 147 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 148 | fi 149 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 150 | i=0 151 | for arg in "$@" ; do 152 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 153 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 154 | 155 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 156 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 157 | else 158 | eval `echo args$i`="\"$arg\"" 159 | fi 160 | i=`expr $i + 1` 161 | done 162 | case $i in 163 | 0) set -- ;; 164 | 1) set -- "$args0" ;; 165 | 2) set -- "$args0" "$args1" ;; 166 | 3) set -- "$args0" "$args1" "$args2" ;; 167 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 168 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 169 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 170 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 171 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 172 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 173 | esac 174 | fi 175 | 176 | # Escape application args 177 | save () { 178 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 179 | echo " " 180 | } 181 | APP_ARGS=`save "$@"` 182 | 183 | # Collect all arguments for the java command, following the shell quoting and substitution rules 184 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 185 | 186 | exec "$JAVACMD" "$@" 187 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | 2 | @rem 3 | @rem Copyright 2015 the original author or authors. 4 | @rem 5 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 6 | @rem you may not use this file except in compliance with the License. 7 | @rem You may obtain a copy of the License at 8 | @rem 9 | @rem https://www.apache.org/licenses/LICENSE-2.0 10 | @rem 11 | @rem Unless required by applicable law or agreed to in writing, software 12 | @rem distributed under the License is distributed on an "AS IS" BASIS, 13 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | @rem See the License for the specific language governing permissions and 15 | @rem limitations under the License. 16 | @rem 17 | 18 | @if "%DEBUG%" == "" @echo off 19 | @rem ########################################################################## 20 | @rem 21 | @rem Gradle startup script for Windows 22 | @rem 23 | @rem ########################################################################## 24 | 25 | @rem Set local scope for the variables with windows NT shell 26 | if "%OS%"=="Windows_NT" setlocal 27 | 28 | set DIRNAME=%~dp0 29 | if "%DIRNAME%" == "" set DIRNAME=. 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if "%ERRORLEVEL%" == "0" goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /iosApp/.gitignore: -------------------------------------------------------------------------------- 1 | xcuserdata/ 2 | 3 | .build/ 4 | 5 | ## Obj-C/Swift specific 6 | *.hmap 7 | 8 | ## App packaging 9 | *.ipa 10 | *.dSYM.zip 11 | *.dSYM 12 | 13 | ## Playgrounds 14 | timeline.xctimeline 15 | playground.xcworkspace -------------------------------------------------------------------------------- /iosApp/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'iosApp' do 5 | # Comment the next line if you don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | # Pods for iosApp 9 | pod 'Mediapiper', :path => '../app' 10 | 11 | end 12 | -------------------------------------------------------------------------------- /iosApp/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Mediapiper (1.0.1): 3 | - MediaPipeTasksGenAI (= 0.10.14) 4 | - MediaPipeTasksGenAIC (= 0.10.14) 5 | - MediaPipeTasksGenAI (0.10.14): 6 | - MediaPipeTasksGenAIC (= 0.10.14) 7 | - MediaPipeTasksGenAIC (0.10.14) 8 | 9 | DEPENDENCIES: 10 | - Mediapiper (from `../app`) 11 | 12 | SPEC REPOS: 13 | trunk: 14 | - MediaPipeTasksGenAI 15 | - MediaPipeTasksGenAIC 16 | 17 | EXTERNAL SOURCES: 18 | Mediapiper: 19 | :path: "../app" 20 | 21 | SPEC CHECKSUMS: 22 | Mediapiper: d64d2cb0f33ec905a807ac58291f9695949883c3 23 | MediaPipeTasksGenAI: 8cd77fa32ea21f7a6319b025aa28cfc3e20ab73b 24 | MediaPipeTasksGenAIC: 270ec81f85e96fac283945702e34112ebbfd5e77 25 | 26 | PODFILE CHECKSUM: fb5292835e750a992d246cbe047046c4e4fdc625 27 | 28 | COCOAPODS: 1.15.2 29 | -------------------------------------------------------------------------------- /iosApp/Pods/Local Podspecs/Mediapiper.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Mediapiper", 3 | "version": "1.0.1", 4 | "homepage": "https://github.com/2BAB/Mediapiper", 5 | "source": { 6 | "http": "" 7 | }, 8 | "authors": "", 9 | "license": "", 10 | "summary": "Mediapiper", 11 | "vendored_frameworks": "build/cocoapods/framework/app.framework", 12 | "libraries": "c++", 13 | "platforms": { 14 | "ios": "15" 15 | }, 16 | "dependencies": { 17 | "MediaPipeTasksGenAI": [ 18 | "0.10.14" 19 | ], 20 | "MediaPipeTasksGenAIC": [ 21 | "0.10.14" 22 | ] 23 | }, 24 | "xcconfig": { 25 | "ENABLE_USER_SCRIPT_SANDBOXING": "NO" 26 | }, 27 | "pod_target_xcconfig": { 28 | "KOTLIN_PROJECT_PATH": ":app", 29 | "PRODUCT_MODULE_NAME": "app" 30 | }, 31 | "script_phases": [ 32 | { 33 | "name": "Build Mediapiper", 34 | "execution_position": "before_compile", 35 | "shell_path": "/bin/sh", 36 | "script": " if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\"\"\n exit 0\n fi\n set -ev\n REPO_ROOT=\"$PODS_TARGET_SRCROOT\"\n \"$REPO_ROOT/../gradlew\" -p \"$REPO_ROOT\" $KOTLIN_PROJECT_PATH:syncFramework -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME -Pkotlin.native.cocoapods.archs=\"$ARCHS\" -Pkotlin.native.cocoapods.configuration=\"$CONFIGURATION\"\n" 37 | } 38 | ], 39 | "resources": [ 40 | "build/compose/cocoapods/compose-resources" 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /iosApp/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Mediapiper (1.0.1): 3 | - MediaPipeTasksGenAI (= 0.10.14) 4 | - MediaPipeTasksGenAIC (= 0.10.14) 5 | - MediaPipeTasksGenAI (0.10.14): 6 | - MediaPipeTasksGenAIC (= 0.10.14) 7 | - MediaPipeTasksGenAIC (0.10.14) 8 | 9 | DEPENDENCIES: 10 | - Mediapiper (from `../app`) 11 | 12 | SPEC REPOS: 13 | trunk: 14 | - MediaPipeTasksGenAI 15 | - MediaPipeTasksGenAIC 16 | 17 | EXTERNAL SOURCES: 18 | Mediapiper: 19 | :path: "../app" 20 | 21 | SPEC CHECKSUMS: 22 | Mediapiper: d64d2cb0f33ec905a807ac58291f9695949883c3 23 | MediaPipeTasksGenAI: 8cd77fa32ea21f7a6319b025aa28cfc3e20ab73b 24 | MediaPipeTasksGenAIC: 270ec81f85e96fac283945702e34112ebbfd5e77 25 | 26 | PODFILE CHECKSUM: fb5292835e750a992d246cbe047046c4e4fdc625 27 | 28 | COCOAPODS: 1.15.2 29 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAI/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | =========================================================================== 204 | For files under tasks/cc/text/language_detector/custom_ops/utils/utf/ 205 | =========================================================================== 206 | /* 207 | * The authors of this software are Rob Pike and Ken Thompson. 208 | * Copyright (c) 2002 by Lucent Technologies. 209 | * Permission to use, copy, modify, and distribute this software for any 210 | * purpose without fee is hereby granted, provided that this entire notice 211 | * is included in all copies of any software which is or includes a copy 212 | * or modification of this software and in all copies of the supporting 213 | * documentation for such software. 214 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 215 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY 216 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 217 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 218 | */ 219 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AvailableLibraries 6 | 7 | 8 | LibraryIdentifier 9 | ios-arm64 10 | LibraryPath 11 | MediaPipeTasksGenAI.framework 12 | SupportedArchitectures 13 | 14 | arm64 15 | 16 | SupportedPlatform 17 | ios 18 | 19 | 20 | LibraryIdentifier 21 | ios-arm64_x86_64-simulator 22 | LibraryPath 23 | MediaPipeTasksGenAI.framework 24 | SupportedArchitectures 25 | 26 | arm64 27 | x86_64 28 | 29 | SupportedPlatform 30 | ios 31 | SupportedPlatformVariant 32 | simulator 33 | 34 | 35 | CFBundlePackageType 36 | XFWK 37 | XCFrameworkFormatVersion 38 | 1.0 39 | 40 | 41 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64/MediaPipeTasksGenAI.framework/MediaPipeTasksGenAI: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64/MediaPipeTasksGenAI.framework/MediaPipeTasksGenAI -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64/MediaPipeTasksGenAI.framework/Modules/MediaPipeTasksGenAI.swiftmodule/arm64.swiftdoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64/MediaPipeTasksGenAI.framework/Modules/MediaPipeTasksGenAI.swiftmodule/arm64.swiftdoc -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64/MediaPipeTasksGenAI.framework/Modules/MediaPipeTasksGenAI.swiftmodule/arm64.swiftinterface: -------------------------------------------------------------------------------- 1 | // swift-interface-format-version: 1.0 2 | // swift-compiler-version: Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51) 3 | // swift-module-flags: -target arm64-apple-ios12.0 -enable-objc-interop -enable-library-evolution -static -O -module-name MediaPipeTasksGenAI 4 | // swift-module-flags-ignorable: -enable-bare-slash-regex 5 | import Foundation 6 | import MediaPipeTasksGenAIC 7 | import Swift 8 | import _Concurrency 9 | import _StringProcessing 10 | @objc(MPPLLMInference) final public class LlmInference : ObjectiveC.NSObject { 11 | @objc public init(options: MediaPipeTasksGenAI.LlmInference.Options) throws 12 | @objc convenience public init(modelPath: Swift.String) throws 13 | @objc final public func generateResponse(inputText: Swift.String) throws -> Swift.String 14 | @objc final public func generateResponseAsync(inputText: Swift.String, progress: @escaping (_ partialResponse: Swift.String?, _ error: Swift.Error?) -> Swift.Void, completion: @escaping (() -> Swift.Void)) throws 15 | @available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *) 16 | final public func generateResponseAsync(inputText: Swift.String) -> _Concurrency.AsyncThrowingStream 17 | final public func sizeInTokens(text: Swift.String) throws -> Swift.Int 18 | @objc deinit 19 | } 20 | extension MediaPipeTasksGenAI.LlmInference { 21 | @objc(MPPLLMInferenceOptions) final public class Options : ObjectiveC.NSObject { 22 | @objc final public var modelPath: Swift.String 23 | @objc final public var maxTokens: Swift.Int 24 | @objc final public var topk: Swift.Int 25 | @objc final public var temperature: Swift.Float 26 | @objc final public var randomSeed: Swift.Int 27 | @objc final public var loraPath: Swift.String? 28 | @objc public init(modelPath: Swift.String) 29 | @objc deinit 30 | } 31 | } 32 | public enum GenAiInferenceError : Swift.Error { 33 | case invalidResponse 34 | case illegalMethodCall 35 | case failedToComputeSizeInTokens(Swift.String?) 36 | case failedToInitializeSession(Swift.String?) 37 | } 38 | extension MediaPipeTasksGenAI.GenAiInferenceError : Foundation.LocalizedError { 39 | public var errorDescription: Swift.String? { 40 | get 41 | } 42 | } 43 | extension MediaPipeTasksGenAI.GenAiInferenceError : Foundation.CustomNSError { 44 | public static var errorDomain: Swift.String { 45 | get 46 | } 47 | public var errorCode: Swift.Int { 48 | get 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64/MediaPipeTasksGenAI.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module MediaPipeTasksGenAI { 2 | header "MediaPipeTasksGenAI.h" 3 | requires objc 4 | } 5 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAI.framework/MediaPipeTasksGenAI: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAI.framework/MediaPipeTasksGenAI -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAI.framework/Modules/MediaPipeTasksGenAI.swiftmodule/arm64.swiftdoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAI.framework/Modules/MediaPipeTasksGenAI.swiftmodule/arm64.swiftdoc -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAI.framework/Modules/MediaPipeTasksGenAI.swiftmodule/arm64.swiftinterface: -------------------------------------------------------------------------------- 1 | // swift-interface-format-version: 1.0 2 | // swift-compiler-version: Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51) 3 | // swift-module-flags: -target arm64-apple-ios12.0-simulator -enable-objc-interop -enable-library-evolution -static -O -module-name MediaPipeTasksGenAI 4 | // swift-module-flags-ignorable: -enable-bare-slash-regex 5 | import Foundation 6 | import MediaPipeTasksGenAIC 7 | import Swift 8 | import _Concurrency 9 | import _StringProcessing 10 | @objc(MPPLLMInference) final public class LlmInference : ObjectiveC.NSObject { 11 | @objc public init(options: MediaPipeTasksGenAI.LlmInference.Options) throws 12 | @objc convenience public init(modelPath: Swift.String) throws 13 | @objc final public func generateResponse(inputText: Swift.String) throws -> Swift.String 14 | @objc final public func generateResponseAsync(inputText: Swift.String, progress: @escaping (_ partialResponse: Swift.String?, _ error: Swift.Error?) -> Swift.Void, completion: @escaping (() -> Swift.Void)) throws 15 | @available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *) 16 | final public func generateResponseAsync(inputText: Swift.String) -> _Concurrency.AsyncThrowingStream 17 | final public func sizeInTokens(text: Swift.String) throws -> Swift.Int 18 | @objc deinit 19 | } 20 | extension MediaPipeTasksGenAI.LlmInference { 21 | @objc(MPPLLMInferenceOptions) final public class Options : ObjectiveC.NSObject { 22 | @objc final public var modelPath: Swift.String 23 | @objc final public var maxTokens: Swift.Int 24 | @objc final public var topk: Swift.Int 25 | @objc final public var temperature: Swift.Float 26 | @objc final public var randomSeed: Swift.Int 27 | @objc final public var loraPath: Swift.String? 28 | @objc public init(modelPath: Swift.String) 29 | @objc deinit 30 | } 31 | } 32 | public enum GenAiInferenceError : Swift.Error { 33 | case invalidResponse 34 | case illegalMethodCall 35 | case failedToComputeSizeInTokens(Swift.String?) 36 | case failedToInitializeSession(Swift.String?) 37 | } 38 | extension MediaPipeTasksGenAI.GenAiInferenceError : Foundation.LocalizedError { 39 | public var errorDescription: Swift.String? { 40 | get 41 | } 42 | } 43 | extension MediaPipeTasksGenAI.GenAiInferenceError : Foundation.CustomNSError { 44 | public static var errorDomain: Swift.String { 45 | get 46 | } 47 | public var errorCode: Swift.Int { 48 | get 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAI.framework/Modules/MediaPipeTasksGenAI.swiftmodule/x86_64.swiftdoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAI.framework/Modules/MediaPipeTasksGenAI.swiftmodule/x86_64.swiftdoc -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAI.framework/Modules/MediaPipeTasksGenAI.swiftmodule/x86_64.swiftinterface: -------------------------------------------------------------------------------- 1 | // swift-interface-format-version: 1.0 2 | // swift-compiler-version: Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51) 3 | // swift-module-flags: -target x86_64-apple-ios12.0-simulator -enable-objc-interop -enable-library-evolution -static -O -module-name MediaPipeTasksGenAI 4 | // swift-module-flags-ignorable: -enable-bare-slash-regex 5 | import Foundation 6 | import MediaPipeTasksGenAIC 7 | import Swift 8 | import _Concurrency 9 | import _StringProcessing 10 | @objc(MPPLLMInference) final public class LlmInference : ObjectiveC.NSObject { 11 | @objc public init(options: MediaPipeTasksGenAI.LlmInference.Options) throws 12 | @objc convenience public init(modelPath: Swift.String) throws 13 | @objc final public func generateResponse(inputText: Swift.String) throws -> Swift.String 14 | @objc final public func generateResponseAsync(inputText: Swift.String, progress: @escaping (_ partialResponse: Swift.String?, _ error: Swift.Error?) -> Swift.Void, completion: @escaping (() -> Swift.Void)) throws 15 | @available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *) 16 | final public func generateResponseAsync(inputText: Swift.String) -> _Concurrency.AsyncThrowingStream 17 | final public func sizeInTokens(text: Swift.String) throws -> Swift.Int 18 | @objc deinit 19 | } 20 | extension MediaPipeTasksGenAI.LlmInference { 21 | @objc(MPPLLMInferenceOptions) final public class Options : ObjectiveC.NSObject { 22 | @objc final public var modelPath: Swift.String 23 | @objc final public var maxTokens: Swift.Int 24 | @objc final public var topk: Swift.Int 25 | @objc final public var temperature: Swift.Float 26 | @objc final public var randomSeed: Swift.Int 27 | @objc final public var loraPath: Swift.String? 28 | @objc public init(modelPath: Swift.String) 29 | @objc deinit 30 | } 31 | } 32 | public enum GenAiInferenceError : Swift.Error { 33 | case invalidResponse 34 | case illegalMethodCall 35 | case failedToComputeSizeInTokens(Swift.String?) 36 | case failedToInitializeSession(Swift.String?) 37 | } 38 | extension MediaPipeTasksGenAI.GenAiInferenceError : Foundation.LocalizedError { 39 | public var errorDescription: Swift.String? { 40 | get 41 | } 42 | } 43 | extension MediaPipeTasksGenAI.GenAiInferenceError : Foundation.CustomNSError { 44 | public static var errorDomain: Swift.String { 45 | get 46 | } 47 | public var errorCode: Swift.Int { 48 | get 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAI.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module MediaPipeTasksGenAI { 2 | header "MediaPipeTasksGenAI.h" 3 | requires objc 4 | } 5 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AvailableLibraries 6 | 7 | 8 | LibraryIdentifier 9 | ios-arm64 10 | LibraryPath 11 | MediaPipeTasksGenAIC.framework 12 | SupportedArchitectures 13 | 14 | arm64 15 | 16 | SupportedPlatform 17 | ios 18 | 19 | 20 | LibraryIdentifier 21 | ios-arm64_x86_64-simulator 22 | LibraryPath 23 | MediaPipeTasksGenAIC.framework 24 | SupportedArchitectures 25 | 26 | arm64 27 | x86_64 28 | 29 | SupportedPlatform 30 | ios 31 | SupportedPlatformVariant 32 | simulator 33 | 34 | 35 | CFBundlePackageType 36 | XFWK 37 | XCFrameworkFormatVersion 38 | 1.0 39 | 40 | 41 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework/ios-arm64/MediaPipeTasksGenAIC.framework/Headers/MediaPipeTasksGenAIC.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework/ios-arm64/MediaPipeTasksGenAIC.framework/Headers/llm_inference_engine.h: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The MediaPipe Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef MEDIAPIPE_TASKS_GENAI_INFERENCE_C_LLM_INFERENCE_ENGINE_H_ 16 | #define MEDIAPIPE_TASKS_GENAI_INFERENCE_C_LLM_INFERENCE_ENGINE_H_ 17 | 18 | #ifdef __cplusplus 19 | #include 20 | #else 21 | #include 22 | #include 23 | #include 24 | #endif 25 | 26 | #ifndef ODML_EXPORT 27 | #define ODML_EXPORT __attribute__((visibility("default"))) 28 | #endif // ODML_EXPORT 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | typedef void LlmInferenceEngine_Session; 35 | 36 | // LlmSessionConfig configures how to execute the model. 37 | typedef struct { 38 | // Path to the model artifact. 39 | const char* model_path; 40 | 41 | // Directory path for storing model related tokenizer and cache weights. the 42 | // user is responsible for providing the directory that can be writable by the 43 | // program. 44 | const char* cache_dir; 45 | 46 | // Sequence batch size for encoding. Used by GPU only. Number of input tokens 47 | // to process at a time for batch processing. Setting this value to 1 means 48 | // both the encoding and decoding share the same graph of sequence length 49 | // of 1. Setting this value to 0 means the batch size will be optimized 50 | // programmatically. 51 | size_t sequence_batch_size; 52 | 53 | // Number of decode steps per sync. Used by GPU only. The default value is 3. 54 | size_t num_decode_steps_per_sync; 55 | 56 | // Maximum number of tokens for input and output. 57 | size_t max_tokens; 58 | 59 | // Top K number of tokens to be sampled from for each decoding step. 60 | size_t topk; 61 | 62 | // Maximum cumulative probability over the tokens to sample from in each 63 | // decoding step for top-p / nucleus sampling. 64 | float topp; 65 | 66 | // Randomness when decoding the next token, 0.0f means greedy decoding. 67 | float temperature; 68 | 69 | // Random seed for sampling tokens. 70 | size_t random_seed; 71 | 72 | // Path to the LoRA tflite flatbuffer file. Optional. 73 | // This is only compatible with GPU models. 74 | const char* lora_path; 75 | } LlmSessionConfig; 76 | 77 | // LlmResponseContext is the return type for 78 | // LlmInferenceEngine_Session_PredictSync. 79 | typedef struct { 80 | // An array of string. The size of the array depends on the number of 81 | // responses. 82 | char** response_array; 83 | 84 | // Number of responses. 85 | int response_count; 86 | 87 | // Done all outputs for this session. 88 | bool done; 89 | } LlmResponseContext; 90 | 91 | // Frees all context within the LlmResponseContext. 92 | ODML_EXPORT void LlmInferenceEngine_CloseResponseContext( 93 | LlmResponseContext* response_context); 94 | 95 | // Create a LlmInferenceEngine session for executing a query. 96 | ODML_EXPORT int LlmInferenceEngine_CreateSession( 97 | const LlmSessionConfig* session_config, 98 | LlmInferenceEngine_Session** session_out, char** error_msg); 99 | 100 | // Free the session, will wait until graph is done executing. 101 | ODML_EXPORT void LlmInferenceEngine_Session_Delete( 102 | LlmInferenceEngine_Session* session); 103 | 104 | // Return the generated output in sync mode. 105 | ODML_EXPORT LlmResponseContext LlmInferenceEngine_Session_PredictSync( 106 | LlmInferenceEngine_Session* session, const char* input); 107 | 108 | // Run callback function in async mode. 109 | // The callback will be invoked multiple times until `response_context.done` 110 | // is `true`. You need to invoke `LlmInferenceEngine_CloseResponseContext` after 111 | // each invocation to free memory. 112 | // The callback context can be a pointer to any user defined data structure as 113 | // it is passed to the callback unmodified. 114 | ODML_EXPORT void LlmInferenceEngine_Session_PredictAsync( 115 | LlmInferenceEngine_Session* session, void* callback_context, 116 | const char* input, 117 | void (*callback)(void* callback_context, 118 | LlmResponseContext* response_context)); 119 | 120 | // Tokenizes an input prompt using a pre-existing processor and returns its 121 | // length in tokens. Returns -1 if tokenization fails. 122 | ODML_EXPORT int LlmInferenceEngine_Session_SizeInTokens( 123 | LlmInferenceEngine_Session* session, const char* input, char** error_msg); 124 | 125 | #ifdef __cplusplus 126 | } // extern C 127 | #endif 128 | 129 | #endif // MEDIAPIPE_TASKS_GENAI_INFERENCE_C_LLM_INFERENCE_ENGINE_H_ 130 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework/ios-arm64/MediaPipeTasksGenAIC.framework/MediaPipeTasksGenAIC: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/iosApp/Pods/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework/ios-arm64/MediaPipeTasksGenAIC.framework/MediaPipeTasksGenAIC -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework/ios-arm64/MediaPipeTasksGenAIC.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module MediaPipeTasksGenAIC { 2 | umbrella header "MediaPipeTasksGenAIC.h" 3 | export * 4 | module * { export * } 5 | link "dl" 6 | link "m" 7 | link "pthread" 8 | link framework "Accelerate" 9 | link framework "CoreFoundation" 10 | link framework "CoreGraphics" 11 | link framework "CoreVideo" 12 | link framework "Metal" 13 | link framework "OpenGLES" 14 | } 15 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAIC.framework/Headers/MediaPipeTasksGenAIC.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAIC.framework/Headers/llm_inference_engine.h: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The MediaPipe Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef MEDIAPIPE_TASKS_GENAI_INFERENCE_C_LLM_INFERENCE_ENGINE_H_ 16 | #define MEDIAPIPE_TASKS_GENAI_INFERENCE_C_LLM_INFERENCE_ENGINE_H_ 17 | 18 | #ifdef __cplusplus 19 | #include 20 | #else 21 | #include 22 | #include 23 | #include 24 | #endif 25 | 26 | #ifndef ODML_EXPORT 27 | #define ODML_EXPORT __attribute__((visibility("default"))) 28 | #endif // ODML_EXPORT 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | typedef void LlmInferenceEngine_Session; 35 | 36 | // LlmSessionConfig configures how to execute the model. 37 | typedef struct { 38 | // Path to the model artifact. 39 | const char* model_path; 40 | 41 | // Directory path for storing model related tokenizer and cache weights. the 42 | // user is responsible for providing the directory that can be writable by the 43 | // program. 44 | const char* cache_dir; 45 | 46 | // Sequence batch size for encoding. Used by GPU only. Number of input tokens 47 | // to process at a time for batch processing. Setting this value to 1 means 48 | // both the encoding and decoding share the same graph of sequence length 49 | // of 1. Setting this value to 0 means the batch size will be optimized 50 | // programmatically. 51 | size_t sequence_batch_size; 52 | 53 | // Number of decode steps per sync. Used by GPU only. The default value is 3. 54 | size_t num_decode_steps_per_sync; 55 | 56 | // Maximum number of tokens for input and output. 57 | size_t max_tokens; 58 | 59 | // Top K number of tokens to be sampled from for each decoding step. 60 | size_t topk; 61 | 62 | // Maximum cumulative probability over the tokens to sample from in each 63 | // decoding step for top-p / nucleus sampling. 64 | float topp; 65 | 66 | // Randomness when decoding the next token, 0.0f means greedy decoding. 67 | float temperature; 68 | 69 | // Random seed for sampling tokens. 70 | size_t random_seed; 71 | 72 | // Path to the LoRA tflite flatbuffer file. Optional. 73 | // This is only compatible with GPU models. 74 | const char* lora_path; 75 | } LlmSessionConfig; 76 | 77 | // LlmResponseContext is the return type for 78 | // LlmInferenceEngine_Session_PredictSync. 79 | typedef struct { 80 | // An array of string. The size of the array depends on the number of 81 | // responses. 82 | char** response_array; 83 | 84 | // Number of responses. 85 | int response_count; 86 | 87 | // Done all outputs for this session. 88 | bool done; 89 | } LlmResponseContext; 90 | 91 | // Frees all context within the LlmResponseContext. 92 | ODML_EXPORT void LlmInferenceEngine_CloseResponseContext( 93 | LlmResponseContext* response_context); 94 | 95 | // Create a LlmInferenceEngine session for executing a query. 96 | ODML_EXPORT int LlmInferenceEngine_CreateSession( 97 | const LlmSessionConfig* session_config, 98 | LlmInferenceEngine_Session** session_out, char** error_msg); 99 | 100 | // Free the session, will wait until graph is done executing. 101 | ODML_EXPORT void LlmInferenceEngine_Session_Delete( 102 | LlmInferenceEngine_Session* session); 103 | 104 | // Return the generated output in sync mode. 105 | ODML_EXPORT LlmResponseContext LlmInferenceEngine_Session_PredictSync( 106 | LlmInferenceEngine_Session* session, const char* input); 107 | 108 | // Run callback function in async mode. 109 | // The callback will be invoked multiple times until `response_context.done` 110 | // is `true`. You need to invoke `LlmInferenceEngine_CloseResponseContext` after 111 | // each invocation to free memory. 112 | // The callback context can be a pointer to any user defined data structure as 113 | // it is passed to the callback unmodified. 114 | ODML_EXPORT void LlmInferenceEngine_Session_PredictAsync( 115 | LlmInferenceEngine_Session* session, void* callback_context, 116 | const char* input, 117 | void (*callback)(void* callback_context, 118 | LlmResponseContext* response_context)); 119 | 120 | // Tokenizes an input prompt using a pre-existing processor and returns its 121 | // length in tokens. Returns -1 if tokenization fails. 122 | ODML_EXPORT int LlmInferenceEngine_Session_SizeInTokens( 123 | LlmInferenceEngine_Session* session, const char* input, char** error_msg); 124 | 125 | #ifdef __cplusplus 126 | } // extern C 127 | #endif 128 | 129 | #endif // MEDIAPIPE_TASKS_GENAI_INFERENCE_C_LLM_INFERENCE_ENGINE_H_ 130 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAIC.framework/MediaPipeTasksGenAIC: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/iosApp/Pods/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAIC.framework/MediaPipeTasksGenAIC -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework/ios-arm64_x86_64-simulator/MediaPipeTasksGenAIC.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module MediaPipeTasksGenAIC { 2 | umbrella header "MediaPipeTasksGenAIC.h" 3 | export * 4 | module * { export * } 5 | link "dl" 6 | link "m" 7 | link "pthread" 8 | link framework "Accelerate" 9 | link framework "CoreFoundation" 10 | link framework "CoreGraphics" 11 | link framework "CoreVideo" 12 | link framework "Metal" 13 | link framework "OpenGLES" 14 | } 15 | -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAIC/frameworks/genai_libraries/libMediaPipeTasksGenAIC_device.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/iosApp/Pods/MediaPipeTasksGenAIC/frameworks/genai_libraries/libMediaPipeTasksGenAIC_device.a -------------------------------------------------------------------------------- /iosApp/Pods/MediaPipeTasksGenAIC/frameworks/genai_libraries/libMediaPipeTasksGenAIC_simulator.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/iosApp/Pods/MediaPipeTasksGenAIC/frameworks/genai_libraries/libMediaPipeTasksGenAIC_simulator.a -------------------------------------------------------------------------------- /iosApp/Pods/Pods.xcodeproj/xcuserdata/2bab.xcuserdatad/xcschemes/MediaPipeTasksGenAI.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /iosApp/Pods/Pods.xcodeproj/xcuserdata/2bab.xcuserdatad/xcschemes/MediaPipeTasksGenAIC.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /iosApp/Pods/Pods.xcodeproj/xcuserdata/2bab.xcuserdatad/xcschemes/Mediapiper.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /iosApp/Pods/Pods.xcodeproj/xcuserdata/2bab.xcuserdatad/xcschemes/Pods-iosApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /iosApp/Pods/Pods.xcodeproj/xcuserdata/2bab.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MediaPipeTasksGenAI.xcscheme 8 | 9 | isShown 10 | 11 | 12 | MediaPipeTasksGenAIC.xcscheme 13 | 14 | isShown 15 | 16 | 17 | Mediapiper.xcscheme 18 | 19 | isShown 20 | 21 | 22 | Pods-iosApp.xcscheme 23 | 24 | isShown 25 | 26 | 27 | 28 | SuppressBuildableAutocreation 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/MediaPipeTasksGenAI/MediaPipeTasksGenAI-xcframeworks-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/MediaPipeTasksGenAI/MediaPipeTasksGenAI-xcframeworks.sh 2 | ${PODS_ROOT}/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/MediaPipeTasksGenAI/MediaPipeTasksGenAI-xcframeworks-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAI/MediaPipeTasksGenAI.framework -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/MediaPipeTasksGenAI/MediaPipeTasksGenAI-xcframeworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | function on_error { 7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" 8 | } 9 | trap 'on_error $LINENO' ERR 10 | 11 | 12 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 13 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 14 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 15 | 16 | 17 | variant_for_slice() 18 | { 19 | case "$1" in 20 | "MediaPipeTasksGenAI.xcframework/ios-arm64") 21 | echo "" 22 | ;; 23 | "MediaPipeTasksGenAI.xcframework/ios-arm64_x86_64-simulator") 24 | echo "simulator" 25 | ;; 26 | esac 27 | } 28 | 29 | archs_for_slice() 30 | { 31 | case "$1" in 32 | "MediaPipeTasksGenAI.xcframework/ios-arm64") 33 | echo "arm64" 34 | ;; 35 | "MediaPipeTasksGenAI.xcframework/ios-arm64_x86_64-simulator") 36 | echo "arm64 x86_64" 37 | ;; 38 | esac 39 | } 40 | 41 | copy_dir() 42 | { 43 | local source="$1" 44 | local destination="$2" 45 | 46 | # Use filter instead of exclude so missing patterns don't throw errors. 47 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" \"${source}*\" \"${destination}\"" 48 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" "${source}"/* "${destination}" 49 | } 50 | 51 | SELECT_SLICE_RETVAL="" 52 | 53 | select_slice() { 54 | local xcframework_name="$1" 55 | xcframework_name="${xcframework_name##*/}" 56 | local paths=("${@:2}") 57 | # Locate the correct slice of the .xcframework for the current architectures 58 | local target_path="" 59 | 60 | # Split archs on space so we can find a slice that has all the needed archs 61 | local target_archs=$(echo $ARCHS | tr " " "\n") 62 | 63 | local target_variant="" 64 | if [[ "$PLATFORM_NAME" == *"simulator" ]]; then 65 | target_variant="simulator" 66 | fi 67 | if [[ ! -z ${EFFECTIVE_PLATFORM_NAME+x} && "$EFFECTIVE_PLATFORM_NAME" == *"maccatalyst" ]]; then 68 | target_variant="maccatalyst" 69 | fi 70 | for i in ${!paths[@]}; do 71 | local matched_all_archs="1" 72 | local slice_archs="$(archs_for_slice "${xcframework_name}/${paths[$i]}")" 73 | local slice_variant="$(variant_for_slice "${xcframework_name}/${paths[$i]}")" 74 | for target_arch in $target_archs; do 75 | if ! [[ "${slice_variant}" == "$target_variant" ]]; then 76 | matched_all_archs="0" 77 | break 78 | fi 79 | 80 | if ! echo "${slice_archs}" | tr " " "\n" | grep -F -q -x "$target_arch"; then 81 | matched_all_archs="0" 82 | break 83 | fi 84 | done 85 | 86 | if [[ "$matched_all_archs" == "1" ]]; then 87 | # Found a matching slice 88 | echo "Selected xcframework slice ${paths[$i]}" 89 | SELECT_SLICE_RETVAL=${paths[$i]} 90 | break 91 | fi 92 | done 93 | } 94 | 95 | install_xcframework() { 96 | local basepath="$1" 97 | local name="$2" 98 | local package_type="$3" 99 | local paths=("${@:4}") 100 | 101 | # Locate the correct slice of the .xcframework for the current architectures 102 | select_slice "${basepath}" "${paths[@]}" 103 | local target_path="$SELECT_SLICE_RETVAL" 104 | if [[ -z "$target_path" ]]; then 105 | echo "warning: [CP] $(basename ${basepath}): Unable to find matching slice in '${paths[@]}' for the current build architectures ($ARCHS) and platform (${EFFECTIVE_PLATFORM_NAME-${PLATFORM_NAME}})." 106 | return 107 | fi 108 | local source="$basepath/$target_path" 109 | 110 | local destination="${PODS_XCFRAMEWORKS_BUILD_DIR}/${name}" 111 | 112 | if [ ! -d "$destination" ]; then 113 | mkdir -p "$destination" 114 | fi 115 | 116 | copy_dir "$source/" "$destination" 117 | echo "Copied $source to $destination" 118 | } 119 | 120 | install_xcframework "${PODS_ROOT}/MediaPipeTasksGenAI/frameworks/MediaPipeTasksGenAI.xcframework" "MediaPipeTasksGenAI" "framework" "ios-arm64" "ios-arm64_x86_64-simulator" 121 | 122 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/MediaPipeTasksGenAI/MediaPipeTasksGenAI.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MediaPipeTasksGenAI 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/MediaPipeTasksGenAI/frameworks" "${PODS_ROOT}/MediaPipeTasksGenAIC/frameworks" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAI" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAIC" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 9 | PODS_ROOT = ${SRCROOT} 10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/MediaPipeTasksGenAI 11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 13 | SKIP_INSTALL = YES 14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 15 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/MediaPipeTasksGenAI/MediaPipeTasksGenAI.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MediaPipeTasksGenAI 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/MediaPipeTasksGenAI/frameworks" "${PODS_ROOT}/MediaPipeTasksGenAIC/frameworks" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAI" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAIC" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 9 | PODS_ROOT = ${SRCROOT} 10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/MediaPipeTasksGenAI 11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 13 | SKIP_INSTALL = YES 14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 15 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/MediaPipeTasksGenAIC/MediaPipeTasksGenAIC-xcframeworks-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/MediaPipeTasksGenAIC/MediaPipeTasksGenAIC-xcframeworks.sh 2 | ${PODS_ROOT}/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/MediaPipeTasksGenAIC/MediaPipeTasksGenAIC-xcframeworks-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAIC/MediaPipeTasksGenAIC.framework -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/MediaPipeTasksGenAIC/MediaPipeTasksGenAIC-xcframeworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | function on_error { 7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" 8 | } 9 | trap 'on_error $LINENO' ERR 10 | 11 | 12 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 13 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 14 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 15 | 16 | 17 | variant_for_slice() 18 | { 19 | case "$1" in 20 | "MediaPipeTasksGenAIC.xcframework/ios-arm64") 21 | echo "" 22 | ;; 23 | "MediaPipeTasksGenAIC.xcframework/ios-arm64_x86_64-simulator") 24 | echo "simulator" 25 | ;; 26 | esac 27 | } 28 | 29 | archs_for_slice() 30 | { 31 | case "$1" in 32 | "MediaPipeTasksGenAIC.xcframework/ios-arm64") 33 | echo "arm64" 34 | ;; 35 | "MediaPipeTasksGenAIC.xcframework/ios-arm64_x86_64-simulator") 36 | echo "arm64 x86_64" 37 | ;; 38 | esac 39 | } 40 | 41 | copy_dir() 42 | { 43 | local source="$1" 44 | local destination="$2" 45 | 46 | # Use filter instead of exclude so missing patterns don't throw errors. 47 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" \"${source}*\" \"${destination}\"" 48 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" "${source}"/* "${destination}" 49 | } 50 | 51 | SELECT_SLICE_RETVAL="" 52 | 53 | select_slice() { 54 | local xcframework_name="$1" 55 | xcframework_name="${xcframework_name##*/}" 56 | local paths=("${@:2}") 57 | # Locate the correct slice of the .xcframework for the current architectures 58 | local target_path="" 59 | 60 | # Split archs on space so we can find a slice that has all the needed archs 61 | local target_archs=$(echo $ARCHS | tr " " "\n") 62 | 63 | local target_variant="" 64 | if [[ "$PLATFORM_NAME" == *"simulator" ]]; then 65 | target_variant="simulator" 66 | fi 67 | if [[ ! -z ${EFFECTIVE_PLATFORM_NAME+x} && "$EFFECTIVE_PLATFORM_NAME" == *"maccatalyst" ]]; then 68 | target_variant="maccatalyst" 69 | fi 70 | for i in ${!paths[@]}; do 71 | local matched_all_archs="1" 72 | local slice_archs="$(archs_for_slice "${xcframework_name}/${paths[$i]}")" 73 | local slice_variant="$(variant_for_slice "${xcframework_name}/${paths[$i]}")" 74 | for target_arch in $target_archs; do 75 | if ! [[ "${slice_variant}" == "$target_variant" ]]; then 76 | matched_all_archs="0" 77 | break 78 | fi 79 | 80 | if ! echo "${slice_archs}" | tr " " "\n" | grep -F -q -x "$target_arch"; then 81 | matched_all_archs="0" 82 | break 83 | fi 84 | done 85 | 86 | if [[ "$matched_all_archs" == "1" ]]; then 87 | # Found a matching slice 88 | echo "Selected xcframework slice ${paths[$i]}" 89 | SELECT_SLICE_RETVAL=${paths[$i]} 90 | break 91 | fi 92 | done 93 | } 94 | 95 | install_xcframework() { 96 | local basepath="$1" 97 | local name="$2" 98 | local package_type="$3" 99 | local paths=("${@:4}") 100 | 101 | # Locate the correct slice of the .xcframework for the current architectures 102 | select_slice "${basepath}" "${paths[@]}" 103 | local target_path="$SELECT_SLICE_RETVAL" 104 | if [[ -z "$target_path" ]]; then 105 | echo "warning: [CP] $(basename ${basepath}): Unable to find matching slice in '${paths[@]}' for the current build architectures ($ARCHS) and platform (${EFFECTIVE_PLATFORM_NAME-${PLATFORM_NAME}})." 106 | return 107 | fi 108 | local source="$basepath/$target_path" 109 | 110 | local destination="${PODS_XCFRAMEWORKS_BUILD_DIR}/${name}" 111 | 112 | if [ ! -d "$destination" ]; then 113 | mkdir -p "$destination" 114 | fi 115 | 116 | copy_dir "$source/" "$destination" 117 | echo "Copied $source to $destination" 118 | } 119 | 120 | install_xcframework "${PODS_ROOT}/MediaPipeTasksGenAIC/frameworks/MediaPipeTasksGenAIC.xcframework" "MediaPipeTasksGenAIC" "framework" "ios-arm64" "ios-arm64_x86_64-simulator" 121 | 122 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/MediaPipeTasksGenAIC/MediaPipeTasksGenAIC.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MediaPipeTasksGenAIC 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/MediaPipeTasksGenAIC/frameworks" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAIC" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 8 | PODS_ROOT = ${SRCROOT} 9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/MediaPipeTasksGenAIC 10 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 12 | SKIP_INSTALL = YES 13 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 14 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/MediaPipeTasksGenAIC/MediaPipeTasksGenAIC.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MediaPipeTasksGenAIC 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/MediaPipeTasksGenAIC/frameworks" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAIC" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 8 | PODS_ROOT = ${SRCROOT} 9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/MediaPipeTasksGenAIC 10 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 12 | SKIP_INSTALL = YES 13 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 14 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Mediapiper/Mediapiper-copy-dsyms-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/../../app/build/cocoapods/framework/app.framework.dSYM -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Mediapiper/Mediapiper-copy-dsyms-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${DWARF_DSYM_FOLDER_PATH}/app.framework.dSYM -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Mediapiper/Mediapiper-copy-dsyms.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | function on_error { 7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" 8 | } 9 | trap 'on_error $LINENO' ERR 10 | 11 | # Used as a return value for each invocation of `strip_invalid_archs` function. 12 | STRIP_BINARY_RETVAL=0 13 | 14 | # Strip invalid architectures 15 | strip_invalid_archs() { 16 | binary="$1" 17 | warn_missing_arch=${2:-true} 18 | # Get architectures for current target binary 19 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 20 | # Intersect them with the architectures we are building for 21 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 22 | # If there are no archs supported by this binary then warn the user 23 | if [[ -z "$intersected_archs" ]]; then 24 | if [[ "$warn_missing_arch" == "true" ]]; then 25 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 26 | fi 27 | STRIP_BINARY_RETVAL=1 28 | return 29 | fi 30 | stripped="" 31 | for arch in $binary_archs; do 32 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 33 | # Strip non-valid architectures in-place 34 | lipo -remove "$arch" -output "$binary" "$binary" 35 | stripped="$stripped $arch" 36 | fi 37 | done 38 | if [[ "$stripped" ]]; then 39 | echo "Stripped $binary of architectures:$stripped" 40 | fi 41 | STRIP_BINARY_RETVAL=0 42 | } 43 | 44 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 45 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 46 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 47 | 48 | # Copies and strips a vendored dSYM 49 | install_dsym() { 50 | local source="$1" 51 | warn_missing_arch=${2:-true} 52 | if [ -r "$source" ]; then 53 | # Copy the dSYM into the targets temp dir. 54 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 55 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 56 | 57 | local basename 58 | basename="$(basename -s .dSYM "$source")" 59 | binary_name="$(ls "$source/Contents/Resources/DWARF")" 60 | binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" 61 | 62 | # Strip invalid architectures from the dSYM. 63 | if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then 64 | strip_invalid_archs "$binary" "$warn_missing_arch" 65 | fi 66 | if [[ $STRIP_BINARY_RETVAL == 0 ]]; then 67 | # Move the stripped file into its final destination. 68 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 69 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 70 | else 71 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 72 | mkdir -p "${DWARF_DSYM_FOLDER_PATH}" 73 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" 74 | fi 75 | fi 76 | } 77 | 78 | # Copies the bcsymbolmap files of a vendored framework 79 | install_bcsymbolmap() { 80 | local bcsymbolmap_path="$1" 81 | local destination="${BUILT_PRODUCTS_DIR}" 82 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" 83 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" 84 | } 85 | 86 | install_dsym "${PODS_ROOT}/../../app/build/cocoapods/framework/app.framework.dSYM" 87 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Mediapiper/Mediapiper.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Mediapiper 3 | ENABLE_USER_SCRIPT_SANDBOXING = NO 4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../app/build/cocoapods/framework" "${PODS_ROOT}/MediaPipeTasksGenAI/frameworks" "${PODS_ROOT}/MediaPipeTasksGenAIC/frameworks" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAI" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAIC" 5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 6 | KOTLIN_PROJECT_PATH = :app 7 | OTHER_LDFLAGS = $(inherited) -l"c++" -framework "Accelerate" -framework "CoreVideo" -framework "Metal" -framework "OpenGLES" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 11 | PODS_ROOT = ${SRCROOT} 12 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../app 13 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 14 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 15 | PRODUCT_MODULE_NAME = app 16 | SKIP_INSTALL = YES 17 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 18 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Mediapiper/Mediapiper.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Mediapiper 3 | ENABLE_USER_SCRIPT_SANDBOXING = NO 4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../app/build/cocoapods/framework" "${PODS_ROOT}/MediaPipeTasksGenAI/frameworks" "${PODS_ROOT}/MediaPipeTasksGenAIC/frameworks" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAI" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAIC" 5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 6 | KOTLIN_PROJECT_PATH = :app 7 | OTHER_LDFLAGS = $(inherited) -l"c++" -framework "Accelerate" -framework "CoreVideo" -framework "Metal" -framework "OpenGLES" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 11 | PODS_ROOT = ${SRCROOT} 12 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../app 13 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 14 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 15 | PRODUCT_MODULE_NAME = app 16 | SKIP_INSTALL = YES 17 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 18 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_DEVELOPMENT_LANGUAGE} 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_iosApp : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_iosApp 5 | @end 6 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-frameworks-Debug-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-frameworks.sh 2 | ${PODS_ROOT}/../../app/build/cocoapods/framework/app.framework -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-frameworks-Debug-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/app.framework -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-frameworks-Release-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-frameworks.sh 2 | ${PODS_ROOT}/../../app/build/cocoapods/framework/app.framework -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-frameworks-Release-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/app.framework -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | function on_error { 7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" 8 | } 9 | trap 'on_error $LINENO' ERR 10 | 11 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 12 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 13 | # frameworks to, so exit 0 (signalling the script phase was successful). 14 | exit 0 15 | fi 16 | 17 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 18 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 19 | 20 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 21 | SWIFT_STDLIB_PATH="${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 22 | BCSYMBOLMAP_DIR="BCSymbolMaps" 23 | 24 | 25 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 26 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 27 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 28 | 29 | # Copies and strips a vendored framework 30 | install_framework() 31 | { 32 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 33 | local source="${BUILT_PRODUCTS_DIR}/$1" 34 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 35 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 36 | elif [ -r "$1" ]; then 37 | local source="$1" 38 | fi 39 | 40 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 41 | 42 | if [ -L "${source}" ]; then 43 | echo "Symlinked..." 44 | source="$(readlink -f "${source}")" 45 | fi 46 | 47 | if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then 48 | # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied 49 | find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do 50 | echo "Installing $f" 51 | install_bcsymbolmap "$f" "$destination" 52 | rm "$f" 53 | done 54 | rmdir "${source}/${BCSYMBOLMAP_DIR}" 55 | fi 56 | 57 | # Use filter instead of exclude so missing patterns don't throw errors. 58 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 59 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 60 | 61 | local basename 62 | basename="$(basename -s .framework "$1")" 63 | binary="${destination}/${basename}.framework/${basename}" 64 | 65 | if ! [ -r "$binary" ]; then 66 | binary="${destination}/${basename}" 67 | elif [ -L "${binary}" ]; then 68 | echo "Destination binary is symlinked..." 69 | dirname="$(dirname "${binary}")" 70 | binary="${dirname}/$(readlink "${binary}")" 71 | fi 72 | 73 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 74 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 75 | strip_invalid_archs "$binary" 76 | fi 77 | 78 | # Resign the code if required by the build settings to avoid unstable apps 79 | code_sign_if_enabled "${destination}/$(basename "$1")" 80 | 81 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 82 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 83 | local swift_runtime_libs 84 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) 85 | for lib in $swift_runtime_libs; do 86 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 87 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 88 | code_sign_if_enabled "${destination}/${lib}" 89 | done 90 | fi 91 | } 92 | # Copies and strips a vendored dSYM 93 | install_dsym() { 94 | local source="$1" 95 | warn_missing_arch=${2:-true} 96 | if [ -r "$source" ]; then 97 | # Copy the dSYM into the targets temp dir. 98 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 99 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 100 | 101 | local basename 102 | basename="$(basename -s .dSYM "$source")" 103 | binary_name="$(ls "$source/Contents/Resources/DWARF")" 104 | binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" 105 | 106 | # Strip invalid architectures from the dSYM. 107 | if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then 108 | strip_invalid_archs "$binary" "$warn_missing_arch" 109 | fi 110 | if [[ $STRIP_BINARY_RETVAL == 0 ]]; then 111 | # Move the stripped file into its final destination. 112 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 113 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 114 | else 115 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 116 | mkdir -p "${DWARF_DSYM_FOLDER_PATH}" 117 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" 118 | fi 119 | fi 120 | } 121 | 122 | # Used as a return value for each invocation of `strip_invalid_archs` function. 123 | STRIP_BINARY_RETVAL=0 124 | 125 | # Strip invalid architectures 126 | strip_invalid_archs() { 127 | binary="$1" 128 | warn_missing_arch=${2:-true} 129 | # Get architectures for current target binary 130 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 131 | # Intersect them with the architectures we are building for 132 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 133 | # If there are no archs supported by this binary then warn the user 134 | if [[ -z "$intersected_archs" ]]; then 135 | if [[ "$warn_missing_arch" == "true" ]]; then 136 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 137 | fi 138 | STRIP_BINARY_RETVAL=1 139 | return 140 | fi 141 | stripped="" 142 | for arch in $binary_archs; do 143 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 144 | # Strip non-valid architectures in-place 145 | lipo -remove "$arch" -output "$binary" "$binary" 146 | stripped="$stripped $arch" 147 | fi 148 | done 149 | if [[ "$stripped" ]]; then 150 | echo "Stripped $binary of architectures:$stripped" 151 | fi 152 | STRIP_BINARY_RETVAL=0 153 | } 154 | 155 | # Copies the bcsymbolmap files of a vendored framework 156 | install_bcsymbolmap() { 157 | local bcsymbolmap_path="$1" 158 | local destination="${BUILT_PRODUCTS_DIR}" 159 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" 160 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" 161 | } 162 | 163 | # Signs a framework with the provided identity 164 | code_sign_if_enabled() { 165 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 166 | # Use the current code_sign_identity 167 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 168 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 169 | 170 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 171 | code_sign_cmd="$code_sign_cmd &" 172 | fi 173 | echo "$code_sign_cmd" 174 | eval "$code_sign_cmd" 175 | fi 176 | } 177 | 178 | if [[ "$CONFIGURATION" == "Debug" ]]; then 179 | install_framework "${PODS_ROOT}/../../app/build/cocoapods/framework/app.framework" 180 | fi 181 | if [[ "$CONFIGURATION" == "Release" ]]; then 182 | install_framework "${PODS_ROOT}/../../app/build/cocoapods/framework/app.framework" 183 | fi 184 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 185 | wait 186 | fi 187 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources-Debug-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh 2 | ${PODS_ROOT}/../../app/build/compose/cocoapods/compose-resources -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources-Debug-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/compose-resources -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources-Release-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh 2 | ${PODS_ROOT}/../../app/build/compose/cocoapods/compose-resources -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources-Release-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/compose-resources -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | function on_error { 7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" 8 | } 9 | trap 'on_error $LINENO' ERR 10 | 11 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 12 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 13 | # resources to, so exit 0 (signalling the script phase was successful). 14 | exit 0 15 | fi 16 | 17 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 18 | 19 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 20 | > "$RESOURCES_TO_COPY" 21 | 22 | XCASSET_FILES=() 23 | 24 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 25 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 26 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 27 | 28 | case "${TARGETED_DEVICE_FAMILY:-}" in 29 | 1,2) 30 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 31 | ;; 32 | 1) 33 | TARGET_DEVICE_ARGS="--target-device iphone" 34 | ;; 35 | 2) 36 | TARGET_DEVICE_ARGS="--target-device ipad" 37 | ;; 38 | 3) 39 | TARGET_DEVICE_ARGS="--target-device tv" 40 | ;; 41 | 4) 42 | TARGET_DEVICE_ARGS="--target-device watch" 43 | ;; 44 | *) 45 | TARGET_DEVICE_ARGS="--target-device mac" 46 | ;; 47 | esac 48 | 49 | install_resource() 50 | { 51 | if [[ "$1" = /* ]] ; then 52 | RESOURCE_PATH="$1" 53 | else 54 | RESOURCE_PATH="${PODS_ROOT}/$1" 55 | fi 56 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 57 | cat << EOM 58 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 59 | EOM 60 | exit 1 61 | fi 62 | case $RESOURCE_PATH in 63 | *.storyboard) 64 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 65 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 66 | ;; 67 | *.xib) 68 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 69 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 70 | ;; 71 | *.framework) 72 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 73 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 74 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 75 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 76 | ;; 77 | *.xcdatamodel) 78 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 79 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 80 | ;; 81 | *.xcdatamodeld) 82 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 83 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 84 | ;; 85 | *.xcmappingmodel) 86 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 87 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 88 | ;; 89 | *.xcassets) 90 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 91 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 92 | ;; 93 | *) 94 | echo "$RESOURCE_PATH" || true 95 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 96 | ;; 97 | esac 98 | } 99 | if [[ "$CONFIGURATION" == "Debug" ]]; then 100 | install_resource "${PODS_ROOT}/../../app/build/compose/cocoapods/compose-resources" 101 | fi 102 | if [[ "$CONFIGURATION" == "Release" ]]; then 103 | install_resource "${PODS_ROOT}/../../app/build/compose/cocoapods/compose-resources" 104 | fi 105 | 106 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 107 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 108 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 109 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 110 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 111 | fi 112 | rm -f "$RESOURCES_TO_COPY" 113 | 114 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 115 | then 116 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 117 | OTHER_XCASSETS=$(find -L "$PWD" -iname "*.xcassets" -type d) 118 | while read line; do 119 | if [[ $line != "${PODS_ROOT}*" ]]; then 120 | XCASSET_FILES+=("$line") 121 | fi 122 | done <<<"$OTHER_XCASSETS" 123 | 124 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 125 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 126 | else 127 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 128 | fi 129 | fi 130 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_iosAppVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_iosAppVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | ENABLE_USER_SCRIPT_SANDBOXING = NO 4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../app/build/cocoapods/framework" "${PODS_ROOT}/MediaPipeTasksGenAI/frameworks" "${PODS_ROOT}/MediaPipeTasksGenAIC/frameworks" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAI" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAIC" 5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' 7 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 8 | OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -framework "Accelerate" -framework "CoreVideo" -framework "MediaPipeTasksGenAI" -framework "MediaPipeTasksGenAIC" -framework "Metal" -framework "OpenGLES" -framework "app" 9 | OTHER_LDFLAGS[sdk=iphoneos*] = $(inherited) -force_load "$(PODS_ROOT)/MediaPipeTasksGenAIC/frameworks/genai_libraries/libMediaPipeTasksGenAIC_device.a" 10 | OTHER_LDFLAGS[sdk=iphonesimulator*] = $(inherited) -force_load "${PODS_ROOT}/MediaPipeTasksGenAIC/frameworks/genai_libraries/libMediaPipeTasksGenAIC_simulator.a" 11 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 12 | PODS_BUILD_DIR = ${BUILD_DIR} 13 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 14 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 15 | PODS_ROOT = ${SRCROOT}/Pods 16 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 17 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 18 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_iosApp { 2 | umbrella header "Pods-iosApp-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /iosApp/Pods/Target Support Files/Pods-iosApp/Pods-iosApp.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | ENABLE_USER_SCRIPT_SANDBOXING = NO 4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../app/build/cocoapods/framework" "${PODS_ROOT}/MediaPipeTasksGenAI/frameworks" "${PODS_ROOT}/MediaPipeTasksGenAIC/frameworks" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAI" "${PODS_XCFRAMEWORKS_BUILD_DIR}/MediaPipeTasksGenAIC" 5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' 7 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 8 | OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -framework "Accelerate" -framework "CoreVideo" -framework "MediaPipeTasksGenAI" -framework "MediaPipeTasksGenAIC" -framework "Metal" -framework "OpenGLES" -framework "app" 9 | OTHER_LDFLAGS[sdk=iphoneos*] = $(inherited) -force_load "$(PODS_ROOT)/MediaPipeTasksGenAIC/frameworks/genai_libraries/libMediaPipeTasksGenAIC_device.a" 10 | OTHER_LDFLAGS[sdk=iphonesimulator*] = $(inherited) -force_load "${PODS_ROOT}/MediaPipeTasksGenAIC/frameworks/genai_libraries/libMediaPipeTasksGenAIC_simulator.a" 11 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 12 | PODS_BUILD_DIR = ${BUILD_DIR} 13 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 14 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 15 | PODS_ROOT = ${SRCROOT}/Pods 16 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 17 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 18 | -------------------------------------------------------------------------------- /iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /iosApp/iosApp.xcodeproj/xcshareddata/xcschemes/iosApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 16 | 22 | 23 | 24 | 25 | 26 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /iosApp/iosApp.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 9 | 10 | 12 | 13 | 14 | 16 | 17 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /iosApp/iosApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /iosApp/iosApp/MediapipeLLMInferenceDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MediapipeLLMInferenceDelegate.swift 3 | // iosApp 4 | // 5 | // Created by 2BAB on 20/6/24. 6 | // 7 | 8 | import Foundation 9 | import MediaPipeTasksGenAI 10 | import app 11 | 12 | 13 | class LLMOperatorSwiftImpl: LLMOperatorSwift { 14 | 15 | let errorTag = "Mediapipe-LLM-Tasks-iOS: " 16 | var llmInference: LlmInference? 17 | 18 | 19 | func loadModel(modelName: String) async throws { 20 | let path = Bundle.main.path(forResource: modelName, ofType: "bin")! 21 | let llmOptions = LlmInference.Options(modelPath: path) 22 | llmOptions.maxTokens = 4096 23 | llmOptions.temperature = 0.9 24 | 25 | llmInference = try LlmInference(options: llmOptions) 26 | } 27 | 28 | func generateResponse(inputText: String) async throws -> String { 29 | return try llmInference!.generateResponse(inputText: inputText) 30 | } 31 | 32 | func generateResponseAsync(inputText: String, progress: @escaping (String) -> Void, completion: @escaping (String) -> Void) async throws { 33 | try llmInference!.generateResponseAsync(inputText: inputText) { partialResponse, error in 34 | // progress 35 | if let e = error { 36 | print("\(self.errorTag) \(e)") 37 | completion(e.localizedDescription) 38 | return 39 | } 40 | if let partial = partialResponse { 41 | progress(partial) 42 | } 43 | } completion: { 44 | completion("") 45 | } 46 | } 47 | 48 | func sizeInTokens(text: String) -> Int32 { 49 | return 0 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /iosApp/iosApp/iosApp.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import MediaPipeTasksGenAI 3 | import app 4 | 5 | @main 6 | class AppDelegate: UIResponder, UIApplicationDelegate { 7 | var window: UIWindow? 8 | 9 | func application( 10 | _ application: UIApplication, 11 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 12 | ) -> Bool { 13 | window = UIWindow(frame: UIScreen.main.bounds) 14 | 15 | do { 16 | let delegate = try LLMOperatorSwiftImpl() 17 | MainKt.onStartup(llmInferenceDelegate: delegate) 18 | } catch let error { 19 | print("Mediapipe GenAI Task SDK failed to init: \(error)") 20 | } 21 | 22 | if let window = window { 23 | window.rootViewController = MainKt.MainViewController() 24 | window.makeKeyAndVisible() 25 | } 26 | return true 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /media/llm-inference-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/media/llm-inference-intro.png -------------------------------------------------------------------------------- /media/object-detection-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2BAB/MediaPiper/832f05c904a3b0cfab77e88aca9c491e843b6228/media/object-detection-intro.png -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "Mediapiper" 2 | // 1. 3 | include(":app") 4 | 5 | pluginManagement { 6 | repositories { 7 | google() 8 | gradlePluginPortal() 9 | mavenCentral() 10 | maven("https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental") 11 | } 12 | } 13 | 14 | dependencyResolutionManagement { 15 | @Suppress("UnstableApiUsage") 16 | repositories { 17 | google() 18 | mavenCentral() 19 | maven("https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental") 20 | } 21 | } 22 | --------------------------------------------------------------------------------