Committed by
GitHub
Add Flutter GUI example for VAD with a microphone. (#905)
正在显示
44 个修改的文件
包含
2289 行增加
和
115 行删除
.github/workflows/flutter-linux.yaml
0 → 100644
| 1 | +name: flutter-linux | ||
| 2 | + | ||
| 3 | +on: | ||
| 4 | + push: | ||
| 5 | + branches: | ||
| 6 | + - flutter | ||
| 7 | + tags: | ||
| 8 | + - '*' | ||
| 9 | + paths: | ||
| 10 | + - '.github/workflows/flutter-linux.yaml' | ||
| 11 | + - 'CMakeLists.txt' | ||
| 12 | + - 'cmake/**' | ||
| 13 | + - 'sherpa-onnx/csrc/*' | ||
| 14 | + - 'sherpa-onnx/c-api/*' | ||
| 15 | + - 'sherpa-onnx/flutter/**' | ||
| 16 | + pull_request: | ||
| 17 | + branches: | ||
| 18 | + - master | ||
| 19 | + paths: | ||
| 20 | + - '.github/workflows/flutter-linux.yaml' | ||
| 21 | + - 'CMakeLists.txt' | ||
| 22 | + - 'cmake/**' | ||
| 23 | + - 'sherpa-onnx/csrc/*' | ||
| 24 | + - 'sherpa-onnx/c-api/*' | ||
| 25 | + - 'sherpa-onnx/flutter/**' | ||
| 26 | + | ||
| 27 | + workflow_dispatch: | ||
| 28 | + | ||
| 29 | +concurrency: | ||
| 30 | + group: flutter-linux-${{ github.ref }} | ||
| 31 | + cancel-in-progress: true | ||
| 32 | + | ||
| 33 | +jobs: | ||
| 34 | + flutter_linux: | ||
| 35 | + name: linux | ||
| 36 | + runs-on: ${{ matrix.os }} | ||
| 37 | + container: ubuntu:18.04 | ||
| 38 | + strategy: | ||
| 39 | + fail-fast: false | ||
| 40 | + matrix: | ||
| 41 | + os: [ubuntu-latest] | ||
| 42 | + | ||
| 43 | + steps: | ||
| 44 | + - uses: actions/checkout@v2 | ||
| 45 | + with: | ||
| 46 | + fetch-depth: 0 | ||
| 47 | + | ||
| 48 | + - name: Install deps | ||
| 49 | + shell: bash | ||
| 50 | + run: | | ||
| 51 | + apt-get update -y | ||
| 52 | + apt-get install -y build-essential jq git cmake | ||
| 53 | + apt-get install -y curl | ||
| 54 | + | ||
| 55 | + - name: Setup Flutter SDK | ||
| 56 | + uses: flutter-actions/setup-flutter@v3 | ||
| 57 | + with: | ||
| 58 | + channel: stable | ||
| 59 | + version: latest | ||
| 60 | + | ||
| 61 | + - name: Install ninja | ||
| 62 | + shell: bash | ||
| 63 | + run: | | ||
| 64 | + apt-get install -y ninja-build | ||
| 65 | + | ||
| 66 | + - name: Display ninja version | ||
| 67 | + shell: bash | ||
| 68 | + run: | | ||
| 69 | + ninja --version | ||
| 70 | + ninja --help || true | ||
| 71 | + which ninja | ||
| 72 | + | ||
| 73 | + - name: Display PWD | ||
| 74 | + shell: bash | ||
| 75 | + run: | | ||
| 76 | + echo "pwd: $PWD" | ||
| 77 | + ls -lh | ||
| 78 | + | ||
| 79 | + - name: Display machine info | ||
| 80 | + shell: bash | ||
| 81 | + run: | | ||
| 82 | + uname -a | ||
| 83 | + | ||
| 84 | + - name: Display flutter info | ||
| 85 | + shell: bash | ||
| 86 | + run: | | ||
| 87 | + which flutter | ||
| 88 | + which dart | ||
| 89 | + | ||
| 90 | + flutter --version | ||
| 91 | + | ||
| 92 | + mkdir -p /__t/flutter-Linux-3.22.1-X64/flutter | ||
| 93 | + | ||
| 94 | + git config --global --add safe.directory /__t/flutter-Linux-3.22.1-X64/flutter | ||
| 95 | + | ||
| 96 | + flutter --version | ||
| 97 | + | ||
| 98 | + dart --version | ||
| 99 | + flutter doctor | ||
| 100 | + | ||
| 101 | + | ||
| 102 | + flutter doctor | ||
| 103 | + | ||
| 104 | + - name: Install libgtk-3-dev | ||
| 105 | + shell: bash | ||
| 106 | + run: | | ||
| 107 | + apt install -y libgtk-3-dev tree clang pkg-config | ||
| 108 | + | ||
| 109 | + - name: Display flutter info (2) | ||
| 110 | + shell: bash | ||
| 111 | + run: | | ||
| 112 | + which flutter | ||
| 113 | + which dart | ||
| 114 | + | ||
| 115 | + flutter --version | ||
| 116 | + dart --version | ||
| 117 | + flutter doctor | ||
| 118 | + | ||
| 119 | + - name: Build sherpa-onnx | ||
| 120 | + uses: addnab/docker-run-action@v3 | ||
| 121 | + with: | ||
| 122 | + image: quay.io/pypa/manylinux2014_x86_64 | ||
| 123 | + options: | | ||
| 124 | + --volume ${{ github.workspace }}/:/home/runner/work/sherpa-onnx/sherpa-onnx | ||
| 125 | + shell: bash | ||
| 126 | + run: | | ||
| 127 | + uname -a | ||
| 128 | + gcc --version | ||
| 129 | + cmake --version | ||
| 130 | + cat /etc/*release | ||
| 131 | + id | ||
| 132 | + pwd | ||
| 133 | + | ||
| 134 | + cd /home/runner/work/sherpa-onnx/sherpa-onnx | ||
| 135 | + | ||
| 136 | + mkdir build | ||
| 137 | + cd build | ||
| 138 | + | ||
| 139 | + cmake \ | ||
| 140 | + -D BUILD_SHARED_LIBS=ON \ | ||
| 141 | + -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \ | ||
| 142 | + -DSHERPA_ONNX_ENABLE_WEBSOCKET=OFF \ | ||
| 143 | + -DBUILD_ESPEAK_NG_EXE=OFF \ | ||
| 144 | + -DSHERPA_ONNX_ENABLE_BINARY=OFF \ | ||
| 145 | + -DCMAKE_INSTALL_PREFIX=./install \ | ||
| 146 | + .. | ||
| 147 | + | ||
| 148 | + make -j2 | ||
| 149 | + make install | ||
| 150 | + | ||
| 151 | + - name: Copy libs | ||
| 152 | + shell: bash | ||
| 153 | + run: | | ||
| 154 | + cp -v build/install/lib/lib* ./sherpa-onnx/flutter/linux/ | ||
| 155 | + | ||
| 156 | + echo "--------------------" | ||
| 157 | + | ||
| 158 | + ls -lh ./sherpa-onnx/flutter/linux/ | ||
| 159 | + | ||
| 160 | + - name: Download model files | ||
| 161 | + shell: bash | ||
| 162 | + run: | | ||
| 163 | + cd sherpa-onnx/flutter | ||
| 164 | + cd example/assets | ||
| 165 | + | ||
| 166 | + curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/silero_vad.onnx | ||
| 167 | + | ||
| 168 | + - name: Build flutter | ||
| 169 | + shell: bash | ||
| 170 | + run: | | ||
| 171 | + | ||
| 172 | + d=$PWD | ||
| 173 | + | ||
| 174 | + pushd sherpa-onnx/flutter | ||
| 175 | + dart pub get | ||
| 176 | + | ||
| 177 | + cd example | ||
| 178 | + flutter build linux | ||
| 179 | + | ||
| 180 | + ls -lh build/linux/x64/release/bundle/sherpa_onnx | ||
| 181 | + file build/linux/x64/release/bundle/sherpa_onnx | ||
| 182 | + | ||
| 183 | + tree build/linux/x64/release/bundle/ | ||
| 184 | + cd build/linux/x64/release/ | ||
| 185 | + | ||
| 186 | + dst=flutter_sherpa_onnx_linux_x64 | ||
| 187 | + mv bundle $dst | ||
| 188 | + | ||
| 189 | + pushd $dst/lib | ||
| 190 | + | ||
| 191 | + ls -lh | ||
| 192 | + mv -v libonnxruntime.so libonnxruntime.so.1.17.1 | ||
| 193 | + mv -v libpiper_phonemize.so libpiper_phonemize.so.1 | ||
| 194 | + popd | ||
| 195 | + | ||
| 196 | + tar cjfv $dst.tar.bz2 $dst | ||
| 197 | + ls -lh | ||
| 198 | + mv $dst.tar.bz2 $d | ||
| 199 | + popd | ||
| 200 | + | ||
| 201 | + ls -lh $dst.tar.bz2 | ||
| 202 | + | ||
| 203 | + - uses: actions/upload-artifact@v2 | ||
| 204 | + with: | ||
| 205 | + name: flutter-sherpa-onnx-linux-x64 | ||
| 206 | + path: ./*.tar.bz2 |
| 1 | -name: flutter | 1 | +name: flutter-macos |
| 2 | 2 | ||
| 3 | on: | 3 | on: |
| 4 | push: | 4 | push: |
| 5 | branches: | 5 | branches: |
| 6 | - flutter | 6 | - flutter |
| 7 | - - flutter-sid-2 | ||
| 8 | tags: | 7 | tags: |
| 9 | - '*' | 8 | - '*' |
| 10 | paths: | 9 | paths: |
| 11 | - - '.github/workflows/flutter.yaml' | 10 | + - '.github/workflows/flutter-macos.yaml' |
| 12 | - 'CMakeLists.txt' | 11 | - 'CMakeLists.txt' |
| 13 | - 'cmake/**' | 12 | - 'cmake/**' |
| 14 | - 'sherpa-onnx/csrc/*' | 13 | - 'sherpa-onnx/csrc/*' |
| @@ -18,7 +17,7 @@ on: | @@ -18,7 +17,7 @@ on: | ||
| 18 | branches: | 17 | branches: |
| 19 | - master | 18 | - master |
| 20 | paths: | 19 | paths: |
| 21 | - - '.github/workflows/flutter.yaml' | 20 | + - '.github/workflows/flutter-macos.yaml' |
| 22 | - 'CMakeLists.txt' | 21 | - 'CMakeLists.txt' |
| 23 | - 'cmake/**' | 22 | - 'cmake/**' |
| 24 | - 'sherpa-onnx/csrc/*' | 23 | - 'sherpa-onnx/csrc/*' |
| @@ -28,17 +27,18 @@ on: | @@ -28,17 +27,18 @@ on: | ||
| 28 | workflow_dispatch: | 27 | workflow_dispatch: |
| 29 | 28 | ||
| 30 | concurrency: | 29 | concurrency: |
| 31 | - group: flutter-${{ github.ref }} | 30 | + group: flutter-macos-${{ github.ref }} |
| 32 | cancel-in-progress: true | 31 | cancel-in-progress: true |
| 33 | 32 | ||
| 34 | jobs: | 33 | jobs: |
| 35 | - flutter: | ||
| 36 | - name: flutter | 34 | + flutter_macos: |
| 35 | + name: macos ${{ matrix.arch }} | ||
| 37 | runs-on: ${{ matrix.os }} | 36 | runs-on: ${{ matrix.os }} |
| 38 | strategy: | 37 | strategy: |
| 39 | fail-fast: false | 38 | fail-fast: false |
| 40 | matrix: | 39 | matrix: |
| 41 | os: [macos-latest] | 40 | os: [macos-latest] |
| 41 | + arch: [x86_64, arm64] | ||
| 42 | 42 | ||
| 43 | steps: | 43 | steps: |
| 44 | - uses: actions/checkout@v4 | 44 | - uses: actions/checkout@v4 |
| @@ -54,7 +54,7 @@ jobs: | @@ -54,7 +54,7 @@ jobs: | ||
| 54 | - name: ccache | 54 | - name: ccache |
| 55 | uses: hendrikmuhs/ccache-action@v1.2 | 55 | uses: hendrikmuhs/ccache-action@v1.2 |
| 56 | with: | 56 | with: |
| 57 | - key: ${{ matrix.os }}-flutter | 57 | + key: ${{ matrix.os }}-flutter-${{ matrix.arch }} |
| 58 | 58 | ||
| 59 | - name: Display PWD | 59 | - name: Display PWD |
| 60 | shell: bash | 60 | shell: bash |
| @@ -67,6 +67,11 @@ jobs: | @@ -67,6 +67,11 @@ jobs: | ||
| 67 | run: | | 67 | run: | |
| 68 | uname -a | 68 | uname -a |
| 69 | 69 | ||
| 70 | + - name: Install tree | ||
| 71 | + shell: bash | ||
| 72 | + run: | | ||
| 73 | + brew install tree | ||
| 74 | + | ||
| 70 | - name: Display flutter info | 75 | - name: Display flutter info |
| 71 | shell: bash | 76 | shell: bash |
| 72 | run: | | 77 | run: | |
| @@ -83,20 +88,22 @@ jobs: | @@ -83,20 +88,22 @@ jobs: | ||
| 83 | export CMAKE_CXX_COMPILER_LAUNCHER=ccache | 88 | export CMAKE_CXX_COMPILER_LAUNCHER=ccache |
| 84 | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" | 89 | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" |
| 85 | cmake --version | 90 | cmake --version |
| 91 | + arch=${{ matrix.arch }} | ||
| 86 | 92 | ||
| 87 | mkdir build | 93 | mkdir build |
| 88 | cd build | 94 | cd build |
| 89 | 95 | ||
| 90 | cmake \ | 96 | cmake \ |
| 91 | -D BUILD_SHARED_LIBS=ON \ | 97 | -D BUILD_SHARED_LIBS=ON \ |
| 92 | - -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' \ | 98 | + -DCMAKE_OSX_ARCHITECTURES=$arch \ |
| 93 | -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \ | 99 | -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \ |
| 94 | -DSHERPA_ONNX_ENABLE_WEBSOCKET=OFF \ | 100 | -DSHERPA_ONNX_ENABLE_WEBSOCKET=OFF \ |
| 95 | - -DSHERPA_ONNX_ENABLE_BINARY=ON \ | 101 | + -DBUILD_ESPEAK_NG_EXE=OFF \ |
| 102 | + -DSHERPA_ONNX_ENABLE_BINARY=OFF \ | ||
| 96 | -DCMAKE_INSTALL_PREFIX=./install \ | 103 | -DCMAKE_INSTALL_PREFIX=./install \ |
| 97 | .. | 104 | .. |
| 98 | 105 | ||
| 99 | - - name: Build sherpa-onnx for macos | 106 | + - name: Build sherpa-onnx for macos ${{ matrix.arch }} |
| 100 | shell: bash | 107 | shell: bash |
| 101 | run: | | 108 | run: | |
| 102 | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" | 109 | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" |
| @@ -105,7 +112,7 @@ jobs: | @@ -105,7 +112,7 @@ jobs: | ||
| 105 | make -j2 | 112 | make -j2 |
| 106 | make install | 113 | make install |
| 107 | 114 | ||
| 108 | - rm -v ./install/lib/libcargs* | 115 | + rm -v ./install/lib/libonnxruntime.dylib |
| 109 | 116 | ||
| 110 | - name: Copy libs | 117 | - name: Copy libs |
| 111 | shell: bash | 118 | shell: bash |
| @@ -122,14 +129,13 @@ jobs: | @@ -122,14 +129,13 @@ jobs: | ||
| 122 | cd sherpa-onnx/flutter | 129 | cd sherpa-onnx/flutter |
| 123 | pushd example/assets | 130 | pushd example/assets |
| 124 | 131 | ||
| 125 | - curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/speaker-recongition-models/3dspeaker_speech_eres2net_base_sv_zh-cn_3dspeaker_16k.onnx | 132 | + # curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/speaker-recongition-models/3dspeaker_speech_eres2net_base_sv_zh-cn_3dspeaker_16k.onnx |
| 126 | curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/silero_vad.onnx | 133 | curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/silero_vad.onnx |
| 127 | - git clone https://github.com/csukuangfj/sr-data | 134 | + # git clone https://github.com/csukuangfj/sr-data |
| 128 | 135 | ||
| 129 | rm -rf sr-data/.git | 136 | rm -rf sr-data/.git |
| 130 | popd | 137 | popd |
| 131 | 138 | ||
| 132 | - | ||
| 133 | - name: Build flutter | 139 | - name: Build flutter |
| 134 | shell: bash | 140 | shell: bash |
| 135 | run: | | 141 | run: | |
| @@ -139,20 +145,25 @@ jobs: | @@ -139,20 +145,25 @@ jobs: | ||
| 139 | dart pub get | 145 | dart pub get |
| 140 | 146 | ||
| 141 | cd example | 147 | cd example |
| 148 | + export FLUTTER_XCODE_ARCHS=${{ matrix.arch }} | ||
| 149 | + echo "FLUTTER_XCODE_ARCHS: $FLUTTER_XCODE_ARCHS" | ||
| 142 | flutter build macos | 150 | flutter build macos |
| 143 | 151 | ||
| 144 | - pushd build/macos/Build/Products/Release/ | ||
| 145 | - tar cjfv sherpa_onnx.app.tar.bz2 ./sherpa_onnx.app | 152 | + cd build/macos/Build/Products/Release/ |
| 153 | + | ||
| 154 | + tree ./sherpa_onnx.app | ||
| 155 | + | ||
| 156 | + app=flutter_sherpa_onnx_macos_${{ matrix.arch }}.app | ||
| 157 | + mv sherpa_onnx.app $app | ||
| 158 | + tar cjfv $app.tar.bz2 $app | ||
| 146 | ls -lh | 159 | ls -lh |
| 147 | - mv sherpa_onnx.app.tar.bz2 $d | ||
| 148 | - popd | 160 | + mv $app.tar.bz2 $d |
| 149 | 161 | ||
| 150 | popd | 162 | popd |
| 151 | 163 | ||
| 152 | - ls -lh sherpa_onnx.app.tar.bz2 | 164 | + ls -lh $app.tar.bz2 |
| 153 | 165 | ||
| 154 | - uses: actions/upload-artifact@v4 | 166 | - uses: actions/upload-artifact@v4 |
| 155 | - if: matrix.os == 'macos-latest' | ||
| 156 | with: | 167 | with: |
| 157 | - name: flutter-sherpa-onnx-app-macos | ||
| 158 | - path: ./sherpa_onnx.app.tar.bz2 | 168 | + name: flutter-sherpa-onnx-app-macos-${{ matrix.arch }} |
| 169 | + path: ./*.tar.bz2 |
.github/workflows/flutter-windows-x64.yaml
0 → 100644
| 1 | +name: flutter-windows-x64 | ||
| 2 | + | ||
| 3 | +on: | ||
| 4 | + push: | ||
| 5 | + branches: | ||
| 6 | + - flutter | ||
| 7 | + tags: | ||
| 8 | + - '*' | ||
| 9 | + paths: | ||
| 10 | + - '.github/workflows/flutter-windows-x64.yaml' | ||
| 11 | + - 'CMakeLists.txt' | ||
| 12 | + - 'cmake/**' | ||
| 13 | + - 'sherpa-onnx/csrc/*' | ||
| 14 | + - 'sherpa-onnx/c-api/*' | ||
| 15 | + - 'sherpa-onnx/flutter/**' | ||
| 16 | + pull_request: | ||
| 17 | + branches: | ||
| 18 | + - master | ||
| 19 | + paths: | ||
| 20 | + - '.github/workflows/flutter-windows-x64.yaml' | ||
| 21 | + - 'CMakeLists.txt' | ||
| 22 | + - 'cmake/**' | ||
| 23 | + - 'sherpa-onnx/csrc/*' | ||
| 24 | + - 'sherpa-onnx/c-api/*' | ||
| 25 | + - 'sherpa-onnx/flutter/**' | ||
| 26 | + | ||
| 27 | + workflow_dispatch: | ||
| 28 | + | ||
| 29 | +concurrency: | ||
| 30 | + group: flutter-windows-x64${{ github.ref }} | ||
| 31 | + cancel-in-progress: true | ||
| 32 | + | ||
| 33 | +jobs: | ||
| 34 | + flutter_windows_x64: | ||
| 35 | + name: flutter windows x64 | ||
| 36 | + runs-on: ${{ matrix.os }} | ||
| 37 | + strategy: | ||
| 38 | + fail-fast: false | ||
| 39 | + matrix: | ||
| 40 | + os: [windows-latest] | ||
| 41 | + | ||
| 42 | + steps: | ||
| 43 | + - uses: actions/checkout@v4 | ||
| 44 | + with: | ||
| 45 | + fetch-depth: 0 | ||
| 46 | + | ||
| 47 | + - name: Setup Flutter SDK | ||
| 48 | + uses: flutter-actions/setup-flutter@v3 | ||
| 49 | + with: | ||
| 50 | + channel: stable | ||
| 51 | + version: latest | ||
| 52 | + | ||
| 53 | + - name: Display PWD | ||
| 54 | + shell: bash | ||
| 55 | + run: | | ||
| 56 | + echo "pwd: $PWD" | ||
| 57 | + ls -lh | ||
| 58 | + | ||
| 59 | + - name: Display machine info | ||
| 60 | + shell: bash | ||
| 61 | + run: | | ||
| 62 | + uname -a | ||
| 63 | + | ||
| 64 | + - name: Display flutter info | ||
| 65 | + shell: bash | ||
| 66 | + run: | | ||
| 67 | + which flutter | ||
| 68 | + which dart | ||
| 69 | + | ||
| 70 | + flutter --version | ||
| 71 | + dart --version | ||
| 72 | + flutter doctor | ||
| 73 | + | ||
| 74 | + - name: Configure CMake | ||
| 75 | + shell: bash | ||
| 76 | + run: | | ||
| 77 | + cmake --version | ||
| 78 | + | ||
| 79 | + mkdir build | ||
| 80 | + cd build | ||
| 81 | + | ||
| 82 | + cmake \ | ||
| 83 | + -A x64 \ | ||
| 84 | + -DBUILD_SHARED_LIBS=ON \ | ||
| 85 | + -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \ | ||
| 86 | + -DSHERPA_ONNX_ENABLE_WEBSOCKET=OFF \ | ||
| 87 | + -DBUILD_ESPEAK_NG_EXE=OFF \ | ||
| 88 | + -DSHERPA_ONNX_ENABLE_BINARY=OFF \ | ||
| 89 | + -DBUILD_ESPEAK_NG_EXE=OFF \ | ||
| 90 | + -DCMAKE_INSTALL_PREFIX=./install \ | ||
| 91 | + .. | ||
| 92 | + | ||
| 93 | + - name: Build sherpa-onnx for windows x64 | ||
| 94 | + shell: bash | ||
| 95 | + run: | | ||
| 96 | + cd build | ||
| 97 | + cmake --build . --config Release -- -m:2 | ||
| 98 | + cmake --build . --config Release --target install -- -m:2 | ||
| 99 | + | ||
| 100 | + - name: Copy libs | ||
| 101 | + shell: bash | ||
| 102 | + run: | | ||
| 103 | + cp -v build/install/lib/*dll ./sherpa-onnx/flutter/windows/ | ||
| 104 | + cp -v build/install/lib/*fst* ./sherpa-onnx/flutter/windows/ | ||
| 105 | + | ||
| 106 | + echo "--------------------" | ||
| 107 | + | ||
| 108 | + ls -lh ./sherpa-onnx/flutter/windows/ | ||
| 109 | + | ||
| 110 | + - name: Download model files | ||
| 111 | + shell: bash | ||
| 112 | + run: | | ||
| 113 | + cd sherpa-onnx/flutter | ||
| 114 | + | ||
| 115 | + cd example/assets | ||
| 116 | + | ||
| 117 | + curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/silero_vad.onnx | ||
| 118 | + | ||
| 119 | + - name: Build flutter | ||
| 120 | + shell: bash | ||
| 121 | + run: | | ||
| 122 | + d=$PWD | ||
| 123 | + | ||
| 124 | + pushd sherpa-onnx/flutter | ||
| 125 | + dart pub get | ||
| 126 | + | ||
| 127 | + cd example | ||
| 128 | + flutter build windows | ||
| 129 | + | ||
| 130 | + cd build/windows/x64/runner/ | ||
| 131 | + | ||
| 132 | + dst=flutter_sherpa_onnx_windows_x64 | ||
| 133 | + mv Release $dst | ||
| 134 | + | ||
| 135 | + tar cjfv $dst.tar.bz2 ./$dst | ||
| 136 | + ls -lh | ||
| 137 | + mv $dst.tar.bz2 $d/ | ||
| 138 | + | ||
| 139 | + popd | ||
| 140 | + | ||
| 141 | + ls -lh $dst.tar.bz2 | ||
| 142 | + | ||
| 143 | + - uses: actions/upload-artifact@v4 | ||
| 144 | + with: | ||
| 145 | + name: flutter-sherpa-onnx-windows-x64 | ||
| 146 | + path: ./*.tar.bz2 |
| @@ -53,9 +53,9 @@ static OnlineRecognizerResult Convert(const OnlineParaformerDecoderResult &src, | @@ -53,9 +53,9 @@ static OnlineRecognizerResult Convert(const OnlineParaformerDecoderResult &src, | ||
| 53 | mergeable = false; | 53 | mergeable = false; |
| 54 | 54 | ||
| 55 | if (i > 0) { | 55 | if (i > 0) { |
| 56 | - const uint8_t *p = reinterpret_cast<const uint8_t *>( | ||
| 57 | - sym_table[src.tokens[i - 1]].c_str()); | ||
| 58 | - if (p[0] < 0x80) { | 56 | + const uint8_t p = reinterpret_cast<const uint8_t *>( |
| 57 | + sym_table[src.tokens[i - 1]].c_str())[0]; | ||
| 58 | + if (p < 0x80) { | ||
| 59 | // put a space between ascii and non-ascii | 59 | // put a space between ascii and non-ascii |
| 60 | text.append(" "); | 60 | text.append(" "); |
| 61 | } | 61 | } |
sherpa-onnx/flutter/example/lib/home.dart
0 → 100644
| 1 | +// Copyright (c) 2024 Xiaomi Corporation | ||
| 2 | +import 'dart:async'; | ||
| 3 | + | ||
| 4 | +import 'package:flutter/foundation.dart'; | ||
| 5 | +import 'package:flutter/material.dart'; | ||
| 6 | +import 'package:path/path.dart' as p; | ||
| 7 | +import 'package:path_provider/path_provider.dart'; | ||
| 8 | +import 'package:record/record.dart'; | ||
| 9 | + | ||
| 10 | +import 'package:sherpa_onnx/sherpa_onnx.dart' as sherpa_onnx; | ||
| 11 | + | ||
| 12 | +import './utils.dart'; | ||
| 13 | + | ||
| 14 | +class HomeScreen extends StatefulWidget { | ||
| 15 | + const HomeScreen({super.key}); | ||
| 16 | + | ||
| 17 | + @override | ||
| 18 | + State<HomeScreen> createState() => _HomeScreenState(); | ||
| 19 | +} | ||
| 20 | + | ||
| 21 | +class _HomeScreenState extends State<HomeScreen> { | ||
| 22 | + late final AudioRecorder _audioRecorder; | ||
| 23 | + | ||
| 24 | + bool _printed = false; | ||
| 25 | + var _color = Colors.black; | ||
| 26 | + bool _isInitialized = false; | ||
| 27 | + | ||
| 28 | + sherpa_onnx.VoiceActivityDetector? _vad; | ||
| 29 | + sherpa_onnx.CircularBuffer? _buffer; | ||
| 30 | + | ||
| 31 | + StreamSubscription<RecordState>? _recordSub; | ||
| 32 | + RecordState _recordState = RecordState.stop; | ||
| 33 | + | ||
| 34 | + @override | ||
| 35 | + void initState() { | ||
| 36 | + _audioRecorder = AudioRecorder(); | ||
| 37 | + | ||
| 38 | + _recordSub = _audioRecorder.onStateChanged().listen((recordState) { | ||
| 39 | + _updateRecordState(recordState); | ||
| 40 | + }); | ||
| 41 | + | ||
| 42 | + super.initState(); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + Future<void> _start() async { | ||
| 46 | + if (!_isInitialized) { | ||
| 47 | + sherpa_onnx.initBindings(); | ||
| 48 | + final src = 'assets/silero_vad.onnx'; | ||
| 49 | + final modelPath = await copyAssetFile(src: src, dst: 'silero_vad.onnx'); | ||
| 50 | + | ||
| 51 | + final sileroVadConfig = sherpa_onnx.SileroVadModelConfig( | ||
| 52 | + model: modelPath, | ||
| 53 | + minSpeechDuration: 0.25, | ||
| 54 | + minSilenceDuration: 0.5, | ||
| 55 | + ); | ||
| 56 | + | ||
| 57 | + final config = sherpa_onnx.VadModelConfig( | ||
| 58 | + sileroVad: sileroVadConfig, | ||
| 59 | + numThreads: 1, | ||
| 60 | + debug: true, | ||
| 61 | + ); | ||
| 62 | + | ||
| 63 | + _vad = sherpa_onnx.VoiceActivityDetector( | ||
| 64 | + config: config, bufferSizeInSeconds: 30); | ||
| 65 | + | ||
| 66 | + _buffer = sherpa_onnx.CircularBuffer(capacity: 16000 * 30); | ||
| 67 | + print(_buffer!.ptr); | ||
| 68 | + | ||
| 69 | + _isInitialized = true; | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + try { | ||
| 73 | + if (await _audioRecorder.hasPermission()) { | ||
| 74 | + const encoder = AudioEncoder.pcm16bits; | ||
| 75 | + | ||
| 76 | + if (!await _isEncoderSupported(encoder)) { | ||
| 77 | + return; | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + final devs = await _audioRecorder.listInputDevices(); | ||
| 81 | + debugPrint(devs.toString()); | ||
| 82 | + | ||
| 83 | + const config = RecordConfig( | ||
| 84 | + encoder: encoder, | ||
| 85 | + sampleRate: 16000, | ||
| 86 | + numChannels: 1, | ||
| 87 | + ); | ||
| 88 | + | ||
| 89 | + final stream = await _audioRecorder.startStream(config); | ||
| 90 | + | ||
| 91 | + final dir = await getApplicationDocumentsDirectory(); | ||
| 92 | + | ||
| 93 | + stream.listen( | ||
| 94 | + (data) { | ||
| 95 | + final samplesFloat32 = | ||
| 96 | + convertBytesToFloat32(Uint8List.fromList(data)); | ||
| 97 | + | ||
| 98 | + _buffer!.push(samplesFloat32); | ||
| 99 | + | ||
| 100 | + final windowSize = _vad!.config.sileroVad.windowSize; | ||
| 101 | + while (_buffer!.size > windowSize) { | ||
| 102 | + final samples = | ||
| 103 | + _buffer!.get(startIndex: _buffer!.head, n: windowSize); | ||
| 104 | + _buffer!.pop(windowSize); | ||
| 105 | + _vad!.acceptWaveform(samples); | ||
| 106 | + if (_vad!.isDetected() && !_printed) { | ||
| 107 | + print('detected'); | ||
| 108 | + _printed = true; | ||
| 109 | + | ||
| 110 | + setState(() => _color = Colors.red); | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + if (!_vad!.isDetected()) { | ||
| 114 | + _printed = false; | ||
| 115 | + setState(() => _color = Colors.black); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + while (!_vad!.isEmpty()) { | ||
| 119 | + final segment = _vad!.front(); | ||
| 120 | + final duration = segment.samples.length / 16000; | ||
| 121 | + final d = DateTime.now(); | ||
| 122 | + final filename = p.join(dir.path, | ||
| 123 | + '${d.year}-${d.month}-${d.day}-${d.hour}-${d.minute}-${d.second}-duration-${duration.toStringAsPrecision(3)}s.wav'); | ||
| 124 | + | ||
| 125 | + bool ok = sherpa_onnx.writeWave( | ||
| 126 | + filename: filename, | ||
| 127 | + samples: segment.samples, | ||
| 128 | + sampleRate: 16000); | ||
| 129 | + if (!ok) { | ||
| 130 | + print('Failed to write $filename'); | ||
| 131 | + } else { | ||
| 132 | + print('Saved to write $filename'); | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + _vad!.pop(); | ||
| 136 | + } | ||
| 137 | + } | ||
| 138 | + }, | ||
| 139 | + onDone: () { | ||
| 140 | + print('stream stopped.'); | ||
| 141 | + }, | ||
| 142 | + ); | ||
| 143 | + } | ||
| 144 | + } catch (e) { | ||
| 145 | + print(e); | ||
| 146 | + } | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + Future<void> _stop() async { | ||
| 150 | + _buffer!.reset(); | ||
| 151 | + _vad!.clear(); | ||
| 152 | + | ||
| 153 | + await _audioRecorder.stop(); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + Future<void> _pause() => _audioRecorder.pause(); | ||
| 157 | + | ||
| 158 | + Future<void> _resume() => _audioRecorder.resume(); | ||
| 159 | + | ||
| 160 | + void _updateRecordState(RecordState recordState) { | ||
| 161 | + setState(() => _recordState = recordState); | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + Future<bool> _isEncoderSupported(AudioEncoder encoder) async { | ||
| 165 | + final isSupported = await _audioRecorder.isEncoderSupported( | ||
| 166 | + encoder, | ||
| 167 | + ); | ||
| 168 | + | ||
| 169 | + if (!isSupported) { | ||
| 170 | + debugPrint('${encoder.name} is not supported on this platform.'); | ||
| 171 | + debugPrint('Supported encoders are:'); | ||
| 172 | + | ||
| 173 | + for (final e in AudioEncoder.values) { | ||
| 174 | + if (await _audioRecorder.isEncoderSupported(e)) { | ||
| 175 | + debugPrint('- ${encoder.name}'); | ||
| 176 | + } | ||
| 177 | + } | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + return isSupported; | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + @override | ||
| 184 | + Widget build(BuildContext context) { | ||
| 185 | + return MaterialApp( | ||
| 186 | + home: Scaffold( | ||
| 187 | + body: Column( | ||
| 188 | + mainAxisAlignment: MainAxisAlignment.center, | ||
| 189 | + children: [ | ||
| 190 | + Container( | ||
| 191 | + width: 100.0, | ||
| 192 | + height: 100.0, | ||
| 193 | + decoration: BoxDecoration( | ||
| 194 | + shape: BoxShape.circle, | ||
| 195 | + color: _color, | ||
| 196 | + ), | ||
| 197 | + ), | ||
| 198 | + const SizedBox(height: 50), | ||
| 199 | + Row( | ||
| 200 | + mainAxisAlignment: MainAxisAlignment.center, | ||
| 201 | + children: <Widget>[ | ||
| 202 | + _buildRecordStopControl(), | ||
| 203 | + const SizedBox(width: 20), | ||
| 204 | + _buildText(), | ||
| 205 | + ], | ||
| 206 | + ), | ||
| 207 | + ], | ||
| 208 | + ), | ||
| 209 | + ), | ||
| 210 | + ); | ||
| 211 | + } | ||
| 212 | + | ||
| 213 | + @override | ||
| 214 | + void dispose() { | ||
| 215 | + _recordSub?.cancel(); | ||
| 216 | + _audioRecorder.dispose(); | ||
| 217 | + _vad?.free(); | ||
| 218 | + _buffer?.free(); | ||
| 219 | + super.dispose(); | ||
| 220 | + } | ||
| 221 | + | ||
| 222 | + Widget _buildRecordStopControl() { | ||
| 223 | + late Icon icon; | ||
| 224 | + late Color color; | ||
| 225 | + | ||
| 226 | + if (_recordState != RecordState.stop) { | ||
| 227 | + icon = const Icon(Icons.stop, color: Colors.red, size: 30); | ||
| 228 | + color = Colors.red.withOpacity(0.1); | ||
| 229 | + } else { | ||
| 230 | + final theme = Theme.of(context); | ||
| 231 | + icon = Icon(Icons.mic, color: theme.primaryColor, size: 30); | ||
| 232 | + color = theme.primaryColor.withOpacity(0.1); | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + return ClipOval( | ||
| 236 | + child: Material( | ||
| 237 | + color: color, | ||
| 238 | + child: InkWell( | ||
| 239 | + child: SizedBox(width: 56, height: 56, child: icon), | ||
| 240 | + onTap: () { | ||
| 241 | + (_recordState != RecordState.stop) ? _stop() : _start(); | ||
| 242 | + }, | ||
| 243 | + ), | ||
| 244 | + ), | ||
| 245 | + ); | ||
| 246 | + } | ||
| 247 | + | ||
| 248 | + Widget _buildText() { | ||
| 249 | + if (_recordState == RecordState.stop) { | ||
| 250 | + return const Text("Start"); | ||
| 251 | + } else { | ||
| 252 | + return const Text("Stop"); | ||
| 253 | + } | ||
| 254 | + } | ||
| 255 | +} |
sherpa-onnx/flutter/example/lib/info.dart
0 → 100644
| 1 | +// Copyright (c) 2024 Xiaomi Corporation | ||
| 2 | +import 'package:flutter/material.dart'; | ||
| 3 | +import 'package:url_launcher/url_launcher.dart'; | ||
| 4 | + | ||
| 5 | +class InfoScreen extends StatelessWidget { | ||
| 6 | + @override | ||
| 7 | + Widget build(BuildContext context) { | ||
| 8 | + const double height = 20; | ||
| 9 | + return Container( | ||
| 10 | + child: Padding( | ||
| 11 | + padding: const EdgeInsets.all(8.0), | ||
| 12 | + child: Column( | ||
| 13 | + crossAxisAlignment: CrossAxisAlignment.start, | ||
| 14 | + children: <Widget>[ | ||
| 15 | + Text('Everything is open-sourced.'), | ||
| 16 | + SizedBox(height: height), | ||
| 17 | + InkWell( | ||
| 18 | + child: Text('Code: https://github.com/k2-fsa/sherpa-onnx'), | ||
| 19 | + onTap: () => launch('https://k2-fsa.github.io/sherpa/onnx/'), | ||
| 20 | + ), | ||
| 21 | + SizedBox(height: height), | ||
| 22 | + InkWell( | ||
| 23 | + child: Text('Doc: https://k2-fsa.github.io/sherpa/onnx/'), | ||
| 24 | + onTap: () => launch('https://k2-fsa.github.io/sherpa/onnx/'), | ||
| 25 | + ), | ||
| 26 | + SizedBox(height: height), | ||
| 27 | + Text('QQ 群: 744602236'), | ||
| 28 | + SizedBox(height: height), | ||
| 29 | + InkWell( | ||
| 30 | + child: Text( | ||
| 31 | + '微信群: https://k2-fsa.github.io/sherpa/social-groups.html'), | ||
| 32 | + onTap: () => | ||
| 33 | + launch('https://k2-fsa.github.io/sherpa/social-groups.html'), | ||
| 34 | + ), | ||
| 35 | + ], | ||
| 36 | + ), | ||
| 37 | + ), | ||
| 38 | + ); | ||
| 39 | + } | ||
| 40 | +} |
| @@ -4,6 +4,8 @@ import 'package:flutter/material.dart'; | @@ -4,6 +4,8 @@ import 'package:flutter/material.dart'; | ||
| 4 | 4 | ||
| 5 | import "./speaker_identification_test.dart"; | 5 | import "./speaker_identification_test.dart"; |
| 6 | import "./vad_test.dart"; | 6 | import "./vad_test.dart"; |
| 7 | +import './home.dart'; | ||
| 8 | +import './info.dart'; | ||
| 7 | 9 | ||
| 8 | void main() { | 10 | void main() { |
| 9 | runApp(const MyApp()); | 11 | runApp(const MyApp()); |
| @@ -11,110 +13,56 @@ void main() { | @@ -11,110 +13,56 @@ void main() { | ||
| 11 | 13 | ||
| 12 | class MyApp extends StatelessWidget { | 14 | class MyApp extends StatelessWidget { |
| 13 | const MyApp({Key? key}) : super(key: key); | 15 | const MyApp({Key? key}) : super(key: key); |
| 14 | - // This widget is the root of your application. | ||
| 15 | @override | 16 | @override |
| 16 | Widget build(BuildContext context) { | 17 | Widget build(BuildContext context) { |
| 17 | return MaterialApp( | 18 | return MaterialApp( |
| 18 | - title: 'Flutter Demo', | 19 | + title: 'Next-gen Kaldi', |
| 19 | theme: ThemeData( | 20 | theme: ThemeData( |
| 20 | - // This is the theme of your application. | ||
| 21 | - // | ||
| 22 | - // Try running your application with "flutter run". You'll see the | ||
| 23 | - // application has a blue toolbar. Then, without quitting the app, try | ||
| 24 | - // changing the primarySwatch below to Colors.green and then invoke | ||
| 25 | - // "hot reload" (press "r" in the console where you ran "flutter run", | ||
| 26 | - // or simply save your changes to "hot reload" in a Flutter IDE). | ||
| 27 | - // Notice that the counter didn't reset back to zero; the application | ||
| 28 | - // is not restarted. | ||
| 29 | primarySwatch: Colors.blue, | 21 | primarySwatch: Colors.blue, |
| 30 | ), | 22 | ), |
| 31 | - home: const MyHomePage(title: 'Flutter Demo Home Page'), | 23 | + home: const MyHomePage(title: 'Next-gen Kaldi: VAD demo'), |
| 32 | ); | 24 | ); |
| 33 | } | 25 | } |
| 34 | } | 26 | } |
| 35 | 27 | ||
| 36 | class MyHomePage extends StatefulWidget { | 28 | class MyHomePage extends StatefulWidget { |
| 37 | const MyHomePage({Key? key, required this.title}) : super(key: key); | 29 | const MyHomePage({Key? key, required this.title}) : super(key: key); |
| 38 | - // This widget is the home page of your application. It is stateful, meaning | ||
| 39 | - // that it has a State object (defined below) that contains fields that affect | ||
| 40 | - // how it looks. | ||
| 41 | - // This class is the configuration for the state. It holds the values (in this | ||
| 42 | - // case the title) provided by the parent (in this case the App widget) and | ||
| 43 | - // used by the build method of the State. Fields in a Widget subclass are | ||
| 44 | - // always marked "final". | ||
| 45 | final String title; | 30 | final String title; |
| 46 | @override | 31 | @override |
| 47 | State<MyHomePage> createState() => _MyHomePageState(); | 32 | State<MyHomePage> createState() => _MyHomePageState(); |
| 48 | } | 33 | } |
| 49 | 34 | ||
| 50 | class _MyHomePageState extends State<MyHomePage> { | 35 | class _MyHomePageState extends State<MyHomePage> { |
| 51 | - int _counter = 0; | ||
| 52 | - Future<void> _incrementCounter() async { | ||
| 53 | - if (_counter <= 10) { | ||
| 54 | - sherpa_onnx.initBindings(); | ||
| 55 | - await testSpeakerID(); | ||
| 56 | - // await testVad(); | ||
| 57 | - } | ||
| 58 | - | ||
| 59 | - setState(() { | ||
| 60 | - // This call to setState tells the Flutter framework that something has | ||
| 61 | - // changed in this State, which causes it to rerun the build method below | ||
| 62 | - // so that the display can reflect the updated values. If we changed | ||
| 63 | - // _counter without calling setState(), then the build method would not be | ||
| 64 | - // called again, and so nothing would appear to happen. | ||
| 65 | - _counter++; | ||
| 66 | - }); | ||
| 67 | - } | ||
| 68 | - | 36 | + int _currentIndex = 0; |
| 37 | + final List<Widget> _tabs = [ | ||
| 38 | + HomeScreen(), | ||
| 39 | + InfoScreen(), | ||
| 40 | + ]; | ||
| 69 | @override | 41 | @override |
| 70 | Widget build(BuildContext context) { | 42 | Widget build(BuildContext context) { |
| 71 | - // This method is rerun every time setState is called, for instance as done | ||
| 72 | - // by the _incrementCounter method above. | ||
| 73 | - // | ||
| 74 | - // The Flutter framework has been optimized to make rerunning build methods | ||
| 75 | - // fast, so that you can just rebuild anything that needs updating rather | ||
| 76 | - // than having to individually change instances of widgets. | ||
| 77 | return Scaffold( | 43 | return Scaffold( |
| 78 | appBar: AppBar( | 44 | appBar: AppBar( |
| 79 | - // Here we take the value from the MyHomePage object that was created by | ||
| 80 | - // the App.build method, and use it to set our appbar title. | ||
| 81 | title: Text(widget.title), | 45 | title: Text(widget.title), |
| 82 | ), | 46 | ), |
| 83 | - body: Center( | ||
| 84 | - // Center is a layout widget. It takes a single child and positions it | ||
| 85 | - // in the middle of the parent. | ||
| 86 | - child: Column( | ||
| 87 | - // Column is also a layout widget. It takes a list of children and | ||
| 88 | - // arranges them vertically. By default, it sizes itself to fit its | ||
| 89 | - // children horizontally, and tries to be as tall as its parent. | ||
| 90 | - // | ||
| 91 | - // Invoke "debug painting" (press "p" in the console, choose the | ||
| 92 | - // "Toggle Debug Paint" action from the Flutter Inspector in Android | ||
| 93 | - // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) | ||
| 94 | - // to see the wireframe for each widget. | ||
| 95 | - // | ||
| 96 | - // Column has various properties to control how it sizes itself and | ||
| 97 | - // how it positions its children. Here we use mainAxisAlignment to | ||
| 98 | - // center the children vertically; the main axis here is the vertical | ||
| 99 | - // axis because Columns are vertical (the cross axis would be | ||
| 100 | - // horizontal). | ||
| 101 | - mainAxisAlignment: MainAxisAlignment.center, | ||
| 102 | - children: <Widget>[ | ||
| 103 | - const Text( | ||
| 104 | - 'You have pushed the button this many times:', | ||
| 105 | - ), | ||
| 106 | - Text( | ||
| 107 | - '$_counter', | ||
| 108 | - style: Theme.of(context).textTheme.headlineSmall, | ||
| 109 | - ), | ||
| 110 | - ], | ||
| 111 | - ), | 47 | + body: _tabs[_currentIndex], |
| 48 | + bottomNavigationBar: BottomNavigationBar( | ||
| 49 | + currentIndex: _currentIndex, | ||
| 50 | + onTap: (int index) { | ||
| 51 | + setState(() { | ||
| 52 | + _currentIndex = index; | ||
| 53 | + }); | ||
| 54 | + }, | ||
| 55 | + items: [ | ||
| 56 | + BottomNavigationBarItem( | ||
| 57 | + icon: Icon(Icons.home), | ||
| 58 | + label: 'Home', | ||
| 59 | + ), | ||
| 60 | + BottomNavigationBarItem( | ||
| 61 | + icon: Icon(Icons.info), | ||
| 62 | + label: 'Info', | ||
| 63 | + ), | ||
| 64 | + ], | ||
| 112 | ), | 65 | ), |
| 113 | - floatingActionButton: FloatingActionButton( | ||
| 114 | - onPressed: _incrementCounter, | ||
| 115 | - tooltip: 'Increment', | ||
| 116 | - child: const Icon(Icons.add), | ||
| 117 | - ), // This trailing comma makes auto-formatting nicer for build methods. | ||
| 118 | ); | 66 | ); |
| 119 | } | 67 | } |
| 120 | } | 68 | } |
| @@ -2,6 +2,7 @@ | @@ -2,6 +2,7 @@ | ||
| 2 | import 'package:path/path.dart'; | 2 | import 'package:path/path.dart'; |
| 3 | import 'package:path_provider/path_provider.dart'; | 3 | import 'package:path_provider/path_provider.dart'; |
| 4 | import 'package:flutter/services.dart' show rootBundle; | 4 | import 'package:flutter/services.dart' show rootBundle; |
| 5 | +import 'dart:typed_data'; | ||
| 5 | import "dart:io"; | 6 | import "dart:io"; |
| 6 | 7 | ||
| 7 | // Copy the asset file from src to dst | 8 | // Copy the asset file from src to dst |
| @@ -16,3 +17,16 @@ Future<String> copyAssetFile({required String src, required String dst}) async { | @@ -16,3 +17,16 @@ Future<String> copyAssetFile({required String src, required String dst}) async { | ||
| 16 | 17 | ||
| 17 | return target; | 18 | return target; |
| 18 | } | 19 | } |
| 20 | + | ||
| 21 | +Float32List convertBytesToFloat32(Uint8List bytes, [endian = Endian.little]) { | ||
| 22 | + final values = Float32List(bytes.length ~/ 2); | ||
| 23 | + | ||
| 24 | + final data = ByteData.view(bytes.buffer); | ||
| 25 | + | ||
| 26 | + for (var i = 0; i < bytes.length; i += 2) { | ||
| 27 | + int short = data.getInt16(i, endian); | ||
| 28 | + values[i ~/ 2] = short / 32678.0; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + return values; | ||
| 32 | +} |
sherpa-onnx/flutter/example/linux/.gitignore
0 → 100644
| 1 | +flutter/ephemeral |
| 1 | +# Project-level configuration. | ||
| 2 | +cmake_minimum_required(VERSION 3.10) | ||
| 3 | +project(runner LANGUAGES CXX) | ||
| 4 | + | ||
| 5 | +# The name of the executable created for the application. Change this to change | ||
| 6 | +# the on-disk name of your application. | ||
| 7 | +set(BINARY_NAME "sherpa_onnx") | ||
| 8 | +# The unique GTK application identifier for this application. See: | ||
| 9 | +# https://wiki.gnome.org/HowDoI/ChooseApplicationID | ||
| 10 | +set(APPLICATION_ID "com.k2fsa.sherpa.onnx") | ||
| 11 | + | ||
| 12 | +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent | ||
| 13 | +# versions of CMake. | ||
| 14 | +cmake_policy(SET CMP0063 NEW) | ||
| 15 | + | ||
| 16 | +# Load bundled libraries from the lib/ directory relative to the binary. | ||
| 17 | +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") | ||
| 18 | + | ||
| 19 | +# Root filesystem for cross-building. | ||
| 20 | +if(FLUTTER_TARGET_PLATFORM_SYSROOT) | ||
| 21 | + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) | ||
| 22 | + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) | ||
| 23 | + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | ||
| 24 | + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) | ||
| 25 | + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | ||
| 26 | + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) | ||
| 27 | +endif() | ||
| 28 | + | ||
| 29 | +# Define build configuration options. | ||
| 30 | +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) | ||
| 31 | + set(CMAKE_BUILD_TYPE "Debug" CACHE | ||
| 32 | + STRING "Flutter build mode" FORCE) | ||
| 33 | + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS | ||
| 34 | + "Debug" "Profile" "Release") | ||
| 35 | +endif() | ||
| 36 | + | ||
| 37 | +# Compilation settings that should be applied to most targets. | ||
| 38 | +# | ||
| 39 | +# Be cautious about adding new options here, as plugins use this function by | ||
| 40 | +# default. In most cases, you should add new options to specific targets instead | ||
| 41 | +# of modifying this function. | ||
| 42 | +function(APPLY_STANDARD_SETTINGS TARGET) | ||
| 43 | + target_compile_features(${TARGET} PUBLIC cxx_std_14) | ||
| 44 | + target_compile_options(${TARGET} PRIVATE -Wall -Werror) | ||
| 45 | + target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>") | ||
| 46 | + target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>") | ||
| 47 | +endfunction() | ||
| 48 | + | ||
| 49 | +# Flutter library and tool build rules. | ||
| 50 | +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") | ||
| 51 | +add_subdirectory(${FLUTTER_MANAGED_DIR}) | ||
| 52 | + | ||
| 53 | +# System-level dependencies. | ||
| 54 | +find_package(PkgConfig REQUIRED) | ||
| 55 | +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) | ||
| 56 | + | ||
| 57 | +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") | ||
| 58 | + | ||
| 59 | +# Define the application target. To change its name, change BINARY_NAME above, | ||
| 60 | +# not the value here, or `flutter run` will no longer work. | ||
| 61 | +# | ||
| 62 | +# Any new source files that you add to the application should be added here. | ||
| 63 | +add_executable(${BINARY_NAME} | ||
| 64 | + "main.cc" | ||
| 65 | + "my_application.cc" | ||
| 66 | + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" | ||
| 67 | +) | ||
| 68 | + | ||
| 69 | +# Apply the standard set of build settings. This can be removed for applications | ||
| 70 | +# that need different build settings. | ||
| 71 | +apply_standard_settings(${BINARY_NAME}) | ||
| 72 | + | ||
| 73 | +# Add dependency libraries. Add any application-specific dependencies here. | ||
| 74 | +target_link_libraries(${BINARY_NAME} PRIVATE flutter) | ||
| 75 | +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) | ||
| 76 | + | ||
| 77 | +# Run the Flutter tool portions of the build. This must not be removed. | ||
| 78 | +add_dependencies(${BINARY_NAME} flutter_assemble) | ||
| 79 | + | ||
| 80 | +# Only the install-generated bundle's copy of the executable will launch | ||
| 81 | +# correctly, since the resources must in the right relative locations. To avoid | ||
| 82 | +# people trying to run the unbundled copy, put it in a subdirectory instead of | ||
| 83 | +# the default top-level location. | ||
| 84 | +set_target_properties(${BINARY_NAME} | ||
| 85 | + PROPERTIES | ||
| 86 | + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" | ||
| 87 | +) | ||
| 88 | + | ||
| 89 | + | ||
| 90 | +# Generated plugin build rules, which manage building the plugins and adding | ||
| 91 | +# them to the application. | ||
| 92 | +include(flutter/generated_plugins.cmake) | ||
| 93 | + | ||
| 94 | + | ||
| 95 | +# === Installation === | ||
| 96 | +# By default, "installing" just makes a relocatable bundle in the build | ||
| 97 | +# directory. | ||
| 98 | +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") | ||
| 99 | +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) | ||
| 100 | + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) | ||
| 101 | +endif() | ||
| 102 | + | ||
| 103 | +# Start with a clean build bundle directory every time. | ||
| 104 | +install(CODE " | ||
| 105 | + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") | ||
| 106 | + " COMPONENT Runtime) | ||
| 107 | + | ||
| 108 | +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") | ||
| 109 | +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") | ||
| 110 | + | ||
| 111 | +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" | ||
| 112 | + COMPONENT Runtime) | ||
| 113 | + | ||
| 114 | +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" | ||
| 115 | + COMPONENT Runtime) | ||
| 116 | + | ||
| 117 | +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 118 | + COMPONENT Runtime) | ||
| 119 | + | ||
| 120 | +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) | ||
| 121 | + install(FILES "${bundled_library}" | ||
| 122 | + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 123 | + COMPONENT Runtime) | ||
| 124 | +endforeach(bundled_library) | ||
| 125 | + | ||
| 126 | +# Copy the native assets provided by the build.dart from all packages. | ||
| 127 | +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") | ||
| 128 | +install(DIRECTORY "${NATIVE_ASSETS_DIR}" | ||
| 129 | + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 130 | + COMPONENT Runtime) | ||
| 131 | + | ||
| 132 | +# Fully re-copy the assets directory on each build to avoid having stale files | ||
| 133 | +# from a previous install. | ||
| 134 | +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") | ||
| 135 | +install(CODE " | ||
| 136 | + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") | ||
| 137 | + " COMPONENT Runtime) | ||
| 138 | +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" | ||
| 139 | + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) | ||
| 140 | + | ||
| 141 | +# Install the AOT library on non-Debug builds only. | ||
| 142 | +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") | ||
| 143 | + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 144 | + COMPONENT Runtime) | ||
| 145 | +endif() |
| 1 | +# This file controls Flutter-level build steps. It should not be edited. | ||
| 2 | +cmake_minimum_required(VERSION 3.10) | ||
| 3 | + | ||
| 4 | +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") | ||
| 5 | + | ||
| 6 | +# Configuration provided via flutter tool. | ||
| 7 | +include(${EPHEMERAL_DIR}/generated_config.cmake) | ||
| 8 | + | ||
| 9 | +# TODO: Move the rest of this into files in ephemeral. See | ||
| 10 | +# https://github.com/flutter/flutter/issues/57146. | ||
| 11 | + | ||
| 12 | +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), | ||
| 13 | +# which isn't available in 3.10. | ||
| 14 | +function(list_prepend LIST_NAME PREFIX) | ||
| 15 | + set(NEW_LIST "") | ||
| 16 | + foreach(element ${${LIST_NAME}}) | ||
| 17 | + list(APPEND NEW_LIST "${PREFIX}${element}") | ||
| 18 | + endforeach(element) | ||
| 19 | + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) | ||
| 20 | +endfunction() | ||
| 21 | + | ||
| 22 | +# === Flutter Library === | ||
| 23 | +# System-level dependencies. | ||
| 24 | +find_package(PkgConfig REQUIRED) | ||
| 25 | +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) | ||
| 26 | +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) | ||
| 27 | +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) | ||
| 28 | + | ||
| 29 | +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") | ||
| 30 | + | ||
| 31 | +# Published to parent scope for install step. | ||
| 32 | +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) | ||
| 33 | +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) | ||
| 34 | +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) | ||
| 35 | +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) | ||
| 36 | + | ||
| 37 | +list(APPEND FLUTTER_LIBRARY_HEADERS | ||
| 38 | + "fl_basic_message_channel.h" | ||
| 39 | + "fl_binary_codec.h" | ||
| 40 | + "fl_binary_messenger.h" | ||
| 41 | + "fl_dart_project.h" | ||
| 42 | + "fl_engine.h" | ||
| 43 | + "fl_json_message_codec.h" | ||
| 44 | + "fl_json_method_codec.h" | ||
| 45 | + "fl_message_codec.h" | ||
| 46 | + "fl_method_call.h" | ||
| 47 | + "fl_method_channel.h" | ||
| 48 | + "fl_method_codec.h" | ||
| 49 | + "fl_method_response.h" | ||
| 50 | + "fl_plugin_registrar.h" | ||
| 51 | + "fl_plugin_registry.h" | ||
| 52 | + "fl_standard_message_codec.h" | ||
| 53 | + "fl_standard_method_codec.h" | ||
| 54 | + "fl_string_codec.h" | ||
| 55 | + "fl_value.h" | ||
| 56 | + "fl_view.h" | ||
| 57 | + "flutter_linux.h" | ||
| 58 | +) | ||
| 59 | +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") | ||
| 60 | +add_library(flutter INTERFACE) | ||
| 61 | +target_include_directories(flutter INTERFACE | ||
| 62 | + "${EPHEMERAL_DIR}" | ||
| 63 | +) | ||
| 64 | +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") | ||
| 65 | +target_link_libraries(flutter INTERFACE | ||
| 66 | + PkgConfig::GTK | ||
| 67 | + PkgConfig::GLIB | ||
| 68 | + PkgConfig::GIO | ||
| 69 | +) | ||
| 70 | +add_dependencies(flutter flutter_assemble) | ||
| 71 | + | ||
| 72 | +# === Flutter tool backend === | ||
| 73 | +# _phony_ is a non-existent file to force this command to run every time, | ||
| 74 | +# since currently there's no way to get a full input/output list from the | ||
| 75 | +# flutter tool. | ||
| 76 | +add_custom_command( | ||
| 77 | + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} | ||
| 78 | + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ | ||
| 79 | + COMMAND ${CMAKE_COMMAND} -E env | ||
| 80 | + ${FLUTTER_TOOL_ENVIRONMENT} | ||
| 81 | + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" | ||
| 82 | + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} | ||
| 83 | + VERBATIM | ||
| 84 | +) | ||
| 85 | +add_custom_target(flutter_assemble DEPENDS | ||
| 86 | + "${FLUTTER_LIBRARY}" | ||
| 87 | + ${FLUTTER_LIBRARY_HEADERS} | ||
| 88 | +) |
sherpa-onnx/flutter/example/linux/main.cc
0 → 100644
| 1 | +#include "my_application.h" | ||
| 2 | + | ||
| 3 | +#include <flutter_linux/flutter_linux.h> | ||
| 4 | +#ifdef GDK_WINDOWING_X11 | ||
| 5 | +#include <gdk/gdkx.h> | ||
| 6 | +#endif | ||
| 7 | + | ||
| 8 | +#include "flutter/generated_plugin_registrant.h" | ||
| 9 | + | ||
| 10 | +struct _MyApplication { | ||
| 11 | + GtkApplication parent_instance; | ||
| 12 | + char** dart_entrypoint_arguments; | ||
| 13 | +}; | ||
| 14 | + | ||
| 15 | +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) | ||
| 16 | + | ||
| 17 | +// Implements GApplication::activate. | ||
| 18 | +static void my_application_activate(GApplication* application) { | ||
| 19 | + MyApplication* self = MY_APPLICATION(application); | ||
| 20 | + GtkWindow* window = | ||
| 21 | + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); | ||
| 22 | + | ||
| 23 | + // Use a header bar when running in GNOME as this is the common style used | ||
| 24 | + // by applications and is the setup most users will be using (e.g. Ubuntu | ||
| 25 | + // desktop). | ||
| 26 | + // If running on X and not using GNOME then just use a traditional title bar | ||
| 27 | + // in case the window manager does more exotic layout, e.g. tiling. | ||
| 28 | + // If running on Wayland assume the header bar will work (may need changing | ||
| 29 | + // if future cases occur). | ||
| 30 | + gboolean use_header_bar = TRUE; | ||
| 31 | +#ifdef GDK_WINDOWING_X11 | ||
| 32 | + GdkScreen* screen = gtk_window_get_screen(window); | ||
| 33 | + if (GDK_IS_X11_SCREEN(screen)) { | ||
| 34 | + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); | ||
| 35 | + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { | ||
| 36 | + use_header_bar = FALSE; | ||
| 37 | + } | ||
| 38 | + } | ||
| 39 | +#endif | ||
| 40 | + if (use_header_bar) { | ||
| 41 | + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); | ||
| 42 | + gtk_widget_show(GTK_WIDGET(header_bar)); | ||
| 43 | + gtk_header_bar_set_title(header_bar, "sherpa_onnx"); | ||
| 44 | + gtk_header_bar_set_show_close_button(header_bar, TRUE); | ||
| 45 | + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); | ||
| 46 | + } else { | ||
| 47 | + gtk_window_set_title(window, "sherpa_onnx"); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + gtk_window_set_default_size(window, 1280, 720); | ||
| 51 | + gtk_widget_show(GTK_WIDGET(window)); | ||
| 52 | + | ||
| 53 | + g_autoptr(FlDartProject) project = fl_dart_project_new(); | ||
| 54 | + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); | ||
| 55 | + | ||
| 56 | + FlView* view = fl_view_new(project); | ||
| 57 | + gtk_widget_show(GTK_WIDGET(view)); | ||
| 58 | + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); | ||
| 59 | + | ||
| 60 | + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); | ||
| 61 | + | ||
| 62 | + gtk_widget_grab_focus(GTK_WIDGET(view)); | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +// Implements GApplication::local_command_line. | ||
| 66 | +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { | ||
| 67 | + MyApplication* self = MY_APPLICATION(application); | ||
| 68 | + // Strip out the first argument as it is the binary name. | ||
| 69 | + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); | ||
| 70 | + | ||
| 71 | + g_autoptr(GError) error = nullptr; | ||
| 72 | + if (!g_application_register(application, nullptr, &error)) { | ||
| 73 | + g_warning("Failed to register: %s", error->message); | ||
| 74 | + *exit_status = 1; | ||
| 75 | + return TRUE; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + g_application_activate(application); | ||
| 79 | + *exit_status = 0; | ||
| 80 | + | ||
| 81 | + return TRUE; | ||
| 82 | +} | ||
| 83 | + | ||
| 84 | +// Implements GApplication::startup. | ||
| 85 | +static void my_application_startup(GApplication* application) { | ||
| 86 | + //MyApplication* self = MY_APPLICATION(object); | ||
| 87 | + | ||
| 88 | + // Perform any actions required at application startup. | ||
| 89 | + | ||
| 90 | + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); | ||
| 91 | +} | ||
| 92 | + | ||
| 93 | +// Implements GApplication::shutdown. | ||
| 94 | +static void my_application_shutdown(GApplication* application) { | ||
| 95 | + //MyApplication* self = MY_APPLICATION(object); | ||
| 96 | + | ||
| 97 | + // Perform any actions required at application shutdown. | ||
| 98 | + | ||
| 99 | + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +// Implements GObject::dispose. | ||
| 103 | +static void my_application_dispose(GObject* object) { | ||
| 104 | + MyApplication* self = MY_APPLICATION(object); | ||
| 105 | + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); | ||
| 106 | + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); | ||
| 107 | +} | ||
| 108 | + | ||
| 109 | +static void my_application_class_init(MyApplicationClass* klass) { | ||
| 110 | + G_APPLICATION_CLASS(klass)->activate = my_application_activate; | ||
| 111 | + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; | ||
| 112 | + G_APPLICATION_CLASS(klass)->startup = my_application_startup; | ||
| 113 | + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; | ||
| 114 | + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; | ||
| 115 | +} | ||
| 116 | + | ||
| 117 | +static void my_application_init(MyApplication* self) {} | ||
| 118 | + | ||
| 119 | +MyApplication* my_application_new() { | ||
| 120 | + return MY_APPLICATION(g_object_new(my_application_get_type(), | ||
| 121 | + "application-id", APPLICATION_ID, | ||
| 122 | + "flags", G_APPLICATION_NON_UNIQUE, | ||
| 123 | + nullptr)); | ||
| 124 | +} |
| 1 | +#ifndef FLUTTER_MY_APPLICATION_H_ | ||
| 2 | +#define FLUTTER_MY_APPLICATION_H_ | ||
| 3 | + | ||
| 4 | +#include <gtk/gtk.h> | ||
| 5 | + | ||
| 6 | +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, | ||
| 7 | + GtkApplication) | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * my_application_new: | ||
| 11 | + * | ||
| 12 | + * Creates a new Flutter-based application. | ||
| 13 | + * | ||
| 14 | + * Returns: a new #MyApplication. | ||
| 15 | + */ | ||
| 16 | +MyApplication* my_application_new(); | ||
| 17 | + | ||
| 18 | +#endif // FLUTTER_MY_APPLICATION_H_ |
| 1 | -platform :osx, '10.14' | 1 | +platform :osx, '10.15' |
| 2 | 2 | ||
| 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. |
| 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' | 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' |
| @@ -557,7 +557,7 @@ | @@ -557,7 +557,7 @@ | ||
| 557 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | 557 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
| 558 | GCC_WARN_UNUSED_FUNCTION = YES; | 558 | GCC_WARN_UNUSED_FUNCTION = YES; |
| 559 | GCC_WARN_UNUSED_VARIABLE = YES; | 559 | GCC_WARN_UNUSED_VARIABLE = YES; |
| 560 | - MACOSX_DEPLOYMENT_TARGET = 10.14; | 560 | + MACOSX_DEPLOYMENT_TARGET = 10.15; |
| 561 | MTL_ENABLE_DEBUG_INFO = NO; | 561 | MTL_ENABLE_DEBUG_INFO = NO; |
| 562 | SDKROOT = macosx; | 562 | SDKROOT = macosx; |
| 563 | SWIFT_COMPILATION_MODE = wholemodule; | 563 | SWIFT_COMPILATION_MODE = wholemodule; |
| @@ -639,7 +639,7 @@ | @@ -639,7 +639,7 @@ | ||
| 639 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | 639 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
| 640 | GCC_WARN_UNUSED_FUNCTION = YES; | 640 | GCC_WARN_UNUSED_FUNCTION = YES; |
| 641 | GCC_WARN_UNUSED_VARIABLE = YES; | 641 | GCC_WARN_UNUSED_VARIABLE = YES; |
| 642 | - MACOSX_DEPLOYMENT_TARGET = 10.14; | 642 | + MACOSX_DEPLOYMENT_TARGET = 10.15; |
| 643 | MTL_ENABLE_DEBUG_INFO = YES; | 643 | MTL_ENABLE_DEBUG_INFO = YES; |
| 644 | ONLY_ACTIVE_ARCH = YES; | 644 | ONLY_ACTIVE_ARCH = YES; |
| 645 | SDKROOT = macosx; | 645 | SDKROOT = macosx; |
| @@ -689,7 +689,7 @@ | @@ -689,7 +689,7 @@ | ||
| 689 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | 689 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
| 690 | GCC_WARN_UNUSED_FUNCTION = YES; | 690 | GCC_WARN_UNUSED_FUNCTION = YES; |
| 691 | GCC_WARN_UNUSED_VARIABLE = YES; | 691 | GCC_WARN_UNUSED_VARIABLE = YES; |
| 692 | - MACOSX_DEPLOYMENT_TARGET = 10.14; | 692 | + MACOSX_DEPLOYMENT_TARGET = 10.15; |
| 693 | MTL_ENABLE_DEBUG_INFO = NO; | 693 | MTL_ENABLE_DEBUG_INFO = NO; |
| 694 | SDKROOT = macosx; | 694 | SDKROOT = macosx; |
| 695 | SWIFT_COMPILATION_MODE = wholemodule; | 695 | SWIFT_COMPILATION_MODE = wholemodule; |
| @@ -11,4 +11,4 @@ PRODUCT_NAME = sherpa_onnx | @@ -11,4 +11,4 @@ PRODUCT_NAME = sherpa_onnx | ||
| 11 | PRODUCT_BUNDLE_IDENTIFIER = com.k2fsa.sherpa.onnx | 11 | PRODUCT_BUNDLE_IDENTIFIER = com.k2fsa.sherpa.onnx |
| 12 | 12 | ||
| 13 | // The copyright displayed in application information | 13 | // The copyright displayed in application information |
| 14 | -PRODUCT_COPYRIGHT = Copyright © 2024 com.k2fsa.sherpa.onnx. All rights reserved. | 14 | +PRODUCT_COPYRIGHT = Copyright © 2024 Next-gen Kaldi. All rights reserved. |
| @@ -6,6 +6,8 @@ | @@ -6,6 +6,8 @@ | ||
| 6 | <true/> | 6 | <true/> |
| 7 | <key>com.apple.security.cs.allow-jit</key> | 7 | <key>com.apple.security.cs.allow-jit</key> |
| 8 | <true/> | 8 | <true/> |
| 9 | + <key>com.apple.security.device.audio-input</key> | ||
| 10 | + <true/> | ||
| 9 | <key>com.apple.security.network.server</key> | 11 | <key>com.apple.security.network.server</key> |
| 10 | <true/> | 12 | <true/> |
| 11 | </dict> | 13 | </dict> |
| @@ -2,6 +2,8 @@ | @@ -2,6 +2,8 @@ | ||
| 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| 3 | <plist version="1.0"> | 3 | <plist version="1.0"> |
| 4 | <dict> | 4 | <dict> |
| 5 | + <key>NSMicrophoneUsageDescription</key> | ||
| 6 | + <string>Need microphone access for Next-gen kaldi to work</string> | ||
| 5 | <key>CFBundleDevelopmentRegion</key> | 7 | <key>CFBundleDevelopmentRegion</key> |
| 6 | <string>$(DEVELOPMENT_LANGUAGE)</string> | 8 | <string>$(DEVELOPMENT_LANGUAGE)</string> |
| 7 | <key>CFBundleExecutable</key> | 9 | <key>CFBundleExecutable</key> |
| @@ -32,7 +32,9 @@ dependencies: | @@ -32,7 +32,9 @@ dependencies: | ||
| 32 | sdk: flutter | 32 | sdk: flutter |
| 33 | 33 | ||
| 34 | path_provider: ^2.1.3 | 34 | path_provider: ^2.1.3 |
| 35 | - path: | 35 | + path: ^1.9.0 |
| 36 | + record: ^5.1.0 | ||
| 37 | + url_launcher: ^6.2.6 | ||
| 36 | 38 | ||
| 37 | sherpa_onnx: | 39 | sherpa_onnx: |
| 38 | # When depending on this package from a real application you should use: | 40 | # When depending on this package from a real application you should use: |
| @@ -71,8 +73,8 @@ flutter: | @@ -71,8 +73,8 @@ flutter: | ||
| 71 | # To add assets to your application, add an assets section, like this: | 73 | # To add assets to your application, add an assets section, like this: |
| 72 | assets: | 74 | assets: |
| 73 | - assets/ | 75 | - assets/ |
| 74 | - - assets/sr-data/enroll/ | ||
| 75 | - - assets/sr-data/test/ | 76 | + # - assets/sr-data/enroll/ |
| 77 | + # - assets/sr-data/test/ | ||
| 76 | # - images/a_dot_ham.jpeg | 78 | # - images/a_dot_ham.jpeg |
| 77 | 79 | ||
| 78 | # An image asset can refer to one or more resolution-specific "variants", see | 80 | # An image asset can refer to one or more resolution-specific "variants", see |
| 1 | +flutter/ephemeral/ | ||
| 2 | + | ||
| 3 | +# Visual Studio user-specific files. | ||
| 4 | +*.suo | ||
| 5 | +*.user | ||
| 6 | +*.userosscache | ||
| 7 | +*.sln.docstates | ||
| 8 | + | ||
| 9 | +# Visual Studio build-related files. | ||
| 10 | +x64/ | ||
| 11 | +x86/ | ||
| 12 | + | ||
| 13 | +# Visual Studio cache files | ||
| 14 | +# files ending in .cache can be ignored | ||
| 15 | +*.[Cc]ache | ||
| 16 | +# but keep track of directories ending in .cache | ||
| 17 | +!*.[Cc]ache/ |
| 1 | +# Project-level configuration. | ||
| 2 | +cmake_minimum_required(VERSION 3.14) | ||
| 3 | +project(sherpa_onnx LANGUAGES CXX) | ||
| 4 | + | ||
| 5 | +# The name of the executable created for the application. Change this to change | ||
| 6 | +# the on-disk name of your application. | ||
| 7 | +set(BINARY_NAME "sherpa_onnx") | ||
| 8 | + | ||
| 9 | +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent | ||
| 10 | +# versions of CMake. | ||
| 11 | +cmake_policy(VERSION 3.14...3.25) | ||
| 12 | + | ||
| 13 | +# Define build configuration option. | ||
| 14 | +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) | ||
| 15 | +if(IS_MULTICONFIG) | ||
| 16 | + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" | ||
| 17 | + CACHE STRING "" FORCE) | ||
| 18 | +else() | ||
| 19 | + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) | ||
| 20 | + set(CMAKE_BUILD_TYPE "Debug" CACHE | ||
| 21 | + STRING "Flutter build mode" FORCE) | ||
| 22 | + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS | ||
| 23 | + "Debug" "Profile" "Release") | ||
| 24 | + endif() | ||
| 25 | +endif() | ||
| 26 | +# Define settings for the Profile build mode. | ||
| 27 | +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") | ||
| 28 | +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") | ||
| 29 | +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") | ||
| 30 | +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") | ||
| 31 | + | ||
| 32 | +# Use Unicode for all projects. | ||
| 33 | +add_definitions(-DUNICODE -D_UNICODE) | ||
| 34 | + | ||
| 35 | +# Compilation settings that should be applied to most targets. | ||
| 36 | +# | ||
| 37 | +# Be cautious about adding new options here, as plugins use this function by | ||
| 38 | +# default. In most cases, you should add new options to specific targets instead | ||
| 39 | +# of modifying this function. | ||
| 40 | +function(APPLY_STANDARD_SETTINGS TARGET) | ||
| 41 | + target_compile_features(${TARGET} PUBLIC cxx_std_17) | ||
| 42 | + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") | ||
| 43 | + target_compile_options(${TARGET} PRIVATE /EHsc) | ||
| 44 | + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") | ||
| 45 | + target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>") | ||
| 46 | +endfunction() | ||
| 47 | + | ||
| 48 | +# Flutter library and tool build rules. | ||
| 49 | +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") | ||
| 50 | +add_subdirectory(${FLUTTER_MANAGED_DIR}) | ||
| 51 | + | ||
| 52 | +# Application build; see runner/CMakeLists.txt. | ||
| 53 | +add_subdirectory("runner") | ||
| 54 | + | ||
| 55 | + | ||
| 56 | +# Generated plugin build rules, which manage building the plugins and adding | ||
| 57 | +# them to the application. | ||
| 58 | +include(flutter/generated_plugins.cmake) | ||
| 59 | + | ||
| 60 | + | ||
| 61 | +# === Installation === | ||
| 62 | +# Support files are copied into place next to the executable, so that it can | ||
| 63 | +# run in place. This is done instead of making a separate bundle (as on Linux) | ||
| 64 | +# so that building and running from within Visual Studio will work. | ||
| 65 | +set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>") | ||
| 66 | +# Make the "install" step default, as it's required to run. | ||
| 67 | +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) | ||
| 68 | +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) | ||
| 69 | + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) | ||
| 70 | +endif() | ||
| 71 | + | ||
| 72 | +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") | ||
| 73 | +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") | ||
| 74 | + | ||
| 75 | +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" | ||
| 76 | + COMPONENT Runtime) | ||
| 77 | + | ||
| 78 | +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" | ||
| 79 | + COMPONENT Runtime) | ||
| 80 | + | ||
| 81 | +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 82 | + COMPONENT Runtime) | ||
| 83 | + | ||
| 84 | +if(PLUGIN_BUNDLED_LIBRARIES) | ||
| 85 | + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" | ||
| 86 | + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 87 | + COMPONENT Runtime) | ||
| 88 | +endif() | ||
| 89 | + | ||
| 90 | +# Copy the native assets provided by the build.dart from all packages. | ||
| 91 | +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") | ||
| 92 | +install(DIRECTORY "${NATIVE_ASSETS_DIR}" | ||
| 93 | + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 94 | + COMPONENT Runtime) | ||
| 95 | + | ||
| 96 | +# Fully re-copy the assets directory on each build to avoid having stale files | ||
| 97 | +# from a previous install. | ||
| 98 | +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") | ||
| 99 | +install(CODE " | ||
| 100 | + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") | ||
| 101 | + " COMPONENT Runtime) | ||
| 102 | +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" | ||
| 103 | + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) | ||
| 104 | + | ||
| 105 | +# Install the AOT library on non-Debug builds only. | ||
| 106 | +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" | ||
| 107 | + CONFIGURATIONS Profile;Release | ||
| 108 | + COMPONENT Runtime) |
| 1 | +# This file controls Flutter-level build steps. It should not be edited. | ||
| 2 | +cmake_minimum_required(VERSION 3.14) | ||
| 3 | + | ||
| 4 | +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") | ||
| 5 | + | ||
| 6 | +# Configuration provided via flutter tool. | ||
| 7 | +include(${EPHEMERAL_DIR}/generated_config.cmake) | ||
| 8 | + | ||
| 9 | +# TODO: Move the rest of this into files in ephemeral. See | ||
| 10 | +# https://github.com/flutter/flutter/issues/57146. | ||
| 11 | +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") | ||
| 12 | + | ||
| 13 | +# Set fallback configurations for older versions of the flutter tool. | ||
| 14 | +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) | ||
| 15 | + set(FLUTTER_TARGET_PLATFORM "windows-x64") | ||
| 16 | +endif() | ||
| 17 | + | ||
| 18 | +# === Flutter Library === | ||
| 19 | +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") | ||
| 20 | + | ||
| 21 | +# Published to parent scope for install step. | ||
| 22 | +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) | ||
| 23 | +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) | ||
| 24 | +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) | ||
| 25 | +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) | ||
| 26 | + | ||
| 27 | +list(APPEND FLUTTER_LIBRARY_HEADERS | ||
| 28 | + "flutter_export.h" | ||
| 29 | + "flutter_windows.h" | ||
| 30 | + "flutter_messenger.h" | ||
| 31 | + "flutter_plugin_registrar.h" | ||
| 32 | + "flutter_texture_registrar.h" | ||
| 33 | +) | ||
| 34 | +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") | ||
| 35 | +add_library(flutter INTERFACE) | ||
| 36 | +target_include_directories(flutter INTERFACE | ||
| 37 | + "${EPHEMERAL_DIR}" | ||
| 38 | +) | ||
| 39 | +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") | ||
| 40 | +add_dependencies(flutter flutter_assemble) | ||
| 41 | + | ||
| 42 | +# === Wrapper === | ||
| 43 | +list(APPEND CPP_WRAPPER_SOURCES_CORE | ||
| 44 | + "core_implementations.cc" | ||
| 45 | + "standard_codec.cc" | ||
| 46 | +) | ||
| 47 | +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") | ||
| 48 | +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN | ||
| 49 | + "plugin_registrar.cc" | ||
| 50 | +) | ||
| 51 | +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") | ||
| 52 | +list(APPEND CPP_WRAPPER_SOURCES_APP | ||
| 53 | + "flutter_engine.cc" | ||
| 54 | + "flutter_view_controller.cc" | ||
| 55 | +) | ||
| 56 | +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") | ||
| 57 | + | ||
| 58 | +# Wrapper sources needed for a plugin. | ||
| 59 | +add_library(flutter_wrapper_plugin STATIC | ||
| 60 | + ${CPP_WRAPPER_SOURCES_CORE} | ||
| 61 | + ${CPP_WRAPPER_SOURCES_PLUGIN} | ||
| 62 | +) | ||
| 63 | +apply_standard_settings(flutter_wrapper_plugin) | ||
| 64 | +set_target_properties(flutter_wrapper_plugin PROPERTIES | ||
| 65 | + POSITION_INDEPENDENT_CODE ON) | ||
| 66 | +set_target_properties(flutter_wrapper_plugin PROPERTIES | ||
| 67 | + CXX_VISIBILITY_PRESET hidden) | ||
| 68 | +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) | ||
| 69 | +target_include_directories(flutter_wrapper_plugin PUBLIC | ||
| 70 | + "${WRAPPER_ROOT}/include" | ||
| 71 | +) | ||
| 72 | +add_dependencies(flutter_wrapper_plugin flutter_assemble) | ||
| 73 | + | ||
| 74 | +# Wrapper sources needed for the runner. | ||
| 75 | +add_library(flutter_wrapper_app STATIC | ||
| 76 | + ${CPP_WRAPPER_SOURCES_CORE} | ||
| 77 | + ${CPP_WRAPPER_SOURCES_APP} | ||
| 78 | +) | ||
| 79 | +apply_standard_settings(flutter_wrapper_app) | ||
| 80 | +target_link_libraries(flutter_wrapper_app PUBLIC flutter) | ||
| 81 | +target_include_directories(flutter_wrapper_app PUBLIC | ||
| 82 | + "${WRAPPER_ROOT}/include" | ||
| 83 | +) | ||
| 84 | +add_dependencies(flutter_wrapper_app flutter_assemble) | ||
| 85 | + | ||
| 86 | +# === Flutter tool backend === | ||
| 87 | +# _phony_ is a non-existent file to force this command to run every time, | ||
| 88 | +# since currently there's no way to get a full input/output list from the | ||
| 89 | +# flutter tool. | ||
| 90 | +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") | ||
| 91 | +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) | ||
| 92 | +add_custom_command( | ||
| 93 | + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} | ||
| 94 | + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} | ||
| 95 | + ${CPP_WRAPPER_SOURCES_APP} | ||
| 96 | + ${PHONY_OUTPUT} | ||
| 97 | + COMMAND ${CMAKE_COMMAND} -E env | ||
| 98 | + ${FLUTTER_TOOL_ENVIRONMENT} | ||
| 99 | + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" | ||
| 100 | + ${FLUTTER_TARGET_PLATFORM} $<CONFIG> | ||
| 101 | + VERBATIM | ||
| 102 | +) | ||
| 103 | +add_custom_target(flutter_assemble DEPENDS | ||
| 104 | + "${FLUTTER_LIBRARY}" | ||
| 105 | + ${FLUTTER_LIBRARY_HEADERS} | ||
| 106 | + ${CPP_WRAPPER_SOURCES_CORE} | ||
| 107 | + ${CPP_WRAPPER_SOURCES_PLUGIN} | ||
| 108 | + ${CPP_WRAPPER_SOURCES_APP} | ||
| 109 | +) |
| 1 | +cmake_minimum_required(VERSION 3.14) | ||
| 2 | +project(runner LANGUAGES CXX) | ||
| 3 | + | ||
| 4 | +# Define the application target. To change its name, change BINARY_NAME in the | ||
| 5 | +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer | ||
| 6 | +# work. | ||
| 7 | +# | ||
| 8 | +# Any new source files that you add to the application should be added here. | ||
| 9 | +add_executable(${BINARY_NAME} WIN32 | ||
| 10 | + "flutter_window.cpp" | ||
| 11 | + "main.cpp" | ||
| 12 | + "utils.cpp" | ||
| 13 | + "win32_window.cpp" | ||
| 14 | + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" | ||
| 15 | + "Runner.rc" | ||
| 16 | + "runner.exe.manifest" | ||
| 17 | +) | ||
| 18 | + | ||
| 19 | +# Apply the standard set of build settings. This can be removed for applications | ||
| 20 | +# that need different build settings. | ||
| 21 | +apply_standard_settings(${BINARY_NAME}) | ||
| 22 | + | ||
| 23 | +# Add preprocessor definitions for the build version. | ||
| 24 | +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") | ||
| 25 | +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") | ||
| 26 | +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") | ||
| 27 | +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") | ||
| 28 | +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") | ||
| 29 | + | ||
| 30 | +# Disable Windows macros that collide with C++ standard library functions. | ||
| 31 | +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") | ||
| 32 | + | ||
| 33 | +# Add dependency libraries and include directories. Add any application-specific | ||
| 34 | +# dependencies here. | ||
| 35 | +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) | ||
| 36 | +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") | ||
| 37 | +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") | ||
| 38 | + | ||
| 39 | +# Run the Flutter tool portions of the build. This must not be removed. | ||
| 40 | +add_dependencies(${BINARY_NAME} flutter_assemble) |
| 1 | +// Microsoft Visual C++ generated resource script. | ||
| 2 | +// | ||
| 3 | +#pragma code_page(65001) | ||
| 4 | +#include "resource.h" | ||
| 5 | + | ||
| 6 | +#define APSTUDIO_READONLY_SYMBOLS | ||
| 7 | +///////////////////////////////////////////////////////////////////////////// | ||
| 8 | +// | ||
| 9 | +// Generated from the TEXTINCLUDE 2 resource. | ||
| 10 | +// | ||
| 11 | +#include "winres.h" | ||
| 12 | + | ||
| 13 | +///////////////////////////////////////////////////////////////////////////// | ||
| 14 | +#undef APSTUDIO_READONLY_SYMBOLS | ||
| 15 | + | ||
| 16 | +///////////////////////////////////////////////////////////////////////////// | ||
| 17 | +// English (United States) resources | ||
| 18 | + | ||
| 19 | +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) | ||
| 20 | +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US | ||
| 21 | + | ||
| 22 | +#ifdef APSTUDIO_INVOKED | ||
| 23 | +///////////////////////////////////////////////////////////////////////////// | ||
| 24 | +// | ||
| 25 | +// TEXTINCLUDE | ||
| 26 | +// | ||
| 27 | + | ||
| 28 | +1 TEXTINCLUDE | ||
| 29 | +BEGIN | ||
| 30 | + "resource.h\0" | ||
| 31 | +END | ||
| 32 | + | ||
| 33 | +2 TEXTINCLUDE | ||
| 34 | +BEGIN | ||
| 35 | + "#include ""winres.h""\r\n" | ||
| 36 | + "\0" | ||
| 37 | +END | ||
| 38 | + | ||
| 39 | +3 TEXTINCLUDE | ||
| 40 | +BEGIN | ||
| 41 | + "\r\n" | ||
| 42 | + "\0" | ||
| 43 | +END | ||
| 44 | + | ||
| 45 | +#endif // APSTUDIO_INVOKED | ||
| 46 | + | ||
| 47 | + | ||
| 48 | +///////////////////////////////////////////////////////////////////////////// | ||
| 49 | +// | ||
| 50 | +// Icon | ||
| 51 | +// | ||
| 52 | + | ||
| 53 | +// Icon with lowest ID value placed first to ensure application icon | ||
| 54 | +// remains consistent on all systems. | ||
| 55 | +IDI_APP_ICON ICON "resources\\app_icon.ico" | ||
| 56 | + | ||
| 57 | + | ||
| 58 | +///////////////////////////////////////////////////////////////////////////// | ||
| 59 | +// | ||
| 60 | +// Version | ||
| 61 | +// | ||
| 62 | + | ||
| 63 | +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) | ||
| 64 | +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD | ||
| 65 | +#else | ||
| 66 | +#define VERSION_AS_NUMBER 1,0,0,0 | ||
| 67 | +#endif | ||
| 68 | + | ||
| 69 | +#if defined(FLUTTER_VERSION) | ||
| 70 | +#define VERSION_AS_STRING FLUTTER_VERSION | ||
| 71 | +#else | ||
| 72 | +#define VERSION_AS_STRING "1.0.0" | ||
| 73 | +#endif | ||
| 74 | + | ||
| 75 | +VS_VERSION_INFO VERSIONINFO | ||
| 76 | + FILEVERSION VERSION_AS_NUMBER | ||
| 77 | + PRODUCTVERSION VERSION_AS_NUMBER | ||
| 78 | + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK | ||
| 79 | +#ifdef _DEBUG | ||
| 80 | + FILEFLAGS VS_FF_DEBUG | ||
| 81 | +#else | ||
| 82 | + FILEFLAGS 0x0L | ||
| 83 | +#endif | ||
| 84 | + FILEOS VOS__WINDOWS32 | ||
| 85 | + FILETYPE VFT_APP | ||
| 86 | + FILESUBTYPE 0x0L | ||
| 87 | +BEGIN | ||
| 88 | + BLOCK "StringFileInfo" | ||
| 89 | + BEGIN | ||
| 90 | + BLOCK "040904e4" | ||
| 91 | + BEGIN | ||
| 92 | + VALUE "CompanyName", "Next-gen Kaldi" "\0" | ||
| 93 | + VALUE "FileDescription", "sherpa_onnx" "\0" | ||
| 94 | + VALUE "FileVersion", VERSION_AS_STRING "\0" | ||
| 95 | + VALUE "InternalName", "sherpa_onnx" "\0" | ||
| 96 | + VALUE "LegalCopyright", "Copyright (C) 2024 Next-gen Kaldi. All rights reserved." "\0" | ||
| 97 | + VALUE "OriginalFilename", "sherpa_onnx.exe" "\0" | ||
| 98 | + VALUE "ProductName", "sherpa_onnx" "\0" | ||
| 99 | + VALUE "ProductVersion", VERSION_AS_STRING "\0" | ||
| 100 | + END | ||
| 101 | + END | ||
| 102 | + BLOCK "VarFileInfo" | ||
| 103 | + BEGIN | ||
| 104 | + VALUE "Translation", 0x409, 1252 | ||
| 105 | + END | ||
| 106 | +END | ||
| 107 | + | ||
| 108 | +#endif // English (United States) resources | ||
| 109 | +///////////////////////////////////////////////////////////////////////////// | ||
| 110 | + | ||
| 111 | + | ||
| 112 | + | ||
| 113 | +#ifndef APSTUDIO_INVOKED | ||
| 114 | +///////////////////////////////////////////////////////////////////////////// | ||
| 115 | +// | ||
| 116 | +// Generated from the TEXTINCLUDE 3 resource. | ||
| 117 | +// | ||
| 118 | + | ||
| 119 | + | ||
| 120 | +///////////////////////////////////////////////////////////////////////////// | ||
| 121 | +#endif // not APSTUDIO_INVOKED |
| 1 | +#include "flutter_window.h" | ||
| 2 | + | ||
| 3 | +#include <optional> | ||
| 4 | + | ||
| 5 | +#include "flutter/generated_plugin_registrant.h" | ||
| 6 | + | ||
| 7 | +FlutterWindow::FlutterWindow(const flutter::DartProject& project) | ||
| 8 | + : project_(project) {} | ||
| 9 | + | ||
| 10 | +FlutterWindow::~FlutterWindow() {} | ||
| 11 | + | ||
| 12 | +bool FlutterWindow::OnCreate() { | ||
| 13 | + if (!Win32Window::OnCreate()) { | ||
| 14 | + return false; | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + RECT frame = GetClientArea(); | ||
| 18 | + | ||
| 19 | + // The size here must match the window dimensions to avoid unnecessary surface | ||
| 20 | + // creation / destruction in the startup path. | ||
| 21 | + flutter_controller_ = std::make_unique<flutter::FlutterViewController>( | ||
| 22 | + frame.right - frame.left, frame.bottom - frame.top, project_); | ||
| 23 | + // Ensure that basic setup of the controller was successful. | ||
| 24 | + if (!flutter_controller_->engine() || !flutter_controller_->view()) { | ||
| 25 | + return false; | ||
| 26 | + } | ||
| 27 | + RegisterPlugins(flutter_controller_->engine()); | ||
| 28 | + SetChildContent(flutter_controller_->view()->GetNativeWindow()); | ||
| 29 | + | ||
| 30 | + flutter_controller_->engine()->SetNextFrameCallback([&]() { | ||
| 31 | + this->Show(); | ||
| 32 | + }); | ||
| 33 | + | ||
| 34 | + // Flutter can complete the first frame before the "show window" callback is | ||
| 35 | + // registered. The following call ensures a frame is pending to ensure the | ||
| 36 | + // window is shown. It is a no-op if the first frame hasn't completed yet. | ||
| 37 | + flutter_controller_->ForceRedraw(); | ||
| 38 | + | ||
| 39 | + return true; | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +void FlutterWindow::OnDestroy() { | ||
| 43 | + if (flutter_controller_) { | ||
| 44 | + flutter_controller_ = nullptr; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + Win32Window::OnDestroy(); | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +LRESULT | ||
| 51 | +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, | ||
| 52 | + WPARAM const wparam, | ||
| 53 | + LPARAM const lparam) noexcept { | ||
| 54 | + // Give Flutter, including plugins, an opportunity to handle window messages. | ||
| 55 | + if (flutter_controller_) { | ||
| 56 | + std::optional<LRESULT> result = | ||
| 57 | + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, | ||
| 58 | + lparam); | ||
| 59 | + if (result) { | ||
| 60 | + return *result; | ||
| 61 | + } | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + switch (message) { | ||
| 65 | + case WM_FONTCHANGE: | ||
| 66 | + flutter_controller_->engine()->ReloadSystemFonts(); | ||
| 67 | + break; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); | ||
| 71 | +} |
| 1 | +#ifndef RUNNER_FLUTTER_WINDOW_H_ | ||
| 2 | +#define RUNNER_FLUTTER_WINDOW_H_ | ||
| 3 | + | ||
| 4 | +#include <flutter/dart_project.h> | ||
| 5 | +#include <flutter/flutter_view_controller.h> | ||
| 6 | + | ||
| 7 | +#include <memory> | ||
| 8 | + | ||
| 9 | +#include "win32_window.h" | ||
| 10 | + | ||
| 11 | +// A window that does nothing but host a Flutter view. | ||
| 12 | +class FlutterWindow : public Win32Window { | ||
| 13 | + public: | ||
| 14 | + // Creates a new FlutterWindow hosting a Flutter view running |project|. | ||
| 15 | + explicit FlutterWindow(const flutter::DartProject& project); | ||
| 16 | + virtual ~FlutterWindow(); | ||
| 17 | + | ||
| 18 | + protected: | ||
| 19 | + // Win32Window: | ||
| 20 | + bool OnCreate() override; | ||
| 21 | + void OnDestroy() override; | ||
| 22 | + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, | ||
| 23 | + LPARAM const lparam) noexcept override; | ||
| 24 | + | ||
| 25 | + private: | ||
| 26 | + // The project to run. | ||
| 27 | + flutter::DartProject project_; | ||
| 28 | + | ||
| 29 | + // The Flutter instance hosted by this window. | ||
| 30 | + std::unique_ptr<flutter::FlutterViewController> flutter_controller_; | ||
| 31 | +}; | ||
| 32 | + | ||
| 33 | +#endif // RUNNER_FLUTTER_WINDOW_H_ |
| 1 | +#include <flutter/dart_project.h> | ||
| 2 | +#include <flutter/flutter_view_controller.h> | ||
| 3 | +#include <windows.h> | ||
| 4 | + | ||
| 5 | +#include "flutter_window.h" | ||
| 6 | +#include "utils.h" | ||
| 7 | + | ||
| 8 | +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, | ||
| 9 | + _In_ wchar_t *command_line, _In_ int show_command) { | ||
| 10 | + // Attach to console when present (e.g., 'flutter run') or create a | ||
| 11 | + // new console when running with a debugger. | ||
| 12 | + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { | ||
| 13 | + CreateAndAttachConsole(); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + // Initialize COM, so that it is available for use in the library and/or | ||
| 17 | + // plugins. | ||
| 18 | + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); | ||
| 19 | + | ||
| 20 | + flutter::DartProject project(L"data"); | ||
| 21 | + | ||
| 22 | + std::vector<std::string> command_line_arguments = | ||
| 23 | + GetCommandLineArguments(); | ||
| 24 | + | ||
| 25 | + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); | ||
| 26 | + | ||
| 27 | + FlutterWindow window(project); | ||
| 28 | + Win32Window::Point origin(10, 10); | ||
| 29 | + Win32Window::Size size(1280, 720); | ||
| 30 | + if (!window.Create(L"sherpa_onnx", origin, size)) { | ||
| 31 | + return EXIT_FAILURE; | ||
| 32 | + } | ||
| 33 | + window.SetQuitOnClose(true); | ||
| 34 | + | ||
| 35 | + ::MSG msg; | ||
| 36 | + while (::GetMessage(&msg, nullptr, 0, 0)) { | ||
| 37 | + ::TranslateMessage(&msg); | ||
| 38 | + ::DispatchMessage(&msg); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + ::CoUninitialize(); | ||
| 42 | + return EXIT_SUCCESS; | ||
| 43 | +} |
| 1 | +//{{NO_DEPENDENCIES}} | ||
| 2 | +// Microsoft Visual C++ generated include file. | ||
| 3 | +// Used by Runner.rc | ||
| 4 | +// | ||
| 5 | +#define IDI_APP_ICON 101 | ||
| 6 | + | ||
| 7 | +// Next default values for new objects | ||
| 8 | +// | ||
| 9 | +#ifdef APSTUDIO_INVOKED | ||
| 10 | +#ifndef APSTUDIO_READONLY_SYMBOLS | ||
| 11 | +#define _APS_NEXT_RESOURCE_VALUE 102 | ||
| 12 | +#define _APS_NEXT_COMMAND_VALUE 40001 | ||
| 13 | +#define _APS_NEXT_CONTROL_VALUE 1001 | ||
| 14 | +#define _APS_NEXT_SYMED_VALUE 101 | ||
| 15 | +#endif | ||
| 16 | +#endif |
不能预览此文件类型
| 1 | +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
| 2 | +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> | ||
| 3 | + <application xmlns="urn:schemas-microsoft-com:asm.v3"> | ||
| 4 | + <windowsSettings> | ||
| 5 | + <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness> | ||
| 6 | + </windowsSettings> | ||
| 7 | + </application> | ||
| 8 | + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> | ||
| 9 | + <application> | ||
| 10 | + <!-- Windows 10 and Windows 11 --> | ||
| 11 | + <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> | ||
| 12 | + <!-- Windows 8.1 --> | ||
| 13 | + <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> | ||
| 14 | + <!-- Windows 8 --> | ||
| 15 | + <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> | ||
| 16 | + <!-- Windows 7 --> | ||
| 17 | + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> | ||
| 18 | + </application> | ||
| 19 | + </compatibility> | ||
| 20 | +</assembly> |
| 1 | +#include "utils.h" | ||
| 2 | + | ||
| 3 | +#include <flutter_windows.h> | ||
| 4 | +#include <io.h> | ||
| 5 | +#include <stdio.h> | ||
| 6 | +#include <windows.h> | ||
| 7 | + | ||
| 8 | +#include <iostream> | ||
| 9 | + | ||
| 10 | +void CreateAndAttachConsole() { | ||
| 11 | + if (::AllocConsole()) { | ||
| 12 | + FILE *unused; | ||
| 13 | + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { | ||
| 14 | + _dup2(_fileno(stdout), 1); | ||
| 15 | + } | ||
| 16 | + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { | ||
| 17 | + _dup2(_fileno(stdout), 2); | ||
| 18 | + } | ||
| 19 | + std::ios::sync_with_stdio(); | ||
| 20 | + FlutterDesktopResyncOutputStreams(); | ||
| 21 | + } | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +std::vector<std::string> GetCommandLineArguments() { | ||
| 25 | + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. | ||
| 26 | + int argc; | ||
| 27 | + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); | ||
| 28 | + if (argv == nullptr) { | ||
| 29 | + return std::vector<std::string>(); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + std::vector<std::string> command_line_arguments; | ||
| 33 | + | ||
| 34 | + // Skip the first argument as it's the binary name. | ||
| 35 | + for (int i = 1; i < argc; i++) { | ||
| 36 | + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + ::LocalFree(argv); | ||
| 40 | + | ||
| 41 | + return command_line_arguments; | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +std::string Utf8FromUtf16(const wchar_t* utf16_string) { | ||
| 45 | + if (utf16_string == nullptr) { | ||
| 46 | + return std::string(); | ||
| 47 | + } | ||
| 48 | + unsigned int target_length = ::WideCharToMultiByte( | ||
| 49 | + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, | ||
| 50 | + -1, nullptr, 0, nullptr, nullptr) | ||
| 51 | + -1; // remove the trailing null character | ||
| 52 | + int input_length = (int)wcslen(utf16_string); | ||
| 53 | + std::string utf8_string; | ||
| 54 | + if (target_length == 0 || target_length > utf8_string.max_size()) { | ||
| 55 | + return utf8_string; | ||
| 56 | + } | ||
| 57 | + utf8_string.resize(target_length); | ||
| 58 | + int converted_length = ::WideCharToMultiByte( | ||
| 59 | + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, | ||
| 60 | + input_length, utf8_string.data(), target_length, nullptr, nullptr); | ||
| 61 | + if (converted_length == 0) { | ||
| 62 | + return std::string(); | ||
| 63 | + } | ||
| 64 | + return utf8_string; | ||
| 65 | +} |
| 1 | +#ifndef RUNNER_UTILS_H_ | ||
| 2 | +#define RUNNER_UTILS_H_ | ||
| 3 | + | ||
| 4 | +#include <string> | ||
| 5 | +#include <vector> | ||
| 6 | + | ||
| 7 | +// Creates a console for the process, and redirects stdout and stderr to | ||
| 8 | +// it for both the runner and the Flutter library. | ||
| 9 | +void CreateAndAttachConsole(); | ||
| 10 | + | ||
| 11 | +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string | ||
| 12 | +// encoded in UTF-8. Returns an empty std::string on failure. | ||
| 13 | +std::string Utf8FromUtf16(const wchar_t* utf16_string); | ||
| 14 | + | ||
| 15 | +// Gets the command line arguments passed in as a std::vector<std::string>, | ||
| 16 | +// encoded in UTF-8. Returns an empty std::vector<std::string> on failure. | ||
| 17 | +std::vector<std::string> GetCommandLineArguments(); | ||
| 18 | + | ||
| 19 | +#endif // RUNNER_UTILS_H_ |
| 1 | +#include "win32_window.h" | ||
| 2 | + | ||
| 3 | +#include <dwmapi.h> | ||
| 4 | +#include <flutter_windows.h> | ||
| 5 | + | ||
| 6 | +#include "resource.h" | ||
| 7 | + | ||
| 8 | +namespace { | ||
| 9 | + | ||
| 10 | +/// Window attribute that enables dark mode window decorations. | ||
| 11 | +/// | ||
| 12 | +/// Redefined in case the developer's machine has a Windows SDK older than | ||
| 13 | +/// version 10.0.22000.0. | ||
| 14 | +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute | ||
| 15 | +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE | ||
| 16 | +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 | ||
| 17 | +#endif | ||
| 18 | + | ||
| 19 | +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; | ||
| 20 | + | ||
| 21 | +/// Registry key for app theme preference. | ||
| 22 | +/// | ||
| 23 | +/// A value of 0 indicates apps should use dark mode. A non-zero or missing | ||
| 24 | +/// value indicates apps should use light mode. | ||
| 25 | +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = | ||
| 26 | + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; | ||
| 27 | +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; | ||
| 28 | + | ||
| 29 | +// The number of Win32Window objects that currently exist. | ||
| 30 | +static int g_active_window_count = 0; | ||
| 31 | + | ||
| 32 | +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); | ||
| 33 | + | ||
| 34 | +// Scale helper to convert logical scaler values to physical using passed in | ||
| 35 | +// scale factor | ||
| 36 | +int Scale(int source, double scale_factor) { | ||
| 37 | + return static_cast<int>(source * scale_factor); | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. | ||
| 41 | +// This API is only needed for PerMonitor V1 awareness mode. | ||
| 42 | +void EnableFullDpiSupportIfAvailable(HWND hwnd) { | ||
| 43 | + HMODULE user32_module = LoadLibraryA("User32.dll"); | ||
| 44 | + if (!user32_module) { | ||
| 45 | + return; | ||
| 46 | + } | ||
| 47 | + auto enable_non_client_dpi_scaling = | ||
| 48 | + reinterpret_cast<EnableNonClientDpiScaling*>( | ||
| 49 | + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); | ||
| 50 | + if (enable_non_client_dpi_scaling != nullptr) { | ||
| 51 | + enable_non_client_dpi_scaling(hwnd); | ||
| 52 | + } | ||
| 53 | + FreeLibrary(user32_module); | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +} // namespace | ||
| 57 | + | ||
| 58 | +// Manages the Win32Window's window class registration. | ||
| 59 | +class WindowClassRegistrar { | ||
| 60 | + public: | ||
| 61 | + ~WindowClassRegistrar() = default; | ||
| 62 | + | ||
| 63 | + // Returns the singleton registrar instance. | ||
| 64 | + static WindowClassRegistrar* GetInstance() { | ||
| 65 | + if (!instance_) { | ||
| 66 | + instance_ = new WindowClassRegistrar(); | ||
| 67 | + } | ||
| 68 | + return instance_; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + // Returns the name of the window class, registering the class if it hasn't | ||
| 72 | + // previously been registered. | ||
| 73 | + const wchar_t* GetWindowClass(); | ||
| 74 | + | ||
| 75 | + // Unregisters the window class. Should only be called if there are no | ||
| 76 | + // instances of the window. | ||
| 77 | + void UnregisterWindowClass(); | ||
| 78 | + | ||
| 79 | + private: | ||
| 80 | + WindowClassRegistrar() = default; | ||
| 81 | + | ||
| 82 | + static WindowClassRegistrar* instance_; | ||
| 83 | + | ||
| 84 | + bool class_registered_ = false; | ||
| 85 | +}; | ||
| 86 | + | ||
| 87 | +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; | ||
| 88 | + | ||
| 89 | +const wchar_t* WindowClassRegistrar::GetWindowClass() { | ||
| 90 | + if (!class_registered_) { | ||
| 91 | + WNDCLASS window_class{}; | ||
| 92 | + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); | ||
| 93 | + window_class.lpszClassName = kWindowClassName; | ||
| 94 | + window_class.style = CS_HREDRAW | CS_VREDRAW; | ||
| 95 | + window_class.cbClsExtra = 0; | ||
| 96 | + window_class.cbWndExtra = 0; | ||
| 97 | + window_class.hInstance = GetModuleHandle(nullptr); | ||
| 98 | + window_class.hIcon = | ||
| 99 | + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); | ||
| 100 | + window_class.hbrBackground = 0; | ||
| 101 | + window_class.lpszMenuName = nullptr; | ||
| 102 | + window_class.lpfnWndProc = Win32Window::WndProc; | ||
| 103 | + RegisterClass(&window_class); | ||
| 104 | + class_registered_ = true; | ||
| 105 | + } | ||
| 106 | + return kWindowClassName; | ||
| 107 | +} | ||
| 108 | + | ||
| 109 | +void WindowClassRegistrar::UnregisterWindowClass() { | ||
| 110 | + UnregisterClass(kWindowClassName, nullptr); | ||
| 111 | + class_registered_ = false; | ||
| 112 | +} | ||
| 113 | + | ||
| 114 | +Win32Window::Win32Window() { | ||
| 115 | + ++g_active_window_count; | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +Win32Window::~Win32Window() { | ||
| 119 | + --g_active_window_count; | ||
| 120 | + Destroy(); | ||
| 121 | +} | ||
| 122 | + | ||
| 123 | +bool Win32Window::Create(const std::wstring& title, | ||
| 124 | + const Point& origin, | ||
| 125 | + const Size& size) { | ||
| 126 | + Destroy(); | ||
| 127 | + | ||
| 128 | + const wchar_t* window_class = | ||
| 129 | + WindowClassRegistrar::GetInstance()->GetWindowClass(); | ||
| 130 | + | ||
| 131 | + const POINT target_point = {static_cast<LONG>(origin.x), | ||
| 132 | + static_cast<LONG>(origin.y)}; | ||
| 133 | + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); | ||
| 134 | + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); | ||
| 135 | + double scale_factor = dpi / 96.0; | ||
| 136 | + | ||
| 137 | + HWND window = CreateWindow( | ||
| 138 | + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, | ||
| 139 | + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), | ||
| 140 | + Scale(size.width, scale_factor), Scale(size.height, scale_factor), | ||
| 141 | + nullptr, nullptr, GetModuleHandle(nullptr), this); | ||
| 142 | + | ||
| 143 | + if (!window) { | ||
| 144 | + return false; | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + UpdateTheme(window); | ||
| 148 | + | ||
| 149 | + return OnCreate(); | ||
| 150 | +} | ||
| 151 | + | ||
| 152 | +bool Win32Window::Show() { | ||
| 153 | + return ShowWindow(window_handle_, SW_SHOWNORMAL); | ||
| 154 | +} | ||
| 155 | + | ||
| 156 | +// static | ||
| 157 | +LRESULT CALLBACK Win32Window::WndProc(HWND const window, | ||
| 158 | + UINT const message, | ||
| 159 | + WPARAM const wparam, | ||
| 160 | + LPARAM const lparam) noexcept { | ||
| 161 | + if (message == WM_NCCREATE) { | ||
| 162 | + auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam); | ||
| 163 | + SetWindowLongPtr(window, GWLP_USERDATA, | ||
| 164 | + reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams)); | ||
| 165 | + | ||
| 166 | + auto that = static_cast<Win32Window*>(window_struct->lpCreateParams); | ||
| 167 | + EnableFullDpiSupportIfAvailable(window); | ||
| 168 | + that->window_handle_ = window; | ||
| 169 | + } else if (Win32Window* that = GetThisFromHandle(window)) { | ||
| 170 | + return that->MessageHandler(window, message, wparam, lparam); | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + return DefWindowProc(window, message, wparam, lparam); | ||
| 174 | +} | ||
| 175 | + | ||
| 176 | +LRESULT | ||
| 177 | +Win32Window::MessageHandler(HWND hwnd, | ||
| 178 | + UINT const message, | ||
| 179 | + WPARAM const wparam, | ||
| 180 | + LPARAM const lparam) noexcept { | ||
| 181 | + switch (message) { | ||
| 182 | + case WM_DESTROY: | ||
| 183 | + window_handle_ = nullptr; | ||
| 184 | + Destroy(); | ||
| 185 | + if (quit_on_close_) { | ||
| 186 | + PostQuitMessage(0); | ||
| 187 | + } | ||
| 188 | + return 0; | ||
| 189 | + | ||
| 190 | + case WM_DPICHANGED: { | ||
| 191 | + auto newRectSize = reinterpret_cast<RECT*>(lparam); | ||
| 192 | + LONG newWidth = newRectSize->right - newRectSize->left; | ||
| 193 | + LONG newHeight = newRectSize->bottom - newRectSize->top; | ||
| 194 | + | ||
| 195 | + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, | ||
| 196 | + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); | ||
| 197 | + | ||
| 198 | + return 0; | ||
| 199 | + } | ||
| 200 | + case WM_SIZE: { | ||
| 201 | + RECT rect = GetClientArea(); | ||
| 202 | + if (child_content_ != nullptr) { | ||
| 203 | + // Size and position the child window. | ||
| 204 | + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, | ||
| 205 | + rect.bottom - rect.top, TRUE); | ||
| 206 | + } | ||
| 207 | + return 0; | ||
| 208 | + } | ||
| 209 | + | ||
| 210 | + case WM_ACTIVATE: | ||
| 211 | + if (child_content_ != nullptr) { | ||
| 212 | + SetFocus(child_content_); | ||
| 213 | + } | ||
| 214 | + return 0; | ||
| 215 | + | ||
| 216 | + case WM_DWMCOLORIZATIONCOLORCHANGED: | ||
| 217 | + UpdateTheme(hwnd); | ||
| 218 | + return 0; | ||
| 219 | + } | ||
| 220 | + | ||
| 221 | + return DefWindowProc(window_handle_, message, wparam, lparam); | ||
| 222 | +} | ||
| 223 | + | ||
| 224 | +void Win32Window::Destroy() { | ||
| 225 | + OnDestroy(); | ||
| 226 | + | ||
| 227 | + if (window_handle_) { | ||
| 228 | + DestroyWindow(window_handle_); | ||
| 229 | + window_handle_ = nullptr; | ||
| 230 | + } | ||
| 231 | + if (g_active_window_count == 0) { | ||
| 232 | + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); | ||
| 233 | + } | ||
| 234 | +} | ||
| 235 | + | ||
| 236 | +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { | ||
| 237 | + return reinterpret_cast<Win32Window*>( | ||
| 238 | + GetWindowLongPtr(window, GWLP_USERDATA)); | ||
| 239 | +} | ||
| 240 | + | ||
| 241 | +void Win32Window::SetChildContent(HWND content) { | ||
| 242 | + child_content_ = content; | ||
| 243 | + SetParent(content, window_handle_); | ||
| 244 | + RECT frame = GetClientArea(); | ||
| 245 | + | ||
| 246 | + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, | ||
| 247 | + frame.bottom - frame.top, true); | ||
| 248 | + | ||
| 249 | + SetFocus(child_content_); | ||
| 250 | +} | ||
| 251 | + | ||
| 252 | +RECT Win32Window::GetClientArea() { | ||
| 253 | + RECT frame; | ||
| 254 | + GetClientRect(window_handle_, &frame); | ||
| 255 | + return frame; | ||
| 256 | +} | ||
| 257 | + | ||
| 258 | +HWND Win32Window::GetHandle() { | ||
| 259 | + return window_handle_; | ||
| 260 | +} | ||
| 261 | + | ||
| 262 | +void Win32Window::SetQuitOnClose(bool quit_on_close) { | ||
| 263 | + quit_on_close_ = quit_on_close; | ||
| 264 | +} | ||
| 265 | + | ||
| 266 | +bool Win32Window::OnCreate() { | ||
| 267 | + // No-op; provided for subclasses. | ||
| 268 | + return true; | ||
| 269 | +} | ||
| 270 | + | ||
| 271 | +void Win32Window::OnDestroy() { | ||
| 272 | + // No-op; provided for subclasses. | ||
| 273 | +} | ||
| 274 | + | ||
| 275 | +void Win32Window::UpdateTheme(HWND const window) { | ||
| 276 | + DWORD light_mode; | ||
| 277 | + DWORD light_mode_size = sizeof(light_mode); | ||
| 278 | + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, | ||
| 279 | + kGetPreferredBrightnessRegValue, | ||
| 280 | + RRF_RT_REG_DWORD, nullptr, &light_mode, | ||
| 281 | + &light_mode_size); | ||
| 282 | + | ||
| 283 | + if (result == ERROR_SUCCESS) { | ||
| 284 | + BOOL enable_dark_mode = light_mode == 0; | ||
| 285 | + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, | ||
| 286 | + &enable_dark_mode, sizeof(enable_dark_mode)); | ||
| 287 | + } | ||
| 288 | +} |
| 1 | +#ifndef RUNNER_WIN32_WINDOW_H_ | ||
| 2 | +#define RUNNER_WIN32_WINDOW_H_ | ||
| 3 | + | ||
| 4 | +#include <windows.h> | ||
| 5 | + | ||
| 6 | +#include <functional> | ||
| 7 | +#include <memory> | ||
| 8 | +#include <string> | ||
| 9 | + | ||
| 10 | +// A class abstraction for a high DPI-aware Win32 Window. Intended to be | ||
| 11 | +// inherited from by classes that wish to specialize with custom | ||
| 12 | +// rendering and input handling | ||
| 13 | +class Win32Window { | ||
| 14 | + public: | ||
| 15 | + struct Point { | ||
| 16 | + unsigned int x; | ||
| 17 | + unsigned int y; | ||
| 18 | + Point(unsigned int x, unsigned int y) : x(x), y(y) {} | ||
| 19 | + }; | ||
| 20 | + | ||
| 21 | + struct Size { | ||
| 22 | + unsigned int width; | ||
| 23 | + unsigned int height; | ||
| 24 | + Size(unsigned int width, unsigned int height) | ||
| 25 | + : width(width), height(height) {} | ||
| 26 | + }; | ||
| 27 | + | ||
| 28 | + Win32Window(); | ||
| 29 | + virtual ~Win32Window(); | ||
| 30 | + | ||
| 31 | + // Creates a win32 window with |title| that is positioned and sized using | ||
| 32 | + // |origin| and |size|. New windows are created on the default monitor. Window | ||
| 33 | + // sizes are specified to the OS in physical pixels, hence to ensure a | ||
| 34 | + // consistent size this function will scale the inputted width and height as | ||
| 35 | + // as appropriate for the default monitor. The window is invisible until | ||
| 36 | + // |Show| is called. Returns true if the window was created successfully. | ||
| 37 | + bool Create(const std::wstring& title, const Point& origin, const Size& size); | ||
| 38 | + | ||
| 39 | + // Show the current window. Returns true if the window was successfully shown. | ||
| 40 | + bool Show(); | ||
| 41 | + | ||
| 42 | + // Release OS resources associated with window. | ||
| 43 | + void Destroy(); | ||
| 44 | + | ||
| 45 | + // Inserts |content| into the window tree. | ||
| 46 | + void SetChildContent(HWND content); | ||
| 47 | + | ||
| 48 | + // Returns the backing Window handle to enable clients to set icon and other | ||
| 49 | + // window properties. Returns nullptr if the window has been destroyed. | ||
| 50 | + HWND GetHandle(); | ||
| 51 | + | ||
| 52 | + // If true, closing this window will quit the application. | ||
| 53 | + void SetQuitOnClose(bool quit_on_close); | ||
| 54 | + | ||
| 55 | + // Return a RECT representing the bounds of the current client area. | ||
| 56 | + RECT GetClientArea(); | ||
| 57 | + | ||
| 58 | + protected: | ||
| 59 | + // Processes and route salient window messages for mouse handling, | ||
| 60 | + // size change and DPI. Delegates handling of these to member overloads that | ||
| 61 | + // inheriting classes can handle. | ||
| 62 | + virtual LRESULT MessageHandler(HWND window, | ||
| 63 | + UINT const message, | ||
| 64 | + WPARAM const wparam, | ||
| 65 | + LPARAM const lparam) noexcept; | ||
| 66 | + | ||
| 67 | + // Called when CreateAndShow is called, allowing subclass window-related | ||
| 68 | + // setup. Subclasses should return false if setup fails. | ||
| 69 | + virtual bool OnCreate(); | ||
| 70 | + | ||
| 71 | + // Called when Destroy is called. | ||
| 72 | + virtual void OnDestroy(); | ||
| 73 | + | ||
| 74 | + private: | ||
| 75 | + friend class WindowClassRegistrar; | ||
| 76 | + | ||
| 77 | + // OS callback called by message pump. Handles the WM_NCCREATE message which | ||
| 78 | + // is passed when the non-client area is being created and enables automatic | ||
| 79 | + // non-client DPI scaling so that the non-client area automatically | ||
| 80 | + // responds to changes in DPI. All other messages are handled by | ||
| 81 | + // MessageHandler. | ||
| 82 | + static LRESULT CALLBACK WndProc(HWND const window, | ||
| 83 | + UINT const message, | ||
| 84 | + WPARAM const wparam, | ||
| 85 | + LPARAM const lparam) noexcept; | ||
| 86 | + | ||
| 87 | + // Retrieves a class instance pointer for |window| | ||
| 88 | + static Win32Window* GetThisFromHandle(HWND const window) noexcept; | ||
| 89 | + | ||
| 90 | + // Update the window frame's theme to match the system theme. | ||
| 91 | + static void UpdateTheme(HWND const window); | ||
| 92 | + | ||
| 93 | + bool quit_on_close_ = false; | ||
| 94 | + | ||
| 95 | + // window handle for top level window. | ||
| 96 | + HWND window_handle_ = nullptr; | ||
| 97 | + | ||
| 98 | + // window handle for hosted content. | ||
| 99 | + HWND child_content_ = nullptr; | ||
| 100 | +}; | ||
| 101 | + | ||
| 102 | +#endif // RUNNER_WIN32_WINDOW_H_ |
| @@ -6,6 +6,7 @@ export 'src/online_stream.dart'; | @@ -6,6 +6,7 @@ export 'src/online_stream.dart'; | ||
| 6 | export 'src/speaker_identification.dart'; | 6 | export 'src/speaker_identification.dart'; |
| 7 | export 'src/vad.dart'; | 7 | export 'src/vad.dart'; |
| 8 | export 'src/wave_reader.dart'; | 8 | export 'src/wave_reader.dart'; |
| 9 | +export 'src/wave_writer.dart'; | ||
| 9 | import 'src/sherpa_onnx_bindings.dart'; | 10 | import 'src/sherpa_onnx_bindings.dart'; |
| 10 | 11 | ||
| 11 | final DynamicLibrary _dylib = () { | 12 | final DynamicLibrary _dylib = () { |
| @@ -345,6 +345,12 @@ typedef SherpaOnnxReadWaveNative = Pointer<SherpaOnnxWave> Function( | @@ -345,6 +345,12 @@ typedef SherpaOnnxReadWaveNative = Pointer<SherpaOnnxWave> Function( | ||
| 345 | 345 | ||
| 346 | typedef SherpaOnnxReadWave = SherpaOnnxReadWaveNative; | 346 | typedef SherpaOnnxReadWave = SherpaOnnxReadWaveNative; |
| 347 | 347 | ||
| 348 | +typedef SherpaOnnxWriteWaveNative = Int32 Function( | ||
| 349 | + Pointer<Float>, Int32, Int32, Pointer<Utf8>); | ||
| 350 | + | ||
| 351 | +typedef SherpaOnnxWriteWave = int Function( | ||
| 352 | + Pointer<Float>, int, int, Pointer<Utf8>); | ||
| 353 | + | ||
| 348 | typedef SherpaOnnxFreeWaveNative = Void Function(Pointer<SherpaOnnxWave>); | 354 | typedef SherpaOnnxFreeWaveNative = Void Function(Pointer<SherpaOnnxWave>); |
| 349 | 355 | ||
| 350 | typedef SherpaOnnxFreeWave = void Function(Pointer<SherpaOnnxWave>); | 356 | typedef SherpaOnnxFreeWave = void Function(Pointer<SherpaOnnxWave>); |
| @@ -448,6 +454,8 @@ class SherpaOnnxBindings { | @@ -448,6 +454,8 @@ class SherpaOnnxBindings { | ||
| 448 | 454 | ||
| 449 | static SherpaOnnxReadWave? readWave; | 455 | static SherpaOnnxReadWave? readWave; |
| 450 | 456 | ||
| 457 | + static SherpaOnnxWriteWave? writeWave; | ||
| 458 | + | ||
| 451 | static SherpaOnnxFreeWave? freeWave; | 459 | static SherpaOnnxFreeWave? freeWave; |
| 452 | 460 | ||
| 453 | static void init(DynamicLibrary dynamicLibrary) { | 461 | static void init(DynamicLibrary dynamicLibrary) { |
| @@ -686,6 +694,11 @@ class SherpaOnnxBindings { | @@ -686,6 +694,11 @@ class SherpaOnnxBindings { | ||
| 686 | .lookup<NativeFunction<SherpaOnnxReadWaveNative>>('SherpaOnnxReadWave') | 694 | .lookup<NativeFunction<SherpaOnnxReadWaveNative>>('SherpaOnnxReadWave') |
| 687 | .asFunction(); | 695 | .asFunction(); |
| 688 | 696 | ||
| 697 | + writeWave ??= dynamicLibrary | ||
| 698 | + .lookup<NativeFunction<SherpaOnnxWriteWaveNative>>( | ||
| 699 | + 'SherpaOnnxWriteWave') | ||
| 700 | + .asFunction(); | ||
| 701 | + | ||
| 689 | freeWave ??= dynamicLibrary | 702 | freeWave ??= dynamicLibrary |
| 690 | .lookup<NativeFunction<SherpaOnnxFreeWaveNative>>('SherpaOnnxFreeWave') | 703 | .lookup<NativeFunction<SherpaOnnxFreeWaveNative>>('SherpaOnnxFreeWave') |
| 691 | .asFunction(); | 704 | .asFunction(); |
| @@ -113,7 +113,7 @@ class CircularBuffer { | @@ -113,7 +113,7 @@ class CircularBuffer { | ||
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | class VoiceActivityDetector { | 115 | class VoiceActivityDetector { |
| 116 | - VoiceActivityDetector._({required this.ptr}); | 116 | + VoiceActivityDetector._({required this.ptr, required this.config}); |
| 117 | 117 | ||
| 118 | // The user has to invoke VoiceActivityDetector.free() to avoid memory leak. | 118 | // The user has to invoke VoiceActivityDetector.free() to avoid memory leak. |
| 119 | factory VoiceActivityDetector( | 119 | factory VoiceActivityDetector( |
| @@ -144,7 +144,7 @@ class VoiceActivityDetector { | @@ -144,7 +144,7 @@ class VoiceActivityDetector { | ||
| 144 | calloc.free(modelPtr); | 144 | calloc.free(modelPtr); |
| 145 | calloc.free(c); | 145 | calloc.free(c); |
| 146 | 146 | ||
| 147 | - return VoiceActivityDetector._(ptr: ptr); | 147 | + return VoiceActivityDetector._(ptr: ptr, config: config); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | void free() { | 150 | void free() { |
| @@ -210,4 +210,5 @@ class VoiceActivityDetector { | @@ -210,4 +210,5 @@ class VoiceActivityDetector { | ||
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | Pointer<SherpaOnnxVoiceActivityDetector> ptr; | 212 | Pointer<SherpaOnnxVoiceActivityDetector> ptr; |
| 213 | + final VadModelConfig config; | ||
| 213 | } | 214 | } |
sherpa-onnx/flutter/lib/src/wave_writer.dart
0 → 100644
| 1 | +// Copyright (c) 2024 Xiaomi Corporation | ||
| 2 | +import 'dart:ffi'; | ||
| 3 | +import 'dart:typed_data'; | ||
| 4 | +import 'package:ffi/ffi.dart'; | ||
| 5 | + | ||
| 6 | +import './sherpa_onnx_bindings.dart'; | ||
| 7 | + | ||
| 8 | +bool writeWave( | ||
| 9 | + {required String filename, | ||
| 10 | + required Float32List samples, | ||
| 11 | + required int sampleRate}) { | ||
| 12 | + final Pointer<Utf8> filenamePtr = filename.toNativeUtf8(); | ||
| 13 | + | ||
| 14 | + final n = samples.length; | ||
| 15 | + final Pointer<Float> p = calloc<Float>(n); | ||
| 16 | + | ||
| 17 | + final pList = p.asTypedList(n); | ||
| 18 | + pList.setAll(0, samples); | ||
| 19 | + | ||
| 20 | + int ok = | ||
| 21 | + SherpaOnnxBindings.writeWave?.call(p, n, sampleRate, filenamePtr) ?? 0; | ||
| 22 | + | ||
| 23 | + calloc.free(p); | ||
| 24 | + calloc.free(filenamePtr); | ||
| 25 | + | ||
| 26 | + return ok == 1; | ||
| 27 | +} |
sherpa-onnx/flutter/linux/CMakeLists.txt
0 → 100644
| 1 | +# The Flutter tooling requires that developers have CMake 3.10 or later | ||
| 2 | +# installed. You should not increase this version, as doing so will cause | ||
| 3 | +# the plugin to fail to compile for some customers of the plugin. | ||
| 4 | +cmake_minimum_required(VERSION 3.10) | ||
| 5 | + | ||
| 6 | +# Project-level configuration. | ||
| 7 | +set(PROJECT_NAME "sherpa_onnx") | ||
| 8 | +project(${PROJECT_NAME} LANGUAGES CXX) | ||
| 9 | + | ||
| 10 | +# Invoke the build for native code shared with the other target platforms. | ||
| 11 | +# This can be changed to accommodate different builds. | ||
| 12 | +# add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared") | ||
| 13 | + | ||
| 14 | +# List of absolute paths to libraries that should be bundled with the plugin. | ||
| 15 | +# This list could contain prebuilt libraries, or libraries created by an | ||
| 16 | +# external build triggered from this build file. | ||
| 17 | +set(sherpa_onnx_bundled_libraries | ||
| 18 | + "${CMAKE_CURRENT_SOURCE_DIR}/libsherpa-onnx-c-api.so" | ||
| 19 | + "${CMAKE_CURRENT_SOURCE_DIR}/libsherpa-onnx-core.so" | ||
| 20 | + "${CMAKE_CURRENT_SOURCE_DIR}/libkaldi-decoder-core.so" | ||
| 21 | + "${CMAKE_CURRENT_SOURCE_DIR}/libsherpa-onnx-kaldifst-core.so" | ||
| 22 | + "${CMAKE_CURRENT_SOURCE_DIR}/libsherpa-onnx-fstfar.so" | ||
| 23 | + "${CMAKE_CURRENT_SOURCE_DIR}/libsherpa-onnx-fst.so" | ||
| 24 | + "${CMAKE_CURRENT_SOURCE_DIR}/libkaldi-native-fbank-core.so" | ||
| 25 | + "${CMAKE_CURRENT_SOURCE_DIR}/libpiper_phonemize.so" | ||
| 26 | + "${CMAKE_CURRENT_SOURCE_DIR}/libespeak-ng.so" | ||
| 27 | + "${CMAKE_CURRENT_SOURCE_DIR}/libucd.so" | ||
| 28 | + "${CMAKE_CURRENT_SOURCE_DIR}/libonnxruntime.so" | ||
| 29 | + "${CMAKE_CURRENT_SOURCE_DIR}/libssentencepiece_core.so" | ||
| 30 | + PARENT_SCOPE | ||
| 31 | +) |
| @@ -39,4 +39,7 @@ flutter run --release -d macos | @@ -39,4 +39,7 @@ flutter run --release -d macos | ||
| 39 | flutter create --platforms=windows,macos,linux . | 39 | flutter create --platforms=windows,macos,linux . |
| 40 | 40 | ||
| 41 | dart analyze | 41 | dart analyze |
| 42 | + | ||
| 43 | +FLUTTER_XCODE_ARCHS=arm64 | ||
| 44 | +FLUTTER_XCODE_ARCHS=x86_64 | ||
| 42 | ``` | 45 | ``` |
| @@ -50,6 +50,10 @@ flutter: | @@ -50,6 +50,10 @@ flutter: | ||
| 50 | platforms: | 50 | platforms: |
| 51 | macos: | 51 | macos: |
| 52 | ffiPlugin: true | 52 | ffiPlugin: true |
| 53 | + windows: | ||
| 54 | + ffiPlugin: true | ||
| 55 | + linux: | ||
| 56 | + ffiPlugin: true | ||
| 53 | 57 | ||
| 54 | # To add assets to your plugin package, add an assets section, like this: | 58 | # To add assets to your plugin package, add an assets section, like this: |
| 55 | # assets: | 59 | # assets: |
sherpa-onnx/flutter/windows/CMakeLists.txt
0 → 100644
| 1 | +# The Flutter tooling requires that developers have a version of Visual Studio | ||
| 2 | +# installed that includes CMake 3.14 or later. You should not increase this | ||
| 3 | +# version, as doing so will cause the plugin to fail to compile for some | ||
| 4 | +# customers of the plugin. | ||
| 5 | +cmake_minimum_required(VERSION 3.14) | ||
| 6 | + | ||
| 7 | +# Project-level configuration. | ||
| 8 | +set(PROJECT_NAME "sherpa_onnx") | ||
| 9 | +project(${PROJECT_NAME} LANGUAGES CXX) | ||
| 10 | + | ||
| 11 | +# Invoke the build for native code shared with the other target platforms. | ||
| 12 | +# This can be changed to accommodate different builds. | ||
| 13 | +# add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared") | ||
| 14 | + | ||
| 15 | +# List of absolute paths to libraries that should be bundled with the plugin. | ||
| 16 | +# This list could contain prebuilt libraries, or libraries created by an | ||
| 17 | +# external build triggered from this build file. | ||
| 18 | +set(sherpa_onnx_bundled_libraries | ||
| 19 | + "${CMAKE_CURRENT_SOURCE_DIR}/sherpa-onnx-c-api.dll" | ||
| 20 | + "${CMAKE_CURRENT_SOURCE_DIR}/sherpa-onnx-core.dll" | ||
| 21 | + "${CMAKE_CURRENT_SOURCE_DIR}/kaldi-decoder-core.dll" | ||
| 22 | + "${CMAKE_CURRENT_SOURCE_DIR}/sherpa-onnx-kaldifst-core.lib" | ||
| 23 | + "${CMAKE_CURRENT_SOURCE_DIR}/sherpa-onnx-fstfar.lib" | ||
| 24 | + "${CMAKE_CURRENT_SOURCE_DIR}/sherpa-onnx-fst.lib" | ||
| 25 | + "${CMAKE_CURRENT_SOURCE_DIR}/kaldi-native-fbank-core.dll" | ||
| 26 | + "${CMAKE_CURRENT_SOURCE_DIR}/piper_phonemize.dll" | ||
| 27 | + "${CMAKE_CURRENT_SOURCE_DIR}/espeak-ng.dll" | ||
| 28 | + "${CMAKE_CURRENT_SOURCE_DIR}/ucd.dll" | ||
| 29 | + "${CMAKE_CURRENT_SOURCE_DIR}/onnxruntime.dll" | ||
| 30 | + "${CMAKE_CURRENT_SOURCE_DIR}/ssentencepiece_core.dll" | ||
| 31 | + PARENT_SCOPE | ||
| 32 | +) |
-
请 注册 或 登录 后发表评论