Skip to content

Commit

Permalink
flutter
Browse files Browse the repository at this point in the history
  • Loading branch information
laves committed Oct 18, 2023
1 parent 469218d commit dd21394
Show file tree
Hide file tree
Showing 14 changed files with 150 additions and 19 deletions.
7 changes: 6 additions & 1 deletion binding/flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,9 @@
* Update flutter-voice-processor

## [2.2.3] - 2023-08-24
* Update native packages
* Update native packages

## [3.0.0] - 2023-10-18
* Engine improvements
* Improved error reporting
* Added reset function
10 changes: 8 additions & 2 deletions binding/flutter/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
group 'ai.picovoice.flutter.rhino'
version '2.2.3'
version '3.0.0'

buildscript {
repositories {
google()
jcenter()
maven {
url 'https://s01.oss.sonatype.org/content/repositories/aipicovoice-1267/'
}
}

dependencies {
Expand All @@ -16,6 +19,9 @@ rootProject.allprojects {
repositories {
google()
jcenter()
maven {
url 'https://s01.oss.sonatype.org/content/repositories/aipicovoice-1267/'
}
}
}

Expand All @@ -33,5 +39,5 @@ android {
}

dependencies {
implementation 'ai.picovoice:rhino-android:2.2.2'
implementation 'ai.picovoice:rhino-android:3.0.0'
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class RhinoPlugin implements FlutterPlugin, MethodCallHandler {
private enum Method {
CREATE,
PROCESS,
RESET,
DELETE
}

Expand All @@ -43,6 +44,8 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBindin
flutterContext = flutterPluginBinding.getApplicationContext();
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "rhino");
channel.setMethodCallHandler(this);

Rhino.setSdk("flutter");
}

@Override
Expand Down Expand Up @@ -147,6 +150,28 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
null);
}
break;
case RESET:
try {
String handle = call.argument("handle");
if (!rhinoPool.containsKey(handle)) {
result.error(
RhinoInvalidStateException.class.getSimpleName(),
"Invalid rhino handle provided to native module",
null);
return;
}

Rhino rhino = rhinoPool.get(handle);
rhino.reset();

result.success(null);
} catch (RhinoException e) {
result.error(
e.getClass().getSimpleName(),
e.getMessage(),
null);
}
break;
case DELETE:
String handle = call.argument("handle");

Expand Down
23 changes: 22 additions & 1 deletion binding/flutter/ios/Classes/SwiftRhinoPlugin.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2021 Picovoice Inc.
// Copyright 2021-2023 Picovoice Inc.
//
// You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
// file accompanying this source.
Expand All @@ -16,6 +16,7 @@ import Rhino
enum Method: String {
case CREATE
case PROCESS
case RESET
case DELETE
}

Expand All @@ -27,6 +28,8 @@ public class SwiftRhinoPlugin: NSObject, FlutterPlugin {

let methodChannel = FlutterMethodChannel(name: "rhino", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(instance, channel: methodChannel)

Rhino.setSdk(sdk: "flutter")
}

public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
Expand Down Expand Up @@ -108,6 +111,24 @@ public class SwiftRhinoPlugin: NSObject, FlutterPlugin {
} catch {
result(errorToFlutterError(RhinoError(error.localizedDescription)))
}
case .RESET:
do {
if let handle = args["handle"] as? String {
if let rhino = rhinoPool[handle] {
try rhino.reset()
result(nil)
} else {
result(errorToFlutterError(
RhinoInvalidStateError("Invalid handle provided to Rhino 'reset'")))
}
} else {
result(errorToFlutterError(RhinoInvalidArgumentError("missing required arguments 'handle'")))
}
} catch let error as RhinoError {
result(errorToFlutterError(error))
} catch {
result(errorToFlutterError(RhinoError(error.localizedDescription)))
}
case .DELETE:
if let handle = args["handle"] as? String {
if let rhino = rhinoPool.removeValue(forKey: handle) {
Expand Down
4 changes: 2 additions & 2 deletions binding/flutter/ios/rhino_flutter.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'rhino_flutter'
s.version = '2.2.3'
s.version = '3.0.0'
s.summary = 'A Flutter package plugin for Picovoice\'s Rhino Speech-to-Intent engine'
s.description = <<-DESC
A Flutter package plugin for Picovoice\'s Rhino Speech-to-Intent engine
Expand All @@ -12,7 +12,7 @@ Pod::Spec.new do |s|
s.source_files = 'Classes/**/*'
s.platform = :ios, '11.0'
s.dependency 'Flutter'
s.dependency 'Rhino-iOS', '~> 2.2.2'
s.dependency 'Rhino-iOS', '~> 3.0.0'

s.swift_version = '5.0'
end
21 changes: 21 additions & 0 deletions binding/flutter/lib/rhino.dart
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ class Rhino {
///
/// returns RhinoInference object.
Future<RhinoInference> process(List<int>? frame) async {
if (_handle == null) {
throw RhinoInvalidStateException(
"Unable to process with Rhino - resources have already been released");
}

try {
Map<String, dynamic> inference = Map<String, dynamic>.from(await _channel
.invokeMethod('process', {'handle': _handle, 'frame': frame}));
Expand All @@ -164,6 +169,22 @@ class Rhino {
}
}

/// Resets the internal state of the engine. It should be called before the
/// engine can be used to infer intent from a new stream of audio.
///
/// Throws a `RhinoException` if reset fails
Future<void> reset() async {
if (_handle == null) {
throw RhinoInvalidStateException(
"Unable to reset Rhino - resources have already been released");
}
try {
await _channel.invokeMethod('reset', {'handle': _handle});
} on PlatformException catch (error) {
throw rhinoStatusToException(error.code, error.message);
}
}

/// Frees memory that was allocated for Rhino
Future<void> delete() async {
if (_handle != null) {
Expand Down
1 change: 1 addition & 0 deletions binding/flutter/lib/rhino_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class RhinoManager {
if (_isListening) {
return;
}

if (_rhino == null || _voiceProcessor == null) {
throw RhinoInvalidStateException(
"Cannot start Rhino - resources have already been released");
Expand Down
2 changes: 1 addition & 1 deletion binding/flutter/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: rhino_flutter
description: A Flutter plugin for Picovoice's Rhino Speech-to-Intent engine
version: 2.2.3
version: 3.0.0
homepage: https://picovoice.ai/
repository: https://github.com/Picovoice/rhino/
documentation: https://picovoice.ai/docs/rhino/
Expand Down
6 changes: 6 additions & 0 deletions demo/flutter/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ buildscript {
repositories {
google()
jcenter()
maven {
url 'https://s01.oss.sonatype.org/content/repositories/aipicovoice-1267/'
}
}

dependencies {
Expand All @@ -13,6 +16,9 @@ allprojects {
repositories {
google()
jcenter()
maven {
url 'https://s01.oss.sonatype.org/content/repositories/aipicovoice-1267/'
}
}
}

Expand Down
41 changes: 41 additions & 0 deletions demo/flutter/integration_test/app_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,47 @@ void main() {
testData = json.decode(testDataJson);
});

testWidgets('Test reset', (tester) async {
String language = testData['tests']['within_context'][0]['language'];
String contextName =
testData['tests']['within_context'][0]['context_name'];

String contextPath =
"assets/test_resources/context_files/${contextName}_$platform.rhn";
String modelPath =
"assets/test_resources/model_files/rhino_params${language != "en" ? "_$language" : ""}.pv";

Rhino rhino;
try {
rhino =
await Rhino.create(accessKey, contextPath, modelPath: modelPath);
} on RhinoException catch (ex) {
expect(ex, equals(null),
reason: "Failed to initialize Rhino for $language: $ex");
return;
}

String audioPath =
"assets/test_resources/audio_samples/test_within_context${language != "en" ? "_$language" : ""}.wav";
List<int> pcm = await loadAudioFile(audioPath);

RhinoInference? inference;
final int frameLength = rhino.frameLength;
for (int i = 0; i < (pcm.length - frameLength); i += frameLength) {
if (i == (pcm.length - frameLength) ~/ 2) {
await rhino.reset();
}
inference = await rhino.process(pcm.sublist(i, i + frameLength));
if (inference.isFinalized) {
break;
}
}

rhino.delete();
expect(inference?.isFinalized, equals(true),
reason: "Rhino should not have finalized after reset");
});

testWidgets('Test within_context all languages', (tester) async {
for (int t = 0; t < testData['tests']['within_context'].length; t++) {
String language = testData['tests']['within_context'][t]['language'];
Expand Down
2 changes: 2 additions & 0 deletions demo/flutter/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelpe
flutter_ios_podfile_setup

target 'Runner' do
pod 'Rhino-iOS', :podspec => 'https://raw.githubusercontent.com/Picovoice/rhino/v3.0/binding/ios/Rhino-iOS.podspec'

use_frameworks!
use_modular_headers!

Expand Down
16 changes: 9 additions & 7 deletions demo/flutter/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ PODS:
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- Rhino-iOS (2.2.2):
- Rhino-iOS (3.0.0):
- ios-voice-processor (~> 1.1.0)
- rhino_flutter (2.2.3):
- rhino_flutter (3.0.0):
- Flutter
- Rhino-iOS (~> 2.2.2)
- Rhino-iOS (~> 3.0.0)

DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_voice_processor (from `.symlinks/plugins/flutter_voice_processor/ios`)
- integration_test (from `.symlinks/plugins/integration_test/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
- Rhino-iOS (from `https://raw.githubusercontent.com/Picovoice/rhino/v3.0/binding/ios/Rhino-iOS.podspec`)
- rhino_flutter (from `.symlinks/plugins/rhino_flutter/ios`)

SPEC REPOS:
trunk:
- ios-voice-processor
- Rhino-iOS

EXTERNAL SOURCES:
Flutter:
Expand All @@ -36,6 +36,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/integration_test/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/ios"
Rhino-iOS:
:podspec: https://raw.githubusercontent.com/Picovoice/rhino/v3.0/binding/ios/Rhino-iOS.podspec
rhino_flutter:
:path: ".symlinks/plugins/rhino_flutter/ios"

Expand All @@ -45,9 +47,9 @@ SPEC CHECKSUMS:
integration_test: a1e7d09bd98eca2fc37aefd79d4f41ad37bdbbe5
ios-voice-processor: 8e32d7f980a06d392d128ef1cd19cf6ddcaca3c1
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
Rhino-iOS: 0fad86b28d35f67ccb6bd0a2efbbcc0d88b05124
rhino_flutter: 06eafa6dfcfae5b21696c7c3dab4007fdd46e5d9
Rhino-iOS: b92978104bfad32da25b9eeaa4f0628b86ffcee9
rhino_flutter: 78d56c9fa0355e4ee94fa59cb3a0d210b5d1e3f9

PODFILE CHECKSUM: 7368163408c647b7eb699d0d788ba6718e18fb8d
PODFILE CHECKSUM: d649e1aef953c2b76883198c9a60c0dfd0334b0a

COCOAPODS: 1.11.3
8 changes: 4 additions & 4 deletions demo/flutter/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,10 @@ packages:
rhino_flutter:
dependency: "direct main"
description:
name: rhino_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.3"
path: "../../binding/flutter"
relative: true
source: path
version: "3.0.0"
sky_engine:
dependency: transitive
description: flutter
Expand Down
3 changes: 2 additions & 1 deletion demo/flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ dependencies:
flutter:
sdk: flutter

rhino_flutter: ^2.2.3
rhino_flutter:
path: ../../binding/flutter

dev_dependencies:
integration_test:
Expand Down

0 comments on commit dd21394

Please sign in to comment.