├── .github └── workflows │ └── main.yml ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── TODO.md ├── android ├── .gitignore ├── assets │ └── snowboy │ │ └── common.res ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── settings.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ ├── ai │ │ └── kitt │ │ │ └── snowboy │ │ │ ├── AppResCopy.java │ │ │ ├── Constants.java │ │ │ ├── MsgEnum.java │ │ │ ├── SnowboyDetect.java │ │ │ ├── SnowboyVad.java │ │ │ ├── snowboy.java │ │ │ └── snowboyJNI.java │ └── is │ │ └── mideind │ │ └── flutter_snowboy │ │ ├── Detector.java │ │ └── FlutterSnowboyPlugin.java │ └── jniLibs │ ├── arm64-v8a │ └── libsnowboy-detect-android.so │ └── armeabi-v7a │ └── libsnowboy-detect-android.so ├── example ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── flutter_snowboy_example │ │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ └── settings_aar.gradle ├── assets │ ├── ding.wav │ └── hi_embla.pmdl ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ └── LaunchImage@3x.png │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── main.m ├── lib │ └── main.dart ├── pubspec.yaml └── test │ └── widget_test.dart ├── ios ├── .gitignore ├── Assets │ └── Snowboy │ │ └── common.res ├── Classes │ ├── FlutterSnowboyPlugin.h │ ├── FlutterSnowboyPlugin.m │ ├── SnowboyDetector.h │ └── SnowboyDetector.mm ├── Snowboy.framework │ ├── Headers │ │ └── Snowboy.h │ ├── Info.plist │ ├── Modules │ │ └── module.modulemap │ └── Snowboy └── flutter_snowboy.podspec ├── lib └── flutter_snowboy.dart ├── pubspec.yaml └── test └── flutter_snowboy_test.dart /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # GitHub Actions workflow for the flutter_snowboy repository 2 | name: tests 3 | 4 | # Controls when the action will run. 5 | on: 6 | # Triggers the workflow on push or pull request events but only for the main branch 7 | push: 8 | branches: 9 | - '*' 10 | pull_request: 11 | branches: 12 | - '*' 13 | 14 | # Allows you to run this workflow manually from the Actions tab 15 | workflow_dispatch: 16 | 17 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 18 | jobs: 19 | # This workflow contains a single job called "build" 20 | build: 21 | # The type of runner that the job will run on 22 | runs-on: ubuntu-latest 23 | 24 | # Steps represent a sequence of tasks that will be executed as part of the job 25 | steps: 26 | - uses: actions/checkout@v4 27 | - uses: actions/setup-java@v3 28 | with: 29 | distribution: 'temurin' 30 | java-version: '11.0.19+7' 31 | - uses: actions/checkout@v4 32 | - uses: subosito/flutter-action@v2 33 | with: 34 | flutter-version: '3.10.0' 35 | channel: 'stable' 36 | - run: flutter config --no-analytics 37 | - run: flutter --disable-telemetry 38 | - run: flutter pub get --suppress-analytics 39 | - run: dart analyze lib example/lib 40 | - run: flutter test 41 | - run: | 42 | cd example 43 | flutter build apk 44 | - name: Slack notification 45 | uses: 8398a7/action-slack@v2 46 | with: 47 | status: ${{ job.status }} 48 | author_name: Integration Testing 49 | env: 50 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} # required 51 | if: failure() # Pick up event if the job fails 52 | 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | .vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | **/pubspec.lock 33 | 34 | # Android related 35 | **/android/**/gradle-wrapper.jar 36 | **/android/.gradle 37 | **/android/captures/ 38 | **/android/gradlew 39 | **/android/gradlew.bat 40 | **/android/local.properties 41 | **/android/**/GeneratedPluginRegistrant.java 42 | 43 | # iOS/XCode related 44 | **/ios/**/*.mode1v3 45 | **/ios/**/*.mode2v3 46 | **/ios/**/*.moved-aside 47 | **/ios/**/*.pbxuser 48 | **/ios/**/*.perspectivev3 49 | **/ios/**/*sync/ 50 | **/ios/**/.sconsign.dblite 51 | **/ios/**/.tags* 52 | **/ios/**/.vagrant/ 53 | **/ios/**/DerivedData/ 54 | **/ios/**/Icon? 55 | **/ios/**/Pods/ 56 | **/ios/**/.symlinks/ 57 | **/ios/**/profile 58 | **/ios/**/xcuserdata 59 | **/ios/.generated/ 60 | **/ios/Flutter/App.framework 61 | **/ios/Flutter/Flutter.framework 62 | **/ios/Flutter/Flutter.podspec 63 | **/ios/Flutter/Generated.xcconfig 64 | **/ios/Flutter/app.flx 65 | **/ios/Flutter/app.zip 66 | **/ios/Flutter/flutter_assets/ 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/ServiceDefinitions.json 69 | **/ios/Runner/GeneratedPluginRegistrant.* 70 | Podfile.lock 71 | 72 | # Exceptions to above rules. 73 | !**/ios/**/default.mode1v3 74 | !**/ios/**/default.mode2v3 75 | !**/ios/**/default.pbxuser 76 | !**/ios/**/default.perspectivev3 77 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: adc687823a831bbebe28bdccfac1a628ca621513 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.1.2+1 - 20-05-2023 2 | 3 | * Various minor fixes 4 | 5 | # 0.1.1+1 - 12-01-2022 6 | 7 | * Null safety + minor fixes. Now requires Dart 2.12+ 8 | 9 | # [0.1.0+1] - 24-08-2021 10 | 11 | * Initial release 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2021-2023 Miðeind ehf. 2 | Snowboy is Copyright (C) 2016-2020 KITT.AI 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 2 | [![Language](https://img.shields.io/badge/language-dart-lightblue)]() 3 | [![Language](https://img.shields.io/badge/language-objective--c-lightgrey)]() 4 | [![Language](https://img.shields.io/badge/language-java-lightgreen)]() 5 | ![Release](https://shields.io/github/v/release/mideind/flutter_snowboy?display_name=tag) 6 | ![pub.dev](https://img.shields.io/pub/v/flutter_snowboy) 7 | [![Build](https://github.com/mideind/flutter_snowboy/actions/workflows/main.yml/badge.svg)]() 8 | 9 | # Flutter Snowboy plugin 10 | 11 | This repository contains the source code to the Flutter Snowboy package. 12 | [Snowboy](https://github.com/seasalt-ai/snowboy) is a cross-platform 13 | DNN-based hotword detection toolkit implemented in C++. This package 14 | makes it easy to use Snowboy in your Flutter app. 15 | 16 | Currently only iOS and Android are supported. 17 | 18 | ## Models 19 | 20 | The Flutter Snowboy package requires a working Snowboy detection 21 | model (`pmdl`) to be useful. To train your own model, clone 22 | [this repo](https://github.com/seasalt-ai/snowboy) and follow 23 | the instructions. 24 | 25 | ## How to use 26 | 27 | ### Add dependency to project 28 | 29 | Add this to the dependencies list in your `pubspec.yaml` file: 30 | 31 | ```yaml 32 | flutter_snowboy: ">=0.1.2" 33 | ``` 34 | 35 | ### Initialize detector 36 | 37 | ```dart 38 | import 'package:flutter_snowboy/flutter_snowboy.dart'; 39 | 40 | ... 41 | 42 | // Instantiate 43 | var detector = Snowboy(); 44 | 45 | // Load model and other resources. 46 | // This is a moderately expensive operation since it involves file I/O. 47 | var success = detector.prepare("/absolute/path/to/model.pmdl"); 48 | 49 | ``` 50 | 51 | ### Start 52 | 53 | ```dart 54 | void hwHandler() { 55 | print("Hotword detected"); 56 | } 57 | 58 | detector.hotwordHandler = hwHandler; 59 | 60 | // ... get audio data as UInt8List (e.g. via flutter_sound) and feed into 61 | // the detect function. Audio data should be 16 kHz, 16-bit mono PCM. 62 | 63 | detector.detect(data); 64 | 65 | // ... and hwHandler() gets called when the hotword is detected in audio data. 66 | ``` 67 | 68 | ## Contributing 69 | 70 | All contributions are welcome. If you would like to lend and hand, feel free to 71 | fork this repository and open pull requests. 72 | 73 | ## Version History 74 | 75 | * 0.1.2 - Various fixes (20-05-2023) 76 | * 0.1.1 - Null safety + minor fixes. Now requires Dart 2.12+ (12-01-2022) 77 | * 0.1.0 - Initial release (24-08-2021) 78 | 79 | ## License 80 | 81 | flutter_snowboy is Copyright (C) 2021-2023 [Miðeind ehf.](https://mideind.is) 82 | Snowboy is Copyright (C) 2016-2020 KITT.AI 83 | 84 | Licensed under the Apache License, Version 2.0 (the "License"); 85 | you may not use this file except in compliance with the License. 86 | You may obtain a copy of the License at 87 | 88 | [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) 89 | or [here](LICENSE) 90 | 91 | Unless required by applicable law or agreed to in writing, software 92 | distributed under the License is distributed on an "AS IS" BASIS, 93 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 94 | See the License for the specific language governing permissions and 95 | limitations under the License. 96 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO for flutter_snowboy 2 | 3 | * Graceful error handling and more input sanity checks in Java & Obj-C implementations 4 | * Find a way to make common.res bundling more elegant (embed in binary?) 5 | 6 | ## Long-term 7 | 8 | * Move over to using Snowman instead of Snowboy? https://github.com/Thalhammer/snowman 9 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /android/assets/snowboy/common.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/android/assets/snowboy/common.res -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'is.mideind.flutter_snowboy' 2 | version '1.0' 3 | 4 | buildscript { 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:4.1.0' 12 | } 13 | } 14 | 15 | rootProject.allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | apply plugin: 'com.android.library' 23 | 24 | dependencies { 25 | implementation fileTree(include: '*.jar', dir: 'libs') 26 | implementation 'androidx.annotation:annotation:1.1.0' 27 | } 28 | 29 | android { 30 | compileSdkVersion 33 31 | 32 | defaultConfig { 33 | minSdkVersion 21 34 | } 35 | 36 | sourceSets { 37 | main { 38 | java.srcDirs = ['src'] 39 | resources.srcDirs = ['src'] 40 | aidl.srcDirs = ['src'] 41 | renderscript.srcDirs = ['src'] 42 | res.srcDirs = ['res'] 43 | assets.srcDirs = ['assets'] 44 | } 45 | } 46 | buildFeatures { 47 | renderScript true 48 | aidl true 49 | } 50 | } 51 | 52 | android.sourceSets.main.assets.srcDirs += ['assets/'] 53 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | 5 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 6 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'flutter_snowboy' 2 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/java/ai/kitt/snowboy/AppResCopy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016-2020 KITT.AI 3 | * Modifications were made by Miðeind ehf. Copyright (C) 2021-2023 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * https://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | package ai.kitt.snowboy; 20 | 21 | import android.content.Context; 22 | import android.util.Log; 23 | import java.io.File; 24 | import java.io.FileOutputStream; 25 | import java.io.InputStream; 26 | 27 | public class AppResCopy { 28 | private final static String TAG = AppResCopy.class.getSimpleName(); 29 | 30 | public static void copyFilesFromAssets(Context context, String assetsSrcDir, 31 | String sdcardDstDir, 32 | boolean override) { 33 | try { 34 | String fileNames[] = context.getAssets().list(assetsSrcDir); 35 | // Log.e(TAG, "fileNames.toString()"); 36 | if (fileNames.length > 0) { 37 | // Log.i(TAG, assetsSrcDir + " directory has " + fileNames.length + " 38 | // files.\n"); 39 | File dir = new File(sdcardDstDir); 40 | if (!dir.exists()) { 41 | if (!dir.mkdirs()) { 42 | Log.e(TAG, "mkdir failed: " + sdcardDstDir); 43 | return; 44 | } else { 45 | // Log.i(TAG, "mkdir ok: " + sdcardDstDir); 46 | } 47 | } else { 48 | // Log.w(TAG, sdcardDstDir + " already exists! "); 49 | } 50 | for (String fileName : fileNames) { 51 | copyFilesFromAssets(context, assetsSrcDir + "/" + fileName, 52 | sdcardDstDir + "/" + fileName, override); 53 | } 54 | } else { 55 | // Log.i(TAG, assetsSrcDir + " is file\n"); 56 | File outFile = new File(sdcardDstDir); 57 | if (outFile.exists()) { 58 | if (override) { 59 | outFile.delete(); 60 | // Log.e(TAG, "overriding file " + sdcardDstDir + "\n"); 61 | } else { 62 | // Log.e(TAG, "file " + sdcardDstDir + " already exists. No 63 | // override.\n"); 64 | return; 65 | } 66 | } 67 | InputStream is = context.getAssets().open(assetsSrcDir); 68 | FileOutputStream fos = new FileOutputStream(outFile); 69 | byte[] buffer = new byte[1024]; 70 | int byteCount = 0; 71 | while ((byteCount = is.read(buffer)) != -1) { 72 | fos.write(buffer, 0, byteCount); 73 | } 74 | fos.flush(); 75 | is.close(); 76 | fos.close(); 77 | // Log.i(TAG, "copy to " + sdcardDstDir + " ok!"); 78 | } 79 | } catch (Exception e) { 80 | e.printStackTrace(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /android/src/main/java/ai/kitt/snowboy/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2023 Miðeind ehf. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package ai.kitt.snowboy; 19 | 20 | public class Constants { 21 | public static final String ASSETS_DIRNAME = "snowboy"; 22 | public static final String COMMON_RES_FILENAME = "common.res"; 23 | } -------------------------------------------------------------------------------- /android/src/main/java/ai/kitt/snowboy/MsgEnum.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016-2020 KITT.AI 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package ai.kitt.snowboy; 19 | 20 | public enum MsgEnum { 21 | MSG_VAD_END, 22 | MSG_VAD_NOSPEECH, 23 | MSG_VAD_SPEECH, 24 | MSG_VOLUME_NOTIFY, 25 | MSG_WAV_DATAINFO, 26 | MSG_RECORD_START, 27 | MSG_RECORD_STOP, 28 | MSG_ACTIVE, 29 | MSG_ERROR, 30 | MSG_INFO; 31 | 32 | public static MsgEnum getMsgEnum(int i) { return MsgEnum.values()[i]; } 33 | } 34 | -------------------------------------------------------------------------------- /android/src/main/java/ai/kitt/snowboy/SnowboyDetect.java: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------------- 2 | * This file was automatically generated by SWIG (https://www.swig.org). 3 | * Version 4.0.2 4 | * 5 | * Do not make changes to this file unless you know what you are doing--modify 6 | * the SWIG interface file instead. 7 | * ----------------------------------------------------------------------------- 8 | */ 9 | 10 | package ai.kitt.snowboy; 11 | 12 | public class SnowboyDetect { 13 | private transient long swigCPtr; 14 | protected transient boolean swigCMemOwn; 15 | 16 | protected SnowboyDetect(long cPtr, boolean cMemoryOwn) { 17 | swigCMemOwn = cMemoryOwn; 18 | swigCPtr = cPtr; 19 | } 20 | 21 | protected static long getCPtr(SnowboyDetect obj) { 22 | return (obj == null) ? 0 : obj.swigCPtr; 23 | } 24 | 25 | @SuppressWarnings("deprecation") 26 | protected void finalize() { 27 | delete(); 28 | } 29 | 30 | public synchronized void delete() { 31 | if (swigCPtr != 0) { 32 | if (swigCMemOwn) { 33 | swigCMemOwn = false; 34 | snowboyJNI.delete_SnowboyDetect(swigCPtr); 35 | } 36 | swigCPtr = 0; 37 | } 38 | } 39 | 40 | public SnowboyDetect(String resource_filename, String model_str) { 41 | this(snowboyJNI.new_SnowboyDetect(resource_filename, model_str), true); 42 | } 43 | 44 | public boolean Reset() { 45 | return snowboyJNI.SnowboyDetect_Reset(swigCPtr, this); 46 | } 47 | 48 | public int RunDetection(String data, boolean is_end) { 49 | return snowboyJNI.SnowboyDetect_RunDetection__SWIG_0(swigCPtr, this, data, 50 | is_end); 51 | } 52 | 53 | public int RunDetection(String data) { 54 | return snowboyJNI.SnowboyDetect_RunDetection__SWIG_1(swigCPtr, this, data); 55 | } 56 | 57 | public int RunDetection(float[] data, int array_length, boolean is_end) { 58 | return snowboyJNI.SnowboyDetect_RunDetection__SWIG_2(swigCPtr, this, data, 59 | array_length, is_end); 60 | } 61 | 62 | public int RunDetection(float[] data, int array_length) { 63 | return snowboyJNI.SnowboyDetect_RunDetection__SWIG_3(swigCPtr, this, data, 64 | array_length); 65 | } 66 | 67 | public int RunDetection(short[] data, int array_length, boolean is_end) { 68 | return snowboyJNI.SnowboyDetect_RunDetection__SWIG_4(swigCPtr, this, data, 69 | array_length, is_end); 70 | } 71 | 72 | public int RunDetection(short[] data, int array_length) { 73 | return snowboyJNI.SnowboyDetect_RunDetection__SWIG_5(swigCPtr, this, data, 74 | array_length); 75 | } 76 | 77 | public int RunDetection(int[] data, int array_length, boolean is_end) { 78 | return snowboyJNI.SnowboyDetect_RunDetection__SWIG_6(swigCPtr, this, data, 79 | array_length, is_end); 80 | } 81 | 82 | public int RunDetection(int[] data, int array_length) { 83 | return snowboyJNI.SnowboyDetect_RunDetection__SWIG_7(swigCPtr, this, data, 84 | array_length); 85 | } 86 | 87 | public void SetSensitivity(String sensitivity_str) { 88 | snowboyJNI.SnowboyDetect_SetSensitivity(swigCPtr, this, sensitivity_str); 89 | } 90 | 91 | public void SetHighSensitivity(String high_sensitivity_str) { 92 | snowboyJNI.SnowboyDetect_SetHighSensitivity(swigCPtr, this, 93 | high_sensitivity_str); 94 | } 95 | 96 | public String GetSensitivity() { 97 | return snowboyJNI.SnowboyDetect_GetSensitivity(swigCPtr, this); 98 | } 99 | 100 | public void SetAudioGain(float audio_gain) { 101 | snowboyJNI.SnowboyDetect_SetAudioGain(swigCPtr, this, audio_gain); 102 | } 103 | 104 | public void UpdateModel() { 105 | snowboyJNI.SnowboyDetect_UpdateModel(swigCPtr, this); 106 | } 107 | 108 | public int NumHotwords() { 109 | return snowboyJNI.SnowboyDetect_NumHotwords(swigCPtr, this); 110 | } 111 | 112 | public void ApplyFrontend(boolean apply_frontend) { 113 | snowboyJNI.SnowboyDetect_ApplyFrontend(swigCPtr, this, apply_frontend); 114 | } 115 | 116 | public int SampleRate() { 117 | return snowboyJNI.SnowboyDetect_SampleRate(swigCPtr, this); 118 | } 119 | 120 | public int NumChannels() { 121 | return snowboyJNI.SnowboyDetect_NumChannels(swigCPtr, this); 122 | } 123 | 124 | public int BitsPerSample() { 125 | return snowboyJNI.SnowboyDetect_BitsPerSample(swigCPtr, this); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /android/src/main/java/ai/kitt/snowboy/SnowboyVad.java: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------------- 2 | * This file was automatically generated by SWIG (https://www.swig.org). 3 | * Version 4.0.2 4 | * 5 | * Do not make changes to this file unless you know what you are doing--modify 6 | * the SWIG interface file instead. 7 | * ----------------------------------------------------------------------------- 8 | */ 9 | 10 | package ai.kitt.snowboy; 11 | 12 | public class SnowboyVad { 13 | private transient long swigCPtr; 14 | protected transient boolean swigCMemOwn; 15 | 16 | protected SnowboyVad(long cPtr, boolean cMemoryOwn) { 17 | swigCMemOwn = cMemoryOwn; 18 | swigCPtr = cPtr; 19 | } 20 | 21 | protected static long getCPtr(SnowboyVad obj) { 22 | return (obj == null) ? 0 : obj.swigCPtr; 23 | } 24 | 25 | @SuppressWarnings("deprecation") 26 | protected void finalize() { 27 | delete(); 28 | } 29 | 30 | public synchronized void delete() { 31 | if (swigCPtr != 0) { 32 | if (swigCMemOwn) { 33 | swigCMemOwn = false; 34 | snowboyJNI.delete_SnowboyVad(swigCPtr); 35 | } 36 | swigCPtr = 0; 37 | } 38 | } 39 | 40 | public SnowboyVad(String resource_filename) { 41 | this(snowboyJNI.new_SnowboyVad(resource_filename), true); 42 | } 43 | 44 | public boolean Reset() { return snowboyJNI.SnowboyVad_Reset(swigCPtr, this); } 45 | 46 | public int RunVad(String data, boolean is_end) { 47 | return snowboyJNI.SnowboyVad_RunVad__SWIG_0(swigCPtr, this, data, is_end); 48 | } 49 | 50 | public int RunVad(String data) { 51 | return snowboyJNI.SnowboyVad_RunVad__SWIG_1(swigCPtr, this, data); 52 | } 53 | 54 | public int RunVad(float[] data, int array_length, boolean is_end) { 55 | return snowboyJNI.SnowboyVad_RunVad__SWIG_2(swigCPtr, this, data, 56 | array_length, is_end); 57 | } 58 | 59 | public int RunVad(float[] data, int array_length) { 60 | return snowboyJNI.SnowboyVad_RunVad__SWIG_3(swigCPtr, this, data, 61 | array_length); 62 | } 63 | 64 | public int RunVad(short[] data, int array_length, boolean is_end) { 65 | return snowboyJNI.SnowboyVad_RunVad__SWIG_4(swigCPtr, this, data, 66 | array_length, is_end); 67 | } 68 | 69 | public int RunVad(short[] data, int array_length) { 70 | return snowboyJNI.SnowboyVad_RunVad__SWIG_5(swigCPtr, this, data, 71 | array_length); 72 | } 73 | 74 | public int RunVad(int[] data, int array_length, boolean is_end) { 75 | return snowboyJNI.SnowboyVad_RunVad__SWIG_6(swigCPtr, this, data, 76 | array_length, is_end); 77 | } 78 | 79 | public int RunVad(int[] data, int array_length) { 80 | return snowboyJNI.SnowboyVad_RunVad__SWIG_7(swigCPtr, this, data, 81 | array_length); 82 | } 83 | 84 | public void SetAudioGain(float audio_gain) { 85 | snowboyJNI.SnowboyVad_SetAudioGain(swigCPtr, this, audio_gain); 86 | } 87 | 88 | public void ApplyFrontend(boolean apply_frontend) { 89 | snowboyJNI.SnowboyVad_ApplyFrontend(swigCPtr, this, apply_frontend); 90 | } 91 | 92 | public int SampleRate() { 93 | return snowboyJNI.SnowboyVad_SampleRate(swigCPtr, this); 94 | } 95 | 96 | public int NumChannels() { 97 | return snowboyJNI.SnowboyVad_NumChannels(swigCPtr, this); 98 | } 99 | 100 | public int BitsPerSample() { 101 | return snowboyJNI.SnowboyVad_BitsPerSample(swigCPtr, this); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /android/src/main/java/ai/kitt/snowboy/snowboy.java: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------------- 2 | * This file was automatically generated by SWIG (https://www.swig.org). 3 | * Version 4.0.2 4 | * 5 | * Do not make changes to this file unless you know what you are doing--modify 6 | * the SWIG interface file instead. 7 | * ----------------------------------------------------------------------------- 8 | */ 9 | 10 | package ai.kitt.snowboy; 11 | 12 | public class snowboy {} 13 | -------------------------------------------------------------------------------- /android/src/main/java/ai/kitt/snowboy/snowboyJNI.java: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------------- 2 | * This file was automatically generated by SWIG (https://www.swig.org). 3 | * Version 4.0.2 4 | * 5 | * Do not make changes to this file unless you know what you are doing--modify 6 | * the SWIG interface file instead. 7 | * ----------------------------------------------------------------------------- 8 | */ 9 | 10 | package ai.kitt.snowboy; 11 | 12 | public class snowboyJNI { 13 | public final static native long new_SnowboyDetect(String jarg1, String jarg2); 14 | public final static native boolean SnowboyDetect_Reset(long jarg1, 15 | SnowboyDetect jarg1_); 16 | public final static native int 17 | SnowboyDetect_RunDetection__SWIG_0(long jarg1, SnowboyDetect jarg1_, 18 | String jarg2, boolean jarg3); 19 | public final static native int 20 | SnowboyDetect_RunDetection__SWIG_1(long jarg1, SnowboyDetect jarg1_, 21 | String jarg2); 22 | public final static native int 23 | SnowboyDetect_RunDetection__SWIG_2(long jarg1, SnowboyDetect jarg1_, 24 | float[] jarg2, int jarg3, boolean jarg4); 25 | public final static native int 26 | SnowboyDetect_RunDetection__SWIG_3(long jarg1, SnowboyDetect jarg1_, 27 | float[] jarg2, int jarg3); 28 | public final static native int 29 | SnowboyDetect_RunDetection__SWIG_4(long jarg1, SnowboyDetect jarg1_, 30 | short[] jarg2, int jarg3, boolean jarg4); 31 | public final static native int 32 | SnowboyDetect_RunDetection__SWIG_5(long jarg1, SnowboyDetect jarg1_, 33 | short[] jarg2, int jarg3); 34 | public final static native int 35 | SnowboyDetect_RunDetection__SWIG_6(long jarg1, SnowboyDetect jarg1_, 36 | int[] jarg2, int jarg3, boolean jarg4); 37 | public final static native int 38 | SnowboyDetect_RunDetection__SWIG_7(long jarg1, SnowboyDetect jarg1_, 39 | int[] jarg2, int jarg3); 40 | public final static native void 41 | SnowboyDetect_SetSensitivity(long jarg1, SnowboyDetect jarg1_, String jarg2); 42 | public final static native void 43 | SnowboyDetect_SetHighSensitivity(long jarg1, SnowboyDetect jarg1_, 44 | String jarg2); 45 | public final static native String 46 | SnowboyDetect_GetSensitivity(long jarg1, SnowboyDetect jarg1_); 47 | public final static native void 48 | SnowboyDetect_SetAudioGain(long jarg1, SnowboyDetect jarg1_, float jarg2); 49 | public final static native void 50 | SnowboyDetect_UpdateModel(long jarg1, SnowboyDetect jarg1_); 51 | public final static native int 52 | SnowboyDetect_NumHotwords(long jarg1, SnowboyDetect jarg1_); 53 | public final static native void 54 | SnowboyDetect_ApplyFrontend(long jarg1, SnowboyDetect jarg1_, boolean jarg2); 55 | public final static native int SnowboyDetect_SampleRate(long jarg1, 56 | SnowboyDetect jarg1_); 57 | public final static native int 58 | SnowboyDetect_NumChannels(long jarg1, SnowboyDetect jarg1_); 59 | public final static native int 60 | SnowboyDetect_BitsPerSample(long jarg1, SnowboyDetect jarg1_); 61 | public final static native void delete_SnowboyDetect(long jarg1); 62 | public final static native long new_SnowboyVad(String jarg1); 63 | public final static native boolean SnowboyVad_Reset(long jarg1, 64 | SnowboyVad jarg1_); 65 | public final static native int SnowboyVad_RunVad__SWIG_0(long jarg1, 66 | SnowboyVad jarg1_, 67 | String jarg2, 68 | boolean jarg3); 69 | public final static native int 70 | SnowboyVad_RunVad__SWIG_1(long jarg1, SnowboyVad jarg1_, String jarg2); 71 | public final static native int 72 | SnowboyVad_RunVad__SWIG_2(long jarg1, SnowboyVad jarg1_, float[] jarg2, 73 | int jarg3, boolean jarg4); 74 | public final static native int SnowboyVad_RunVad__SWIG_3(long jarg1, 75 | SnowboyVad jarg1_, 76 | float[] jarg2, 77 | int jarg3); 78 | public final static native int 79 | SnowboyVad_RunVad__SWIG_4(long jarg1, SnowboyVad jarg1_, short[] jarg2, 80 | int jarg3, boolean jarg4); 81 | public final static native int SnowboyVad_RunVad__SWIG_5(long jarg1, 82 | SnowboyVad jarg1_, 83 | short[] jarg2, 84 | int jarg3); 85 | public final static native int 86 | SnowboyVad_RunVad__SWIG_6(long jarg1, SnowboyVad jarg1_, int[] jarg2, 87 | int jarg3, boolean jarg4); 88 | public final static native int SnowboyVad_RunVad__SWIG_7(long jarg1, 89 | SnowboyVad jarg1_, 90 | int[] jarg2, 91 | int jarg3); 92 | public final static native void 93 | SnowboyVad_SetAudioGain(long jarg1, SnowboyVad jarg1_, float jarg2); 94 | public final static native void 95 | SnowboyVad_ApplyFrontend(long jarg1, SnowboyVad jarg1_, boolean jarg2); 96 | public final static native int SnowboyVad_SampleRate(long jarg1, 97 | SnowboyVad jarg1_); 98 | public final static native int SnowboyVad_NumChannels(long jarg1, 99 | SnowboyVad jarg1_); 100 | public final static native int SnowboyVad_BitsPerSample(long jarg1, 101 | SnowboyVad jarg1_); 102 | public final static native void delete_SnowboyVad(long jarg1); 103 | } 104 | -------------------------------------------------------------------------------- /android/src/main/java/is/mideind/flutter_snowboy/Detector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2023 Miðeind ehf. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package is.mideind.flutter_snowboy; 19 | 20 | import ai.kitt.snowboy.Constants; 21 | import ai.kitt.snowboy.MsgEnum; 22 | import ai.kitt.snowboy.SnowboyDetect; 23 | import android.os.Handler; 24 | import android.os.Message; 25 | import android.util.Log; 26 | import java.nio.ByteBuffer; 27 | import java.nio.ByteOrder; 28 | 29 | public class Detector { 30 | // Load compiled Snowboy shared object 31 | static { System.loadLibrary("snowboy-detect-android"); } 32 | 33 | private final Handler handler; 34 | private final SnowboyDetect snowboy; 35 | 36 | public Detector(Handler handler, String commonPath, String modelPath, 37 | String sensitivity, double audioGain, boolean applyFrontend) { 38 | 39 | // Create and configure SnowboyDetect object 40 | this.snowboy = new SnowboyDetect(commonPath, modelPath); 41 | this.snowboy.SetSensitivity(sensitivity); 42 | this.snowboy.SetAudioGain((float)audioGain); 43 | this.snowboy.ApplyFrontend(applyFrontend); 44 | 45 | this.handler = handler; 46 | } 47 | 48 | public void detect(byte[] audioBuffer) { 49 | // Convert data to 16-bit shorts and feed into Snowboy detection function 50 | short[] audioData = new short[audioBuffer.length / 2]; 51 | ByteBuffer.wrap(audioBuffer) 52 | .order(ByteOrder.LITTLE_ENDIAN) 53 | .asShortBuffer() 54 | .get(audioData); 55 | int result = this.snowboy.RunDetection(audioData, audioData.length); 56 | 57 | // Process result from Snowboy detection fn 58 | if (result == -2) { 59 | // post a higher CPU usage: 60 | // sendMessage(MsgEnum.MSG_VAD_NOSPEECH, null); 61 | } else if (result == -1) { 62 | sendMessage(MsgEnum.MSG_ERROR, "Unknown Detection Error"); 63 | } else if (result == 0) { 64 | // post a higher CPU usage: 65 | // sendMessage(MsgEnum.MSG_VAD_SPEECH, null); 66 | } else if (result > 0) { 67 | sendMessage(MsgEnum.MSG_ACTIVE, null); 68 | // Log.i("Snowboy: ", "Hotword " + Integer.toString(result) + " 69 | // detected!"); 70 | } 71 | } 72 | 73 | private void sendMessage(MsgEnum what, Object obj) { 74 | if (handler != null) { 75 | Message msg = handler.obtainMessage(what.ordinal(), obj); 76 | handler.sendMessage(msg); 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /android/src/main/java/is/mideind/flutter_snowboy/FlutterSnowboyPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2023 Miðeind ehf. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package is.mideind.flutter_snowboy; 19 | 20 | import ai.kitt.snowboy.AppResCopy; 21 | import ai.kitt.snowboy.Constants; 22 | import android.content.Context; 23 | import android.os.Handler; 24 | import android.os.Message; 25 | import android.os.Looper; 26 | import androidx.annotation.NonNull; 27 | import io.flutter.embedding.engine.plugins.FlutterPlugin; 28 | import io.flutter.plugin.common.MethodCall; 29 | import io.flutter.plugin.common.MethodChannel; 30 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 31 | import io.flutter.plugin.common.MethodChannel.Result; 32 | import is.mideind.flutter_snowboy.Detector; 33 | import java.io.File; 34 | import java.util.*; 35 | 36 | public class FlutterSnowboyPlugin implements FlutterPlugin, MethodCallHandler { 37 | // The MethodChannel that handles communication between Flutter and native 38 | // Android. This local reference serves to register the plugin with the 39 | // Flutter Engine and unregister it when the Flutter Engine is detached from 40 | // the Activity. 41 | private MethodChannel channel; 42 | 43 | private Context context; 44 | private Detector detector; 45 | 46 | // Handler invoked when hotword is detected 47 | public Handler handle = new Handler(Looper.getMainLooper()) { 48 | @Override 49 | public void handleMessage(Message msg) { 50 | // System.err.println("Handler invoked!"); 51 | 52 | channel.invokeMethod("hotword", null, new Result() { 53 | // Boilerplate 54 | @Override 55 | public void success(Object o) { 56 | } 57 | 58 | @Override 59 | public void error(String s, String s1, Object o) { 60 | } 61 | 62 | @Override 63 | public void notImplemented() { 64 | } 65 | }); 66 | } 67 | }; 68 | 69 | public void prepareSnowboy(@NonNull MethodCall call, @NonNull Result result) { 70 | // Copy assets required by Snowboy to filesystem 71 | String rsrcPath = context.getFilesDir().getAbsolutePath() + "/" + 72 | Constants.ASSETS_DIRNAME; 73 | String commonPath = rsrcPath + "/" + Constants.COMMON_RES_FILENAME; 74 | 75 | try { 76 | AppResCopy.copyFilesFromAssets(context, Constants.ASSETS_DIRNAME, 77 | rsrcPath, true); 78 | 79 | ArrayList args = call.arguments(); 80 | 81 | String modelPath = (String) args.get(0); 82 | 83 | // Basic sanity check 84 | if (modelPath == null || modelPath.trim().isEmpty()) { 85 | System.out.println("Invalid model path: '" + modelPath + "'"); 86 | result.success(false); 87 | return; 88 | } 89 | 90 | // Make sure model exists at path 91 | File modelFile = new File(modelPath); 92 | if (!modelFile.exists()) { 93 | System.out.println("No model at path: '" + modelPath + "'"); 94 | result.success(false); 95 | return; 96 | } 97 | 98 | System.out.println("Final model path: '" + modelPath + "'"); 99 | 100 | String sensitivity = args.get(1) + ""; 101 | double audioGain = (double) args.get(2); 102 | boolean applyFrontend = (boolean) args.get(3); 103 | 104 | detector = new Detector(handle, commonPath, modelPath, sensitivity, 105 | audioGain, applyFrontend); 106 | 107 | } catch (Exception e) { 108 | e.printStackTrace(); 109 | result.success(false); 110 | } 111 | 112 | result.success(true); 113 | } 114 | 115 | public void detectSnowboy(@NonNull MethodCall call, @NonNull Result result) { 116 | try { 117 | // Retrieve first argument from Flutter. This should be audio data. 118 | ArrayList args = call.arguments(); 119 | byte[] bytes = (byte[]) args.get(0); 120 | // Feed bytes into detector 121 | detector.detect(bytes); 122 | } catch (Exception e) { 123 | e.printStackTrace(); 124 | result.success(false); 125 | } 126 | result.success(true); 127 | } 128 | 129 | public void purgeSnowboy(@NonNull MethodCall call, @NonNull Result result) { 130 | // Dispose of any resources used by detector. 131 | detector = null; 132 | result.success(null); 133 | } 134 | 135 | @Override 136 | public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { 137 | // Called when the Flutter plugin is attached to the Flutter Engine. 138 | channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), 139 | "plugin_snowboy"); 140 | channel.setMethodCallHandler(this); 141 | context = flutterPluginBinding.getApplicationContext(); 142 | } 143 | 144 | @Override 145 | public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { 146 | channel.setMethodCallHandler(null); 147 | } 148 | 149 | @Override 150 | public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { 151 | // Forward Flutter method calls to native code 152 | if (call.method.equals("prepareSnowboy")) { 153 | prepareSnowboy(call, result); 154 | } else if (call.method.equals("detectSnowboy")) { 155 | detectSnowboy(call, result); 156 | } else if (call.method.equals("purgeSnowboy")) { 157 | purgeSnowboy(call, result); 158 | } else { 159 | result.notImplemented(); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /android/src/main/jniLibs/arm64-v8a/libsnowboy-detect-android.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/android/src/main/jniLibs/arm64-v8a/libsnowboy-detect-android.so -------------------------------------------------------------------------------- /android/src/main/jniLibs/armeabi-v7a/libsnowboy-detect-android.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/android/src/main/jniLibs/armeabi-v7a/libsnowboy-detect-android.so -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: adc687823a831bbebe28bdccfac1a628ca621513 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Example app that uses flutter_snowboy 2 | 3 | Simple app that demonstrates how to use the flutter_snowboy plugin. 4 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 33 29 | 30 | defaultConfig { 31 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 32 | applicationId "is.mideind.flutter_snowboy_example" 33 | minSdkVersion 31 34 | targetSdkVersion 31 35 | versionCode flutterVersionCode.toInteger() 36 | versionName flutterVersionName 37 | } 38 | 39 | buildTypes { 40 | release { 41 | // TODO: Add your own signing config for the release build. 42 | // Signing with the debug keys for now, so `flutter run --release` works. 43 | signingConfig signingConfigs.debug 44 | } 45 | } 46 | namespace 'is.mideind.flutter_snowboy_example' 47 | } 48 | 49 | flutter { 50 | source '../..' 51 | } 52 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 14 | 21 | 25 | 33 | 37 | 38 | 39 | 40 | 41 | 42 | 45 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/flutter_snowboy_example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package is.mideind.flutter_snowboy_example; 2 | 3 | import io.flutter.embedding.android.FlutterActivity; 4 | 5 | public class MainActivity extends FlutterActivity { 6 | } 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:7.4.2' 9 | } 10 | } 11 | 12 | allprojects { 13 | 14 | repositories { 15 | google() 16 | jcenter() 17 | } 18 | tasks.withType(JavaCompile) { 19 | options.deprecation = true 20 | // options.compilerArgs << '-Xlint:-options' 21 | // options.compilerArgs << '-Xlint:unchecked' 22 | // options.compilerArgs << '-Xlint:deprecation' 23 | } 24 | 25 | } 26 | 27 | rootProject.buildDir = '../build' 28 | subprojects { 29 | project.buildDir = "${rootProject.buildDir}/${project.name}" 30 | } 31 | subprojects { 32 | project.evaluationDependsOn(':app') 33 | } 34 | 35 | tasks.register("clean", Delete) { 36 | delete rootProject.buildDir 37 | } 38 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /example/android/settings_aar.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /example/assets/ding.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/assets/ding.wav -------------------------------------------------------------------------------- /example/assets/hi_embla.pmdl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/assets/hi_embla.pmdl -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '12.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 32 | end 33 | 34 | post_install do |installer| 35 | installer.pods_project.targets.each do |target| 36 | flutter_additional_ios_build_settings(target) 37 | target.build_configurations.each do |config| 38 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 13 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 14 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 15 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 16 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 17 | EB5F32BFB9618B616D3713A6 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B9C0D2A6A6C67371F161C6A /* libPods-Runner.a */; }; 18 | F44856512668F2960098872C /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F44856502668F2960098872C /* Accelerate.framework */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXCopyFilesBuildPhase section */ 22 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 23 | isa = PBXCopyFilesBuildPhase; 24 | buildActionMask = 2147483647; 25 | dstPath = ""; 26 | dstSubfolderSpec = 10; 27 | files = ( 28 | ); 29 | name = "Embed Frameworks"; 30 | runOnlyForDeploymentPostprocessing = 0; 31 | }; 32 | /* End PBXCopyFilesBuildPhase section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | 08D0912B1FBC476F82642EEE /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 36 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 37 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 38 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 39 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 40 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 41 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 42 | 7B9C0D2A6A6C67371F161C6A /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | 91622AEA0A1F1E6BFF0F78C0 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 44 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 45 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 46 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 48 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 49 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 50 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 51 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | C4E8D52815BAA09648D9E388 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 53 | F44856502668F2960098872C /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; 54 | /* End PBXFileReference section */ 55 | 56 | /* Begin PBXFrameworksBuildPhase section */ 57 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | EB5F32BFB9618B616D3713A6 /* libPods-Runner.a in Frameworks */, 62 | F44856512668F2960098872C /* Accelerate.framework in Frameworks */, 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 9740EEB11CF90186004384FC /* Flutter */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 73 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 74 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 75 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 76 | ); 77 | name = Flutter; 78 | sourceTree = ""; 79 | }; 80 | 97C146E51CF9000F007C117D = { 81 | isa = PBXGroup; 82 | children = ( 83 | 9740EEB11CF90186004384FC /* Flutter */, 84 | 97C146F01CF9000F007C117D /* Runner */, 85 | 97C146EF1CF9000F007C117D /* Products */, 86 | FFD2C0452C78E51E66B4F438 /* Pods */, 87 | C1AC7649944008E5BBEFFE1F /* Frameworks */, 88 | ); 89 | sourceTree = ""; 90 | }; 91 | 97C146EF1CF9000F007C117D /* Products */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 97C146EE1CF9000F007C117D /* Runner.app */, 95 | ); 96 | name = Products; 97 | sourceTree = ""; 98 | }; 99 | 97C146F01CF9000F007C117D /* Runner */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 103 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 104 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 105 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 106 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 107 | 97C147021CF9000F007C117D /* Info.plist */, 108 | 97C146F11CF9000F007C117D /* Supporting Files */, 109 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 110 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 111 | ); 112 | path = Runner; 113 | sourceTree = ""; 114 | }; 115 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 97C146F21CF9000F007C117D /* main.m */, 119 | ); 120 | name = "Supporting Files"; 121 | sourceTree = ""; 122 | }; 123 | C1AC7649944008E5BBEFFE1F /* Frameworks */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | F44856502668F2960098872C /* Accelerate.framework */, 127 | 7B9C0D2A6A6C67371F161C6A /* libPods-Runner.a */, 128 | ); 129 | name = Frameworks; 130 | sourceTree = ""; 131 | }; 132 | FFD2C0452C78E51E66B4F438 /* Pods */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 08D0912B1FBC476F82642EEE /* Pods-Runner.debug.xcconfig */, 136 | C4E8D52815BAA09648D9E388 /* Pods-Runner.release.xcconfig */, 137 | 91622AEA0A1F1E6BFF0F78C0 /* Pods-Runner.profile.xcconfig */, 138 | ); 139 | path = Pods; 140 | sourceTree = ""; 141 | }; 142 | /* End PBXGroup section */ 143 | 144 | /* Begin PBXNativeTarget section */ 145 | 97C146ED1CF9000F007C117D /* Runner */ = { 146 | isa = PBXNativeTarget; 147 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 148 | buildPhases = ( 149 | EF832184358DADFA454195D8 /* [CP] Check Pods Manifest.lock */, 150 | 9740EEB61CF901F6004384FC /* Run Script */, 151 | 97C146EA1CF9000F007C117D /* Sources */, 152 | 97C146EB1CF9000F007C117D /* Frameworks */, 153 | 97C146EC1CF9000F007C117D /* Resources */, 154 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 155 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 156 | 3B240D6C70DC54C32CF95C16 /* [CP] Copy Pods Resources */, 157 | ); 158 | buildRules = ( 159 | ); 160 | dependencies = ( 161 | ); 162 | name = Runner; 163 | productName = Runner; 164 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 165 | productType = "com.apple.product-type.application"; 166 | }; 167 | /* End PBXNativeTarget section */ 168 | 169 | /* Begin PBXProject section */ 170 | 97C146E61CF9000F007C117D /* Project object */ = { 171 | isa = PBXProject; 172 | attributes = { 173 | BuildIndependentTargetsInParallel = YES; 174 | LastUpgradeCheck = 1430; 175 | ORGANIZATIONNAME = ""; 176 | TargetAttributes = { 177 | 97C146ED1CF9000F007C117D = { 178 | CreatedOnToolsVersion = 7.3.1; 179 | }; 180 | }; 181 | }; 182 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 183 | compatibilityVersion = "Xcode 9.3"; 184 | developmentRegion = en; 185 | hasScannedForEncodings = 0; 186 | knownRegions = ( 187 | en, 188 | Base, 189 | ); 190 | mainGroup = 97C146E51CF9000F007C117D; 191 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 192 | projectDirPath = ""; 193 | projectRoot = ""; 194 | targets = ( 195 | 97C146ED1CF9000F007C117D /* Runner */, 196 | ); 197 | }; 198 | /* End PBXProject section */ 199 | 200 | /* Begin PBXResourcesBuildPhase section */ 201 | 97C146EC1CF9000F007C117D /* Resources */ = { 202 | isa = PBXResourcesBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 206 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 207 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 208 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXResourcesBuildPhase section */ 213 | 214 | /* Begin PBXShellScriptBuildPhase section */ 215 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 216 | isa = PBXShellScriptBuildPhase; 217 | alwaysOutOfDate = 1; 218 | buildActionMask = 2147483647; 219 | files = ( 220 | ); 221 | inputPaths = ( 222 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", 223 | ); 224 | name = "Thin Binary"; 225 | outputPaths = ( 226 | ); 227 | runOnlyForDeploymentPostprocessing = 0; 228 | shellPath = /bin/sh; 229 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n"; 230 | }; 231 | 3B240D6C70DC54C32CF95C16 /* [CP] Copy Pods Resources */ = { 232 | isa = PBXShellScriptBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | ); 236 | inputFileListPaths = ( 237 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", 238 | ); 239 | name = "[CP] Copy Pods Resources"; 240 | outputFileListPaths = ( 241 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", 242 | ); 243 | runOnlyForDeploymentPostprocessing = 0; 244 | shellPath = /bin/sh; 245 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; 246 | showEnvVarsInLog = 0; 247 | }; 248 | 9740EEB61CF901F6004384FC /* Run Script */ = { 249 | isa = PBXShellScriptBuildPhase; 250 | alwaysOutOfDate = 1; 251 | buildActionMask = 2147483647; 252 | files = ( 253 | ); 254 | inputPaths = ( 255 | ); 256 | name = "Run Script"; 257 | outputPaths = ( 258 | ); 259 | runOnlyForDeploymentPostprocessing = 0; 260 | shellPath = /bin/sh; 261 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 262 | }; 263 | EF832184358DADFA454195D8 /* [CP] Check Pods Manifest.lock */ = { 264 | isa = PBXShellScriptBuildPhase; 265 | buildActionMask = 2147483647; 266 | files = ( 267 | ); 268 | inputFileListPaths = ( 269 | ); 270 | inputPaths = ( 271 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 272 | "${PODS_ROOT}/Manifest.lock", 273 | ); 274 | name = "[CP] Check Pods Manifest.lock"; 275 | outputFileListPaths = ( 276 | ); 277 | outputPaths = ( 278 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | shellPath = /bin/sh; 282 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 283 | showEnvVarsInLog = 0; 284 | }; 285 | /* End PBXShellScriptBuildPhase section */ 286 | 287 | /* Begin PBXSourcesBuildPhase section */ 288 | 97C146EA1CF9000F007C117D /* Sources */ = { 289 | isa = PBXSourcesBuildPhase; 290 | buildActionMask = 2147483647; 291 | files = ( 292 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 293 | 97C146F31CF9000F007C117D /* main.m in Sources */, 294 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 295 | ); 296 | runOnlyForDeploymentPostprocessing = 0; 297 | }; 298 | /* End PBXSourcesBuildPhase section */ 299 | 300 | /* Begin PBXVariantGroup section */ 301 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 302 | isa = PBXVariantGroup; 303 | children = ( 304 | 97C146FB1CF9000F007C117D /* Base */, 305 | ); 306 | name = Main.storyboard; 307 | sourceTree = ""; 308 | }; 309 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 310 | isa = PBXVariantGroup; 311 | children = ( 312 | 97C147001CF9000F007C117D /* Base */, 313 | ); 314 | name = LaunchScreen.storyboard; 315 | sourceTree = ""; 316 | }; 317 | /* End PBXVariantGroup section */ 318 | 319 | /* Begin XCBuildConfiguration section */ 320 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 321 | isa = XCBuildConfiguration; 322 | buildSettings = { 323 | ALWAYS_SEARCH_USER_PATHS = NO; 324 | CLANG_ANALYZER_NONNULL = YES; 325 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 326 | CLANG_CXX_LIBRARY = "libc++"; 327 | CLANG_ENABLE_MODULES = YES; 328 | CLANG_ENABLE_OBJC_ARC = YES; 329 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 330 | CLANG_WARN_BOOL_CONVERSION = YES; 331 | CLANG_WARN_COMMA = YES; 332 | CLANG_WARN_CONSTANT_CONVERSION = YES; 333 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 334 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 335 | CLANG_WARN_EMPTY_BODY = YES; 336 | CLANG_WARN_ENUM_CONVERSION = YES; 337 | CLANG_WARN_INFINITE_RECURSION = YES; 338 | CLANG_WARN_INT_CONVERSION = YES; 339 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 340 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 341 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 342 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 343 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 344 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 345 | CLANG_WARN_STRICT_PROTOTYPES = YES; 346 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 347 | CLANG_WARN_UNREACHABLE_CODE = YES; 348 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 349 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 350 | COPY_PHASE_STRIP = NO; 351 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 352 | ENABLE_NS_ASSERTIONS = NO; 353 | ENABLE_STRICT_OBJC_MSGSEND = YES; 354 | GCC_C_LANGUAGE_STANDARD = gnu99; 355 | GCC_NO_COMMON_BLOCKS = YES; 356 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 357 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 358 | GCC_WARN_UNDECLARED_SELECTOR = YES; 359 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 360 | GCC_WARN_UNUSED_FUNCTION = YES; 361 | GCC_WARN_UNUSED_VARIABLE = YES; 362 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 363 | MTL_ENABLE_DEBUG_INFO = NO; 364 | OTHER_CPLUSPLUSFLAGS = ( 365 | "$(OTHER_CFLAGS)", 366 | "-fmodules", 367 | "-fcxx-modules", 368 | ); 369 | SDKROOT = iphoneos; 370 | SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; 371 | TARGETED_DEVICE_FAMILY = 1; 372 | VALIDATE_PRODUCT = YES; 373 | }; 374 | name = Profile; 375 | }; 376 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 377 | isa = XCBuildConfiguration; 378 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 379 | buildSettings = { 380 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 381 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 382 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 383 | DEVELOPMENT_TEAM = XT9WMG6U47; 384 | ENABLE_BITCODE = NO; 385 | GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; 386 | INFOPLIST_FILE = Runner/Info.plist; 387 | INFOPLIST_KEY_CFBundleDisplayName = flutter_snowboy_example; 388 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 389 | LD_RUNPATH_SEARCH_PATHS = ( 390 | "$(inherited)", 391 | "@executable_path/Frameworks", 392 | ); 393 | MARKETING_VERSION = 1.0; 394 | PRODUCT_BUNDLE_IDENTIFIER = is.mideind.FlutterSnowboyExample; 395 | PRODUCT_NAME = "$(TARGET_NAME)"; 396 | TARGETED_DEVICE_FAMILY = 1; 397 | VERSIONING_SYSTEM = "apple-generic"; 398 | }; 399 | name = Profile; 400 | }; 401 | 97C147031CF9000F007C117D /* Debug */ = { 402 | isa = XCBuildConfiguration; 403 | buildSettings = { 404 | ALWAYS_SEARCH_USER_PATHS = NO; 405 | CLANG_ANALYZER_NONNULL = YES; 406 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 407 | CLANG_CXX_LIBRARY = "libc++"; 408 | CLANG_ENABLE_MODULES = YES; 409 | CLANG_ENABLE_OBJC_ARC = YES; 410 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 411 | CLANG_WARN_BOOL_CONVERSION = YES; 412 | CLANG_WARN_COMMA = YES; 413 | CLANG_WARN_CONSTANT_CONVERSION = YES; 414 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 415 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 416 | CLANG_WARN_EMPTY_BODY = YES; 417 | CLANG_WARN_ENUM_CONVERSION = YES; 418 | CLANG_WARN_INFINITE_RECURSION = YES; 419 | CLANG_WARN_INT_CONVERSION = YES; 420 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 421 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 422 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 423 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 424 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 425 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 426 | CLANG_WARN_STRICT_PROTOTYPES = YES; 427 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 428 | CLANG_WARN_UNREACHABLE_CODE = YES; 429 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 430 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 431 | COPY_PHASE_STRIP = NO; 432 | DEBUG_INFORMATION_FORMAT = dwarf; 433 | ENABLE_STRICT_OBJC_MSGSEND = YES; 434 | ENABLE_TESTABILITY = YES; 435 | GCC_C_LANGUAGE_STANDARD = gnu99; 436 | GCC_DYNAMIC_NO_PIC = NO; 437 | GCC_NO_COMMON_BLOCKS = YES; 438 | GCC_OPTIMIZATION_LEVEL = 0; 439 | GCC_PREPROCESSOR_DEFINITIONS = ( 440 | "DEBUG=1", 441 | "$(inherited)", 442 | ); 443 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 444 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 445 | GCC_WARN_UNDECLARED_SELECTOR = YES; 446 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 447 | GCC_WARN_UNUSED_FUNCTION = YES; 448 | GCC_WARN_UNUSED_VARIABLE = YES; 449 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 450 | MTL_ENABLE_DEBUG_INFO = YES; 451 | ONLY_ACTIVE_ARCH = YES; 452 | OTHER_CPLUSPLUSFLAGS = ( 453 | "$(OTHER_CFLAGS)", 454 | "-fmodules", 455 | "-fcxx-modules", 456 | ); 457 | SDKROOT = iphoneos; 458 | TARGETED_DEVICE_FAMILY = 1; 459 | }; 460 | name = Debug; 461 | }; 462 | 97C147041CF9000F007C117D /* Release */ = { 463 | isa = XCBuildConfiguration; 464 | buildSettings = { 465 | ALWAYS_SEARCH_USER_PATHS = NO; 466 | CLANG_ANALYZER_NONNULL = YES; 467 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 468 | CLANG_CXX_LIBRARY = "libc++"; 469 | CLANG_ENABLE_MODULES = YES; 470 | CLANG_ENABLE_OBJC_ARC = YES; 471 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 472 | CLANG_WARN_BOOL_CONVERSION = YES; 473 | CLANG_WARN_COMMA = YES; 474 | CLANG_WARN_CONSTANT_CONVERSION = YES; 475 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 476 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 477 | CLANG_WARN_EMPTY_BODY = YES; 478 | CLANG_WARN_ENUM_CONVERSION = YES; 479 | CLANG_WARN_INFINITE_RECURSION = YES; 480 | CLANG_WARN_INT_CONVERSION = YES; 481 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 482 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 483 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 484 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 485 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 486 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 487 | CLANG_WARN_STRICT_PROTOTYPES = YES; 488 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 489 | CLANG_WARN_UNREACHABLE_CODE = YES; 490 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 491 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 492 | COPY_PHASE_STRIP = YES; 493 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 494 | ENABLE_NS_ASSERTIONS = NO; 495 | ENABLE_STRICT_OBJC_MSGSEND = YES; 496 | GCC_C_LANGUAGE_STANDARD = gnu99; 497 | GCC_NO_COMMON_BLOCKS = YES; 498 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 499 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 500 | GCC_WARN_UNDECLARED_SELECTOR = YES; 501 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 502 | GCC_WARN_UNUSED_FUNCTION = YES; 503 | GCC_WARN_UNUSED_VARIABLE = YES; 504 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 505 | MTL_ENABLE_DEBUG_INFO = NO; 506 | OTHER_CPLUSPLUSFLAGS = ( 507 | "$(OTHER_CFLAGS)", 508 | "-fmodules", 509 | "-fcxx-modules", 510 | ); 511 | SDKROOT = iphoneos; 512 | SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; 513 | TARGETED_DEVICE_FAMILY = 1; 514 | VALIDATE_PRODUCT = YES; 515 | }; 516 | name = Release; 517 | }; 518 | 97C147061CF9000F007C117D /* Debug */ = { 519 | isa = XCBuildConfiguration; 520 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 521 | buildSettings = { 522 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 523 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 524 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 525 | DEVELOPMENT_TEAM = XT9WMG6U47; 526 | ENABLE_BITCODE = NO; 527 | GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; 528 | INFOPLIST_FILE = Runner/Info.plist; 529 | INFOPLIST_KEY_CFBundleDisplayName = flutter_snowboy_example; 530 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 531 | LD_RUNPATH_SEARCH_PATHS = ( 532 | "$(inherited)", 533 | "@executable_path/Frameworks", 534 | ); 535 | MARKETING_VERSION = 1.0; 536 | PRODUCT_BUNDLE_IDENTIFIER = is.mideind.FlutterSnowboyExample; 537 | PRODUCT_NAME = "$(TARGET_NAME)"; 538 | TARGETED_DEVICE_FAMILY = 1; 539 | VERSIONING_SYSTEM = "apple-generic"; 540 | }; 541 | name = Debug; 542 | }; 543 | 97C147071CF9000F007C117D /* Release */ = { 544 | isa = XCBuildConfiguration; 545 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 546 | buildSettings = { 547 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 548 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 549 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 550 | DEVELOPMENT_TEAM = XT9WMG6U47; 551 | ENABLE_BITCODE = NO; 552 | GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; 553 | INFOPLIST_FILE = Runner/Info.plist; 554 | INFOPLIST_KEY_CFBundleDisplayName = flutter_snowboy_example; 555 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 556 | LD_RUNPATH_SEARCH_PATHS = ( 557 | "$(inherited)", 558 | "@executable_path/Frameworks", 559 | ); 560 | MARKETING_VERSION = 1.0; 561 | PRODUCT_BUNDLE_IDENTIFIER = is.mideind.FlutterSnowboyExample; 562 | PRODUCT_NAME = "$(TARGET_NAME)"; 563 | TARGETED_DEVICE_FAMILY = 1; 564 | VERSIONING_SYSTEM = "apple-generic"; 565 | }; 566 | name = Release; 567 | }; 568 | /* End XCBuildConfiguration section */ 569 | 570 | /* Begin XCConfigurationList section */ 571 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 572 | isa = XCConfigurationList; 573 | buildConfigurations = ( 574 | 97C147031CF9000F007C117D /* Debug */, 575 | 97C147041CF9000F007C117D /* Release */, 576 | 249021D3217E4FDB00AE95B9 /* Profile */, 577 | ); 578 | defaultConfigurationIsVisible = 0; 579 | defaultConfigurationName = Release; 580 | }; 581 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 582 | isa = XCConfigurationList; 583 | buildConfigurations = ( 584 | 97C147061CF9000F007C117D /* Debug */, 585 | 97C147071CF9000F007C117D /* Release */, 586 | 249021D4217E4FDB00AE95B9 /* Profile */, 587 | ); 588 | defaultConfigurationIsVisible = 0; 589 | defaultConfigurationName = Release; 590 | }; 591 | /* End XCConfigurationList section */ 592 | }; 593 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 594 | } 595 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CADisableMinimumFrameDurationOnPhone 6 | 7 | CFBundleDevelopmentRegion 8 | $(DEVELOPMENT_LANGUAGE) 9 | CFBundleDisplayName 10 | flutter_snowboy_example 11 | CFBundleExecutable 12 | $(EXECUTABLE_NAME) 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | flutter_snowboy_example 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | $(MARKETING_VERSION) 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | $(FLUTTER_BUILD_NUMBER) 27 | LSRequiresIPhoneOS 28 | 29 | NSMicrophoneUsageDescription 30 | This app uses the microphone for hotword detection. 31 | UIApplicationSupportsIndirectInputEvents 32 | 33 | UILaunchStoryboardName 34 | LaunchScreen 35 | UIMainStoryboardFile 36 | Main 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | UISupportedInterfaceOrientations~ipad 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationPortraitUpsideDown 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * flutter_snowboy - Flutter package wrapper for Snowboy hotword detection. 3 | * 4 | * Copyright 2021-2023 Miðeind ehf. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | // Example application demonstrating use of the Flutter Snowboy plugin. 21 | 22 | import 'dart:async'; 23 | import 'dart:io'; 24 | 25 | import 'package:flutter/material.dart'; 26 | import 'package:flutter/services.dart'; 27 | 28 | import 'package:audiofileplayer/audiofileplayer.dart'; 29 | import 'package:path_provider/path_provider.dart'; 30 | import 'package:audio_session/audio_session.dart'; 31 | import 'package:flutter_sound/flutter_sound.dart'; 32 | 33 | import 'package:flutter_snowboy/flutter_snowboy.dart'; 34 | 35 | const kSampleRate = 16000; 36 | const kNumChannels = 1; 37 | 38 | void main() { 39 | runApp(SnowboyExampleApp()); 40 | } 41 | 42 | class SnowboyExampleApp extends StatefulWidget { 43 | @override 44 | _SnowboyExampleAppState createState() => _SnowboyExampleAppState(); 45 | } 46 | 47 | class _SnowboyExampleAppState extends State { 48 | bool running = false; 49 | int numDetected = 0; 50 | String status = "Snowboy is not running"; 51 | String buttonTitle = 'Start detection'; 52 | 53 | late Snowboy detector; 54 | 55 | FlutterSoundRecorder _micRecorder = FlutterSoundRecorder(); 56 | StreamController? _recordingDataController; 57 | StreamSubscription? _recordingDataSubscription; 58 | 59 | @override 60 | void initState() { 61 | super.initState(); 62 | initPlatformState(); 63 | } 64 | 65 | // Platform messages are asynchronous, so we initialize in an async method. 66 | Future initPlatformState() async { 67 | final String modelPath = await copyModelToFilesystem("hi_embla.pmdl"); 68 | // Create detector object and prepare it 69 | detector = Snowboy(); 70 | await detector.prepare(modelPath); 71 | detector.hotwordHandler = hotwordHandler; 72 | await configureAudioSession(); 73 | } 74 | 75 | Future configureAudioSession() async { 76 | final session = await AudioSession.instance; 77 | await session.configure(AudioSessionConfiguration( 78 | avAudioSessionCategory: AVAudioSessionCategory.playAndRecord, 79 | avAudioSessionCategoryOptions: 80 | AVAudioSessionCategoryOptions.defaultToSpeaker | 81 | AVAudioSessionCategoryOptions.allowBluetooth, 82 | // AVAudioSessionCategoryOptions.duckOthers, 83 | // avAudioSessionMode: AVAudioSessionMode.spokenAudio, 84 | avAudioSessionMode: AVAudioSessionMode.defaultMode, 85 | avAudioSessionRouteSharingPolicy: 86 | AVAudioSessionRouteSharingPolicy.defaultPolicy, 87 | avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none, 88 | androidAudioAttributes: const AndroidAudioAttributes( 89 | contentType: AndroidAudioContentType.speech, 90 | flags: AndroidAudioFlags.none, 91 | usage: AndroidAudioUsage.voiceCommunication, 92 | ), 93 | androidAudioFocusGainType: AndroidAudioFocusGainType.gain, 94 | androidWillPauseWhenDucked: true, 95 | )); 96 | await session.setActive(true); 97 | } 98 | 99 | // Copy model from asset bundle to temp directory on the filesystem 100 | static Future copyModelToFilesystem(String filename) async { 101 | final String dir = (await getTemporaryDirectory()).path; 102 | final String finalPath = "$dir/$filename"; 103 | if (await File(finalPath).exists() == true) { 104 | // Don't overwrite existing file 105 | return finalPath; 106 | } 107 | ByteData bytes = await rootBundle.load("assets/$filename"); 108 | final buffer = bytes.buffer; 109 | await File(finalPath).writeAsBytes( 110 | buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes)); 111 | return finalPath; 112 | } 113 | 114 | // Function to invoke when hotword is detected 115 | void hotwordHandler() { 116 | // Increment counter 117 | setState(() { 118 | numDetected += 1; 119 | }); 120 | // Play sound 121 | Audio.load('assets/ding.wav') 122 | ..play() 123 | ..dispose(); 124 | } 125 | 126 | Future startDetection() async { 127 | // Prep recording session 128 | await _micRecorder.openRecorder(); 129 | 130 | // Create recording stream 131 | _recordingDataController = StreamController(); 132 | _recordingDataSubscription = 133 | _recordingDataController?.stream.listen((buffer) { 134 | // When we get data, feed it into Snowboy detector 135 | if (buffer is FoodData) { 136 | Uint8List copy = new Uint8List.fromList(buffer.data!); 137 | // print("Got audio data (${buffer.data.lengthInBytes} bytes"); 138 | detector.detect(copy); 139 | } 140 | }); 141 | 142 | // Start recording 143 | await _micRecorder.startRecorder( 144 | toStream: _recordingDataController!.sink as StreamSink, 145 | codec: Codec.pcm16, 146 | numChannels: kNumChannels, 147 | sampleRate: kSampleRate); 148 | } 149 | 150 | Future stopDetection() async { 151 | await _micRecorder.stopRecorder(); 152 | await _micRecorder.closeRecorder(); 153 | await _recordingDataSubscription?.cancel(); 154 | await _recordingDataController?.close(); 155 | } 156 | 157 | void toggleHotwordDetection() async { 158 | String s; 159 | String t; 160 | bool r; 161 | 162 | if (running == false) { 163 | await startDetection(); 164 | s = "Snowboy is running\nSay 'Hi Embla' to trigger hotword handler."; 165 | t = "Stop detection"; 166 | r = true; 167 | } else { 168 | await stopDetection(); 169 | s = "Snowboy is not running"; 170 | t = "Start detection"; 171 | r = false; 172 | } 173 | setState(() { 174 | status = s; 175 | running = r; 176 | buttonTitle = t; 177 | }); 178 | } 179 | 180 | @override 181 | Widget build(BuildContext context) { 182 | return MaterialApp( 183 | home: Scaffold( 184 | appBar: AppBar( 185 | title: const Text('Flutter Snowboy example'), 186 | ), 187 | body: Center( 188 | child: Column(children: [ 189 | Text("\n"), 190 | MaterialButton( 191 | minWidth: double.infinity, 192 | child: Text(buttonTitle, 193 | style: TextStyle( 194 | fontSize: 30.0, 195 | )), 196 | onPressed: toggleHotwordDetection, 197 | ), 198 | Text("\n" + status, 199 | textAlign: TextAlign.center, 200 | style: TextStyle( 201 | fontSize: 20.0, 202 | )), 203 | Text('\nHotword heard $numDetected times', 204 | textAlign: TextAlign.center, 205 | style: TextStyle( 206 | fontSize: 20.0, 207 | )), 208 | ]), 209 | ), 210 | ), 211 | ); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_snowboy_example 2 | description: Demonstrates how to use the flutter_snowboy plugin. 3 | version: 0.1.2+1 4 | 5 | # The following line prevents the package from being accidentally published to 6 | # pub.dev using `pub publish`. This is preferred for private packages. 7 | publish_to: 'none' 8 | 9 | environment: 10 | sdk: '>=2.12.0 <4.0.0' 11 | 12 | dependencies: 13 | flutter: 14 | sdk: flutter 15 | 16 | audiofileplayer: '^2.1.1' 17 | path_provider: '^2.0.15' 18 | audio_session: '^0.1.14' 19 | flutter_sound: '^9.2.13' 20 | 21 | flutter_snowboy: 22 | # When depending on this package from a real application you should use: 23 | # flutter_snowboy: ^x.y.z 24 | # See https://dart.dev/tools/pub/dependencies#version-constraints 25 | # The example app is bundled with the plugin so we use a path dependency on 26 | # the parent directory to use the current plugin's version. 27 | path: ../ 28 | 29 | dev_dependencies: 30 | flutter_test: 31 | sdk: flutter 32 | 33 | # The following section is specific to Flutter. 34 | flutter: 35 | uses-material-design: true 36 | assets: 37 | - assets/hi_embla.pmdl 38 | - assets/ding.wav 39 | -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | // import 'package:flutter/material.dart'; 9 | // import 'package:flutter_test/flutter_test.dart'; 10 | 11 | // import 'package:flutter_snowboy_example/main.dart'; 12 | 13 | void main() {} 14 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | /Flutter/flutter_export_environment.sh -------------------------------------------------------------------------------- /ios/Assets/Snowboy/common.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/ios/Assets/Snowboy/common.res -------------------------------------------------------------------------------- /ios/Classes/FlutterSnowboyPlugin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2023 Miðeind ehf. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #import 19 | 20 | @interface FlutterSnowboyPlugin : NSObject 21 | @end 22 | -------------------------------------------------------------------------------- /ios/Classes/FlutterSnowboyPlugin.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2023 Miðeind ehf. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #import "FlutterSnowboyPlugin.h" 19 | #import "SnowboyDetector.h" 20 | 21 | // Snowboy configuration defaults 22 | #define SNOWBOY_DEFAULT_SENSITIVITY 0.5 23 | #define SNOWBOY_DEFAULT_AUDIO_GAIN 1.0 24 | // Should be false for pmdl, true for umdl 25 | #define SNOWBOY_DEFAULT_APPLY_FRONTEND FALSE 26 | 27 | @interface FlutterSnowboyPlugin () 28 | @property(nonatomic, retain) FlutterMethodChannel *channel; 29 | @end 30 | 31 | @implementation FlutterSnowboyPlugin 32 | 33 | + (void)registerWithRegistrar:(NSObject *)registrar { 34 | // Create a channel to communicate with the Flutter app 35 | FlutterMethodChannel *channel = 36 | [FlutterMethodChannel methodChannelWithName:@"plugin_snowboy" 37 | binaryMessenger:[registrar messenger]]; 38 | // Create an instance of the plugin and register it with the channel 39 | FlutterSnowboyPlugin *instance = [FlutterSnowboyPlugin new]; 40 | instance.channel = channel; 41 | [registrar addMethodCallDelegate:instance channel:channel]; 42 | } 43 | 44 | - (void)handleMethodCall:(FlutterMethodCall *)call 45 | result:(FlutterResult)result { 46 | // Method call handler for Flutter channel 47 | if ([call.method isEqualToString:@"prepareSnowboy"]) { 48 | result([NSNumber numberWithBool:[self prepareSnowboy:call result:result]]); 49 | } else if ([call.method isEqualToString:@"detectSnowboy"]) { 50 | [self detectSnowboy:call result:result]; 51 | } else if ([call.method isEqualToString:@"purgeSnowboy"]) { 52 | [self purgeSnowboy:call result:result]; 53 | } else { 54 | result(FlutterMethodNotImplemented); 55 | } 56 | } 57 | 58 | - (BOOL)prepareSnowboy:(FlutterMethodCall *)call result:(FlutterResult)result { 59 | 60 | // First, validate all arguments 61 | 62 | // Model path 63 | NSString *modelPath = [call.arguments objectAtIndex:0]; 64 | if ([[NSFileManager defaultManager] fileExistsAtPath:modelPath] == FALSE) { 65 | NSLog(@"No Snowboy model found at path %@", modelPath); 66 | return FALSE; 67 | } 68 | 69 | // Sensitivity 70 | NSNumber *sensitivity = [call.arguments objectAtIndex:1]; 71 | if (sensitivity == nil) { 72 | sensitivity = [NSNumber numberWithDouble:SNOWBOY_DEFAULT_SENSITIVITY]; 73 | } 74 | 75 | // Audio gain 76 | NSNumber *audioGain = [call.arguments objectAtIndex:2]; 77 | if (audioGain == nil) { 78 | audioGain = [NSNumber numberWithDouble:SNOWBOY_DEFAULT_AUDIO_GAIN]; 79 | } 80 | 81 | // Frontend processing (should only be enabled for umdl models) 82 | NSNumber *applyFrontend = [call.arguments objectAtIndex:3]; 83 | if (applyFrontend == nil) { 84 | audioGain = [NSNumber numberWithBool:SNOWBOY_DEFAULT_APPLY_FRONTEND]; 85 | } 86 | 87 | // Initialize detector instance 88 | return [[SnowboyDetector sharedInstance] prepare:modelPath 89 | sensitivity:[sensitivity doubleValue] 90 | audioGain:[audioGain doubleValue] 91 | applyFrontend:[applyFrontend boolValue]]; 92 | } 93 | 94 | - (void)detectSnowboy:(FlutterMethodCall *)call result:(FlutterResult)result { 95 | // Make sure detector is initialized 96 | if ([[SnowboyDetector sharedInstance] inited] == FALSE) { 97 | NSLog(@"Attempt to run detector on data prior to initialization!"); 98 | return; 99 | } 100 | 101 | // Pass audio data to SnowboyDetector instance 102 | NSArray *args = call.arguments; 103 | FlutterStandardTypedData *typedData = [args objectAtIndex:0]; 104 | NSData *audioData = [typedData data]; 105 | [[SnowboyDetector sharedInstance] detect:audioData channel:self.channel]; 106 | } 107 | 108 | - (void)purgeSnowboy:(FlutterMethodCall *)call result:(FlutterResult)result { 109 | // Release all resources used by detector 110 | [[SnowboyDetector sharedInstance] purge]; 111 | } 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /ios/Classes/SnowboyDetector.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2023 Miðeind ehf. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #import 19 | #import 20 | 21 | typedef void (^SnowboyDetectorBlock)(void); 22 | 23 | @interface SnowboyDetector : NSObject 24 | 25 | + (instancetype)sharedInstance; 26 | - (BOOL)prepare:(NSString *)modelPath 27 | sensitivity:(double)sensitivity 28 | audioGain:(double)audioGain 29 | applyFrontend:(BOOL)applyFrontend; 30 | - (void)detect:(NSData *)audioData channel:(FlutterMethodChannel *)channel; 31 | - (void)purge; 32 | - (BOOL)inited; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ios/Classes/SnowboyDetector.mm: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2023 Miðeind ehf. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | // This is an Objective-C++ wrapper around the Snowboy C++ detector. 19 | 20 | #import "SnowboyDetector.h" 21 | #import 22 | #import 23 | 24 | @interface SnowboyDetector () { 25 | snowboy::SnowboyDetect *_snowboyDetect; 26 | } 27 | @end 28 | 29 | @implementation SnowboyDetector 30 | 31 | // Singleton instance 32 | + (instancetype)sharedInstance { 33 | static SnowboyDetector *instance = nil; 34 | if (!instance) { 35 | instance = [self new]; 36 | } 37 | return instance; 38 | } 39 | 40 | // Initialize the Snowboy detector with the given model 41 | // file and other configuration parameters. 42 | - (BOOL)prepare:(NSString *)modelPath 43 | sensitivity:(double)sensitivity 44 | audioGain:(double)audioGain 45 | applyFrontend:(BOOL)applyFrontend { 46 | 47 | _snowboyDetect = NULL; 48 | 49 | NSString *commonPath = [[NSBundle mainBundle] pathForResource:@"common" 50 | ofType:@"res"]; 51 | if (![[NSFileManager defaultManager] fileExistsAtPath:commonPath]) { 52 | NSLog( 53 | @"Unable to init Snowboy, required bundled file 'common.res' missing"); 54 | return FALSE; 55 | } 56 | if (![[NSFileManager defaultManager] fileExistsAtPath:modelPath]) { 57 | NSLog(@"Unable to init Snowboy, no file at model path %@", modelPath); 58 | return FALSE; 59 | } 60 | 61 | // Create and configure Snowboy C++ detector object 62 | _snowboyDetect = 63 | new snowboy::SnowboyDetect(std::string([commonPath UTF8String]), 64 | std::string([modelPath UTF8String])); 65 | NSString *ssString = [NSString stringWithFormat:@"%f", sensitivity]; 66 | _snowboyDetect->SetSensitivity( 67 | [ssString cStringUsingEncoding:NSUTF8StringEncoding]); 68 | _snowboyDetect->SetAudioGain(audioGain); 69 | _snowboyDetect->ApplyFrontend(applyFrontend); 70 | 71 | return TRUE; 72 | } 73 | 74 | // Run the Snowboy detector on the given audio data 75 | - (void)detect:(NSData *)audioData channel:(FlutterMethodChannel *)channel { 76 | const int16_t *bytes = (int16_t *)[audioData bytes]; 77 | const int len = (int)[audioData length] / 2; // 16-bit audio 78 | int result = _snowboyDetect->RunDetection((const int16_t *)bytes, len); 79 | dispatch_async(dispatch_get_main_queue(), ^{ 80 | if (result == 1) { 81 | [channel invokeMethod:@"hotword" arguments:nil]; 82 | } 83 | }); 84 | } 85 | 86 | // Release the Snowboy detector 87 | - (void)purge { 88 | if (_snowboyDetect != NULL) { 89 | delete _snowboyDetect; 90 | _snowboyDetect = NULL; 91 | } 92 | } 93 | 94 | // Returns true if the Snowboy detector has been initialized 95 | - (BOOL)inited { 96 | return (_snowboyDetect != NULL); 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /ios/Snowboy.framework/Headers/Snowboy.h: -------------------------------------------------------------------------------- 1 | // include/snowboy-detect.h 2 | 3 | // Copyright 2016 KITT.AI (author: Guoguo Chen) 4 | 5 | #ifndef SNOWBOY_INCLUDE_SNOWBOY_DETECT_H_ 6 | #define SNOWBOY_INCLUDE_SNOWBOY_DETECT_H_ 7 | 8 | #include 9 | #include 10 | 11 | namespace snowboy { 12 | 13 | // Forward declaration. 14 | struct WaveHeader; 15 | class PipelineDetect; 16 | 17 | //////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // SnowboyDetect class interface. 20 | // 21 | //////////////////////////////////////////////////////////////////////////////// 22 | class SnowboyDetect { 23 | public: 24 | // Constructor that takes a resource file, and a list of hotword models which 25 | // are separated by comma. In the case that more than one hotword exist in the 26 | // provided models, RunDetection() will return the index of the hotword, if 27 | // the corresponding hotword is triggered. 28 | // 29 | // CAVEAT: a personal model only contain one hotword, but an universal model 30 | // may contain multiple hotwords. It is your responsibility to figure 31 | // out the index of the hotword. For example, if your model string is 32 | // "foo.pmdl,bar.umdl", where foo.pmdl contains hotword x, bar.umdl 33 | // has two hotwords y and z, the indices of different hotwords are as 34 | // follows: 35 | // x 1 36 | // y 2 37 | // z 3 38 | // 39 | // @param [in] resource_filename Filename of resource file. 40 | // @param [in] model_str A string of multiple hotword models, 41 | // separated by comma. 42 | SnowboyDetect(const std::string& resource_filename, 43 | const std::string& model_str); 44 | 45 | // Resets the detection. This class handles voice activity detection (VAD) 46 | // internally. But if you have an external VAD, you should call Reset() 47 | // whenever you see segment end from your VAD. 48 | bool Reset(); 49 | 50 | // Runs hotword detection. Supported audio format is WAVE (with linear PCM, 51 | // 8-bits unsigned integer, 16-bits signed integer or 32-bits signed integer). 52 | // See SampleRate(), NumChannels() and BitsPerSample() for the required 53 | // sampling rate, number of channels and bits per sample values. You are 54 | // supposed to provide a small chunk of data (e.g., 0.1 second) each time you 55 | // call RunDetection(). Larger chunk usually leads to longer delay, but less 56 | // CPU usage. 57 | // 58 | // Definition of return values: 59 | // -2: Silence. 60 | // -1: Error. 61 | // 0: No event. 62 | // 1: Hotword 1 triggered. 63 | // 2: Hotword 2 triggered. 64 | // ... 65 | // 66 | // @param [in] data Small chunk of data to be detected. See 67 | // above for the supported data format. 68 | int RunDetection(const std::string& data); 69 | 70 | // Various versions of RunDetection() that take different format of audio. If 71 | // NumChannels() > 1, e.g., NumChannels() == 2, then the array is as follows: 72 | // 73 | // d1c1, d1c2, d2c1, d2c2, d3c1, d3c2, ..., dNc1, dNc2 74 | // 75 | // where d1c1 means data point 1 of channel 1. 76 | // 77 | // @param [in] data Small chunk of data to be detected. See 78 | // above for the supported data format. 79 | // @param [in] array_length Length of the data array. 80 | int RunDetection(const float* const data, const int array_length); 81 | int RunDetection(const int16_t* const data, const int array_length); 82 | int RunDetection(const int32_t* const data, const int array_length); 83 | 84 | // Sets the sensitivity string for the loaded hotwords. A is 85 | // a list of floating numbers between 0 and 1, and separated by comma. For 86 | // example, if there are 3 loaded hotwords, your string should looks something 87 | // like this: 88 | // 0.4,0.5,0.8 89 | // Make sure you properly align the sensitivity value to the corresponding 90 | // hotword. 91 | void SetSensitivity(const std::string& sensitivity_str); 92 | 93 | // Returns the sensitivity string for the current hotwords. 94 | std::string GetSensitivity() const; 95 | 96 | // Applied a fixed gain to the input audio. In case you have a very weak 97 | // microphone, you can use this function to boost input audio level. 98 | void SetAudioGain(const float audio_gain); 99 | 100 | // Writes the models to the model filenames specified in in the 101 | // constructor. This overwrites the original model with the latest parameter 102 | // setting. You are supposed to call this function if you have updated the 103 | // hotword sensitivities through SetSensitivity(), and you would like to store 104 | // those values in the model as the default value. 105 | void UpdateModel() const; 106 | 107 | // Returns the number of the loaded hotwords. This helps you to figure the 108 | // index of the hotwords. 109 | int NumHotwords() const; 110 | 111 | // If is true, then apply frontend audio processing; 112 | // otherwise turns the audio processing off. 113 | void ApplyFrontend(const bool apply_frontend); 114 | 115 | // Returns the required sampling rate, number of channels and bits per sample 116 | // values for the audio data. You should use this information to set up your 117 | // audio capturing interface. 118 | int SampleRate() const; 119 | int NumChannels() const; 120 | int BitsPerSample() const; 121 | 122 | ~SnowboyDetect(); 123 | 124 | private: 125 | std::unique_ptr wave_header_; 126 | std::unique_ptr detect_pipeline_; 127 | }; 128 | 129 | } // namespace snowboy 130 | 131 | #endif // SNOWBOY_INCLUDE_SNOWBOY_DETECT_H_ 132 | -------------------------------------------------------------------------------- /ios/Snowboy.framework/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/ios/Snowboy.framework/Info.plist -------------------------------------------------------------------------------- /ios/Snowboy.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module Snowboy { 2 | umbrella header "Snowboy.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /ios/Snowboy.framework/Snowboy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mideind/FlutterSnowboy/0289edded4207ed37be2c7bdb219a0500b143ce8/ios/Snowboy.framework/Snowboy -------------------------------------------------------------------------------- /ios/flutter_snowboy.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html. 3 | # Run `pod lib lint flutter_snowboy.podspec` to validate before publishing. 4 | # 5 | Pod::Spec.new do |s| 6 | s.name = 'flutter_snowboy' 7 | s.version = '0.1.2' 8 | s.summary = 'Flutter Snowboy plugin.' 9 | s.description = 'Flutter plugin for Snowboy DNN-based hotword detection.' 10 | s.homepage = 'https://github.com/mideind/flutter_snowboy' 11 | s.author = { "Miðeind" => "mideind@mideind.is" } 12 | s.license = { :type => 'Apache 2', :file => '../LICENSE' } 13 | s.source = { :path => '.' } 14 | s.source_files = ['Classes/**/*.h', 'Classes/**/*.m', 'Classes/**/*.mm'] 15 | s.public_header_files = ['Classes/**/*.h'] 16 | s.vendored_frameworks = 'Snowboy.framework' 17 | s.resources = 'Assets/**/*' 18 | s.dependency 'Flutter' 19 | s.platform = :ios, '12.0' 20 | s.framework = 'Accelerate' 21 | s.requires_arc = true 22 | # Compile source files as Objective-C++ 23 | s.xcconfig = { 24 | 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11', 25 | 'CLANG_CXX_LIBRARY' => 'libc++', 26 | 'GCC_INPUT_FILETYPE' => 'sourcecode.cpp.objcpp', 27 | } 28 | # Flutter.framework does not contain an i386 slice. 29 | s.pod_target_xcconfig = { 30 | 'DEFINES_MODULE' => 'YES', 31 | 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' 32 | } 33 | end 34 | -------------------------------------------------------------------------------- /lib/flutter_snowboy.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * flutter_snowboy - Flutter package wrapper for Snowboy hotword detection. 3 | * 4 | * Copyright (C) 2021-2023 Miðeind ehf. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | library flutter_snowboy; 21 | 22 | import 'dart:async'; 23 | 24 | import 'package:flutter/services.dart'; 25 | 26 | const kDefaultSensitivity = 0.5; 27 | const kDefaultAudioGain = 1.0; 28 | 29 | class Snowboy { 30 | MethodChannel _channel = const MethodChannel('plugin_snowboy'); 31 | Function? hotwordHandler; 32 | 33 | /// Constructor 34 | Snowboy() { 35 | // Register handler to receive messages from the native plugin. 36 | _channel.setMethodCallHandler(channelMethodCallHandler); 37 | } 38 | 39 | /// Handle messages from the native plugin. 40 | Future channelMethodCallHandler(MethodCall methodCall) async { 41 | switch (methodCall.method) { 42 | case 'hotword': 43 | if (hotwordHandler != null) { 44 | hotwordHandler!(); 45 | } 46 | break; 47 | default: 48 | throw MissingPluginException('notImplemented'); 49 | } 50 | } 51 | 52 | void _err(String methodName, String msg) { 53 | print("Error invoking Snowboy '$methodName' method: $msg"); 54 | } 55 | 56 | /// Instantiate Snowboy in the native plugin code, load 57 | /// provided model and other resources, w. configuration. 58 | Future prepare(String modelPath, 59 | {double sensitivity = kDefaultSensitivity, 60 | double audioGain = kDefaultAudioGain, 61 | bool applyFrontend = false}) async { 62 | try { 63 | final bool success = await _channel.invokeMethod( 64 | 'prepareSnowboy', [modelPath, sensitivity, audioGain, applyFrontend]); 65 | return success; 66 | } on PlatformException catch (e) { 67 | _err("prepareSnowboy", e.toString()); 68 | return false; 69 | } 70 | } 71 | 72 | /// Detect hotword in the provided audio data. 73 | Future detect(Uint8List data) async { 74 | try { 75 | await _channel.invokeMethod('detectSnowboy', [data]); 76 | } on PlatformException catch (e) { 77 | _err("detectSnowboy", e.toString()); 78 | } 79 | } 80 | 81 | /// Dispose of all resources. 82 | Future purge() async { 83 | try { 84 | await _channel.invokeMethod('purgeSnowboy'); 85 | } on PlatformException catch (e) { 86 | _err("purgeSnowboy", e.toString()); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_snowboy 2 | description: Flutter wrapper plugin for Snowboy, a cross-platform DNN-based hotword detection toolkit developed by KITT.AI. 3 | version: 0.1.2+1 4 | homepage: https://github.com/mideind/flutter_snowboy 5 | 6 | environment: 7 | sdk: '>=2.12.0 <4.0.0' 8 | flutter: ">=2.17.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | test: ">=1.20.0" 18 | 19 | flutter: 20 | plugin: 21 | platforms: 22 | android: 23 | package: is.mideind.flutter_snowboy 24 | pluginClass: FlutterSnowboyPlugin 25 | ios: 26 | pluginClass: FlutterSnowboyPlugin 27 | -------------------------------------------------------------------------------- /test/flutter_snowboy_test.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * flutter_snowboy - Flutter package wrapper for Snowboy hotword detection. 3 | * 4 | * Copyright (C) 2021-2023 Miðeind ehf. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | import 'package:flutter_test/flutter_test.dart'; 21 | 22 | import 'package:flutter_snowboy/flutter_snowboy.dart'; 23 | 24 | void main() { 25 | TestWidgetsFlutterBinding.ensureInitialized(); 26 | 27 | // Tests 28 | test('Instantiation', () { 29 | var s = Snowboy(); 30 | expect(s, s); 31 | }); 32 | } 33 | --------------------------------------------------------------------------------